This is a combination of 10 commits.
Make sure that global variables are initialized lazily in scene3d.
Fix coverity issue (no POSITION attribute + use after move)
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
Change namings of gltf-util
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
Remove Duplicated code in gltf2-util using template
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
Enable automated tests that load the exercise DLI model
Replace std::string global variables with C-style string.
A std::string global variable would allocate a memory in heap,
then copy the string from .text section to the heap.
This patch may reduce loading time & memory a little.
Use ModelNode / ModelPrimitive / Material instead of Actor / Renderer
- This patch is based on the previous patch
https://review.tizen.org/gerrit/#/c/platform/core/uifw/dali-toolkit/+/288075/
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
Fix svace/coverity issue (initialize value at Material)
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
Change public member variable to private
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
Allow to use premultiplied external texture
FrameBuffer result colortexture is premultiplied always.
So make we always use premultiplied texture.
And make a way to user determine native image source is premultiplied or not.
+
Since FBO texture always premultiplied, revert scene view's trick
https://review.tizen.org/gerrit/c/platform/core/uifw/dali-toolkit/+/285486
Change-Id: Idfec7ea5a26dcc827953ce268c32adc8f89247bd
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
utc-Dali-Hash.cpp
utc-Dali-JsonReader.cpp
utc-Dali-JsonUtil.cpp
+ utc-Dali-MaterialImpl.cpp
utc-Dali-ModelCacheManager.cpp
+ utc-Dali-ModelPrimitiveImpl.cpp
)
# List of test harness files (Won't get parsed for test cases)
1.f,
1.f,
Vector3(0.2, 0.1, 0.0),
+ 1.0f,
0.0f,
0.5f,
Vector3(0, 0, 1),
false,
true,
false,
+ Scene3D::Material::AlphaModeType::MASK,
true,
true,
{
},
},
},
+ nullptr
},
{
nullptr,
1.f,
1.f,
Vector3(0.2, 0.1, 0.0),
+ -1.0f,
0.04f,
1.0f,
Vector3::ONE,
true,
true,
false,
+ Scene3D::Material::AlphaModeType::OPAQUE,
true,
false,
{
},
},
},
+ nullptr,
},
};
DALI_TEST_EQUAL(md.mNormalScale, m.mNormalScale);
DALI_TEST_EQUAL(md.mOcclusionStrength, m.mOcclusionStrength);
DALI_TEST_EQUAL(md.mEmissiveFactor, m.mEmissiveFactor);
+ DALI_TEST_EQUAL(md.mIor, m.mIor);
DALI_TEST_EQUAL(md.mDielectricSpecular, m.mDielectricSpecular);
DALI_TEST_EQUAL(md.mSpecularFactor, m.mSpecularFactor);
DALI_TEST_EQUAL(md.mSpecularColorFactor, m.mSpecularColorFactor);
DALI_TEST_EQUAL(md.mNeedAlbedoTexture, m.mNeedAlbedoTexture);
DALI_TEST_EQUAL(md.mNeedMetallicRoughnessTexture, m.mNeedMetallicRoughnessTexture);
DALI_TEST_EQUAL(md.mNeedNormalTexture, m.mNeedNormalTexture);
+ DALI_TEST_EQUAL(md.mAlphaModeType, m.mAlphaModeType);
DALI_TEST_EQUAL(md.mIsOpaque, m.mIsOpaque);
DALI_TEST_EQUAL(md.mIsMask, m.mIsMask);
}
DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions.size(), 1u);
- DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions[0].mProperties.size(), 57u);
+ DALI_TEST_EQUAL(ctx.loadResult.mAnimationDefinitions[0].GetPropertyCount(), 57u);
- uint32_t id = ctx.loadResult.mScene.GetNode(ctx.loadResult.mAnimationDefinitions[0].mProperties[0].mNodeIndex)->mNodeId;
+ uint32_t id = ctx.loadResult.mScene.GetNode(ctx.loadResult.mAnimationDefinitions[0].GetPropertyAt(0).mNodeIndex)->mNodeId;
DALI_TEST_EQUAL(id, root.FindChildByName("Skeleton_torso_joint_1").GetProperty<int32_t>(Dali::Actor::Property::ID));
END_TEST;
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <toolkit-event-thread-callback.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/internal/model-components/material-impl.h>
+#include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+void model_components_material_impl_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void model_components_material_impl_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+namespace
+{
+const char* TEST_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/gallery-small-1.jpg";
+} // namespace
+
+// Method test
+int UtcDaliMaterialImplSetGetTextureInformation(void)
+{
+ tet_infoline("UtcDaliMaterialImplSetGetTextureInformation.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::Material material = Scene3D::Material::New();
+
+ Scene3D::Internal::Material::TextureInformation baseColor;
+ Dali::Texture baseColorTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ Dali::Sampler baseColorSampler = Dali::Sampler::New();
+ baseColor.mTexture = baseColorTexture;
+ baseColor.mSampler = baseColorSampler;
+ baseColor.mUrl = "baseColor";
+ GetImplementation(material).SetTextureInformation(Scene3D::Material::TextureType::BASE_COLOR, std::move(baseColor));
+ DALI_TEST_EQUALS(baseColorTexture, material.GetTexture(Scene3D::Material::TextureType::BASE_COLOR), TEST_LOCATION);
+ DALI_TEST_EQUALS(baseColorSampler, material.GetSampler(Scene3D::Material::TextureType::BASE_COLOR), TEST_LOCATION);
+ DALI_TEST_EQUALS("baseColor", material.GetProperty<std::string>(Scene3D::Material::Property::BASE_COLOR_URL), TEST_LOCATION);
+
+ Scene3D::Internal::Material::TextureInformation metallicRoughness;
+ Dali::Texture metallicRoughnessTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ Dali::Sampler metallicRoughnessSampler = Dali::Sampler::New();
+ metallicRoughness.mTexture = metallicRoughnessTexture;
+ metallicRoughness.mSampler = metallicRoughnessSampler;
+ metallicRoughness.mUrl = "metallicRoughness";
+ GetImplementation(material).SetTextureInformation(Scene3D::Material::TextureType::METALLIC_ROUGHNESS, std::move(metallicRoughness));
+ DALI_TEST_EQUALS(metallicRoughnessTexture, material.GetTexture(Scene3D::Material::TextureType::METALLIC_ROUGHNESS), TEST_LOCATION);
+ DALI_TEST_EQUALS(metallicRoughnessSampler, material.GetSampler(Scene3D::Material::TextureType::METALLIC_ROUGHNESS), TEST_LOCATION);
+ DALI_TEST_EQUALS("metallicRoughness", material.GetProperty<std::string>(Scene3D::Material::Property::METALLIC_ROUGHNESS_URL), TEST_LOCATION);
+
+ Scene3D::Internal::Material::TextureInformation normal;
+ Dali::Texture normalTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ Dali::Sampler normalSampler = Dali::Sampler::New();
+ normal.mTexture = normalTexture;
+ normal.mSampler = normalSampler;
+ normal.mUrl = "normal";
+ GetImplementation(material).SetTextureInformation(Scene3D::Material::TextureType::NORMAL, std::move(normal));
+ DALI_TEST_EQUALS(normalTexture, material.GetTexture(Scene3D::Material::TextureType::NORMAL), TEST_LOCATION);
+ DALI_TEST_EQUALS(normalSampler, material.GetSampler(Scene3D::Material::TextureType::NORMAL), TEST_LOCATION);
+ DALI_TEST_EQUALS("normal", material.GetProperty<std::string>(Scene3D::Material::Property::NORMAL_URL), TEST_LOCATION);
+
+ Dali::TextureSet textureSet = GetImplementation(material).GetTextureSet();
+ DALI_TEST_EQUALS(3, textureSet.GetTextureCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(baseColorTexture, textureSet.GetTexture(0u), TEST_LOCATION);
+ DALI_TEST_EQUALS(metallicRoughnessTexture, textureSet.GetTexture(1u), TEST_LOCATION);
+ DALI_TEST_EQUALS(normalTexture, textureSet.GetTexture(2u), TEST_LOCATION);
+ DALI_TEST_EQUALS(baseColorSampler, textureSet.GetSampler(0u), TEST_LOCATION);
+ DALI_TEST_EQUALS(metallicRoughnessSampler, textureSet.GetSampler(1u), TEST_LOCATION);
+
+ DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+ GetImplementation(material).UpdateMaterialData();
+
+ std::vector<std::string> defines;
+ defines.push_back("THREE_TEX");
+ defines.push_back("GLTF_CHANNELS");
+ defines.push_back("BASECOLOR_TEX");
+ defines.push_back("METALLIC_ROUGHNESS_TEX");
+ defines.push_back("NORMAL_TEX");
+
+ std::string fragmentShader = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
+ for(const auto& define : defines)
+ {
+ Scene3D::Loader::ShaderDefinition::ApplyDefine(fragmentShader, define);
+ }
+
+ DALI_TEST_EQUALS(fragmentShader, GetImplementation(material).GetFragmentShader(), TEST_LOCATION);
+
+ Scene3D ::Internal ::Material ::TextureInformation occlusion;
+ Dali ::Texture occlusiontexture = Dali ::Texture ::New(TextureType ::TEXTURE_2D, Pixel ::RGBA8888, 100, 100);
+ Dali ::Sampler occlusionSampler = Dali ::Sampler ::New();
+ occlusion.mTexture = occlusiontexture;
+ occlusion.mSampler = occlusionSampler;
+ occlusion.mUrl = "occlusion";
+ GetImplementation(material).SetTextureInformation(Scene3D ::Material ::TextureType ::OCCLUSION, std ::move(occlusion));
+ DALI_TEST_EQUALS(occlusiontexture, material.GetTexture(Scene3D ::Material ::TextureType ::OCCLUSION), TEST_LOCATION);
+ DALI_TEST_EQUALS(occlusionSampler, material.GetSampler(Scene3D ::Material ::TextureType ::OCCLUSION), TEST_LOCATION);
+ DALI_TEST_EQUALS("occlusion", material.GetProperty<std ::string>(Scene3D ::Material ::Property ::OCCLUSION_URL), TEST_LOCATION);
+
+ Scene3D::Internal::Material::TextureInformation emissive;
+ Dali::Texture emissiveTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ Dali::Sampler emissiveSampler = Dali::Sampler::New();
+ emissive.mTexture = emissiveTexture;
+ emissive.mSampler = emissiveSampler;
+ emissive.mUrl = "emissive";
+ GetImplementation(material).SetTextureInformation(Scene3D::Material::TextureType::EMISSIVE, std::move(emissive));
+ DALI_TEST_EQUALS(emissiveTexture, material.GetTexture(Scene3D::Material::TextureType::EMISSIVE), TEST_LOCATION);
+ DALI_TEST_EQUALS(emissiveSampler, material.GetSampler(Scene3D::Material::TextureType::EMISSIVE), TEST_LOCATION);
+ DALI_TEST_EQUALS("emissive", material.GetProperty<std::string>(Scene3D::Material::Property::EMISSIVE_URL), TEST_LOCATION);
+
+ Scene3D ::Internal ::Material ::TextureInformation specular;
+ Dali ::Texture specularTexture = Dali ::Texture ::New(TextureType ::TEXTURE_2D, Pixel ::RGBA8888, 100, 100);
+ Dali ::Sampler specularSampler = Dali ::Sampler ::New();
+ specular.mTexture = specularTexture;
+ specular.mSampler = specularSampler;
+ specular.mUrl = "specular";
+ GetImplementation(material).SetTextureInformation(Scene3D ::Material ::TextureType ::SPECULAR, std ::move(specular));
+ DALI_TEST_EQUALS(specularTexture, material.GetTexture(Scene3D ::Material ::TextureType ::SPECULAR), TEST_LOCATION);
+ DALI_TEST_EQUALS(specularSampler, material.GetSampler(Scene3D ::Material ::TextureType ::SPECULAR), TEST_LOCATION);
+ DALI_TEST_EQUALS("specular", material.GetProperty<std ::string>(Scene3D ::Material ::Property ::SPECULAR_URL), TEST_LOCATION);
+
+ Scene3D::Internal::Material::TextureInformation specularColor;
+ Dali::Texture specularColorTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ Dali::Sampler specularColorSampler = Dali::Sampler::New();
+ specularColor.mTexture = specularColorTexture;
+ specularColor.mSampler = specularColorSampler;
+ specularColor.mUrl = "specularColor";
+ GetImplementation(material).SetTextureInformation(Scene3D::Material::TextureType::SPECULAR_COLOR, std::move(specularColor));
+ DALI_TEST_EQUALS(specularColorTexture, material.GetTexture(Scene3D::Material::TextureType::SPECULAR_COLOR), TEST_LOCATION);
+ DALI_TEST_EQUALS(specularColorSampler, material.GetSampler(Scene3D::Material::TextureType::SPECULAR_COLOR), TEST_LOCATION);
+ DALI_TEST_EQUALS("specularColor", material.GetProperty<std::string>(Scene3D::Material::Property::SPECULAR_COLOR_URL), TEST_LOCATION);
+
+ textureSet = GetImplementation(material).GetTextureSet();
+ DALI_TEST_EQUALS(7, textureSet.GetTextureCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(baseColorTexture, textureSet.GetTexture(0u), TEST_LOCATION);
+ DALI_TEST_EQUALS(metallicRoughnessTexture, textureSet.GetTexture(1u), TEST_LOCATION);
+ DALI_TEST_EQUALS(normalTexture, textureSet.GetTexture(2u), TEST_LOCATION);
+ DALI_TEST_EQUALS(occlusiontexture, textureSet.GetTexture(3u), TEST_LOCATION);
+ DALI_TEST_EQUALS(emissiveTexture, textureSet.GetTexture(4u), TEST_LOCATION);
+ DALI_TEST_EQUALS(specularTexture, textureSet.GetTexture(5u), TEST_LOCATION);
+ DALI_TEST_EQUALS(specularColorTexture, textureSet.GetTexture(6u), TEST_LOCATION);
+
+ DALI_TEST_EQUALS(baseColorSampler, textureSet.GetSampler(0u), TEST_LOCATION);
+ DALI_TEST_EQUALS(metallicRoughnessSampler, textureSet.GetSampler(1u), TEST_LOCATION);
+ DALI_TEST_EQUALS(normalSampler, textureSet.GetSampler(2u), TEST_LOCATION);
+ DALI_TEST_EQUALS(occlusionSampler, textureSet.GetSampler(3u), TEST_LOCATION);
+ DALI_TEST_EQUALS(emissiveSampler, textureSet.GetSampler(4u), TEST_LOCATION);
+ DALI_TEST_EQUALS(specularSampler, textureSet.GetSampler(5u), TEST_LOCATION);
+ DALI_TEST_EQUALS(specularColorSampler, textureSet.GetSampler(6u), TEST_LOCATION);
+
+ DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+ GetImplementation(material).UpdateMaterialData();
+
+ defines.push_back("OCCLUSION");
+ defines.push_back("EMISSIVE");
+ defines.push_back("MATERIAL_SPECULAR_TEXTURE");
+ defines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE");
+
+ fragmentShader = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
+ for(const auto& define : defines)
+ {
+ Scene3D::Loader::ShaderDefinition::ApplyDefine(fragmentShader, define);
+ }
+
+ DALI_TEST_EQUALS(fragmentShader, GetImplementation(material).GetFragmentShader(), TEST_LOCATION);
+
+ END_TEST;
+}
+
+// Method test
+int UtcDaliMaterialCheckUniform(void)
+{
+ tet_infoline("UtcDaliMaterialCheckUniform.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::Material material = Scene3D::Material::New();
+
+ Vector4 baseColorFactor(0.1f, 0.2f, 0.3f, 0.4f);
+ material.SetProperty(Scene3D::Material::Property::BASE_COLOR_FACTOR, baseColorFactor);
+ DALI_TEST_EQUALS(baseColorFactor, material.GetProperty<Vector4>(Scene3D::Material::Property::BASE_COLOR_FACTOR), TEST_LOCATION);
+
+ float metallicFactor = 0.5f;
+ material.SetProperty(Scene3D::Material::Property::METALLIC_FACTOR, metallicFactor);
+ DALI_TEST_EQUALS(metallicFactor, material.GetProperty<float>(Scene3D::Material::Property::METALLIC_FACTOR), TEST_LOCATION);
+
+ float roughnessFactor = 0.6f;
+ material.SetProperty(Scene3D::Material::Property::ROUGHNESS_FACTOR, roughnessFactor);
+ DALI_TEST_EQUALS(roughnessFactor, material.GetProperty<float>(Scene3D::Material::Property::ROUGHNESS_FACTOR), TEST_LOCATION);
+
+ float normalScale = 0.7f;
+ material.SetProperty(Scene3D::Material::Property::NORMAL_SCALE, normalScale);
+ DALI_TEST_EQUALS(normalScale, material.GetProperty<float>(Scene3D::Material::Property::NORMAL_SCALE), TEST_LOCATION);
+
+ float occlusionStrength = 0.8f;
+ material.SetProperty(Scene3D::Material::Property::OCCLUSION_STRENGTH, occlusionStrength);
+ DALI_TEST_EQUALS(occlusionStrength, material.GetProperty<float>(Scene3D::Material::Property::OCCLUSION_STRENGTH), TEST_LOCATION);
+
+ Vector3 emissiveFactor(0.9f, 0.1f, 0.2f);
+ material.SetProperty(Scene3D::Material::Property::EMISSIVE_FACTOR, emissiveFactor);
+ DALI_TEST_EQUALS(emissiveFactor, material.GetProperty<Vector3>(Scene3D::Material::Property::EMISSIVE_FACTOR), TEST_LOCATION);
+
+ Dali::Scene3D::Material::AlphaModeType alphaMode = Dali::Scene3D::Material::AlphaModeType::BLEND;
+ material.SetProperty(Scene3D::Material::Property::ALPHA_MODE, alphaMode);
+ DALI_TEST_EQUALS(alphaMode, material.GetProperty<Dali::Scene3D::Material::AlphaModeType>(Scene3D::Material ::Property ::ALPHA_MODE), TEST_LOCATION);
+
+ float alphaCutoff = 0.9f;
+ material.SetProperty(Scene3D ::Material ::Property ::ALPHA_CUTOFF, alphaCutoff);
+ DALI_TEST_EQUALS(alphaCutoff, material.GetProperty<float>(Scene3D ::Material ::Property ::ALPHA_CUTOFF), TEST_LOCATION);
+
+ bool doubleSided = false;
+ material.SetProperty(Scene3D ::Material ::Property ::DOUBLE_SIDED, doubleSided);
+ DALI_TEST_EQUALS(doubleSided, material.GetProperty<bool>(Scene3D ::Material ::Property ::DOUBLE_SIDED), TEST_LOCATION);
+
+ float ior = 1.0f;
+ material.SetProperty(Scene3D::Material::Property::IOR, ior);
+ DALI_TEST_EQUALS(ior, material.GetProperty<float>(Scene3D::Material::Property::IOR), TEST_LOCATION);
+
+ float specularFactor = 1.0f;
+ material.SetProperty(Scene3D::Material::Property::SPECULAR_FACTOR, specularFactor);
+ DALI_TEST_EQUALS(specularFactor, material.GetProperty<float>(Scene3D::Material::Property::SPECULAR_FACTOR), TEST_LOCATION);
+
+ Vector3 specularColorFactor(1.0f, 1.0f, 1.0f);
+ material.SetProperty(Scene3D::Material::Property::SPECULAR_COLOR_FACTOR, specularColorFactor);
+ DALI_TEST_EQUALS(specularColorFactor, material.GetProperty<Vector3>(Scene3D::Material::Property::SPECULAR_COLOR_FACTOR), TEST_LOCATION);
+
+ DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+ GetImplementation(material).UpdateMaterialData();
+
+ Dali::Shader shader = Dali::Shader::New(SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data(), SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data());
+ Dali::Geometry geometry = Dali::Geometry::New();
+ Dali::Renderer renderer = Dali::Renderer::New(geometry, shader);
+
+ GetImplementation(material).SetRendererUniform(renderer);
+
+ DALI_TEST_EQUALS(baseColorFactor, renderer.GetProperty<Vector4>(renderer.GetPropertyIndex("uColorFactor")), TEST_LOCATION);
+ DALI_TEST_EQUALS(metallicFactor, renderer.GetProperty<float>(renderer.GetPropertyIndex("uMetallicFactor")), TEST_LOCATION);
+ DALI_TEST_EQUALS(roughnessFactor, renderer.GetProperty<float>(renderer.GetPropertyIndex("uRoughnessFactor")), TEST_LOCATION);
+ DALI_TEST_EQUALS(normalScale, renderer.GetProperty<float>(renderer.GetPropertyIndex("uNormalScale")), TEST_LOCATION);
+ DALI_TEST_EQUALS(emissiveFactor, renderer.GetProperty<Vector3>(renderer.GetPropertyIndex("uEmissiveFactor")), TEST_LOCATION);
+ float dielectricSpecular = (Dali::Equals(ior, -1.0)) ? 0.04f : powf((ior - 1.0f) / (ior + 1.0f), 2.0f);
+ DALI_TEST_EQUALS(dielectricSpecular, renderer.GetProperty<float>(renderer.GetPropertyIndex("uDielectricSpecular")), TEST_LOCATION);
+ DALI_TEST_EQUALS(specularFactor, renderer.GetProperty<float>(renderer.GetPropertyIndex("uSpecularFactor")), TEST_LOCATION);
+ DALI_TEST_EQUALS(specularColorFactor, renderer.GetProperty<Vector3>(renderer.GetPropertyIndex("uSpecularColorFactor")), TEST_LOCATION);
+ float opaque = alphaMode == Dali::Scene3D::Material::AlphaModeType::BLEND ? 0.0f : 1.0f;
+ float mask = alphaMode == Dali::Scene3D::Material::AlphaModeType::MASK ? 1.0f : 0.0f;
+ DALI_TEST_EQUALS(opaque, renderer.GetProperty<float>(renderer.GetPropertyIndex("uOpaque")), TEST_LOCATION);
+ DALI_TEST_EQUALS(mask, renderer.GetProperty<float>(renderer.GetPropertyIndex("uMask")), TEST_LOCATION);
+ DALI_TEST_EQUALS(alphaCutoff, renderer.GetProperty<float>(renderer.GetPropertyIndex("uAlphaThreshold")), TEST_LOCATION);
+
+ DALI_TEST_EQUALS(DepthTestMode::ON, renderer.GetProperty<DepthTestMode::Type>(Dali::Renderer::Property::DEPTH_TEST_MODE), TEST_LOCATION);
+ DALI_TEST_EQUALS(FaceCullingMode::BACK, renderer.GetProperty<FaceCullingMode::Type>(Dali::Renderer::Property::FACE_CULLING_MODE), TEST_LOCATION);
+ DALI_TEST_EQUALS(DepthTestMode::ON, renderer.GetProperty<DepthTestMode::Type>(Dali::Renderer::Property::DEPTH_TEST_MODE), TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliMaterialImplLoadTexture_1(void)
+{
+ tet_infoline("UtcDaliMaterialLoadTexture.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::Material material = Scene3D::Material::New();
+
+ DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+ DALI_TEST_CHECK(!material.GetTexture(Scene3D::Material::TextureType::BASE_COLOR));
+ material.SetProperty(Scene3D::Material::Property::BASE_COLOR_URL, TEST_IMAGE_FILE_NAME);
+ DALI_TEST_EQUALS(false, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(16);
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(16);
+
+ DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+ DALI_TEST_CHECK(material.GetTexture(Scene3D::Material::TextureType::BASE_COLOR));
+ Dali::Texture baseColorTexture = material.GetTexture(Scene3D::Material::TextureType::BASE_COLOR);
+
+ Dali::TextureSet textureSet = GetImplementation(material).GetTextureSet();
+ DALI_TEST_EQUALS(1u, textureSet.GetTextureCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(baseColorTexture, textureSet.GetTexture(0u), TEST_LOCATION);
+ DALI_TEST_CHECK(textureSet.GetSampler(0u));
+
+ material.SetProperty(Scene3D::Material::Property::BASE_COLOR_URL, TEST_IMAGE_FILE_NAME);
+ DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+ DALI_TEST_EQUALS(baseColorTexture, material.GetTexture(Scene3D::Material::TextureType::BASE_COLOR), TEST_LOCATION);
+
+ material.SetProperty(Scene3D::Material::Property::BASE_COLOR_URL, "");
+ DALI_TEST_CHECK(!material.GetTexture(Scene3D::Material::TextureType::BASE_COLOR));
+
+ END_TEST;
+}
+
+int UtcDaliMaterialImplLoadTexture_2(void)
+{
+ tet_infoline("UtcDaliMaterialImplLoadTexture_2.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::Material material = Scene3D::Material::New();
+
+ DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+ DALI_TEST_CHECK(!material.GetTexture(Scene3D::Material::TextureType::BASE_COLOR));
+ material.SetProperty(Scene3D::Material::Property::BASE_COLOR_URL, TEST_IMAGE_FILE_NAME);
+ DALI_TEST_EQUALS(false, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+ material.SetProperty(Scene3D::Material::Property::BASE_COLOR_URL, "");
+ DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
+ DALI_TEST_CHECK(!material.GetTexture(Scene3D::Material::TextureType::BASE_COLOR));
+
+ END_TEST;
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/internal/model-components/model-primitive-impl.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+void model_components_model_primitive_impl_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void model_components_model_primitive_impl_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+namespace
+{
+} // namespace
+
+// Method test
+int UtcDaliModelPrimitiveImplSetData(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+
+ tet_printf("Check primitive don't have material initial time\n");
+
+ DALI_TEST_CHECK(!GetImplementation(modelPrimitive).GetRenderer());
+ DALI_TEST_CHECK(!modelPrimitive.GetGeometry());
+ DALI_TEST_CHECK(!modelPrimitive.GetMaterial());
+
+ Dali::Geometry geometry = Dali::Geometry::New();
+ Dali::Scene3D::Material material = Dali::Scene3D::Material::New();
+
+ modelPrimitive.SetGeometry(geometry);
+ modelPrimitive.SetMaterial(material);
+ DALI_TEST_CHECK(geometry == modelPrimitive.GetGeometry());
+ DALI_TEST_CHECK(material == modelPrimitive.GetMaterial());
+ DALI_TEST_CHECK(GetImplementation(modelPrimitive).GetRenderer());
+
+ END_TEST;
+}
\ No newline at end of file
utc-Dali-EnvironmentDefinition.cpp
utc-Dali-FacialAnimation.cpp
utc-Dali-KtxLoader.cpp
+ utc-Dali-Material.cpp
utc-Dali-Model.cpp
+ utc-Dali-ModelNode.cpp
+ utc-Dali-ModelPrimitive.cpp
utc-Dali-SceneView.cpp
utc-Dali-MatrixStack.cpp
utc-Dali-MeshDefinition.cpp
return actor.FindChildByName(property.mNodeName);
};
+ uint32_t animatedPropertyIndex = 0;
for (bool b: { false, true })
{
AnimationDefinition animDef;
- animDef.mName = "WalkRight";
- animDef.mDuration = 10.f;
- animDef.mLoopCount = 2;
- animDef.mEndAction = Animation::BAKE_FINAL;
- animDef.mSpeedFactor = .7f;
- animDef.mProperties.push_back(AnimatedProperty{
+ animDef.SetName("WalkRight");
+ animDef.SetDuration(10.f);
+ animDef.SetLoopCount(2);
+ animDef.SetEndAction(Animation::BAKE_FINAL);
+ animDef.SetSpeedFactor(.7f);
+ animDef.SetProperty(animatedPropertyIndex++,std::move(AnimatedProperty{
INVALID_INDEX,
"ChristopherPlummer",
"position",
b
} },
AlphaFunction::EASE_OUT,
- TimePeriod(animDef.mDuration)
- });
+ TimePeriod(animDef.GetDuration())
+ }));
auto anim = animDef.ReAnimate(getActor);
- DALI_TEST_EQUAL(anim.GetDuration(), animDef.mDuration);
- DALI_TEST_EQUAL(anim.GetEndAction(), animDef.mEndAction);
- DALI_TEST_EQUAL(anim.GetSpeedFactor(), animDef.mSpeedFactor);
- DALI_TEST_EQUAL(anim.GetLoopCount(), animDef.mLoopCount);
+ DALI_TEST_EQUAL(anim.GetDuration(), animDef.GetDuration());
+ DALI_TEST_EQUAL(anim.GetEndAction(), animDef.GetEndAction());
+ DALI_TEST_EQUAL(anim.GetSpeedFactor(), animDef.GetSpeedFactor());
+ DALI_TEST_EQUAL(anim.GetLoopCount(), animDef.GetLoopCount());
}
END_TEST;
kf.Add(0.f, Vector3::ZERO);
kf.Add(1.f, Vector3::XAXIS * 100.f);
+ uint32_t animatedPropertyIndex = 0;
AnimationDefinition animDef;
- animDef.mName = "WalkRight";
- animDef.mDuration = 10.f;
- animDef.mLoopCount = 2;
- animDef.mEndAction = Animation::BAKE_FINAL;
- animDef.mSpeedFactor = .7f;
- animDef.mProperties.push_back(AnimatedProperty{
+ animDef.SetName("WalkRight");
+ animDef.SetDuration(10.f);
+ animDef.SetLoopCount(2);
+ animDef.SetEndAction(Animation::BAKE_FINAL);
+ animDef.SetSpeedFactor(.7f);
+ animDef.SetProperty(animatedPropertyIndex++, std::move(AnimatedProperty{
INVALID_INDEX,
"ChristopherPlummer",
"position",
kf,
nullptr,
AlphaFunction::EASE_OUT,
- TimePeriod(animDef.mDuration)
- });
+ TimePeriod(animDef.GetDuration())
+ }));
auto anim = animDef.ReAnimate(getActor);
- DALI_TEST_EQUAL(anim.GetDuration(), animDef.mDuration);
- DALI_TEST_EQUAL(anim.GetEndAction(), animDef.mEndAction);
- DALI_TEST_EQUAL(anim.GetSpeedFactor(), animDef.mSpeedFactor);
- DALI_TEST_EQUAL(anim.GetLoopCount(), animDef.mLoopCount);
+ DALI_TEST_EQUAL(anim.GetDuration(), animDef.GetDuration());
+ DALI_TEST_EQUAL(anim.GetEndAction(), animDef.GetEndAction());
+ DALI_TEST_EQUAL(anim.GetSpeedFactor(), animDef.GetSpeedFactor());
+ DALI_TEST_EQUAL(anim.GetLoopCount(), animDef.GetLoopCount());
END_TEST;
}
AnimationDefinition animDef = LoadBvh(TEST_RESOURCE_DIR "/test.bvh", "testBvh");
- DALI_TEST_EQUAL(animDef.mName, "testBvh");
- DALI_TEST_EQUAL(animDef.mDuration, 0.3f);
+ DALI_TEST_EQUAL(animDef.GetName(), "testBvh");
+ DALI_TEST_EQUAL(animDef.GetDuration(), 0.3f);
- DALI_TEST_EQUAL(animDef.mProperties[0].mNodeName, "root");
- DALI_TEST_EQUAL(animDef.mProperties[0].mPropertyName, "position");
- DALI_TEST_EQUAL(animDef.mProperties[0].mKeyFrames.GetType(), Property::Type::VECTOR3);
- DALI_TEST_EQUAL(animDef.mProperties[0].mTimePeriod.durationSeconds, 0.3f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mNodeName, "root");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mPropertyName, "position");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mKeyFrames.GetType(), Property::Type::VECTOR3);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mTimePeriod.durationSeconds, 0.3f);
- DALI_TEST_EQUAL(animDef.mProperties[1].mNodeName, "root");
- DALI_TEST_EQUAL(animDef.mProperties[1].mPropertyName, "orientation");
- DALI_TEST_EQUAL(animDef.mProperties[1].mKeyFrames.GetType(), Property::Type::ROTATION);
- DALI_TEST_EQUAL(animDef.mProperties[1].mTimePeriod.durationSeconds, 0.3f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mNodeName, "root");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mPropertyName, "orientation");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mKeyFrames.GetType(), Property::Type::ROTATION);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mTimePeriod.durationSeconds, 0.3f);
- DALI_TEST_EQUAL(animDef.mProperties[2].mNodeName, "first");
- DALI_TEST_EQUAL(animDef.mProperties[2].mPropertyName, "position");
- DALI_TEST_EQUAL(animDef.mProperties[2].mKeyFrames.GetType(), Property::Type::VECTOR3);
- DALI_TEST_EQUAL(animDef.mProperties[2].mTimePeriod.durationSeconds, 0.3f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mNodeName, "first");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mPropertyName, "position");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mKeyFrames.GetType(), Property::Type::VECTOR3);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mTimePeriod.durationSeconds, 0.3f);
- DALI_TEST_EQUAL(animDef.mProperties[3].mNodeName, "first");
- DALI_TEST_EQUAL(animDef.mProperties[3].mPropertyName, "orientation");
- DALI_TEST_EQUAL(animDef.mProperties[3].mKeyFrames.GetType(), Property::Type::ROTATION);
- DALI_TEST_EQUAL(animDef.mProperties[3].mTimePeriod.durationSeconds, 0.3f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mNodeName, "first");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mPropertyName, "orientation");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mKeyFrames.GetType(), Property::Type::ROTATION);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mTimePeriod.durationSeconds, 0.3f);
Actor root = Actor::New();
root.SetProperty(Actor::Property::NAME, "root");
};
Animation animation = animDef.ReAnimate(getActor);
- DALI_TEST_EQUAL(animation.GetDuration(), animDef.mDuration);
+ DALI_TEST_EQUAL(animation.GetDuration(), animDef.GetDuration());
application.GetScene().Add(root);
TestApplication application;
AnimationDefinition animDef = LoadBvh("/nothing.bvh", "testBvh");
- DALI_TEST_EQUALS(0u, animDef.mProperties.size(), TEST_LOCATION);
+ DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION);
END_TEST;
}
AnimationDefinition animDef = LoadFacialAnimation(TEST_RESOURCE_DIR "/facial-blendshape-animation.json");
- DALI_TEST_EQUAL(animDef.mName, "Facial_Blendshape_Animation");
- DALI_TEST_EQUAL(animDef.mDuration, 14.966001f);
- DALI_TEST_EQUAL(animDef.mEndAction, Animation::BAKE);
- DALI_TEST_EQUAL(animDef.mSpeedFactor, 1.0f);
- DALI_TEST_EQUAL(animDef.mLoopCount, 1);
- DALI_TEST_EQUAL(animDef.mProperties.size(), 122);
+ std::string name = animDef.GetName();
+ DALI_TEST_EQUAL(name, "Facial_Blendshape_Animation");
+ DALI_TEST_EQUAL(animDef.GetDuration(), 14.966001f);
+ DALI_TEST_EQUAL(animDef.GetEndAction(), Animation::BAKE);
+ DALI_TEST_EQUAL(animDef.GetSpeedFactor(), 1.0f);
+ DALI_TEST_EQUAL(animDef.GetLoopCount(), 1);
+ DALI_TEST_EQUAL(animDef.GetPropertyCount(), 122);
- DALI_TEST_EQUAL(animDef.mProperties[0].mNodeName, "GEO_1");
- DALI_TEST_EQUAL(animDef.mProperties[0].mPropertyName, "uBlendShapeWeight[0]");
- DALI_TEST_EQUAL(animDef.mProperties[0].mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.mProperties[0].mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.mProperties[0].mTimePeriod.durationSeconds, 14.966001f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mNodeName, "GEO_1");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mPropertyName, "uBlendShapeWeight[0]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mTimePeriod.durationSeconds, 14.966001f);
- DALI_TEST_EQUAL(animDef.mProperties[69].mNodeName, "GEO_2");
- DALI_TEST_EQUAL(animDef.mProperties[69].mPropertyName, "uBlendShapeWeight[1]");
- DALI_TEST_EQUAL(animDef.mProperties[69].mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.mProperties[69].mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.mProperties[69].mTimePeriod.durationSeconds, 14.966001f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mNodeName, "GEO_2");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mPropertyName, "uBlendShapeWeight[1]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mTimePeriod.durationSeconds, 14.966001f);
- DALI_TEST_EQUAL(animDef.mProperties[86].mNodeName, "GEO_3");
- DALI_TEST_EQUAL(animDef.mProperties[86].mPropertyName, "uBlendShapeWeight[2]");
- DALI_TEST_EQUAL(animDef.mProperties[86].mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.mProperties[86].mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.mProperties[86].mTimePeriod.durationSeconds, 14.966001f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mNodeName, "GEO_3");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mPropertyName, "uBlendShapeWeight[2]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mTimePeriod.durationSeconds, 14.966001f);
- DALI_TEST_EQUAL(animDef.mProperties[100].mNodeName, "GEO_4");
- DALI_TEST_EQUAL(animDef.mProperties[100].mPropertyName, "uBlendShapeWeight[7]");
- DALI_TEST_EQUAL(animDef.mProperties[100].mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.mProperties[100].mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.mProperties[100].mTimePeriod.durationSeconds, 14.966001f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mNodeName, "GEO_4");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mPropertyName, "uBlendShapeWeight[7]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mTimePeriod.durationSeconds, 14.966001f);
- DALI_TEST_EQUAL(animDef.mProperties[121].mNodeName, "GEO_5");
- DALI_TEST_EQUAL(animDef.mProperties[121].mPropertyName, "uBlendShapeWeight[19]");
- DALI_TEST_EQUAL(animDef.mProperties[121].mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.mProperties[121].mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.mProperties[121].mTimePeriod.durationSeconds, 14.966001f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mNodeName, "GEO_5");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mPropertyName, "uBlendShapeWeight[19]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mTimePeriod.durationSeconds, 14.966001f);
auto actor = Actor::New();
actor.SetProperty(Actor::Property::NAME, "GEO_1");
};
auto anim = animDef.ReAnimate(getActor);
- DALI_TEST_EQUAL(anim.GetDuration(), animDef.mDuration);
- DALI_TEST_EQUAL(anim.GetEndAction(), animDef.mEndAction);
- DALI_TEST_EQUAL(anim.GetSpeedFactor(), animDef.mSpeedFactor);
- DALI_TEST_EQUAL(anim.GetLoopCount(), animDef.mLoopCount);
+ DALI_TEST_EQUAL(anim.GetDuration(), animDef.GetDuration());
+ DALI_TEST_EQUAL(anim.GetEndAction(), animDef.GetEndAction());
+ DALI_TEST_EQUAL(anim.GetSpeedFactor(), animDef.GetSpeedFactor());
+ DALI_TEST_EQUAL(anim.GetLoopCount(), animDef.GetLoopCount());
END_TEST;
}
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/public-api/model-components/material.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+void model_components_material_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void model_components_material_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+namespace
+{
+} // namespace
+
+// Positive test case for a method
+int UtcDaliMaterialNew(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliMaterialNew");
+
+ Scene3D::Material material = Scene3D::Material::New();
+ DALI_TEST_CHECK(material);
+ END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliMaterialDownCast(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliMaterialDownCast");
+
+ Scene3D::Material material = Scene3D::Material::New();
+ BaseHandle handle(material);
+
+ Scene3D::Material material2 = Scene3D::Material::DownCast(handle);
+ DALI_TEST_CHECK(material);
+ DALI_TEST_CHECK(material2);
+ DALI_TEST_CHECK(material2 == material);
+ END_TEST;
+}
+
+int UtcDaliMaterialTypeRegistry(void)
+{
+ ToolkitTestApplication application;
+
+ TypeRegistry typeRegistry = TypeRegistry::Get();
+ DALI_TEST_CHECK(typeRegistry);
+
+ TypeInfo typeInfo = typeRegistry.GetTypeInfo("Material");
+ DALI_TEST_CHECK(typeInfo);
+
+ BaseHandle handle = typeInfo.CreateInstance();
+ DALI_TEST_CHECK(handle);
+
+ Scene3D::Material mateiral = Scene3D::Material::DownCast(handle);
+ DALI_TEST_CHECK(mateiral);
+
+ END_TEST;
+}
+
+int UtcDaliMaterialCopyAndAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::Material mateiral = Scene3D::Material::New();
+ DALI_TEST_CHECK(mateiral);
+
+ Scene3D::Material copy(mateiral);
+ DALI_TEST_CHECK(mateiral == copy);
+
+ Scene3D::Material assign;
+ DALI_TEST_CHECK(!assign);
+
+ assign = copy;
+ DALI_TEST_CHECK(assign == mateiral);
+
+ END_TEST;
+}
+
+int UtcDaliMaterialMoveConstructor(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::Material mateiral = Scene3D::Material::New();
+ DALI_TEST_EQUALS(1, mateiral.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+ Scene3D::Material moved = std::move(mateiral);
+ DALI_TEST_CHECK(moved);
+ DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+ DALI_TEST_CHECK(!mateiral);
+
+ END_TEST;
+}
+
+int UtcDaliMaterialMoveAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::Material mateiral = Scene3D::Material::New();
+ DALI_TEST_EQUALS(1, mateiral.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+ Scene3D::Material moved;
+ moved = std::move(mateiral);
+ DALI_TEST_CHECK(moved);
+ DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+ DALI_TEST_CHECK(!mateiral);
+
+ END_TEST;
+}
+
+// Method test
+int UtcDaliMaterialSetGetProperty(void)
+{
+ tet_infoline("UtcDaliMaterialSetGetProperty.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::Material material = Scene3D::Material::New();
+
+ std::string name = "name";
+ material.SetProperty(Scene3D::Material::Property::NAME, name);
+ DALI_TEST_EQUALS(name, material.GetProperty<std::string>(Scene3D::Material::Property::NAME), TEST_LOCATION);
+
+ std::string baseColorUrl = "baseColorUrl";
+ material.SetProperty(Scene3D::Material::Property::BASE_COLOR_URL, baseColorUrl);
+ DALI_TEST_EQUALS(baseColorUrl, material.GetProperty<std::string>(Scene3D::Material::Property::BASE_COLOR_URL), TEST_LOCATION);
+
+ Vector4 baseColorFactor(0.1f, 0.2f, 0.3f, 0.4f);
+ material.SetProperty(Scene3D::Material::Property::BASE_COLOR_FACTOR, baseColorFactor);
+ DALI_TEST_EQUALS(baseColorFactor, material.GetProperty<Vector4>(Scene3D::Material::Property::BASE_COLOR_FACTOR), TEST_LOCATION);
+
+ std::string metallicRoughnessUrl = "metallicRoughnessUrl";
+ material.SetProperty(Scene3D::Material::Property::METALLIC_ROUGHNESS_URL, metallicRoughnessUrl);
+ DALI_TEST_EQUALS(metallicRoughnessUrl, material.GetProperty<std::string>(Scene3D::Material::Property::METALLIC_ROUGHNESS_URL), TEST_LOCATION);
+
+ float metallicFactor = 0.5f;
+ material.SetProperty(Scene3D::Material::Property::METALLIC_FACTOR, metallicFactor);
+ DALI_TEST_EQUALS(metallicFactor, material.GetProperty<float>(Scene3D::Material::Property::METALLIC_FACTOR), TEST_LOCATION);
+
+ float roughnessFactor = 0.6f;
+ material.SetProperty(Scene3D::Material::Property::ROUGHNESS_FACTOR, roughnessFactor);
+ DALI_TEST_EQUALS(roughnessFactor, material.GetProperty<float>(Scene3D::Material::Property::ROUGHNESS_FACTOR), TEST_LOCATION);
+
+ std::string normalUrl = "normalUrl";
+ material.SetProperty(Scene3D::Material::Property::NORMAL_URL, normalUrl);
+ DALI_TEST_EQUALS(normalUrl, material.GetProperty<std::string>(Scene3D::Material::Property::NORMAL_URL), TEST_LOCATION);
+
+ float normalScale = 0.7f;
+ material.SetProperty(Scene3D::Material::Property::NORMAL_SCALE, normalScale);
+ DALI_TEST_EQUALS(normalScale, material.GetProperty<float>(Scene3D::Material::Property::NORMAL_SCALE), TEST_LOCATION);
+
+ std::string occlusionUrl = "occlusionUrl";
+ material.SetProperty(Scene3D::Material::Property::OCCLUSION_URL, occlusionUrl);
+ DALI_TEST_EQUALS(occlusionUrl, material.GetProperty<std::string>(Scene3D::Material::Property::OCCLUSION_URL), TEST_LOCATION);
+
+ float occlusionStrength = 0.8f;
+ material.SetProperty(Scene3D::Material::Property::OCCLUSION_STRENGTH, occlusionStrength);
+ DALI_TEST_EQUALS(occlusionStrength, material.GetProperty<float>(Scene3D::Material::Property::OCCLUSION_STRENGTH), TEST_LOCATION);
+
+ std::string emissiveUrl = "emissiveUrl";
+ material.SetProperty(Scene3D::Material::Property::EMISSIVE_URL, emissiveUrl);
+ DALI_TEST_EQUALS(emissiveUrl, material.GetProperty<std::string>(Scene3D::Material::Property::EMISSIVE_URL), TEST_LOCATION);
+
+ Vector3 emissiveFactor(0.9f, 0.1f, 0.2f);
+ material.SetProperty(Scene3D::Material::Property::EMISSIVE_FACTOR, emissiveFactor);
+ DALI_TEST_EQUALS(emissiveFactor, material.GetProperty<Vector3>(Scene3D::Material::Property::EMISSIVE_FACTOR), TEST_LOCATION);
+
+ int alphaMode = 1;
+ material.SetProperty(Scene3D::Material::Property::ALPHA_MODE, alphaMode);
+ DALI_TEST_EQUALS(alphaMode, material.GetProperty<int>(Scene3D::Material ::Property ::ALPHA_MODE), TEST_LOCATION);
+
+ float alphaCutoff = 0.9f;
+ material.SetProperty(Scene3D ::Material ::Property ::ALPHA_CUTOFF, alphaCutoff);
+ DALI_TEST_EQUALS(alphaCutoff, material.GetProperty<float>(Scene3D ::Material ::Property ::ALPHA_CUTOFF), TEST_LOCATION);
+
+ bool doubleSided = true;
+ material.SetProperty(Scene3D ::Material ::Property ::DOUBLE_SIDED, doubleSided);
+ DALI_TEST_EQUALS(doubleSided, material.GetProperty<bool>(Scene3D ::Material ::Property ::DOUBLE_SIDED), TEST_LOCATION);
+
+ float ior = 1.0f;
+ material.SetProperty(Scene3D::Material::Property::IOR, ior);
+ DALI_TEST_EQUALS(ior, material.GetProperty<float>(Scene3D::Material::Property::IOR), TEST_LOCATION);
+
+ std::string specularUrl = "specularUrl";
+ material.SetProperty(Scene3D::Material::Property::SPECULAR_URL, specularUrl);
+ DALI_TEST_EQUALS(specularUrl, material.GetProperty<std::string>(Scene3D::Material::Property::SPECULAR_URL), TEST_LOCATION);
+
+ float specularFactor = 1.0f;
+ material.SetProperty(Scene3D::Material::Property::SPECULAR_FACTOR, specularFactor);
+ DALI_TEST_EQUALS(specularFactor, material.GetProperty<float>(Scene3D::Material::Property::SPECULAR_FACTOR), TEST_LOCATION);
+
+ std::string specularColorUrl = "specularColorUrl";
+ material.SetProperty(Scene3D::Material::Property::SPECULAR_COLOR_URL, specularColorUrl);
+ DALI_TEST_EQUALS(specularColorUrl, material.GetProperty<std::string>(Scene3D::Material::Property::SPECULAR_COLOR_URL), TEST_LOCATION);
+
+ Vector3 specularColorFactor(1.0f, 1.0f, 1.0f);
+ material.SetProperty(Scene3D::Material::Property::SPECULAR_COLOR_FACTOR, specularColorFactor);
+ DALI_TEST_EQUALS(specularColorFactor, material.GetProperty<Vector3>(Scene3D::Material::Property::SPECULAR_COLOR_FACTOR), TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliMaterialSetGetTexture(void)
+{
+ tet_infoline("UtcDaliMaterialSetGetTexture.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::Material material = Scene3D::Material::New();
+
+ Dali::Texture baseColor = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ material.SetTexture(Scene3D::Material::TextureType::BASE_COLOR, baseColor);
+ DALI_TEST_EQUALS(baseColor, material.GetTexture(Scene3D::Material::TextureType::BASE_COLOR), TEST_LOCATION);
+
+ Dali::Texture metallicRoughness = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ material.SetTexture(Scene3D::Material::TextureType::METALLIC_ROUGHNESS, metallicRoughness);
+ DALI_TEST_EQUALS(metallicRoughness, material.GetTexture(Scene3D::Material::TextureType::METALLIC_ROUGHNESS), TEST_LOCATION);
+
+ Dali::Texture normal = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ material.SetTexture(Scene3D::Material::TextureType::NORMAL, normal);
+ DALI_TEST_EQUALS(normal, material.GetTexture(Scene3D::Material::TextureType::NORMAL), TEST_LOCATION);
+
+ Dali::Texture occlusion = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ material.SetTexture(Scene3D::Material::TextureType::OCCLUSION, occlusion);
+ DALI_TEST_EQUALS(occlusion, material.GetTexture(Scene3D::Material::TextureType::OCCLUSION), TEST_LOCATION);
+
+ Dali::Texture emissive = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ material.SetTexture(Scene3D::Material::TextureType::EMISSIVE, emissive);
+ DALI_TEST_EQUALS(emissive, material.GetTexture(Scene3D::Material::TextureType::EMISSIVE), TEST_LOCATION);
+
+ Dali::Texture specular = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ material.SetTexture(Scene3D::Material::TextureType::SPECULAR, specular);
+ DALI_TEST_EQUALS(specular, material.GetTexture(Scene3D::Material::TextureType::SPECULAR), TEST_LOCATION);
+
+ Dali::Texture specularColor = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100);
+ material.SetTexture(Scene3D::Material::TextureType::SPECULAR_COLOR, specularColor);
+ DALI_TEST_EQUALS(specularColor, material.GetTexture(Scene3D::Material::TextureType::SPECULAR_COLOR), TEST_LOCATION);
+
+ DALI_TEST_CHECK(!material.GetTexture((Scene3D::Material::TextureType)100));
+
+ END_TEST;
+}
+
+int UtcDaliMaterialSetGetSampler(void)
+{
+ tet_infoline("UtcDaliMaterialSetGetSampler.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::Material material = Scene3D::Material::New();
+
+ Dali::Sampler baseColor = Dali::Sampler::New();
+ material.SetSampler(Scene3D::Material::TextureType::BASE_COLOR, baseColor);
+ DALI_TEST_EQUALS(baseColor, material.GetSampler(Scene3D::Material::TextureType::BASE_COLOR), TEST_LOCATION);
+
+ Dali::Sampler metallicRoughness = Dali::Sampler::New();
+ material.SetSampler(Scene3D::Material::TextureType::METALLIC_ROUGHNESS, metallicRoughness);
+ DALI_TEST_EQUALS(metallicRoughness, material.GetSampler(Scene3D::Material::TextureType::METALLIC_ROUGHNESS), TEST_LOCATION);
+
+ Dali::Sampler normal = Dali::Sampler::New();
+ material.SetSampler(Scene3D::Material::TextureType::NORMAL, normal);
+ DALI_TEST_EQUALS(normal, material.GetSampler(Scene3D::Material::TextureType::NORMAL), TEST_LOCATION);
+
+ Dali::Sampler occlusion = Dali::Sampler::New();
+ material.SetSampler(Scene3D::Material::TextureType::OCCLUSION, occlusion);
+ DALI_TEST_EQUALS(occlusion, material.GetSampler(Scene3D::Material::TextureType::OCCLUSION), TEST_LOCATION);
+
+ Dali::Sampler emissive = Dali::Sampler::New();
+ material.SetSampler(Scene3D::Material::TextureType::EMISSIVE, emissive);
+ DALI_TEST_EQUALS(emissive, material.GetSampler(Scene3D::Material::TextureType::EMISSIVE), TEST_LOCATION);
+
+ Dali::Sampler specular = Dali::Sampler::New();
+ material.SetSampler(Scene3D::Material::TextureType::SPECULAR, specular);
+ DALI_TEST_EQUALS(specular, material.GetSampler(Scene3D::Material::TextureType::SPECULAR), TEST_LOCATION);
+
+ Dali::Sampler specularColor = Dali::Sampler::New();
+ material.SetSampler(Scene3D::Material::TextureType::SPECULAR_COLOR, specularColor);
+ DALI_TEST_EQUALS(specularColor, material.GetSampler(Scene3D::Material::TextureType::SPECULAR_COLOR), TEST_LOCATION);
+
+ DALI_TEST_CHECK(!material.GetSampler((Scene3D::Material::TextureType)100));
+
+ END_TEST;
+}
\ No newline at end of file
#include <toolkit-event-thread-callback.h>
#include <dali-scene3d/public-api/controls/model/model.h>
+#include <dali-scene3d/public-api/model-components/model-node.h>
#include <dali/devel-api/actors/camera-actor-devel.h>
const char* TEST_GLTF_ANIMATION_TEST_FILE_NAME = TEST_RESOURCE_DIR "/animationTest.gltf";
const char* TEST_GLTF_MULTIPLE_PRIMITIVE_FILE_NAME = TEST_RESOURCE_DIR "/simpleMultiplePrimitiveTest.gltf";
const char* TEST_DLI_FILE_NAME = TEST_RESOURCE_DIR "/arc.dli";
-// @TODO: The test cases for loading the DLI model below is temporarily disabled.
-// Need to fix how resources are loaded when a model contains multiple scenes and
-// each scene has its own root node.
-#ifdef MULTIPLE_SCENES_MODEL_SUPPORT
-const char* TEST_DLI_EXERCISE_FILE_NAME = TEST_RESOURCE_DIR "/exercise.dli";
-#endif
+const char* TEST_DLI_EXERCISE_FILE_NAME = TEST_RESOURCE_DIR "/exercise.dli";
+
/**
* For the diffuse and specular cube map texture.
* These textures are based off version of Wave engine sample
}
// Positive test case for a method
+int UtcDaliModelNewP2(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliModelNew without url");
+
+ Scene3D::Model model = Scene3D::Model::New();
+ DALI_TEST_CHECK(model);
+
+ application.GetScene().Add(model);
+
+ DALI_TEST_CHECK(model.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE));
+
+ application.GetScene().Remove(model);
+
+ DALI_TEST_CHECK(!model.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE));
+
+ END_TEST;
+}
+
+// Positive test case for a method
int UtcDaliModelDownCast(void)
{
ToolkitTestApplication application;
uint32_t modelCount = model.GetModelRoot().GetChildCount();
DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION);
- Actor rootActor = model.GetModelRoot();
- Vector3 rootSize = rootActor.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+ Scene3D::ModelNode rootNode = model.GetModelRoot();
+ Vector3 rootSize = rootNode.GetProperty<Vector3>(Dali::Actor::Property::SIZE);
DALI_TEST_EQUALS(Vector3(2, 2, 1), rootSize, TEST_LOCATION);
END_TEST;
naturalSize = model.GetNaturalSize();
DALI_TEST_EQUALS(Vector3(2, 2, 2), naturalSize, TEST_LOCATION);
- Actor root = model.GetModelRoot();
- DALI_TEST_CHECK(root);
+ Scene3D::ModelNode rootNode = model.GetModelRoot();
+ DALI_TEST_CHECK(rootNode);
END_TEST;
}
int UtcDaliModelAnimation03(void)
{
-#ifdef MULTIPLE_SCENES_MODEL_SUPPORT
ToolkitTestApplication application;
Scene3D::Model model = Scene3D::Model::New(TEST_DLI_EXERCISE_FILE_NAME);
Animation animationByName = model.GetAnimation("idleClip");
DALI_TEST_CHECK(animationByName);
DALI_TEST_EQUALS(animationByIndex, animationByName, TEST_LOCATION);
-#else
- tet_result(TET_PASS);
-#endif
END_TEST;
}
int UtcDaliModelCameraGenerate01(void)
{
-#ifdef MULTIPLE_SCENES_MODEL_SUPPORT
ToolkitTestApplication application;
Scene3D::Model model = Scene3D::Model::New(TEST_DLI_EXERCISE_FILE_NAME);
generatedCamera = model.GenerateCamera(1u); // Fail to generate camera
DALI_TEST_CHECK(!generatedCamera);
-#else
- tet_result(TET_PASS);
-#endif
END_TEST;
}
CameraActor appliedCamera;
DALI_TEST_EQUALS(model.ApplyCamera(0u, appliedCamera), false, TEST_LOCATION); // Cannot apply into empty camera.
- auto CompareCameraProperties = [](CameraActor lhs, CameraActor rhs, const char* location) {
+ auto CompareCameraProperties = [](CameraActor lhs, CameraActor rhs, const char* location)
+ {
DALI_TEST_EQUALS(lhs.GetProperty<int>(Dali::CameraActor::Property::PROJECTION_MODE), rhs.GetProperty<int>(Dali::CameraActor::Property::PROJECTION_MODE), TEST_LOCATION);
DALI_TEST_EQUALS(lhs.GetProperty<float>(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE), rhs.GetProperty<float>(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE), TEST_LOCATION);
{
DALI_TEST_EQUALS(lhs.GetProperty<float>(Dali::CameraActor::Property::FIELD_OF_VIEW), rhs.GetProperty<float>(Dali::CameraActor::Property::FIELD_OF_VIEW), TEST_LOCATION);
// TODO : Open this test when infinity far projection implement.
- //DALI_TEST_EQUALS(lhs.GetProperty<float>(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), rhs.GetProperty<float>(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), TEST_LOCATION);
+ // DALI_TEST_EQUALS(lhs.GetProperty<float>(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), rhs.GetProperty<float>(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), TEST_LOCATION);
}
else
{
DALI_TEST_EQUALS(textureSet2.GetTextureCount(), 9u, TEST_LOCATION);
DALI_TEST_EQUALS(textureSet3.GetTextureCount(), 9u, TEST_LOCATION);
- for (uint32_t i = 0; i < 7u; i++)
+ for(uint32_t i = 0; i < 7u; i++)
{
DALI_TEST_EQUALS(textureSet2.GetTexture(i), textureSet3.GetTexture(i), TEST_LOCATION);
}
END_TEST;
}
+int UtcDaliModelAddRemoveModelNode(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::Model model = Scene3D::Model::New();
+ model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
+
+ Scene3D::ModelNode node1 = Scene3D::ModelNode::New();
+ Scene3D::ModelNode node2 = Scene3D::ModelNode::New();
+ Scene3D::ModelNode node3 = Scene3D::ModelNode::New();
+ Scene3D::ModelNode node4 = Scene3D::ModelNode::New();
+
+ model.AddModelNode(node1);
+ model.AddModelNode(node2);
+ model.AddModelNode(node3);
+ model.RemoveModelNode(node1); // Remove node before scene on
+
+ application.GetScene().Add(model);
+
+ Dali::Scene3D::ModelNode root = model.GetModelRoot();
+ DALI_TEST_CHECK(root);
+ DALI_TEST_EQUALS(2, root.GetChildCount(), TEST_LOCATION);
+
+ model.RemoveModelNode(node2); // Remove node after scene on
+
+ DALI_TEST_EQUALS(1, root.GetChildCount(), TEST_LOCATION);
+
+ model.AddModelNode(node4); // Add during scene on
+
+ DALI_TEST_EQUALS(2, root.GetChildCount(), TEST_LOCATION);
+
+ application.GetScene().Remove(model);
+
+ model.RemoveModelNode(node3); // Remove node after scene off
+
+ END_TEST;
+}
+
+int UtcDaliModelFindChildModelNodeByName(void)
+{
+ tet_infoline(" UtcDaliModelNodeFindChildModelNodeByName.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::Model model = Scene3D::Model::New();
+ application.GetScene().Add(model);
+
+ Scene3D::ModelNode modelNode1 = Scene3D::ModelNode::New();
+ Scene3D::ModelNode modelNode2 = Scene3D::ModelNode::New();
+
+ modelNode1.SetProperty(Dali::Actor::Property::NAME, "modelNode1");
+ modelNode2.SetProperty(Dali::Actor::Property::NAME, "modelNode2");
+ model.AddModelNode(modelNode1);
+ model.AddModelNode(modelNode2);
+
+ Scene3D::ModelNode child1 = model.FindChildModelNodeByName("modelNode1");
+ DALI_TEST_CHECK(child1);
+ DALI_TEST_EQUALS(child1, modelNode1, TEST_LOCATION);
+
+ Scene3D::ModelNode child2 = model.FindChildModelNodeByName("modelNode2");
+ DALI_TEST_CHECK(child2);
+ DALI_TEST_EQUALS(child2, modelNode2, TEST_LOCATION);
+
+ END_TEST;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/public-api/model-components/model-node.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+void model_components_model_node_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void model_components_model_node_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+namespace
+{
+} // namespace
+
+// Negative test case for a method
+int UtcDaliModelNodeUninitialized(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliModelNodeUninitialized");
+
+ Scene3D::ModelNode modelNode;
+
+ try
+ {
+ // New() must be called to create a ModelNode or it wont be valid.
+ Actor a = Actor::New();
+ modelNode.Add(a);
+ DALI_TEST_CHECK(false);
+ }
+ catch(Dali::DaliException& e)
+ {
+ // Tests that a negative test of an assertion succeeds
+ DALI_TEST_PRINT_ASSERT(e);
+ DALI_TEST_CHECK(!modelNode);
+ }
+ END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliModelNodeNew(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliModelNodeNew");
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::New();
+ DALI_TEST_CHECK(modelNode);
+ END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliModelNodeDownCast(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliModelNodeDownCast");
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::New();
+ BaseHandle handle(modelNode);
+
+ Scene3D::ModelNode modelNode2 = Scene3D::ModelNode::DownCast(handle);
+ DALI_TEST_CHECK(modelNode);
+ DALI_TEST_CHECK(modelNode2);
+ DALI_TEST_CHECK(modelNode2 == modelNode);
+ END_TEST;
+}
+
+int UtcDaliModelNodeTypeRegistry(void)
+{
+ ToolkitTestApplication application;
+
+ TypeRegistry typeRegistry = TypeRegistry::Get();
+ DALI_TEST_CHECK(typeRegistry);
+
+ TypeInfo typeInfo = typeRegistry.GetTypeInfo("ModelNode");
+ DALI_TEST_CHECK(typeInfo);
+
+ BaseHandle handle = typeInfo.CreateInstance();
+ DALI_TEST_CHECK(handle);
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::DownCast(handle);
+ DALI_TEST_CHECK(modelNode);
+
+ END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliModelNodeAddRemove(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliModelAddRemove");
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::New();
+ DALI_TEST_CHECK(modelNode);
+
+ Actor actor = Actor::New();
+ DALI_TEST_CHECK(!actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE));
+
+ modelNode.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ modelNode.SetProperty(Actor::Property::SIZE, application.GetScene().GetSize());
+ modelNode.Add(actor);
+ application.GetScene().Add(modelNode);
+
+ DALI_TEST_CHECK(actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE));
+
+ modelNode.Remove(actor);
+
+ DALI_TEST_CHECK(!actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE));
+ END_TEST;
+}
+
+int UtcDaliModelNodeCopyAndAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::New();
+ DALI_TEST_CHECK(modelNode);
+
+ Scene3D::ModelNode copy(modelNode);
+ DALI_TEST_CHECK(modelNode == copy);
+
+ Scene3D::ModelNode assign;
+ DALI_TEST_CHECK(!assign);
+
+ assign = copy;
+ DALI_TEST_CHECK(assign == modelNode);
+
+ END_TEST;
+}
+
+int UtcDaliModelNodeMoveConstructor(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::New();
+ DALI_TEST_EQUALS(1, modelNode.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+ modelNode.SetProperty(Actor::Property::SENSITIVE, false);
+ DALI_TEST_CHECK(false == modelNode.GetProperty<bool>(Actor::Property::SENSITIVE));
+
+ Scene3D::ModelNode moved = std::move(modelNode);
+ DALI_TEST_CHECK(moved);
+ DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+ DALI_TEST_CHECK(false == moved.GetProperty<bool>(Actor::Property::SENSITIVE));
+ DALI_TEST_CHECK(!modelNode);
+
+ END_TEST;
+}
+
+int UtcDaliModelNodeMoveAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::New();
+ DALI_TEST_EQUALS(1, modelNode.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+ modelNode.SetProperty(Actor::Property::SENSITIVE, false);
+ DALI_TEST_CHECK(false == modelNode.GetProperty<bool>(Actor::Property::SENSITIVE));
+
+ Scene3D::ModelNode moved;
+ moved = std::move(modelNode);
+ DALI_TEST_CHECK(moved);
+ DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+ DALI_TEST_CHECK(false == moved.GetProperty<bool>(Actor::Property::SENSITIVE));
+ DALI_TEST_CHECK(!modelNode);
+
+ END_TEST;
+}
+
+int UtcDaliModelNodeOnSizeSet(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::New();
+
+ application.GetScene().Add(modelNode);
+
+ application.SendNotification();
+ application.Render();
+
+ Vector2 size(200.0f, 300.0f);
+ modelNode.SetProperty(Actor::Property::SIZE, size);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(modelNode.GetCurrentProperty<Vector2>(Actor::Property::SIZE), size, TEST_LOCATION);
+
+ END_TEST;
+}
+
+// Method test
+
+int UtcDaliModelNodeAddRemovePrimitive(void)
+{
+ tet_infoline(" UtcDaliModelNodeAddPrimitive.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::New();
+
+ uint32_t expect = 0u;
+
+ tet_printf("Test empty primitive case\n");
+
+ DALI_TEST_EQUALS(expect, modelNode.GetModelPrimitiveCount(), TEST_LOCATION);
+ DALI_TEST_CHECK(!modelNode.GetModelPrimitive(0u));
+ DALI_TEST_CHECK(!modelNode.GetModelPrimitive(1u));
+
+ Scene3D::ModelPrimitive primitive1 = Scene3D::ModelPrimitive::New();
+ Scene3D::ModelPrimitive primitive2 = Scene3D::ModelPrimitive::New();
+
+ Scene3D::Material material = Scene3D::Material::New();
+
+ primitive1.SetMaterial(material);
+ primitive2.SetMaterial(material);
+
+ tet_printf("Test primitive appended during off scene\n");
+
+ modelNode.AddModelPrimitive(primitive1);
+ ++expect;
+ DALI_TEST_EQUALS(expect, modelNode.GetModelPrimitiveCount(), TEST_LOCATION);
+ DALI_TEST_CHECK(primitive1 == modelNode.GetModelPrimitive(0u));
+ DALI_TEST_CHECK(!modelNode.GetModelPrimitive(1u));
+
+ tet_printf("Test primitive appended during on scene\n");
+
+ application.GetScene().Add(modelNode);
+
+ modelNode.AddModelPrimitive(primitive2);
+ ++expect;
+ DALI_TEST_EQUALS(expect, modelNode.GetModelPrimitiveCount(), TEST_LOCATION);
+ DALI_TEST_CHECK(primitive1 == modelNode.GetModelPrimitive(0u));
+ DALI_TEST_CHECK(primitive2 == modelNode.GetModelPrimitive(1u));
+
+ modelNode.RemoveModelPrimitive(primitive1);
+ DALI_TEST_CHECK(primitive2 == modelNode.GetModelPrimitive(0u));
+ DALI_TEST_CHECK(!modelNode.GetModelPrimitive(1u));
+
+ modelNode.RemoveModelPrimitive(0u);
+ DALI_TEST_CHECK(!modelNode.GetModelPrimitive(0u));
+ DALI_TEST_CHECK(!modelNode.GetModelPrimitive(1u));
+
+ modelNode.Unparent();
+
+ END_TEST;
+}
+
+int UtcDaliModelNodeFindChildModelNodeByName(void)
+{
+ tet_infoline(" UtcDaliModelNodeFindChildModelNodeByName.");
+
+ ToolkitTestApplication application;
+
+ Scene3D::ModelNode modelNode = Scene3D::ModelNode::New();
+ Scene3D::ModelNode modelNode1 = Scene3D::ModelNode::New();
+ Scene3D::ModelNode modelNode2 = Scene3D::ModelNode::New();
+
+ modelNode1.SetProperty(Dali::Actor::Property::NAME, "modelNode1");
+ modelNode2.SetProperty(Dali::Actor::Property::NAME, "modelNode2");
+ modelNode.Add(modelNode1);
+ modelNode.Add(modelNode2);
+
+ Scene3D::ModelNode child1 = modelNode.FindChildModelNodeByName("modelNode1");
+ DALI_TEST_CHECK(child1);
+ DALI_TEST_EQUALS(child1, modelNode1, TEST_LOCATION);
+
+ Scene3D::ModelNode child2 = modelNode.FindChildModelNodeByName("modelNode2");
+ DALI_TEST_CHECK(child2);
+ DALI_TEST_EQUALS(child2, modelNode2, TEST_LOCATION);
+
+ END_TEST;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <dali-scene3d/public-api/model-components/model-primitive.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+void model_components_model_primitive_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void model_components_model_primitive_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+namespace
+{
+} // namespace
+
+// Positive test case for a method
+int UtcDaliModelPrimitiveNew(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliModelPrimitiveNew");
+
+ Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+ DALI_TEST_CHECK(modelPrimitive);
+ END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliModelPrimitiveDownCast(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliModelPrimitiveDownCast");
+
+ Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+ BaseHandle handle(modelPrimitive);
+
+ Scene3D::ModelPrimitive modelPrimitive2 = Scene3D::ModelPrimitive::DownCast(handle);
+ DALI_TEST_CHECK(modelPrimitive);
+ DALI_TEST_CHECK(modelPrimitive2);
+ DALI_TEST_CHECK(modelPrimitive2 == modelPrimitive);
+ END_TEST;
+}
+
+int UtcDaliModelPrimitiveTypeRegistry(void)
+{
+ ToolkitTestApplication application;
+
+ TypeRegistry typeRegistry = TypeRegistry::Get();
+ DALI_TEST_CHECK(typeRegistry);
+
+ TypeInfo typeInfo = typeRegistry.GetTypeInfo("ModelPrimitive");
+ DALI_TEST_CHECK(typeInfo);
+
+ BaseHandle handle = typeInfo.CreateInstance();
+ DALI_TEST_CHECK(handle);
+
+ Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::DownCast(handle);
+ DALI_TEST_CHECK(modelPrimitive);
+
+ END_TEST;
+}
+
+int UtcDaliModelPrimitiveCopyAndAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+ DALI_TEST_CHECK(modelPrimitive);
+
+ Scene3D::ModelPrimitive copy(modelPrimitive);
+ DALI_TEST_CHECK(modelPrimitive == copy);
+
+ Scene3D::ModelPrimitive assign;
+ DALI_TEST_CHECK(!assign);
+
+ assign = copy;
+ DALI_TEST_CHECK(assign == modelPrimitive);
+
+ END_TEST;
+}
+
+int UtcDaliModelPrimitiveMoveConstructor(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+ DALI_TEST_EQUALS(1, modelPrimitive.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+ Scene3D::ModelPrimitive moved = std::move(modelPrimitive);
+ DALI_TEST_CHECK(moved);
+ DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+ DALI_TEST_CHECK(!modelPrimitive);
+
+ END_TEST;
+}
+
+int UtcDaliModelPrimitiveMoveAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+ DALI_TEST_EQUALS(1, modelPrimitive.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+ Scene3D::ModelPrimitive moved;
+ moved = std::move(modelPrimitive);
+ DALI_TEST_CHECK(moved);
+ DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+ END_TEST;
+}
+
+// Method test
+int UtcDaliModelPrimitiveSetGetGeometry(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+
+ tet_printf("Check primitive don't have renderer initial time\n");
+
+ DALI_TEST_CHECK(!modelPrimitive.GetGeometry());
+
+ Dali::Geometry geometry = Dali::Geometry::New();
+
+ modelPrimitive.SetGeometry(geometry);
+ DALI_TEST_CHECK(geometry == modelPrimitive.GetGeometry());
+
+ tet_printf("Replace as new Renderer\n");
+
+ Dali::Geometry geometry2 = Dali::Geometry::New();
+
+ modelPrimitive.SetGeometry(geometry2);
+ DALI_TEST_CHECK(geometry != modelPrimitive.GetGeometry());
+ DALI_TEST_CHECK(geometry2 == modelPrimitive.GetGeometry());
+ END_TEST;
+}
+
+int UtcDaliModelPrimitiveSetGetMaterial(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::ModelPrimitive modelPrimitive = Scene3D::ModelPrimitive::New();
+
+ tet_printf("Check primitive don't have material initial time\n");
+
+ DALI_TEST_CHECK(!modelPrimitive.GetMaterial());
+
+ Dali::Scene3D::Material material = Dali::Scene3D::Material::New();
+
+ modelPrimitive.SetMaterial(material);
+ DALI_TEST_CHECK(material == modelPrimitive.GetMaterial());
+
+ tet_printf("Replace as new Material\n");
+
+ Dali::Scene3D::Material material2 = Dali::Scene3D::Material::New();
+
+ modelPrimitive.SetMaterial(material2);
+ DALI_TEST_CHECK(material != modelPrimitive.GetMaterial());
+ DALI_TEST_CHECK(material2 == modelPrimitive.GetMaterial());
+
+ END_TEST;
+}
\ No newline at end of file
nodeDef.mExtras.push_back(NodeDefinition::Extra{"frobnicateFactor", frobnicateFactor});
Context ctx;
- auto actor = nodeDef.CreateActor(ctx.createParams);
+ auto actor = nodeDef.CreateModelNode(ctx.createParams);
DALI_TEST_EQUAL(nodeDef.mName, actor.GetProperty(Actor::Property::NAME).Get<std::string>());
DALI_TEST_EQUAL(nodeDef.mPosition, actor.GetProperty(Actor::Property::POSITION).Get<Vector3>());
DALI_TEST_EQUAL(nodeDef.mOrientation, actor.GetProperty(Actor::Property::ORIENTATION).Get<Quaternion>());
auto shader = Shader::New(VSH, FSH);
ctx.resources.mShaders.push_back({ShaderDefinition{}, shader});
- auto actor = nodeDef.CreateActor(ctx.createParams);
+ auto actor = nodeDef.CreateModelNode(ctx.createParams);
DALI_TEST_EQUAL(1, actor.GetRendererCount());
auto renderer = actor.GetRendererAt(0);
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
END_TEST;
}
-int UtcDaliImageConvertPixelDataToUrl(void)
+int UtcDaliImageConvertPixelDataToUrl01(void)
{
ToolkitTestApplication application;
- tet_infoline("UtcDaliImageConvertPixelDataToUrl");
+ tet_infoline("UtcDaliImageConvertPixelDataToUrl01");
unsigned int width(64);
unsigned int height(64);
END_TEST;
}
-int UtcDaliImageConvertNativeImageSourceToUrl(void)
+int UtcDaliImageConvertPixelDataToUrl02(void)
{
ToolkitTestApplication application;
- tet_infoline("UtcDaliImageConvertNativeImageSourceToUrl");
+ tet_infoline("UtcDaliImageConvertPixelDataToUrl02");
+
+ unsigned int width(64);
+ unsigned int height(64);
+ unsigned int bufferSize = width * height * Pixel::GetBytesPerPixel(Pixel::RGBA8888);
+
+ unsigned char* buffer = reinterpret_cast<unsigned char*>(malloc(bufferSize));
+ PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE);
+
+ DALI_TEST_CHECK(Dali::Toolkit::Image::GenerateUrl(pixelData, true).GetUrl().size() > 0u);
+
+ END_TEST;
+}
+
+int UtcDaliImageConvertNativeImageSourceToUrl01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliImageConvertNativeImageSourceToUrl01");
unsigned int width(64);
unsigned int height(64);
END_TEST;
}
+int UtcDaliImageConvertNativeImageSourceToUrl02(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliImageConvertNativeImageSourceToUrl02");
+
+ unsigned int width(64);
+ unsigned int height(64);
+ try
+ {
+ NativeImageSourcePtr nativeImageSource = NativeImageSource::New(width, height, NativeImageSource::COLOR_DEPTH_DEFAULT);
+
+ DALI_TEST_CHECK(Dali::Toolkit::Image::GenerateUrl(nativeImageSource, true).GetUrl().size() > 0u);
+ }
+ catch(Dali::DaliException& e)
+ {
+ DALI_TEST_PRINT_ASSERT(e);
+ DALI_TEST_ASSERT(e, "Adaptor::IsAvailable()", TEST_LOCATION);
+ }
+ catch(...)
+ {
+ tet_printf("Assertion test failed - wrong Exception\n");
+ tet_result(TET_FAIL);
+ }
+
+ END_TEST;
+}
+
int UtcDaliImageConvertEncodedImageBufferToUrl(void)
{
ToolkitTestApplication application;
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
using namespace Dali;
using namespace Dali::Toolkit;
-int UtcImageUrlConstructor(void)
+int UtcImageUrlConstructor01(void)
{
ToolkitTestApplication application;
DALI_TEST_CHECK(downcastUrl);
END_TEST;
}
+
+int UtcImageUrlConstructor02(void)
+{
+ ToolkitTestApplication application;
+
+ tet_infoline(" UtcImageUrlValid ");
+
+ // Test default constructor.
+ ImageUrl imageUrl;
+ DALI_TEST_CHECK(!imageUrl);
+
+ // Test object creation
+ Texture image = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 4u, 4u); // test texture
+ imageUrl = ImageUrl::New(image, true);
+ DALI_TEST_CHECK(imageUrl);
+
+ // Test copy constructor
+ ImageUrl ImageUrlCopy(imageUrl);
+ DALI_TEST_CHECK(ImageUrlCopy);
+
+ // Test down cast
+ BaseHandle baseUrl;
+ baseUrl = imageUrl;
+ ImageUrl downcastUrl = ImageUrl::DownCast(baseUrl);
+ DALI_TEST_CHECK(downcastUrl);
+ END_TEST;
+}
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
END_TEST;
}
+int UtcDaliImageVisualWithFrameBufferPreMultipliedAlpha01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("Use FrameBuffer as url");
+
+ uint32_t width(64);
+ uint32_t height(64);
+ FrameBuffer frameBuffer = Dali::FrameBuffer::New(width, height, FrameBuffer::Attachment::NONE);
+
+ DALI_TEST_CHECK(frameBuffer);
+ ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(frameBuffer, Pixel::Format::RGBA8888, width, height);
+ std::string url = imageUrl.GetUrl();
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, url);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(16);
+
+ Renderer renderer = actor.GetRendererAt(0);
+
+ // Check whether preMultipliedAlpha is true.
+ auto preMultipliedAlpha = renderer.GetProperty<bool>(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA);
+ DALI_TEST_EQUALS(preMultipliedAlpha, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliImageVisualWithFrameBufferPreMultipliedAlpha02(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("Use FrameBuffer as url");
+
+ uint32_t width(64);
+ uint32_t height(64);
+ FrameBuffer frameBuffer = Dali::FrameBuffer::New(width, height, FrameBuffer::Attachment::NONE);
+
+ DALI_TEST_CHECK(frameBuffer);
+
+ Texture texture = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+ frameBuffer.AttachColorTexture(texture);
+
+ ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(frameBuffer, 0u);
+ std::string url = imageUrl.GetUrl();
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, url);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(16);
+
+ Renderer renderer = actor.GetRendererAt(0);
+
+ // Check whether preMultipliedAlpha is true.
+ auto preMultipliedAlpha = renderer.GetProperty<bool>(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA);
+ DALI_TEST_EQUALS(preMultipliedAlpha, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliImageVisualWithPixelData(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("Use PixelData as url");
+
+ uint32_t width(64);
+ uint32_t height(64);
+ uint32_t bufferSize = width * height * Pixel::GetBytesPerPixel(Pixel::RGBA8888);
+
+ uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(bufferSize));
+ PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE);
+
+ DALI_TEST_CHECK(pixelData);
+
+ ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(pixelData);
+ std::string url = imageUrl.GetUrl();
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, url);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(16);
+
+ Renderer renderer = actor.GetRendererAt(0);
+
+ // Check whether preMultipliedAlpha is false.
+ auto preMultipliedAlpha = renderer.GetProperty<bool>(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA);
+ DALI_TEST_EQUALS(preMultipliedAlpha, false, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliImageVisualWithPixelDataPreMultipliedAlpha(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("Use PixelData as url");
+
+ uint32_t width(64);
+ uint32_t height(64);
+ uint32_t bufferSize = width * height * Pixel::GetBytesPerPixel(Pixel::RGBA8888);
+
+ uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(bufferSize));
+ PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE);
+
+ DALI_TEST_CHECK(pixelData);
+
+ ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(pixelData, true);
+ std::string url = imageUrl.GetUrl();
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, url);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(16);
+
+ Renderer renderer = actor.GetRendererAt(0);
+
+ // Check whether preMultipliedAlpha is true.
+ auto preMultipliedAlpha = renderer.GetProperty<bool>(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA);
+ DALI_TEST_EQUALS(preMultipliedAlpha, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliImageVisualWithNativeImage(void)
{
ToolkitTestApplication application;
DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+ application.SendNotification();
+ application.Render(16);
+
Renderer renderer = actor.GetRendererAt(0);
Shader shader = renderer.GetShader();
DALI_TEST_EQUALS(pos != std::string::npos, true, TEST_LOCATION);
+ // Check whether preMultipliedAlpha is false.
+ auto preMultipliedAlpha = renderer.GetProperty<bool>(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA);
+ DALI_TEST_EQUALS(preMultipliedAlpha, false, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliImageVisualWithNativeImagePreMultipliedAlpha(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("Use Native Image as url");
+
+ NativeImageSourcePtr nativeImageSource = NativeImageSource::New(500, 500, NativeImageSource::COLOR_DEPTH_DEFAULT);
+ ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(nativeImageSource, true);
+ std::string url = imageUrl.GetUrl();
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, url);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(16);
+
+ Renderer renderer = actor.GetRendererAt(0);
+ Shader shader = renderer.GetShader();
+
+ Property::Value value = shader.GetProperty(Shader::Property::PROGRAM);
+ DALI_TEST_CHECK(value.GetType() == Property::MAP);
+ const Property::Map* outMap = value.GetMap();
+ std::string fragmentShader = (*outMap)["fragment"].Get<std::string>();
+
+ const char* fragmentPrefix = Dali::NativeImageSourceTest::GetCustomFragmentPrefix();
+ size_t pos = fragmentShader.find(fragmentPrefix);
+
+ DALI_TEST_EQUALS(pos != std::string::npos, true, TEST_LOCATION);
+
+ // Check whether preMultipliedAlpha is true.
+ auto preMultipliedAlpha = renderer.GetProperty<bool>(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA);
+ DALI_TEST_EQUALS(preMultipliedAlpha, true, TEST_LOCATION);
+
END_TEST;
}
tet_infoline("Use Native Image as url and Use custom shader");
NativeImageSourcePtr nativeImageSource = NativeImageSource::New(500, 500, NativeImageSource::COLOR_DEPTH_DEFAULT);
- ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(nativeImageSource);
+ ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(nativeImageSource, true);
std::string url = imageUrl.GetUrl();
VisualFactory factory = VisualFactory::Get();
DALI_TEST_EQUALS(std::string(fragmentPrefix) + customFragmentShaderSource, fragmentShaderSource, TEST_LOCATION);
+ // Check whether preMultipliedAlpha is false.
+ // Note : We dont use preMultiplied alpha when app developer using custom shader.
+ auto preMultipliedAlpha = renderer.GetProperty<bool>(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA);
+ DALI_TEST_EQUALS(preMultipliedAlpha, false, TEST_LOCATION);
+
END_TEST;
}
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
std::string url2;
std::string url3;
std::string url4;
+ std::string url5;
+ std::string url6;
// scope to ensure texturesets are kept alive by texture manager
{
auto texture = Texture::New(Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, 88, 99);
DALI_TEST_CHECK(url4 != url);
DALI_TEST_CHECK(url4 != url2);
DALI_TEST_CHECK(url4 != url3);
+
+ // add same texture again with preMultiplied, should give new Url
+ url5 = TextureManager::AddTexture(texture, true);
+ DALI_TEST_CHECK(url5.size() > 0u);
+ DALI_TEST_CHECK(url5 != url);
+ DALI_TEST_CHECK(url5 != url2);
+ DALI_TEST_CHECK(url5 != url3);
+ DALI_TEST_CHECK(url5 != url4);
+
+ textureSet = TextureSet::New();
+ url6 = TextureManager::AddTexture(textureSet, true);
+ DALI_TEST_CHECK(url6.size() > 0u);
+ DALI_TEST_CHECK(url6 != url);
+ DALI_TEST_CHECK(url6 != url2);
+ DALI_TEST_CHECK(url6 != url3);
+ DALI_TEST_CHECK(url6 != url4);
+ DALI_TEST_CHECK(url6 != url5);
}
auto textureSet = TextureManager::RemoveTexture(url);
textureSet = TextureManager::RemoveTexture(url4);
DALI_TEST_CHECK(!textureSet && "Texture needs to be removed from texture manager");
+ textureSet = TextureManager::RemoveTexture(url5);
+ DALI_TEST_CHECK(textureSet && "Texture needs to be non empty handle");
+ textureSet = TextureManager::RemoveTexture(url5);
+ DALI_TEST_CHECK(!textureSet && "Texture needs to be removed from texture manager");
+
+ textureSet = TextureManager::RemoveTexture(url6);
+ DALI_TEST_CHECK(textureSet && "Texture needs to be non empty handle");
+ textureSet = TextureManager::RemoveTexture(url6);
+ DALI_TEST_CHECK(!textureSet && "Texture needs to be removed from texture manager");
+
END_TEST;
}
ModelCacheManager(const ModelCacheManager& rhs) = default;
ModelCacheManager(ModelCacheManager&& rhs) = default;
ModelCacheManager& operator=(const ModelCacheManager& rhs) = default;
- ModelCacheManager& operator=(ModelCacheManager&& rhs) = default;
+ ModelCacheManager& operator=(ModelCacheManager&& rhs) noexcept = default;
private:
class Impl;
// INTERNAL INCLUDES
#include <dali-scene3d/internal/common/model-cache-manager.h>
#include <dali-scene3d/internal/controls/scene-view/scene-view-impl.h>
+#include <dali-scene3d/internal/model-components/model-node-impl.h>
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/loader/animation-definition.h>
#include <dali-scene3d/public-api/loader/camera-parameters.h>
{
namespace
{
+/**
+ * Creates control through type registry
+ */
BaseHandle Create()
{
return Scene3D::Model::New(std::string());
DALI_TYPE_REGISTRATION_BEGIN(Scene3D::Model, Toolkit::Control, Create);
DALI_TYPE_REGISTRATION_END()
-static constexpr uint32_t OFFSET_FOR_DIFFUSE_CUBE_TEXTURE = 2u;
-static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u;
-
static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f);
static constexpr bool DEFAULT_MODEL_CHILDREN_SENSITIVE = false;
Model::~Model()
{
- if(ModelCacheManager::Get())
+ if(ModelCacheManager::Get() && !mModelUrl.empty())
{
ModelCacheManager::Get().UnreferenceModelCache(mModelUrl);
}
return handle;
}
-const Actor Model::GetModelRoot() const
+const Scene3D::ModelNode Model::GetModelRoot() const
{
return mModelRoot;
}
+void Model::AddModelNode(Scene3D::ModelNode modelNode)
+{
+ if(!mModelRoot)
+ {
+ CreateModelRoot();
+ }
+
+ mModelRoot.Add(modelNode);
+ if(mModelUrl.empty())
+ {
+ mModelResourceReady = true;
+ }
+
+ if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
+ {
+ UpdateImageBasedLightTexture();
+ UpdateImageBasedLightScaleFactor();
+ }
+
+ if(Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
+ {
+ NotifyResourceReady();
+ }
+}
+
+void Model::RemoveModelNode(Scene3D::ModelNode modelNode)
+{
+ if(mModelRoot)
+ {
+ mModelRoot.Remove(modelNode);
+ }
+}
+
void Model::SetChildrenSensitive(bool enable)
{
if(mModelChildrenSensitive != enable)
return false;
}
+Scene3D::ModelNode Model::FindChildModelNodeByName(std::string_view nodeName)
+{
+ Actor childActor = Self().FindChildByName(nodeName);
+ return Scene3D::ModelNode::DownCast(childActor);
+}
+
///////////////////////////////////////////////////////////
//
// Private methods
void Model::OnSceneConnection(int depth)
{
- if(!mModelLoadTask && !mModelRoot)
+ if(!mModelLoadTask && !mModelResourceReady && !mModelUrl.empty())
{
+ // Request model load only if we setup url.
if(ModelCacheManager::Get())
{
ModelCacheManager::Get().ReferenceModelCache(mModelUrl);
mModelLoadTask = new ModelLoadTask(mModelUrl, mResourceDirectoryUrl, MakeCallback(this, &Model::OnModelLoadComplete));
Dali::AsyncTaskManager::Get().AddTask(mModelLoadTask);
}
+
// If diffuse and specular url is not valid, IBL does not need to be loaded.
if(!mDiffuseIblUrl.empty() && !mSpecularIblUrl.empty())
{
parent = parent.GetParent();
}
+ NotifyResourceReady();
Control::OnSceneConnection(depth);
}
return mModelResourceReady && mIblDiffuseResourceReady && mIblSpecularResourceReady;
}
+void Model::CreateModelRoot()
+{
+ mModelRoot = Scene3D::ModelNode::New();
+ mModelRoot.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
+ mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION);
+ mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
+ mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
+ mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
+ Self().Add(mModelRoot);
+}
+
void Model::ScaleModel()
{
if(!mModelRoot)
mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
}
-void Model::CollectRenderableActor(Actor actor)
+void Model::UpdateImageBasedLightTextureRecursively(Scene3D::ModelNode node, Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
+{
+ if(!node)
+ {
+ return;
+ }
+
+ GetImplementation(node).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
+ uint32_t childrenCount = node.GetChildCount();
+ for(uint32_t i = 0; i < childrenCount; ++i)
+ {
+ Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
+ if(!childNode)
+ {
+ continue;
+ }
+ UpdateImageBasedLightTextureRecursively(childNode, diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
+ }
+}
+
+void Model::UpdateImageBasedLightScaleFactorRecursively(Scene3D::ModelNode node, float iblScaleFactor)
{
- uint32_t rendererCount = actor.GetRendererCount();
- if(rendererCount)
+ if(!node)
{
- mRenderableActors.push_back(actor);
+ return;
}
- uint32_t childrenCount = actor.GetChildCount();
+ node.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), iblScaleFactor);
+ GetImplementation(node).SetImageBasedLightScaleFactor(iblScaleFactor);
+
+ uint32_t childrenCount = node.GetChildCount();
for(uint32_t i = 0; i < childrenCount; ++i)
{
- CollectRenderableActor(actor.GetChildAt(i));
+ Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
+ if(!childNode)
+ {
+ continue;
+ }
+ UpdateImageBasedLightScaleFactorRecursively(childNode, iblScaleFactor);
}
}
currentIblSpecularMipmapLevels = 1u;
}
- for(auto&& actor : mRenderableActors)
- {
- Actor renderableActor = actor.GetHandle();
- if(!renderableActor)
- {
- continue;
- }
-
- uint32_t rendererCount = renderableActor.GetRendererCount();
- for(uint32_t i = 0; i < rendererCount; ++i)
- {
- Dali::Renderer renderer = renderableActor.GetRendererAt(i);
- if(!renderer)
- {
- continue;
- }
- Dali::TextureSet textures = renderer.GetTextures();
- if(!textures)
- {
- continue;
- }
- uint32_t textureCount = textures.GetTextureCount();
- // EnvMap requires at least 2 texture, diffuse and specular
- if(textureCount > 2u &&
- (textures.GetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE) != currentDiffuseTexture ||
- textures.GetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE) != currentSpecularTexture))
- {
- Dali::TextureSet newTextures = Dali::TextureSet::New();
-
- for(uint32_t index = 0u; index < textureCount; ++index)
- {
- Dali::Texture texture = textures.GetTexture(index);
- if(index == textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE)
- {
- texture = currentDiffuseTexture;
- }
- else if(index == textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE)
- {
- texture = currentSpecularTexture;
- }
-
- newTextures.SetTexture(index, texture);
- newTextures.SetSampler(index, textures.GetSampler(index));
- }
-
- renderer.SetTextures(newTextures);
- }
- }
- renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
- renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), static_cast<float>(currentIblSpecularMipmapLevels));
- }
+ UpdateImageBasedLightTextureRecursively(mModelRoot, currentDiffuseTexture, currentSpecularTexture, currentIblScaleFactor, currentIblSpecularMipmapLevels);
}
void Model::UpdateImageBasedLightScaleFactor()
}
float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
- for(auto&& actor : mRenderableActors)
- {
- Actor renderableActor = actor.GetHandle();
- if(renderableActor)
- {
- renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
- }
- }
+ UpdateImageBasedLightScaleFactorRecursively(mModelRoot, currentIblScaleFactor);
}
void Model::ApplyCameraTransform(Dali::CameraActor camera) const
{
ResetResourceTasks();
- if(ModelCacheManager::Get())
+ if(ModelCacheManager::Get() && !mModelUrl.empty())
{
ModelCacheManager::Get().UnreferenceModelCache(mModelUrl);
}
return;
}
+ if(!mModelRoot)
+ {
+ CreateModelRoot();
+ }
CreateModel();
- mRenderableActors.clear();
- CollectRenderableActor(mModelRoot);
auto& resources = mModelLoadTask->GetResources();
auto& scene = mModelLoadTask->GetScene();
UpdateImageBasedLightTexture();
UpdateImageBasedLightScaleFactor();
-
- mModelRoot.SetProperty(Dali::Actor::Property::SENSITIVE, mModelChildrenSensitive);
- mModelRoot.SetProperty(Dali::Actor::Property::KEYBOARD_FOCUSABLE, mModelChildrenFocusable);
- mModelRoot.SetProperty(Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN, mModelChildrenFocusable);
-
- Self().Add(mModelRoot);
Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
mModelResourceReady = true;
void Model::CreateModel()
{
- mModelRoot = Actor::New();
- mModelRoot.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
-
BoundingVolume AABB;
- auto& resources = mModelLoadTask->GetResources();
- auto& scene = mModelLoadTask->GetScene();
- auto& resourceChoices = mModelLoadTask->GetResourceChoices();
+ auto& resources = mModelLoadTask->GetResources();
+ auto& scene = mModelLoadTask->GetScene();
+ auto& resourceChoices = mModelLoadTask->GetResourceChoices();
Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}};
for(auto&& animation : mModelLoadTask->GetAnimations())
{
Dali::Animation anim = animation.ReAnimate(getActor);
- mAnimations.push_back({animation.mName, anim});
+ mAnimations.push_back({animation.GetName(), anim});
}
}
}
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
#include <dali-scene3d/public-api/loader/load-result.h>
+#include <dali-scene3d/public-api/model-components/model-node.h>
namespace Dali
{
/**
* @copydoc Model::GetModelRoot()
*/
- const Actor GetModelRoot() const;
+ const Scene3D::ModelNode GetModelRoot() const;
+
+ /**
+ * @copydoc Model::AddModelNode()
+ */
+ void AddModelNode(Scene3D::ModelNode modelNode);
+
+ /**
+ * @copydoc Model::RemoveModelNode()
+ */
+ void RemoveModelNode(Scene3D::ModelNode modelNode);
/**
* @copydoc Model::SetChildrenSensitive()
*/
bool ApplyCamera(uint32_t index, Dali::CameraActor camera) const;
+ /**
+ * @copydoc Model::FindChildModelNodeByName()
+ */
+ Scene3D::ModelNode FindChildModelNodeByName(std::string_view nodeName);
+
protected:
/**
* @brief Constructs a new Model.
private:
/**
+ * @brief Create Model Root of this Model class.
+ */
+ void CreateModelRoot();
+
+ /**
* @brief Scales the model to fit the control or to return to original size.
*/
void ScaleModel();
/**
* @brief Changes IBL information of the input node.
*/
- void CollectRenderableActor(Actor actor);
+ void UpdateImageBasedLightTextureRecursively(Scene3D::ModelNode node, Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels);
+
+ /**
+ * @brief Changes IBL factor of the input node.
+ */
+ void UpdateImageBasedLightScaleFactorRecursively(Scene3D::ModelNode node, float iblScaleFactor);
/**
* @brief Changes IBL textures of the input node.
void ResetCameraParameters();
private:
- std::string mModelUrl;
- std::string mResourceDirectoryUrl;
- Dali::Actor mModelRoot;
- std::vector<AnimationData> mAnimations;
- std::vector<CameraData> mCameraParameters;
- std::vector<WeakHandle<Actor>> mRenderableActors;
- WeakHandle<Scene3D::SceneView> mParentSceneView;
+ std::string mModelUrl;
+ std::string mResourceDirectoryUrl;
+ Scene3D::ModelNode mModelRoot;
+ std::vector<AnimationData> mAnimations;
+ std::vector<CameraData> mCameraParameters;
+ WeakHandle<Scene3D::SceneView> mParentSceneView;
// Asynchronous loading variable
ModelLoadTaskPtr mModelLoadTask;
std::string mDiffuseIblUrl;
std::string mSpecularIblUrl;
- // TODO: This default texture can be removed after 3D Resource Cache is added.
Dali::Texture mDefaultSpecularTexture;
Dali::Texture mDefaultDiffuseTexture;
Dali::Texture mSceneSpecularTexture;
Property::Map imagePropertyMap;
imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, imageUrl.GetUrl());
- // To make sure this visual call LoadTexture API immediate.
- imagePropertyMap.Insert(Toolkit::ImageVisual::Property::LOAD_POLICY, Toolkit::ImageVisual::LoadPolicy::IMMEDIATE);
- imagePropertyMap.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, Toolkit::ImageVisual::ReleasePolicy::DESTROYED);
// To flip rendered scene without CameraActor::SetInvertYAxis() to avoid backface culling.
imagePropertyMap.Insert(Toolkit::ImageVisual::Property::PIXEL_AREA, Vector4(0.0f, 1.0f, 1.0f, -1.0f));
mVisual = Toolkit::VisualFactory::Get().CreateVisual(imagePropertyMap);
- // Use premultiplied alpha when we use FBO
- if(mVisual)
- {
- Toolkit::GetImplementation(mVisual).EnablePreMultipliedAlpha(true);
- }
-
Toolkit::DevelControl::RegisterVisual(*this, RENDERING_BUFFER, mVisual);
mRenderTask.SetFrameBuffer(mFrameBuffer);
${scene3d_internal_dir}/loader/hash.cpp
${scene3d_internal_dir}/loader/json-reader.cpp
${scene3d_internal_dir}/loader/json-util.cpp
+ ${scene3d_internal_dir}/model-components/material-impl.cpp
+ ${scene3d_internal_dir}/model-components/model-node-data-impl.cpp
+ ${scene3d_internal_dir}/model-components/model-node-impl.cpp
+ ${scene3d_internal_dir}/model-components/model-primitive-impl.cpp
)
// TODO: Multiple texture coordinate will be supported.
in mediump vec2 vUV;
in lowp mat3 vTBN;
-#ifdef COLOR_ATTRIBUTE
in lowp vec4 vColor;
-#endif
in highp vec3 vPositionToCamera;
out vec4 FragColor;
lowp vec4 baseColor = texture(sAlbedoAlpha, vUV);
baseColor = vec4(linear(baseColor.rgb), baseColor.w) * uColorFactor;
#else // BASECOLOR_TEX
-#ifdef COLOR_ATTRIBUTE
lowp vec4 baseColor = vColor * uColorFactor;
-#else // COLOR_ATTRIBUTE
- lowp vec4 baseColor = uColorFactor;
-#endif // COLOR_ATTRIBUTE
#endif // BASECOLOR_TEX
#ifdef METALLIC_ROUGHNESS_TEX
#endif // NORMAL_TEX
#else // THREE_TEX
vec4 albedoMetal = texture(sAlbedoMetal, vUV);
-#ifdef COLOR_ATTRIBUTE
lowp vec4 baseColor = vec4(linear(albedoMetal.rgb), 1.0) * vColor * uColorFactor;
-#else // COLOR_ATTRIBUTE
- lowp vec4 baseColor = vec4(linear(albedoMetal.rgb), 1.0) * uColorFactor;
-#endif // COLOR_ATTRIBUTE
metallic = albedoMetal.METALLIC * metallic;
in vec3 aTangent;
#endif
-#ifdef COLOR_ATTRIBUTE
in vec4 aVertexColor;
-uniform lowp float uHasVertexColor;
-#endif
#ifdef MORPH
uniform highp sampler2D sBlendShapeGeometry;
out mediump vec2 vUV;
out lowp mat3 vTBN;
-#ifdef COLOR_ATTRIBUTE
out lowp vec4 vColor;
-#endif
out highp vec3 vPositionToCamera;
uniform highp mat4 uViewMatrix;
vUV = aTexCoord;
#endif
-#ifdef COLOR_ATTRIBUTE
- vColor = mix(vec4(1.0f), aVertexColor, uHasVertexColor);
-#endif
+ vColor = aVertexColor;
gl_Position = uProjection * positionV;
}
namespace
{
-const std::string NODES = "nodes";
-const std::string SCENES = "scenes";
-const std::string NODE = "node";
-const std::string URI = "uri";
-const std::string URL = "url";
-const std::string CUSTOMIZATION = "customization";
-const std::string HINTS = "hints";
-const std::string NAME("name");
-const std::string BLEND_SHAPE_HEADER("blendShapeHeader");
-const std::string BLEND_SHAPES("blendShapes");
-const std::string BLEND_SHAPE_VERSION_1_0("1.0");
-const std::string BLEND_SHAPE_VERSION_2_0("2.0");
-const std::string VERSION("version");
+const char* NODES = "nodes";
+const char* SCENES = "scenes";
+const char* NODE = "node";
+const char* URI = "uri";
+const char* URL = "url";
+const char* HINTS = "hints";
+const char* NAME("name");
+const char* BLEND_SHAPE_HEADER("blendShapeHeader");
+const char* BLEND_SHAPES("blendShapes");
+const char* BLEND_SHAPE_VERSION_1_0("1.0");
+const char* BLEND_SHAPE_VERSION_2_0("2.0");
+const char* VERSION("version");
const char* const SHADOW_MAP_SIZE = "shadowMapSize";
const char* const ORTHOGRAPHIC_SIZE = "orthographicSize";
++iAnim)
{
const TreeNode& tnAnim = (*iAnim).second;
+ uint32_t animationPropertyIndex = 0;
AnimationDefinition animDef;
- ReadString(tnAnim.GetChild(NAME), animDef.mName);
+ std::string animationName;
+ ReadString(tnAnim.GetChild(NAME), animationName);
+ animDef.SetName(animationName);
- auto iFind = std::lower_bound(definitions.begin(), definitions.end(), animDef, [](const AnimationDefinition& ad0, const AnimationDefinition& ad1) { return ad0.mName < ad1.mName; });
- const bool overwrite = iFind != definitions.end() && iFind->mName == animDef.mName;
+ auto iFind = std::lower_bound(definitions.begin(), definitions.end(), animDef, [](const AnimationDefinition& ad0, const AnimationDefinition& ad1) { return ad0.GetName() < ad1.GetName(); });
+ const bool overwrite = iFind != definitions.end() && iFind->GetName() == animDef.GetName();
if(overwrite)
{
- mOnError(FormatString("Pre-existing animation with name '%s' is being overwritten.", animDef.mName.c_str()));
+ mOnError(FormatString("Pre-existing animation with name '%s' is being overwritten.", animDef.GetName().c_str()));
}
// Duration -- We need something that animated properties' delay / duration can
// be expressed as a multiple of; 0 won't work. This is small enough (i.e. shorter
// than our frame delay) to not be restrictive WRT replaying. If anything needs
// to occur more frequently, then Animations are likely not your solution anyway.
- animDef.mDuration = AnimationDefinition::MIN_DURATION_SECONDS;
- if(!ReadFloat(tnAnim.GetChild("duration"), animDef.mDuration))
+ animDef.SetDuration(AnimationDefinition::MIN_DURATION_SECONDS);
+ float animationDuration;
+ if(!ReadFloat(tnAnim.GetChild("duration"), animationDuration))
{
+ animDef.SetDuration(animationDuration);
mOnError(FormatString("Animation '%s' fails to define '%s', defaulting to %f.",
- animDef.mName.c_str(),
+ animDef.GetName().c_str(),
"duration",
- animDef.mDuration));
+ animDef.GetDuration()));
}
// Get loop count - # of playbacks. Default is once. 0 means repeat indefinitely.
- animDef.mLoopCount = 1;
- if(ReadInt(tnAnim.GetChild("loopCount"), animDef.mLoopCount) &&
- animDef.mLoopCount < 0)
+ int32_t animationLoopCount = 1;
+ if(ReadInt(tnAnim.GetChild("loopCount"), animationLoopCount) && animationLoopCount < 0)
{
- animDef.mLoopCount = 0;
+ animationLoopCount = 0;
}
+ animDef.SetLoopCount(animationLoopCount);
std::string endAction;
if(ReadString(tnAnim.GetChild("endAction"), endAction))
{
if("BAKE" == endAction)
{
- animDef.mEndAction = Animation::BAKE;
+ animDef.SetEndAction(Animation::BAKE);
}
else if("DISCARD" == endAction)
{
- animDef.mEndAction = Animation::DISCARD;
+ animDef.SetEndAction(Animation::DISCARD);
}
else if("BAKE_FINAL" == endAction)
{
- animDef.mEndAction = Animation::BAKE_FINAL;
+ animDef.SetEndAction(Animation::BAKE_FINAL);
}
}
{
if("BAKE" == endAction)
{
- animDef.mDisconnectAction = Animation::BAKE;
+ animDef.SetDisconnectAction(Animation::BAKE);
}
else if("DISCARD" == endAction)
{
- animDef.mDisconnectAction = Animation::DISCARD;
+ animDef.SetDisconnectAction(Animation::DISCARD);
}
else if("BAKE_FINAL" == endAction)
{
- animDef.mDisconnectAction = Animation::BAKE_FINAL;
+ animDef.SetDisconnectAction(Animation::BAKE_FINAL);
}
}
if(const TreeNode* tnProperties = tnAnim.GetChild("properties"))
{
- animDef.mProperties.reserve(tnProperties->Size());
+ animDef.ReserveSize(tnProperties->Size());
for(TreeNode::ConstIterator iProperty = tnProperties->CBegin(), iPropertyEnd = tnProperties->CEnd();
iProperty != iPropertyEnd;
++iProperty)
AnimatedProperty animProp;
if(!ReadString(tnProperty.GetChild("node"), animProp.mNodeName))
{
- mOnError(FormatString("Animation '%s': Failed to read the 'node' tag.", animDef.mName.c_str()));
+ mOnError(FormatString("Animation '%s': Failed to read the 'node' tag.", animDef.GetName().c_str()));
continue;
}
if(!ReadString(tnProperty.GetChild("property"), animProp.mPropertyName))
{
- mOnError(FormatString("Animation '%s': Failed to read the 'property' tag", animDef.mName.c_str()));
+ mOnError(FormatString("Animation '%s': Failed to read the 'property' tag", animDef.GetName().c_str()));
continue;
}
// these are the defaults
animProp.mTimePeriod.delaySeconds = 0.f;
- animProp.mTimePeriod.durationSeconds = animDef.mDuration;
+ animProp.mTimePeriod.durationSeconds = animDef.GetDuration();
if(!ReadTimePeriod(tnProperty.GetChild("timePeriod"), animProp.mTimePeriod))
{
mOnError(FormatString("Animation '%s': timePeriod missing in Property #%d: defaulting to %f.",
- animDef.mName.c_str(),
- animDef.mProperties.size(),
+ animDef.GetName().c_str(),
+ animDef.GetPropertyCount(),
animProp.mTimePeriod.durationSeconds));
}
}
}
- animDef.mProperties.push_back(std::move(animProp));
+ animDef.SetProperty(animationPropertyIndex++, std::move(animProp));
}
}
+ if(auto proc = params.input->mAnimationPropertyProcessor) // optional processing
+ {
+ Property::Map map;
+ ParseProperties(tnAnim, map);
+ proc(animDef, std::move(map), mOnError);
+ }
+
if(overwrite)
{
*iFind = std::move(animDef);
{
iFind = definitions.insert(iFind, std::move(animDef));
}
-
- if(auto proc = params.input->mAnimationPropertyProcessor) // optional processing
- {
- Property::Map map;
- ParseProperties(tnAnim, map);
- proc(animDef, std::move(map), mOnError);
- }
}
}
/*
-* Copyright (c) 2022 Samsung Electronics Co., Ltd.
+* Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
static_cast<uint32_t>(-1),
};
-const std::map<std::string_view, AccessorType::Type> ACCESSOR_TYPES{
- ENUM_STRING_MAPPING(AccessorType, SCALAR),
- ENUM_STRING_MAPPING(AccessorType, VEC2),
- ENUM_STRING_MAPPING(AccessorType, VEC3),
- ENUM_STRING_MAPPING(AccessorType, VEC4),
- ENUM_STRING_MAPPING(AccessorType, MAT2),
- ENUM_STRING_MAPPING(AccessorType, MAT3),
- ENUM_STRING_MAPPING(AccessorType, MAT4),
-};
+const std::map<std::string_view, AccessorType::Type>& GetAccessorTypes()
+{
+ static const std::map<std::string_view, AccessorType::Type> ACCESSOR_TYPES{
+ ENUM_STRING_MAPPING(AccessorType, SCALAR),
+ ENUM_STRING_MAPPING(AccessorType, VEC2),
+ ENUM_STRING_MAPPING(AccessorType, VEC3),
+ ENUM_STRING_MAPPING(AccessorType, VEC4),
+ ENUM_STRING_MAPPING(AccessorType, MAT2),
+ ENUM_STRING_MAPPING(AccessorType, MAT3),
+ ENUM_STRING_MAPPING(AccessorType, MAT4),
+ };
+ return ACCESSOR_TYPES;
+}
-const std::map<std::string_view, AlphaMode::Type> ALPHA_MODE_TYPES{
- ENUM_STRING_MAPPING(AlphaMode::Type, OPAQUE),
- ENUM_STRING_MAPPING(AlphaMode::Type, MASK),
- ENUM_STRING_MAPPING(AlphaMode::Type, BLEND),
-};
+const std::map<std::string_view, AlphaMode::Type>& GetAlphaModeTypes()
+{
+ static const std::map<std::string_view, AlphaMode::Type> ALPHA_MODE_TYPES{
+ ENUM_STRING_MAPPING(AlphaMode::Type, OPAQUE),
+ ENUM_STRING_MAPPING(AlphaMode::Type, MASK),
+ ENUM_STRING_MAPPING(AlphaMode::Type, BLEND),
+ };
+ return ALPHA_MODE_TYPES;
+}
-const std::map<std::string_view, Attribute::Type> ATTRIBUTE_TYPES{
- ENUM_STRING_MAPPING(Attribute::Type, POSITION),
- ENUM_STRING_MAPPING(Attribute::Type, NORMAL),
- ENUM_STRING_MAPPING(Attribute::Type, TANGENT),
- ENUM_STRING_MAPPING(Attribute::Type, TEXCOORD_0),
- ENUM_STRING_MAPPING(Attribute::Type, TEXCOORD_1),
- ENUM_STRING_MAPPING(Attribute::Type, COLOR_0),
- ENUM_STRING_MAPPING(Attribute::Type, JOINTS_0),
- ENUM_STRING_MAPPING(Attribute::Type, WEIGHTS_0),
-};
+const std::map<std::string_view, Attribute::Type>& GetAttributeTypes()
+{
+ static const std::map<std::string_view, Attribute::Type> ATTRIBUTE_TYPES{
+ ENUM_STRING_MAPPING(Attribute::Type, POSITION),
+ ENUM_STRING_MAPPING(Attribute::Type, NORMAL),
+ ENUM_STRING_MAPPING(Attribute::Type, TANGENT),
+ ENUM_STRING_MAPPING(Attribute::Type, TEXCOORD_0),
+ ENUM_STRING_MAPPING(Attribute::Type, TEXCOORD_1),
+ ENUM_STRING_MAPPING(Attribute::Type, COLOR_0),
+ ENUM_STRING_MAPPING(Attribute::Type, JOINTS_0),
+ ENUM_STRING_MAPPING(Attribute::Type, WEIGHTS_0),
+ };
+ return ATTRIBUTE_TYPES;
+}
-const std::map<std::string_view, Animation::Sampler::Interpolation::Type> ANIMATION_SAMPLER_INTERPOLATION{
- ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, STEP),
- ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, LINEAR),
- ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, CUBICSPLINE),
-};
+const std::map<std::string_view, Animation::Sampler::Interpolation::Type>& GetAnimationSamplerInterpolation()
+{
+ static const std::map<std::string_view, Animation::Sampler::Interpolation::Type> ANIMATION_SAMPLER_INTERPOLATION{
+ ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, STEP),
+ ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, LINEAR),
+ ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, CUBICSPLINE),
+ };
+ return ANIMATION_SAMPLER_INTERPOLATION;
+}
-const std::map<std::string_view, Animation::Channel::Target::Type> ANIMATION_CHANNEL_TARGET_PATH_TYPES{
- ENUM_STRING_MAPPING(Animation::Channel::Target::Type, TRANSLATION),
- ENUM_STRING_MAPPING(Animation::Channel::Target::Type, ROTATION),
- ENUM_STRING_MAPPING(Animation::Channel::Target::Type, SCALE),
- ENUM_STRING_MAPPING(Animation::Channel::Target::Type, WEIGHTS),
-};
+const std::map<std::string_view, Animation::Channel::Target::Type>& GetAnimationChannelTargetPathTypes()
+{
+ static const std::map<std::string_view, Animation::Channel::Target::Type> ANIMATION_CHANNEL_TARGET_PATH_TYPES{
+ ENUM_STRING_MAPPING(Animation::Channel::Target::Type, TRANSLATION),
+ ENUM_STRING_MAPPING(Animation::Channel::Target::Type, ROTATION),
+ ENUM_STRING_MAPPING(Animation::Channel::Target::Type, SCALE),
+ ENUM_STRING_MAPPING(Animation::Channel::Target::Type, WEIGHTS),
+ };
+ return ANIMATION_CHANNEL_TARGET_PATH_TYPES;
+}
} // namespace
-ENUM_TYPE_FROM_STRING(AccessorType, ACCESSOR_TYPES)
-ENUM_TYPE_FROM_STRING(AlphaMode, ALPHA_MODE_TYPES)
-ENUM_TYPE_FROM_STRING(Attribute, ATTRIBUTE_TYPES)
-ENUM_TYPE_FROM_STRING(Animation::Sampler::Interpolation, ANIMATION_SAMPLER_INTERPOLATION)
-ENUM_TYPE_FROM_STRING(Animation::Channel::Target, ANIMATION_CHANNEL_TARGET_PATH_TYPES)
+ENUM_TYPE_FROM_STRING(AccessorType, GetAccessorTypes())
+ENUM_TYPE_FROM_STRING(AlphaMode, GetAlphaModeTypes())
+ENUM_TYPE_FROM_STRING(Attribute, GetAttributeTypes())
+ENUM_TYPE_FROM_STRING(Animation::Sampler::Interpolation, GetAnimationSamplerInterpolation())
+ENUM_TYPE_FROM_STRING(Animation::Channel::Target, GetAnimationChannelTargetPathTypes())
bool Component::IsUnsigned(Type t)
{
#include <dali-scene3d/internal/loader/gltf2-util.h>
// EXTERNAL INCLUDES
+#include <dali/devel-api/threading/mutex.h>
#include <dali/integration-api/debug.h>
using namespace Dali::Scene3D::Loader;
MeshDefinition::Blob::ApplyMinMax(accessor.mMin, accessor.mMax, accessor.mCount, values);
}
-const auto BUFFER_READER = std::move(json::Reader<gltf2::Buffer>()
- .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::Buffer::mByteLength))
- .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Buffer::mUri)));
-
-const auto BUFFER_VIEW_READER = std::move(json::Reader<gltf2::BufferView>()
- .Register(*json::MakeProperty("buffer", gltf2::RefReader<gltf2::Document>::Read<gltf2::Buffer, &gltf2::Document::mBuffers>, &gltf2::BufferView::mBuffer))
- .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteOffset))
- .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteLength))
- .Register(*json::MakeProperty("byteStride", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteStride))
- .Register(*json::MakeProperty("target", json::Read::Number<uint32_t>, &gltf2::BufferView::mTarget)));
-
-const auto BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::BufferViewClient>()
- .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::BufferViewClient::mBufferView))
- .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferViewClient::mByteOffset)));
-
-const auto COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::ComponentTypedBufferViewClient>()
- .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, gltf2::Ref<gltf2::BufferView>>("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::ComponentTypedBufferViewClient::mBufferView))
- .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, uint32_t>("byteOffset", json::Read::Number<uint32_t>, &gltf2::ComponentTypedBufferViewClient::mByteOffset))
- .Register(*json::MakeProperty("componentType", json::Read::Enum<gltf2::Component::Type>, &gltf2::ComponentTypedBufferViewClient::mComponentType)));
-
-const auto ACCESSOR_SPARSE_READER = std::move(json::Reader<gltf2::Accessor::Sparse>()
- .Register(*json::MakeProperty("count", json::Read::Number<uint32_t>, &gltf2::Accessor::Sparse::mCount))
- .Register(*json::MakeProperty("indices", json::ObjectReader<gltf2::ComponentTypedBufferViewClient>::Read, &gltf2::Accessor::Sparse::mIndices))
- .Register(*json::MakeProperty("values", json::ObjectReader<gltf2::BufferViewClient>::Read, &gltf2::Accessor::Sparse::mValues)));
-
-const auto ACCESSOR_READER = std::move(json::Reader<gltf2::Accessor>()
- .Register(*new json::Property<gltf2::Accessor, gltf2::Ref<gltf2::BufferView>>("bufferView",
- gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>,
- &gltf2::Accessor::mBufferView))
- .Register(*new json::Property<gltf2::Accessor, uint32_t>("byteOffset",
- json::Read::Number<uint32_t>,
- &gltf2::Accessor::mByteOffset))
- .Register(*new json::Property<gltf2::Accessor, gltf2::Component::Type>("componentType",
- json::Read::Enum<gltf2::Component::Type>,
- &gltf2::Accessor::mComponentType))
- .Register(*new json::Property<gltf2::Accessor, std::string_view>("name", json::Read::StringView, &gltf2::Accessor::mName))
- .Register(*json::MakeProperty("count", json::Read::Number<uint32_t>, &gltf2::Accessor::mCount))
- .Register(*json::MakeProperty("normalized", json::Read::Boolean, &gltf2::Accessor::mNormalized))
- .Register(*json::MakeProperty("type", gltf2::ReadStringEnum<gltf2::AccessorType>, &gltf2::Accessor::mType))
- .Register(*json::MakeProperty("min", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMin))
- .Register(*json::MakeProperty("max", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMax))
- .Register(*new json::Property<gltf2::Accessor, gltf2::Accessor::Sparse>("sparse", json::ObjectReader<gltf2::Accessor::Sparse>::Read, &gltf2::Accessor::SetSparse)));
-
-const auto IMAGE_READER = std::move(json::Reader<gltf2::Image>()
- .Register(*new json::Property<gltf2::Image, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
- .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Image::mUri))
- .Register(*json::MakeProperty("mimeType", json::Read::StringView, &gltf2::Image::mMimeType))
- .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::Image::mBufferView)));
-
-const auto SAMPLER_READER = std::move(json::Reader<gltf2::Sampler>()
- .Register(*json::MakeProperty("minFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMinFilter))
- .Register(*json::MakeProperty("magFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMagFilter))
- .Register(*json::MakeProperty("wrapS", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapS))
- .Register(*json::MakeProperty("wrapT", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapT)));
-
-const auto TEXURE_READER = std::move(json::Reader<gltf2::Texture>()
- .Register(*json::MakeProperty("source", gltf2::RefReader<gltf2::Document>::Read<gltf2::Image, &gltf2::Document::mImages>, &gltf2::Texture::mSource))
- .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Document>::Read<gltf2::Sampler, &gltf2::Document::mSamplers>, &gltf2::Texture::mSampler)));
-
-const auto TEXURE_INFO_READER = std::move(json::Reader<gltf2::TextureInfo>()
- .Register(*json::MakeProperty("index", gltf2::RefReader<gltf2::Document>::Read<gltf2::Texture, &gltf2::Document::mTextures>, &gltf2::TextureInfo::mTexture))
- .Register(*json::MakeProperty("texCoord", json::Read::Number<uint32_t>, &gltf2::TextureInfo::mTexCoord))
- .Register(*json::MakeProperty("scale", json::Read::Number<float>, &gltf2::TextureInfo::mScale))
- .Register(*json::MakeProperty("strength", json::Read::Number<float>, &gltf2::TextureInfo::mStrength)));
-
-const auto MATERIAL_PBR_READER = std::move(json::Reader<gltf2::Material::Pbr>()
- .Register(*json::MakeProperty("baseColorFactor", gltf2::ReadDaliVector<Vector4>, &gltf2::Material::Pbr::mBaseColorFactor))
- .Register(*json::MakeProperty("baseColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mBaseColorTexture))
- .Register(*json::MakeProperty("metallicFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mMetallicFactor))
- .Register(*json::MakeProperty("roughnessFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mRoughnessFactor))
- .Register(*json::MakeProperty("metallicRoughnessTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mMetallicRoughnessTexture)));
-
-const auto MATERIAL_SPECULAR_READER = std::move(json::Reader<gltf2::MaterialSpecular>()
- .Register(*json::MakeProperty("specularFactor", json::Read::Number<float>, &gltf2::MaterialSpecular::mSpecularFactor))
- .Register(*json::MakeProperty("specularTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularTexture))
- .Register(*json::MakeProperty("specularColorFactor", gltf2::ReadDaliVector<Vector3>, &gltf2::MaterialSpecular::mSpecularColorFactor))
- .Register(*json::MakeProperty("specularColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularColorTexture)));
-
-const auto MATERIAL_IOR_READER = std::move(json::Reader<gltf2::MaterialIor>()
- .Register(*json::MakeProperty("ior", json::Read::Number<float>, &gltf2::MaterialIor::mIor)));
-
-const auto MATERIAL_EXTENSION_READER = std::move(json::Reader<gltf2::MaterialExtensions>()
- .Register(*json::MakeProperty("KHR_materials_ior", json::ObjectReader<gltf2::MaterialIor>::Read, &gltf2::MaterialExtensions::mMaterialIor))
- .Register(*json::MakeProperty("KHR_materials_specular", json::ObjectReader<gltf2::MaterialSpecular>::Read, &gltf2::MaterialExtensions::mMaterialSpecular)));
-
-const auto MATERIAL_READER = std::move(json::Reader<gltf2::Material>()
- .Register(*new json::Property<gltf2::Material, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
- .Register(*json::MakeProperty("pbrMetallicRoughness", json::ObjectReader<gltf2::Material::Pbr>::Read, &gltf2::Material::mPbrMetallicRoughness))
- .Register(*json::MakeProperty("normalTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mNormalTexture))
- .Register(*json::MakeProperty("occlusionTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mOcclusionTexture))
- .Register(*json::MakeProperty("emissiveTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mEmissiveTexture))
- .Register(*json::MakeProperty("emissiveFactor", gltf2::ReadDaliVector<Vector3>, &gltf2::Material::mEmissiveFactor))
- .Register(*json::MakeProperty("alphaMode", gltf2::ReadStringEnum<gltf2::AlphaMode>, &gltf2::Material::mAlphaMode))
- .Register(*json::MakeProperty("alphaCutoff", json::Read::Number<float>, &gltf2::Material::mAlphaCutoff))
- .Register(*json::MakeProperty("doubleSided", json::Read::Boolean, &gltf2::Material::mDoubleSided))
- .Register(*json::MakeProperty("extensions", json::ObjectReader<gltf2::MaterialExtensions>::Read, &gltf2::Material::mMaterialExtensions)));
+const json::Reader<gltf2::Buffer>& GetBufferReader()
+{
+ static const auto BUFFER_READER = std::move(json::Reader<gltf2::Buffer>()
+ .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::Buffer::mByteLength))
+ .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Buffer::mUri)));
+ return BUFFER_READER;
+}
+
+const json::Reader<gltf2::BufferView>& GetBufferViewReader()
+{
+ static const auto BUFFER_VIEW_READER = std::move(json::Reader<gltf2::BufferView>()
+ .Register(*json::MakeProperty("buffer", gltf2::RefReader<gltf2::Document>::Read<gltf2::Buffer, &gltf2::Document::mBuffers>, &gltf2::BufferView::mBuffer))
+ .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteOffset))
+ .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteLength))
+ .Register(*json::MakeProperty("byteStride", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteStride))
+ .Register(*json::MakeProperty("target", json::Read::Number<uint32_t>, &gltf2::BufferView::mTarget)));
+ return BUFFER_VIEW_READER;
+}
+
+const json::Reader<gltf2::BufferViewClient>& GetBufferViewClientReader()
+{
+ static const auto BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::BufferViewClient>()
+ .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::BufferViewClient::mBufferView))
+ .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferViewClient::mByteOffset)));
+ return BUFFER_VIEW_CLIENT_READER;
+}
+
+const json::Reader<gltf2::ComponentTypedBufferViewClient>& GetComponentTypedBufferViewClientReader()
+{
+ static const auto COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::ComponentTypedBufferViewClient>()
+ .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, gltf2::Ref<gltf2::BufferView>>("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::ComponentTypedBufferViewClient::mBufferView))
+ .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, uint32_t>("byteOffset", json::Read::Number<uint32_t>, &gltf2::ComponentTypedBufferViewClient::mByteOffset))
+ .Register(*json::MakeProperty("componentType", json::Read::Enum<gltf2::Component::Type>, &gltf2::ComponentTypedBufferViewClient::mComponentType)));
+ return COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER;
+}
+
+const json::Reader<gltf2::Accessor::Sparse>& GetAccessorSparseReader()
+{
+ static const auto ACCESSOR_SPARSE_READER = std::move(json::Reader<gltf2::Accessor::Sparse>()
+ .Register(*json::MakeProperty("count", json::Read::Number<uint32_t>, &gltf2::Accessor::Sparse::mCount))
+ .Register(*json::MakeProperty("indices", json::ObjectReader<gltf2::ComponentTypedBufferViewClient>::Read, &gltf2::Accessor::Sparse::mIndices))
+ .Register(*json::MakeProperty("values", json::ObjectReader<gltf2::BufferViewClient>::Read, &gltf2::Accessor::Sparse::mValues)));
+ return ACCESSOR_SPARSE_READER;
+}
+
+const json::Reader<gltf2::Accessor>& GetAccessorReader()
+{
+ static const auto ACCESSOR_READER = std::move(json::Reader<gltf2::Accessor>()
+ .Register(*new json::Property<gltf2::Accessor, gltf2::Ref<gltf2::BufferView>>("bufferView",
+ gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>,
+ &gltf2::Accessor::mBufferView))
+ .Register(*new json::Property<gltf2::Accessor, uint32_t>("byteOffset",
+ json::Read::Number<uint32_t>,
+ &gltf2::Accessor::mByteOffset))
+ .Register(*new json::Property<gltf2::Accessor, gltf2::Component::Type>("componentType",
+ json::Read::Enum<gltf2::Component::Type>,
+ &gltf2::Accessor::mComponentType))
+ .Register(*new json::Property<gltf2::Accessor, std::string_view>("name", json::Read::StringView, &gltf2::Accessor::mName))
+ .Register(*json::MakeProperty("count", json::Read::Number<uint32_t>, &gltf2::Accessor::mCount))
+ .Register(*json::MakeProperty("normalized", json::Read::Boolean, &gltf2::Accessor::mNormalized))
+ .Register(*json::MakeProperty("type", gltf2::ReadStringEnum<gltf2::AccessorType>, &gltf2::Accessor::mType))
+ .Register(*json::MakeProperty("min", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMin))
+ .Register(*json::MakeProperty("max", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMax))
+ .Register(*new json::Property<gltf2::Accessor, gltf2::Accessor::Sparse>("sparse", json::ObjectReader<gltf2::Accessor::Sparse>::Read, &gltf2::Accessor::SetSparse)));
+ return ACCESSOR_READER;
+}
+
+const json::Reader<gltf2::Image>& GetImageReader()
+{
+ static const auto IMAGE_READER = std::move(json::Reader<gltf2::Image>()
+ .Register(*new json::Property<gltf2::Image, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
+ .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Image::mUri))
+ .Register(*json::MakeProperty("mimeType", json::Read::StringView, &gltf2::Image::mMimeType))
+ .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::Image::mBufferView)));
+ return IMAGE_READER;
+}
+
+const json::Reader<gltf2::Sampler>& GetSamplerReader()
+{
+ static const auto SAMPLER_READER = std::move(json::Reader<gltf2::Sampler>()
+ .Register(*json::MakeProperty("minFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMinFilter))
+ .Register(*json::MakeProperty("magFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMagFilter))
+ .Register(*json::MakeProperty("wrapS", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapS))
+ .Register(*json::MakeProperty("wrapT", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapT)));
+ return SAMPLER_READER;
+}
+
+const json::Reader<gltf2::Texture>& GetTextureReader()
+{
+ static const auto TEXURE_READER = std::move(json::Reader<gltf2::Texture>()
+ .Register(*json::MakeProperty("source", gltf2::RefReader<gltf2::Document>::Read<gltf2::Image, &gltf2::Document::mImages>, &gltf2::Texture::mSource))
+ .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Document>::Read<gltf2::Sampler, &gltf2::Document::mSamplers>, &gltf2::Texture::mSampler)));
+ return TEXURE_READER;
+}
+
+const json::Reader<gltf2::TextureInfo>& GetTextureInfoReader()
+{
+ static const auto TEXURE_INFO_READER = std::move(json::Reader<gltf2::TextureInfo>()
+ .Register(*json::MakeProperty("index", gltf2::RefReader<gltf2::Document>::Read<gltf2::Texture, &gltf2::Document::mTextures>, &gltf2::TextureInfo::mTexture))
+ .Register(*json::MakeProperty("texCoord", json::Read::Number<uint32_t>, &gltf2::TextureInfo::mTexCoord))
+ .Register(*json::MakeProperty("scale", json::Read::Number<float>, &gltf2::TextureInfo::mScale))
+ .Register(*json::MakeProperty("strength", json::Read::Number<float>, &gltf2::TextureInfo::mStrength)));
+ return TEXURE_INFO_READER;
+}
+
+const json::Reader<gltf2::Material::Pbr>& GetMaterialPbrReader()
+{
+ static const auto MATERIAL_PBR_READER = std::move(json::Reader<gltf2::Material::Pbr>()
+ .Register(*json::MakeProperty("baseColorFactor", gltf2::ReadDaliVector<Vector4>, &gltf2::Material::Pbr::mBaseColorFactor))
+ .Register(*json::MakeProperty("baseColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mBaseColorTexture))
+ .Register(*json::MakeProperty("metallicFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mMetallicFactor))
+ .Register(*json::MakeProperty("roughnessFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mRoughnessFactor))
+ .Register(*json::MakeProperty("metallicRoughnessTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mMetallicRoughnessTexture)));
+ return MATERIAL_PBR_READER;
+}
+
+const json::Reader<gltf2::MaterialSpecular>& GetMaterialSpecularReader()
+{
+ static const auto MATERIAL_SPECULAR_READER = std::move(json::Reader<gltf2::MaterialSpecular>()
+ .Register(*json::MakeProperty("specularFactor", json::Read::Number<float>, &gltf2::MaterialSpecular::mSpecularFactor))
+ .Register(*json::MakeProperty("specularTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularTexture))
+ .Register(*json::MakeProperty("specularColorFactor", gltf2::ReadDaliVector<Vector3>, &gltf2::MaterialSpecular::mSpecularColorFactor))
+ .Register(*json::MakeProperty("specularColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularColorTexture)));
+ return MATERIAL_SPECULAR_READER;
+}
+
+const json::Reader<gltf2::MaterialIor>& GetMaterialIorReader()
+{
+ static const auto MATERIAL_IOR_READER = std::move(json::Reader<gltf2::MaterialIor>()
+ .Register(*json::MakeProperty("ior", json::Read::Number<float>, &gltf2::MaterialIor::mIor)));
+ return MATERIAL_IOR_READER;
+}
+
+const json::Reader<gltf2::MaterialExtensions>& GetMaterialExtensionsReader()
+{
+ static const auto MATERIAL_EXTENSION_READER = std::move(json::Reader<gltf2::MaterialExtensions>()
+ .Register(*json::MakeProperty("KHR_materials_ior", json::ObjectReader<gltf2::MaterialIor>::Read, &gltf2::MaterialExtensions::mMaterialIor))
+ .Register(*json::MakeProperty("KHR_materials_specular", json::ObjectReader<gltf2::MaterialSpecular>::Read, &gltf2::MaterialExtensions::mMaterialSpecular)));
+ return MATERIAL_EXTENSION_READER;
+}
+
+const json::Reader<gltf2::Material>& GetMaterialReader()
+{
+ static const auto MATERIAL_READER = std::move(json::Reader<gltf2::Material>()
+ .Register(*new json::Property<gltf2::Material, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
+ .Register(*json::MakeProperty("pbrMetallicRoughness", json::ObjectReader<gltf2::Material::Pbr>::Read, &gltf2::Material::mPbrMetallicRoughness))
+ .Register(*json::MakeProperty("normalTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mNormalTexture))
+ .Register(*json::MakeProperty("occlusionTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mOcclusionTexture))
+ .Register(*json::MakeProperty("emissiveTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mEmissiveTexture))
+ .Register(*json::MakeProperty("emissiveFactor", gltf2::ReadDaliVector<Vector3>, &gltf2::Material::mEmissiveFactor))
+ .Register(*json::MakeProperty("alphaMode", gltf2::ReadStringEnum<gltf2::AlphaMode>, &gltf2::Material::mAlphaMode))
+ .Register(*json::MakeProperty("alphaCutoff", json::Read::Number<float>, &gltf2::Material::mAlphaCutoff))
+ .Register(*json::MakeProperty("doubleSided", json::Read::Boolean, &gltf2::Material::mDoubleSided))
+ .Register(*json::MakeProperty("extensions", json::ObjectReader<gltf2::MaterialExtensions>::Read, &gltf2::Material::mMaterialExtensions)));
+ return MATERIAL_READER;
+}
std::map<gltf2::Attribute::Type, gltf2::Ref<gltf2::Accessor>> ReadMeshPrimitiveAttributes(const json_value_s& j)
{
return result;
}
-const auto MESH_PRIMITIVE_READER = std::move(json::Reader<gltf2::Mesh::Primitive>()
- .Register(*json::MakeProperty("attributes", ReadMeshPrimitiveAttributes, &gltf2::Mesh::Primitive::mAttributes))
- .Register(*json::MakeProperty("indices", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Mesh::Primitive::mIndices))
- .Register(*json::MakeProperty("material", gltf2::RefReader<gltf2::Document>::Read<gltf2::Material, &gltf2::Document::mMaterials>, &gltf2::Mesh::Primitive::mMaterial))
- .Register(*json::MakeProperty("mode", json::Read::Enum<gltf2::Mesh::Primitive::Mode>, &gltf2::Mesh::Primitive::mMode))
- .Register(*json::MakeProperty("targets", ReadMeshPrimitiveTargets, &gltf2::Mesh::Primitive::mTargets)));
-
-const auto MESH_READER = std::move(json::Reader<gltf2::Mesh>()
- .Register(*new json::Property<gltf2::Mesh, std::string_view>("name", json::Read::StringView, &gltf2::Mesh::mName))
- .Register(*json::MakeProperty("primitives",
- json::Read::Array<gltf2::Mesh::Primitive, json::ObjectReader<gltf2::Mesh::Primitive>::Read>,
- &gltf2::Mesh::mPrimitives))
- .Register(*json::MakeProperty("weights", json::Read::Array<float, json::Read::Number>, &gltf2::Mesh::mWeights)));
-
-const auto SKIN_READER = std::move(json::Reader<gltf2::Skin>()
- .Register(*new json::Property<gltf2::Skin, std::string_view>("name", json::Read::StringView, &gltf2::Skin::mName))
- .Register(*json::MakeProperty("inverseBindMatrices",
- gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>,
- &gltf2::Skin::mInverseBindMatrices))
- .Register(*json::MakeProperty("skeleton",
- gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>,
- &gltf2::Skin::mSkeleton))
- .Register(*json::MakeProperty("joints",
- json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
- &gltf2::Skin::mJoints)));
-
-const auto CAMERA_PERSPECTIVE_READER = std::move(json::Reader<gltf2::Camera::Perspective>()
- .Register(*json::MakeProperty("aspectRatio", json::Read::Number<float>, &gltf2::Camera::Perspective::mAspectRatio))
- .Register(*json::MakeProperty("yfov", json::Read::Number<float>, &gltf2::Camera::Perspective::mYFov))
- .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Perspective::mZFar))
- .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Perspective::mZNear))); // TODO: infinite perspective projection, where znear is omitted
-
-const auto CAMERA_ORTHOGRAPHIC_READER = std::move(json::Reader<gltf2::Camera::Orthographic>()
- .Register(*json::MakeProperty("xmag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mXMag))
- .Register(*json::MakeProperty("ymag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mYMag))
- .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZFar))
- .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZNear)));
-
-const auto CAMERA_READER = std::move(json::Reader<gltf2::Camera>()
- .Register(*new json::Property<gltf2::Camera, std::string_view>("name", json::Read::StringView, &gltf2::Camera::mName))
- .Register(*json::MakeProperty("type", json::Read::StringView, &gltf2::Camera::mType))
- .Register(*json::MakeProperty("perspective", json::ObjectReader<gltf2::Camera::Perspective>::Read, &gltf2::Camera::mPerspective))
- .Register(*json::MakeProperty("orthographic", json::ObjectReader<gltf2::Camera::Orthographic>::Read, &gltf2::Camera::mOrthographic)));
-
-const auto NODE_READER = std::move(json::Reader<gltf2::Node>()
- .Register(*new json::Property<gltf2::Node, std::string_view>("name", json::Read::StringView, &gltf2::Node::mName))
- .Register(*json::MakeProperty("translation", gltf2::ReadDaliVector<Vector3>, &gltf2::Node::mTranslation))
- .Register(*json::MakeProperty("rotation", gltf2::ReadQuaternion, &gltf2::Node::mRotation))
- .Register(*json::MakeProperty("scale", gltf2::ReadDaliVector<Vector3>, &gltf2::Node::mScale))
- .Register(*new json::Property<gltf2::Node, Matrix>("matrix", gltf2::ReadDaliVector<Matrix>, &gltf2::Node::SetMatrix))
- .Register(*json::MakeProperty("camera", gltf2::RefReader<gltf2::Document>::Read<gltf2::Camera, &gltf2::Document::mCameras>, &gltf2::Node::mCamera))
- .Register(*json::MakeProperty("children", json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>, &gltf2::Node::mChildren))
- .Register(*json::MakeProperty("mesh", gltf2::RefReader<gltf2::Document>::Read<gltf2::Mesh, &gltf2::Document::mMeshes>, &gltf2::Node::mMesh))
- .Register(*json::MakeProperty("skin", gltf2::RefReader<gltf2::Document>::Read<gltf2::Skin, &gltf2::Document::mSkins>, &gltf2::Node::mSkin)));
-
-const auto ANIMATION_SAMPLER_READER = std::move(json::Reader<gltf2::Animation::Sampler>()
- .Register(*json::MakeProperty("input", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mInput))
- .Register(*json::MakeProperty("output", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mOutput))
- .Register(*json::MakeProperty("interpolation", gltf2::ReadStringEnum<gltf2::Animation::Sampler::Interpolation>, &gltf2::Animation::Sampler::mInterpolation)));
-
-const auto ANIMATION_TARGET_READER = std::move(json::Reader<gltf2::Animation::Channel::Target>()
- .Register(*json::MakeProperty("node", gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>, &gltf2::Animation::Channel::Target::mNode))
- .Register(*json::MakeProperty("path", gltf2::ReadStringEnum<gltf2::Animation::Channel::Target>, &gltf2::Animation::Channel::Target::mPath)));
-
-const auto ANIMATION_CHANNEL_READER = std::move(json::Reader<gltf2::Animation::Channel>()
- .Register(*json::MakeProperty("target", json::ObjectReader<gltf2::Animation::Channel::Target>::Read, &gltf2::Animation::Channel::mTarget))
- .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Animation>::Read<gltf2::Animation::Sampler, &gltf2::Animation::mSamplers>, &gltf2::Animation::Channel::mSampler)));
-
-const auto ANIMATION_READER = std::move(json::Reader<gltf2::Animation>()
- .Register(*new json::Property<gltf2::Animation, std::string_view>("name", json::Read::StringView, &gltf2::Animation::mName))
- .Register(*json::MakeProperty("samplers",
- json::Read::Array<gltf2::Animation::Sampler, json::ObjectReader<gltf2::Animation::Sampler>::Read>,
- &gltf2::Animation::mSamplers))
- .Register(*json::MakeProperty("channels",
- json::Read::Array<gltf2::Animation::Channel, json::ObjectReader<gltf2::Animation::Channel>::Read>,
- &gltf2::Animation::mChannels)));
-
-const auto SCENE_READER = std::move(json::Reader<gltf2::Scene>()
- .Register(*new json::Property<gltf2::Scene, std::string_view>("name", json::Read::StringView, &gltf2::Scene::mName))
- .Register(*json::MakeProperty("nodes",
- json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
- &gltf2::Scene::mNodes)));
-
-const auto DOCUMENT_READER = std::move(json::Reader<gltf2::Document>()
- .Register(*json::MakeProperty("buffers",
- json::Read::Array<gltf2::Buffer, json::ObjectReader<gltf2::Buffer>::Read>,
- &gltf2::Document::mBuffers))
- .Register(*json::MakeProperty("bufferViews",
- json::Read::Array<gltf2::BufferView, json::ObjectReader<gltf2::BufferView>::Read>,
- &gltf2::Document::mBufferViews))
- .Register(*json::MakeProperty("accessors",
- json::Read::Array<gltf2::Accessor, json::ObjectReader<gltf2::Accessor>::Read>,
- &gltf2::Document::mAccessors))
- .Register(*json::MakeProperty("images",
- json::Read::Array<gltf2::Image, json::ObjectReader<gltf2::Image>::Read>,
- &gltf2::Document::mImages))
- .Register(*json::MakeProperty("samplers",
- json::Read::Array<gltf2::Sampler, json::ObjectReader<gltf2::Sampler>::Read>,
- &gltf2::Document::mSamplers))
- .Register(*json::MakeProperty("textures",
- json::Read::Array<gltf2::Texture, json::ObjectReader<gltf2::Texture>::Read>,
- &gltf2::Document::mTextures))
- .Register(*json::MakeProperty("materials",
- json::Read::Array<gltf2::Material, json::ObjectReader<gltf2::Material>::Read>,
- &gltf2::Document::mMaterials))
- .Register(*json::MakeProperty("meshes",
- json::Read::Array<gltf2::Mesh, json::ObjectReader<gltf2::Mesh>::Read>,
- &gltf2::Document::mMeshes))
- .Register(*json::MakeProperty("skins",
- json::Read::Array<gltf2::Skin, json::ObjectReader<gltf2::Skin>::Read>,
- &gltf2::Document::mSkins))
- .Register(*json::MakeProperty("cameras",
- json::Read::Array<gltf2::Camera, json::ObjectReader<gltf2::Camera>::Read>,
- &gltf2::Document::mCameras))
- .Register(*json::MakeProperty("nodes",
- json::Read::Array<gltf2::Node, json::ObjectReader<gltf2::Node>::Read>,
- &gltf2::Document::mNodes))
- .Register(*json::MakeProperty("animations",
- ReadAnimationArray,
- &gltf2::Document::mAnimations))
- .Register(*json::MakeProperty("scenes",
- json::Read::Array<gltf2::Scene, json::ObjectReader<gltf2::Scene>::Read>,
- &gltf2::Document::mScenes))
- .Register(*json::MakeProperty("scene", gltf2::RefReader<gltf2::Document>::Read<gltf2::Scene, &gltf2::Document::mScenes>, &gltf2::Document::mScene)));
+const json::Reader<gltf2::Mesh::Primitive>& GetMeshPrimitiveReader()
+{
+ static const auto MESH_PRIMITIVE_READER = std::move(json::Reader<gltf2::Mesh::Primitive>()
+ .Register(*json::MakeProperty("attributes", ReadMeshPrimitiveAttributes, &gltf2::Mesh::Primitive::mAttributes))
+ .Register(*json::MakeProperty("indices", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Mesh::Primitive::mIndices))
+ .Register(*json::MakeProperty("material", gltf2::RefReader<gltf2::Document>::Read<gltf2::Material, &gltf2::Document::mMaterials>, &gltf2::Mesh::Primitive::mMaterial))
+ .Register(*json::MakeProperty("mode", json::Read::Enum<gltf2::Mesh::Primitive::Mode>, &gltf2::Mesh::Primitive::mMode))
+ .Register(*json::MakeProperty("targets", ReadMeshPrimitiveTargets, &gltf2::Mesh::Primitive::mTargets)));
+ return MESH_PRIMITIVE_READER;
+}
+
+const json::Reader<gltf2::Mesh>& GetMeshReader()
+{
+ static const auto MESH_READER = std::move(json::Reader<gltf2::Mesh>()
+ .Register(*new json::Property<gltf2::Mesh, std::string_view>("name", json::Read::StringView, &gltf2::Mesh::mName))
+ .Register(*json::MakeProperty("primitives",
+ json::Read::Array<gltf2::Mesh::Primitive, json::ObjectReader<gltf2::Mesh::Primitive>::Read>,
+ &gltf2::Mesh::mPrimitives))
+ .Register(*json::MakeProperty("weights", json::Read::Array<float, json::Read::Number>, &gltf2::Mesh::mWeights)));
+ return MESH_READER;
+}
+
+const json::Reader<gltf2::Skin>& GetSkinReader()
+{
+ static const auto SKIN_READER = std::move(json::Reader<gltf2::Skin>()
+ .Register(*new json::Property<gltf2::Skin, std::string_view>("name", json::Read::StringView, &gltf2::Skin::mName))
+ .Register(*json::MakeProperty("inverseBindMatrices",
+ gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>,
+ &gltf2::Skin::mInverseBindMatrices))
+ .Register(*json::MakeProperty("skeleton",
+ gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>,
+ &gltf2::Skin::mSkeleton))
+ .Register(*json::MakeProperty("joints",
+ json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
+ &gltf2::Skin::mJoints)));
+ return SKIN_READER;
+}
+
+const json::Reader<gltf2::Camera::Perspective>& GetCameraPerspectiveReader()
+{
+ static const auto CAMERA_PERSPECTIVE_READER = std::move(json::Reader<gltf2::Camera::Perspective>()
+ .Register(*json::MakeProperty("aspectRatio", json::Read::Number<float>, &gltf2::Camera::Perspective::mAspectRatio))
+ .Register(*json::MakeProperty("yfov", json::Read::Number<float>, &gltf2::Camera::Perspective::mYFov))
+ .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Perspective::mZFar))
+ .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Perspective::mZNear))); // TODO: infinite perspective projection, where znear is omitted
+ return CAMERA_PERSPECTIVE_READER;
+}
+
+const json::Reader<gltf2::Camera::Orthographic>& GetCameraOrthographicReader()
+{
+ static const auto CAMERA_ORTHOGRAPHIC_READER = std::move(json::Reader<gltf2::Camera::Orthographic>()
+ .Register(*json::MakeProperty("xmag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mXMag))
+ .Register(*json::MakeProperty("ymag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mYMag))
+ .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZFar))
+ .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZNear)));
+ return CAMERA_ORTHOGRAPHIC_READER;
+}
+
+const json::Reader<gltf2::Camera>& GetCameraReader()
+{
+ static const auto CAMERA_READER = std::move(json::Reader<gltf2::Camera>()
+ .Register(*new json::Property<gltf2::Camera, std::string_view>("name", json::Read::StringView, &gltf2::Camera::mName))
+ .Register(*json::MakeProperty("type", json::Read::StringView, &gltf2::Camera::mType))
+ .Register(*json::MakeProperty("perspective", json::ObjectReader<gltf2::Camera::Perspective>::Read, &gltf2::Camera::mPerspective))
+ .Register(*json::MakeProperty("orthographic", json::ObjectReader<gltf2::Camera::Orthographic>::Read, &gltf2::Camera::mOrthographic)));
+ return CAMERA_READER;
+}
+
+const json::Reader<gltf2::Node>& GetNodeReader()
+{
+ static const auto NODE_READER = std::move(json::Reader<gltf2::Node>()
+ .Register(*new json::Property<gltf2::Node, std::string_view>("name", json::Read::StringView, &gltf2::Node::mName))
+ .Register(*json::MakeProperty("translation", gltf2::ReadDaliVector<Vector3>, &gltf2::Node::mTranslation))
+ .Register(*json::MakeProperty("rotation", gltf2::ReadQuaternion, &gltf2::Node::mRotation))
+ .Register(*json::MakeProperty("scale", gltf2::ReadDaliVector<Vector3>, &gltf2::Node::mScale))
+ .Register(*new json::Property<gltf2::Node, Matrix>("matrix", gltf2::ReadDaliVector<Matrix>, &gltf2::Node::SetMatrix))
+ .Register(*json::MakeProperty("camera", gltf2::RefReader<gltf2::Document>::Read<gltf2::Camera, &gltf2::Document::mCameras>, &gltf2::Node::mCamera))
+ .Register(*json::MakeProperty("children", json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>, &gltf2::Node::mChildren))
+ .Register(*json::MakeProperty("mesh", gltf2::RefReader<gltf2::Document>::Read<gltf2::Mesh, &gltf2::Document::mMeshes>, &gltf2::Node::mMesh))
+ .Register(*json::MakeProperty("skin", gltf2::RefReader<gltf2::Document>::Read<gltf2::Skin, &gltf2::Document::mSkins>, &gltf2::Node::mSkin)));
+ return NODE_READER;
+}
+
+const json::Reader<gltf2::Animation::Sampler>& GetAnimationSamplerReader()
+{
+ static const auto ANIMATION_SAMPLER_READER = std::move(json::Reader<gltf2::Animation::Sampler>()
+ .Register(*json::MakeProperty("input", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mInput))
+ .Register(*json::MakeProperty("output", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mOutput))
+ .Register(*json::MakeProperty("interpolation", gltf2::ReadStringEnum<gltf2::Animation::Sampler::Interpolation>, &gltf2::Animation::Sampler::mInterpolation)));
+ return ANIMATION_SAMPLER_READER;
+}
+
+const json::Reader<gltf2::Animation::Channel::Target>& GetAnimationChannelTargetReader()
+{
+ static const auto ANIMATION_TARGET_READER = std::move(json::Reader<gltf2::Animation::Channel::Target>()
+ .Register(*json::MakeProperty("node", gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>, &gltf2::Animation::Channel::Target::mNode))
+ .Register(*json::MakeProperty("path", gltf2::ReadStringEnum<gltf2::Animation::Channel::Target>, &gltf2::Animation::Channel::Target::mPath)));
+ return ANIMATION_TARGET_READER;
+}
+
+const json::Reader<gltf2::Animation::Channel>& GetAnimationChannelReader()
+{
+ static const auto ANIMATION_CHANNEL_READER = std::move(json::Reader<gltf2::Animation::Channel>()
+ .Register(*json::MakeProperty("target", json::ObjectReader<gltf2::Animation::Channel::Target>::Read, &gltf2::Animation::Channel::mTarget))
+ .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Animation>::Read<gltf2::Animation::Sampler, &gltf2::Animation::mSamplers>, &gltf2::Animation::Channel::mSampler)));
+ return ANIMATION_CHANNEL_READER;
+}
+
+const json::Reader<gltf2::Animation>& GetAnimationReader()
+{
+ static const auto ANIMATION_READER = std::move(json::Reader<gltf2::Animation>()
+ .Register(*new json::Property<gltf2::Animation, std::string_view>("name", json::Read::StringView, &gltf2::Animation::mName))
+ .Register(*json::MakeProperty("samplers",
+ json::Read::Array<gltf2::Animation::Sampler, json::ObjectReader<gltf2::Animation::Sampler>::Read>,
+ &gltf2::Animation::mSamplers))
+ .Register(*json::MakeProperty("channels",
+ json::Read::Array<gltf2::Animation::Channel, json::ObjectReader<gltf2::Animation::Channel>::Read>,
+ &gltf2::Animation::mChannels)));
+ return ANIMATION_READER;
+}
+
+const json::Reader<gltf2::Scene>& GetSceneReader()
+{
+ static const auto SCENE_READER = std::move(json::Reader<gltf2::Scene>()
+ .Register(*new json::Property<gltf2::Scene, std::string_view>("name", json::Read::StringView, &gltf2::Scene::mName))
+ .Register(*json::MakeProperty("nodes",
+ json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
+ &gltf2::Scene::mNodes)));
+ return SCENE_READER;
+}
+
+const json::Reader<gltf2::Document>& GetDocumentReader()
+{
+ static const auto DOCUMENT_READER = std::move(json::Reader<gltf2::Document>()
+ .Register(*json::MakeProperty("buffers",
+ json::Read::Array<gltf2::Buffer, json::ObjectReader<gltf2::Buffer>::Read>,
+ &gltf2::Document::mBuffers))
+ .Register(*json::MakeProperty("bufferViews",
+ json::Read::Array<gltf2::BufferView, json::ObjectReader<gltf2::BufferView>::Read>,
+ &gltf2::Document::mBufferViews))
+ .Register(*json::MakeProperty("accessors",
+ json::Read::Array<gltf2::Accessor, json::ObjectReader<gltf2::Accessor>::Read>,
+ &gltf2::Document::mAccessors))
+ .Register(*json::MakeProperty("images",
+ json::Read::Array<gltf2::Image, json::ObjectReader<gltf2::Image>::Read>,
+ &gltf2::Document::mImages))
+ .Register(*json::MakeProperty("samplers",
+ json::Read::Array<gltf2::Sampler, json::ObjectReader<gltf2::Sampler>::Read>,
+ &gltf2::Document::mSamplers))
+ .Register(*json::MakeProperty("textures",
+ json::Read::Array<gltf2::Texture, json::ObjectReader<gltf2::Texture>::Read>,
+ &gltf2::Document::mTextures))
+ .Register(*json::MakeProperty("materials",
+ json::Read::Array<gltf2::Material, json::ObjectReader<gltf2::Material>::Read>,
+ &gltf2::Document::mMaterials))
+ .Register(*json::MakeProperty("meshes",
+ json::Read::Array<gltf2::Mesh, json::ObjectReader<gltf2::Mesh>::Read>,
+ &gltf2::Document::mMeshes))
+ .Register(*json::MakeProperty("skins",
+ json::Read::Array<gltf2::Skin, json::ObjectReader<gltf2::Skin>::Read>,
+ &gltf2::Document::mSkins))
+ .Register(*json::MakeProperty("cameras",
+ json::Read::Array<gltf2::Camera, json::ObjectReader<gltf2::Camera>::Read>,
+ &gltf2::Document::mCameras))
+ .Register(*json::MakeProperty("nodes",
+ json::Read::Array<gltf2::Node, json::ObjectReader<gltf2::Node>::Read>,
+ &gltf2::Document::mNodes))
+ .Register(*json::MakeProperty("animations",
+ ReadAnimationArray,
+ &gltf2::Document::mAnimations))
+ .Register(*json::MakeProperty("scenes",
+ json::Read::Array<gltf2::Scene, json::ObjectReader<gltf2::Scene>::Read>,
+ &gltf2::Document::mScenes))
+ .Register(*json::MakeProperty("scene", gltf2::RefReader<gltf2::Document>::Read<gltf2::Scene, &gltf2::Document::mScenes>, &gltf2::Document::mScene)));
+ return DOCUMENT_READER;
+}
void ConvertBuffer(const gltf2::Buffer& buffer, decltype(ResourceBundle::mBuffers)& outBuffers, const std::string& resourcePath)
{
}
}
+void AddTextureStage(uint32_t semantic, MaterialDefinition& materialDefinition, gltf2::TextureInfo textureInfo, const Dali::Scene3D::Loader::ImageMetadata &metaData, ConversionContext& context)
+{
+ materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(textureInfo, context, metaData)});
+ materialDefinition.mFlags |= semantic;
+}
+
void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<std::string, ImageMetadata>& imageMetaData, decltype(ResourceBundle::mMaterials)& outMaterials, ConversionContext& context)
{
- auto getTextureMetaData = [](const std::unordered_map<std::string, ImageMetadata>& metaData, const gltf2::TextureInfo& info) {
+ auto getTextureMetaData = [](const std::unordered_map<std::string, ImageMetadata>& metaData, const gltf2::TextureInfo& info)
+ {
if(!info.mTexture->mSource->mUri.empty())
{
if(auto search = metaData.find(info.mTexture->mSource->mUri.data()); search != metaData.end())
auto& pbr = material.mPbrMetallicRoughness;
if(material.mAlphaMode == gltf2::AlphaMode::BLEND)
{
- materialDefinition.mIsOpaque = false;
+ materialDefinition.mAlphaModeType = Scene3D::Material::AlphaModeType::BLEND;
+ materialDefinition.mIsOpaque = false;
materialDefinition.mFlags |= MaterialDefinition::TRANSPARENCY;
}
else if(material.mAlphaMode == gltf2::AlphaMode::MASK)
{
- materialDefinition.mIsMask = true;
+ materialDefinition.mAlphaModeType = Scene3D::Material::AlphaModeType::MASK;
+ materialDefinition.mIsMask = true;
materialDefinition.SetAlphaCutoff(std::min(1.f, std::max(0.f, material.mAlphaCutoff)));
}
materialDefinition.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!material.mNormalTexture + !!material.mOcclusionTexture + !!material.mEmissiveTexture);
if(pbr.mBaseColorTexture)
{
- const auto semantic = MaterialDefinition::ALBEDO;
- materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mBaseColorTexture, context, getTextureMetaData(imageMetaData, pbr.mBaseColorTexture))});
- // TODO: and there had better be one
- materialDefinition.mFlags |= semantic;
+ AddTextureStage(MaterialDefinition::ALBEDO, materialDefinition, pbr.mBaseColorTexture, getTextureMetaData(imageMetaData, pbr.mBaseColorTexture), context);
}
else
{
if(pbr.mMetallicRoughnessTexture)
{
- const auto semantic = MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
- MaterialDefinition::GLTF_CHANNELS;
- materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mMetallicRoughnessTexture, context, getTextureMetaData(imageMetaData, pbr.mMetallicRoughnessTexture))});
- // TODO: and there had better be one
- materialDefinition.mFlags |= semantic;
+ AddTextureStage(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+ materialDefinition,
+ pbr.mMetallicRoughnessTexture,
+ getTextureMetaData(imageMetaData, pbr.mMetallicRoughnessTexture),
+ context);
}
else
{
materialDefinition.mNormalScale = material.mNormalTexture.mScale;
if(material.mNormalTexture)
{
- const auto semantic = MaterialDefinition::NORMAL;
- materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mNormalTexture, context, getTextureMetaData(imageMetaData, material.mNormalTexture))});
- // TODO: and there had better be one
- materialDefinition.mFlags |= semantic;
+ AddTextureStage(MaterialDefinition::NORMAL, materialDefinition, material.mNormalTexture, getTextureMetaData(imageMetaData, material.mNormalTexture), context);
}
else
{
if(material.mOcclusionTexture)
{
- const auto semantic = MaterialDefinition::OCCLUSION;
- materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mOcclusionTexture, context, getTextureMetaData(imageMetaData, material.mOcclusionTexture))});
- // TODO: and there had better be one
- materialDefinition.mFlags |= semantic;
+ AddTextureStage(MaterialDefinition::OCCLUSION, materialDefinition, material.mOcclusionTexture, getTextureMetaData(imageMetaData, material.mOcclusionTexture), context);
materialDefinition.mOcclusionStrength = material.mOcclusionTexture.mStrength;
}
materialDefinition.mEmissiveFactor = material.mEmissiveFactor;
if(material.mEmissiveTexture)
{
- const auto semantic = MaterialDefinition::EMISSIVE;
- materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mEmissiveTexture, context, getTextureMetaData(imageMetaData, material.mEmissiveTexture))});
- // TODO: and there had better be one
- materialDefinition.mFlags |= semantic;
+ AddTextureStage(MaterialDefinition::EMISSIVE, materialDefinition, material.mEmissiveTexture, getTextureMetaData(imageMetaData, material.mEmissiveTexture), context);
+ materialDefinition.mEmissiveFactor = material.mEmissiveFactor;
}
if(!Dali::Equals(material.mMaterialExtensions.mMaterialIor.mIor, gltf2::UNDEFINED_FLOAT_VALUE))
{
- float ior = material.mMaterialExtensions.mMaterialIor.mIor;
- materialDefinition.mDielectricSpecular = powf((ior - 1.0f) / (ior + 1.0f), 2.0f);
+ materialDefinition.mIor = material.mMaterialExtensions.mMaterialIor.mIor;
+ materialDefinition.mDielectricSpecular = powf((materialDefinition.mIor - 1.0f) / (materialDefinition.mIor + 1.0f), 2.0f);
}
materialDefinition.mSpecularFactor = material.mMaterialExtensions.mMaterialSpecular.mSpecularFactor;
materialDefinition.mSpecularColorFactor = material.mMaterialExtensions.mMaterialSpecular.mSpecularColorFactor;
if(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture)
{
- const auto semantic = MaterialDefinition::SPECULAR;
- materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture, context, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture))});
- materialDefinition.mFlags |= semantic;
+ AddTextureStage(MaterialDefinition::SPECULAR, materialDefinition, material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture), context);
}
if(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture)
{
- const auto semantic = MaterialDefinition::SPECULAR_COLOR;
- materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture, context, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture))});
- materialDefinition.mFlags |= semantic;
+ AddTextureStage(MaterialDefinition::SPECULAR_COLOR, materialDefinition, material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture), context);
}
materialDefinition.mDoubleSided = material.mDoubleSided;
auto& attribs = primitive.mAttributes;
meshDefinition.mPrimitiveType = GLTF2_TO_DALI_PRIMITIVES[primitive.mMode];
- auto& accPositions = *attribs.find(gltf2::Attribute::POSITION)->second;
+ auto positionIter = attribs.find(gltf2::Attribute::POSITION);
+
+ if(positionIter == attribs.end())
+ {
+ DALI_LOG_ERROR("Primitive mesh dosn't have POSITION atrributes!");
+ continue;
+ }
+
+ auto& accPositions = *positionIter->second;
meshDefinition.mPositions = ConvertMeshPrimitiveAccessor(accPositions);
// glTF2 support vector4 tangent for mesh.
// https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#meshes-overview
auto& resources = output.mResources;
const auto index = scene.GetNodeCount();
- auto weakNode = scene.AddNode([&]() {
+ auto weakNode = scene.AddNode([&]()
+ {
std::unique_ptr<NodeDefinition> nodeDefinition{new NodeDefinition()};
nodeDefinition->mParentIdx = parentIndex;
return duration;
}
-float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation::Channel& channel, Index nodeIndex, uint32_t& propertyIndex, std::vector<Dali::Scene3D::Loader::AnimatedProperty>& properties)
+float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation::Channel& channel, Index nodeIndex, uint32_t& propertyIndex, AnimationDefinition& animationDefinition)
{
const gltf2::Accessor& input = *channel.mSampler->mInput;
const gltf2::Accessor& output = *channel.mSampler->mOutput;
const auto remainingSize = sizeof(weightNameBuffer) - prefixSize;
for(uint32_t weightIndex = 0u, endWeightIndex = channel.mSampler->mOutput->mCount / channel.mSampler->mInput->mCount; weightIndex < endWeightIndex; ++weightIndex)
{
- AnimatedProperty& animatedProperty = properties[propertyIndex++];
+ AnimatedProperty animatedProperty;
animatedProperty.mNodeIndex = nodeIndex;
snprintf(pWeightName, remainingSize, "%d]", weightIndex);
}
animatedProperty.mTimePeriod = {0.f, duration};
+
+ animationDefinition.SetProperty(propertyIndex++, std::move(animatedProperty));
}
return duration;
}
+template<typename T>
+float LoadAnimation(AnimationDefinition& animationDefinition, Index nodeIndex, Index propertyIndex, const std::string& propertyName, const gltf2::Animation::Channel& channel, ConversionContext& context)
+{
+ AnimatedProperty animatedProperty;
+ animatedProperty.mNodeIndex = nodeIndex;
+ animatedProperty.mPropertyName = propertyName;
+
+ animatedProperty.mKeyFrames = KeyFrames::New();
+ float duration = LoadKeyFrames<T>(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
+ animatedProperty.mTimePeriod = {0.f, duration};
+
+ animationDefinition.SetProperty(propertyIndex, std::move(animatedProperty));
+ return duration;
+}
+
void ConvertAnimations(const gltf2::Document& document, ConversionContext& context)
{
auto& output = context.mOutput;
for(const auto& animation : document.mAnimations)
{
- AnimationDefinition animationDef;
+ AnimationDefinition animationDefinition;
if(!animation.mName.empty())
{
- animationDef.mName = animation.mName;
+ animationDefinition.SetName(animation.mName.data());
}
uint32_t numberOfProperties = 0u;
numberOfProperties++;
}
}
- animationDef.mProperties.resize(numberOfProperties);
+ animationDefinition.ReserveSize(numberOfProperties);
Index propertyIndex = 0u;
for(const auto& channel : animation.mChannels)
{
case gltf2::Animation::Channel::Target::TRANSLATION:
{
- AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
-
- animatedProperty.mNodeIndex = nodeIndex;
- animatedProperty.mPropertyName = POSITION_PROPERTY;
-
- animatedProperty.mKeyFrames = KeyFrames::New();
- duration = LoadKeyFrames<Vector3>(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
-
- animatedProperty.mTimePeriod = {0.f, duration};
+ duration = LoadAnimation<Vector3>(animationDefinition, nodeIndex, propertyIndex, POSITION_PROPERTY.data(), channel, context);
break;
}
case gltf2::Animation::Channel::Target::ROTATION:
{
- AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
-
- animatedProperty.mNodeIndex = nodeIndex;
- animatedProperty.mPropertyName = ORIENTATION_PROPERTY;
-
- animatedProperty.mKeyFrames = KeyFrames::New();
- duration = LoadKeyFrames<Quaternion>(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
-
- animatedProperty.mTimePeriod = {0.f, duration};
+ duration = LoadAnimation<Quaternion>(animationDefinition, nodeIndex, propertyIndex, ORIENTATION_PROPERTY.data(), channel, context);
break;
}
case gltf2::Animation::Channel::Target::SCALE:
{
- AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
-
- animatedProperty.mNodeIndex = nodeIndex;
- animatedProperty.mPropertyName = SCALE_PROPERTY;
-
- animatedProperty.mKeyFrames = KeyFrames::New();
- duration = LoadKeyFrames<Vector3>(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
-
- animatedProperty.mTimePeriod = {0.f, duration};
+ duration = LoadAnimation<Vector3>(animationDefinition, nodeIndex, propertyIndex, SCALE_PROPERTY.data(), channel, context);
break;
}
case gltf2::Animation::Channel::Target::WEIGHTS:
{
- duration = LoadBlendShapeKeyFrames(context, channel, nodeIndex, propertyIndex, animationDef.mProperties);
+ duration = LoadBlendShapeKeyFrames(context, channel, nodeIndex, propertyIndex, animationDefinition);
break;
}
}
}
- animationDef.mDuration = std::max(duration, animationDef.mDuration);
+ animationDefinition.SetDuration(std::max(duration, animationDefinition.GetDuration()));
++propertyIndex;
}
- output.mAnimationDefinitions.push_back(std::move(animationDef));
+ output.mAnimationDefinitions.push_back(std::move(animationDefinition));
}
}
void SetObjectReaders()
{
- json::SetObjectReader(BUFFER_READER);
- json::SetObjectReader(BUFFER_VIEW_READER);
- json::SetObjectReader(BUFFER_VIEW_CLIENT_READER);
- json::SetObjectReader(COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER);
- json::SetObjectReader(ACCESSOR_SPARSE_READER);
- json::SetObjectReader(ACCESSOR_READER);
- json::SetObjectReader(IMAGE_READER);
- json::SetObjectReader(SAMPLER_READER);
- json::SetObjectReader(TEXURE_READER);
- json::SetObjectReader(TEXURE_INFO_READER);
- json::SetObjectReader(MATERIAL_PBR_READER);
- json::SetObjectReader(MATERIAL_SPECULAR_READER);
- json::SetObjectReader(MATERIAL_IOR_READER);
- json::SetObjectReader(MATERIAL_EXTENSION_READER);
- json::SetObjectReader(MATERIAL_READER);
- json::SetObjectReader(MESH_PRIMITIVE_READER);
- json::SetObjectReader(MESH_READER);
- json::SetObjectReader(SKIN_READER);
- json::SetObjectReader(CAMERA_PERSPECTIVE_READER);
- json::SetObjectReader(CAMERA_ORTHOGRAPHIC_READER);
- json::SetObjectReader(CAMERA_READER);
- json::SetObjectReader(NODE_READER);
- json::SetObjectReader(ANIMATION_SAMPLER_READER);
- json::SetObjectReader(ANIMATION_TARGET_READER);
- json::SetObjectReader(ANIMATION_CHANNEL_READER);
- json::SetObjectReader(ANIMATION_READER);
- json::SetObjectReader(SCENE_READER);
+ json::SetObjectReader(GetBufferReader());
+ json::SetObjectReader(GetBufferViewReader());
+ json::SetObjectReader(GetBufferViewClientReader());
+ json::SetObjectReader(GetComponentTypedBufferViewClientReader());
+ json::SetObjectReader(GetAccessorSparseReader());
+ json::SetObjectReader(GetAccessorReader());
+ json::SetObjectReader(GetImageReader());
+ json::SetObjectReader(GetSamplerReader());
+ json::SetObjectReader(GetTextureReader());
+ json::SetObjectReader(GetTextureInfoReader());
+ json::SetObjectReader(GetMaterialPbrReader());
+ json::SetObjectReader(GetMaterialSpecularReader());
+ json::SetObjectReader(GetMaterialIorReader());
+ json::SetObjectReader(GetMaterialExtensionsReader());
+ json::SetObjectReader(GetMaterialReader());
+ json::SetObjectReader(GetMeshPrimitiveReader());
+ json::SetObjectReader(GetMeshReader());
+ json::SetObjectReader(GetSkinReader());
+ json::SetObjectReader(GetCameraPerspectiveReader());
+ json::SetObjectReader(GetCameraOrthographicReader());
+ json::SetObjectReader(GetCameraReader());
+ json::SetObjectReader(GetNodeReader());
+ json::SetObjectReader(GetAnimationSamplerReader());
+ json::SetObjectReader(GetAnimationChannelTargetReader());
+ json::SetObjectReader(GetAnimationChannelReader());
+ json::SetObjectReader(GetAnimationReader());
+ json::SetObjectReader(GetSceneReader());
}
void SetDefaultEnvironmentMap(const gltf2::Document& document, ConversionContext& context)
void ReadDocument(const json_object_s& jsonObject, gltf2::Document& document)
{
- DOCUMENT_READER.Read(jsonObject, document);
+ GetDocumentReader().Read(jsonObject, document);
}
void ReadDocumentFromParsedData(const json_object_s& jsonObject, gltf2::Document& document)
*/
// EXTERNAL INCLUDES
-#include <dali/devel-api/threading/mutex.h>
#include <dali/public-api/common/dali-common.h>
// INTERNAL INCLUDES
return true;
}
-const std::map<std::string, Property::Value (*)(const TreeNode*)> kTypeIds{
- // NONE
- {"boolean", [](const TreeNode* tn) {
- return ReadPrimitiveHelper<bool>(tn, ReadBool);
- }},
- {"float", [](const TreeNode* tn) {
- return ReadPrimitiveHelper<float>(tn, ReadFloat);
- }},
- {"integer", [](const TreeNode* tn) {
- return ReadPrimitiveHelper<int>(tn, ReadInt);
- }},
- {"vector2", ReadVectorHelper<Vector2>},
- {"vector3", ReadVectorHelper<Vector3>},
- {"vector4", ReadVectorHelper<Vector4>},
- {"matrix3", ReadVectorHelper<Matrix3>},
- {"matrix", ReadVectorHelper<Matrix>},
- {"rectangle", [](const TreeNode* tn) {
- Rect<int> value;
- if(ReadQuadHelper<int>(tn, {&value.x, &value.y, &value.width, &value.height}))
- {
- return Property::Value(value);
- }
- return Property::Value();
- }},
- {"rotation", ReadRotationHelper},
- // STRING - not particularly animatable
- // ARRAY - not particularly animatable
- // MAP - not particularly animatable
- {"extents", [](const TreeNode* tn) {
- Extents value;
- if(ReadQuadHelper<uint16_t>(tn, {&value.start, &value.end, &value.top, &value.bottom}))
- {
- return Property::Value(value);
- }
- return Property::Value();
- }},
-};
+const std::map<std::string_view, Property::Value (*)(const TreeNode*)>& GetTypeIds()
+{
+ static const std::map<std::string_view, Property::Value (*)(const TreeNode*)> kTypeIds{
+ // NONE
+ {"boolean", [](const TreeNode* tn) {
+ return ReadPrimitiveHelper<bool>(tn, ReadBool);
+ }},
+ {"float", [](const TreeNode* tn) {
+ return ReadPrimitiveHelper<float>(tn, ReadFloat);
+ }},
+ {"integer", [](const TreeNode* tn) {
+ return ReadPrimitiveHelper<int>(tn, ReadInt);
+ }},
+ {"vector2", ReadVectorHelper<Vector2>},
+ {"vector3", ReadVectorHelper<Vector3>},
+ {"vector4", ReadVectorHelper<Vector4>},
+ {"matrix3", ReadVectorHelper<Matrix3>},
+ {"matrix", ReadVectorHelper<Matrix>},
+ {"rectangle", [](const TreeNode* tn) {
+ Rect<int> value;
+ if(ReadQuadHelper<int>(tn, {&value.x, &value.y, &value.width, &value.height}))
+ {
+ return Property::Value(value);
+ }
+ return Property::Value();
+ }},
+ {"rotation", ReadRotationHelper},
+ // STRING - not particularly animatable
+ // ARRAY - not particularly animatable
+ // MAP - not particularly animatable
+ {"extents", [](const TreeNode* tn) {
+ Extents value;
+ if(ReadQuadHelper<uint16_t>(tn, {&value.start, &value.end, &value.top, &value.bottom}))
+ {
+ return Property::Value(value);
+ }
+ return Property::Value();
+ }},
+ };
+ return kTypeIds;
+}
Property::Value (*const kArrayPropertyProcessors[])(const TreeNode*){
ReadVectorHelper<Matrix>,
auto jsonType = tn.GetChild("type");
if(jsonType && jsonType->GetType() == TreeNode::STRING)
{
- auto iFind = kTypeIds.find(jsonType->GetString());
- if(iFind != kTypeIds.end())
+ auto iFind = GetTypeIds().find(jsonType->GetString());
+ if(iFind != GetTypeIds().end())
{
propValue = iFind->second(tn.GetChild("value"));
}
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/internal/model-components/material-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/rendering/sampler.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-scene3d/internal/model-components/material-modify-observer.h>
+#include <dali-scene3d/public-api/loader/node-definition.h>
+#include <dali-scene3d/public-api/loader/renderer-state.h>
+#include <dali-scene3d/public-api/loader/utils.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Creates Material through type registry
+ */
+BaseHandle Create()
+{
+ return Scene3D::Material::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::Material, Dali::BaseHandle, Create);
+DALI_TYPE_REGISTRATION_END()
+
+static constexpr uint32_t OFFSET_FOR_DIFFUSE_CUBE_TEXTURE = 2u;
+static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u;
+static constexpr uint32_t INVALID_INDEX = 0u;
+static constexpr uint32_t ALPHA_CUTOFF_FLAG = Scene3D::Loader::MaterialDefinition::Flags::SUBSURFACE << 1;
+static constexpr std::string_view THREE_TEX_KEYWORD = "THREE_TEX";
+static constexpr std::string_view GLTF_CHANNELS_KEYWORD = "GLTF_CHANNELS";
+
+enum TextureIndex
+{
+ BASE_COLOR,
+ METALLIC_ROUGHNESS,
+ NORMAL,
+ OCCLUSION,
+ EMISSIVE,
+ SPECULAR,
+ SPECULAR_COLOR,
+ TEXTURE_TYPE_NUMBER,
+};
+
+} // unnamed namespace
+
+MaterialPtr Material::New()
+{
+ MaterialPtr material = new Material();
+
+ material->Initialize();
+
+ return material;
+}
+
+Material::Material()
+: mName(),
+ mModifyFlag(MaterialModifyObserver::ModifyFlag::NONE),
+ mObserverNotifying(false)
+{
+ mAsyncImageLoader = Dali::Toolkit::AsyncImageLoader::New();
+ mAsyncImageLoader.ImageLoadedSignal().Connect(this, &Material::TextureLoadComplete);
+ mTextureInformations.assign(TEXTURE_TYPE_NUMBER, TextureInformation());
+ mTextureInformations[BASE_COLOR].mSemantic = Scene3D::Loader::MaterialDefinition::ALBEDO;
+ // TODO : How we support dli manner
+ mTextureInformations[METALLIC_ROUGHNESS].mSemantic = Scene3D::Loader::MaterialDefinition::METALLIC | Scene3D::Loader::MaterialDefinition::ROUGHNESS |
+ Scene3D::Loader::MaterialDefinition::GLTF_CHANNELS;
+ mTextureInformations[NORMAL].mSemantic = Scene3D::Loader::MaterialDefinition::NORMAL;
+ mTextureInformations[OCCLUSION].mSemantic = Scene3D::Loader::MaterialDefinition::OCCLUSION;
+ mTextureInformations[EMISSIVE].mSemantic = Scene3D::Loader::MaterialDefinition::EMISSIVE;
+ mTextureInformations[SPECULAR].mSemantic = Scene3D::Loader::MaterialDefinition::SPECULAR;
+ mTextureInformations[SPECULAR_COLOR].mSemantic = Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR;
+
+ mTextureInformations[BASE_COLOR].mDefineKeyword = "BASECOLOR_TEX";
+ mTextureInformations[METALLIC_ROUGHNESS].mDefineKeyword = "METALLIC_ROUGHNESS_TEX";
+ mTextureInformations[NORMAL].mDefineKeyword = "NORMAL_TEX";
+ mTextureInformations[OCCLUSION].mDefineKeyword = "OCCLUSION";
+ mTextureInformations[EMISSIVE].mDefineKeyword = "EMISSIVE";
+ mTextureInformations[SPECULAR].mDefineKeyword = "MATERIAL_SPECULAR_TEXTURE";
+ mTextureInformations[SPECULAR_COLOR].mDefineKeyword = "MATERIAL_SPECULAR_COLOR_TEXTURE";
+
+ mTextureInformations[TextureIndex::EMISSIVE].mFactor = Vector4::ZERO;
+}
+
+Material::~Material() = default;
+
+void Material::Initialize()
+{
+}
+
+void Material::SetProperty(Dali::Property::Index index, Dali::Property::Value propertyValue)
+{
+ bool needToApply = true;
+ switch(index)
+ {
+ case Dali::Scene3D::Material::Property::NAME:
+ {
+ std::string name;
+ if(propertyValue.Get(name))
+ {
+ mName = name;
+ }
+ needToApply = false;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::BASE_COLOR_URL:
+ {
+ std::string baseColorUrl;
+ if(propertyValue.Get(baseColorUrl))
+ {
+ RequestTextureLoad(mTextureInformations[TextureIndex::BASE_COLOR], baseColorUrl);
+ needToApply = false;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::BASE_COLOR_FACTOR:
+ {
+ Vector4 baseColorFactor;
+ if(propertyValue.Get(baseColorFactor))
+ {
+ mTextureInformations[TextureIndex::BASE_COLOR].mFactor = baseColorFactor;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::METALLIC_ROUGHNESS_URL:
+ {
+ std::string metallicRoughnessUrl;
+ if(propertyValue.Get(metallicRoughnessUrl))
+ {
+ RequestTextureLoad(mTextureInformations[TextureIndex::METALLIC_ROUGHNESS], metallicRoughnessUrl);
+ needToApply = false;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::METALLIC_FACTOR:
+ {
+ float metallicFactor;
+ if(propertyValue.Get(metallicFactor))
+ {
+ mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.x = metallicFactor;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::ROUGHNESS_FACTOR:
+ {
+ float roughnessFactor;
+ if(propertyValue.Get(roughnessFactor))
+ {
+ mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.y = roughnessFactor;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::NORMAL_URL:
+ {
+ std::string normalUrl;
+ if(propertyValue.Get(normalUrl))
+ {
+ RequestTextureLoad(mTextureInformations[TextureIndex::NORMAL], normalUrl);
+ needToApply = false;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::NORMAL_SCALE:
+ {
+ float normalScale;
+ if(propertyValue.Get(normalScale))
+ {
+ mTextureInformations[TextureIndex::NORMAL].mFactor.x = normalScale;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::OCCLUSION_URL:
+ {
+ std::string occlusionUrl;
+ if(propertyValue.Get(occlusionUrl))
+ {
+ RequestTextureLoad(mTextureInformations[TextureIndex::OCCLUSION], occlusionUrl);
+ needToApply = false;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::OCCLUSION_STRENGTH:
+ {
+ float occlusionStrength;
+ if(propertyValue.Get(occlusionStrength))
+ {
+ mTextureInformations[TextureIndex::OCCLUSION].mFactor.x = occlusionStrength;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::EMISSIVE_URL:
+ {
+ std::string emissiveUrl;
+ if(propertyValue.Get(emissiveUrl))
+ {
+ RequestTextureLoad(mTextureInformations[TextureIndex::EMISSIVE], emissiveUrl);
+ needToApply = false;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::EMISSIVE_FACTOR:
+ {
+ Vector3 emissiveFactor;
+ if(propertyValue.Get(emissiveFactor))
+ {
+ mTextureInformations[TextureIndex::EMISSIVE].mFactor = emissiveFactor;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::ALPHA_MODE:
+ {
+ Dali::Scene3D::Material::AlphaModeType alphaMode;
+ if(propertyValue.Get(alphaMode))
+ {
+ mAlphaMode = alphaMode;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::ALPHA_CUTOFF:
+ {
+ float alphaCutoff;
+ if(propertyValue.Get(alphaCutoff))
+ {
+ mAlphaCutoff = alphaCutoff;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::DOUBLE_SIDED:
+ {
+ bool doubleSided;
+ if(propertyValue.Get(doubleSided))
+ {
+ mDoubleSided = doubleSided;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::IOR:
+ {
+ float ior;
+ if(propertyValue.Get(ior))
+ {
+ mIor = ior;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::SPECULAR_URL:
+ {
+ std::string specularUrl;
+ if(propertyValue.Get(specularUrl))
+ {
+ RequestTextureLoad(mTextureInformations[TextureIndex::SPECULAR], specularUrl);
+ needToApply = false;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::SPECULAR_FACTOR:
+ {
+ float specularFactor;
+ if(propertyValue.Get(specularFactor))
+ {
+ mTextureInformations[TextureIndex::SPECULAR].mFactor.x = specularFactor;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::SPECULAR_COLOR_URL:
+ {
+ std::string specularColorUrl;
+ if(propertyValue.Get(specularColorUrl))
+ {
+ RequestTextureLoad(mTextureInformations[TextureIndex::SPECULAR_COLOR], specularColorUrl);
+ needToApply = false;
+ }
+ break;
+ }
+ case Dali::Scene3D::Material::Property::SPECULAR_COLOR_FACTOR:
+ {
+ Vector3 specularColorFactor;
+ if(propertyValue.Get(specularColorFactor))
+ {
+ mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor = specularColorFactor;
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
+ }
+ break;
+ }
+ }
+
+ if(needToApply)
+ {
+ Apply();
+ }
+}
+
+Dali::Property::Value Material::GetProperty(Dali::Property::Index index) const
+{
+ Dali::Property::Value value;
+ switch(index)
+ {
+ case Dali::Scene3D::Material::Property::NAME:
+ {
+ value = mName;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::BASE_COLOR_URL:
+ {
+ value = mTextureInformations[TextureIndex::BASE_COLOR].mUrl;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::BASE_COLOR_FACTOR:
+ {
+ value = mTextureInformations[TextureIndex::BASE_COLOR].mFactor;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::METALLIC_ROUGHNESS_URL:
+ {
+ value = mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mUrl;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::METALLIC_FACTOR:
+ {
+ value = mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.x;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::ROUGHNESS_FACTOR:
+ {
+ value = mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.y;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::NORMAL_URL:
+ {
+ value = mTextureInformations[TextureIndex::NORMAL].mUrl;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::NORMAL_SCALE:
+ {
+ value = mTextureInformations[TextureIndex::NORMAL].mFactor.x;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::OCCLUSION_URL:
+ {
+ value = mTextureInformations[TextureIndex::OCCLUSION].mUrl;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::OCCLUSION_STRENGTH:
+ {
+ value = mTextureInformations[TextureIndex::OCCLUSION].mFactor.x;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::EMISSIVE_URL:
+ {
+ value = mTextureInformations[TextureIndex::EMISSIVE].mUrl;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::EMISSIVE_FACTOR:
+ {
+ value = Vector3(mTextureInformations[TextureIndex::EMISSIVE].mFactor);
+ break;
+ }
+ case Dali::Scene3D::Material::Property::ALPHA_MODE:
+ {
+ value = mAlphaMode;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::ALPHA_CUTOFF:
+ {
+ value = mAlphaCutoff;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::DOUBLE_SIDED:
+ {
+ value = mDoubleSided;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::IOR:
+ {
+ value = mIor;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::SPECULAR_URL:
+ {
+ value = mTextureInformations[TextureIndex::SPECULAR].mUrl;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::SPECULAR_FACTOR:
+ {
+ value = mTextureInformations[TextureIndex::SPECULAR].mFactor.x;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::SPECULAR_COLOR_URL:
+ {
+ value = mTextureInformations[TextureIndex::SPECULAR_COLOR].mUrl;
+ break;
+ }
+ case Dali::Scene3D::Material::Property::SPECULAR_COLOR_FACTOR:
+ {
+ value = Vector3(mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor);
+ break;
+ }
+ }
+ return value;
+}
+
+void Material::SetTextureInformation(Scene3D::Material::TextureType index, TextureInformation&& textureInformation)
+{
+ mTextureInformations[index].mFactor = textureInformation.mFactor;
+ mTextureInformations[index].mSampler = textureInformation.mSampler;
+ mTextureInformations[index].mTexture = textureInformation.mTexture;
+ mTextureInformations[index].mUrl = std::move(textureInformation.mUrl);
+}
+
+void Material::SetTexture(Scene3D::Material::TextureType index, Dali::Texture texture)
+{
+ if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
+ {
+ if(mTextureInformations[index].mTexture != texture)
+ {
+ if(mTextureInformations[index].mLoadingTaskId != INVALID_INDEX)
+ {
+ mAsyncImageLoader.Cancel(mTextureInformations[index].mLoadingTaskId);
+ mTextureInformations[index].mLoadingTaskId = INVALID_INDEX;
+ }
+ mTextureInformations[index].mTexture = texture;
+ if(IsResourceReady())
+ {
+ ResourcesLoadComplete();
+ }
+ }
+ }
+}
+
+Dali::Texture Material::GetTexture(Scene3D::Material::TextureType index)
+{
+ if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
+ {
+ return mTextureInformations[index].mTexture;
+ }
+ return Dali::Texture();
+}
+
+TextureSet Material::GetTextureSet()
+{
+ TextureSet textures = TextureSet::New();
+ for(uint32_t i = 0, count = 0; i < TEXTURE_TYPE_NUMBER; ++i)
+ {
+ if(!mTextureInformations[i].mTexture)
+ {
+ continue;
+ }
+ textures.SetTexture(count, mTextureInformations[i].mTexture);
+ Sampler sampler = mTextureInformations[i].mSampler;
+ if(!sampler)
+ {
+ auto samplerFlag = Scene3D::Loader::SamplerFlags::FILTER_LINEAR | (Scene3D::Loader::SamplerFlags::FILTER_LINEAR << Scene3D::Loader::SamplerFlags::FILTER_MAG_SHIFT) |
+ (Scene3D::Loader::SamplerFlags::WRAP_REPEAT << Scene3D::Loader::SamplerFlags::WRAP_S_SHIFT) | (Scene3D::Loader::SamplerFlags::WRAP_REPEAT << Scene3D::Loader::SamplerFlags::WRAP_T_SHIFT);
+ sampler = Scene3D::Loader::SamplerFlags::MakeSampler(samplerFlag);
+ }
+ textures.SetSampler(count, sampler);
+ count++;
+ }
+ return textures;
+}
+
+void Material::SetSampler(Scene3D::Material::TextureType index, Dali::Sampler sampler)
+{
+ if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
+ {
+ mTextureInformations[index].mSampler = sampler;
+ }
+}
+
+Dali::Sampler Material::GetSampler(Scene3D::Material::TextureType index)
+{
+ if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
+ {
+ return mTextureInformations[index].mSampler;
+ }
+ return Dali::Sampler();
+}
+
+std::string Material::GetVertexShader()
+{
+ return mShaderData.mVertexShaderSource;
+}
+
+std::string Material::GetFragmentShader()
+{
+ return mShaderData.mFragmentShaderSource;
+}
+
+void Material::Apply()
+{
+ if(IsResourceReady())
+ {
+ UpdateMaterialData();
+ NotifyObserver();
+ return;
+ }
+ // The cases this material is applied to primitive are,
+ // 1. material is added on Primitive.
+ // When material is added on Primitive (1 case)
+ // 1-1. when IsResourceReady() returns true,
+ // Primitive can takes information from Material
+ // 1-2. if false.
+ // Material will noti to primitives when all resources are ready.
+ // 2. Some properties are changed
+ // 2-1. when IsResourceReady() returns true,
+ // Call NotifyObserver directly.
+ // 2-2. if false.
+ // Material will noti to primitives when all resources are ready.
+}
+
+void Material::AddObserver(MaterialModifyObserver* observer)
+{
+ for(auto& observerEntity : mObservers)
+ {
+ if(observerEntity.first == observer)
+ {
+ observerEntity.second = true;
+ return;
+ }
+ }
+ mObservers.push_back({observer, true});
+}
+
+void Material::RemoveObserver(MaterialModifyObserver* observer)
+{
+ // Block during notifying to observer
+ if(mObserverNotifying)
+ {
+ for(uint32_t i = 0; i < mObservers.size(); ++i)
+ {
+ if(mObservers[i].first == observer)
+ {
+ mObservers[i].second = false;
+ return;
+ }
+ }
+ }
+ else
+ {
+ for(uint32_t i = 0; i < mObservers.size(); ++i)
+ {
+ if(mObservers[i].first == observer)
+ {
+ mObservers.erase(mObservers.begin() + i);
+ return;
+ }
+ }
+ }
+}
+
+void Material::UpdateMaterialData()
+{
+ uint32_t materialFlag = 0u;
+ if(mAlphaMode == Dali::Scene3D::Material::AlphaModeType::BLEND)
+ {
+ mIsOpaque = false;
+ mIsMask = false;
+ materialFlag |= Scene3D::Loader::MaterialDefinition::TRANSPARENCY;
+ }
+ else if(mAlphaMode == Dali::Scene3D::Material::AlphaModeType::MASK)
+ {
+ mIsOpaque = true;
+ mIsMask = true;
+ }
+ const bool hasTransparency = MaskMatch(materialFlag, Scene3D::Loader::MaterialDefinition::TRANSPARENCY);
+
+ for(auto&& textureInformation : mTextureInformations)
+ {
+ if(!textureInformation.mTexture)
+ {
+ continue;
+ }
+ materialFlag |= textureInformation.mSemantic;
+ }
+
+ if(mMaterialFlag != materialFlag || mShaderData.mVertexShaderSource.empty() || mShaderData.mFragmentShaderSource.empty())
+ {
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::SHADER;
+
+ mMaterialFlag = materialFlag;
+ mShaderData.mVertexShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data();
+ mShaderData.mFragmentShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
+
+ std::vector<std::string> defines;
+ defines.push_back(THREE_TEX_KEYWORD.data());
+ for(auto&& textureInformation : mTextureInformations)
+ {
+ if(!textureInformation.mTexture)
+ {
+ continue;
+ }
+ defines.push_back(textureInformation.mDefineKeyword);
+ }
+ defines.push_back(GLTF_CHANNELS_KEYWORD.data());
+
+ for(const auto& define : defines)
+ {
+ Scene3D::Loader::ShaderDefinition::ApplyDefine(mShaderData.mFragmentShaderSource, define);
+ }
+ }
+
+ // Finish to make all the material flag according to the gltf2-util.
+ // Then make defines as fallowing shader-definition-factory.
+
+ // The renderer State below can be used in primitive to set renderer properties.
+
+ // for renderer setting
+ mRendererState = Scene3D::Loader::RendererState::DEPTH_TEST;
+ if(!mDoubleSided)
+ {
+ mRendererState |= Scene3D::Loader::RendererState::CULL_BACK;
+ }
+
+ if(hasTransparency)
+ {
+ mRendererState = (mRendererState | Scene3D::Loader::RendererState::ALPHA_BLEND);
+ }
+}
+
+bool Material::IsResourceReady()
+{
+ for(auto&& textureInformation : mTextureInformations)
+ {
+ if(!textureInformation.IsReady())
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+void Material::SetRendererUniform(Dali::Renderer renderer)
+{
+ renderer.RegisterProperty("uColorFactor", mTextureInformations[TextureIndex::BASE_COLOR].mFactor);
+ renderer.RegisterProperty("uMetallicFactor", mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.x);
+ renderer.RegisterProperty("uRoughnessFactor", mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.y);
+ renderer.RegisterProperty("uNormalScale", mTextureInformations[TextureIndex::NORMAL].mFactor.x);
+ if(mTextureInformations[TextureIndex::OCCLUSION].mTexture)
+ {
+ renderer.RegisterProperty("uOcclusionStrength", mTextureInformations[TextureIndex::OCCLUSION].mFactor.x);
+ }
+ renderer.RegisterProperty("uEmissiveFactor", Vector3(mTextureInformations[TextureIndex::EMISSIVE].mFactor));
+ float dielectricSpecular = (Dali::Equals(mIor, -1.0)) ? 0.04f : powf((mIor - 1.0f) / (mIor + 1.0f), 2.0f);
+ renderer.RegisterProperty("uDielectricSpecular", dielectricSpecular);
+ renderer.RegisterProperty("uSpecularFactor", mTextureInformations[TextureIndex::SPECULAR].mFactor.x);
+ renderer.RegisterProperty("uSpecularColorFactor", Vector3(mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor));
+
+ float opaque = mIsOpaque ? 1.0f : 0.0f;
+ float mask = mIsMask ? 1.0f : 0.0f;
+ renderer.RegisterProperty("uOpaque", opaque);
+ renderer.RegisterProperty("uMask", mask);
+ renderer.RegisterProperty("uAlphaThreshold", mAlphaCutoff);
+
+ renderer.RegisterProperty("uCubeMatrix", Matrix::IDENTITY);
+
+ renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), 6.f);
+ renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), 1.0f);
+ renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblYDirectionUniformName().data(), Vector3(1.0f, -1.0, 1.0));
+
+ Scene3D::Loader::RendererState::Apply(mRendererState, renderer);
+}
+
+uint32_t Material::GetSpecularImageBasedLightTextureOffset()
+{
+ return OFFSET_FOR_SPECULAR_CUBE_TEXTURE;
+}
+
+uint32_t Material::GetDiffuseImageBasedLightTextureOffset()
+{
+ return OFFSET_FOR_DIFFUSE_CUBE_TEXTURE;
+}
+
+std::string_view Material::GetImageBasedLightScaleFactorName()
+{
+ return Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName();
+}
+
+std::string_view Material::GetImageBasedLightMaxLodUniformName()
+{
+ return Dali::Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName();
+}
+
+void Material::ResetFlag()
+{
+ mModifyFlag = MaterialModifyObserver::ModifyFlag::NONE;
+}
+
+void Material::NotifyObserver()
+{
+ if(mModifyFlag != MaterialModifyObserver::ModifyFlag::NONE && IsResourceReady())
+ {
+ if(mObserverNotifying)
+ {
+ DALI_LOG_ERROR("Notify during observing is not allowed.");
+ return;
+ }
+
+ Dali::Scene3D::Material handle(this); // Keep itself's life during notify
+
+ // Copy the flag due to the flag can be changed during observe.
+ MaterialModifyObserver::ModifyFlag copiedFlag = mModifyFlag;
+ mModifyFlag = MaterialModifyObserver::ModifyFlag::NONE;
+
+ // Need to block mObserver container change during observe
+ mObserverNotifying = true;
+ for(uint32_t i = 0; i < mObservers.size(); ++i)
+ {
+ if(mObservers[i].second)
+ {
+ mObservers[i].first->OnMaterialModified(handle, copiedFlag);
+ }
+ }
+ mObserverNotifying = false;
+
+ // Resolve observer queue during notify
+ mObservers.erase(std::remove_if(mObservers.begin(), mObservers.end(), [](auto& e) { return !e.second; }), mObservers.end());
+ }
+}
+
+void Material::RequestTextureLoad(TextureInformation& textureInformation, const std::string& url)
+{
+ if(textureInformation.mUrl == url)
+ {
+ return;
+ }
+
+ textureInformation.mUrl = url;
+ if(textureInformation.mLoadingTaskId != INVALID_INDEX)
+ {
+ mAsyncImageLoader.Cancel(textureInformation.mLoadingTaskId);
+ textureInformation.mLoadingTaskId = INVALID_INDEX;
+ }
+
+ if(url.empty())
+ {
+ textureInformation.mTexture.Reset();
+ return;
+ }
+ textureInformation.mLoadingTaskId = mAsyncImageLoader.Load(url);
+}
+
+void Material::TextureLoadComplete(uint32_t loadedTaskId, PixelData pixelData)
+{
+ for(auto&& textureInformation : mTextureInformations)
+ {
+ if(textureInformation.mLoadingTaskId != loadedTaskId)
+ {
+ continue;
+ }
+
+ if(pixelData)
+ {
+ textureInformation.mTexture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
+ textureInformation.mTexture.Upload(pixelData);
+ }
+ textureInformation.mLoadingTaskId = INVALID_INDEX;
+ break;
+ }
+
+ if(IsResourceReady())
+ {
+ ResourcesLoadComplete();
+ }
+}
+
+void Material::ResourcesLoadComplete()
+{
+ mModifyFlag |= MaterialModifyObserver::ModifyFlag::TEXTURE;
+ Apply();
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_IMPL_H
+#define DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_IMPL_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/public-api/image-loader/async-image-loader.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/rendering/texture.h>
+#include <set>
+#include <utility>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/material-modify-observer.h>
+#include <dali-scene3d/public-api/loader/material-definition.h>
+#include <dali-scene3d/public-api/loader/shader-definition.h>
+#include <dali-scene3d/public-api/model-components/material.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+using MaterialPtr = IntrusivePtr<Material>;
+
+/**
+ * @brief This is the internal base class for Material of model.
+ *
+ * @SINCE_2_2.99
+ */
+class Material : public BaseObject, public ConnectionTracker
+{
+private:
+ using ObserverContainer = std::vector<std::pair<MaterialModifyObserver*, bool>>;
+
+public:
+ /**
+ * @brief Pair of texture handle and it's own scale factor. Texture handle can be empty
+ */
+ struct TextureInformation
+ {
+ bool IsReady()
+ {
+ return mLoadingTaskId == 0u;
+ }
+
+ std::string mUrl;
+ Dali::Texture mTexture;
+ Vector4 mFactor{Vector4::ONE};
+ Dali::Sampler mSampler;
+ uint32_t mLoadingTaskId{0u};
+ uint32_t mSemantic;
+ std::string mDefineKeyword;
+ };
+
+ using TextureInformationContainer = std::vector<TextureInformation>;
+
+public:
+ // Creation & Destruction
+ /**
+ * @brief Create a new Material object.
+ * @return A smart-pointer to the newly allocated Material.
+ */
+ static MaterialPtr New();
+
+protected:
+ /**
+ * @brief Construct a new Material.
+ */
+ Material();
+
+ /**
+ * @brief Second-phase constructor.
+ */
+ void Initialize();
+
+ /**
+ * @brief Virtual destructor.
+ */
+ virtual ~Material();
+
+public:
+ /**
+ * @copydoc Dali::Scene3D::Material::SetProperty()
+ */
+ void SetProperty(Dali::Property::Index index, Dali::Property::Value propertyValue);
+
+ /**
+ * @copydoc Dali::Scene3D::Material::GetProperty()
+ */
+ Dali::Property::Value GetProperty(Dali::Property::Index index) const;
+
+ /**
+ * @brief Set a texture information for the material.
+ *
+ * @param[in] index The index of the texture to set.
+ * @param[in] textureInformation The texture information to set.
+ *
+ * @note This function moves the value of textureInformation.
+ */
+ void SetTextureInformation(Scene3D::Material::TextureType index, TextureInformation&& textureInformation);
+
+ /**
+ * @brief Set a texture for the material.
+ *
+ * @param[in] index The index of the texture to set.
+ * @param[in] texture The texture to set.
+ */
+ void SetTexture(Scene3D::Material::TextureType index, Dali::Texture texture);
+
+ /**
+ * @brief Get texture for the material.
+ *
+ * @param[in] index The index of the texture to get.
+ *
+ * @return The texture at the given index.
+ */
+ Dali::Texture GetTexture(Scene3D::Material::TextureType index);
+
+ /**
+ * @brief Get the texture set for this material.
+ *
+ * @return The texture set for this material.
+ */
+ TextureSet GetTextureSet();
+
+ /**
+ * @brief Set a sampler for the material.
+ *
+ * @param[in] index The index of the sampler to set.
+ * @param[in] sampler The sampler to set.
+ */
+ void SetSampler(Scene3D::Material::TextureType index, Dali::Sampler sampler);
+
+ /**
+ * @brief Get a sampler for the material.
+
+ * @param[in] index The index of the sampler to get.
+ *
+ * @return The sampler at the given index.
+ */
+ Dali::Sampler GetSampler(Scene3D::Material::TextureType index);
+
+ /**
+ * @brief Get vertex shader code for this material.
+ *
+ * @return Vertex shader code for this material.
+ */
+ std::string GetVertexShader();
+
+ /**
+ * @brief Get fragment shader code for this material.
+ *
+ * @return Fragment shader code for this material.
+ */
+ std::string GetFragmentShader();
+
+public:
+ /**
+ * @brief Add observer to this material.
+ *
+ * @param[in] observer Pointer of observer.
+ */
+ void AddObserver(MaterialModifyObserver* observer);
+
+ /**
+ * @brief Remove observer from this material.
+ *
+ * @param[in] observer Pointer of observer.
+ */
+ void RemoveObserver(MaterialModifyObserver* observer);
+
+ /**
+ * @brief Update material data.
+ */
+ void UpdateMaterialData();
+
+ /**
+ * @brief Set uniform value to the Renderer.
+ *
+ * @param[in] renderer Renderer object.
+ */
+ void SetRendererUniform(Dali::Renderer renderer);
+
+ /**
+ * @brief Get specular image based light texture offset.
+ *
+ * @return Specular image based light texture offset.
+ */
+ uint32_t GetSpecularImageBasedLightTextureOffset();
+
+ /**
+ * @brief Get diffuse image based light texture offset.
+ *
+ * @return Diffuse image based light texture offset.
+ */
+ uint32_t GetDiffuseImageBasedLightTextureOffset();
+
+ /**
+ * @brief Get image based light scale factor name.
+ *
+ * @return Image based light scale factor name.
+ */
+ std::string_view GetImageBasedLightScaleFactorName();
+
+ /**
+ * @brief Get image based light max lod uniform name.
+ *
+ * @return Image based light max lod uniform name.
+ */
+ std::string_view GetImageBasedLightMaxLodUniformName();
+
+ /**
+ * @brief Check if resource is ready.
+ *
+ * @return True if resource is ready, false otherwise.
+ */
+ bool IsResourceReady();
+
+ /**
+ * @brief Reset dirty flag of this material.
+ */
+ void ResetFlag();
+
+private:
+ /**
+ * @brief Check modify flag and send observers the material changeness.
+ * It will clean up modify flag
+ */
+ void NotifyObserver();
+
+ /**
+ * @brief Request loading an image from a URL and store it in TextureInformation.
+ *
+ * @param[in] textureInformation TextureInformation object to store loaded texture information.
+ * @param[in] url URL of the image to load.
+ */
+ void RequestTextureLoad(TextureInformation& textureInformation, const std::string& url);
+
+ /**
+ * @brief Called when loading requested by RequestTextureLoad is complete.
+ *
+ * @param[in] loadedTaskId ID of the loaded texture.
+ * @param[in] pixelData PixelData of the loaded texture.
+ */
+ void TextureLoadComplete(uint32_t loadedTaskId, PixelData pixelData);
+
+ /**
+ * @brief Called when all requested textures are loaded.
+ */
+ void ResourcesLoadComplete();
+
+ /**
+ * @brief Update the material using each attribute of this material and send a notification to the ModelPrimitive class.
+ */
+ void Apply();
+
+private:
+ // Delete copy & move operator
+ Material(const Material&) = delete;
+ Material(Material&&) = delete;
+ Material& operator=(const Material& rhs) = delete;
+ Material& operator=(Material&& rhs) = delete;
+
+private:
+ ObserverContainer mObservers{}; ///< List of observers who need to be notified after some properties are changed.
+
+ TextureInformationContainer mTextureInformations;
+ Dali::Toolkit::AsyncImageLoader mAsyncImageLoader;
+
+ std::string mName; ///< Material name
+ Dali::Scene3D::Material::AlphaModeType mAlphaMode = Scene3D::Material::AlphaModeType::OPAQUE; ///< Alpha mode
+ float mAlphaCutoff = 0.5f; ///< Alpha cutoff value
+ bool mDoubleSided = false; ///< Whether to render both sides
+ float mIor = -1.0f; ///< Index of refraction (TODO: Magic number)
+ MaterialModifyObserver::ModifyFlag mModifyFlag = MaterialModifyObserver::ModifyFlag::NONE; ///< Modified dirty flags
+
+ Scene3D::Loader::ShaderDefinition::RawData mShaderData;
+
+ uint32_t mMaterialFlag = 0u;
+ Scene3D::Loader::RendererState::Type mRendererState = Scene3D::Loader::RendererState::NONE;
+
+ bool mIsOpaque = true;
+ bool mIsMask = false;
+ bool mObserverNotifying; ///< True if observe is notify now. If then, we should not change the mObservers.
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::Material& GetImplementation(Dali::Scene3D::Material& material)
+{
+ DALI_ASSERT_ALWAYS(material && "Material handle is empty");
+
+ BaseObject& handle = material.GetBaseObject();
+
+ return static_cast<Internal::Material&>(handle);
+}
+
+inline const Internal::Material& GetImplementation(const Dali::Scene3D::Material& material)
+{
+ DALI_ASSERT_ALWAYS(material && "Material handle is empty");
+
+ const BaseObject& handle = material.GetBaseObject();
+
+ return static_cast<const Internal::Material&>(handle);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_IMPL_H
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_MODIFY_OBSERVER_H
+#define DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_MODIFY_OBSERVER_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/common/bitwise-enum.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/model-components/material.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+/**
+ * @brief MaterialModifyObserver is a class to notify that the material has changed.
+ */
+class MaterialModifyObserver
+{
+public:
+ /**
+ * @brief Flag which informations are changed.
+ */
+ enum ModifyFlag
+ {
+ NONE = 0,
+ TEXTURE = 1 << 0,
+ SHADER = 1 << 1,
+ UNIFORM = 1 << 2,
+ };
+
+ /**
+ * @brief Notify to observers that texture is changed.
+ *
+ * @param[in] material The handle material itself. TODO : Are we need this?
+ * @param[in] flag Flag which informations are changed.
+ */
+ virtual void OnMaterialModified(Dali::Scene3D::Material material, ModifyFlag flag) = 0;
+};
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+// specialization has to be done in the same namespace
+template<>
+struct EnableBitMaskOperators<Scene3D::Internal::MaterialModifyObserver::ModifyFlag>
+{
+ static const bool ENABLE = true;
+};
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_MODIFY_OBSERVER_H
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/internal/model-components/model-node-data-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/model-primitive-impl.h>
+#include <dali-scene3d/public-api/model-components/model-node.h>
+
+namespace
+{
+} // namespace
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Creates control through type registry
+ */
+BaseHandle Create()
+{
+ return Scene3D::ModelNode::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelNode, Dali::CustomActor, Create);
+DALI_TYPE_REGISTRATION_END()
+} // unnamed namespace
+
+ModelNode::Impl::Impl(ModelNode& modelNodeImpl)
+: mModelNodeImpl(modelNodeImpl)
+{
+}
+
+ModelNode::Impl::~Impl()
+{
+ for(auto&& primitive : mModelPrimitiveContainer)
+ {
+ GetImplementation(primitive).RemovePrimitiveObserver(this);
+ }
+ for(auto&& boneData : mBoneDataContainer)
+ {
+ boneData.primitive.Reset();
+ if(boneData.constraint)
+ {
+ boneData.constraint.Remove();
+ boneData.constraint.Reset();
+ }
+ }
+}
+
+void ModelNode::Impl::OnSceneConnection(int depth)
+{
+}
+
+void ModelNode::Impl::OnSceneDisconnection()
+{
+}
+
+void ModelNode::Impl::OnRendererCreated(Renderer renderer)
+{
+ mModelNodeImpl.Self().AddRenderer(renderer);
+}
+
+// Public Method
+
+void ModelNode::Impl::AddModelPrimitive(Scene3D::ModelPrimitive modelPrimitive)
+{
+ for(auto&& primitive : mModelPrimitiveContainer)
+ {
+ if(primitive == modelPrimitive)
+ {
+ return;
+ }
+ }
+
+ mModelPrimitiveContainer.push_back(modelPrimitive);
+
+ Actor self = mModelNodeImpl.Self();
+
+ GetImplementation(modelPrimitive).AddPrimitiveObserver(this);
+ if(mDiffuseTexture && mSpecularTexture)
+ {
+ GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
+ }
+
+ Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
+ if(renderer)
+ {
+ uint32_t rendererCount = self.GetRendererCount();
+ bool exist = false;
+ for(uint32_t i = 0; i < rendererCount; ++i)
+ {
+ if(renderer == self.GetRendererAt(i))
+ {
+ exist = true;
+ break;
+ }
+ }
+ if(!exist)
+ {
+ self.AddRenderer(renderer);
+ }
+ }
+}
+
+void ModelNode::Impl::RemoveModelPrimitive(Scene3D::ModelPrimitive modelPrimitive)
+{
+ uint32_t primitiveCount = GetModelPrimitiveCount();
+ for(uint32_t i = 0; i < primitiveCount; ++i)
+ {
+ if(mModelPrimitiveContainer[i] != modelPrimitive)
+ {
+ continue;
+ }
+ RemoveModelPrimitive(i);
+ break;
+ }
+}
+
+void ModelNode::Impl::RemoveModelPrimitive(uint32_t index)
+{
+ if(index >= mModelPrimitiveContainer.size())
+ {
+ return;
+ }
+
+ Actor self = mModelNodeImpl.Self();
+ GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
+
+ Dali::Renderer renderer = GetImplementation(mModelPrimitiveContainer[index]).GetRenderer();
+ if(renderer)
+ {
+ self.RemoveRenderer(renderer);
+ }
+
+ mModelPrimitiveContainer.erase(mModelPrimitiveContainer.begin() + index);
+}
+
+Scene3D::ModelPrimitive ModelNode::Impl::GetModelPrimitive(uint32_t index) const
+{
+ if(index < mModelPrimitiveContainer.size())
+ {
+ return mModelPrimitiveContainer[index];
+ }
+ return Scene3D::ModelPrimitive();
+}
+
+void ModelNode::Impl::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
+{
+ mDiffuseTexture = diffuseTexture;
+ mSpecularTexture = specularTexture;
+ mIblScaleFactor = iblScaleFactor;
+ mSpecularMipmapLevels = specularMipmapLevels;
+ for(auto&& primitive : mModelPrimitiveContainer)
+ {
+ GetImplementation(primitive).SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
+ }
+}
+
+void ModelNode::Impl::SetImageBasedLightScaleFactor(float iblScaleFactor)
+{
+ mIblScaleFactor = iblScaleFactor;
+ for(auto&& primitive : mModelPrimitiveContainer)
+ {
+ GetImplementation(primitive).SetImageBasedLightScaleFactor(iblScaleFactor);
+ }
+}
+
+void ModelNode::Impl::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
+{
+ GetImplementation(primitive).SetBlendShapeData(data);
+}
+
+void ModelNode::Impl::SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex)
+{
+ Dali::Scene3D::Loader::Skinning::BoneData boneData;
+ boneData.primitive = primitive;
+ boneData.boneIndex = boneIndex;
+ char propertyNameBuffer[32];
+ snprintf(propertyNameBuffer, sizeof(propertyNameBuffer), "%s[%d]", Dali::Scene3D::Loader::Skinning::BONE_UNIFORM_NAME, boneIndex);
+ boneData.propertyName = propertyNameBuffer;
+ boneData.inverseMatrix = inverseMatrix;
+ mBoneDataContainer.push_back(std::move(boneData));
+
+ UpdateBoneMatrix(primitive);
+}
+
+void ModelNode::Impl::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive)
+{
+ for(auto&& boneData : mBoneDataContainer)
+ {
+ if(boneData.primitive != primitive)
+ {
+ continue;
+ }
+
+ Dali::Renderer renderer = GetImplementation(primitive).GetRenderer();
+ if(!renderer)
+ {
+ continue;
+ }
+
+ Dali::Shader shader = renderer.GetShader();
+ if(!shader)
+ {
+ continue;
+ }
+
+ if(boneData.constraint)
+ {
+ boneData.constraint.Remove();
+ boneData.constraint.Reset();
+ }
+
+ if(shader.GetPropertyIndex(boneData.propertyName) == Property::INVALID_INDEX)
+ {
+ auto propBoneXform = shader.RegisterProperty(boneData.propertyName, Matrix{false});
+
+ Matrix inverseMatrix = boneData.inverseMatrix;
+ // Constrain bone matrix to joint transform.
+ boneData.constraint = Constraint::New<Matrix>(shader, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs)
+ { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); });
+
+ Actor joint = mModelNodeImpl.Self();
+ auto propJointMatrix = joint.GetPropertyIndex(Dali::Scene3D::Loader::Skinning::JOINT_MATRIX);
+ boneData.constraint.AddSource(Source{joint, propJointMatrix});
+ boneData.constraint.Apply();
+ }
+ break;
+ }
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_DATA_IMPL_H
+#define DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_DATA_IMPL_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/animation/constraints.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/object/type-registry.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/model-node-impl.h>
+#include <dali-scene3d/internal/model-components/model-primitive-modify-observer.h>
+#include <dali-scene3d/public-api/loader/skinning-details.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+/**
+ * @brief Holds the Implementation for the internal model node class
+ */
+class ModelNode::Impl : public ModelPrimitiveModifyObserver
+{
+public:
+ using ModelPrimitiveContainer = std::vector<Scene3D::ModelPrimitive>;
+ using BoneDataContainer = std::vector<Dali::Scene3D::Loader::Skinning::BoneData>;
+
+ /**
+ * @brief Constructor.
+ * @param[in] modelNodeImpl The control which owns this implementation
+ */
+ Impl(ModelNode& modelNodeImpl);
+
+ /**
+ * @brief Destructor.
+ */
+ ~Impl();
+
+public:
+ /**
+ * @copydoc Dali::Scene3D::Internal::ModelNode::OnSceneConnection()
+ */
+ void OnSceneConnection(int depth);
+
+ /**
+ * @copydoc Dali::Scene3D::Internal::ModelNode::OnSceneConnection()
+ */
+ void OnSceneDisconnection();
+
+public: // Public Method
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::GetModelPrimitiveCount()
+ */
+ inline uint32_t GetModelPrimitiveCount() const
+ {
+ return static_cast<uint32_t>(mModelPrimitiveContainer.size());
+ }
+
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::AddModelPrimitive()
+ */
+ void AddModelPrimitive(Scene3D::ModelPrimitive modelPrimitive);
+
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::RemoveModelPrimitive()
+ */
+ void RemoveModelPrimitive(Scene3D::ModelPrimitive modelPrimitive);
+
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::RemoveModelPrimitive()
+ */
+ void RemoveModelPrimitive(uint32_t index);
+
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::GetModelPrimitive()
+ */
+ Scene3D::ModelPrimitive GetModelPrimitive(uint32_t index) const;
+
+ /**
+ * @brief Sets the diffuse and specular image-based lighting textures for a ModelPrimitive.
+ *
+ * @param[in] diffuseTexture The diffuse texture.
+ * @param[in] specularTexture The specular texture.
+ * @param[in] iblScaleFactor The scale factor for the image-based lighting.
+ * @param[in] specularMipmapLevels The number of mipmap levels for the specular texture.
+ */
+ void SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels);
+
+ /**
+ * @brief Sets the scale factor for image-based lighting.
+ *
+ * @param[in] iblScaleFactor The scale factor for image-based lighting.
+ */
+ void SetImageBasedLightScaleFactor(float iblScaleFactor);
+
+ /**
+ * @brief Sets the blend shape data for a ModelPrimitive.
+ *
+ * @param[in] data The blend shape data.
+ * @param[in] primitive The ModelPrimitive to set the blend shape data for.
+ */
+ void SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive);
+
+ /**
+ * @brief Sets the bone matrix for a ModelPrimitive and bone index.
+ *
+ * @param[in] inverseMatrix The inverse matrix of the bone.
+ * @param[in] primitive The ModelPrimitive to set the bone matrix for.
+ * @param[in] boneIndex The index of the bone to set the matrix for.
+ */
+ void SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex);
+
+ /**
+ * @brief Called when a Renderer of ModelPrimitive is created.
+ *
+ * @param[in] renderer The Renderer that is created.
+ */
+ void OnRendererCreated(Renderer renderer) override;
+
+private:
+ /**
+ * @brief Updates the bone matrix for a ModelPrimitive.
+ *
+ * @param[in] primitive The ModelPrimitive to set the bone matrix for.
+ */
+ void UpdateBoneMatrix(Scene3D::ModelPrimitive primitive);
+
+private:
+ ModelNode& mModelNodeImpl; ///< Owner of this data
+ ModelPrimitiveContainer mModelPrimitiveContainer; ///< List of model primitives
+ BoneDataContainer mBoneDataContainer;
+ Dali::Texture mSpecularTexture;
+ Dali::Texture mDiffuseTexture;
+ float mIblScaleFactor{1.0f};
+ uint32_t mSpecularMipmapLevels{1u};
+};
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_DATA_IMPL_H
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/internal/model-components/model-node-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/model-node-data-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+Dali::Scene3D::ModelNode ModelNode::New()
+{
+ // Create the implementation, temporarily owned on stack
+ IntrusivePtr<ModelNode> nodeImpl = new ModelNode();
+
+ // Pass ownership to handle
+ Scene3D::ModelNode handle(*nodeImpl);
+
+ // Second-phase init of the implementation
+ // This can only be done after the CustomActor connection has been made...
+ nodeImpl->Initialize();
+
+ return handle;
+}
+
+ModelNode::ModelNode()
+: CustomActorImpl(ActorFlags::DISABLE_SIZE_NEGOTIATION),
+ mImpl(new Impl(*this))
+{
+}
+
+ModelNode::~ModelNode()
+{
+}
+
+void ModelNode::Initialize()
+{
+ OnInitialize();
+}
+
+void ModelNode::OnInitialize()
+{
+}
+
+void ModelNode::OnSceneConnection(int depth)
+{
+ mImpl->OnSceneConnection(depth);
+}
+
+void ModelNode::OnSceneDisconnection()
+{
+ mImpl->OnSceneDisconnection();
+}
+
+void ModelNode::OnChildAdd(Actor& child)
+{
+}
+
+void ModelNode::OnChildRemove(Actor& child)
+{
+}
+
+void ModelNode::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
+{
+}
+
+void ModelNode::OnSizeSet(const Vector3& targetSize)
+{
+}
+
+void ModelNode::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
+{
+ // @todo size negotiate background to new size, animate as well?
+}
+
+void ModelNode::OnRelayout(const Vector2& size, RelayoutContainer& container)
+{
+}
+
+void ModelNode::OnSetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
+{
+}
+
+Vector3 ModelNode::GetNaturalSize()
+{
+ return Vector3::ZERO;
+}
+
+float ModelNode::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
+{
+ return 0.0f;
+}
+
+float ModelNode::GetHeightForWidth(float width)
+{
+ return 0.0f;
+}
+
+float ModelNode::GetWidthForHeight(float height)
+{
+ return 0.0f;
+}
+
+bool ModelNode::RelayoutDependentOnChildren(Dimension::Type dimension)
+{
+ return false;
+}
+
+void ModelNode::OnCalculateRelayoutSize(Dimension::Type dimension)
+{
+}
+
+void ModelNode::OnLayoutNegotiated(float size, Dimension::Type dimension)
+{
+}
+
+ModelNode& GetImplementation(Dali::Scene3D::ModelNode& handle)
+{
+ CustomActorImpl& customInterface = handle.GetImplementation();
+ ModelNode& impl = dynamic_cast<Internal::ModelNode&>(customInterface);
+ return impl;
+}
+
+const ModelNode& GetImplementation(const Dali::Scene3D::ModelNode& handle)
+{
+ const CustomActorImpl& customInterface = handle.GetImplementation();
+ // downcast to control
+ const ModelNode& impl = dynamic_cast<const Internal::ModelNode&>(customInterface);
+ return impl;
+}
+
+// Public Method
+
+uint32_t ModelNode::GetModelPrimitiveCount() const
+{
+ return mImpl->GetModelPrimitiveCount();
+}
+
+void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
+{
+ mImpl->AddModelPrimitive(modelPrimitive);
+}
+
+void ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
+{
+ mImpl->RemoveModelPrimitive(modelPrimitive);
+}
+
+void ModelNode::RemoveModelPrimitive(uint32_t index)
+{
+ mImpl->RemoveModelPrimitive(index);
+}
+
+Dali::Scene3D::ModelPrimitive ModelNode::GetModelPrimitive(uint32_t index) const
+{
+ return mImpl->GetModelPrimitive(index);
+}
+
+Scene3D::ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName)
+{
+ Actor childActor = Self().FindChildByName(nodeName);
+ return Scene3D::ModelNode::DownCast(childActor);
+}
+
+void ModelNode::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
+{
+ mImpl->SetImageBasedLightTexture(diffuseTexture, specularTexture, iblScaleFactor, specularMipmapLevels);
+}
+
+void ModelNode::SetImageBasedLightScaleFactor(float iblScaleFactor)
+{
+ mImpl->SetImageBasedLightScaleFactor(iblScaleFactor);
+}
+
+void ModelNode::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
+{
+ mImpl->SetBlendShapeData(data, primitive);
+}
+
+void ModelNode::SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex)
+{
+ mImpl->SetBoneMatrix(inverseMatrix, primitive, boneIndex);
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_IMPL_H
+#define DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_IMPL_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/actors/custom-actor-impl.h>
+#include <dali/public-api/common/dali-common.h>
+#include <memory> // for std::unique_ptr
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/loader/mesh-definition.h>
+#include <dali-scene3d/public-api/model-components/model-node.h>
+#include <dali-scene3d/public-api/model-components/model-primitive.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+/**
+ * @addtogroup dali_toolkit_controls_model
+ * @{
+ */
+
+namespace Internal
+{
+/**
+ * @brief This is the internal base class for custom node of model.
+ *
+ * @SINCE_2_2.99
+ */
+class DALI_SCENE3D_API ModelNode : public CustomActorImpl
+{
+public:
+ // Creation & Destruction
+ /**
+ * @brief Creates a new ModelNodeImpl instance that does not require touch by default.
+ *
+ * If touch is required, then the user can connect to this class' touch signal.
+ * @SINCE_2_2.99
+ * @return A handle to the ModelNode instance
+ */
+ static Scene3D::ModelNode New();
+
+protected:
+ /**
+ * @brief Virtual destructor.
+ * @SINCE_2_2.99
+ */
+ virtual ~ModelNode();
+
+protected: // From CustomActorImpl
+ /**
+ * @copydoc CustomActorImpl::OnSceneConnection()
+ * @note If overridden, then an up-call to ModelNode::OnSceneConnection MUST be made at the end.
+ */
+ void OnSceneConnection(int depth) override;
+
+ /**
+ * @copydoc CustomActorImpl::OnSceneDisconnection()
+ * @note If overridden, then an up-call to ModelNode::OnSceneDisconnection MUST be made at the end.
+ */
+ void OnSceneDisconnection() override;
+
+ /**
+ * @copydoc CustomActorImpl::OnChildAdd()
+ * @note If overridden, then an up-call to ModelNode::OnChildAdd MUST be made at the end.
+ */
+ void OnChildAdd(Actor& child) override;
+
+ /**
+ * @copydoc CustomActorImpl::OnChildRemove()
+ * @note If overridden, then an up-call to ModelNode::OnChildRemove MUST be made at the end.
+ */
+ void OnChildRemove(Actor& child) override;
+
+ /**
+ * @copydoc CustomActorImpl::OnPropertySet()
+ * @note If overridden, then an up-call to ModelNode::OnChildRemove MUST be made at the end.
+ */
+ void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
+
+ /**
+ * @copydoc CustomActorImpl::OnSizeSet()
+ * @note If overridden, then an up-call to ModelNode::OnSizeSet MUST be made at the end.
+ */
+ void OnSizeSet(const Vector3& targetSize) override;
+
+ /**
+ * @copydoc CustomActorImpl::OnSizeAnimation()
+ * @note If overridden, then an up-call to ModelNode::OnSizeAnimation MUST be made at the end.
+ */
+ void OnSizeAnimation(Animation& animation, const Vector3& targetSize) override;
+
+ /**
+ * @copydoc CustomActorImpl::OnRelayout()
+ */
+ void OnRelayout(const Vector2& size, RelayoutContainer& container) override;
+
+ /**
+ * @copydoc CustomActorImpl::OnSetResizePolicy()
+ */
+ void OnSetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension) override;
+
+ /**
+ * @copydoc CustomActorImpl::GetNaturalSize()
+ */
+ Vector3 GetNaturalSize() override;
+
+ /**
+ * @copydoc CustomActorImpl::CalculateChildSize()
+ */
+ float CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension) override;
+
+ /**
+ * @copydoc CustomActorImpl::GetHeightForWidth()
+ */
+ float GetHeightForWidth(float width) override;
+
+ /**
+ * @copydoc CustomActorImpl::GetWidthForHeight()
+ */
+ float GetWidthForHeight(float height) override;
+
+ /**
+ * @copydoc CustomActorImpl::RelayoutDependentOnChildren()
+ */
+ bool RelayoutDependentOnChildren(Dimension::Type dimension = Dimension::ALL_DIMENSIONS) override;
+
+ /**
+ * @copydoc CustomActorImpl::OnCalculateRelayoutSize()
+ */
+ void OnCalculateRelayoutSize(Dimension::Type dimension) override;
+
+ /**
+ * @copydoc CustomActorImpl::OnLayoutNegotiated()
+ */
+ void OnLayoutNegotiated(float size, Dimension::Type dimension) override;
+
+protected:
+ // Construction
+
+ /**
+ * @brief ModelNode constructor.
+ *
+ * @SINCE_2_2.99
+ */
+ ModelNode();
+
+ /**
+ * @brief Second phase initialization.
+ * @SINCE_2_2.99
+ */
+ void Initialize();
+
+public: // API for derived classes to override
+ // Lifecycle
+
+ /**
+ * @brief This method is called after the Node has been initialized.
+ *
+ * Derived classes should do any second phase initialization by overriding this method.
+ * @SINCE_2_2.99
+ */
+ virtual void OnInitialize();
+
+public: // Public Method
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::GetModelPrimitiveCount()
+ */
+ uint32_t GetModelPrimitiveCount() const;
+
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::AddModelPrimitive()
+ */
+ void AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive);
+
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
+ */
+ void RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive);
+
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::RemoveModelPrimitive(uint32_t index)
+ */
+ void RemoveModelPrimitive(uint32_t index);
+
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::GetModelPrimitive()
+ */
+ Dali::Scene3D::ModelPrimitive GetModelPrimitive(uint32_t index) const;
+
+ /**
+ * @copydoc Dali::Scene3D::ModelNode::FindChildModelNodeByName()
+ */
+ Scene3D::ModelNode FindChildModelNodeByName(std::string_view nodeName);
+
+ /**
+ * @brief Sets the diffuse and specular image-based lighting textures for a ModelPrimitive.
+ *
+ * @param[in] diffuseTexture The diffuse texture.
+ * @param[in] specularTexture The specular texture.
+ * @param[in] iblScaleFactor The scale factor for the image-based lighting.
+ * @param[in] specularMipmapLevels The number of mipmap levels for the specular texture.
+ */
+ void SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels);
+
+ /**
+ * @brief Sets the scale factor for image-based lighting.
+ *
+ * @param[in] iblScaleFactor The scale factor for image-based lighting.
+ */
+ void SetImageBasedLightScaleFactor(float iblScaleFactor);
+
+ /**
+ * @brief Sets the blend shape data for a ModelPrimitive.
+ *
+ * @param[in] data The blend shape data.
+ * @param[in] primitive The ModelPrimitive to set the blend shape data for.
+ */
+ void SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive);
+
+ /**
+ * @brief Sets the bone matrix for a ModelPrimitive and bone index.
+ *
+ * @param[in] inverseMatrix The inverse matrix of the bone.
+ * @param[in] primitive The ModelPrimitive to set the bone matrix for.
+ * @param[in] boneIndex The index of the bone to set the matrix for.
+ */
+ void SetBoneMatrix(const Matrix& inverseMatrix, Scene3D::ModelPrimitive primitive, Scene3D::Loader::Index& boneIndex);
+
+private:
+ /// @cond internal
+
+ // Not copyable or movable
+ DALI_INTERNAL ModelNode(const ModelNode&) = delete; ///< Deleted copy constructor.
+ DALI_INTERNAL ModelNode(ModelNode&&) = delete; ///< Deleted move constructor.
+ DALI_INTERNAL ModelNode& operator=(const ModelNode&) = delete; ///< Deleted copy assignment operator.
+ DALI_INTERNAL ModelNode& operator=(ModelNode&&) = delete; ///< Deleted move assignment operator.
+
+public:
+ class DALI_INTERNAL Impl; // Class declaration is public so we can internally add devel API's to the ModelNode's Impl
+
+private:
+ const std::unique_ptr<Impl> mImpl;
+ /// @endcond
+};
+
+/**
+ * @brief Gets implementation from the handle.
+ *
+ * @SINCE_2_2.99
+ * @param handle
+ * @return Implementation
+ * @pre handle is initialized and points to a node
+ */
+DALI_SCENE3D_API Internal::ModelNode& GetImplementation(Dali::Scene3D::ModelNode& handle);
+
+/**
+ * @brief Gets implementation from the handle.
+ *
+ * @SINCE_2_2.99
+ * @param handle
+ * @return Implementation
+ * @pre Handle is initialized and points to a node.
+ */
+DALI_SCENE3D_API const Internal::ModelNode& GetImplementation(const Dali::Scene3D::ModelNode& handle);
+
+} // namespace Internal
+
+/**
+ * @}
+ */
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_IMPL_H
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/internal/model-components/model-primitive-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/material-impl.h>
+#include <dali-scene3d/public-api/loader/environment-definition.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+/**
+ * Creates control through type registry
+ */
+BaseHandle Create()
+{
+ return Scene3D::ModelPrimitive::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelPrimitive, Dali::BaseHandle, Create);
+DALI_TYPE_REGISTRATION_END()
+
+constexpr std::string_view MORPH_KEYWORD = "MORPH";
+constexpr std::string_view MORPH_POSITION_KEYWORD = "MORPH_POSITION";
+constexpr std::string_view MORPH_NORMAL_KEYWORD = "MORPH_NORMAL";
+constexpr std::string_view MORPH_TANGENT_KEYWORD = "MORPH_TANGENT";
+constexpr std::string_view MORPH_VERSION_2_0_KEYWORD = "MORPH_VERSION_2_0";
+} // unnamed namespace
+
+ModelPrimitivePtr ModelPrimitive::New()
+{
+ ModelPrimitivePtr primitive = new ModelPrimitive();
+
+ primitive->Initialize();
+
+ return primitive;
+}
+
+ModelPrimitive::ModelPrimitive()
+{
+}
+
+ModelPrimitive::~ModelPrimitive()
+{
+ if(mMaterial)
+ {
+ GetImplementation(mMaterial).RemoveObserver(this);
+ }
+ mMaterial.Reset();
+}
+
+void ModelPrimitive::Initialize()
+{
+}
+
+void ModelPrimitive::SetRenderer(Dali::Renderer renderer)
+{
+ mRenderer = renderer;
+ mGeometry = renderer.GetGeometry();
+ mTextureSet = renderer.GetTextures();
+ mShader = renderer.GetShader();
+}
+
+Dali::Renderer ModelPrimitive::GetRenderer() const
+{
+ return mRenderer;
+}
+
+void ModelPrimitive::SetGeometry(Dali::Geometry geometry)
+{
+ mGeometry = geometry;
+ CreateRenderer();
+}
+
+Dali::Geometry ModelPrimitive::GetGeometry() const
+{
+ return mGeometry;
+}
+
+void ModelPrimitive::SetMaterial(Dali::Scene3D::Material material, bool updateRenderer)
+{
+ if(!material)
+ {
+ return;
+ }
+
+ if(mMaterial != material)
+ {
+ // Stop observe from previous material.
+ if(mMaterial)
+ {
+ GetImplementation(mMaterial).RemoveObserver(this);
+ }
+
+ mMaterial = material;
+
+ // Start observe from new material.
+
+ if(mMaterial)
+ {
+ GetImplementation(mMaterial).AddObserver(this);
+ }
+
+ if(updateRenderer)
+ {
+ mIsMaterialChanged = true;
+ if(GetImplementation(mMaterial).IsResourceReady())
+ {
+ GetImplementation(mMaterial).UpdateMaterialData();
+ ApplyMaterialToRenderer();
+ }
+ }
+ UpdateImageBasedLightTexture();
+ }
+}
+
+Dali::Scene3D::Material ModelPrimitive::GetMaterial() const
+{
+ return mMaterial;
+}
+
+void ModelPrimitive::AddPrimitiveObserver(ModelPrimitiveModifyObserver* observer)
+{
+ mObservers.insert(observer);
+}
+
+void ModelPrimitive::RemovePrimitiveObserver(ModelPrimitiveModifyObserver* observer)
+{
+ mObservers.erase(observer);
+}
+
+void ModelPrimitive::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
+{
+ mDiffuseTexture = diffuseTexture;
+ mSpecularTexture = specularTexture;
+ mIblScaleFactor = iblScaleFactor;
+ mSpecularMipmapLevels = specularMipmapLevels;
+
+ UpdateImageBasedLightTexture();
+}
+
+void ModelPrimitive::SetImageBasedLightScaleFactor(float iblScaleFactor)
+{
+ mIblScaleFactor = iblScaleFactor;
+ if(mRenderer && mMaterial)
+ {
+ mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName().data(), iblScaleFactor);
+ }
+}
+
+void ModelPrimitive::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data)
+{
+ mBlendShapeData = std::move(data);
+ Scene3D::Loader::BlendShapes::ConfigureProperties(mBlendShapeData, mShader);
+}
+
+void ModelPrimitive::SetBlendShapeGeometry(Dali::Texture blendShapeGeometry)
+{
+ mBlendShapeGeometry = blendShapeGeometry;
+}
+
+void ModelPrimitive::SetBlendShapeOptions(bool hasPositions, bool hasNormals, bool hasTangents)
+{
+ mHasPositions = hasPositions;
+ mHasNormals = hasNormals;
+ mHasTangents = hasTangents;
+}
+
+void ModelPrimitive::SetSkinned(bool isSkinned)
+{
+ mHasSkinning = isSkinned;
+}
+
+// From MaterialModifyObserver
+
+void ModelPrimitive::OnMaterialModified(Dali::Scene3D::Material material, MaterialModifyObserver::ModifyFlag flag)
+{
+ ApplyMaterialToRenderer(flag);
+}
+
+void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag)
+{
+ uint32_t shaderFlag = (flag & static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::SHADER));
+ if(mIsMaterialChanged || shaderFlag == static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::SHADER))
+ {
+ std::string vertexShader = GetImplementation(mMaterial).GetVertexShader();
+ std::string fragmentShader = GetImplementation(mMaterial).GetFragmentShader();
+
+ std::vector<std::string> defines;
+ defines.push_back("VEC4_TANGENT");
+ if(mHasSkinning)
+ {
+ defines.push_back("SKINNING");
+ }
+ if(mHasPositions || mHasNormals || mHasTangents)
+ {
+ if(mHasPositions)
+ {
+ defines.push_back(MORPH_POSITION_KEYWORD.data());
+ }
+ if(mHasNormals)
+ {
+ defines.push_back(MORPH_NORMAL_KEYWORD.data());
+ }
+ if(mHasTangents)
+ {
+ defines.push_back(MORPH_TANGENT_KEYWORD.data());
+ }
+ defines.push_back(MORPH_KEYWORD.data());
+ if(mBlendShapeData.version == Scene3D::Loader::BlendShapes::Version::VERSION_2_0)
+ {
+ defines.push_back(MORPH_VERSION_2_0_KEYWORD.data());
+ }
+ }
+ for(const auto& define : defines)
+ {
+ Scene3D::Loader::ShaderDefinition::ApplyDefine(vertexShader, define);
+ }
+
+ mShader.Reset();
+ mShader = Shader::New(vertexShader, fragmentShader);
+ if(mBlendShapeData.version != Scene3D::Loader::BlendShapes::Version::INVALID && mBlendShapeData.mActor.GetHandle())
+ {
+ Scene3D::Loader::BlendShapes::ConfigureProperties(mBlendShapeData, mShader);
+ }
+
+ if(!mRenderer)
+ {
+ CreateRenderer();
+ }
+ else
+ {
+ mRenderer.SetShader(mShader);
+ }
+ }
+
+ uint32_t textureFlag = (flag & static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::TEXTURE));
+ if(mIsMaterialChanged || textureFlag == static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::TEXTURE))
+ {
+ mTextureSet = GetImplementation(mMaterial).GetTextureSet();
+
+ if(mBlendShapeGeometry)
+ {
+ TextureSet newTextureSet = TextureSet::New();
+ newTextureSet.SetTexture(0u, mBlendShapeGeometry);
+
+ const unsigned int numberOfTextures = mTextureSet.GetTextureCount();
+ for(unsigned int index = 0u; index < numberOfTextures; ++index)
+ {
+ const unsigned int newIndex = index + 1u;
+ newTextureSet.SetTexture(newIndex, mTextureSet.GetTexture(index));
+ newTextureSet.SetSampler(newIndex, mTextureSet.GetSampler(index));
+ }
+
+ mTextureSet = newTextureSet;
+ }
+
+ uint32_t textureCount = mTextureSet.GetTextureCount();
+ Texture brdfTexture = Scene3D::Loader::EnvironmentDefinition::GetBrdfTexture();
+ if(!mSpecularTexture || !mDiffuseTexture)
+ {
+ Scene3D::Loader::EnvironmentMapData environmentMapData;
+ environmentMapData.mPixelData.resize(6);
+ for(auto& face : environmentMapData.mPixelData)
+ {
+ face.push_back(PixelData::New(new uint8_t[3]{0xff, 0xff, 0xff}, 3, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY));
+ }
+ environmentMapData.SetEnvironmentMapType(Dali::Scene3D::EnvironmentMapType::CUBEMAP);
+ Texture iblTexture = environmentMapData.GetTexture();
+ mDiffuseTexture = iblTexture;
+ mSpecularTexture = iblTexture;
+ }
+
+ mTextureSet.SetTexture(textureCount++, brdfTexture);
+ mTextureSet.SetTexture(textureCount++, mDiffuseTexture);
+ mTextureSet.SetTexture(textureCount, mSpecularTexture);
+
+ auto specularSampler = Sampler::New();
+ specularSampler.SetWrapMode(WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE);
+ specularSampler.SetFilterMode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR);
+ mTextureSet.SetSampler(textureCount, specularSampler);
+
+ if(!mRenderer)
+ {
+ CreateRenderer();
+ }
+ else
+ {
+ mRenderer.SetTextures(mTextureSet);
+ }
+ }
+
+ uint32_t uniformFlag = (flag & static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::UNIFORM));
+ if(mIsMaterialChanged || uniformFlag == static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::UNIFORM))
+ {
+ if(!mRenderer)
+ {
+ mNeedToSetRendererUniform = true;
+ }
+ else
+ {
+ UpdateRendererUniform();
+ }
+ }
+ mIsMaterialChanged = false;
+}
+
+void ModelPrimitive::CreateRenderer()
+{
+ if(!mShader || !mGeometry || !mTextureSet || mRenderer)
+ {
+ return;
+ }
+
+ mRenderer = Renderer::New(mGeometry, mShader);
+ mRenderer.SetTextures(mTextureSet);
+ UpdateRendererUniform();
+ for(auto* observer : mObservers)
+ {
+ observer->OnRendererCreated(mRenderer);
+ }
+}
+
+void ModelPrimitive::UpdateImageBasedLightTexture()
+{
+ if(mRenderer && mMaterial)
+ {
+ Dali::TextureSet textures = mRenderer.GetTextures();
+ if(!textures)
+ {
+ return;
+ }
+
+ uint32_t textureCount = textures.GetTextureCount();
+ if(textureCount > 2u &&
+ (textures.GetTexture(textureCount - GetImplementation(mMaterial).GetDiffuseImageBasedLightTextureOffset()) != mDiffuseTexture ||
+ textures.GetTexture(textureCount - GetImplementation(mMaterial).GetSpecularImageBasedLightTextureOffset()) != mSpecularTexture))
+ {
+ Dali::TextureSet newTextures = Dali::TextureSet::New();
+
+ for(uint32_t index = 0u; index < textureCount; ++index)
+ {
+ Dali::Texture texture = textures.GetTexture(index);
+ if(index == textureCount - GetImplementation(mMaterial).GetDiffuseImageBasedLightTextureOffset())
+ {
+ texture = mDiffuseTexture;
+ }
+ else if(index == textureCount - GetImplementation(mMaterial).GetSpecularImageBasedLightTextureOffset())
+ {
+ texture = mSpecularTexture;
+ }
+
+ newTextures.SetTexture(index, texture);
+ newTextures.SetSampler(index, textures.GetSampler(index));
+ }
+
+ mRenderer.SetTextures(newTextures);
+ }
+ mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName() .data(), mIblScaleFactor);
+ mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightMaxLodUniformName().data(), static_cast<float>(mSpecularMipmapLevels));
+ }
+}
+
+void ModelPrimitive::UpdateRendererUniform()
+{
+ mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName().data(), mIblScaleFactor);
+ mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightMaxLodUniformName().data(), static_cast<float>(mSpecularMipmapLevels));
+ GetImplementation(mMaterial).SetRendererUniform(mRenderer);
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_IMPL_H
+#define DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_IMPL_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property.h>
+#include <set>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/material-modify-observer.h>
+#include <dali-scene3d/internal/model-components/model-primitive-modify-observer.h>
+#include <dali-scene3d/public-api/loader/blend-shape-details.h>
+#include <dali-scene3d/public-api/loader/mesh-definition.h>
+#include <dali-scene3d/public-api/model-components/material.h>
+#include <dali-scene3d/public-api/model-components/model-primitive.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+using ModelPrimitivePtr = IntrusivePtr<ModelPrimitive>;
+
+/**
+ * @brief TODO : Explain me.
+ * Use Vector4 Tangent data
+ * Same ModelPrimitive all shares IBL
+ */
+class ModelPrimitive : public BaseObject, public MaterialModifyObserver
+{
+private:
+ using ModelPrimitiveModifyObserverContainer = std::set<ModelPrimitiveModifyObserver*>;
+
+public:
+ // Creation & Destruction
+ /**
+ * @brief Create a new ModelPrimitive object.
+ * @return A smart-pointer to the newly allocated ModelPrimitive.
+ */
+ static ModelPrimitivePtr New();
+
+protected:
+ /**
+ * @brief Construct a new ModelPrimitive.
+ */
+ ModelPrimitive();
+
+ /**
+ * @brief Second-phase constructor.
+ */
+ void Initialize();
+
+ /**
+ * @brief Virtual destructor.
+ */
+ virtual ~ModelPrimitive();
+
+public:
+ /**
+ * @brief Set Renderer that is created by Scene3D::Loader internally.
+ */
+ void SetRenderer(Dali::Renderer renderer);
+
+ /**
+ * @copydoc Dali::Scene3D::ModelPrimitive::GetRenderer()
+ */
+ Dali::Renderer GetRenderer() const;
+
+ /**
+ * @copydoc Dali::Scene3D::ModelPrimitive::SetGeometry()
+ */
+ void SetGeometry(Dali::Geometry geometry);
+
+ /**
+ * @copydoc Dali::Scene3D::ModelPrimitive::GetGeometry()
+ */
+ Dali::Geometry GetGeometry() const;
+
+ /**
+ * @copydoc Dali::Scene3D::ModelPrimitive::SetMaterial()
+ */
+ void SetMaterial(Dali::Scene3D::Material material, bool updateRenderer = true);
+
+ /**
+ * @copydoc Dali::Scene3D::ModelPrimitive::GetMaterial()
+ */
+ Dali::Scene3D::Material GetMaterial() const;
+
+ /**
+ * @brief Adds a primitive observer to this model primitive.
+ *
+ * @param[in] observer The observer to add.
+ */
+ void AddPrimitiveObserver(ModelPrimitiveModifyObserver* observer);
+
+ /**
+ * @brief Removes a primitive observer from this model primitive.
+ *
+ * @param[in] observer The observer to remove.
+ */
+ void RemovePrimitiveObserver(ModelPrimitiveModifyObserver* observer);
+
+ /**
+ * @brief Sets the image-based lighting texture for this model primitive.
+ *
+ * @param[in] diffuseTexture The diffuse texture.
+ * @param[in] specularTexture The specular texture.
+ * @param[in] iblScaleFactor The scale factor to set for image-based lighting.
+ * @param[in] specularMipmapLevels The number of mipmap levels of specular texture.
+ */
+ void SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels);
+
+ /**
+ * @brief Sets the scale factor for image-based lighting for this model primitive.
+ *
+ * @param[in] iblScaleFactor The scale factor to set for image-based lighting.
+ */
+ void SetImageBasedLightScaleFactor(float iblScaleFactor);
+
+ /**
+ * @brief Sets the blend shape data for this model primitive.
+ *
+ * @param[in] data The blend shape data to set.
+ */
+ void SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data);
+
+ /**
+ * @brief Sets the blend shape geometry for this model primitive.
+ *
+ * @param[in] blendShapeGeometry The blend shape geometry to set.
+ */
+ void SetBlendShapeGeometry(Dali::Texture blendShapeGeometry);
+
+ /**
+ * @brief Sets the blend shape options for this model primitive.
+ *
+ * @param[in] hasPositions Whether or not this model primitive has positions for blend shapes.
+ * @param[in] hasNormals Whether or not this model primitive has normals for blend shapes.
+ * @param[in] hasTangents Whether or not this model primitive has tangents for blend shapes.
+ */
+ void SetBlendShapeOptions(bool hasPositions, bool hasNormals, bool hasTangents);
+
+ /**
+ * @brief Sets whether or not this model primitive is skinned.
+ *
+ * @param[in] isSkinned Whether or not this model primitive is skinned.
+ */
+ void SetSkinned(bool isSkinned);
+
+private: // From MaterialModifyObserver
+ /**
+ * @copydoc Dali::Scene3D::Internal::Material::MaterialModifyObserver::OnMaterialModified()
+ */
+ void OnMaterialModified(Dali::Scene3D::Material material, MaterialModifyObserver::ModifyFlag flag) override;
+
+private:
+ /**
+ * @brief Apply materials data into renderer.
+ */
+ void ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag = MaterialModifyObserver::ModifyFlag::NONE);
+
+ /**
+ * @brief Updates the uniform of renderer.
+ */
+ void UpdateRendererUniform();
+
+ /**
+ * @brief Creates a renderer.
+ */
+ void CreateRenderer();
+
+ /**
+ * @brief Updates the image-based lighting texture.
+ */
+ void UpdateImageBasedLightTexture();
+
+private:
+ // Delete copy & move operator
+ ModelPrimitive(const ModelPrimitive&) = delete;
+ ModelPrimitive(ModelPrimitive&&) = delete;
+ ModelPrimitive& operator=(const ModelPrimitive& rhs) = delete;
+ ModelPrimitive& operator=(ModelPrimitive&& rhs) noexcept = delete;
+
+private:
+ ModelPrimitiveModifyObserverContainer mObservers{};
+
+ // For Renderer
+ Dali::Renderer mRenderer;
+ Dali::Geometry mGeometry;
+ Dali::Shader mShader;
+ Dali::TextureSet mTextureSet;
+ Dali::Scene3D::Material mMaterial;
+
+ // For IBL
+ Dali::Texture mSpecularTexture;
+ Dali::Texture mDiffuseTexture;
+ float mIblScaleFactor{1.0f};
+ uint32_t mSpecularMipmapLevels{1u};
+
+ // For blend shape
+ Scene3D::Loader::BlendShapes::BlendShapeData mBlendShapeData;
+ Dali::Texture mBlendShapeGeometry;
+ bool mHasSkinning = false;
+ bool mHasPositions = false;
+ bool mHasNormals = false;
+ bool mHasTangents = false;
+
+ bool mIsMaterialChanged = false;
+ bool mNeedToSetRendererUniform = false;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::ModelPrimitive& GetImplementation(Dali::Scene3D::ModelPrimitive& modelPrimitive)
+{
+ DALI_ASSERT_ALWAYS(modelPrimitive && "ModelPrimitive handle is empty");
+
+ BaseObject& handle = modelPrimitive.GetBaseObject();
+
+ return static_cast<Internal::ModelPrimitive&>(handle);
+}
+
+inline const Internal::ModelPrimitive& GetImplementation(const Dali::Scene3D::ModelPrimitive& modelPrimitive)
+{
+ DALI_ASSERT_ALWAYS(modelPrimitive && "ModelPrimitive handle is empty");
+
+ const BaseObject& handle = modelPrimitive.GetBaseObject();
+
+ return static_cast<const Internal::ModelPrimitive&>(handle);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_IMPL_H
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_MODIFY_OBSERVER_H
+#define DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_MODIFY_OBSERVER_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/model-components/model-primitive.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+/**
+ * @brief Observer class that notifies ModelNode when a Renderer of ModelPrimitive is created.
+ */
+class ModelPrimitiveModifyObserver
+{
+public:
+ /**
+ * @brief Called when a Renderer of ModelPrimitive is created.
+ *
+ * @param[in] renderer The Renderer that is created.
+ */
+ virtual void OnRendererCreated(Renderer renderer) = 0;
+};
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_MODIFY_OBSERVER_H
// INTERNAL INCLUDES
#include <dali-scene3d/internal/controls/model/model-impl.h>
+#include <dali-scene3d/public-api/model-components/model-node.h>
namespace Dali
{
VerifyCustomActorPointer<Internal::Model>(internal);
}
-const Actor Model::GetModelRoot() const
+const ModelNode Model::GetModelRoot() const
{
return GetImpl(*this).GetModelRoot();
}
+void Model::AddModelNode(ModelNode modelNode)
+{
+ return GetImpl(*this).AddModelNode(modelNode);
+}
+
+void Model::RemoveModelNode(ModelNode modelNode)
+{
+ return GetImpl(*this).RemoveModelNode(modelNode);
+}
+
void Model::SetChildrenSensitive(bool enable)
{
GetImpl(*this).SetChildrenSensitive(enable);
return GetImpl(*this).ApplyCamera(index, camera);
}
+ModelNode Model::FindChildModelNodeByName(std::string_view nodeName)
+{
+ return GetImpl(*this).FindChildModelNodeByName(nodeName);
+}
+
} // namespace Scene3D
} // namespace Dali
// INTERNAL INCLUDES
#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/model-components/model-node.h>
namespace Dali
{
* @SINCE_2_1.41
* @param[in] modelUrl model file path.(e.g., glTF, and DLI).
* @param[in] resourceDirectoryUrl resource file path that includes binary, image etc.
+ * @note If modelUrl is empty, it will not load resouces. Only ModelRoot will be created.
* @note If resourceDirectoryUrl is empty, the parent directory path of modelUrl is used for resource path.
* @return A handle to a newly allocated Dali resource
*/
- static Model New(const std::string& modelUrl, const std::string& resourceDirectoryUrl = std::string());
+ static Model New(const std::string& modelUrl = std::string(), const std::string& resourceDirectoryUrl = std::string());
/**
* @brief Creates an uninitialized Model.
static Model DownCast(BaseHandle handle);
/**
- * @brief Retrieves model root Actor.
+ * @brief Retrieves model root Node.
*
* @SINCE_2_1.41
- * @return Root Actor of the model.
+ * @return Root Node of the model.
*/
- const Actor GetModelRoot() const;
+ const ModelNode GetModelRoot() const;
+
+ /**
+ * @brief Add new ModelNode to this Model.
+ * This modelNode will become child of ModelRoot.
+ *
+ * @SINCE_2_2.99
+ * @param[in] modelNode the root of ModelNode tree to be added.
+ */
+ void AddModelNode(ModelNode modelNode);
+
+ /**
+ * @brief Remove ModelNode from this Model.
+ *
+ * @SINCE_2_2.99
+ * @param[in] modelNode the root of ModelNode tree to be removed.
+ */
+ void RemoveModelNode(ModelNode modelNode);
/**
* @brief Whether allow this model's children actor to use events.
*/
bool ApplyCamera(uint32_t index, Dali::CameraActor camera) const;
+ /**
+ * @brief Returns a child ModelNode object with a name that matches nodeName.
+ *
+ * @param[in] nodeName The name of the child ModelNode object you want to find.
+ * @return Returns a child ModelNode object with a name that matches nodeName. If there is no corresponding child ModelNode object, it returns an empty ModelNode object.
+ */
+ ModelNode FindChildModelNodeByName(std::string_view nodeName);
+
public: // Not intended for application developers
/// @cond internal
/**
${scene3d_public_api_dir}/loader/string-callback.cpp
${scene3d_public_api_dir}/loader/utils.cpp
${scene3d_public_api_dir}/loader/view-projection.cpp
+ ${scene3d_public_api_dir}/model-components/material.cpp
+ ${scene3d_public_api_dir}/model-components/model-node.cpp
+ ${scene3d_public_api_dir}/model-components/model-primitive.cpp
)
\ No newline at end of file
#define DALI_ALPHA_FUNCTION_ENTRY(x) { #x, AlphaFunction::x }
// clang-format on
-std::unordered_map<std::string, AlphaFunction> sFunctions{
- DALI_ALPHA_FUNCTION_ENTRY(DEFAULT),
- DALI_ALPHA_FUNCTION_ENTRY(LINEAR),
- DALI_ALPHA_FUNCTION_ENTRY(REVERSE),
- DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_SQUARE),
- DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_SQUARE),
- DALI_ALPHA_FUNCTION_ENTRY(EASE_IN),
- DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT),
- DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_OUT),
- DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_SINE),
- DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_SINE),
- DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_OUT_SINE),
- DALI_ALPHA_FUNCTION_ENTRY(BOUNCE),
- DALI_ALPHA_FUNCTION_ENTRY(SIN),
- DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_BACK),
-};
+std::unordered_map<std::string, AlphaFunction>& GetFunctions()
+{
+ static std::unordered_map<std::string, AlphaFunction> sFunctions{
+ DALI_ALPHA_FUNCTION_ENTRY(DEFAULT),
+ DALI_ALPHA_FUNCTION_ENTRY(LINEAR),
+ DALI_ALPHA_FUNCTION_ENTRY(REVERSE),
+ DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_SQUARE),
+ DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_SQUARE),
+ DALI_ALPHA_FUNCTION_ENTRY(EASE_IN),
+ DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT),
+ DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_OUT),
+ DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_SINE),
+ DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_SINE),
+ DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_OUT_SINE),
+ DALI_ALPHA_FUNCTION_ENTRY(BOUNCE),
+ DALI_ALPHA_FUNCTION_ENTRY(SIN),
+ DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_BACK),
+ };
+ return sFunctions;
+}
#undef DALI_ALPHA_FUNCTION_ENTRY
AlphaFunction GetAlphaFunction(const std::string& name, bool* found)
{
- auto iFind = sFunctions.find(name);
- bool success = iFind != sFunctions.end();
+ auto iFind = GetFunctions().find(name);
+ bool success = iFind != GetFunctions().end();
if(found)
{
*found = success;
void RegisterAlphaFunction(const std::string& name, AlphaFunction alphaFn)
{
- DALI_ASSERT_ALWAYS(sFunctions.insert({name, alphaFn}).second &&
+ DALI_ASSERT_ALWAYS(GetFunctions().insert({name, alphaFn}).second &&
"Function with given key already exists.");
}
{
}
+AnimationDefinition& AnimationDefinition::operator=(AnimationDefinition&& other)
+{
+ AnimationDefinition tmp(std::move(other));
+ mName = std::move(tmp.mName);
+ mDuration = tmp.mDuration;
+ mLoopCount = tmp.mLoopCount;
+ mDisconnectAction = tmp.mDisconnectAction;
+ mEndAction = tmp.mEndAction;
+ mSpeedFactor = tmp.mSpeedFactor;
+ mPlayRange = tmp.mPlayRange;
+ mProperties.swap(tmp.mProperties);
+ return *this;
+}
+
void AnimationDefinition::Animate(Animation& animation, AnimatedProperty::GetActor getActor)
{
DALI_ASSERT_ALWAYS(animation);
return animation;
}
-AnimationDefinition& AnimationDefinition::operator=(AnimationDefinition&& other)
+void AnimationDefinition::SetName(const std::string& name)
{
- AnimationDefinition tmp(std::move(other));
- mName = std::move(tmp.mName);
- mDuration = tmp.mDuration;
- mLoopCount = tmp.mLoopCount;
- mDisconnectAction = tmp.mDisconnectAction;
- mEndAction = tmp.mEndAction;
- mSpeedFactor = tmp.mSpeedFactor;
- mPlayRange = tmp.mPlayRange;
- mProperties.swap(tmp.mProperties);
- return *this;
+ mName = name;
+}
+
+const std::string& AnimationDefinition::GetName() const
+{
+ return mName;
+}
+
+void AnimationDefinition::SetDuration(float duration)
+{
+ mDuration = duration;
+}
+
+float AnimationDefinition::GetDuration() const
+{
+ return mDuration;
+}
+
+void AnimationDefinition::SetLoopCount(int32_t loopCount)
+{
+ mLoopCount = loopCount;
+}
+
+int AnimationDefinition::GetLoopCount() const
+{
+ return mLoopCount;
+}
+
+void AnimationDefinition::SetDisconnectAction(Animation::EndAction disconnectAction)
+{
+ mDisconnectAction = disconnectAction;
+}
+
+Animation::EndAction AnimationDefinition::GetDisconnectAction() const
+{
+ return mDisconnectAction;
+}
+
+void AnimationDefinition::SetEndAction(Animation::EndAction endAction)
+{
+ mEndAction = endAction;
+}
+
+Animation::EndAction AnimationDefinition::GetEndAction() const
+{
+ return mEndAction;
+}
+
+void AnimationDefinition::SetSpeedFactor(float speedFactor)
+{
+ mSpeedFactor = speedFactor;
+}
+
+float AnimationDefinition::GetSpeedFactor() const
+{
+ return mSpeedFactor;
+}
+
+void AnimationDefinition::SetPlayRange(const Vector2& playRange)
+{
+ mPlayRange = playRange;
+}
+
+Vector2 AnimationDefinition::GetPlayRange() const
+{
+ return mPlayRange;
+}
+
+void AnimationDefinition::ReserveSize(uint32_t size)
+{
+ mProperties.reserve(size);
+}
+
+uint32_t AnimationDefinition::GetPropertyCount()
+{
+ return mProperties.size();
+}
+
+void AnimationDefinition::SetProperty(uint32_t index, AnimatedProperty&& property)
+{
+ if(mProperties.size() <= index)
+ {
+ mProperties.resize(index + 1);
+ }
+ mProperties[index] = std::move(property);
+}
+
+const AnimatedProperty& AnimationDefinition::GetPropertyAt(uint32_t index)
+{
+ return mProperties[index];
}
} // namespace Dali::Scene3D::Loader
AnimationDefinition(AnimationDefinition&& other);
+ AnimationDefinition& operator=(AnimationDefinition&& other);
+
/**
* @brief Registers the properties against the given @a animation. @a getActor
* will be used to obtain the Actors for each AnimatedProperty.
*/
Animation ReAnimate(AnimatedProperty::GetActor getActor);
- AnimationDefinition& operator=(AnimationDefinition&& other);
+ /**
+ * @brief Set the name of the animation.
+ *
+ * @param[in] name The name of the animation.
+ */
+ void SetName(const std::string& name);
+
+ /**
+ * @brief Get the name of the animation.
+ *
+ * @return The name of the animation.
+ */
+ const std::string& GetName() const;
+
+ /**
+ * @brief Set the duration of the animation in seconds.
+ *
+ * @param[in] duration The duration of the animation in seconds.
+ */
+ void SetDuration(float duration);
+
+ /**
+ * @brief Get the duration of the animation in seconds.
+ *
+ * @return The duration of the animation in seconds.
+ */
+ float GetDuration() const;
+
+ /**
+ * @brief Set the number of times to loop the animation.
+ *
+ * @param[in] loopCount The number of times to loop the animation. Use -1 for infinite looping.
+ */
+ void SetLoopCount(int32_t loopCount);
+
+ /**
+ * @brief Get the number of times to loop the animation.
+ *
+ * @return The number of times to loop the animation. Use -1 for infinite looping.
+ */
+ int GetLoopCount() const;
+
+ /**
+ * @brief Set what should happen when an animation is disconnected from an object.
+ *
+ * @param[in] disconnectAction What should happen when an animation is disconnected from an object.
+ */
+ void SetDisconnectAction(Animation::EndAction disconnectAction);
+
+ /**
+ * @brief Get what should happen when an animation is disconnected from an object.
+ *
+ * @return What should happen when an animation is disconnected from an object.
+ */
+ Animation::EndAction GetDisconnectAction() const;
+
+ /**
+ * @brief Set what should happen when an animation reaches its end.
+ *
+ * @param[in] endAction What should happen when an animation reaches its end.
+ */
+ void SetEndAction(Animation::EndAction endAction);
+
+ /**
+ * @brief Get what should happen when an animation reaches its end.
+ *
+ * @return What should happen when an animation reaches its end.
+ */
+ Animation::EndAction GetEndAction() const;
+
+ /**
+ * @brief Set a speed factor for this animation. This can be used to speed up or slow down playback of this animation relative to other animations in a scene.
+ *
+ * @param[in] speedFactor The speed factor for this animation. 1.0 is normal speed, 2.0 is double speed, 0.5 is half speed, etc.
+ */
+ void SetSpeedFactor(float speedFactor);
+
+ /**
+ * @brief Get a speed factor for this animation. This can be used to speed up or slow down playback of this animation relative to other animations in a scene.
+ *
+ * @return The speed factor for this animation. 1.0 is normal speed, 2.0 is double speed, 0.5 is half speed, etc.
+ */
+ float GetSpeedFactor() const;
+
+ /**
+ * @brief Set a range within which to play this animation. This can be used to play only part of an animation or to play it backwards by setting playRange.y < playRange.x
+ *
+ * @param[in] playRange A range within which to play this animation. x = start time in seconds, y = end time in seconds
+ */
+ void SetPlayRange(const Vector2& playRange);
+
+ /**
+ * @brief Get a range within which to play this animation. This can be used to play only part of an animation or to play it backwards by setting playRange.y < playRange.x
+ *
+ * @return A range within which to play this animation. x = start time in seconds, y = end time in seconds
+ */
+ Vector2 GetPlayRange() const;
+
+ /**
+ * @brief Reserves Animated property vector's size
+ *
+ * @param[in] size The size to reserve property
+ */
+ void ReserveSize(uint32_t size);
+
+ /**
+ * @brief Retrieves the number of animated properties' count
+ *
+ * @return The count of animated properties.
+ */
+ uint32_t GetPropertyCount();
+
+ /**
+ * @brief Add a property that will be animated by this AnimationDefinition
+ *
+ * @param[in] index The index the property will be stored.
+ * @param[in] property The property that will be animated by this AnimationDefinition
+ */
+ void SetProperty(uint32_t index, AnimatedProperty&& property);
+
+ /**
+ * @brief Retrieves animated property at the index
+ *
+ * @param[in] index The index of property to be retrieved.
+ */
+ const AnimatedProperty& GetPropertyAt(uint32_t index);
-public: // DATA
+private: // DATA
std::string mName;
float mDuration = DEFAULT_DURATION_SECONDS;
- int mLoopCount = 1;
+ int32_t mLoopCount = 1;
Animation::EndAction mDisconnectAction = Animation::BAKE_FINAL;
Animation::EndAction mEndAction = Animation::BAKE;
float mSpeedFactor = 1.f;
} // namespace Dali::Scene3D::Loader
-#endif //DALI_SCENE3D_LOADER_ANIMATION_DEFINITION_H
+#endif // DALI_SCENE3D_LOADER_ANIMATION_DEFINITION_H
namespace Dali::Scene3D::Loader
{
-const std::string BlendShapes::NUMBER_OF_BLEND_SHAPES("uNumberOfBlendShapes");
-const std::string BlendShapes::UNNORMALIZE_FACTOR("uBlendShapeUnnormalizeFactor");
-const std::string BlendShapes::COMPONENT_SIZE("uBlendShapeComponentSize");
+const char* BlendShapes::NUMBER_OF_BLEND_SHAPES("uNumberOfBlendShapes");
+const char* BlendShapes::UNNORMALIZE_FACTOR("uBlendShapeUnnormalizeFactor");
+const char* BlendShapes::COMPONENT_SIZE("uBlendShapeComponentSize");
-const std::string BlendShapes::COMPONENTS("blendShapeComponents");
+const char* BlendShapes::COMPONENTS("blendShapeComponents");
-const std::string BlendShapes::WEIGHTS_UNIFORM("uBlendShapeWeight");
+const char* BlendShapes::WEIGHTS_UNIFORM("uBlendShapeWeight");
-void BlendShapes::ConfigureProperties(const std::pair<MeshDefinition, MeshGeometry>& mesh, Shader shader, Actor actor)
+void BlendShapes::ConfigureProperties(const BlendShapeData& data, Shader shader)
{
unsigned int index = 0u;
char weightNameBuffer[32];
char unnormalizeFactorNameBuffer[64];
- char* const pWeightName = weightNameBuffer + snprintf(weightNameBuffer, sizeof(weightNameBuffer), "%s", WEIGHTS_UNIFORM.c_str());
- char* const pFactorName = unnormalizeFactorNameBuffer + snprintf(unnormalizeFactorNameBuffer, sizeof(unnormalizeFactorNameBuffer), "%s", UNNORMALIZE_FACTOR.c_str());
- for(const auto& blendShape : mesh.first.mBlendShapes)
+ char* const pWeightName = weightNameBuffer + snprintf(weightNameBuffer, sizeof(weightNameBuffer), "%s", WEIGHTS_UNIFORM);
+ char* const pFactorName = unnormalizeFactorNameBuffer + snprintf(unnormalizeFactorNameBuffer, sizeof(unnormalizeFactorNameBuffer), "%s", UNNORMALIZE_FACTOR);
+ for(const auto& weight : data.weights)
{
snprintf(pWeightName, sizeof(weightNameBuffer) - (pWeightName - weightNameBuffer), "[%d]", index);
std::string weightName{weightNameBuffer};
- actor.RegisterProperty(weightName, blendShape.weight);
+ Dali::Actor actor = data.mActor.GetHandle();
+ if(actor)
+ {
+ actor.RegisterProperty(weightName, weight);
+ }
- if(shader && mesh.first.mBlendShapeVersion == Version::VERSION_1_0)
+ if(shader && data.version == Version::VERSION_1_0)
{
snprintf(pFactorName, sizeof(unnormalizeFactorNameBuffer) - (pFactorName - unnormalizeFactorNameBuffer), "[%d]", index);
std::string factorName{unnormalizeFactorNameBuffer};
- shader.RegisterProperty(factorName, mesh.second.blendShapeUnnormalizeFactor[index]);
+ shader.RegisterProperty(factorName, data.unnormalizeFactors[index]);
}
++index;
if(shader)
{
- if(Version::VERSION_2_0 == mesh.first.mBlendShapeVersion)
+ if(Version::VERSION_2_0 == data.version)
{
- shader.RegisterProperty(UNNORMALIZE_FACTOR, mesh.second.blendShapeUnnormalizeFactor[0u]);
+ shader.RegisterProperty(UNNORMALIZE_FACTOR, data.unnormalizeFactors[0u]);
}
shader.RegisterProperty(NUMBER_OF_BLEND_SHAPES, Property::Value(static_cast<float>(index)));
- shader.RegisterProperty(COMPONENT_SIZE, Property::Value(static_cast<float>(mesh.second.blendShapeBufferOffset)));
+ shader.RegisterProperty(COMPONENT_SIZE, Property::Value(static_cast<float>(data.bufferOffset)));
// Create a read only property to preserve the components of the blend shape.
- int32_t components = 0x0;
- for(auto& bs : mesh.first.mBlendShapes)
- {
- components |= (bs.deltas.IsDefined() * Component::POSITIONS) |
- (bs.normals.IsDefined() * Component::NORMALS) | (bs.tangents.IsDefined() * Component::TANGENTS);
- }
- shader.RegisterProperty(COMPONENTS, components, Property::AccessMode::READ_ONLY);
+ shader.RegisterProperty(COMPONENTS, data.components, Property::AccessMode::READ_ONLY);
}
}
// EXTERNAL INCLUDES
#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/weak-handle.h>
#include <dali/public-api/rendering/shader.h>
#include <string>
};
};
+ struct BlendShapeData
+ {
+ std::vector<float> weights;
+ std::vector<float> unnormalizeFactors;
+ Version version{Scene3D::Loader::BlendShapes::Version::INVALID};
+ uint32_t bufferOffset{0};
+ int32_t components{0x0};
+ Dali::WeakHandle<Actor> mActor;
+ };
+
// shader properties - animatable (uniforms)
- static const std::string NUMBER_OF_BLEND_SHAPES; ///< Integer number of blend shapes loaded.
- static const std::string UNNORMALIZE_FACTOR; ///< Scalar(s) for position components of blend shapes; Version 1.0: float array (1 per blend shape); Version 2.0: single float.
- static const std::string COMPONENT_SIZE; ///< Integer offset from one component (positions / normals / tangents) of a blend shape to the next.
+ static const char* NUMBER_OF_BLEND_SHAPES; ///< Integer number of blend shapes loaded.
+ static const char* UNNORMALIZE_FACTOR; ///< Scalar(s) for position components of blend shapes; Version 1.0: float array (1 per blend shape); Version 2.0: single float.
+ static const char* COMPONENT_SIZE; ///< Integer offset from one component (positions / normals / tangents) of a blend shape to the next.
// shader properties - read-only (not available as uniforms)
- static const std::string COMPONENTS; ///< Integer bitmask of the blend shape components that the shader uses; refer to the Components enum.
+ static const char* COMPONENTS; ///< Integer bitmask of the blend shape components that the shader uses; refer to the Components enum.
// actor property (instance) - animatable (uniforms)
- static const std::string WEIGHTS_UNIFORM; ///< The weight of each blend shape in a float array
+ static const char* WEIGHTS_UNIFORM; ///< The weight of each blend shape in a float array
/**
* @brief Registers properties based on the mesh definition (and geometry) and identified by the above string constants,
* on the given @a shader and @a actor.
*/
- static void ConfigureProperties(const std::pair<MeshDefinition, MeshGeometry>& mesh, Shader shader, Actor actor);
+ static void ConfigureProperties(const BlendShapeData& data, Shader shader);
BlendShapes() = delete;
};
{
AnimationDefinition animationDefinition;
- animationDefinition.mName = animationName;
- animationDefinition.mDuration = frameTime * (frameCount - 1);
+ animationDefinition.SetName(animationName);
+ animationDefinition.SetDuration(frameTime * (frameCount - 1));
float keyFrameInterval = (frameCount > 1u) ? 1.0f / static_cast<float>(frameCount - 1u) : Dali::Math::MACHINE_EPSILON_10;
std::vector<std::shared_ptr<Joint>> jointList;
if(!jointList.empty())
{
- animationDefinition.mProperties.resize(jointList.size() * 2u); // translation and rotation
+ animationDefinition.ReserveSize(jointList.size() * 2u); // translation and rotation
for(uint32_t i = 0; i < jointList.size(); ++i)
{
- AnimatedProperty& translationProperty = animationDefinition.mProperties[i * 2u];
- translationProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.mDuration);
+ AnimatedProperty translationProperty;
+ translationProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration());
translationProperty.mNodeName = jointList[i]->name;
translationProperty.mPropertyName = PROPERTY_NAME_POSITION.data();
- AnimatedProperty& rotationProperty = animationDefinition.mProperties[i * 2u + 1];
- rotationProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.mDuration);
+ AnimatedProperty rotationProperty;
+ rotationProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration());
rotationProperty.mNodeName = jointList[i]->name;
rotationProperty.mPropertyName = PROPERTY_NAME_ORIENTATION.data();
translationProperty.mKeyFrames.Add(static_cast<float>(j) * keyFrameInterval, (jointList[i]->translations[j] * scale));
rotationProperty.mKeyFrames.Add(static_cast<float>(j) * keyFrameInterval, jointList[i]->rotations[j]);
}
+ animationDefinition.SetProperty(i * 2u, std::move(translationProperty));
+ animationDefinition.SetProperty(i * 2u + 1, std::move(rotationProperty));
}
}
// EXTERNAL INCLUDES
#include <dali/devel-api/adaptor-framework/environment-variable.h>
#include <dali/devel-api/adaptor-framework/image-loading.h>
+#include <dali/devel-api/threading/mutex.h>
// INTERNAL INCLUDES
#include <dali-scene3d/public-api/loader/environment-map-loader.h>
}
static constexpr float DEFAULT_INTENSITY = 1.0f;
+
} // unnamed namespace
namespace Dali::Scene3D::Loader
{
namespace
{
-const std::string PRE_COMPUTED_BRDF_TEXTURE_FILE_NAME = "brdfLUT.png";
+const char* PRE_COMPUTED_BRDF_TEXTURE_FILE_NAME = "brdfLUT.png";
+}
+PixelData EnvironmentDefinition::mBrdfPixelData;
+Texture EnvironmentDefinition::mBrdfTexture;
+bool EnvironmentDefinition::mIsBrdfLoaded = false;
+
+Dali::Texture EnvironmentDefinition::GetBrdfTexture()
+{
+ if(!mBrdfTexture)
+ {
+ if(!mIsBrdfLoaded)
+ {
+ LoadBrdfTexture();
+ }
+ mBrdfTexture = Texture::New(TextureType::TEXTURE_2D, mBrdfPixelData.GetPixelFormat(), mBrdfPixelData.GetWidth(), mBrdfPixelData.GetHeight());
+ mBrdfTexture.Upload(mBrdfPixelData);
+ }
+ return mBrdfTexture;
}
EnvironmentDefinition::RawData
-EnvironmentDefinition::LoadRaw(const std::string& environmentsPath) const
+EnvironmentDefinition::LoadRaw(const std::string& environmentsPath)
{
RawData raw;
- auto loadFn = [&environmentsPath](const std::string& path, EnvironmentMapData& environmentMapData) {
+ auto loadFn = [&environmentsPath](const std::string& path, EnvironmentMapData& environmentMapData)
+ {
if(path.empty())
{
environmentMapData.mPixelData.resize(6);
if(mUseBrdfTexture)
{
- Devel::PixelBuffer pixelBuffer = LoadImageFromFile(GetDaliImagePath() + PRE_COMPUTED_BRDF_TEXTURE_FILE_NAME);
- if(pixelBuffer)
- {
- raw.mBrdf = Devel::PixelBuffer::Convert(pixelBuffer);
- }
+ LoadBrdfTexture();
}
return raw;
}
-EnvironmentDefinition::Textures EnvironmentDefinition::Load(RawData&& raw) const
+EnvironmentDefinition::Textures EnvironmentDefinition::Load(RawData&& raw)
{
Textures textures;
textures.mSpecularMipmapLevels = raw.mSpecular.GetMipmapLevels();
}
- if(raw.mBrdf)
+ if(mUseBrdfTexture)
{
- textures.mBrdf = Texture::New(TextureType::TEXTURE_2D, raw.mBrdf.GetPixelFormat(), raw.mBrdf.GetWidth(), raw.mBrdf.GetHeight());
- textures.mBrdf.Upload(raw.mBrdf);
+ textures.mBrdf = GetBrdfTexture();
}
return textures;
}
return DEFAULT_INTENSITY;
}
+void EnvironmentDefinition::LoadBrdfTexture()
+{
+ static Dali::Mutex mutex;
+ {
+ Mutex::ScopedLock lock(mutex);
+ if(!mIsBrdfLoaded)
+ {
+ Devel::PixelBuffer pixelBuffer = LoadImageFromFile(GetDaliImagePath() + PRE_COMPUTED_BRDF_TEXTURE_FILE_NAME);
+ if(pixelBuffer)
+ {
+ mBrdfPixelData = Devel::PixelBuffer::Convert(pixelBuffer);
+ mIsBrdfLoaded = true;
+ }
+ }
+ }
+}
+
} // namespace Dali::Scene3D::Loader
\ No newline at end of file
EnvironmentDefinition(EnvironmentDefinition&&) = default;
EnvironmentDefinition& operator=(EnvironmentDefinition&&) = default;
+ static Dali::Texture GetBrdfTexture();
+
/**
* @brief Loads raw pixel data for the given diffuse and specular maps.
* @note This can be done on any thread.
*/
- RawData LoadRaw(const std::string& environmentsPath) const;
+ RawData LoadRaw(const std::string& environmentsPath);
/**
* @brief Creates DALi cubemap Textures from the pixel data in @a raw, then
* returns them in a Textures object.
* @note This must only be called from the event thread.
*/
- Textures Load(RawData&& raw) const;
+ Textures Load(RawData&& raw);
/**
* @brief Get default intensity value.
*/
static float GetDefaultIntensity();
+private:
+ static void LoadBrdfTexture();
+
public: // DATA
std::string mDiffuseMapPath;
std::string mSpecularMapPath;
Vector3 mYDirection = Vector3::ONE;
float mIblIntensity = 1.0f;
bool mUseBrdfTexture = false;
+
+private:
+ static PixelData mBrdfPixelData;
+ static Texture mBrdfTexture;
+ static bool mIsBrdfLoaded;
};
} // namespace Dali::Scene3D::Loader
FACIAL_ANIMATION_READER.Read(rootObj, facialAnimation);\r
\r
AnimationDefinition animationDefinition;\r
- animationDefinition.mName = std::string(facialAnimation.mName.data());\r
- animationDefinition.mDuration = MILLISECONDS_TO_SECONDS * static_cast<float>(facialAnimation.mTime[facialAnimation.mNumberOfFrames - 1u]);\r
+ animationDefinition.SetName(facialAnimation.mName.data());\r
+ animationDefinition.SetDuration(MILLISECONDS_TO_SECONDS * static_cast<float>(facialAnimation.mTime[facialAnimation.mNumberOfFrames - 1u]));\r
\r
// Calculate the number of animated properties.\r
uint32_t numberOfAnimatedProperties = 0u;\r
{\r
numberOfAnimatedProperties += blendShape.mNumberOfMorphTarget;\r
}\r
- animationDefinition.mProperties.resize(numberOfAnimatedProperties);\r
+ animationDefinition.ReserveSize(numberOfAnimatedProperties);\r
\r
- // Create the key frame instances.\r
- for(auto& animatedProperty : animationDefinition.mProperties)\r
- {\r
- animatedProperty.mKeyFrames = Dali::KeyFrames::New();\r
- }\r
-\r
- // Set the property names\r
uint32_t targets = 0u;\r
for(const auto& blendShape : facialAnimation.mBlendShapes)\r
{\r
for(uint32_t morphTargetIndex = 0u; morphTargetIndex < blendShape.mNumberOfMorphTarget; ++morphTargetIndex)\r
{\r
- AnimatedProperty& animatedProperty = animationDefinition.mProperties[targets + morphTargetIndex];\r
- animatedProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.mDuration);\r
-\r
+ AnimatedProperty animatedProperty;\r
+ animatedProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration());\r
animatedProperty.mNodeName = blendShape.mNodeName;\r
-\r
std::stringstream weightPropertyStream;\r
weightPropertyStream << BlendShapes::WEIGHTS_UNIFORM << "[" << morphTargetIndex << "]";\r
animatedProperty.mPropertyName = weightPropertyStream.str();\r
- }\r
- targets += blendShape.mNumberOfMorphTarget;\r
- }\r
\r
- targets = 0u;\r
- for(const auto& blendShape : facialAnimation.mBlendShapes)\r
- {\r
- for(uint32_t timeIndex = 0u; timeIndex < facialAnimation.mNumberOfFrames; ++timeIndex)\r
- {\r
- const float progress = MILLISECONDS_TO_SECONDS * static_cast<float>(facialAnimation.mTime[timeIndex]) / animationDefinition.mDuration;\r
-\r
- for(uint32_t morphTargetIndex = 0u; morphTargetIndex < blendShape.mNumberOfMorphTarget; ++morphTargetIndex)\r
+ animatedProperty.mKeyFrames = Dali::KeyFrames::New();\r
+ for(uint32_t timeIndex = 0u; timeIndex < facialAnimation.mNumberOfFrames; ++timeIndex)\r
{\r
- AnimatedProperty& animatedProperty = animationDefinition.mProperties[targets + morphTargetIndex];\r
-\r
+ const float progress = MILLISECONDS_TO_SECONDS * static_cast<float>(facialAnimation.mTime[timeIndex]) / animationDefinition.GetDuration();\r
animatedProperty.mKeyFrames.Add(progress, blendShape.mKeys[timeIndex][morphTargetIndex]);\r
}\r
+ animationDefinition.SetProperty(targets + morphTargetIndex, std::move(animatedProperty));\r
}\r
+\r
targets += blendShape.mNumberOfMorphTarget;\r
}\r
\r
WrapMode::CLAMP_TO_EDGE,
WrapMode::MIRRORED_REPEAT};
-const SamplerFlags::Type SINGLE_VALUE_SAMPLER = SamplerFlags::Encode(FilterMode::NEAREST, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE);
+const SamplerFlags::Type GetSingleValueSampler()
+{
+ static const SamplerFlags::Type SINGLE_VALUE_SAMPLER = SamplerFlags::Encode(FilterMode::NEAREST, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE);
+ return SINGLE_VALUE_SAMPLER;
+}
static constexpr std::string_view EMBEDDED_DATA_PREFIX = "data:";
static constexpr std::string_view EMBEDDED_DATA_IMAGE_MEDIA_TYPE = "image/";
}
else
{
+ textureDefinition.mDirectoryPath = resourcePath;
pixelData = SyncImageLoader::Load(resourcePath + textureDefinition.mImageUri, textureDefinition.mMinImageDimensions, fittingMode, textureDefinition.mSamplingMode, orientationCorrection);
}
return pixelData;
{
const auto bufferSize = 4;
uint8_t* buffer = new uint8_t[bufferSize]{0x7f, 0x7f, 0xff, 0xff}; // normal of (0, 0, 1), roughness of 1
- raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+ raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
}
}
else
buffer[0] = static_cast<uint8_t>(mColor.r * 255.f);
buffer[1] = static_cast<uint8_t>(mColor.g * 255.f);
buffer[2] = static_cast<uint8_t>(mColor.b * 255.f);
- raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, format, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+ raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, format, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
}
// If we have transparency, or an image based albedo map, we will have to continue with separate metallicRoughness + normal.
// glTF2 uses B & G, so we might as well just set all components to 1.0.
const auto bufferSize = 4;
uint8_t* buffer = new uint8_t[bufferSize]{0xff, 0xff, 0xff, 0xff};
- raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+ raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
}
if(checkStage(NORMAL))
{
const auto bufferSize = 3;
uint8_t* buffer = new uint8_t[bufferSize]{0x7f, 0x7f, 0xff}; // normal of (0, 0, 1)
- raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+ raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
}
else // single-value normal-roughness
{
const auto bufferSize = 4;
uint8_t* buffer = new uint8_t[bufferSize]{0x7f, 0x7f, 0xff, 0xff}; // normal of (0, 0, 1), roughness of 1.0
- raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+ raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
}
}
}
#include <dali-scene3d/public-api/loader/environment-definition.h>
#include <dali-scene3d/public-api/loader/index.h>
#include <dali-scene3d/public-api/loader/utils.h>
+#include <dali-scene3d/public-api/model-components/material.h>
namespace Dali::Scene3D::Loader
{
struct DALI_SCENE3D_API TextureDefinition
{
std::string mImageUri; // When the texture is loaded from embedded resources, this URI is used as a data stream.
+ std::string mDirectoryPath;
SamplerFlags::Type mSamplerFlags;
ImageDimensions mMinImageDimensions;
SamplingMode::Type mSamplingMode;
float mNormalScale = 1.f;
float mOcclusionStrength = 1.f;
Vector3 mEmissiveFactor = Vector3::ZERO;
+ float mIor = -1.0f;
float mDielectricSpecular = 0.04f;
float mSpecularFactor = 1.0f;
Vector3 mSpecularColorFactor = Vector3::ONE;
bool mNeedNormalTexture = true;
bool mDoubleSided = false;
- bool mIsOpaque = true;
- bool mIsMask = false;
+ Scene3D::Material::AlphaModeType mAlphaModeType = Scene3D::Material::AlphaModeType::OPAQUE;
+ bool mIsOpaque = true;
+ bool mIsMask = false;
std::vector<TextureStage> mTextureStages;
+ Material mMaterial;
};
} // namespace Dali::Scene3D::Loader
-#ifndef DALI_SCENE3D_LOADERER_MATRIX_STACK_H_
-#define DALI_SCENE3D_LOADERER_MATRIX_STACK_H_
+#ifndef DALI_SCENE3D_LOADER_MATRIX_STACK_H_
+#define DALI_SCENE3D_LOADER_MATRIX_STACK_H_
/*
* Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
} // namespace Dali::Scene3D::Loader
-#endif //DALI_SCENE3D_LOADERER_MATRIX_STACK_H_
+#endif //DALI_SCENE3D_LOADER_MATRIX_STACK_H_
uint16_t (*mFunc)(uintptr_t&);
};
-const std::string QUAD("quad");
+const char* QUAD("quad");
///@brief Reads a blob from the given stream @a source into @a target, which must have
/// at least @a descriptor.length bytes.
raw.mAttribs.push_back({"aVertexColor", propertyType, static_cast<uint32_t>(bufferSize / propertySize), std::move(buffer)});
}
}
+ else
+ {
+ std::vector<uint8_t> buffer(raw.mAttribs[0].mNumElements * sizeof(Vector4));
+ auto colors = reinterpret_cast<Vector4*>(buffer.data());
+
+ for(uint32_t i = 0; i < raw.mAttribs[0].mNumElements; i++)
+ {
+ colors[i] = Vector4::ONE;
+ }
+
+ raw.mAttribs.push_back({"aVertexColor", Property::VECTOR4, raw.mAttribs[0].mNumElements, std::move(buffer)});
+ }
if(IsSkinned())
{
return meshGeometry;
}
+void MeshDefinition::RetrieveBlendShapeComponents(bool& hasPositions, bool& hasNormals, bool& hasTangents) const
+{
+ for(const auto& blendShape : mBlendShapes)
+ {
+ hasPositions = hasPositions || blendShape.deltas.IsDefined();
+ hasNormals = hasNormals || blendShape.normals.IsDefined();
+ hasTangents = hasTangents || blendShape.tangents.IsDefined();
+ }
+}
+
} // namespace Dali::Scene3D::Loader
*/
MeshGeometry Load(RawData&& raw) const;
+ /**
+ * @brief Retrieves what Components information is in this mesh's BlendShape.
+ *
+ * @param[out] hasPositions True if the BlendShape has position components
+ * @param[out] hasNormals True if the BlendShape has normal components
+ * @param[out] hasTangents True if the BlendShape has tangent components
+ */
+ void RetrieveBlendShapeComponents(bool& hasPositions, bool& hasNormals, bool& hasTangents) const;
+
public: // DATA
std::shared_ptr<RawData> mRawData;
uint32_t mFlags = 0x0;
std::vector<BlendShape> mBlendShapes;
BlendShapes::Version mBlendShapeVersion = BlendShapes::Version::INVALID;
- Index mSkeletonIdx = INVALID_INDEX;
+ Index mSkeletonIdx = INVALID_INDEX;
+ ModelPrimitive mModelPrimitive;
};
} // namespace Dali::Scene3D::Loader
-#ifndef DALI_SCENE3D_LOADERER_MESH_GEOMETRY_H
-#define DALI_SCENE3D_LOADERER_MESH_GEOMETRY_H
+#ifndef DALI_SCENE3D_LOADER_MESH_GEOMETRY_H
+#define DALI_SCENE3D_LOADER_MESH_GEOMETRY_H
/*
* Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
// INTERNAL INCLUDES
#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/model-components/model-primitive.h>
namespace Dali::Scene3D::Loader
{
struct DALI_SCENE3D_API MeshGeometry
{
- Geometry geometry; ///< The array of vertices.
- Texture blendShapeGeometry; ///< The array of vertices of the different blend shapes encoded inside a texture with power of two dimensions.
- Vector<float> blendShapeUnnormalizeFactor; ///< Factor used to unnormalize the geometry of the blend shape.
- unsigned int blendShapeBufferOffset{0}; ///< Offset used to calculate the start of each blend shape.
+ Geometry geometry; ///< The array of vertices.
+ Texture blendShapeGeometry; ///< The array of vertices of the different blend shapes encoded inside a texture with power of two dimensions.
+ Vector<float> blendShapeUnnormalizeFactor; ///< Factor used to unnormalize the geometry of the blend shape.
+ unsigned int blendShapeBufferOffset{0}; ///< Offset used to calculate the start of each blend shape.
};
} // namespace Dali::Scene3D::Loader
-#endif // DALI_SCENE3D_LOADERER_MESH_GEOMETRY_H
+#endif // DALI_SCENE3D_LOADER_MESH_GEOMETRY_H
#include <dali-scene3d/public-api/loader/node-definition.h>
// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/material-impl.h>
+#include <dali-scene3d/internal/model-components/model-primitive-impl.h>
#include <dali-scene3d/public-api/loader/renderer-state.h>
#include <dali-scene3d/public-api/loader/utils.h>
+#include <dali/integration-api/debug.h>
+
namespace Dali
{
namespace
{
-constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
-constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
-constexpr std::string_view IBL_MAXLOD("uMaxLOD");
+static constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
+static constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
+static constexpr std::string_view IBL_MAXLOD("uMaxLOD");
+
+static constexpr uint32_t MAX_NUMBER_OF_MATERIAL_TEXTURE = 7;
+static constexpr uint32_t SEMANTICS[MAX_NUMBER_OF_MATERIAL_TEXTURE] =
+ {
+ Scene3D::Loader::MaterialDefinition::ALBEDO,
+ Scene3D::Loader::MaterialDefinition::METALLIC | Scene3D::Loader::MaterialDefinition::ROUGHNESS,
+ Scene3D::Loader::MaterialDefinition::NORMAL,
+ Scene3D::Loader::MaterialDefinition::OCCLUSION,
+ Scene3D::Loader::MaterialDefinition::EMISSIVE,
+ Scene3D::Loader::MaterialDefinition::SPECULAR,
+ Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR,
+};
+
+static constexpr Scene3D::Material::TextureType TEXTURE_TYPES[MAX_NUMBER_OF_MATERIAL_TEXTURE] =
+ {
+ Scene3D::Material::TextureType::BASE_COLOR,
+ Scene3D::Material::TextureType::METALLIC_ROUGHNESS,
+ Scene3D::Material::TextureType::NORMAL,
+ Scene3D::Material::TextureType::OCCLUSION,
+ Scene3D::Material::TextureType::EMISSIVE,
+ Scene3D::Material::TextureType::SPECULAR,
+ Scene3D::Material::TextureType::SPECULAR_COLOR,
+};
+
+Vector4 GetTextureFactor(Scene3D::Loader::MaterialDefinition& materialDefinition, uint32_t semantic)
+{
+ Vector4 factor = Vector4::ONE;
+ switch(semantic)
+ {
+ case Scene3D::Loader::MaterialDefinition::ALBEDO:
+ factor = materialDefinition.mBaseColorFactor;
+ break;
+ case Scene3D::Loader::MaterialDefinition::METALLIC | Scene3D::Loader::MaterialDefinition::ROUGHNESS:
+ factor = Vector4(materialDefinition.mMetallic, materialDefinition.mRoughness, 0.0f, 0.0f);
+ break;
+ case Scene3D::Loader::MaterialDefinition::NORMAL:
+ factor.x = materialDefinition.mNormalScale;
+ break;
+ case Scene3D::Loader::MaterialDefinition::OCCLUSION:
+ factor.x = materialDefinition.mOcclusionStrength;
+ break;
+ case Scene3D::Loader::MaterialDefinition::EMISSIVE:
+ factor = materialDefinition.mEmissiveFactor;
+ break;
+ case Scene3D::Loader::MaterialDefinition::SPECULAR:
+ factor.x = materialDefinition.mSpecularFactor;
+ break;
+ case Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR:
+ factor = materialDefinition.mSpecularColorFactor;
+ break;
+ default:
+ break;
+ }
+ return factor;
+}
+
} // namespace
namespace Scene3D
reflector.Reflect(ResourceType::Shader, mShaderIdx);
}
-void NodeDefinition::Renderable::OnCreate(const NodeDefinition& node, CreateParams& params, Actor& actor) const
+void NodeDefinition::Renderable::OnCreate(const NodeDefinition& nodeDefinition, CreateParams& params, ModelNode& node) const
{
DALI_ASSERT_DEBUG(mShaderIdx != INVALID_INDEX);
auto& resources = params.mResources;
RendererState::Apply(resources.mShaders[mShaderIdx].first.mRendererState, renderer);
- actor.AddRenderer(renderer);
+ node.AddRenderer(renderer);
}
-const std::string NodeDefinition::ORIGINAL_MATRIX_PROPERTY_NAME = "originalMatrix";
+const char* NodeDefinition::ORIGINAL_MATRIX_PROPERTY_NAME = "originalMatrix";
-Actor NodeDefinition::CreateActor(CreateParams& params)
+ModelNode NodeDefinition::CreateModelNode(CreateParams& params)
{
- Actor actor = Actor::New();
- mNodeId = actor.GetProperty<int32_t>(Dali::Actor::Property::ID);
+ ModelNode node = ModelNode::New();
+ mNodeId = node.GetProperty<int32_t>(Dali::Actor::Property::ID);
- SetActorCentered(actor);
+ SetActorCentered(node);
- actor.SetProperty(Actor::Property::NAME, mName);
- actor.SetProperty(Actor::Property::POSITION, mPosition);
- actor.SetProperty(Actor::Property::ORIENTATION, mOrientation);
- actor.SetProperty(Actor::Property::SCALE, mScale);
- actor.SetProperty(Actor::Property::SIZE, mSize);
- actor.SetProperty(Actor::Property::VISIBLE, mIsVisible);
+ node.SetProperty(Actor::Property::NAME, mName);
+ node.SetProperty(Actor::Property::POSITION, mPosition);
+ node.SetProperty(Actor::Property::ORIENTATION, mOrientation);
+ node.SetProperty(Actor::Property::SCALE, mScale);
+ node.SetProperty(Actor::Property::SIZE, mSize);
+ node.SetProperty(Actor::Property::VISIBLE, mIsVisible);
- actor.RegisterProperty(ORIGINAL_MATRIX_PROPERTY_NAME, GetLocalSpace(), Property::AccessMode::READ_ONLY);
+ node.RegisterProperty(ORIGINAL_MATRIX_PROPERTY_NAME, GetLocalSpace(), Property::AccessMode::READ_ONLY);
- actor.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
+ node.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
for(auto& renderable : mRenderables)
{
- renderable->OnCreate(*this, params, actor);
+ renderable->OnCreate(*this, params, node);
}
for(auto& e : mExtras)
{
- actor.RegisterProperty(e.mKey, e.mValue);
+ node.RegisterProperty(e.mKey, e.mValue);
}
for(auto& c : mConstraints)
{
- params.mConstrainables.push_back(ConstraintRequest{&c, actor});
+ params.mConstrainables.push_back(ConstraintRequest{&c, node});
}
- return actor;
+ return node;
}
Matrix NodeDefinition::GetLocalSpace() const
reflector.Reflect(ResourceType::Material, mMaterialIdx);
}
-void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
+void ModelRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const
{
DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX);
- Renderable::OnCreate(node, params, actor);
+ Renderable::OnCreate(nodeDefinition, params, node);
auto& resources = params.mResources;
auto& mesh = resources.mMeshes[mMeshIdx];
- auto renderer = actor.GetRendererAt(actor.GetRendererCount() - 1u);
+ auto renderer = node.GetRendererAt(node.GetRendererCount() - 1u);
Geometry geometry = mesh.second.geometry;
renderer.SetGeometry(geometry);
- auto shader = renderer.GetShader();
-
- if(mesh.first.IsSkinned())
- {
- params.mSkinnables.push_back(SkinningShaderConfigurationRequest{mesh.first.mSkeletonIdx, shader});
- }
-
- if(mesh.first.HasBlendShapes())
- {
- params.mBlendshapeRequests.push_back(BlendshapeShaderConfigurationRequest{node.mName, mMeshIdx, shader});
- }
-
TextureSet textures = resources.mMaterials[mMaterialIdx].second;
-
// Set the blend shape texture.
if(mesh.second.blendShapeGeometry)
{
textures = newTextureSet;
}
+ renderer.SetTextures(textures);
+
+ {
+ mesh.first.mModelPrimitive = ModelPrimitive::New();
+ auto primitive = mesh.first.mModelPrimitive;
+ GetImplementation(primitive).SetRenderer(renderer);
+
+ Index envIndex = resources.mMaterials[mMaterialIdx].first.mEnvironmentIdx;
+ uint32_t specularMipmap = resources.mEnvironmentMaps[envIndex].second.mSpecularMipmapLevels;
+ GetImplementation(primitive).SetImageBasedLightTexture(resources.mEnvironmentMaps[envIndex].second.mDiffuse,
+ resources.mEnvironmentMaps[envIndex].second.mSpecular,
+ resources.mEnvironmentMaps[envIndex].first.mIblIntensity,
+ specularMipmap);
+
+ bool hasPositions = false;
+ bool hasNormals = false;
+ bool hasTangents = false;
+ mesh.first.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
+ GetImplementation(primitive).SetBlendShapeOptions(hasPositions, hasNormals, hasTangents);
+ GetImplementation(primitive).SetBlendShapeGeometry(mesh.second.blendShapeGeometry);
+ GetImplementation(primitive).SetSkinned(mesh.first.IsSkinned());
+ }
+
+ auto shader = renderer.GetShader();
+ if(mesh.first.IsSkinned())
+ {
+ params.mSkinnables.push_back(SkinningShaderConfigurationRequest{mesh.first.mSkeletonIdx, shader, mesh.first.mModelPrimitive});
+ }
- renderer.RegisterProperty("uHasVertexColor", static_cast<float>(mesh.first.mColors.IsDefined()));
+ if(mesh.first.HasBlendShapes())
+ {
+ params.mBlendshapeRequests.push_back(BlendshapeShaderConfigurationRequest{nodeDefinition.mName, mMeshIdx, shader, mesh.first.mModelPrimitive});
+ }
auto& matDef = resources.mMaterials[mMaterialIdx].first;
- actor.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
- actor.RegisterProperty("uMetallicFactor", matDef.mMetallic);
- actor.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
- actor.RegisterProperty("uDielectricSpecular", matDef.mDielectricSpecular);
- actor.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
- actor.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
- actor.RegisterProperty("uNormalScale", matDef.mNormalScale);
- actor.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
+ renderer.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
+ renderer.RegisterProperty("uMetallicFactor", matDef.mMetallic);
+ renderer.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
+ renderer.RegisterProperty("uDielectricSpecular", matDef.mDielectricSpecular);
+ renderer.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
+ renderer.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
+ renderer.RegisterProperty("uNormalScale", matDef.mNormalScale);
+ renderer.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
if(matDef.mFlags & MaterialDefinition::OCCLUSION)
{
renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
}
- Index envIdx = matDef.mEnvironmentIdx;
- renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
- renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection);
-
float opaque = matDef.mIsOpaque ? 1.0f : 0.0f;
float mask = matDef.mIsMask ? 1.0f : 0.0f;
float alphaCutoff = matDef.GetAlphaCutoff();
renderer.RegisterProperty("uMask", mask);
renderer.RegisterProperty("uAlphaThreshold", alphaCutoff);
- renderer.SetTextures(textures);
+ Index envIndex = matDef.mEnvironmentIdx;
+ uint32_t specularMipmap = resources.mEnvironmentMaps[envIndex].second.mSpecularMipmapLevels;
+ renderer.RegisterProperty(IBL_MAXLOD.data(), static_cast<float>(specularMipmap));
+ renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIndex].first.mIblIntensity);
+ renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIndex].first.mYDirection);
+
+ node.SetProperty(Actor::Property::COLOR, mColor);
+
+ {
+ matDef.mMaterial = Material::New();
+ auto material = matDef.mMaterial;
+ uint32_t textureIndexOffset = (mesh.second.blendShapeGeometry) ? 1 : 0;
+ uint32_t textureIndex = 0;
+ for(uint32_t i = 0; i < MAX_NUMBER_OF_MATERIAL_TEXTURE; ++i)
+ {
+ Internal::Material::TextureInformation textureInformation;
+ if(matDef.CheckTextures(SEMANTICS[i]))
+ {
+ textureInformation.mTexture = textures.GetTexture(textureIndex + textureIndexOffset);
+ textureInformation.mSampler = textures.GetSampler(textureIndex + textureIndexOffset);
+ textureInformation.mUrl = matDef.mTextureStages[textureIndex].mTexture.mDirectoryPath + matDef.mTextureStages[textureIndex].mTexture.mImageUri;
+ textureIndex++;
+ }
+ textureInformation.mFactor = GetTextureFactor(matDef, SEMANTICS[i]);
+ GetImplementation(material).SetTextureInformation(TEXTURE_TYPES[i], std::move(textureInformation));
+ }
+ material.SetProperty(Scene3D::Material::Property::ALPHA_MODE, matDef.mAlphaModeType);
+ material.SetProperty(Scene3D::Material::Property::ALPHA_CUTOFF, matDef.GetAlphaCutoff());
+ material.SetProperty(Scene3D::Material::Property::DOUBLE_SIDED, matDef.mDoubleSided);
+ material.SetProperty(Scene3D::Material::Property::IOR, matDef.mIor);
+ GetImplementation(mesh.first.mModelPrimitive).SetMaterial(material, false);
+ GetImplementation(material).ResetFlag();
+ }
- uint32_t specularMipmap = resources.mEnvironmentMaps[envIdx].second.mSpecularMipmapLevels;
- actor.SetProperty(Actor::Property::COLOR, mColor);
- actor.RegisterProperty(IBL_MAXLOD.data(), static_cast<float>(specularMipmap));
+ node.AddModelPrimitive(mesh.first.mModelPrimitive);
}
-void ArcRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
+void ArcRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const
{
- ModelRenderable::OnCreate(node, params, actor);
+ ModelRenderable::OnCreate(nodeDefinition, params, node);
- actor.RegisterProperty("antiAliasing", mAntiAliasing ? 1 : 0);
- actor.RegisterProperty("arcCaps", mArcCaps);
- actor.RegisterProperty("radius", mRadius);
+ node.RegisterProperty("antiAliasing", mAntiAliasing ? 1 : 0);
+ node.RegisterProperty("arcCaps", mArcCaps);
+ node.RegisterProperty("radius", mRadius);
const float startAngleRadians = mStartAngleDegrees * Math::PI_OVER_180;
Vector2 startPolar{std::cos(startAngleRadians), std::sin(startAngleRadians)};
- actor.RegisterProperty("startAngle", startPolar);
+ node.RegisterProperty("startAngle", startPolar);
const float endAngleRadians = mEndAngleDegrees * Math::PI_OVER_180;
Vector2 endPolar{std::cos(endAngleRadians), std::sin(endAngleRadians)};
- actor.RegisterProperty("endAngle", endPolar);
+ node.RegisterProperty("endAngle", endPolar);
}
void ArcRenderable::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector)
#include <dali-scene3d/public-api/loader/customization.h>
#include <dali-scene3d/public-api/loader/matrix-stack.h>
#include <dali-scene3d/public-api/loader/resource-bundle.h>
+#include <dali-scene3d/public-api/model-components/model-node.h>
namespace Dali
{
*/
struct DALI_SCENE3D_API SkinningShaderConfigurationRequest
{
- Index mSkeletonIdx;
- Shader mShader;
+ Index mSkeletonIdx;
+ Shader mShader;
+ ModelPrimitive mPrimitive;
bool operator<(const SkinningShaderConfigurationRequest& other) const
{
*/
struct DALI_SCENE3D_API BlendshapeShaderConfigurationRequest
{
- std::string mNodeName;
- Index mMeshIdx;
- Shader mShader;
+ std::string mNodeName;
+ Index mMeshIdx;
+ Shader mShader;
+ ModelPrimitive mPrimitive;
bool operator<(const BlendshapeShaderConfigurationRequest& other) const
{
struct CreateParams
{
public: // input
- const ResourceBundle& mResources;
- Transforms& mXforms;
+ ResourceBundle& mResources;
+ Transforms& mXforms;
public: // output
std::vector<ConstraintRequest> mConstrainables;
virtual bool GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const;
virtual void RegisterResources(IResourceReceiver& receiver) const;
virtual void ReflectResources(IResourceReflector& reflector);
- virtual void OnCreate(const NodeDefinition& node, CreateParams& params, Actor& actor) const;
+ virtual void OnCreate(const NodeDefinition& nodeDefinition, CreateParams& params, ModelNode& node) const;
};
struct CustomizationDefinition
public: // METHODS
/**
- * @brief Creates a DALi Actor from this definition only.
+ * @brief Creates a ModelNode from this definition only.
* @note Not recursive.
*/
- Actor CreateActor(CreateParams& params);
+ ModelNode CreateModelNode(CreateParams& params);
/**
* @brief Gets local space matrix of this node
static std::string_view GetIblMaxLodUniformName();
public: // DATA
- static const std::string ORIGINAL_MATRIX_PROPERTY_NAME;
+ static const char* ORIGINAL_MATRIX_PROPERTY_NAME;
std::string mName;
uint32_t mNodeId = INVALID_INDEX;
bool GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const override;
void RegisterResources(IResourceReceiver& receiver) const override;
void ReflectResources(IResourceReflector& reflector) override;
- void OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const override;
+ void OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const override;
};
/**
public: // METHODS
static void GetEndVectorWithDiffAngle(float startAngle, float endAngle, Vector2& endVector);
- void OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const override;
+ void OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const override;
};
} // namespace Loader
{
namespace
{
-std::map<std::string_view, Type> COMPARISONS{
-#define DECL_COMPARISON(x) {#x, Comparison::x}
- DECL_COMPARISON(NEVER),
- DECL_COMPARISON(ALWAYS),
- DECL_COMPARISON(LESS),
- DECL_COMPARISON(GREATER),
- DECL_COMPARISON(EQUAL),
- DECL_COMPARISON(NOT_EQUAL),
- DECL_COMPARISON(LESS_EQUAL),
- DECL_COMPARISON(GREATER_EQUAL),
-#undef DECL_COMPARISON
-};
+const std::map<std::string_view, Type>& GetComparisons()
+{
+ static const std::map<std::string_view, Type> COMPARISONS{
+ #define DECL_COMPARISON(x) {#x, Comparison::x}
+ DECL_COMPARISON(NEVER),
+ DECL_COMPARISON(ALWAYS),
+ DECL_COMPARISON(LESS),
+ DECL_COMPARISON(GREATER),
+ DECL_COMPARISON(EQUAL),
+ DECL_COMPARISON(NOT_EQUAL),
+ DECL_COMPARISON(LESS_EQUAL),
+ DECL_COMPARISON(GREATER_EQUAL),
+ #undef DECL_COMPARISON
+ };
+ return COMPARISONS;
+}
Type InterpretComparison(const std::string_view& str)
{
Type value = 0x0;
- auto iFind = COMPARISONS.find(str);
- if(iFind != COMPARISONS.end())
+ auto iFind = GetComparisons().find(str);
+ if(iFind != GetComparisons().end())
{
value = iFind->second;
}
return value;
}
-std::map<std::string_view, Type> BLEND_FACTORS{
-#define DECL_BLEND_FACTOR(x) {#x, Dali::Scene3D::Loader::BlendFactor::x}
- DECL_BLEND_FACTOR(ZERO),
- DECL_BLEND_FACTOR(ONE),
- DECL_BLEND_FACTOR(SRC_COLOR),
- DECL_BLEND_FACTOR(ONE_MINUS_SRC_COLOR),
- DECL_BLEND_FACTOR(SRC_ALPHA),
- DECL_BLEND_FACTOR(ONE_MINUS_SRC_ALPHA),
- DECL_BLEND_FACTOR(DST_ALPHA),
- DECL_BLEND_FACTOR(ONE_MINUS_DST_ALPHA),
- DECL_BLEND_FACTOR(DST_COLOR),
- DECL_BLEND_FACTOR(ONE_MINUS_DST_COLOR),
- DECL_BLEND_FACTOR(SRC_ALPHA_SATURATE),
- DECL_BLEND_FACTOR(CONSTANT_COLOR),
- DECL_BLEND_FACTOR(ONE_MINUS_CONSTANT_COLOR),
- DECL_BLEND_FACTOR(CONSTANT_ALPHA),
- DECL_BLEND_FACTOR(ONE_MINUS_CONSTANT_ALPHA),
-#undef DECL_BLEND_FACTOR
-};
+const std::map<std::string_view, Type>& GetBlendFactors()
+{
+ static const std::map<std::string_view, Type> BLEND_FACTORS{
+ #define DECL_BLEND_FACTOR(x) {#x, Dali::Scene3D::Loader::BlendFactor::x}
+ DECL_BLEND_FACTOR(ZERO),
+ DECL_BLEND_FACTOR(ONE),
+ DECL_BLEND_FACTOR(SRC_COLOR),
+ DECL_BLEND_FACTOR(ONE_MINUS_SRC_COLOR),
+ DECL_BLEND_FACTOR(SRC_ALPHA),
+ DECL_BLEND_FACTOR(ONE_MINUS_SRC_ALPHA),
+ DECL_BLEND_FACTOR(DST_ALPHA),
+ DECL_BLEND_FACTOR(ONE_MINUS_DST_ALPHA),
+ DECL_BLEND_FACTOR(DST_COLOR),
+ DECL_BLEND_FACTOR(ONE_MINUS_DST_COLOR),
+ DECL_BLEND_FACTOR(SRC_ALPHA_SATURATE),
+ DECL_BLEND_FACTOR(CONSTANT_COLOR),
+ DECL_BLEND_FACTOR(ONE_MINUS_CONSTANT_COLOR),
+ DECL_BLEND_FACTOR(CONSTANT_ALPHA),
+ DECL_BLEND_FACTOR(ONE_MINUS_CONSTANT_ALPHA),
+ #undef DECL_BLEND_FACTOR
+ };
+ return BLEND_FACTORS;
+}
Type InterpretBlendFactor(const std::string_view& str, uint8_t item)
{
Type value = 0x0;
- auto iFind = BLEND_FACTORS.find(str);
- if(iFind != BLEND_FACTORS.end())
+ auto iFind = GetBlendFactors().find(str);
+ if(iFind != GetBlendFactors().end())
{
value = iFind->second << (BLEND_FACTOR_BASE_SHIFT + BLEND_FACTOR_ITEM_BITS * item);
}
return value;
}
-std::map<std::string_view, Type> BUFFER_MODES{
-#define DECL_BUFFER_MODE(x) {#x, BufferMode::x}
- DECL_BUFFER_MODE(NONE),
- DECL_BUFFER_MODE(AUTO),
- DECL_BUFFER_MODE(COLOR),
- DECL_BUFFER_MODE(STENCIL),
- DECL_BUFFER_MODE(COLOR_STENCIL),
-};
+const std::map<std::string_view, Type>& GetBufferModes()
+{
+ static const std::map<std::string_view, Type> BUFFER_MODES{
+ #define DECL_BUFFER_MODE(x) {#x, BufferMode::x}
+ DECL_BUFFER_MODE(NONE),
+ DECL_BUFFER_MODE(AUTO),
+ DECL_BUFFER_MODE(COLOR),
+ DECL_BUFFER_MODE(STENCIL),
+ DECL_BUFFER_MODE(COLOR_STENCIL),
+ #undef DECL_BUFFER_MODE
+ };
+ return BUFFER_MODES;
+}
Type InterpretBufferMode(const std::string_view& str)
{
Type value = 0x0;
- auto iFind = BUFFER_MODES.find(str);
- if(iFind != BUFFER_MODES.end())
+ auto iFind = GetBufferModes().find(str);
+ if(iFind != GetBufferModes().end())
{
value = iFind->second << BUFFER_MODE_SHIFT;
}
return value;
}
-std::map<std::string_view, Type (*)(const std::string_view&)> RENDERER_STATE_PROCESSORS{
- {"DEPTH_WRITE", [](const std::string_view&) -> Type { return DEPTH_WRITE; }},
- {"DEPTH_TEST", [](const std::string_view&) -> Type { return DEPTH_TEST; }},
- {"CULL_FRONT", [](const std::string_view&) -> Type { return CULL_FRONT; }},
- {"CULL_BACK", [](const std::string_view&) -> Type { return CULL_BACK; }},
- {"ALPHA_BLEND", [](const std::string_view&) -> Type { return ALPHA_BLEND; }},
- {"DEPTH_FUNC", [](const std::string_view& arg) -> Type {
- Type value = (arg[0] == ':') ? (InterpretComparison(std::string_view(arg.data() + 1, arg.size() - 1)) << DEPTH_FUNCTION_SHIFT) : 0x0;
- return value;
- }},
- {"BLEND_SRC_RGB", [](const std::string_view& arg) -> Type {
- Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 0) : 0x0;
- return value;
- }},
- {"BLEND_DST_RGB", [](const std::string_view& arg) -> Type {
- Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 1) : 0x0;
- return value;
- }},
- {"BLEND_SRC_ALPHA", [](const std::string_view& arg) -> Type {
- Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 2) : 0x0;
- return value;
- }},
- {"BLEND_DST_ALPHA", [](const std::string_view& arg) -> Type {
- Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 3) : 0x0;
- return value;
- }},
- {"BUFFER_MODE", [](const std::string_view& arg) -> Type {
- Type value = (arg[0] == ':') ? InterpretBufferMode(std::string_view(arg.data() + 1, arg.size() - 1)) : 0x0;
- return value;
- }},
-};
+const std::map<std::string_view, Type (*)(const std::string_view&)>& GetRendererStateProcessors()
+{
+ static const std::map<std::string_view, Type (*)(const std::string_view&)> RENDERER_STATE_PROCESSORS{
+ {"DEPTH_WRITE", [](const std::string_view&) -> Type { return DEPTH_WRITE; }},
+ {"DEPTH_TEST", [](const std::string_view&) -> Type { return DEPTH_TEST; }},
+ {"CULL_FRONT", [](const std::string_view&) -> Type { return CULL_FRONT; }},
+ {"CULL_BACK", [](const std::string_view&) -> Type { return CULL_BACK; }},
+ {"ALPHA_BLEND", [](const std::string_view&) -> Type { return ALPHA_BLEND; }},
+ {"DEPTH_FUNC", [](const std::string_view& arg) -> Type {
+ Type value = (arg[0] == ':') ? (InterpretComparison(std::string_view(arg.data() + 1, arg.size() - 1)) << DEPTH_FUNCTION_SHIFT) : 0x0;
+ return value;
+ }},
+ {"BLEND_SRC_RGB", [](const std::string_view& arg) -> Type {
+ Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 0) : 0x0;
+ return value;
+ }},
+ {"BLEND_DST_RGB", [](const std::string_view& arg) -> Type {
+ Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 1) : 0x0;
+ return value;
+ }},
+ {"BLEND_SRC_ALPHA", [](const std::string_view& arg) -> Type {
+ Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 2) : 0x0;
+ return value;
+ }},
+ {"BLEND_DST_ALPHA", [](const std::string_view& arg) -> Type {
+ Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 3) : 0x0;
+ return value;
+ }},
+ {"BUFFER_MODE", [](const std::string_view& arg) -> Type {
+ Type value = (arg[0] == ':') ? InterpretBufferMode(std::string_view(arg.data() + 1, arg.size() - 1)) : 0x0;
+ return value;
+ }},
+ };
+ return RENDERER_STATE_PROCESSORS;
+}
} // namespace
{
auto iNextToken = std::find(string, iEnd, '|');
auto iColon = std::find(string, iNextToken, ':');
- auto i = RENDERER_STATE_PROCESSORS.find(std::string_view(string, iColon - string));
- if(i != RENDERER_STATE_PROCESSORS.end() && size_t(std::distance(string, iNextToken)) >= i->first.size())
+ auto i = GetRendererStateProcessors().find(std::string_view(string, iColon - string));
+ if(i != GetRendererStateProcessors().end() && size_t(std::distance(string, iNextToken)) >= i->first.size())
{
value |= i->second(std::string_view(string + i->first.size(), iNextToken - iColon));
}
-#ifndef DALI_SCENE3D_LOADERERER_INTERPRET_RENDERER_STATE_H
-#define DALI_SCENE3D_LOADERERER_INTERPRET_RENDERER_STATE_H
+#ifndef DALI_SCENE3D_LOADERER_INTERPRET_RENDERER_STATE_H
+#define DALI_SCENE3D_LOADERER_INTERPRET_RENDERER_STATE_H
/*
* Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
} // namespace RendererState
} // namespace Dali::Scene3D::Loader
-#endif //DALI_SCENE3D_LOADERERER_INTERPRET_RENDERER_STATE_H
+#endif //DALI_SCENE3D_LOADERER_INTERPRET_RENDERER_STATE_H
-#ifndef DALI_SCENE3D_LOADERERERERER_RESOURCE_BUNDLE_H_
-#define DALI_SCENE3D_LOADERERERERER_RESOURCE_BUNDLE_H_
+#ifndef DALI_SCENE3D_LOADERERERER_RESOURCE_BUNDLE_H_
+#define DALI_SCENE3D_LOADERERERER_RESOURCE_BUNDLE_H_
/*
* Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
} // namespace Dali::Scene3D::Loader
-#endif //DALI_SCENE3D_LOADERERERERER_RESOURCE_BUNDLE_H_
+#endif //DALI_SCENE3D_LOADERERERER_RESOURCE_BUNDLE_H_
// INTERNAL
#include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-scene3d/internal/model-components/model-node-impl.h>
#include <dali-scene3d/public-api/loader/blend-shape-details.h>
#include <dali-scene3d/public-api/loader/skinning-details.h>
#include <dali-scene3d/public-api/loader/utils.h>
-//#define DEBUG_SCENE_DEFINITION
-//#define DEBUG_JOINTS
+// #define DEBUG_SCENE_DEFINITION
+// #define DEBUG_JOINTS
#if defined(DEBUG_SCENE_DEFINITION) || defined(DEBUG_JOINTS)
#define DEBUG_ONLY(x) x
{
namespace
{
-const std::string JOINT_MATRIX{"jointMatrix"};
-
-const std::map<Property::Type, Constraint (*)(Actor&, Property::Index)> sConstraintFactory = {
- {Property::Type::BOOLEAN,
- [](Actor& a, Property::Index i) {
- return Constraint::New<bool>(a, i, [](bool& current, const PropertyInputContainer& inputs) {
- current = inputs[0]->GetBoolean();
- });
- }},
- {Property::Type::INTEGER,
- [](Actor& a, Property::Index i) {
- return Constraint::New<int>(a, i, [](int& current, const PropertyInputContainer& inputs) {
- current = inputs[0]->GetInteger();
- });
- }},
- {Property::Type::FLOAT,
- [](Actor& a, Property::Index i) {
- return Constraint::New<float>(a, i, EqualToConstraint());
- }},
- {Property::Type::VECTOR2,
- [](Actor& a, Property::Index i) {
- return Constraint::New<Vector2>(a, i, EqualToConstraint());
- }},
- {Property::Type::VECTOR3,
- [](Actor& a, Property::Index i) {
- return Constraint::New<Vector3>(a, i, EqualToConstraint());
- }},
- {Property::Type::VECTOR4,
- [](Actor& a, Property::Index i) {
- return Constraint::New<Vector4>(a, i, EqualToConstraint());
- }},
- {Property::Type::MATRIX,
- [](Actor& a, Property::Index i) {
- return Constraint::New<Matrix>(a, i, EqualToConstraint());
- }},
- {Property::Type::MATRIX3,
- [](Actor& a, Property::Index i) {
- return Constraint::New<Matrix3>(a, i, EqualToConstraint());
- }},
- {Property::Type::ROTATION,
- [](Actor& a, Property::Index i) {
- return Constraint::New<Quaternion>(a, i, EqualToConstraint());
- }},
-};
+
+const std::map<Property::Type, Constraint (*)(Actor&, Property::Index)>& GetConstraintFactory()
+{
+ static const std::map<Property::Type, Constraint (*)(Actor&, Property::Index)> sConstraintFactory = {
+ {Property::Type::BOOLEAN,
+ [](Actor& a, Property::Index i) {
+ return Constraint::New<bool>(a, i, [](bool& current, const PropertyInputContainer& inputs) {
+ current = inputs[0]->GetBoolean();
+ });
+ }},
+ {Property::Type::INTEGER,
+ [](Actor& a, Property::Index i) {
+ return Constraint::New<int>(a, i, [](int& current, const PropertyInputContainer& inputs) {
+ current = inputs[0]->GetInteger();
+ });
+ }},
+ {Property::Type::FLOAT,
+ [](Actor& a, Property::Index i) {
+ return Constraint::New<float>(a, i, EqualToConstraint());
+ }},
+ {Property::Type::VECTOR2,
+ [](Actor& a, Property::Index i) {
+ return Constraint::New<Vector2>(a, i, EqualToConstraint());
+ }},
+ {Property::Type::VECTOR3,
+ [](Actor& a, Property::Index i) {
+ return Constraint::New<Vector3>(a, i, EqualToConstraint());
+ }},
+ {Property::Type::VECTOR4,
+ [](Actor& a, Property::Index i) {
+ return Constraint::New<Vector4>(a, i, EqualToConstraint());
+ }},
+ {Property::Type::MATRIX,
+ [](Actor& a, Property::Index i) {
+ return Constraint::New<Matrix>(a, i, EqualToConstraint());
+ }},
+ {Property::Type::MATRIX3,
+ [](Actor& a, Property::Index i) {
+ return Constraint::New<Matrix3>(a, i, EqualToConstraint());
+ }},
+ {Property::Type::ROTATION,
+ [](Actor& a, Property::Index i) {
+ return Constraint::New<Quaternion>(a, i, EqualToConstraint());
+ }},
+ };
+ return sConstraintFactory;
+}
struct ResourceReflector : IResourceReflector
{
{
mCreationContext.mXforms.modelStack.Push(n.GetLocalSpace());
- Actor a = n.CreateActor(mCreationContext);
+ ModelNode a = n.CreateModelNode(mCreationContext);
if(!mActorStack.empty())
{
mActorStack.back().Add(a);
mCreationContext.mXforms.modelStack.Pop();
}
- Actor GetRoot() const
+ ModelNode GetRoot() const
{
return mRoot;
}
private:
NodeDefinition::CreateParams& mCreationContext;
- std::vector<Actor> mActorStack;
- Actor mRoot;
+ std::vector<ModelNode> mActorStack;
+ ModelNode mRoot;
};
bool IsAncestor(const SceneDefinition& scene, Index ancestor, Index node, Index rootHint = INVALID_INDEX)
propJointMatrix = ConfigureJointMatrix(parent, ancestor, propJointMatrix);
}
- auto myPropJointMatrix = actor.GetPropertyIndex(JOINT_MATRIX);
+ auto myPropJointMatrix = actor.GetPropertyIndex(Skinning::JOINT_MATRIX);
if(myPropJointMatrix == Property::INVALID_INDEX)
{
- myPropJointMatrix = actor.RegisterProperty(JOINT_MATRIX, Matrix{false});
+ myPropJointMatrix = actor.RegisterProperty(Skinning::JOINT_MATRIX, Matrix{false});
Constraint constraint = Constraint::New<Matrix>(actor, propJointMatrix, [](Matrix& output, const PropertyInputContainer& inputs) {
Matrix jointMatrix{false};
jointMatrix.SetTransformComponents(Vector3::ONE, inputs[0]->GetQuaternion(), inputs[1]->GetVector3());
requests.end());
}
-void ConfigureBoneMatrix(const Matrix& ibm, Actor joint, Shader& shader, Index& boneIdx)
+void ConfigureBoneMatrix(const Matrix& ibm, ModelNode joint, ModelPrimitive primitive, Index& boneIdx)
{
// Register bone transform on shader.
- char propertyNameBuffer[32];
- snprintf(propertyNameBuffer, sizeof(propertyNameBuffer), "%s[%d]", Skinning::BONE_UNIFORM_NAME.c_str(), boneIdx);
- DALI_ASSERT_DEBUG(shader.GetPropertyIndex(propertyNameBuffer) == Property::INVALID_INDEX);
- auto propBoneXform = shader.RegisterProperty(propertyNameBuffer, Matrix{false});
-
- // Constrain bone matrix to joint transform.
- Constraint constraint = Constraint::New<Matrix>(shader, propBoneXform, [ibm](Matrix& output, const PropertyInputContainer& inputs) {
- Matrix::Multiply(output, ibm, inputs[0]->GetMatrix());
- });
-
- auto propJointMatrix = joint.GetPropertyIndex(JOINT_MATRIX);
- constraint.AddSource(Source{joint, propJointMatrix});
- constraint.Apply();
-
+ Internal::GetImplementation(joint).SetBoneMatrix(ibm, primitive, boneIdx);
++boneIdx;
}
Visit(iNode, choices, refCounterVisitor);
}
-Actor SceneDefinition::CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params)
+ModelNode SceneDefinition::CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params)
{
ActorCreatorVisitor actorCreatorVisitor(params);
if(iTarget != Property::INVALID_INDEX)
{
auto propertyType = cr.mTarget.GetPropertyType(iTarget);
- auto iFind = sConstraintFactory.find(propertyType);
- if(iFind == sConstraintFactory.end())
+ auto iFind = GetConstraintFactory().find(propertyType);
+ if(iFind == GetConstraintFactory().end())
{
onError(FormatString("node '%s': Property '%s' has unsupported type '%s'; ignored.",
sourceName,
auto rootJoint = root.FindChildByName(node->mName);
DALI_ASSERT_ALWAYS(!!rootJoint);
- DALI_ASSERT_DEBUG(rootJoint.GetPropertyIndex(JOINT_MATRIX) == Property::INVALID_INDEX);
- auto propJointMatrix = rootJoint.RegisterProperty(JOINT_MATRIX, Matrix{false});
+ DALI_ASSERT_DEBUG(rootJoint.GetPropertyIndex(Skinning::JOINT_MATRIX) == Property::INVALID_INDEX);
+ auto propJointMatrix = rootJoint.RegisterProperty(Skinning::JOINT_MATRIX, Matrix{false});
Constraint constraint = Constraint::New<Matrix>(rootJoint, propJointMatrix, [](Matrix& output, const PropertyInputContainer& inputs) {
output.SetTransformComponents(Vector3::ONE, inputs[0]->GetQuaternion(), inputs[1]->GetVector3());
});
for(auto& joint : skeleton.mJoints)
{
auto node = GetNode(joint.mNodeIdx);
- Actor actor = rootActor.FindChildByName(node->mName);
- ConfigureBoneMatrix(joint.mInverseBindMatrix, actor, request.mShader, boneIdx);
+ ModelNode modelNode = ModelNode::DownCast(rootActor.FindChildByName(node->mName));
+ if(!modelNode)
+ {
+ continue;
+ }
+ ConfigureBoneMatrix(joint.mInverseBindMatrix, modelNode, request.mPrimitive, boneIdx);
}
}
}
if(mesh.first.HasBlendShapes())
{
Actor actor = rootActor.FindChildByName(node->mName);
-
- // Sets the property to be animated.
- BlendShapes::ConfigureProperties(mesh, i.mShader, actor);
+ Scene3D::ModelNode node = Scene3D::ModelNode::DownCast(actor);
+ if(!node)
+ {
+ continue;
+ }
+ BlendShapes::BlendShapeData data;
+ data.components = 0x0;
+ for(auto&& blendShape : mesh.first.mBlendShapes)
+ {
+ data.weights.push_back(blendShape.weight);
+ data.components |= (blendShape.deltas.IsDefined() * BlendShapes::Component::POSITIONS) |
+ (blendShape.normals.IsDefined() * BlendShapes::Component::NORMALS) | (blendShape.tangents.IsDefined() * BlendShapes::Component::TANGENTS);
+ }
+ for(auto&& factor : mesh.second.blendShapeUnnormalizeFactor)
+ {
+ data.unnormalizeFactors.push_back(factor);
+ }
+ data.version = mesh.first.mBlendShapeVersion;
+ data.bufferOffset = mesh.second.blendShapeBufferOffset;
+ data.mActor = actor;
+ Internal::GetImplementation(node).SetBlendShapeData(data, i.mPrimitive);
}
}
}
-#ifndef DALI_SCENE3D_LOADERER_SCENE_DEFINITION_H_
-#define DALI_SCENE3D_LOADERER_SCENE_DEFINITION_H_
+#ifndef DALI_SCENE3D_LOADER_SCENE_DEFINITION_H_
+#define DALI_SCENE3D_LOADER_SCENE_DEFINITION_H_
/*
* Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
/*
* @brief Given a bundle of @a resources that are loaded, and customization
- * @a choices, this method traverses the scene, creating the actors and renderers
+ * @a choices, this method traverses the scene, creating the ModelNodes and renderers
* from node definitions.
- * @return Handle to the root actor.
+ * @return Handle to the root node.
*/
- Actor CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params);
+ ModelNode CreateNodes(Index iNode, const Customization::Choices& choices, NodeDefinition::CreateParams& params);
/*
* @brief Creates / update a registry of mappings from customization tags to
} // namespace Dali::Scene3D::Loader
-#endif //DALI_SCENE3D_LOADERER_SCENE_DEFINITION_H_
+#endif //DALI_SCENE3D_LOADER_SCENE_DEFINITION_H_
}
};
-void RetrieveBlendShapeComponents(const std::vector<MeshDefinition::BlendShape>& blendShapes, bool& hasPositions, bool& hasNormals, bool& hasTangents)
-{
- for(const auto& blendShape : blendShapes)
- {
- hasPositions = hasPositions || blendShape.deltas.IsDefined();
- hasNormals = hasNormals || blendShape.normals.IsDefined();
- hasTangents = hasTangents || blendShape.tangents.IsDefined();
- }
-}
-
uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
{
Hash hash;
bool hasPositions = false;
bool hasNormals = false;
bool hasTangents = false;
- RetrieveBlendShapeComponents(meshDef.mBlendShapes, hasPositions, hasNormals, hasTangents);
+ meshDef.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
if(hasPositions)
{
hash.Add("MORPHPOS");
bool hasPositions = false;
bool hasNormals = false;
bool hasTangents = false;
- RetrieveBlendShapeComponents(meshDef.mBlendShapes, hasPositions, hasNormals, hasTangents);
+ meshDef.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
if(hasPositions)
{
{
namespace
{
-const std::string SHADER_HINT_OUTPUT_IS_TRANSPARENT("OUTPUT_IS_TRANSPARENT"); ///< Might generate transparent alpha from opaque inputs.
-const std::string SHADER_HINT_MODIFIES_GEOMETRY("MODIFIES_GEOMETRY"); ///< Might change position of vertices, this option disables any culling optimizations.
-
+const char* SHADER_HINT_OUTPUT_IS_TRANSPARENT("OUTPUT_IS_TRANSPARENT"); ///< Might generate transparent alpha from opaque inputs.
+const char* SHADER_HINT_MODIFIES_GEOMETRY("MODIFIES_GEOMETRY"); ///< Might change position of vertices, this option disables any culling optimizations.
} // namespace
ShaderDefinition::ShaderDefinition(const ShaderDefinition& other)
-#ifndef DALI_SCENE3D_LOADERER_SKELETON_H
-#define DALI_SCENE3D_LOADERER_SKELETON_H
+#ifndef DALI_SCENE3D_LOADER_SKELETON_H
+#define DALI_SCENE3D_LOADER_SKELETON_H
/*
* Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
} // namespace Dali::Scene3D::Loader
-#endif //DALI_SCENE3D_LOADERER_SKELETON_H
+#endif //DALI_SCENE3D_LOADER_SKELETON_H
{
const unsigned int Skinning::MAX_JOINTS = 64;
-const std::string Skinning::BONE_UNIFORM_NAME = "uBone";
+const char* Skinning::BONE_UNIFORM_NAME = "uBone";
+const char* Skinning::JOINT_MATRIX = "jointMatrix";
} // namespace Dali::Scene3D::Loader
// EXTERNAL INCLUDES
#include <dali/public-api/rendering/shader.h>
+#include <dali/public-api/animation/constraint.h>
#include <string>
// INTERNAL INCLUDES
#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/loader/index.h>
+#include <dali-scene3d/public-api/model-components/model-primitive.h>
namespace Dali::Scene3D::Loader
{
struct DALI_SCENE3D_API Skinning
{
+public:
+ struct BoneData
+ {
+ Dali::Scene3D::ModelPrimitive primitive;
+ Dali::Constraint constraint;
+ Scene3D::Loader::Index boneIndex;
+ std::string propertyName;
+ Matrix inverseMatrix;
+ };
+
/*
* @brief Upper limit on the number of joints supported.
*/
/*
* @brief Name of bone matrix uniform (array).
*/
- static const std::string BONE_UNIFORM_NAME;
+ static const char* BONE_UNIFORM_NAME;
+ static const char* JOINT_MATRIX;
Skinning() = delete;
};
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/public-api/model-components/material.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/rendering/sampler.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/material-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+Material Material::New()
+{
+ Internal::MaterialPtr internal = Internal::Material::New();
+
+ return Material(internal.Get());
+}
+
+Material::Material()
+{
+}
+
+Material::Material(const Material& mateiral) = default;
+
+Material::Material(Material&& rhs) = default;
+
+Material::~Material()
+{
+}
+
+Material& Material::operator=(const Material& handle) = default;
+
+Material& Material::operator=(Material&& rhs) = default;
+
+Material Material::DownCast(BaseHandle handle)
+{
+ return Material(dynamic_cast<Dali::Scene3D::Internal::Material*>(handle.GetObjectPtr()));
+}
+
+Material::Material(Dali::Scene3D::Internal::Material* internal)
+: BaseHandle(internal)
+{
+}
+
+// Public Method
+
+void Material::SetProperty(Dali::Property::Index index, Dali::Property::Value propertyValue)
+{
+ GetImplementation(*this).SetProperty(index, propertyValue);
+}
+
+Dali::Property::Value Material::GetProperty(Dali::Property::Index index) const
+{
+ return GetImplementation(*this).GetProperty(index);
+}
+
+void Material::SetTexture(Scene3D::Material::TextureType index, Dali::Texture texture)
+{
+ GetImplementation(*this).SetTexture(index, texture);
+}
+
+Dali::Texture Material::GetTexture(Scene3D::Material::TextureType index)
+{
+ return GetImplementation(*this).GetTexture(index);
+}
+
+void Material::SetSampler(Scene3D::Material::TextureType index, Dali::Sampler sampler)
+{
+ GetImplementation(*this).SetSampler(index, sampler);
+}
+
+Dali::Sampler Material::GetSampler(Scene3D::Material::TextureType index)
+{
+ return GetImplementation(*this).GetSampler(index);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_H
+#define DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/rendering/sampler.h>
+#include <dali/public-api/rendering/texture.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/api.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+// Forward declarations.
+namespace Internal
+{
+class Material;
+} // namespace Internal
+
+/**
+ * @addtogroup dali_scene3d_model_components_material
+ * @{
+ */
+
+/**
+ * @brief Class for setting Material properties of 3D models
+ *
+ * @SINCE_2_2.99
+ *
+ * @note This Material class is for setting Material properties of 3D models.
+ * This Material supports properties and textures for PBR.
+ * Also, Material can be shared with multiple ModelPrimitives and if the value is modified,
+ * the rendering results of all ModelPrimitives using this Material will be changed.
+ *
+ * @code
+ * Material material = Material::New();
+ * ModelPrimitive modelPrimitive = ModelPrimitive::New();
+ * modelPrimitive.SetMaterial(material);
+ * material.SetProperty(PropertyIndex, PropertyValue);
+ * @endcode
+ */
+class DALI_SCENE3D_API Material : public Dali::BaseHandle
+{
+public:
+ /**
+ * @brief Enumeration for the start and end property ranges for material.
+ * @SINCE_2_2.99
+ */
+ enum PropertyRange
+ {
+ PROPERTY_START_INDEX = PROPERTY_REGISTRATION_START_INDEX, ///< Start index is used by the property registration macro. @SINCE_2_2.99
+ MATERIAL_PROPERTY_START_INDEX = PROPERTY_START_INDEX, ///< Start index of Control properties. @SINCE_2_2.99
+ MATERIAL_PROPERTY_END_INDEX = MATERIAL_PROPERTY_START_INDEX + 1000, ///< Reserving 1000 property indices. @SINCE_2_2.99
+
+ ANIMATABLE_PROPERTY_START_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX, ///< @SINCE_2_2.99
+ ANIMATABLE_PROPERTY_END_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 1000, ///< Reserve animatable property indices, @SINCE_2_2.99
+ };
+
+ /**
+ * @brief Enumeration for the instance of properties belonging to the Material class.
+ * @SINCE_2_2.99
+ */
+ struct Property
+ {
+ enum
+ {
+ /**
+ * @brief Name of material.
+ * @details type Property::STRING.
+ * @SINCE_2_2.99
+ */
+ NAME = MATERIAL_PROPERTY_START_INDEX,
+
+ /**
+ * @brief Property for the URL of the base color texture.
+ * @details Type Property::STRING.
+ * @SINCE_2_2.99
+ */
+ BASE_COLOR_URL,
+
+ /**
+ * @brief Property for the base color factor of the material surface.
+ * @details Type Property::VECTOR4.
+ * @SINCE_2_2.99
+ */
+ BASE_COLOR_FACTOR,
+
+ /**
+ * @brief Property for the URL of the metallic-roughness texture.
+ * @details Type Property::STRING.
+ * @SINCE_2_2.99
+ */
+ METALLIC_ROUGHNESS_URL,
+
+ /**
+ * @brief Property for the metallic factor of the material surface.
+ * @details Type Property::FLOAT.
+ * @SINCE_2_2.99
+ */
+ METALLIC_FACTOR,
+
+ /**
+ * @brief Property for the roughness factor of the material surface.
+ * @details Type Property::FLOAT.
+ * @SINCE_2_2.99
+ */
+ ROUGHNESS_FACTOR,
+
+ /**
+ * @brief Property for the URL of the normal texture.
+ * @details Type Property::STRING.
+ * @SINCE_2_2.99
+ */
+ NORMAL_URL,
+
+ /**
+ * @brief Property for the scale factor applied to normal vectors.
+ * @details Type Property::FLOAT.
+ * @SINCE_2_2.99
+ */
+ NORMAL_SCALE,
+
+ /**
+ * @brief Property for the URL of the occlusion texture.
+ * @details Type Property::STRING.
+ * @SINCE_2_2.99
+ */
+ OCCLUSION_URL,
+
+ /**
+ * @brief Property for the occlusion strength of the material surface.
+ * @details Type Property::FLOAT.
+ * @SINCE_2_2.99
+ */
+ OCCLUSION_STRENGTH,
+
+ /**
+ * @brief Property for the URL of the emissive texture.
+ * @details Type Property::STRING.
+ * @SINCE_2_2.99
+ */
+ EMISSIVE_URL,
+
+ /**
+ * @brief Emissive factor Property.
+ * @details type Property::VECTOR3.
+ * @SINCE_2_2.99
+ */
+ EMISSIVE_FACTOR,
+
+ /**
+ * @brief Alpha mode Property.
+ * @details type Property::INTEGER.
+ * @SINCE_2_2.99
+ */
+ ALPHA_MODE,
+
+ /**
+ * @brief Alpha cutoff Property.
+ * @details type Property::FLOAT.
+ * @SINCE_2_2.99
+ */
+ ALPHA_CUTOFF,
+
+ /**
+ * @brief Double sided Property.
+ * @details type Property::BOOLEAN.
+ * @SINCE_2_2.99
+ */
+ DOUBLE_SIDED,
+
+ /**
+ *@brief Index of refraction (IOR) of the material surface
+ *@details type Property::FLOAT
+ * @SINCE_2_2.99
+ */
+ IOR,
+
+ /**
+ * @brief Property for the URL of the specular texture.
+ * @details Type Property::STRING.
+ * @SINCE_2_2.99
+ */
+ SPECULAR_URL,
+
+ /**
+ *@brief Property for the specular factor of the material surface.
+ *@details Type Property::FLOAT.
+ * @SINCE_2_2.99
+ */
+ SPECULAR_FACTOR,
+
+ /**
+ * @brief Property for the URL of the specular color texture.
+ * @details Type Property::STRING.
+ * @SINCE_2_2.99
+ */
+ SPECULAR_COLOR_URL,
+
+ /**
+ *@brief Property for the specular color factor of the material surface.
+ *@details Type Property::VECTOR3.
+ * @SINCE_2_2.99
+ */
+ SPECULAR_COLOR_FACTOR,
+ };
+ };
+
+ enum TextureType
+ {
+ /**
+ * @brief Base Color Texture Property.
+ * @SINCE_2_2.99
+ * @note This texture represents the base color of the material. In most cases, this will be the diffuse color of the material.
+ */
+ BASE_COLOR,
+
+ /**
+ * @brief Metallic Roughness Texture Property.
+ * @SINCE_2_2.99
+ * @note This texture represents the metallicness and roughness of the material. This texture can be used to make the material look more metallic or rough.
+ */
+ METALLIC_ROUGHNESS,
+
+ /**
+ * @brief Normal Texture Property.
+ * @SINCE_2_2.99
+ * @note This texture represents the surface of the material. This texture can be used to make the surface of the material look smooth or rough.
+ */
+ NORMAL,
+
+ /**
+ * @brief Occlusion Texture Property.
+ * @SINCE_2_2.99
+ * @note This texture represents the depth of the material. This texture can be used to make the material look more three-dimensional.
+ */
+ OCCLUSION,
+
+ /**
+ * @brief Emissive Texture Property.
+ * @SINCE_2_2.99
+ * @note This texture makes the material look like it's emitting light. This texture can be used to make the material look like it's glowing.
+ */
+ EMISSIVE,
+
+ /**
+ * @brief Specular Texture Property.
+ * @SINCE_2_2.99
+ * @note This texture represents the specular reflection of the material. This texture can be used to make the material look more reflective.
+ */
+ SPECULAR,
+
+ /**
+ * @brief Specular Color Texture Property.
+ * @SINCE_2_2.99
+ * @note This texture represents the color of the specular reflection of the material. This texture can be used to set the color of the specular reflection of the material.
+ */
+ SPECULAR_COLOR,
+ };
+
+ enum AlphaModeType
+ {
+ /**
+ * @brief This indicates that the material is fully opaque and that the alpha value should be ignored.
+ * @SINCE_2_2.99
+ */
+ OPAQUE,
+
+ /**
+ * @brief This indicates that the material is either fully opaque or fully transparent depending on the alpha value. The alpha value is used to mask out areas of the material that should be transparent.
+ * @SINCE_2_2.99
+ */
+ MASK,
+
+ /**
+ * @brief This indicates that the material is transparent and that the alpha value should be used to blend the material with the background.
+ * @SINCE_2_2.99
+ */
+ BLEND,
+ };
+
+public: // Creation & Destruction
+ /**
+ * @brief Create an initialized Material.
+ *
+ * @SINCE_2_2.99
+ * @return A handle to a newly allocated Dali resource
+ */
+ static Material New();
+
+ /**
+ * @brief Creates an uninitialized Material.
+ *
+ * Only derived versions can be instantiated. Calling member
+ * functions with an uninitialized Dali::Object is not allowed.
+ *
+ * @SINCE_2_2.99
+ */
+ Material();
+
+ /**
+ * @brief Destructor.
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ *
+ * @SINCE_2_2.99
+ */
+ ~Material();
+
+ /**
+ * @brief Copy constructor.
+ *
+ * @SINCE_2_2.99
+ * @param[in] material Handle to an object
+ */
+ Material(const Material& material);
+
+ /**
+ * @brief Move constructor
+ *
+ * @SINCE_2_2.99
+ * @param[in] rhs A reference to the moved handle
+ */
+ Material(Material&& rhs);
+
+ /**
+ * @brief Assignment operator.
+ *
+ * @SINCE_2_2.99
+ * @param[in] material Handle to an object
+ * @return reference to this
+ */
+ Material& operator=(const Material& material);
+
+ /**
+ * @brief Move assignment
+ *
+ * @SINCE_2_2.99
+ * @param[in] rhs A reference to the moved handle
+ * @return A reference to this
+ */
+ Material& operator=(Material&& rhs);
+
+ /**
+ * @brief Downcasts an Object handle to Material.
+ *
+ * If handle points to a Material, the downcast produces valid handle.
+ * If not, the returned handle is left uninitialized.
+ *
+ * @SINCE_2_2.99
+ * @param[in] handle Handle to an object
+ * @return Handle to a Material or an uninitialized handle
+ */
+ static Material DownCast(BaseHandle handle);
+
+public: // Public Method
+ /**
+ * @brief Sets the value of an existing property.
+ * @note BaseHandle is not subclass of Handle. So this API is not use Handle.SetProperty
+ *
+ * @SINCE_2_2.99
+ * @param[in] index The index of the property
+ * @param[in] propertyValue The new value of the property
+ */
+ void SetProperty(Dali::Property::Index index, Dali::Property::Value propertyValue);
+
+ /**
+ * @brief Retrieves a property value.
+ * @note BaseHandle is not subclass of Handle. So this API is not use Handle.SetProperty
+ *
+ * @SINCE_2_2.99
+ * @param[in] index The index of the property
+ * @return The property value
+ * @note This returns the value set by SetProperty() or the animation target value if it is being animated.
+ */
+ Dali::Property::Value GetProperty(Dali::Property::Index index) const;
+
+ /**
+ * @brief Convenience function for obtaining a property of a known type.
+ *
+ * @SINCE_2_2.99
+ * @param[in] index The index of the property
+ * @return The property value
+ * @pre The property types match i.e. PropertyTypes::Get<T>() is equal to GetPropertyType(index).
+ * @see GetProperty()
+ */
+ template<typename T>
+ T GetProperty(Dali::Property::Index index) const
+ {
+ Dali::Property::Value value = GetProperty(index);
+
+ return T(value.Get<T>());
+ }
+
+ /**
+ * @brief Sets the texture for a given texture type.
+ *
+ * @SINCE_2_2.99
+ * @param[in] index The texture type index
+ * @param[in] texture The texture to set.
+ */
+ void SetTexture(Scene3D::Material::TextureType index, Dali::Texture texture);
+
+ /**
+ * @brief Gets the texture for a given texture type.
+ *
+ * @SINCE_2_2.99
+ * @param[in] index The texture type index
+ * @return The texture at the given index.
+ */
+ Dali::Texture GetTexture(Scene3D::Material::TextureType index);
+
+ /**
+ * @brief Sets the sampler for a given texture type.
+ *
+ * @SINCE_2_2.99
+ * @param[in] index The texture type index
+ * @param[in] sampler The sampler to use for this texture type
+ */
+ void SetSampler(Scene3D::Material::TextureType index, Dali::Sampler sampler);
+
+ /**
+ * @brief Gets the sampler for a given texture type.
+ *
+ * @SINCE_2_2.99
+ * @param[in] index The texture type index
+ * @return The sampler used for this texture type
+ */
+ Dali::Sampler GetSampler(Scene3D::Material::TextureType index);
+
+public: // Not intended for application developers
+ /// @cond internal
+ /**
+ * @brief Creates a handle using the Scene3D::Internal implementation.
+ *
+ * @param[in] implementation The Material implementation
+ */
+ DALI_INTERNAL Material(Dali::Scene3D::Internal::Material* implementation);
+ /// @endcond
+};
+
+/**
+ * @}
+ */
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_H
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/public-api/model-components/model-node.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/actors/custom-actor.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/model-node-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+ModelNode ModelNode::New()
+{
+ return Scene3D::Internal::ModelNode::New();
+}
+
+ModelNode::ModelNode()
+{
+}
+
+ModelNode::ModelNode(const ModelNode& modelNode) = default;
+
+ModelNode::ModelNode(ModelNode&& rhs) = default;
+
+ModelNode::~ModelNode()
+{
+}
+
+ModelNode& ModelNode::operator=(const ModelNode& handle) = default;
+
+ModelNode& ModelNode::operator=(ModelNode&& rhs) = default;
+
+ModelNode ModelNode::DownCast(BaseHandle handle)
+{
+ ModelNode result;
+
+ CustomActor custom = Dali::CustomActor::DownCast(handle);
+ if(custom)
+ {
+ CustomActorImpl& customImpl = custom.GetImplementation();
+
+ Internal::ModelNode* impl = dynamic_cast<Internal::ModelNode*>(&customImpl);
+
+ if(impl)
+ {
+ result = ModelNode(customImpl.GetOwner());
+ }
+ }
+
+ return result;
+}
+
+ModelNode::ModelNode(Internal::ModelNode& implementation)
+: CustomActor(implementation)
+{
+}
+
+ModelNode::ModelNode(Dali::Internal::CustomActor* internal)
+: CustomActor(internal)
+{
+ // Can have a NULL pointer so we only need to check if the internal implementation is our class
+ // when there is a value.
+ if(internal)
+ {
+ DALI_ASSERT_DEBUG(dynamic_cast<Internal::ModelNode*>(&CustomActor(internal).GetImplementation()));
+ }
+}
+
+// Public Method
+
+uint32_t ModelNode::GetModelPrimitiveCount() const
+{
+ return Internal::GetImplementation(*this).GetModelPrimitiveCount();
+}
+
+void ModelNode::AddModelPrimitive(ModelPrimitive modelPrimitive)
+{
+ Internal::GetImplementation(*this).AddModelPrimitive(modelPrimitive);
+}
+
+void ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
+{
+ Internal::GetImplementation(*this).RemoveModelPrimitive(modelPrimitive);
+}
+
+void ModelNode::RemoveModelPrimitive(uint32_t index)
+{
+ Internal::GetImplementation(*this).RemoveModelPrimitive(index);
+}
+
+ModelPrimitive ModelNode::GetModelPrimitive(uint32_t index) const
+{
+ return Internal::GetImplementation(*this).GetModelPrimitive(index);
+}
+
+ModelNode ModelNode::FindChildModelNodeByName(std::string_view nodeName)
+{
+ return Internal::GetImplementation(*this).FindChildModelNodeByName(nodeName);
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_H
+#define DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/actors/custom-actor.h>
+#include <dali/public-api/common/dali-common.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/model-components/model-primitive.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+// Forward declarations.
+
+namespace Internal
+{
+class ModelNode;
+}
+/**
+ * @addtogroup dali_scene3d_model_components_model_node
+ * @{
+ */
+
+/**
+ * @brief ModelNode is a class for representing the Node of Model in Scene3D.
+ * ModelNode contains multiple ModelPrimitives and allows easy access and modification of Material information that ModelPrimitive has.
+ * If a 3D format file is loaded by Model, ModelNode is created internally to construct the model.
+ * In addition, you can create a Custom ModelNode using ModelPrimitive and Material directly and add it to Model.
+ *
+ * @SINCE_2_2.99
+ *
+ * @code
+ * ModelNode modelNode = ModelNode::New();
+ * ModelPrimitive modelPrimitive = ModelPrimitive::New();
+ * modelNode.AddModelPrimitive(modelPrimitive);
+ *
+ * Material material = Material::New();
+ * modelPrimitive.SetMaterial(material);
+ * material.SetProperty(PropertyIndex, PropertyValue);
+ * @endcode
+ */
+class DALI_SCENE3D_API ModelNode : public Dali::CustomActor
+{
+public:
+ /**
+ * @brief Create an initialized ModelNode.
+ *
+ * @SINCE_2_2.99
+ * @return A handle to a newly allocated Dali resource
+ */
+ static ModelNode New();
+
+ /**
+ * @brief Creates an uninitialized ModelNode.
+ *
+ * Only derived versions can be instantiated. Calling member
+ * functions with an uninitialized Dali::Object is not allowed.
+ *
+ * @SINCE_2_2.99
+ */
+ ModelNode();
+
+ /**
+ * @brief Destructor.
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ *
+ * @SINCE_2_2.99
+ */
+ ~ModelNode();
+
+ /**
+ * @brief Copy constructor.
+ *
+ * @SINCE_2_2.99
+ * @param[in] modelNode Handle to an object
+ */
+ ModelNode(const ModelNode& modelNode);
+
+ /**
+ * @brief Move constructor
+ *
+ * @SINCE_2_2.99
+ * @param[in] rhs A reference to the moved handle
+ */
+ ModelNode(ModelNode&& rhs);
+
+ /**
+ * @brief Assignment operator.
+ *
+ * @SINCE_2_2.99
+ * @param[in] modelNode Handle to an object
+ * @return reference to this
+ */
+ ModelNode& operator=(const ModelNode& modelNode);
+
+ /**
+ * @brief Move assignment
+ *
+ * @SINCE_2_2.99
+ * @param[in] rhs A reference to the moved handle
+ * @return A reference to this
+ */
+ ModelNode& operator=(ModelNode&& rhs);
+
+ /**
+ * @brief Downcasts an Object handle to ModelNode.
+ *
+ * If handle points to a ModelNode, the downcast produces valid handle.
+ * If not, the returned handle is left uninitialized.
+ *
+ * @SINCE_2_2.99
+ * @param[in] handle Handle to an object
+ * @return Handle to a ModelNode or an uninitialized handle
+ */
+ static ModelNode DownCast(BaseHandle handle);
+
+public: // Public Method
+
+ /**
+ * @brief Gets the number of ModelPrimitives this node has.
+ *
+ * @SINCE_2_2.99
+ * @return The number of ModelPrimitives this node has.
+ */
+ uint32_t GetModelPrimitiveCount() const;
+
+ /**
+ * @brief Appends a ModelPrimitive to this node.
+ *
+ * @SINCE_2_2.99
+ * @param[in] modelPrimitive The ModelPrimitive to append.
+ */
+ void AddModelPrimitive(ModelPrimitive modelPrimitive);
+
+ /**
+ * @brief Removes a ModelPrimitive from this node.
+ *
+ * @SINCE_2_2.99
+ * @param[in] modelPrimitive The ModelPrimitive to remove.
+ */
+ void RemoveModelPrimitive(ModelPrimitive modelPrimitive);
+
+ /**
+ * @brief Removes a ModelPrimitive from this node by index.
+ *
+ * @SINCE_2_2.99
+ * @param[in] index The index of the ModelPrimitive to remove.
+ */
+ void RemoveModelPrimitive(uint32_t index);
+
+ /**
+ * @brief Gets a ModelPrimitive by index.
+ *
+ * @SINCE_2_2.99
+ * @param[in] index The index of the ModelPrimitive to get.
+ * @return The ModelPrimitive at the given index, or an empty handle if the index is out of range.
+ */
+ ModelPrimitive GetModelPrimitive(uint32_t index) const;
+
+ /**
+ * @brief Returns a child ModelNode object with a name that matches nodeName.
+ *
+ * @param[in] nodeName The name of the child ModelNode object you want to find.
+ * @return Returns a child ModelNode object with a name that matches nodeName. If there is no corresponding child ModelNode object, it returns an empty ModelNode object.
+ */
+ ModelNode FindChildModelNodeByName(std::string_view nodeName);
+
+public: // Not intended for application developers
+ /// @cond internal
+ /**
+ * @brief Creates a handle using the Scene3D::Internal implementation.
+ *
+ * @param[in] implementation The ModelNodel implementation
+ */
+ DALI_INTERNAL ModelNode(Internal::ModelNode& implementation);
+
+ /**
+ * @brief Allows the creation of this Control from an Internal::CustomActor pointer.
+ *
+ * @param[in] internal A pointer to the internal CustomActor
+ */
+ DALI_INTERNAL ModelNode(Dali::Internal::CustomActor* internal);
+ /// @endcond
+};
+
+/**
+ * @}
+ */
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_COMPONENTS_MODEL_NODE_H
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/public-api/model-components/model-primitive.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/model-components/model-primitive-impl.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+ModelPrimitive ModelPrimitive::New()
+{
+ Internal::ModelPrimitivePtr internal = Internal::ModelPrimitive::New();
+
+ return ModelPrimitive(internal.Get());
+}
+
+ModelPrimitive::ModelPrimitive()
+{
+}
+
+ModelPrimitive::ModelPrimitive(const ModelPrimitive& modelPrimitive) = default;
+
+ModelPrimitive::ModelPrimitive(ModelPrimitive&& rhs) = default;
+
+ModelPrimitive::~ModelPrimitive()
+{
+}
+
+ModelPrimitive& ModelPrimitive::operator=(const ModelPrimitive& handle) = default;
+
+ModelPrimitive& ModelPrimitive::operator=(ModelPrimitive&& rhs) = default;
+
+ModelPrimitive ModelPrimitive::DownCast(BaseHandle handle)
+{
+ return ModelPrimitive(dynamic_cast<Dali::Scene3D::Internal::ModelPrimitive*>(handle.GetObjectPtr()));
+}
+
+ModelPrimitive::ModelPrimitive(Dali::Scene3D::Internal::ModelPrimitive* internal)
+: BaseHandle(internal)
+{
+}
+
+// Public Method
+void ModelPrimitive::SetGeometry(Dali::Geometry geometry)
+{
+ GetImplementation(*this).SetGeometry(geometry);
+}
+
+Dali::Geometry ModelPrimitive::GetGeometry() const
+{
+ return GetImplementation(*this).GetGeometry();
+}
+
+void ModelPrimitive::SetMaterial(Dali::Scene3D::Material material)
+{
+ GetImplementation(*this).SetMaterial(material);
+}
+
+Dali::Scene3D::Material ModelPrimitive::GetMaterial() const
+{
+ return GetImplementation(*this).GetMaterial();
+}
+
+} // namespace Scene3D
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_H
+#define DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_H
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/rendering/renderer.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/model-components/material.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+//Forward declarations.
+namespace Internal
+{
+class ModelPrimitive;
+} // namespace Internal
+
+/**
+ * @addtogroup dali_scene3d_model_components_model_primitive
+ * @{
+ */
+
+/**
+ * @brief This ModelPrimitive class is required to draw the mesh geometry defined by the user.
+ * Users can set Dali::Geometry and Material to ModelPrimitive using SetGeometry and SetMaterial methods respectively.
+ * When ModelPrimitive added to ModelNode using ModelNode::AddModelPrimitive() method, the Geometry is rendered on the screen according to the Material settings.
+ *
+ * @SINCE_2_2.99
+ *
+ * If you load resources from 3D format files such as glTF using Model class, ModelPrimitive is also created internally.
+ * In this case, blendShape morphing or skeletal animation defined in the format can be used.
+ * However, for the custom ModelPrimitive that is created by user, blendShape morphing or skeletal animation is not supported.
+ */
+class DALI_SCENE3D_API ModelPrimitive : public Dali::BaseHandle
+{
+public: // Creation & Destruction
+ /**
+ * @brief Create an initialized ModelPrimitive.
+ *
+ * @SINCE_2_2.99
+ * @return A handle to a newly allocated Dali resource
+ */
+ static ModelPrimitive New();
+
+ /**
+ * @brief Creates an uninitialized ModelPrimitive.
+ *
+ * Only derived versions can be instantiated. Calling member
+ * functions with an uninitialized Dali::Object is not allowed.
+ *
+ * @SINCE_2_2.99
+ */
+ ModelPrimitive();
+
+ /**
+ * @brief Destructor.
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ *
+ * @SINCE_2_2.99
+ */
+ ~ModelPrimitive();
+
+ /**
+ * @brief Copy constructor.
+ *
+ * @SINCE_2_2.99
+ * @param[in] modelPrimtive Handle to an object
+ */
+ ModelPrimitive(const ModelPrimitive& modelPrimtive);
+
+ /**
+ * @brief Move constructor
+ *
+ * @SINCE_2_2.99
+ * @param[in] rhs A reference to the moved handle
+ */
+ ModelPrimitive(ModelPrimitive&& rhs);
+
+ /**
+ * @brief Assignment operator.
+ *
+ * @SINCE_2_2.99
+ * @param[in] modelPrimitive Handle to an object
+ * @return reference to this
+ */
+ ModelPrimitive& operator=(const ModelPrimitive& modelPrimitive);
+
+ /**
+ * @brief Move assignment
+ *
+ * @SINCE_2_2.99
+ * @param[in] rhs A reference to the moved handle
+ * @return A reference to this
+ */
+ ModelPrimitive& operator=(ModelPrimitive&& rhs);
+
+ /**
+ * @brief Downcasts an Object handle to ModelPrimitive.
+ *
+ * If handle points to a ModelPrimitive, the downcast produces valid handle.
+ * If not, the returned handle is left uninitialized.
+ *
+ * @SINCE_2_2.99
+ * @param[in] handle Handle to an object
+ * @return Handle to a ModelPrimitive or an uninitialized handle
+ */
+ static ModelPrimitive DownCast(BaseHandle handle);
+
+public: // Public Method
+ /**
+ * @brief Set the geometry for this renderer.
+ *
+ * @SINCE_2_2.99
+ * @param[in] geometry The geometry to set.
+ */
+ void SetGeometry(Dali::Geometry geometry);
+
+ /**
+ * @brief Get the geometry for this renderer.
+ *
+ * @SINCE_2_2.99
+ * @return The geometry for this renderer.
+ */
+ Dali::Geometry GetGeometry() const;
+
+ /**
+ * @brief Sets the material for this primitive.
+ *
+ * @SINCE_2_2.99
+ * @param[in] material The material
+ */
+ void SetMaterial(Material material);
+
+ /**
+ * @brief Retrieves a material.
+ *
+ * @SINCE_2_2.99
+ * @return The material handle
+ */
+ Material GetMaterial() const;
+
+public: // Not intended for application developers
+ /// @cond internal
+ /**
+ * @brief Creates a handle using the Scene3D::Internal implementation.
+ *
+ * @param[in] implementation The ModelPrimitive implementation
+ */
+ DALI_INTERNAL ModelPrimitive(Dali::Scene3D::Internal::ModelPrimitive* implementation);
+ /// @endcond
+};
+
+/**
+ * @}
+ */
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
namespace TextureManager
{
-std::string AddTexture(Texture& texture)
+std::string AddTexture(Texture& texture, bool preMultiplied)
{
TextureSet set = TextureSet::New();
set.SetTexture(0u, texture);
- return AddTexture(set);
+ return AddTexture(set, preMultiplied);
}
-std::string AddTexture(TextureSet& textureSet)
+std::string AddTexture(TextureSet& textureSet, bool preMultiplied)
{
auto visualFactory = Toolkit::VisualFactory::Get();
auto& textureMgr = GetImplementation(visualFactory).GetTextureManager();
- return textureMgr.AddExternalTexture(textureSet);
+ return textureMgr.AddExternalTexture(textureSet, preMultiplied);
}
TextureSet RemoveTexture(const std::string& textureUrl)
#define DALI_TOOLKIT_DEVEL_API_TEXTURE_MANAGER_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* @note this method does not check for duplicates,
* if same Texture is added multiple times, a different URL is returned each time
* @param[in] texture the Texture to add
+ * @param[in] preMultiplied Whether this external texture preMultiplied or not. Default as false.
* @return the Url string representing this texture
*/
-DALI_TOOLKIT_API std::string AddTexture(Texture& texture);
+DALI_TOOLKIT_API std::string AddTexture(Texture& texture, bool preMultiplied = false);
/**
* @brief Add a TextureSet to texture manager
* @note this method does not check for duplicates,
* if same TextureSet is added multiple times, a different URL is returned each time
* @param[in] textureSet the TextureSet to add
+ * @param[in] preMultiplied Whether this external texture preMultiplied or not. Default as false.
* @return the Url string representing this texture
*/
-DALI_TOOLKIT_API std::string AddTexture(TextureSet& textureSet);
+DALI_TOOLKIT_API std::string AddTexture(TextureSet& textureSet, bool preMultiplied = false);
/**
* @brief Removes a TextureSet from toolkit
{
#define TOKEN_STRING(x) #x
-const std::string KEYNAME_ACTORS = "actors";
-const std::string KEYNAME_ENTRY_TRANSITION = "entryTransition";
-const std::string KEYNAME_EXIT_TRANSITION = "exitTransition";
-const std::string KEYNAME_INCLUDES = "includes";
-const std::string KEYNAME_INHERIT = "inherit";
-const std::string KEYNAME_MAPPINGS = "mappings";
-const std::string KEYNAME_NAME = "name";
-const std::string KEYNAME_SIGNALS = "signals";
-const std::string KEYNAME_STATES = "states";
-const std::string KEYNAME_STYLES = "styles";
-const std::string KEYNAME_TEMPLATES = "templates";
-const std::string KEYNAME_TRANSITIONS = "transitions";
-const std::string KEYNAME_TYPE = "type";
-const std::string KEYNAME_VISUALS = "visuals";
-
-const std::string PROPERTIES = "properties";
-const std::string ANIMATABLE_PROPERTIES = "animatableProperties";
+const char* KEYNAME_ACTORS = "actors";
+const char* KEYNAME_ENTRY_TRANSITION = "entryTransition";
+const char* KEYNAME_EXIT_TRANSITION = "exitTransition";
+const char* KEYNAME_INCLUDES = "includes";
+const char* KEYNAME_INHERIT = "inherit";
+const char* KEYNAME_MAPPINGS = "mappings";
+const char* KEYNAME_SIGNALS = "signals";
+const char* KEYNAME_STATES = "states";
+const char* KEYNAME_STYLES = "styles";
+const char* KEYNAME_TEMPLATES = "templates";
+const char* KEYNAME_TRANSITIONS = "transitions";
+const char* KEYNAME_TYPE = "type";
+const char* KEYNAME_VISUALS = "visuals";
+
+const char* PROPERTIES = "properties";
+const char* ANIMATABLE_PROPERTIES = "animatableProperties";
typedef std::vector<const TreeNode*> TreeNodeList;
namespace
{
-const std::string READING_INFO_TYPE_NAME = "name";
-const std::string READING_INFO_TYPE_ROLE = "role";
-const std::string READING_INFO_TYPE_DESCRIPTION = "description";
-const std::string READING_INFO_TYPE_STATE = "state";
-const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
-const std::string READING_INFO_TYPE_SEPARATOR = "|";
+const char* READING_INFO_TYPE_NAME = "name";
+const char* READING_INFO_TYPE_ROLE = "role";
+const char* READING_INFO_TYPE_DESCRIPTION = "description";
+const char* READING_INFO_TYPE_STATE = "state";
+const char* READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
+const char* READING_INFO_TYPE_SEPARATOR = "|";
} // namespace
namespace Dali
const char* const IMAGE_BRDF_FILE_NAME = "brdfLUT.png";
// glTF file extension
-const std::string GLTF_EXT(".gltf");
+const char* GLTF_EXT(".gltf");
/**
* cube map face index
* The alignment depends on the alignment value of the text label (Use Text::VerticalAlignment enumerations).
*/
const float VERTICAL_ALIGNMENT_TABLE[Text::VerticalAlignment::BOTTOM + 1] =
- {
+{
0.0f, // VerticalAlignment::TOP
0.5f, // VerticalAlignment::CENTER
1.0f // VerticalAlignment::BOTTOM
};
-const std::string TEXT_FIT_ENABLE_KEY("enable");
-const std::string TEXT_FIT_MIN_SIZE_KEY("minSize");
-const std::string TEXT_FIT_MAX_SIZE_KEY("maxSize");
-const std::string TEXT_FIT_STEP_SIZE_KEY("stepSize");
-const std::string TEXT_FIT_FONT_SIZE_KEY("fontSize");
-const std::string TEXT_FIT_FONT_SIZE_TYPE_KEY("fontSizeType");
+const char* TEXT_FIT_ENABLE_KEY("enable");
+const char* TEXT_FIT_MIN_SIZE_KEY("minSize");
+const char* TEXT_FIT_MAX_SIZE_KEY("maxSize");
+const char* TEXT_FIT_STEP_SIZE_KEY("stepSize");
+const char* TEXT_FIT_FONT_SIZE_KEY("fontSize");
+const char* TEXT_FIT_FONT_SIZE_TYPE_KEY("fontSizeType");
#if defined(DEBUG_ENABLED)
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
#endif
const Scripting::StringEnum AUTO_SCROLL_STOP_MODE_TABLE[] =
- {
+{
{"IMMEDIATE", Toolkit::TextLabel::AutoScrollStopMode::IMMEDIATE},
{"FINISH_LOOP", Toolkit::TextLabel::AutoScrollStopMode::FINISH_LOOP},
};
#define GET_LOCALE_TEXT(string) dgettext("dali-toolkit", string)
#endif
-const std::string TEXT_SELECTION_POPUP_BUTTON_STYLE_NAME("TextSelectionPopupButton");
+const char* TEXT_SELECTION_POPUP_BUTTON_STYLE_NAME("TextSelectionPopupButton");
const Dali::Vector4 DEFAULT_OPTION_PRESSED_COLOR(Dali::Vector4(0.24f, 0.72f, 0.8f, 1.0f));
const float DEFAULT_OPTION_PRESSED_CORNER_RADIUS = 0.0f;
const Dali::Vector4 DEFAULT_LABEL_PADDING(Dali::Vector4(24.0f, 24.0f, 14.0f, 14.0f));
const char* const OPTION_PASTE("optionPaste"); // "Paste" popup option.
const char* const OPTION_CLIPBOARD("optionClipboard"); // "Clipboard" popup option.
-const std::string IDS_LTR("IDS_LTR");
-const std::string RTL_DIRECTION("RTL");
+const char* IDS_LTR("IDS_LTR");
+const char* RTL_DIRECTION("RTL");
BaseHandle Create()
{
// Whether to mirror the list of buttons (for right to left languages)
bool mirror = false;
#if defined(__GLIBC__)
- char* idsLtr = GET_LOCALE_TEXT(IDS_LTR.c_str());
+ char* idsLtr = GET_LOCALE_TEXT(IDS_LTR);
if(NULL != idsLtr)
{
- mirror = (0 == strcmp(idsLtr, RTL_DIRECTION.c_str()));
+ mirror = (0 == strcmp(idsLtr, RTL_DIRECTION));
if(mirror)
{
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
namespace Internal
{
-ImageUrl::ImageUrl(Texture& texture)
+ImageUrl::ImageUrl(Texture& texture, bool preMultiplied)
{
- mUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
+ mUrl = Dali::Toolkit::TextureManager::AddTexture(texture, preMultiplied);
}
ImageUrl::ImageUrl(const EncodedImageBuffer& encodedImageBuffer)
}
}
-ImageUrlPtr ImageUrl::New(Texture& texture)
+ImageUrlPtr ImageUrl::New(Texture& texture, bool preMultiplied)
{
- ImageUrlPtr imageUrlPtr = new ImageUrl(texture);
+ ImageUrlPtr imageUrlPtr = new ImageUrl(texture, preMultiplied);
return imageUrlPtr;
}
#define DALI_TOOLKIT_INTERNAL_IMAGE_URL_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @brief Constructor.
*/
- ImageUrl(Texture& texture);
+ ImageUrl(Texture& texture, bool preMultiplied);
/**
* @brief Constructor.
/**
* @copydoc Dali::Toolkit::ImageUrl::New
*/
- static ImageUrlPtr New(Texture& texture);
+ static ImageUrlPtr New(Texture& texture, bool preMultiplied);
/**
* @copydoc Dali::Toolkit::ImageUrl::New
DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_TEXT_PERFORMANCE_MARKER, false);
-const std::string KEY_C_NAME = "c";
-const std::string KEY_V_NAME = "v";
-const std::string KEY_X_NAME = "x";
-const std::string KEY_A_NAME = "a";
-const std::string KEY_INSERT_NAME = "Insert";
+const char* KEY_C_NAME = "c";
+const char* KEY_V_NAME = "v";
+const char* KEY_X_NAME = "x";
+const char* KEY_A_NAME = "a";
+const char* KEY_INSERT_NAME = "Insert";
} // namespace
constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
-const std::string EMPTY_STRING("");
+const char* EMPTY_STRING = "";
} // namespace
}
}
-const std::string& Controller::InputFontHandler::GetInputFontFamily(const Controller& controller)
+std::string Controller::InputFontHandler::GetInputFontFamily(const Controller& controller)
{
if(NULL != controller.mImpl->mEventData)
{
struct Controller::InputFontHandler
{
static void SetInputFontFamily(Controller& controller, const std::string& fontFamily);
- static const std::string& GetInputFontFamily(const Controller& controller);
+ static std::string GetInputFontFamily(const Controller& controller);
static void SetInputFontWeight(const Controller& controller, FontWeight weight);
static bool IsInputFontWeightDefined(const Controller& controller);
static FontWeight GetInputFontWeight(const Controller& controller);
namespace
{
-const std::string EMPTY_STRING("");
+const char* EMPTY_STRING = "";
}
namespace Dali::Toolkit::Text
}
}
-const std::string& Controller::InputProperties::GetInputShadowProperties(const Controller& controller)
+std::string Controller::InputProperties::GetInputShadowProperties(const Controller& controller)
{
return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.shadowProperties : EMPTY_STRING;
}
}
}
-const std::string& Controller::InputProperties::GetInputUnderlineProperties(const Controller& controller)
+std::string Controller::InputProperties::GetInputUnderlineProperties(const Controller& controller)
{
return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.underlineProperties : EMPTY_STRING;
}
}
}
-const std::string& Controller::InputProperties::GetInputEmbossProperties(const Controller& controller)
+std::string Controller::InputProperties::GetInputEmbossProperties(const Controller& controller)
{
return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.embossProperties : controller.GetDefaultEmbossProperties();
}
}
}
-const std::string& Controller::InputProperties::GetInputOutlineProperties(const Controller& controller)
+std::string Controller::InputProperties::GetInputOutlineProperties(const Controller& controller)
{
return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.outlineProperties : controller.GetDefaultOutlineProperties();
}
static void SetInputShadowProperties(Controller& controller, const std::string& shadowProperties);
- static const std::string& GetInputShadowProperties(const Controller& controller);
+ static std::string GetInputShadowProperties(const Controller& controller);
static void SetInputUnderlineProperties(Controller& controller, const std::string& underlineProperties);
- static const std::string& GetInputUnderlineProperties(const Controller& controller);
+ static std::string GetInputUnderlineProperties(const Controller& controller);
static void SetInputEmbossProperties(Controller& controller, const std::string& embossProperties);
- static const std::string& GetInputEmbossProperties(const Controller& controller);
+ static std::string GetInputEmbossProperties(const Controller& controller);
static void SetInputOutlineProperties(Controller& controller, const std::string& outlineProperties);
- static const std::string& GetInputOutlineProperties(const Controller& controller);
+ static std::string GetInputOutlineProperties(const Controller& controller);
static void SetInputModePassword(Controller& controller, bool passwordInput);
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
#endif
-const std::string EMPTY_STRING("");
+const char* EMPTY_STRING = "";
const char* const PLACEHOLDER_TEXT = "text";
const char* const PLACEHOLDER_TEXT_FOCUSED = "textFocused";
}
}
-const std::string& Controller::PlaceholderHandler::GetPlaceholderFontFamily(const Controller& controller)
+std::string Controller::PlaceholderHandler::GetPlaceholderFontFamily(const Controller& controller)
{
if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
{
static void SetPlaceholderText(Controller& controller, PlaceholderType type, const std::string& text);
static void GetPlaceholderText(const Controller& controller, PlaceholderType type, std::string& text);
static void SetPlaceholderFontFamily(Controller& controller, const std::string& placeholderTextFontFamily);
- static const std::string& GetPlaceholderFontFamily(const Controller& controller);
+ static std::string GetPlaceholderFontFamily(const Controller& controller);
static void SetPlaceholderTextFontWeight(Controller& controller, FontWeight weight);
static bool IsPlaceholderTextFontWeightDefined(const Controller& controller);
static FontWeight GetPlaceholderTextFontWeight(const Controller& controller);
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
#endif
-const std::string EMPTY_STRING("");
+const char* EMPTY_STRING = "";
template<typename Type>
void EnsureCreated(Type*& object)
}
}
-const std::string& Controller::GetDefaultFontFamily() const
+std::string Controller::GetDefaultFontFamily() const
{
return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.family : EMPTY_STRING;
}
PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily);
}
-const std::string& Controller::GetPlaceholderFontFamily() const
+std::string Controller::GetPlaceholderFontFamily() const
{
return PlaceholderHandler::GetPlaceholderFontFamily(*this);
}
mImpl->mEmbossDefaults->properties = embossProperties;
}
-const std::string& Controller::GetDefaultEmbossProperties() const
+std::string Controller::GetDefaultEmbossProperties() const
{
return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING;
}
mImpl->mOutlineDefaults->properties = outlineProperties;
}
-const std::string& Controller::GetDefaultOutlineProperties() const
+std::string Controller::GetDefaultOutlineProperties() const
{
return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING;
}
InputFontHandler::SetInputFontFamily(*this, fontFamily);
}
-const std::string& Controller::GetInputFontFamily() const
+std::string Controller::GetInputFontFamily() const
{
return InputFontHandler::GetInputFontFamily(*this);
}
InputProperties::SetInputShadowProperties(*this, shadowProperties);
}
-const std::string& Controller::GetInputShadowProperties() const
+std::string Controller::GetInputShadowProperties() const
{
return InputProperties::GetInputShadowProperties(*this);
}
InputProperties::SetInputUnderlineProperties(*this, underlineProperties);
}
-const std::string& Controller::GetInputUnderlineProperties() const
+std::string Controller::GetInputUnderlineProperties() const
{
return InputProperties::GetInputUnderlineProperties(*this);
}
InputProperties::SetInputEmbossProperties(*this, embossProperties);
}
-const std::string& Controller::GetInputEmbossProperties() const
+std::string Controller::GetInputEmbossProperties() const
{
return InputProperties::GetInputEmbossProperties(*this);
}
InputProperties::SetInputOutlineProperties(*this, outlineProperties);
}
-const std::string& Controller::GetInputOutlineProperties() const
+std::string Controller::GetInputOutlineProperties() const
{
return InputProperties::GetInputOutlineProperties(*this);
}
}
}
-const std::string& Controller::GetInputStrikethroughProperties() const
+std::string Controller::GetInputStrikethroughProperties() const
{
return (NULL != mImpl->mEventData) ? mImpl->mEventData->mInputStyle.strikethroughProperties : EMPTY_STRING;
}
*
* @return The default font family.
*/
- const std::string& GetDefaultFontFamily() const;
+ std::string GetDefaultFontFamily() const;
/**
* @brief Sets the placeholder text font family.
*
* @return The placeholder text font family
*/
- const std::string& GetPlaceholderFontFamily() const;
+ std::string GetPlaceholderFontFamily() const;
/**
* @brief Sets the default font weight.
*
* @return The emboss's properties string.
*/
- const std::string& GetDefaultEmbossProperties() const;
+ std::string GetDefaultEmbossProperties() const;
/**
* @brief Sets the outline's properties string.
*
* @return The outline's properties string.
*/
- const std::string& GetDefaultOutlineProperties() const;
+ std::string GetDefaultOutlineProperties() const;
/**
* @brief Sets the default line spacing.
*
* @return The input text's font family name.
*/
- const std::string& GetInputFontFamily() const;
+ std::string GetInputFontFamily() const;
/**
* @brief Sets the input font's weight.
*
* @return The shadow's properties string.
*/
- const std::string& GetInputShadowProperties() const;
+ std::string GetInputShadowProperties() const;
/**
* @brief Sets the input underline's properties string.
*
* @return The underline's properties string.
*/
- const std::string& GetInputUnderlineProperties() const;
+ std::string GetInputUnderlineProperties() const;
/**
* @brief Sets the input emboss's properties string.
*
* @return The emboss's properties string.
*/
- const std::string& GetInputEmbossProperties() const;
+ std::string GetInputEmbossProperties() const;
/**
* @brief Sets input the outline's properties string.
*
* @return The outline's properties string.
*/
- const std::string& GetInputOutlineProperties() const;
+ std::string GetInputOutlineProperties() const;
/**
* @brief Sets the input strikethrough's properties string.
*
* @return The strikethrough's properties string.
*/
- const std::string& GetInputStrikethroughProperties() const;
+ std::string GetInputStrikethroughProperties() const;
/**
* @brief Set the control's interface.
{
namespace
{
-const std::string NONE("none");
-const std::string MULTIPLY("multiply");
+const char* MULTIPLY = "multiply";
} // namespace
void ProcessEmbeddedItem(const Tag& tag, EmbeddedItem& embeddedItem)
{
namespace
{
-const std::string FONT_PREFIX("font-");
-const unsigned int FONT_PREFIX_LENGTH = 5u;
-const unsigned int MIN_FONT_ATTRIBUTE_SIZE = 4u; ///< The minimum length of any of the possible 'weight', 'width' , 'slant' or 'size' values.
const unsigned int MAX_FONT_ATTRIBUTE_SIZE = 15u; ///< The maximum length of any of the possible 'weight', 'width' or 'slant' values.
const float PIXEL_FORMAT_64_FACTOR = 64.f; ///< 64.f is used to convert from point size to 26.6 pixel format.
} // namespace
const char* const HEX_COLOR_TOKEN("0x");
const char* const ALPHA_ONE("FF");
-const std::string BLACK_COLOR("black");
-const std::string WHITE_COLOR("white");
-const std::string RED_COLOR("red");
-const std::string GREEN_COLOR("green");
-const std::string BLUE_COLOR("blue");
-const std::string YELLOW_COLOR("yellow");
-const std::string MAGENTA_COLOR("magenta");
-const std::string CYAN_COLOR("cyan");
-const std::string TRANSPARENT_COLOR("transparent");
-
-const std::string SOLID_UNDERLINE("solid");
-const std::string DASHED_UNDERLINE("dashed");
-const std::string DOUBLE_UNDERLINE("double");
-
-const std::string BEGIN_HORIZONTAL_ALIGNMENT("begin");
-const std::string CENTER_HORIZONTAL_ALIGNMENT("center");
-const std::string END_HORIZONTAL_ALIGNMENT("end");
+const char* BLACK_COLOR("black");
+const char* WHITE_COLOR("white");
+const char* RED_COLOR("red");
+const char* GREEN_COLOR("green");
+const char* BLUE_COLOR("blue");
+const char* YELLOW_COLOR("yellow");
+const char* MAGENTA_COLOR("magenta");
+const char* CYAN_COLOR("cyan");
+const char* TRANSPARENT_COLOR("transparent");
+
+const char* SOLID_UNDERLINE("solid");
+const char* DASHED_UNDERLINE("dashed");
+const char* DOUBLE_UNDERLINE("double");
+
+const char* BEGIN_HORIZONTAL_ALIGNMENT("begin");
+const char* CENTER_HORIZONTAL_ALIGNMENT("center");
+const char* END_HORIZONTAL_ALIGNMENT("end");
} // namespace
{
namespace
{
-const std::string COLOR_KEY("color");
-const std::string OFFSET_KEY("offset");
-const std::string BLUR_RADIUS_KEY("blurRadius");
-const std::string WIDTH_KEY("width");
-const std::string HEIGHT_KEY("height");
-const std::string ENABLE_KEY("enable");
-const std::string TYPE_KEY("type");
-const std::string DASH_WIDTH_KEY("dashWidth");
-const std::string DASH_GAP_KEY("dashGap");
-const std::string TRUE_TOKEN("true");
-const std::string FALSE_TOKEN("false");
+const char* COLOR_KEY = "color";
+const char* OFFSET_KEY = "offset";
+const char* BLUR_RADIUS_KEY = "blurRadius";
+const char* WIDTH_KEY = "width";
+const char* HEIGHT_KEY = "height";
+const char* ENABLE_KEY = "enable";
+const char* TYPE_KEY = "type";
+const char* DASH_WIDTH_KEY = "dashWidth";
+const char* DASH_GAP_KEY = "dashGap";
+const char* TRUE_TOKEN = "true";
} // namespace
bool ParseShadowProperties(const Property::Map& shadowPropertiesMap,
{
namespace
{
-const std::string STYLE_KEY("style");
-const std::string WEIGHT_KEY("weight");
-const std::string WIDTH_KEY("width");
-const std::string SLANT_KEY("slant");
-const std::string FAMILY_KEY("family");
-const std::string TYPE_KEY("type");
-
-const std::string SYSTEM_TOKEN("system");
+const char* WEIGHT_KEY = "weight";
+const char* WIDTH_KEY = "width";
+const char* SLANT_KEY = "slant";
+const char* FAMILY_KEY = "family";
+const char* TYPE_KEY = "type";
+
+const char* SYSTEM_TOKEN = "system";
} // namespace
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
// CLASS HEADER
-#include "texture-cache-manager.h"
+#include <dali-toolkit/internal/texture-manager/texture-cache-manager.h>
// EXTERNAL HEADERS
#include <dali/devel-api/common/hash.h>
return texture;
}
-TextureSet TextureCacheManager::GetExternalTextureSet(const TextureCacheManager::TextureId& textureId)
+TextureCacheManager::ExternalTextureInfo& TextureCacheManager::GetExternalTextureInfo(const TextureCacheManager::TextureId& textureId)
{
- TextureSet textureSet; // empty handle
TextureCacheIndex cacheIndex = GetCacheIndexFromExternalTextureId(textureId);
- if(cacheIndex != INVALID_CACHE_INDEX)
- {
- textureSet = mExternalTextures[cacheIndex.GetIndex()].textureSet;
- }
- return textureSet;
+ DALI_ASSERT_ALWAYS(cacheIndex != INVALID_CACHE_INDEX);
+
+ return mExternalTextures[cacheIndex.GetIndex()];
}
EncodedImageBuffer TextureCacheManager::GetEncodedImageBuffer(const TextureCacheManager::TextureId& bufferId)
return encodedImageBuffer;
}
-std::string TextureCacheManager::AddExternalTexture(const TextureSet& textureSet)
+std::string TextureCacheManager::AddExternalTexture(const TextureSet& textureSet, bool preMultiplied)
{
TextureId textureId = GenerateTextureId(TextureCacheIndex(TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_TEXTURE, mExternalTextures.size()));
- TextureCacheManager::ExternalTextureInfo textureInfo(textureId, textureSet);
+ TextureCacheManager::ExternalTextureInfo textureInfo(textureId, textureSet, preMultiplied);
mExternalTextures.emplace_back(textureInfo);
- DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::AddExternalTexture() : New texture registered. textureId:%d\n", textureInfo.textureId);
+ DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::AddExternalTexture() : New texture registered. textureId:%d, preMultiplied:%d\n", textureInfo.textureId, preMultiplied);
return VisualUrl::CreateTextureUrl(std::to_string(textureInfo.textureId));
}
#define DALI_TOOLKIT_TEXTURE_CACHE_MANAGER_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
static constexpr TextureId INVALID_TEXTURE_ID = TextureManagerType::INVALID_TEXTURE_ID;
static constexpr TextureCacheIndex INVALID_CACHE_INDEX = TextureManagerType::INVALID_CACHE_INDEX;
- using UseAtlas = TextureManagerType::UseAtlas;
- using StorageType = TextureManagerType::StorageType;
- using LoadType = TextureManagerType::LoadType;
- using LoadState = TextureManagerType::LoadState;
- using ReloadPolicy = TextureManagerType::ReloadPolicy;
- using MultiplyOnLoad = TextureManagerType::MultiplyOnLoad;
- using TextureInfo = TextureManagerType::TextureInfo;
+ using UseAtlas = TextureManagerType::UseAtlas;
+ using StorageType = TextureManagerType::StorageType;
+ using LoadType = TextureManagerType::LoadType;
+ using LoadState = TextureManagerType::LoadState;
+ using ReloadPolicy = TextureManagerType::ReloadPolicy;
+ using MultiplyOnLoad = TextureManagerType::MultiplyOnLoad;
+ using TextureInfo = TextureManagerType::TextureInfo;
+ using ExternalTextureInfo = TextureManagerType::ExternalTextureInfo;
public:
/**
Texture GetTexture(const TextureCacheManager::TextureId& textureId, uint32_t textureIndex = 0);
/**
- * @brief Get the external texture set if the texture id is valid
+ * @brief Get the external texture set information if the texture id is valid
* @param[in] textureId The texture Id to look up
- * @return the external texture set, or an empty handle if textureId is not valid
+ * @return the external texture information. Assert if textureId is not valid
*/
- TextureSet GetExternalTextureSet(const TextureCacheManager::TextureId& textureId);
+ TextureCacheManager::ExternalTextureInfo& GetExternalTextureInfo(const TextureCacheManager::TextureId& textureId);
/**
* @brief Get the encoded image buffer
/**
* Adds an external texture to the texture manager
* @param[in] texture The texture to add
+ * @param[in] preMultiplied Whether this external texture preMultiplied or not. Default as false.
* @return string containing the URL for the texture
*/
- std::string AddExternalTexture(const TextureSet& texture);
+ std::string AddExternalTexture(const TextureSet& texture, bool preMultiplied);
/**
* Adds an encoded image buffer to the texture manager
// Private defined structs.
/**
- * @brief This struct is used to manage the life-cycle of ExternalTexture url.
- */
- struct ExternalTextureInfo
- {
- ExternalTextureInfo(const TextureCacheManager::TextureId& textureId,
- const TextureSet& textureSet)
- : textureId(textureId),
- textureSet(textureSet),
- referenceCount(1u)
- {
- }
- TextureCacheManager::TextureId textureId;
- TextureSet textureSet;
- std::int16_t referenceCount;
- };
-
- /**
* @brief This struct is used to manage the life-cycle of EncodedImageBuffer url.
*/
struct EncodedImageBufferInfo
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
// CLASS HEADER
-#include "texture-manager-impl.h"
+#include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
// EXTERNAL HEADERS
#include <dali/devel-api/adaptor-framework/environment-variable.h>
if(location.size() > 0u)
{
TextureId id = std::stoi(location);
- textureSet = mTextureCacheManager.GetExternalTextureSet(id);
- if(textureSet)
+ auto externalTextureInfo = mTextureCacheManager.GetExternalTextureInfo(id);
+ if(externalTextureInfo.textureSet)
{
- preMultiplyOnLoad = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
- textureId = id;
- return textureSet;
+ textureId = id;
+
+ if(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD)
+ {
+ // Change preMultiplyOnLoad value so make caller determine to preMultiplyAlpha or not.
+ // TODO : Should we seperate input and output value?
+ preMultiplyOnLoad = externalTextureInfo.preMultiplied ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+ }
+ return externalTextureInfo.textureSet;
}
}
}
#define DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @copydoc TextureCacheManager::AddExternalTexture
*/
- inline std::string AddExternalTexture(const TextureSet& texture)
+ inline std::string AddExternalTexture(const TextureSet& texture, bool preMultiplied = false)
{
- return mTextureCacheManager.AddExternalTexture(texture);
+ return mTextureCacheManager.AddExternalTexture(texture, preMultiplied);
}
/**
#define DALI_TOOLKIT_TEXTURE_MANAGER_TYPE_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
const TextureId& maskTextureId,
const VisualUrl& url,
const Dali::ImageDimensions& desiredSize,
- const float& scaleFactor,
+ float scaleFactor,
const Dali::FittingMode::Type& fittingMode,
const Dali::SamplingMode::Type& samplingMode,
- const bool& loadSynchronously,
- const bool& cropToMask,
+ bool loadSynchronously,
+ bool cropToMask,
const UseAtlas& useAtlas,
const TextureHash& hash,
- const bool& orientationCorrection,
- const bool& preMultiplyOnLoad,
+ bool orientationCorrection,
+ bool preMultiplyOnLoad,
const Dali::AnimatedImageLoading& animatedImageLoading,
- const std::uint32_t& frameIndex,
- const bool& loadYuvPlanes)
+ std::uint32_t frameIndex,
+ bool loadYuvPlanes)
: url(url),
desiredSize(desiredSize),
useSize(desiredSize),
bool loadYuvPlanes : 1; ///< true if the image should be loaded as yuv planes
};
+/**
+ * @brief This struct is used to manage the life-cycle of ExternalTexture url.
+ */
+struct ExternalTextureInfo
+{
+ ExternalTextureInfo(const TextureId& textureId,
+ const TextureSet& textureSet,
+ bool preMultiplied)
+ : textureId(textureId),
+ textureSet(textureSet),
+ referenceCount(1u),
+ preMultiplied(preMultiplied)
+ {
+ }
+
+ TextureId textureId; ///< The TextureId associated with this ExternalTexture
+ TextureSet textureSet; ///< The external texture
+ std::int16_t referenceCount; ///< The reference count of clients using this ExternalTexture
+ bool preMultiplied : 1; ///< True if the image's color was multiplied by it's alpha
+};
+
} // namespace TextureManagerType
} // namespace Internal
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
}
-ImageUrl ImageUrl::New(Texture& texture)
+ImageUrl ImageUrl::New(Texture& texture, bool preMultiplied)
{
- Toolkit::Internal::ImageUrlPtr internal = Toolkit::Internal::ImageUrl::New(texture);
+ Toolkit::Internal::ImageUrlPtr internal = Toolkit::Internal::ImageUrl::New(texture, preMultiplied);
return ImageUrl(internal.Get());
}
#define DALI_TOOLKIT_IMAGE_URL_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* @brief Create an initialized ImageUrl.
*
* @param[in] texture The texture url is got from external buffer.
+ * @param[in] preMultiplied Whether this external texture preMultiplied or not. Default as false.
* @return A handle to a newly allocated Dali resource.
*/
- static ImageUrl New(Texture& texture);
+ static ImageUrl New(Texture& texture, bool preMultiplied = false);
/**
* @brief Create an initialized ImageUrl.
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
// CLASS HEADER
-#include "image.h"
+#include <dali-toolkit/public-api/image-loader/image.h>
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
{
Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelFormat, width, height);
frameBuffer.AttachColorTexture(texture, 0u, 0u);
- Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture);
+ // TODO : Need to check frameBuffer result use preMultiplied color or not. By default, we use premultiplied
+ Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture, true);
return imageUrl;
}
Dali::Toolkit::ImageUrl GenerateUrl(const Dali::FrameBuffer frameBuffer, uint8_t index)
{
Texture texture = Dali::DevelFrameBuffer::GetColorTexture(frameBuffer, index);
- Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture);
+ // TODO : Need to check frameBuffer result use preMultiplied color or not. By default, we use premultiplied
+ Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture, true);
return imageUrl;
}
-Dali::Toolkit::ImageUrl GenerateUrl(const Dali::PixelData pixelData)
+Dali::Toolkit::ImageUrl GenerateUrl(const Dali::PixelData pixelData, bool preMultiplied)
{
Texture texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
texture.Upload(pixelData);
- Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture);
+ Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture, preMultiplied);
return imageUrl;
}
-Dali::Toolkit::ImageUrl GenerateUrl(const Dali::NativeImageSourcePtr nativeImageSource)
+Dali::Toolkit::ImageUrl GenerateUrl(const Dali::NativeImageSourcePtr nativeImageSource, bool preMultiplied)
{
Texture texture = Dali::Texture::New(*nativeImageSource);
- Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture);
+ Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture, preMultiplied);
return imageUrl;
}
#define DALI_TOOLKIT_IMAGE_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* This Url can be used in visuals to render the pixel data.
* @note This method does not check for duplicates, If same pixel data is entered multiple times, a different URL is returned each time.
* @param[in] pixelData the pixel data to converted to Url
+ * @param[in] preMultiplied Whether this pixel data preMultiplied or not. Default as false.
* @return the ImageUrl representing this pixel data
*/
-DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::PixelData pixelData);
+DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::PixelData pixelData, bool preMultiplied = false);
/**
* @brief Generate a Url from native image source.
* This Url can be used in visuals to render the native image source.
* @note This method does not check for duplicates, If same native image source is entered multiple times, a different URL is returned each time.
* @param[in] nativeImageSource the native image source to converted to Url
+ * @param[in] preMultiplied Whether this native image source preMultiplied or not. Default as false.
* @return the ImageUrl representing this native image source
*/
-DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::NativeImageSourcePtr nativeImageSource);
+DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::NativeImageSourcePtr nativeImageSource, bool preMultiplied = false);
/**
* @brief Generate a Url from encoded image buffer.