2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.h>
22 #include <dali/integration-api/debug.h>
25 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
26 #include <dali-toolkit/internal/controls/scene3d-view/gltf-loader.h>
36 const char* const IMAGE_BRDF_FILE_NAME = "brdfLUT.png";
38 // glTF file extension
39 const char* GLTF_EXT(".gltf");
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}};
49 Scene3dView::Scene3dView()
50 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
54 mDefaultCamera(CameraActor::New()),
56 mLightType(Toolkit::Scene3dView::LightType::NONE),
57 mLightVector(Vector3::ONE),
58 mLightColor(Vector3::ONE),
63 Scene3dView::~Scene3dView()
67 Toolkit::Scene3dView Scene3dView::New(const std::string& filePath)
69 Scene3dView* impl = new Scene3dView();
71 Dali::Toolkit::Scene3dView handle = Dali::Toolkit::Scene3dView(*impl);
73 // Second-phase init of the implementation
74 // This can only be done after the CustomActor connection has been made...
75 impl->mFilePath = filePath;
81 Toolkit::Scene3dView Scene3dView::New(const std::string& filePath, const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor)
83 Scene3dView* impl = new Scene3dView();
85 Dali::Toolkit::Scene3dView handle = Dali::Toolkit::Scene3dView(*impl);
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);
96 bool Scene3dView::CreateScene()
98 if(std::string::npos != mFilePath.rfind(GLTF_EXT))
100 Internal::Gltf::Loader gltfloader;
101 return (gltfloader.LoadScene(mFilePath, *this));
107 uint32_t Scene3dView::GetAnimationCount()
109 return mAnimationArray.size();
112 bool Scene3dView::PlayAnimation(uint32_t index)
114 if(GetAnimationCount() <= index)
119 mAnimationArray[index].Play();
123 bool Scene3dView::PlayAnimations()
125 for(auto&& animation : mAnimationArray)
133 bool Scene3dView::SetLight(Toolkit::Scene3dView::LightType type, Vector3 lightVector, Vector3 lightColor)
136 mLightVector = lightVector;
137 mLightColor = lightColor;
139 for(auto&& shader : mShaderArray)
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);
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)
154 uint32_t byteSize = bytesPerPixel * xFaceSize * yFaceSize;
155 uint8_t* destBuffer = reinterpret_cast<uint8_t*>(malloc(byteSize + 4u));
157 if(DALI_LIKELY(destBuffer))
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)
165 memcpy(destBuffer + destOffset, sourceBuffer + srcOffset, destStride);
166 srcOffset += srcStride;
167 destOffset += destStride;
172 DALI_LOG_ERROR("malloc is failed. request malloc size : %u\n", byteSize + 4u);
178 void Scene3dView::UploadTextureFace(Texture& texture, Devel::PixelBuffer pixelBuffer, uint32_t faceIndex)
180 uint8_t* imageBuffer = pixelBuffer.GetBuffer();
181 uint32_t bytesPerPixel = Pixel::GetBytesPerPixel(pixelBuffer.GetPixelFormat());
182 uint32_t imageWidth = pixelBuffer.GetWidth();
183 uint32_t imageHeight = pixelBuffer.GetHeight();
185 CubeType cubeType = (imageWidth / 4 == imageHeight / 3) ? CROSS_HORIZONTAL : ((imageWidth / 6 == imageHeight) ? ARRAY_HORIZONTAL : NONE);
187 uint32_t faceSize = 0;
188 if(cubeType == CROSS_HORIZONTAL)
190 faceSize = imageWidth / 4;
192 else if(cubeType == ARRAY_HORIZONTAL)
194 faceSize = imageWidth / 6;
201 uint32_t xOffset = CUBEMAP_INDEX_X[cubeType][faceIndex] * faceSize;
202 uint32_t yOffset = CUBEMAP_INDEX_Y[cubeType][faceIndex] * faceSize;
204 uint8_t* tempImageBuffer = GetCroppedBuffer(imageBuffer, bytesPerPixel, imageWidth, imageHeight, xOffset, yOffset, faceSize, faceSize);
205 if(DALI_LIKELY(tempImageBuffer))
207 PixelData pixelData = PixelData::New(tempImageBuffer, faceSize * faceSize * bytesPerPixel, faceSize, faceSize, pixelBuffer.GetPixelFormat(), PixelData::FREE);
208 texture.Upload(pixelData, CubeMapLayer::POSITIVE_X + faceIndex, 0, 0, 0, faceSize, faceSize);
212 void Scene3dView::SetCubeMap(const std::string& diffuseTexturePath, const std::string& specularTexturePath, Vector4 scaleFactor)
215 const std::string imageDirPath = AssetManager::GetDaliImagePath();
216 const std::string imageBrdfUrl = imageDirPath + IMAGE_BRDF_FILE_NAME;
217 mBRDFTexture = LoadTexture(imageBrdfUrl.c_str(), true);
224 Devel::PixelBuffer diffusePixelBuffer = LoadImageFromFile(diffuseTexturePath);
225 uint32_t diffuseFaceSize = diffusePixelBuffer.GetWidth() / 4;
226 mDiffuseTexture = Texture::New(TextureType::TEXTURE_CUBE, diffusePixelBuffer.GetPixelFormat(), diffuseFaceSize, diffuseFaceSize);
227 for(uint32_t i = 0; i < 6; ++i)
229 UploadTextureFace(mDiffuseTexture, diffusePixelBuffer, i);
231 mDiffuseTexture.GenerateMipmaps();
234 Devel::PixelBuffer specularPixelBuffer = LoadImageFromFile(specularTexturePath);
235 uint32_t specularFaceSize = specularPixelBuffer.GetWidth() / 4;
236 mSpecularTexture = Texture::New(TextureType::TEXTURE_CUBE, specularPixelBuffer.GetPixelFormat(), specularFaceSize, specularFaceSize);
237 for(uint32_t i = 0; i < 6; ++i)
239 UploadTextureFace(mSpecularTexture, specularPixelBuffer, i);
241 mSpecularTexture.GenerateMipmaps();
243 mIBLScaleFactor = scaleFactor;
247 bool Scene3dView::SetDefaultCamera(const Dali::Camera::Type type, const float nearPlane, const Vector3 cameraPosition)
249 mDefaultCamera.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
250 mDefaultCamera.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
251 mDefaultCamera.SetType(type);
252 mDefaultCamera.SetNearClippingPlane(nearPlane);
253 mDefaultCamera.SetProperty(Actor::Property::POSITION, cameraPosition);
257 void Scene3dView::AddCamera(CameraActor cameraActor)
259 mCameraActorArray.push_back(cameraActor);
262 void Scene3dView::AddAnimation(Animation animation)
264 mAnimationArray.push_back(animation);
267 void Scene3dView::AddShader(Shader shader)
269 mShaderArray.push_back(shader);
272 Actor Scene3dView::GetRoot()
277 CameraActor Scene3dView::GetDefaultCamera()
279 return mDefaultCamera;
282 uint32_t Scene3dView::GetCameraCount()
284 return mCameraActorArray.size();
287 CameraActor Scene3dView::GetCamera(uint32_t cameraIndex)
289 CameraActor cameraActor;
290 if(cameraIndex >= mCameraActorArray.size())
294 cameraActor = mCameraActorArray[cameraIndex];
298 Toolkit::Scene3dView::LightType Scene3dView::GetLightType()
303 Vector3 Scene3dView::GetLightVector()
308 Vector3 Scene3dView::GetLightColor()
313 Vector4 Scene3dView::GetIBLScaleFactor()
315 return mIBLScaleFactor;
318 Texture Scene3dView::GetBRDFTexture()
323 Texture Scene3dView::GetSpecularTexture()
325 return mSpecularTexture;
328 bool Scene3dView::HasImageBasedLighting()
333 Texture Scene3dView::GetDiffuseTexture()
335 return mDiffuseTexture;
338 Texture Scene3dView::LoadTexture(const char* imageUrl, bool generateMipmaps)
342 Devel::PixelBuffer pixelBuffer = LoadImageFromFile(imageUrl);
345 texture = Texture::New(TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight());
346 PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
347 texture.Upload(pixelData);
351 texture.GenerateMipmaps();
358 void Scene3dView::OnInitialize()
360 mRoot.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
361 mRoot.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
363 Layer layer = Layer::New();
364 layer.SetProperty(Layer::Property::BEHAVIOR, Layer::LAYER_3D);
365 layer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
366 layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
370 // Apply some default resizing rules.
371 self.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
372 self.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
378 } //namespace Internal
380 } //namespace Toolkit