Merge "Fix more compile error/warnings for gcc-13" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / node-definition.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/public-api/loader/node-definition.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-scene3d/internal/light/light-impl.h>
26 #include <dali-scene3d/internal/model-components/material-impl.h>
27 #include <dali-scene3d/internal/model-components/model-node-impl.h>
28 #include <dali-scene3d/internal/model-components/model-primitive-impl.h>
29 #include <dali-scene3d/public-api/loader/renderer-state.h>
30 #include <dali-scene3d/public-api/loader/utils.h>
31
32 namespace Dali
33 {
34 namespace
35 {
36 static constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
37 static constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
38 static constexpr std::string_view IBL_MAXLOD("uMaxLOD");
39
40 static constexpr uint32_t MAX_NUMBER_OF_MATERIAL_TEXTURE = 7;
41 static constexpr uint32_t SEMANTICS[MAX_NUMBER_OF_MATERIAL_TEXTURE] =
42   {
43     Scene3D::Loader::MaterialDefinition::ALBEDO,
44     Scene3D::Loader::MaterialDefinition::METALLIC | Scene3D::Loader::MaterialDefinition::ROUGHNESS,
45     Scene3D::Loader::MaterialDefinition::NORMAL,
46     Scene3D::Loader::MaterialDefinition::OCCLUSION,
47     Scene3D::Loader::MaterialDefinition::EMISSIVE,
48     Scene3D::Loader::MaterialDefinition::SPECULAR,
49     Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR,
50 };
51
52 static constexpr Scene3D::Material::TextureType TEXTURE_TYPES[MAX_NUMBER_OF_MATERIAL_TEXTURE] =
53   {
54     Scene3D::Material::TextureType::BASE_COLOR,
55     Scene3D::Material::TextureType::METALLIC_ROUGHNESS,
56     Scene3D::Material::TextureType::NORMAL,
57     Scene3D::Material::TextureType::OCCLUSION,
58     Scene3D::Material::TextureType::EMISSIVE,
59     Scene3D::Material::TextureType::SPECULAR,
60     Scene3D::Material::TextureType::SPECULAR_COLOR,
61 };
62
63 Vector4 GetTextureFactor(Scene3D::Loader::MaterialDefinition& materialDefinition, uint32_t semantic)
64 {
65   Vector4 factor = Vector4::ONE;
66   switch(semantic)
67   {
68     case Scene3D::Loader::MaterialDefinition::ALBEDO:
69       factor = materialDefinition.mBaseColorFactor;
70       break;
71     case Scene3D::Loader::MaterialDefinition::METALLIC | Scene3D::Loader::MaterialDefinition::ROUGHNESS:
72       factor = Vector4(materialDefinition.mMetallic, materialDefinition.mRoughness, 0.0f, 0.0f);
73       break;
74     case Scene3D::Loader::MaterialDefinition::NORMAL:
75       factor.x = materialDefinition.mNormalScale;
76       break;
77     case Scene3D::Loader::MaterialDefinition::OCCLUSION:
78       factor.x = materialDefinition.mOcclusionStrength;
79       break;
80     case Scene3D::Loader::MaterialDefinition::EMISSIVE:
81       factor = materialDefinition.mEmissiveFactor;
82       break;
83     case Scene3D::Loader::MaterialDefinition::SPECULAR:
84       factor.x = materialDefinition.mSpecularFactor;
85       break;
86     case Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR:
87       factor = materialDefinition.mSpecularColorFactor;
88       break;
89     default:
90       break;
91   }
92   return factor;
93 }
94
95 } // namespace
96
97 namespace Scene3D
98 {
99 namespace Loader
100 {
101 bool NodeDefinition::Renderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
102 {
103   return false;
104 }
105
106 void NodeDefinition::Renderable::RegisterResources(IResourceReceiver& receiver) const
107 {
108   receiver.Register(ResourceType::Shader, mShaderIdx);
109 }
110
111 void NodeDefinition::Renderable::ReflectResources(IResourceReflector& reflector)
112 {
113   reflector.Reflect(ResourceType::Shader, mShaderIdx);
114 }
115
116 void NodeDefinition::Renderable::OnCreate(const NodeDefinition& nodeDefinition, CreateParams& params, ModelNode& node) const
117 {
118   DALI_ASSERT_DEBUG(mShaderIdx != INVALID_INDEX);
119   auto&  resources = params.mResources;
120   Shader shader    = resources.mShaders[mShaderIdx].second;
121
122   static Geometry defaultGeometry = Geometry::New();
123   Renderer        renderer        = Renderer::New(defaultGeometry, shader);
124
125   RendererState::Apply(resources.mShaders[mShaderIdx].first.mRendererState, renderer);
126
127   node.AddRenderer(renderer);
128 }
129
130 const char* NodeDefinition::ORIGINAL_MATRIX_PROPERTY_NAME = "originalMatrix";
131
132 ModelNode NodeDefinition::CreateModelNode(CreateParams& params)
133 {
134   ModelNode node = ModelNode::New();
135   mNodeId        = node.GetProperty<int32_t>(Dali::Actor::Property::ID);
136
137   SetActorCentered(node);
138
139   node.SetProperty(Actor::Property::NAME, mName);
140   node.SetProperty(Actor::Property::POSITION, mPosition);
141   node.SetProperty(Actor::Property::ORIENTATION, mOrientation);
142   node.SetProperty(Actor::Property::SCALE, mScale);
143   node.SetProperty(Actor::Property::SIZE, mSize);
144   node.SetProperty(Actor::Property::VISIBLE, mIsVisible);
145
146   node.RegisterProperty(ORIGINAL_MATRIX_PROPERTY_NAME, GetLocalSpace(), Property::AccessMode::READ_ONLY);
147
148   node.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
149
150   for(auto& renderable : mRenderables)
151   {
152     renderable->OnCreate(*this, params, node);
153   }
154
155   for(auto& e : mExtras)
156   {
157     node.RegisterProperty(e.mKey, e.mValue);
158   }
159
160   for(auto& c : mConstraints)
161   {
162     params.mConstrainables.push_back(ConstraintRequest{&c, node});
163   }
164
165   return node;
166 }
167
168 Matrix NodeDefinition::GetLocalSpace() const
169 {
170   Matrix localSpace{false};
171   localSpace.SetTransformComponents(mScale, mOrientation, mPosition);
172   return localSpace;
173 }
174
175 std::string_view NodeDefinition::GetIblScaleFactorUniformName()
176 {
177   return IBL_INTENSITY_STRING;
178 }
179
180 std::string_view NodeDefinition::GetIblYDirectionUniformName()
181 {
182   return IBL_Y_DIRECTION;
183 }
184
185 std::string_view NodeDefinition::GetIblMaxLodUniformName()
186 {
187   return IBL_MAXLOD;
188 }
189
190 bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
191 {
192   if(mRenderables.empty())
193   {
194     return false;
195   }
196
197   bool useModelExtents = false;
198   for(auto& renderable : mRenderables)
199   {
200     Vector3 renderableMin(Vector3::ONE * MAXFLOAT), renderableMax(-Vector3::ONE * MAXFLOAT);
201     if(!renderable->GetExtents(resources, renderableMin, renderableMax))
202     {
203       useModelExtents = false;
204       break;
205     }
206     useModelExtents = true;
207     min.x           = std::min(min.x, renderableMin.x);
208     min.y           = std::min(min.y, renderableMin.y);
209     min.z           = std::min(min.z, renderableMin.z);
210     max.x           = std::max(max.x, renderableMax.x);
211     max.y           = std::max(max.y, renderableMax.y);
212     max.z           = std::max(max.z, renderableMax.z);
213   }
214   if(!useModelExtents)
215   {
216     // If the renderable node don't have mesh accessor, use size to compute extents.
217     min = -mSize / 2.0f;
218     max = mSize / 2.0f;
219   }
220   return true;
221 }
222
223 bool ModelRenderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
224 {
225   auto&    mesh    = resources.mMeshes[mMeshIdx];
226   uint32_t minSize = mesh.first.mPositions.mBlob.mMin.size();
227   uint32_t maxSize = mesh.first.mPositions.mBlob.mMax.size();
228   if(minSize == maxSize && minSize >= 2u && maxSize >= 2u)
229   {
230     min = Vector3(mesh.first.mPositions.mBlob.mMin[0], mesh.first.mPositions.mBlob.mMin[1], 0.0f);
231     max = Vector3(mesh.first.mPositions.mBlob.mMax[0], mesh.first.mPositions.mBlob.mMax[1], 0.0f);
232     if(minSize == 3u)
233     {
234       min.z = mesh.first.mPositions.mBlob.mMin[2];
235       max.z = mesh.first.mPositions.mBlob.mMax[2];
236     }
237     return true;
238   }
239   return false;
240 }
241
242 void ModelRenderable::RegisterResources(IResourceReceiver& receiver) const
243 {
244   Renderable::RegisterResources(receiver);
245   receiver.Register(ResourceType::Mesh, mMeshIdx);
246   receiver.Register(ResourceType::Material, mMaterialIdx);
247 }
248
249 void ModelRenderable::ReflectResources(IResourceReflector& reflector)
250 {
251   Renderable::ReflectResources(reflector);
252   reflector.Reflect(ResourceType::Mesh, mMeshIdx);
253   reflector.Reflect(ResourceType::Material, mMaterialIdx);
254 }
255
256 void ModelRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const
257 {
258   DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX);
259   if(mShaderIdx == INVALID_INDEX)
260   {
261     Shader          shader          = params.mShaderManager->ProduceShader(params.mResources.mMaterials[mMaterialIdx].first, params.mResources.mMeshes[mMeshIdx].first);
262     static Geometry defaultGeometry = Geometry::New();
263     Renderer        renderer        = Renderer::New(defaultGeometry, shader);
264
265     RendererState::Apply(params.mShaderManager->GetRendererState(params.mResources.mMaterials[mMaterialIdx].first), renderer);
266     Internal::GetImplementation(node).UpdateShader(params.mShaderManager);
267     node.AddRenderer(renderer);
268   }
269   else
270   {
271     Renderable::OnCreate(nodeDefinition, params, node);
272   }
273
274   auto& resources = params.mResources;
275   auto& mesh      = resources.mMeshes[mMeshIdx];
276
277   auto     renderer = node.GetRendererAt(node.GetRendererCount() - 1u);
278   Geometry geometry = mesh.second.geometry;
279   renderer.SetGeometry(geometry);
280
281   TextureSet textures = resources.mMaterials[mMaterialIdx].second;
282   // Set the blend shape texture.
283   if(mesh.second.blendShapeGeometry)
284   {
285     TextureSet newTextureSet = TextureSet::New();
286     newTextureSet.SetTexture(0u, mesh.second.blendShapeGeometry);
287
288     const unsigned int numberOfTextures = textures.GetTextureCount();
289     for(unsigned int index = 0u; index < numberOfTextures; ++index)
290     {
291       const unsigned int newIndex = index + 1u;
292       newTextureSet.SetTexture(newIndex, textures.GetTexture(index));
293       newTextureSet.SetSampler(newIndex, textures.GetSampler(index));
294     }
295
296     textures = newTextureSet;
297   }
298   renderer.SetTextures(textures);
299
300   {
301     mesh.first.mModelPrimitive = ModelPrimitive::New();
302     auto primitive             = mesh.first.mModelPrimitive;
303     GetImplementation(primitive).SetRenderer(renderer);
304
305     Index    envIndex       = resources.mMaterials[mMaterialIdx].first.mEnvironmentIdx;
306     uint32_t specularMipmap = resources.mEnvironmentMaps[envIndex].second.mSpecularMipmapLevels;
307     GetImplementation(primitive).SetImageBasedLightTexture(resources.mEnvironmentMaps[envIndex].second.mDiffuse,
308                                                            resources.mEnvironmentMaps[envIndex].second.mSpecular,
309                                                            resources.mEnvironmentMaps[envIndex].first.mIblIntensity,
310                                                            specularMipmap);
311
312     bool hasPositions = false;
313     bool hasNormals   = false;
314     bool hasTangents  = false;
315     mesh.first.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
316     GetImplementation(primitive).SetBlendShapeOptions(hasPositions, hasNormals, hasTangents, mesh.first.mBlendShapeVersion);
317     GetImplementation(primitive).SetBlendShapeGeometry(mesh.second.blendShapeGeometry);
318     GetImplementation(primitive).SetSkinned(mesh.first.IsSkinned());
319   }
320
321   auto shader = renderer.GetShader();
322   if(mesh.first.IsSkinned())
323   {
324     params.mSkinnables.push_back(SkinningShaderConfigurationRequest{mesh.first.mSkeletonIdx, shader, mesh.first.mModelPrimitive});
325   }
326
327   if(mesh.first.HasBlendShapes())
328   {
329     params.mBlendshapeRequests.push_back(BlendshapeShaderConfigurationRequest{nodeDefinition.mName, mMeshIdx, shader, mesh.first.mModelPrimitive});
330   }
331
332   auto& matDef = resources.mMaterials[mMaterialIdx].first;
333   renderer.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
334   renderer.RegisterProperty("uMetallicFactor", matDef.mMetallic);
335   renderer.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
336   renderer.RegisterProperty("uDielectricSpecular", matDef.mDielectricSpecular);
337   renderer.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
338   renderer.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
339   renderer.RegisterProperty("uNormalScale", matDef.mNormalScale);
340   renderer.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
341   if(matDef.mFlags & MaterialDefinition::OCCLUSION)
342   {
343     renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
344   }
345
346   float opaque      = matDef.mIsOpaque ? 1.0f : 0.0f;
347   float mask        = matDef.mIsMask ? 1.0f : 0.0f;
348   float alphaCutoff = matDef.GetAlphaCutoff();
349
350   renderer.RegisterProperty("uOpaque", opaque);
351   renderer.RegisterProperty("uMask", mask);
352   renderer.RegisterProperty("uAlphaThreshold", alphaCutoff);
353
354   Index    envIndex       = matDef.mEnvironmentIdx;
355   uint32_t specularMipmap = resources.mEnvironmentMaps[envIndex].second.mSpecularMipmapLevels;
356   renderer.RegisterProperty(IBL_MAXLOD.data(), static_cast<float>(specularMipmap));
357   renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIndex].first.mIblIntensity);
358   renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIndex].first.mYDirection);
359
360   node.SetProperty(Actor::Property::COLOR, mColor);
361
362   // If user uses customshader, the properties of the shader could not be changed by Material.
363   if(mShaderIdx == INVALID_INDEX)
364   {
365     matDef.mMaterial            = Material::New();
366     auto     material           = matDef.mMaterial;
367     uint32_t textureIndexOffset = (mesh.second.blendShapeGeometry) ? 1 : 0;
368     uint32_t textureIndex       = 0;
369     for(uint32_t i = 0; i < MAX_NUMBER_OF_MATERIAL_TEXTURE; ++i)
370     {
371       Internal::Material::TextureInformation textureInformation;
372       if(matDef.CheckTextures(SEMANTICS[i]))
373       {
374         textureInformation.mTexture = textures.GetTexture(textureIndex + textureIndexOffset);
375         textureInformation.mSampler = textures.GetSampler(textureIndex + textureIndexOffset);
376         textureInformation.mUrl     = matDef.mTextureStages[textureIndex].mTexture.mDirectoryPath + matDef.mTextureStages[textureIndex].mTexture.mImageUri;
377         textureIndex++;
378       }
379       textureInformation.mFactor = GetTextureFactor(matDef, SEMANTICS[i]);
380       GetImplementation(material).SetTextureInformation(TEXTURE_TYPES[i], std::move(textureInformation));
381     }
382     material.SetProperty(Scene3D::Material::Property::ALPHA_MODE, matDef.mAlphaModeType);
383     material.SetProperty(Scene3D::Material::Property::ALPHA_CUTOFF, matDef.GetAlphaCutoff());
384     material.SetProperty(Scene3D::Material::Property::DOUBLE_SIDED, matDef.mDoubleSided);
385     material.SetProperty(Scene3D::Material::Property::IOR, matDef.mIor);
386     GetImplementation(mesh.first.mModelPrimitive).SetMaterial(material, false);
387     GetImplementation(material).ResetFlag();
388   }
389
390   node.AddModelPrimitive(mesh.first.mModelPrimitive);
391 }
392
393 void ArcRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const
394 {
395   ModelRenderable::OnCreate(nodeDefinition, params, node);
396
397   node.RegisterProperty("antiAliasing", mAntiAliasing ? 1 : 0);
398   node.RegisterProperty("arcCaps", mArcCaps);
399   node.RegisterProperty("radius", mRadius);
400
401   const float startAngleRadians = mStartAngleDegrees * Math::PI_OVER_180;
402   Vector2     startPolar{std::cos(startAngleRadians), std::sin(startAngleRadians)};
403   node.RegisterProperty("startAngle", startPolar);
404
405   const float endAngleRadians = mEndAngleDegrees * Math::PI_OVER_180;
406   Vector2     endPolar{std::cos(endAngleRadians), std::sin(endAngleRadians)};
407   node.RegisterProperty("endAngle", endPolar);
408 }
409
410 void ArcRenderable::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector)
411 {
412   float endAngle = 0.f;
413
414   if(diffAngle <= 0.001f)
415   {
416     // 0.001 is used to ensure is empty arc when startAngle = endAngle + 360 * N
417     endAngle = startAngle + 0.001f;
418   }
419   else if(diffAngle >= 360.f)
420   {
421     endAngle = diffAngle + 359.99f;
422   }
423   else
424   {
425     endAngle = startAngle + 360.0f + diffAngle;
426   }
427   endVector.x = cosf(endAngle * Math::PI_OVER_180);
428   endVector.y = sinf(endAngle * Math::PI_OVER_180);
429 }
430
431 } // namespace Loader
432 } // namespace Scene3D
433 } // namespace Dali