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-data-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/model-components/model-primitive-impl.h>
28 #include <dali-scene3d/public-api/model-components/model-node.h>
43 * Creates control through type registry
47 return Scene3D::ModelNode::New();
50 // Setup properties, signals and actions using the type-registry.
51 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelNode, Dali::CustomActor, Create);
52 DALI_TYPE_REGISTRATION_END()
53 } // unnamed namespace
55 ModelNode::Impl::Impl(ModelNode& modelNodeImpl)
56 : mModelNodeImpl(modelNodeImpl)
60 ModelNode::Impl::~Impl()
62 for(auto&& primitive : mModelPrimitiveContainer)
64 GetImplementation(primitive).RemovePrimitiveObserver(this);
66 for(auto&& boneData : mBoneDataContainer)
68 boneData.primitive.Reset();
69 if(boneData.constraint)
71 boneData.constraint.Remove();
72 boneData.constraint.Reset();
77 void ModelNode::Impl::OnSceneConnection(int depth)
81 void ModelNode::Impl::OnSceneDisconnection()
85 void ModelNode::Impl::OnRendererCreated(Renderer renderer)
87 mModelNodeImpl.Self().AddRenderer(renderer);
92 void ModelNode::Impl::AddModelPrimitive(Scene3D::ModelPrimitive modelPrimitive)
94 for(auto&& primitive : mModelPrimitiveContainer)
96 if(primitive == modelPrimitive)
102 mModelPrimitiveContainer.push_back(modelPrimitive);
104 Actor self = mModelNodeImpl.Self();
106 GetImplementation(modelPrimitive).AddPrimitiveObserver(this);
107 if(mDiffuseTexture && mSpecularTexture)
109 GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
112 Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
115 uint32_t rendererCount = self.GetRendererCount();
117 for(uint32_t i = 0; i < rendererCount; ++i)
119 if(renderer == self.GetRendererAt(i))
127 self.AddRenderer(renderer);
132 void ModelNode::Impl::RemoveModelPrimitive(Scene3D::ModelPrimitive modelPrimitive)
134 uint32_t primitiveCount = GetModelPrimitiveCount();
135 for(uint32_t i = 0; i < primitiveCount; ++i)
137 if(mModelPrimitiveContainer[i] != modelPrimitive)
141 RemoveModelPrimitive(i);
146 void ModelNode::Impl::RemoveModelPrimitive(uint32_t index)
148 if(index >= mModelPrimitiveContainer.size())
153 Actor self = mModelNodeImpl.Self();
154 GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
156 Dali::Renderer renderer = GetImplementation(mModelPrimitiveContainer[index]).GetRenderer();
159 self.RemoveRenderer(renderer);
162 mModelPrimitiveContainer.erase(mModelPrimitiveContainer.begin() + index);
165 Scene3D::ModelPrimitive ModelNode::Impl::GetModelPrimitive(uint32_t index) const
167 if(index < mModelPrimitiveContainer.size())
169 return mModelPrimitiveContainer[index];
171 return Scene3D::ModelPrimitive();
174 void ModelNode::Impl::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
176 mDiffuseTexture = diffuseTexture;
177 mSpecularTexture = specularTexture;
178 mIblScaleFactor = iblScaleFactor;
179 mSpecularMipmapLevels = specularMipmapLevels;
180 for(auto&& primitive : mModelPrimitiveContainer)
182 GetImplementation(primitive).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
186 void ModelNode::Impl::SetImageBasedLightScaleFactor(float iblScaleFactor)
188 mIblScaleFactor = iblScaleFactor;
189 for(auto&& primitive : mModelPrimitiveContainer)
191 GetImplementation(primitive).SetImageBasedLightScaleFactor(iblScaleFactor);
195 void ModelNode::Impl::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
197 GetImplementation(primitive).SetBlendShapeData(data);
200 void ModelNode::Impl::SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex)
202 Dali::Scene3D::Loader::Skinning::BoneData boneData;
203 boneData.primitive = primitive;
204 boneData.boneIndex = boneIndex;
205 char propertyNameBuffer[32];
206 snprintf(propertyNameBuffer, sizeof(propertyNameBuffer), "%s[%d]", Dali::Scene3D::Loader::Skinning::BONE_UNIFORM_NAME, boneIndex);
207 boneData.propertyName = propertyNameBuffer;
208 boneData.inverseMatrix = inverseMatrix;
209 mBoneDataContainer.push_back(std::move(boneData));
211 UpdateBoneMatrix(primitive);
214 void ModelNode::Impl::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive)
216 for(auto&& boneData : mBoneDataContainer)
218 if(boneData.primitive != primitive)
223 Dali::Renderer renderer = GetImplementation(primitive).GetRenderer();
229 Dali::Shader shader = renderer.GetShader();
235 if(boneData.constraint)
237 boneData.constraint.Remove();
238 boneData.constraint.Reset();
241 if(shader.GetPropertyIndex(boneData.propertyName) == Property::INVALID_INDEX)
243 auto propBoneXform = shader.RegisterProperty(boneData.propertyName, Matrix{false});
245 Matrix inverseMatrix = boneData.inverseMatrix;
246 // Constrain bone matrix to joint transform.
247 boneData.constraint = Constraint::New<Matrix>(shader, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs)
248 { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
250 Actor joint = mModelNodeImpl.Self();
251 auto propJointMatrix = joint.GetPropertyIndex(Dali::Scene3D::Loader::Skinning::JOINT_MATRIX);
252 boneData.constraint.AddSource(Source{joint, propJointMatrix});
253 boneData.constraint.Apply();
259 } // namespace Internal
261 } // namespace Scene3D