2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-scene3d/public-api/loader/node-definition.h>
22 #include <dali-scene3d/public-api/loader/renderer-state.h>
23 #include <dali-scene3d/public-api/loader/utils.h>
29 constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
30 constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
31 constexpr std::string_view IBL_MAXLOD("uMaxLOD");
38 bool NodeDefinition::Renderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
43 void NodeDefinition::Renderable::RegisterResources(IResourceReceiver& receiver) const
45 receiver.Register(ResourceType::Shader, mShaderIdx);
48 void NodeDefinition::Renderable::ReflectResources(IResourceReflector& reflector)
50 reflector.Reflect(ResourceType::Shader, mShaderIdx);
53 void NodeDefinition::Renderable::OnCreate(const NodeDefinition& node, CreateParams& params, Actor& actor) const
55 DALI_ASSERT_DEBUG(mShaderIdx != INVALID_INDEX);
56 auto& resources = params.mResources;
57 Shader shader = resources.mShaders[mShaderIdx].second;
59 static Geometry defaultGeometry = Geometry::New();
60 Renderer renderer = Renderer::New(defaultGeometry, shader);
62 RendererState::Apply(resources.mShaders[mShaderIdx].first.mRendererState, renderer);
64 actor.AddRenderer(renderer);
67 const char* NodeDefinition::ORIGINAL_MATRIX_PROPERTY_NAME = "originalMatrix";
69 Actor NodeDefinition::CreateActor(CreateParams& params)
71 Actor actor = Actor::New();
72 mNodeId = actor.GetProperty<int32_t>(Dali::Actor::Property::ID);
74 SetActorCentered(actor);
76 actor.SetProperty(Actor::Property::NAME, mName);
77 actor.SetProperty(Actor::Property::POSITION, mPosition);
78 actor.SetProperty(Actor::Property::ORIENTATION, mOrientation);
79 actor.SetProperty(Actor::Property::SCALE, mScale);
80 actor.SetProperty(Actor::Property::SIZE, mSize);
81 actor.SetProperty(Actor::Property::VISIBLE, mIsVisible);
83 actor.RegisterProperty(ORIGINAL_MATRIX_PROPERTY_NAME, GetLocalSpace(), Property::AccessMode::READ_ONLY);
85 actor.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
87 for(auto& renderable : mRenderables)
89 renderable->OnCreate(*this, params, actor);
92 for(auto& e : mExtras)
94 actor.RegisterProperty(e.mKey, e.mValue);
97 for(auto& c : mConstraints)
99 params.mConstrainables.push_back(ConstraintRequest{&c, actor});
105 Matrix NodeDefinition::GetLocalSpace() const
107 Matrix localSpace{false};
108 localSpace.SetTransformComponents(mScale, mOrientation, mPosition);
112 std::string_view NodeDefinition::GetIblScaleFactorUniformName()
114 return IBL_INTENSITY_STRING;
117 std::string_view NodeDefinition::GetIblYDirectionUniformName()
119 return IBL_Y_DIRECTION;
122 std::string_view NodeDefinition::GetIblMaxLodUniformName()
127 bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
129 if(mRenderables.empty())
134 bool useModelExtents = false;
135 for(auto& renderable : mRenderables)
137 Vector3 renderableMin(Vector3::ONE * MAXFLOAT), renderableMax(-Vector3::ONE * MAXFLOAT);
138 if(!renderable->GetExtents(resources, renderableMin, renderableMax))
140 useModelExtents = false;
143 useModelExtents = true;
144 min.x = std::min(min.x, renderableMin.x);
145 min.y = std::min(min.y, renderableMin.y);
146 min.z = std::min(min.z, renderableMin.z);
147 max.x = std::max(max.x, renderableMax.x);
148 max.y = std::max(max.y, renderableMax.y);
149 max.z = std::max(max.z, renderableMax.z);
153 // If the renderable node don't have mesh accessor, use size to compute extents.
160 bool ModelRenderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
162 auto& mesh = resources.mMeshes[mMeshIdx];
163 uint32_t minSize = mesh.first.mPositions.mBlob.mMin.size();
164 uint32_t maxSize = mesh.first.mPositions.mBlob.mMax.size();
165 if(minSize == maxSize && minSize >= 2u && maxSize >= 2u)
167 min = Vector3(mesh.first.mPositions.mBlob.mMin[0], mesh.first.mPositions.mBlob.mMin[1], 0.0f);
168 max = Vector3(mesh.first.mPositions.mBlob.mMax[0], mesh.first.mPositions.mBlob.mMax[1], 0.0f);
171 min.z = mesh.first.mPositions.mBlob.mMin[2];
172 max.z = mesh.first.mPositions.mBlob.mMax[2];
179 void ModelRenderable::RegisterResources(IResourceReceiver& receiver) const
181 Renderable::RegisterResources(receiver);
182 receiver.Register(ResourceType::Mesh, mMeshIdx);
183 receiver.Register(ResourceType::Material, mMaterialIdx);
186 void ModelRenderable::ReflectResources(IResourceReflector& reflector)
188 Renderable::ReflectResources(reflector);
189 reflector.Reflect(ResourceType::Mesh, mMeshIdx);
190 reflector.Reflect(ResourceType::Material, mMaterialIdx);
193 void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
195 DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX);
196 Renderable::OnCreate(node, params, actor);
198 auto& resources = params.mResources;
199 auto& mesh = resources.mMeshes[mMeshIdx];
201 auto renderer = actor.GetRendererAt(actor.GetRendererCount() - 1u);
202 Geometry geometry = mesh.second.geometry;
203 renderer.SetGeometry(geometry);
205 auto shader = renderer.GetShader();
207 if(mesh.first.IsSkinned())
209 params.mSkinnables.push_back(SkinningShaderConfigurationRequest{mesh.first.mSkeletonIdx, shader});
212 if(mesh.first.HasBlendShapes())
214 params.mBlendshapeRequests.push_back(BlendshapeShaderConfigurationRequest{node.mName, mMeshIdx, shader});
217 TextureSet textures = resources.mMaterials[mMaterialIdx].second;
219 // Set the blend shape texture.
220 if(mesh.second.blendShapeGeometry)
222 TextureSet newTextureSet = TextureSet::New();
223 newTextureSet.SetTexture(0u, mesh.second.blendShapeGeometry);
225 const unsigned int numberOfTextures = textures.GetTextureCount();
226 for(unsigned int index = 0u; index < numberOfTextures; ++index)
228 const unsigned int newIndex = index + 1u;
229 newTextureSet.SetTexture(newIndex, textures.GetTexture(index));
230 newTextureSet.SetSampler(newIndex, textures.GetSampler(index));
233 textures = newTextureSet;
236 renderer.RegisterProperty("uHasVertexColor", static_cast<float>(mesh.first.mColors.IsDefined()));
238 auto& matDef = resources.mMaterials[mMaterialIdx].first;
239 actor.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
240 actor.RegisterProperty("uMetallicFactor", matDef.mMetallic);
241 actor.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
242 actor.RegisterProperty("uDielectricSpecular", matDef.mDielectricSpecular);
243 actor.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
244 actor.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
245 actor.RegisterProperty("uNormalScale", matDef.mNormalScale);
246 actor.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
247 if(matDef.mFlags & MaterialDefinition::OCCLUSION)
249 renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
252 Index envIdx = matDef.mEnvironmentIdx;
253 renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
254 renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection);
256 float opaque = matDef.mIsOpaque ? 1.0f : 0.0f;
257 float mask = matDef.mIsMask ? 1.0f : 0.0f;
258 float alphaCutoff = matDef.GetAlphaCutoff();
260 renderer.RegisterProperty("uOpaque", opaque);
261 renderer.RegisterProperty("uMask", mask);
262 renderer.RegisterProperty("uAlphaThreshold", alphaCutoff);
264 renderer.SetTextures(textures);
266 uint32_t specularMipmap = resources.mEnvironmentMaps[envIdx].second.mSpecularMipmapLevels;
267 actor.SetProperty(Actor::Property::COLOR, mColor);
268 actor.RegisterProperty(IBL_MAXLOD.data(), static_cast<float>(specularMipmap));
271 void ArcRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
273 ModelRenderable::OnCreate(node, params, actor);
275 actor.RegisterProperty("antiAliasing", mAntiAliasing ? 1 : 0);
276 actor.RegisterProperty("arcCaps", mArcCaps);
277 actor.RegisterProperty("radius", mRadius);
279 const float startAngleRadians = mStartAngleDegrees * Math::PI_OVER_180;
280 Vector2 startPolar{std::cos(startAngleRadians), std::sin(startAngleRadians)};
281 actor.RegisterProperty("startAngle", startPolar);
283 const float endAngleRadians = mEndAngleDegrees * Math::PI_OVER_180;
284 Vector2 endPolar{std::cos(endAngleRadians), std::sin(endAngleRadians)};
285 actor.RegisterProperty("endAngle", endPolar);
288 void ArcRenderable::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector)
290 float endAngle = 0.f;
292 if(diffAngle <= 0.001f)
294 // 0.001 is used to ensure is empty arc when startAngle = endAngle + 360 * N
295 endAngle = startAngle + 0.001f;
297 else if(diffAngle >= 360.f)
299 endAngle = diffAngle + 359.99f;
303 endAngle = startAngle + 360.0f + diffAngle;
305 endVector.x = cosf(endAngle * Math::PI_OVER_180);
306 endVector.y = sinf(endAngle * Math::PI_OVER_180);
309 } // namespace Loader
310 } // namespace Scene3D