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