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