Scene and glTF Loader
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scene3d-view / scene3d-view-impl.cpp
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 namespace Dali
25 {
26
27 namespace Toolkit
28 {
29
30 namespace Internal
31 {
32
33 namespace
34 {
35
36 // glTF file extension
37 const std::string GLTF_EXT( ".gltf" );
38
39 /**
40  * cube map face index
41  */
42 const uint32_t CUBEMAP_INDEX_X[2][6] = { { 2, 0, 1, 1, 1, 3 }, { 0, 1, 2, 3, 4, 5 } };
43 const uint32_t CUBEMAP_INDEX_Y[2][6] = { { 1, 1, 0, 2, 1, 1 }, { 0, 0, 0, 0, 0, 0 } };
44
45 }//namespace
46
47 Scene3dView::Scene3dView()
48   : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
49   mRoot( Actor::New() ),
50   mShaderArray(),
51   mCameraActorArray(),
52   mDefaultCamera( CameraActor::New() ),
53   mAnimationArray(),
54   mLightType( Toolkit::Scene3dView::LightType::NONE ),
55   mLightVector( Vector3::ONE ),
56   mLightColor( Vector3::ONE )
57 {
58 }
59
60 Scene3dView::~Scene3dView()
61 {
62 }
63
64 Toolkit::Scene3dView Scene3dView::New( const std::string& filePath )
65 {
66   Scene3dView* impl = new Scene3dView();
67
68   Dali::Toolkit::Scene3dView handle = Dali::Toolkit::Scene3dView( *impl );
69
70   // Second-phase init of the implementation
71   // This can only be done after the CustomActor connection has been made...
72   impl->mFilePath = filePath;
73   impl->Initialize();
74
75   return handle;
76 }
77
78 Toolkit::Scene3dView Scene3dView::New( const std::string& filePath, const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor )
79 {
80   Scene3dView* impl = new Scene3dView();
81
82   Dali::Toolkit::Scene3dView handle = Dali::Toolkit::Scene3dView( *impl );
83
84   // Second-phase init of the implementation
85   // This can only be done after the CustomActor connection has been made...
86   impl->mFilePath = filePath;
87   impl->SetCubeMap( diffuseTexturePath, specularTexturePath, scaleFactor );
88   impl->Initialize();
89
90   return handle;
91 }
92
93 bool Scene3dView::CreateScene()
94 {
95   if( std::string::npos != mFilePath.rfind( GLTF_EXT ) )
96   {
97     Internal::Gltf::Loader gltfloader;
98     return( gltfloader.LoadScene( mFilePath, *this ) );
99   }
100
101   return false;
102 }
103
104 uint32_t Scene3dView::GetAnimationCount()
105 {
106   return mAnimationArray.size();
107 }
108
109 bool Scene3dView::PlayAnimation( uint32_t index )
110 {
111   if( GetAnimationCount() <= index )
112   {
113     return false;
114   }
115
116   mAnimationArray[index].Play();
117   return true;
118 }
119
120 bool Scene3dView::PlayAnimations()
121 {
122   for( auto&& animation : mAnimationArray )
123   {
124     animation.Play();
125   }
126
127   return true;
128 }
129
130 bool Scene3dView::SetLight( Toolkit::Scene3dView::LightType type, Vector3 lightVector, Vector3 lightColor )
131 {
132   if( type > Toolkit::Scene3dView::LightType::DIRECTIONAL_LIGHT )
133   {
134     return false;
135   }
136
137   mLightType = static_cast<Toolkit::Scene3dView::LightType>(
138                ( mLightType >= Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT ) ?
139                Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT + type :
140                type );
141
142   mLightVector = lightVector;
143   mLightColor = lightColor;
144
145   for( auto&& shader : mShaderArray )
146   {
147     shader.RegisterProperty( "uLightType", ( GetLightType() & ~Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT ) );
148     shader.RegisterProperty( "uLightVector", lightVector );
149     shader.RegisterProperty( "uLightColor", lightColor );
150   }
151
152   return true;
153 }
154
155 uint8_t* Scene3dView::GetCroppedBuffer( uint8_t* sourceBuffer, uint32_t bytesPerPixel, uint32_t width, uint32_t height, uint32_t xOffset, uint32_t yOffset, uint32_t xFaceSize, uint32_t yFaceSize )
156 {
157   uint32_t byteSize = bytesPerPixel * xFaceSize * yFaceSize;
158   uint8_t* destBuffer = reinterpret_cast<uint8_t*>( malloc( byteSize + 4u ) );
159
160   int32_t srcStride = width * bytesPerPixel;
161   int32_t destStride = xFaceSize * bytesPerPixel;
162   int32_t srcOffset = xOffset * bytesPerPixel + yOffset * srcStride;
163   int32_t destOffset = 0;
164   for( uint16_t row = yOffset; row < yOffset + yFaceSize; ++row )
165   {
166     memcpy( destBuffer + destOffset, sourceBuffer + srcOffset, destStride );
167     srcOffset += srcStride;
168     destOffset += destStride;
169   }
170
171   return destBuffer;
172 }
173
174 void Scene3dView::UploadTextureFace( Texture& texture, Devel::PixelBuffer pixelBuffer, uint32_t faceIndex )
175 {
176   uint8_t* imageBuffer = pixelBuffer.GetBuffer();
177   uint32_t bytesPerPixel = Pixel::GetBytesPerPixel( pixelBuffer.GetPixelFormat() );
178   uint32_t imageWidth = pixelBuffer.GetWidth();
179   uint32_t imageHeight = pixelBuffer.GetHeight();
180
181   CubeType cubeType = ( imageWidth / 4 == imageHeight / 3 ) ? CROSS_HORIZONTAL :
182     ( ( imageWidth / 6 == imageHeight ) ? ARRAY_HORIZONTAL : NONE );
183
184   uint32_t faceSize = 0;
185   if( cubeType == CROSS_HORIZONTAL )
186   {
187     faceSize = imageWidth / 4;
188   }
189   else if( cubeType == ARRAY_HORIZONTAL )
190   {
191     faceSize = imageWidth / 6;
192   }
193   else
194   {
195     return;
196   }
197
198   uint32_t xOffset = CUBEMAP_INDEX_X[cubeType][faceIndex] * faceSize;
199   uint32_t yOffset = CUBEMAP_INDEX_Y[cubeType][faceIndex] * faceSize;
200
201   uint8_t* tempImageBuffer = GetCroppedBuffer( imageBuffer, bytesPerPixel, imageWidth, imageHeight, xOffset, yOffset, faceSize, faceSize );
202   PixelData pixelData = PixelData::New( tempImageBuffer, faceSize * faceSize * bytesPerPixel, faceSize, faceSize, pixelBuffer.GetPixelFormat(), PixelData::FREE );
203   texture.Upload( pixelData, CubeMapLayer::POSITIVE_X + faceIndex, 0, 0, 0, faceSize, faceSize );
204 }
205
206 void Scene3dView::SetCubeMap( const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor )
207 {
208   mLightType = Toolkit::Scene3dView::LightType::IMAGE_BASED_LIGHT;
209
210   // BRDF texture
211   std::string imageBrdfUrl = DALI_IMAGE_DIR "brdfLUT.png";
212   mBRDFTexture = LoadTexture( imageBrdfUrl.c_str(), true );
213   if( !mBRDFTexture )
214   {
215     return;
216   }
217
218   // Diffuse Cube Map
219   Devel::PixelBuffer diffusePixelBuffer = LoadImageFromFile( diffuseTexturePath );
220   uint32_t diffuseFaceSize = diffusePixelBuffer.GetWidth() / 4;
221   mDiffuseTexture = Texture::New( TextureType::TEXTURE_CUBE, diffusePixelBuffer.GetPixelFormat(), diffuseFaceSize, diffuseFaceSize );
222   for( uint32_t i = 0; i < 6; ++i )
223   {
224     UploadTextureFace( mDiffuseTexture, diffusePixelBuffer, i );
225   }
226   mDiffuseTexture.GenerateMipmaps();
227
228   // Specular Cube Map
229   Devel::PixelBuffer specularPixelBuffer = LoadImageFromFile( specularTexturePath );
230   uint32_t specularFaceSize = specularPixelBuffer.GetWidth() / 4;
231   mSpecularTexture = Texture::New( TextureType::TEXTURE_CUBE, specularPixelBuffer.GetPixelFormat(), specularFaceSize, specularFaceSize );
232   for( uint32_t i = 0; i < 6; ++i )
233   {
234     UploadTextureFace( mSpecularTexture, specularPixelBuffer, i );
235   }
236   mSpecularTexture.GenerateMipmaps();
237
238   mIBLScaleFactor = scaleFactor;
239 }
240
241 bool Scene3dView::SetDefaultCamera( const Dali::Camera::Type type, const float nearPlane, const Vector3 cameraPosition )
242 {
243   mDefaultCamera.SetParentOrigin( ParentOrigin::CENTER );
244   mDefaultCamera.SetAnchorPoint( AnchorPoint::CENTER );
245   mDefaultCamera.SetType( type );
246   mDefaultCamera.SetNearClippingPlane( nearPlane );
247   mDefaultCamera.SetPosition( cameraPosition );
248   return true;
249 }
250
251 void Scene3dView::AddCamera( CameraActor cameraActor )
252 {
253   mCameraActorArray.push_back( cameraActor );
254 }
255
256 void Scene3dView::AddAnimation( Animation animation )
257 {
258   mAnimationArray.push_back( animation );
259 }
260
261 void Scene3dView::AddShader( Shader shader )
262 {
263   mShaderArray.push_back( shader );
264 }
265
266 Actor Scene3dView::GetRoot()
267 {
268   return mRoot;
269 }
270
271 CameraActor Scene3dView::GetDefaultCamera()
272 {
273   return mDefaultCamera;
274 }
275
276 uint32_t Scene3dView::GetCameraCount()
277 {
278   return mCameraActorArray.size();
279 }
280
281 CameraActor Scene3dView::GetCamera( uint32_t cameraIndex )
282 {
283   CameraActor cameraActor;
284   if( cameraIndex < 0 || cameraIndex >= mCameraActorArray.size() )
285   {
286     return cameraActor;
287   }
288   cameraActor = mCameraActorArray[cameraIndex];
289   return cameraActor;
290 }
291
292 Toolkit::Scene3dView::LightType Scene3dView::GetLightType()
293 {
294   return mLightType;
295 }
296
297 Vector3 Scene3dView::GetLightVector()
298 {
299   return mLightVector;
300 }
301
302 Vector3 Scene3dView::GetLightColor()
303 {
304   return mLightColor;
305 }
306
307 Vector4 Scene3dView::GetIBLScaleFactor()
308 {
309   return mIBLScaleFactor;
310 }
311
312 Texture Scene3dView::GetBRDFTexture()
313 {
314   return mBRDFTexture;
315 }
316
317 Texture Scene3dView::GetSpecularTexture()
318 {
319   return mSpecularTexture;
320 }
321
322 Texture Scene3dView::GetDiffuseTexture()
323 {
324   return mDiffuseTexture;
325 }
326
327 Texture Scene3dView::LoadTexture( const char *imageUrl, bool generateMipmaps )
328 {
329   Texture texture;
330
331   Devel::PixelBuffer pixelBuffer = LoadImageFromFile( imageUrl );
332   if( pixelBuffer )
333   {
334     texture = Texture::New( TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
335     PixelData pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
336     texture.Upload( pixelData );
337
338     if( generateMipmaps )
339     {
340       texture.GenerateMipmaps();
341     }
342   }
343
344   return texture;
345 }
346
347 void Scene3dView::OnInitialize()
348 {
349   mRoot.SetParentOrigin( ParentOrigin::CENTER );
350   mRoot.SetAnchorPoint( AnchorPoint::CENTER );
351
352   Layer layer = Layer::New();
353   layer.SetBehavior( Layer::LAYER_3D );
354   layer.SetParentOrigin( ParentOrigin::CENTER );
355   layer.SetAnchorPoint( AnchorPoint::CENTER );
356   layer.Add( mRoot );
357
358   Actor self = Self();
359   // Apply some default resizing rules.
360   self.SetParentOrigin( ParentOrigin::CENTER );
361   self.SetAnchorPoint( AnchorPoint::CENTER );
362   self.Add( layer );
363
364   CreateScene();
365 }
366
367 }//namespace Internal
368
369 }//namespace Toolkit
370
371 }//namespace Dali
372