f1101508a1dfde19844a77336549973f03424014
[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/public-api/loader/renderer-state.h>
23 #include <dali-scene3d/public-api/loader/utils.h>
24
25 namespace Dali
26 {
27 namespace
28 {
29 constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
30 constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
31 } // namespace
32
33 namespace Scene3D
34 {
35 namespace Loader
36 {
37 bool NodeDefinition::Renderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
38 {
39   return false;
40 }
41
42 void NodeDefinition::Renderable::RegisterResources(IResourceReceiver& receiver) const
43 {
44   receiver.Register(ResourceType::Shader, mShaderIdx);
45 }
46
47 void NodeDefinition::Renderable::ReflectResources(IResourceReflector& reflector)
48 {
49   reflector.Reflect(ResourceType::Shader, mShaderIdx);
50 }
51
52 void NodeDefinition::Renderable::OnCreate(const NodeDefinition& node, CreateParams& params, Actor& actor) const
53 {
54   DALI_ASSERT_DEBUG(mShaderIdx != INVALID_INDEX);
55   auto&  resources = params.mResources;
56   Shader shader    = resources.mShaders[mShaderIdx].second;
57
58   static Geometry defaultGeometry = Geometry::New();
59   Renderer        renderer        = Renderer::New(defaultGeometry, shader);
60
61   RendererState::Apply(resources.mShaders[mShaderIdx].first.mRendererState, renderer);
62
63   actor.AddRenderer(renderer);
64 }
65
66 const char* NodeDefinition::ORIGINAL_MATRIX_PROPERTY_NAME = "originalMatrix";
67
68 Actor NodeDefinition::CreateActor(CreateParams& params)
69 {
70   Actor actor = Actor::New();
71   mNodeId     = actor.GetProperty<int32_t>(Dali::Actor::Property::ID);
72
73   SetActorCentered(actor);
74
75   actor.SetProperty(Actor::Property::NAME, mName);
76   actor.SetProperty(Actor::Property::POSITION, mPosition);
77   actor.SetProperty(Actor::Property::ORIENTATION, mOrientation);
78   actor.SetProperty(Actor::Property::SCALE, mScale);
79   actor.SetProperty(Actor::Property::SIZE, mSize);
80   actor.SetProperty(Actor::Property::VISIBLE, mIsVisible);
81
82   actor.RegisterProperty(ORIGINAL_MATRIX_PROPERTY_NAME, GetLocalSpace(), Property::AccessMode::READ_ONLY);
83
84   actor.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
85
86   for(auto& renderable : mRenderables)
87   {
88     renderable->OnCreate(*this, params, actor);
89   }
90
91   for(auto& e : mExtras)
92   {
93     actor.RegisterProperty(e.mKey, e.mValue);
94   }
95
96   for(auto& c : mConstraints)
97   {
98     params.mConstrainables.push_back(ConstraintRequest{&c, actor});
99   }
100
101   return actor;
102 }
103
104 Matrix NodeDefinition::GetLocalSpace() const
105 {
106   Matrix localSpace{false};
107   localSpace.SetTransformComponents(mScale, mOrientation, mPosition);
108   return localSpace;
109 }
110
111 std::string_view NodeDefinition::GetIblScaleFactorUniformName()
112 {
113   return IBL_INTENSITY_STRING;
114 }
115
116 std::string_view NodeDefinition::GetIblYDirectionUniformName()
117 {
118   return IBL_Y_DIRECTION;
119 }
120
121 bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
122 {
123   if(mRenderables.empty())
124   {
125     return false;
126   }
127
128   bool useModelExtents = false;
129   for(auto& renderable : mRenderables)
130   {
131     Vector3 renderableMin(Vector3::ONE * MAXFLOAT), renderableMax(-Vector3::ONE * MAXFLOAT);
132     if(!renderable->GetExtents(resources, renderableMin, renderableMax))
133     {
134       useModelExtents = false;
135       break;
136     }
137     useModelExtents = true;
138     min.x           = std::min(min.x, renderableMin.x);
139     min.y           = std::min(min.y, renderableMin.y);
140     min.z           = std::min(min.z, renderableMin.z);
141     max.x           = std::max(max.x, renderableMax.x);
142     max.y           = std::max(max.y, renderableMax.y);
143     max.z           = std::max(max.z, renderableMax.z);
144   }
145   if(!useModelExtents)
146   {
147     // If the renderable node don't have mesh accessor, use size to compute extents.
148     min = -mSize / 2.0f;
149     max = mSize / 2.0f;
150   }
151   return true;
152 }
153
154 bool ModelRenderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
155 {
156   auto&    mesh    = resources.mMeshes[mMeshIdx];
157   uint32_t minSize = mesh.first.mPositions.mBlob.mMin.size();
158   uint32_t maxSize = mesh.first.mPositions.mBlob.mMax.size();
159   if(minSize == maxSize && minSize >= 2u && maxSize >= 2u)
160   {
161     min = Vector3(mesh.first.mPositions.mBlob.mMin[0], mesh.first.mPositions.mBlob.mMin[1], 0.0f);
162     max = Vector3(mesh.first.mPositions.mBlob.mMax[0], mesh.first.mPositions.mBlob.mMax[1], 0.0f);
163     if(minSize == 3u)
164     {
165       min.z = mesh.first.mPositions.mBlob.mMin[2];
166       max.z = mesh.first.mPositions.mBlob.mMax[2];
167     }
168     return true;
169   }
170   return false;
171 }
172
173 void ModelRenderable::RegisterResources(IResourceReceiver& receiver) const
174 {
175   Renderable::RegisterResources(receiver);
176   receiver.Register(ResourceType::Mesh, mMeshIdx);
177   receiver.Register(ResourceType::Material, mMaterialIdx);
178 }
179
180 void ModelRenderable::ReflectResources(IResourceReflector& reflector)
181 {
182   Renderable::ReflectResources(reflector);
183   reflector.Reflect(ResourceType::Mesh, mMeshIdx);
184   reflector.Reflect(ResourceType::Material, mMaterialIdx);
185 }
186
187 void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
188 {
189   DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX);
190   Renderable::OnCreate(node, params, actor);
191
192   auto& resources = params.mResources;
193   auto& mesh      = resources.mMeshes[mMeshIdx];
194
195   auto     renderer = actor.GetRendererAt(actor.GetRendererCount() - 1u);
196   Geometry geometry = mesh.second.geometry;
197   renderer.SetGeometry(geometry);
198
199   auto shader = renderer.GetShader();
200
201   if(mesh.first.IsSkinned())
202   {
203     params.mSkinnables.push_back(SkinningShaderConfigurationRequest{mesh.first.mSkeletonIdx, shader});
204   }
205
206   if(mesh.first.HasBlendShapes())
207   {
208     params.mBlendshapeRequests.push_back(BlendshapeShaderConfigurationRequest{node.mName, mMeshIdx, shader});
209   }
210
211   TextureSet textures = resources.mMaterials[mMaterialIdx].second;
212
213   // Set the blend shape texture.
214   if(mesh.second.blendShapeGeometry)
215   {
216     TextureSet newTextureSet = TextureSet::New();
217     newTextureSet.SetTexture(0u, mesh.second.blendShapeGeometry);
218
219     const unsigned int numberOfTextures = textures.GetTextureCount();
220     for(unsigned int index = 0u; index < numberOfTextures; ++index)
221     {
222       const unsigned int newIndex = index + 1u;
223       newTextureSet.SetTexture(newIndex, textures.GetTexture(index));
224       newTextureSet.SetSampler(newIndex, textures.GetSampler(index));
225     }
226
227     textures = newTextureSet;
228   }
229
230   renderer.RegisterProperty("uHasVertexColor", static_cast<float>(mesh.first.mColors.IsDefined()));
231
232   auto& matDef = resources.mMaterials[mMaterialIdx].first;
233   actor.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
234   actor.RegisterProperty("uMetallicFactor", matDef.mMetallic);
235   actor.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
236   actor.RegisterProperty("uDielectricSpecular", matDef.mDielectricSpecular);
237   actor.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
238   actor.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
239   actor.RegisterProperty("uNormalScale", matDef.mNormalScale);
240   if(matDef.mFlags & MaterialDefinition::OCCLUSION)
241   {
242     renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
243   }
244   if(matDef.mFlags & MaterialDefinition::EMISSIVE)
245   {
246     renderer.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
247   }
248
249   Index envIdx = matDef.mEnvironmentIdx;
250   renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
251   renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection);
252
253   float opaque      = matDef.mIsOpaque ? 1.0f : 0.0f;
254   float mask        = matDef.mIsMask ? 1.0f : 0.0f;
255   float alphaCutoff = matDef.GetAlphaCutoff();
256
257   renderer.RegisterProperty("uOpaque", opaque);
258   renderer.RegisterProperty("uMask", mask);
259   renderer.RegisterProperty("uAlphaThreshold", alphaCutoff);
260
261   renderer.SetTextures(textures);
262
263   actor.SetProperty(Actor::Property::COLOR, mColor);
264 }
265
266 void ArcRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
267 {
268   ModelRenderable::OnCreate(node, params, actor);
269
270   actor.RegisterProperty("antiAliasing", mAntiAliasing ? 1 : 0);
271   actor.RegisterProperty("arcCaps", mArcCaps);
272   actor.RegisterProperty("radius", mRadius);
273
274   const float startAngleRadians = mStartAngleDegrees * Math::PI_OVER_180;
275   Vector2     startPolar{std::cos(startAngleRadians), std::sin(startAngleRadians)};
276   actor.RegisterProperty("startAngle", startPolar);
277
278   const float endAngleRadians = mEndAngleDegrees * Math::PI_OVER_180;
279   Vector2     endPolar{std::cos(endAngleRadians), std::sin(endAngleRadians)};
280   actor.RegisterProperty("endAngle", endPolar);
281 }
282
283 void ArcRenderable::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector)
284 {
285   float endAngle = 0.f;
286
287   if(diffAngle <= 0.001f)
288   {
289     // 0.001 is used to ensure is empty arc when startAngle = endAngle + 360 * N
290     endAngle = startAngle + 0.001f;
291   }
292   else if(diffAngle >= 360.f)
293   {
294     endAngle = diffAngle + 359.99f;
295   }
296   else
297   {
298     endAngle = startAngle + 360.0f + diffAngle;
299   }
300   endVector.x = cosf(endAngle * Math::PI_OVER_180);
301   endVector.y = sinf(endAngle * Math::PI_OVER_180);
302 }
303
304 } // namespace Loader
305 } // namespace Scene3D
306 } // namespace Dali