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