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