Fix the normalization factor calculation for blendshapes
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / model-components / model-node-impl.cpp
1 /*
2  * Copyright (c) 2023 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-scene3d/internal/model-components/model-node-impl.h>
20
21 // EXTERNAL INCLUDES
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>
25
26 // INTERNAL INCLUDES
27 #include <dali-scene3d/internal/model-components/model-primitive-impl.h>
28
29 namespace Dali
30 {
31 namespace Scene3D
32 {
33 namespace Internal
34 {
35 namespace
36 {
37 /**
38  * Creates control through type registry
39  */
40 BaseHandle Create()
41 {
42   return Scene3D::ModelNode::New();
43 }
44
45 // Setup properties, signals and actions using the type-registry.
46 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelNode, Dali::CustomActor, Create);
47 DALI_TYPE_REGISTRATION_END()
48 } // unnamed namespace
49
50 Dali::Scene3D::ModelNode ModelNode::New()
51 {
52   // Create the implementation, temporarily owned on stack
53   IntrusivePtr<ModelNode> nodeImpl = new ModelNode();
54
55   // Pass ownership to handle
56   Scene3D::ModelNode handle(*nodeImpl);
57
58   // Second-phase init of the implementation
59   // This can only be done after the CustomActor connection has been made...
60   nodeImpl->Initialize();
61
62   return handle;
63 }
64
65 ModelNode::ModelNode()
66 : CustomActorImpl(ActorFlags::DISABLE_SIZE_NEGOTIATION)
67 {
68 }
69
70 ModelNode::~ModelNode()
71 {
72 }
73
74 void ModelNode::Initialize()
75 {
76   OnInitialize();
77 }
78
79 void ModelNode::OnInitialize()
80 {
81 }
82
83 void ModelNode::OnSceneConnection(int depth)
84 {
85 }
86
87 void ModelNode::OnSceneDisconnection()
88 {
89 }
90
91 void ModelNode::OnChildAdd(Actor& child)
92 {
93 }
94
95 void ModelNode::OnChildRemove(Actor& child)
96 {
97 }
98
99 void ModelNode::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
100 {
101 }
102
103 void ModelNode::OnSizeSet(const Vector3& targetSize)
104 {
105 }
106
107 void ModelNode::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
108 {
109   // @todo size negotiate background to new size, animate as well?
110 }
111
112 void ModelNode::OnRelayout(const Vector2& size, RelayoutContainer& container)
113 {
114 }
115
116 void ModelNode::OnSetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
117 {
118 }
119
120 Vector3 ModelNode::GetNaturalSize()
121 {
122   return Vector3::ZERO;
123 }
124
125 float ModelNode::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
126 {
127   return 0.0f;
128 }
129
130 float ModelNode::GetHeightForWidth(float width)
131 {
132   return 0.0f;
133 }
134
135 float ModelNode::GetWidthForHeight(float height)
136 {
137   return 0.0f;
138 }
139
140 bool ModelNode::RelayoutDependentOnChildren(Dimension::Type dimension)
141 {
142   return false;
143 }
144
145 void ModelNode::OnCalculateRelayoutSize(Dimension::Type dimension)
146 {
147 }
148
149 void ModelNode::OnLayoutNegotiated(float size, Dimension::Type dimension)
150 {
151 }
152
153 ModelNode& GetImplementation(Dali::Scene3D::ModelNode& handle)
154 {
155   CustomActorImpl& customInterface = handle.GetImplementation();
156   ModelNode&       impl            = dynamic_cast<Internal::ModelNode&>(customInterface);
157   return impl;
158 }
159
160 const ModelNode& GetImplementation(const Dali::Scene3D::ModelNode& handle)
161 {
162   const CustomActorImpl& customInterface = handle.GetImplementation();
163   // downcast to control
164   const ModelNode& impl = dynamic_cast<const Internal::ModelNode&>(customInterface);
165   return impl;
166 }
167
168 // Public Method
169
170 uint32_t ModelNode::GetModelPrimitiveCount() const
171 {
172   return static_cast<uint32_t>(mModelPrimitiveContainer.size());
173 }
174
175 void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
176 {
177   for(auto&& primitive : mModelPrimitiveContainer)
178   {
179     if(primitive == modelPrimitive)
180     {
181       return;
182     }
183   }
184
185   mModelPrimitiveContainer.push_back(modelPrimitive);
186
187   Actor self = Self();
188   GetImplementation(modelPrimitive).AddPrimitiveObserver(this);
189   if(mDiffuseTexture && mSpecularTexture)
190   {
191     GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
192   }
193
194   Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
195   if(renderer)
196   {
197     uint32_t rendererCount = self.GetRendererCount();
198     bool     exist         = false;
199     for(uint32_t i = 0; i < rendererCount; ++i)
200     {
201       if(renderer == self.GetRendererAt(i))
202       {
203         exist = true;
204         break;
205       }
206     }
207     if(!exist)
208     {
209       self.AddRenderer(renderer);
210     }
211   }
212 }
213
214 void ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
215 {
216   uint32_t primitiveCount = GetModelPrimitiveCount();
217   for(uint32_t i = 0; i < primitiveCount; ++i)
218   {
219     if(mModelPrimitiveContainer[i] != modelPrimitive)
220     {
221       continue;
222     }
223     RemoveModelPrimitive(i);
224     break;
225   }
226 }
227
228 void ModelNode::RemoveModelPrimitive(uint32_t index)
229 {
230   if(index >= mModelPrimitiveContainer.size())
231   {
232     return;
233   }
234
235   Actor self = Self();
236   GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
237
238   Dali::Renderer renderer = GetImplementation(mModelPrimitiveContainer[index]).GetRenderer();
239   if(renderer)
240   {
241     self.RemoveRenderer(renderer);
242   }
243
244   mModelPrimitiveContainer.erase(mModelPrimitiveContainer.begin() + index);
245 }
246
247 Dali::Scene3D::ModelPrimitive ModelNode::GetModelPrimitive(uint32_t index) const
248 {
249   if(index < mModelPrimitiveContainer.size())
250   {
251     return mModelPrimitiveContainer[index];
252   }
253   return Scene3D::ModelPrimitive();
254 }
255
256 Scene3D::ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName)
257 {
258   Actor childActor = Self().FindChildByName(nodeName);
259   return Scene3D::ModelNode::DownCast(childActor);
260 }
261
262 void ModelNode::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
263 {
264   mDiffuseTexture       = diffuseTexture;
265   mSpecularTexture      = specularTexture;
266   mIblScaleFactor       = iblScaleFactor;
267   mSpecularMipmapLevels = specularMipmapLevels;
268   for(auto&& primitive : mModelPrimitiveContainer)
269   {
270     GetImplementation(primitive).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
271   }
272 }
273
274 void ModelNode::SetImageBasedLightScaleFactor(float iblScaleFactor)
275 {
276   mIblScaleFactor = iblScaleFactor;
277   for(auto&& primitive : mModelPrimitiveContainer)
278   {
279     GetImplementation(primitive).SetImageBasedLightScaleFactor(iblScaleFactor);
280   }
281 }
282
283 void ModelNode::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
284 {
285   GetImplementation(primitive).SetBlendShapeData(data);
286 }
287
288 void ModelNode::SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex)
289 {
290   Dali::Scene3D::Loader::Skinning::BoneData boneData;
291   boneData.primitive = primitive;
292   boneData.boneIndex = boneIndex;
293   char propertyNameBuffer[32];
294   snprintf(propertyNameBuffer, sizeof(propertyNameBuffer), "%s[%d]", Dali::Scene3D::Loader::Skinning::BONE_UNIFORM_NAME, boneIndex);
295   boneData.propertyName  = propertyNameBuffer;
296   boneData.inverseMatrix = inverseMatrix;
297   mBoneDataContainer.push_back(std::move(boneData));
298
299   UpdateBoneMatrix(primitive);
300 }
301
302 void ModelNode::OnRendererCreated(Renderer renderer)
303 {
304   Self().AddRenderer(renderer);
305 }
306
307 void ModelNode::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive)
308 {
309   for(auto&& boneData : mBoneDataContainer)
310   {
311     if(boneData.primitive != primitive)
312     {
313       continue;
314     }
315
316     Dali::Renderer renderer = GetImplementation(primitive).GetRenderer();
317     if(!renderer)
318     {
319       continue;
320     }
321
322     Dali::Shader shader = renderer.GetShader();
323     if(!shader)
324     {
325       continue;
326     }
327
328     if(boneData.constraint)
329     {
330       boneData.constraint.Remove();
331       boneData.constraint.Reset();
332     }
333
334     if(shader.GetPropertyIndex(boneData.propertyName) == Property::INVALID_INDEX)
335     {
336       auto propBoneXform = shader.RegisterProperty(boneData.propertyName, Matrix{false});
337
338       Matrix inverseMatrix = boneData.inverseMatrix;
339       // Constrain bone matrix to joint transform.
340       boneData.constraint = Constraint::New<Matrix>(shader, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs)
341                                                     { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
342
343       Actor joint = Self();
344       boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX});
345       boneData.constraint.ApplyPost();
346     }
347     break;
348   }
349 }
350
351 } // namespace Internal
352
353 } // namespace Scene3D
354
355 } // namespace Dali