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