2 * Copyright (c) 2023 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-scene3d/internal/model-components/model-node-impl.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/object/type-registry-helper.h>
24 #include <dali/public-api/object/type-registry.h>
27 #include <dali-scene3d/internal/light/light-impl.h>
28 #include <dali-scene3d/internal/model-components/model-primitive-impl.h>
39 * Creates control through type registry
43 return Scene3D::ModelNode::New();
46 // Setup properties, signals and actions using the type-registry.
47 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelNode, Dali::CustomActor, Create);
48 DALI_TYPE_REGISTRATION_END()
49 } // unnamed namespace
51 Dali::Scene3D::ModelNode ModelNode::New()
53 // Create the implementation, temporarily owned on stack
54 IntrusivePtr<ModelNode> nodeImpl = new ModelNode();
56 // Pass ownership to handle
57 Scene3D::ModelNode handle(*nodeImpl);
59 // Second-phase init of the implementation
60 // This can only be done after the CustomActor connection has been made...
61 nodeImpl->Initialize();
66 ModelNode::ModelNode()
67 : CustomActorImpl(ActorFlags::DISABLE_SIZE_NEGOTIATION)
71 ModelNode::~ModelNode()
75 void ModelNode::Initialize()
78 mLights.resize(Scene3D::Internal::Light::GetMaximumEnabledLightCount());
81 void ModelNode::OnInitialize()
85 void ModelNode::OnSceneConnection(int depth)
89 void ModelNode::OnSceneDisconnection()
93 void ModelNode::OnChildAdd(Actor& child)
97 void ModelNode::OnChildRemove(Actor& child)
101 void ModelNode::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
105 void ModelNode::OnSizeSet(const Vector3& targetSize)
109 void ModelNode::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
111 // @todo size negotiate background to new size, animate as well?
114 void ModelNode::OnRelayout(const Vector2& size, RelayoutContainer& container)
118 void ModelNode::OnSetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
122 Vector3 ModelNode::GetNaturalSize()
124 return Vector3::ZERO;
127 float ModelNode::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
132 float ModelNode::GetHeightForWidth(float width)
137 float ModelNode::GetWidthForHeight(float height)
142 bool ModelNode::RelayoutDependentOnChildren(Dimension::Type dimension)
147 void ModelNode::OnCalculateRelayoutSize(Dimension::Type dimension)
151 void ModelNode::OnLayoutNegotiated(float size, Dimension::Type dimension)
155 ModelNode& GetImplementation(Dali::Scene3D::ModelNode& handle)
157 CustomActorImpl& customInterface = handle.GetImplementation();
158 ModelNode& impl = dynamic_cast<Internal::ModelNode&>(customInterface);
162 const ModelNode& GetImplementation(const Dali::Scene3D::ModelNode& handle)
164 const CustomActorImpl& customInterface = handle.GetImplementation();
165 // downcast to control
166 const ModelNode& impl = dynamic_cast<const Internal::ModelNode&>(customInterface);
172 uint32_t ModelNode::GetModelPrimitiveCount() const
174 return static_cast<uint32_t>(mModelPrimitiveContainer.size());
177 void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
179 for(auto&& primitive : mModelPrimitiveContainer)
181 if(primitive == modelPrimitive)
187 mModelPrimitiveContainer.push_back(modelPrimitive);
190 GetImplementation(modelPrimitive).AddPrimitiveObserver(this);
191 if(mDiffuseTexture && mSpecularTexture)
193 GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
196 uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
197 for(uint32_t i = 0; i < maxLightCount; ++i)
201 GetImplementation(modelPrimitive).AddLight(mLights[i], i);
205 GetImplementation(modelPrimitive).UpdateShader(mShaderManager);
207 Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
210 uint32_t rendererCount = self.GetRendererCount();
212 for(uint32_t i = 0; i < rendererCount; ++i)
214 if(renderer == self.GetRendererAt(i))
222 self.AddRenderer(renderer);
227 void ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
229 uint32_t primitiveCount = GetModelPrimitiveCount();
230 for(uint32_t i = 0; i < primitiveCount; ++i)
232 if(mModelPrimitiveContainer[i] != modelPrimitive)
237 RemoveModelPrimitive(i);
242 void ModelNode::RemoveModelPrimitive(uint32_t index)
244 if(index >= mModelPrimitiveContainer.size())
249 GetImplementation(mModelPrimitiveContainer[index]).UpdateShader(nullptr);
251 uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
252 for(uint32_t i = 0; i < maxLightCount; ++i)
256 GetImplementation(mModelPrimitiveContainer[index]).RemoveLight(i);
261 GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
263 Dali::Renderer renderer = GetImplementation(mModelPrimitiveContainer[index]).GetRenderer();
266 self.RemoveRenderer(renderer);
269 mModelPrimitiveContainer.erase(mModelPrimitiveContainer.begin() + index);
272 Dali::Scene3D::ModelPrimitive ModelNode::GetModelPrimitive(uint32_t index) const
274 if(index < mModelPrimitiveContainer.size())
276 return mModelPrimitiveContainer[index];
278 return Scene3D::ModelPrimitive();
281 Scene3D::ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName)
283 Actor childActor = Self().FindChildByName(nodeName);
284 return Scene3D::ModelNode::DownCast(childActor);
287 void ModelNode::RetrieveBlendShapeNames(std::vector<std::string>& blendShapeNames) const
289 blendShapeNames.reserve(blendShapeNames.size() + mBlendShapeIndexMap.size());
290 for(const auto& iter : mBlendShapeIndexMap)
292 blendShapeNames.push_back(iter.first);
296 Loader::BlendShapes::Index ModelNode::GetBlendShapeIndexByName(std::string_view blendShapeName) const
298 auto iter = mBlendShapeIndexMap.find(std::string(blendShapeName));
299 if(iter != mBlendShapeIndexMap.end())
303 return Loader::BlendShapes::INVALID_INDEX;
306 void ModelNode::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
308 mDiffuseTexture = diffuseTexture;
309 mSpecularTexture = specularTexture;
310 mIblScaleFactor = iblScaleFactor;
311 mSpecularMipmapLevels = specularMipmapLevels;
312 for(auto&& primitive : mModelPrimitiveContainer)
314 GetImplementation(primitive).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
318 void ModelNode::SetImageBasedLightScaleFactor(float iblScaleFactor)
320 mIblScaleFactor = iblScaleFactor;
321 for(auto&& primitive : mModelPrimitiveContainer)
323 GetImplementation(primitive).SetImageBasedLightScaleFactor(iblScaleFactor);
327 void ModelNode::AddLight(Scene3D::Light light, uint32_t lightIndex)
329 mLights[lightIndex] = light;
330 for(auto&& primitive : mModelPrimitiveContainer)
332 GetImplementation(primitive).AddLight(light, lightIndex);
336 void ModelNode::RemoveLight(uint32_t lightIndex)
338 for(auto&& primitive : mModelPrimitiveContainer)
340 GetImplementation(primitive).RemoveLight(lightIndex);
342 mLights[lightIndex].Reset();
345 void ModelNode::UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager)
347 if(mShaderManager != shaderManager)
349 mShaderManager = shaderManager;
350 for(auto&& primitive : mModelPrimitiveContainer)
352 GetImplementation(primitive).UpdateShader(mShaderManager);
357 void ModelNode::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
359 // Update mBlendShapeIndexMap
360 mBlendShapeIndexMap.clear();
361 const auto blendShapeCount = data.names.size();
362 for(Loader::BlendShapes::Index index = 0u; index < blendShapeCount; ++index)
364 auto& name = data.names[index];
367 mBlendShapeIndexMap[name] = index;
371 GetImplementation(primitive).SetBlendShapeData(data);
374 void ModelNode::SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex)
376 Dali::Scene3D::Loader::Skinning::BoneData boneData;
377 boneData.primitive = primitive;
378 boneData.boneIndex = boneIndex;
379 char propertyNameBuffer[32];
380 snprintf(propertyNameBuffer, sizeof(propertyNameBuffer), "%s[%d]", Dali::Scene3D::Loader::Skinning::BONE_UNIFORM_NAME, boneIndex);
381 boneData.propertyName = propertyNameBuffer;
382 boneData.inverseMatrix = inverseMatrix;
383 mBoneDataContainer.push_back(std::move(boneData));
385 UpdateBoneMatrix(primitive);
388 void ModelNode::OnRendererCreated(Renderer renderer)
390 Self().AddRenderer(renderer);
393 void ModelNode::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive)
395 for(auto&& boneData : mBoneDataContainer)
397 if(boneData.primitive != primitive)
402 Dali::Renderer renderer = GetImplementation(primitive).GetRenderer();
408 if(boneData.constraint)
410 boneData.constraint.Remove();
411 boneData.constraint.Reset();
414 auto propBoneXform = renderer.GetPropertyIndex(boneData.propertyName);
415 if(propBoneXform == Property::INVALID_INDEX)
417 propBoneXform = renderer.RegisterProperty(boneData.propertyName, Matrix{false});
420 Matrix inverseMatrix = boneData.inverseMatrix;
421 // Constrain bone matrix to joint transform.
422 boneData.constraint = Constraint::New<Matrix>(renderer, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs) { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
424 Actor joint = Self();
425 boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX});
426 boneData.constraint.ApplyPost();
431 } // namespace Internal
433 } // namespace Scene3D