+ Dali::Scene3D::Loader::Skinning::BoneData boneData;
+ boneData.primitive = primitive;
+ boneData.boneIndex = boneIndex;
+ char propertyNameBuffer[32];
+ snprintf(propertyNameBuffer, sizeof(propertyNameBuffer), "%s[%d]", Dali::Scene3D::Loader::Skinning::BONE_UNIFORM_NAME, boneIndex);
+ boneData.propertyName = propertyNameBuffer;
+ boneData.inverseMatrix = inverseMatrix;
+ mBoneDataContainer.push_back(std::move(boneData));
+
+ UpdateBoneMatrix(primitive);
+}
+
+void ModelNode::OnRendererCreated(Renderer renderer)
+{
+ Self().AddRenderer(renderer);
+}
+
+void ModelNode::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive)
+{
+ for(auto&& boneData : mBoneDataContainer)
+ {
+ if(boneData.primitive != primitive)
+ {
+ continue;
+ }
+
+ Dali::Renderer renderer = GetImplementation(primitive).GetRenderer();
+ if(!renderer)
+ {
+ continue;
+ }
+
+ if(boneData.constraint)
+ {
+ boneData.constraint.Remove();
+ boneData.constraint.Reset();
+ }
+
+ auto propBoneXform = renderer.GetPropertyIndex(boneData.propertyName);
+ if(propBoneXform == Property::INVALID_INDEX)
+ {
+ propBoneXform = renderer.RegisterProperty(boneData.propertyName, Matrix{false});
+ }
+
+ Matrix inverseMatrix = boneData.inverseMatrix;
+ // Constrain bone matrix to joint transform.
+ boneData.constraint = Constraint::New<Matrix>(renderer, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs) { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
+
+ Actor joint = Self();
+ boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX});
+ boneData.constraint.ApplyPost();
+ break;
+ }