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