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