From: huayong.xu Date: Mon, 20 Mar 2023 11:08:48 +0000 (+0800) Subject: [Tizen] Backport 7.5 Scene3D for use ModelNode X-Git-Tag: accepted/tizen/7.0/unified/20230424.020513~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F01%2F291501%2F2;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git [Tizen] Backport 7.5 Scene3D for use ModelNode 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 Change namings of gltf-util Signed-off-by: seungho baek Remove Duplicated code in gltf2-util using template Signed-off-by: seungho baek 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 Fix svace/coverity issue (initialize value at Material) Signed-off-by: Eunki, Hong Change public member variable to private Signed-off-by: seungho baek 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 --- diff --git a/automated-tests/src/dali-scene3d-internal/CMakeLists.txt b/automated-tests/src/dali-scene3d-internal/CMakeLists.txt index 06da0de..561e753 100755 --- a/automated-tests/src/dali-scene3d-internal/CMakeLists.txt +++ b/automated-tests/src/dali-scene3d-internal/CMakeLists.txt @@ -15,7 +15,9 @@ SET(TC_SOURCES 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) diff --git a/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp b/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp index 8133fb9..92f66ed 100644 --- a/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp +++ b/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp @@ -202,6 +202,7 @@ int UtcDaliGltfLoaderSuccess1(void) 1.f, 1.f, Vector3(0.2, 0.1, 0.0), + 1.0f, 0.0f, 0.5f, Vector3(0, 0, 1), @@ -209,6 +210,7 @@ int UtcDaliGltfLoaderSuccess1(void) false, true, false, + Scene3D::Material::AlphaModeType::MASK, true, true, { @@ -267,6 +269,7 @@ int UtcDaliGltfLoaderSuccess1(void) }, }, }, + nullptr }, { nullptr, @@ -281,6 +284,7 @@ int UtcDaliGltfLoaderSuccess1(void) 1.f, 1.f, Vector3(0.2, 0.1, 0.0), + -1.0f, 0.04f, 1.0f, Vector3::ONE, @@ -288,6 +292,7 @@ int UtcDaliGltfLoaderSuccess1(void) true, true, false, + Scene3D::Material::AlphaModeType::OPAQUE, true, false, { @@ -337,6 +342,7 @@ int UtcDaliGltfLoaderSuccess1(void) }, }, }, + nullptr, }, }; @@ -355,12 +361,14 @@ int UtcDaliGltfLoaderSuccess1(void) 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); @@ -672,9 +680,9 @@ int UtcDaliGltfLoaderAnimationLoadingTest(void) } 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(Dali::Actor::Property::ID)); END_TEST; diff --git a/automated-tests/src/dali-scene3d-internal/utc-Dali-MaterialImpl.cpp b/automated-tests/src/dali-scene3d-internal/utc-Dali-MaterialImpl.cpp new file mode 100644 index 0000000..088bb6f --- /dev/null +++ b/automated-tests/src/dali-scene3d-internal/utc-Dali-MaterialImpl.cpp @@ -0,0 +1,339 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include + +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(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(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(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 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(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(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(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(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(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(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(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(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(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(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(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(Scene3D ::Material ::Property ::ALPHA_CUTOFF), TEST_LOCATION); + + bool doubleSided = false; + material.SetProperty(Scene3D ::Material ::Property ::DOUBLE_SIDED, doubleSided); + DALI_TEST_EQUALS(doubleSided, material.GetProperty(Scene3D ::Material ::Property ::DOUBLE_SIDED), TEST_LOCATION); + + float ior = 1.0f; + material.SetProperty(Scene3D::Material::Property::IOR, ior); + DALI_TEST_EQUALS(ior, material.GetProperty(Scene3D::Material::Property::IOR), TEST_LOCATION); + + float specularFactor = 1.0f; + material.SetProperty(Scene3D::Material::Property::SPECULAR_FACTOR, specularFactor); + DALI_TEST_EQUALS(specularFactor, material.GetProperty(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(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(renderer.GetPropertyIndex("uColorFactor")), TEST_LOCATION); + DALI_TEST_EQUALS(metallicFactor, renderer.GetProperty(renderer.GetPropertyIndex("uMetallicFactor")), TEST_LOCATION); + DALI_TEST_EQUALS(roughnessFactor, renderer.GetProperty(renderer.GetPropertyIndex("uRoughnessFactor")), TEST_LOCATION); + DALI_TEST_EQUALS(normalScale, renderer.GetProperty(renderer.GetPropertyIndex("uNormalScale")), TEST_LOCATION); + DALI_TEST_EQUALS(emissiveFactor, renderer.GetProperty(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(renderer.GetPropertyIndex("uDielectricSpecular")), TEST_LOCATION); + DALI_TEST_EQUALS(specularFactor, renderer.GetProperty(renderer.GetPropertyIndex("uSpecularFactor")), TEST_LOCATION); + DALI_TEST_EQUALS(specularColorFactor, renderer.GetProperty(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(renderer.GetPropertyIndex("uOpaque")), TEST_LOCATION); + DALI_TEST_EQUALS(mask, renderer.GetProperty(renderer.GetPropertyIndex("uMask")), TEST_LOCATION); + DALI_TEST_EQUALS(alphaCutoff, renderer.GetProperty(renderer.GetPropertyIndex("uAlphaThreshold")), TEST_LOCATION); + + DALI_TEST_EQUALS(DepthTestMode::ON, renderer.GetProperty(Dali::Renderer::Property::DEPTH_TEST_MODE), TEST_LOCATION); + DALI_TEST_EQUALS(FaceCullingMode::BACK, renderer.GetProperty(Dali::Renderer::Property::FACE_CULLING_MODE), TEST_LOCATION); + DALI_TEST_EQUALS(DepthTestMode::ON, renderer.GetProperty(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; +} diff --git a/automated-tests/src/dali-scene3d-internal/utc-Dali-ModelPrimitiveImpl.cpp b/automated-tests/src/dali-scene3d-internal/utc-Dali-ModelPrimitiveImpl.cpp new file mode 100644 index 0000000..00dba92 --- /dev/null +++ b/automated-tests/src/dali-scene3d-internal/utc-Dali-ModelPrimitiveImpl.cpp @@ -0,0 +1,65 @@ +/* + * 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 +#include +#include +#include + +#include + +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 diff --git a/automated-tests/src/dali-scene3d/CMakeLists.txt b/automated-tests/src/dali-scene3d/CMakeLists.txt index 799dd6d..41a55c0 100755 --- a/automated-tests/src/dali-scene3d/CMakeLists.txt +++ b/automated-tests/src/dali-scene3d/CMakeLists.txt @@ -16,7 +16,10 @@ SET(TC_SOURCES 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 diff --git a/automated-tests/src/dali-scene3d/utc-Dali-AnimationDefinition.cpp b/automated-tests/src/dali-scene3d/utc-Dali-AnimationDefinition.cpp index 99b0aaf..a2e052c 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-AnimationDefinition.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-AnimationDefinition.cpp @@ -48,15 +48,16 @@ int UtcDaliAnimationDefinitionReAnimate(void) 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", @@ -66,14 +67,14 @@ int UtcDaliAnimationDefinitionReAnimate(void) 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; @@ -93,27 +94,28 @@ int UtcDaliAnimationDefinitionReAnimateKeyFrames(void) 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; } diff --git a/automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp b/automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp index db5f525..2315bfd 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp @@ -27,28 +27,28 @@ int UtcDaliLoadBvh(void) 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"); @@ -62,7 +62,7 @@ int UtcDaliLoadBvh(void) }; Animation animation = animDef.ReAnimate(getActor); - DALI_TEST_EQUAL(animation.GetDuration(), animDef.mDuration); + DALI_TEST_EQUAL(animation.GetDuration(), animDef.GetDuration()); application.GetScene().Add(root); @@ -98,6 +98,6 @@ int UtcDaliLoadBvhFailed(void) 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; } diff --git a/automated-tests/src/dali-scene3d/utc-Dali-FacialAnimation.cpp b/automated-tests/src/dali-scene3d/utc-Dali-FacialAnimation.cpp index 2e97dc9..100cd72 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-FacialAnimation.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-FacialAnimation.cpp @@ -28,42 +28,43 @@ int UtcDaliLoadFacialAnimation(void) 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"); @@ -82,10 +83,10 @@ int UtcDaliLoadFacialAnimation(void) }; 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; } diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Material.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Material.cpp new file mode 100644 index 0000000..c3fcdd0 --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-Material.cpp @@ -0,0 +1,310 @@ +/* + * 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 +#include +#include +#include + +#include + +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(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(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(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(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(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(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(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(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(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(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(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(Scene3D::Material::Property::EMISSIVE_FACTOR), TEST_LOCATION); + + int alphaMode = 1; + material.SetProperty(Scene3D::Material::Property::ALPHA_MODE, alphaMode); + DALI_TEST_EQUALS(alphaMode, material.GetProperty(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(Scene3D ::Material ::Property ::ALPHA_CUTOFF), TEST_LOCATION); + + bool doubleSided = true; + material.SetProperty(Scene3D ::Material ::Property ::DOUBLE_SIDED, doubleSided); + DALI_TEST_EQUALS(doubleSided, material.GetProperty(Scene3D ::Material ::Property ::DOUBLE_SIDED), TEST_LOCATION); + + float ior = 1.0f; + material.SetProperty(Scene3D::Material::Property::IOR, ior); + DALI_TEST_EQUALS(ior, material.GetProperty(Scene3D::Material::Property::IOR), TEST_LOCATION); + + std::string specularUrl = "specularUrl"; + material.SetProperty(Scene3D::Material::Property::SPECULAR_URL, specularUrl); + DALI_TEST_EQUALS(specularUrl, material.GetProperty(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(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(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(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 diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp index 7840c74..e931b3b 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp @@ -25,6 +25,7 @@ #include #include +#include #include @@ -54,12 +55,8 @@ const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/Animate 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 @@ -152,6 +149,26 @@ int UtcDaliModelNew(void) } // 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(Actor::Property::CONNECTED_TO_SCENE)); + + application.GetScene().Remove(model); + + DALI_TEST_CHECK(!model.GetProperty(Actor::Property::CONNECTED_TO_SCENE)); + + END_TEST; +} + +// Positive test case for a method int UtcDaliModelDownCast(void) { ToolkitTestApplication application; @@ -315,8 +332,8 @@ int UtcDaliModelOnScene02(void) uint32_t modelCount = model.GetModelRoot().GetChildCount(); DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION); - Actor rootActor = model.GetModelRoot(); - Vector3 rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); + Scene3D::ModelNode rootNode = model.GetModelRoot(); + Vector3 rootSize = rootNode.GetProperty(Dali::Actor::Property::SIZE); DALI_TEST_EQUALS(Vector3(2, 2, 1), rootSize, TEST_LOCATION); END_TEST; @@ -367,8 +384,8 @@ int UtcDaliModelGetNaturalSize(void) 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; } @@ -1011,7 +1028,6 @@ int UtcDaliModelAnimation02(void) int UtcDaliModelAnimation03(void) { -#ifdef MULTIPLE_SCENES_MODEL_SUPPORT ToolkitTestApplication application; Scene3D::Model model = Scene3D::Model::New(TEST_DLI_EXERCISE_FILE_NAME); @@ -1040,16 +1056,12 @@ int UtcDaliModelAnimation03(void) 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); @@ -1077,9 +1089,6 @@ int UtcDaliModelCameraGenerate01(void) generatedCamera = model.GenerateCamera(1u); // Fail to generate camera DALI_TEST_CHECK(!generatedCamera); -#else - tet_result(TET_PASS); -#endif END_TEST; } @@ -1126,7 +1135,8 @@ int UtcDaliModelCameraGenerate02(void) 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(Dali::CameraActor::Property::PROJECTION_MODE), rhs.GetProperty(Dali::CameraActor::Property::PROJECTION_MODE), TEST_LOCATION); DALI_TEST_EQUALS(lhs.GetProperty(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE), rhs.GetProperty(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE), TEST_LOCATION); @@ -1134,7 +1144,7 @@ int UtcDaliModelCameraGenerate02(void) { DALI_TEST_EQUALS(lhs.GetProperty(Dali::CameraActor::Property::FIELD_OF_VIEW), rhs.GetProperty(Dali::CameraActor::Property::FIELD_OF_VIEW), TEST_LOCATION); // TODO : Open this test when infinity far projection implement. - //DALI_TEST_EQUALS(lhs.GetProperty(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), rhs.GetProperty(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), TEST_LOCATION); + // DALI_TEST_EQUALS(lhs.GetProperty(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), rhs.GetProperty(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), TEST_LOCATION); } else { @@ -1339,7 +1349,7 @@ int UtcDaliModelResourceCacheCheck(void) 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); } @@ -1350,3 +1360,68 @@ int UtcDaliModelResourceCacheCheck(void) 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 diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ModelNode.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ModelNode.cpp new file mode 100644 index 0000000..e124bc6 --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-ModelNode.cpp @@ -0,0 +1,296 @@ +/* + * 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 +#include +#include +#include + +#include + +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(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(Actor::Property::CONNECTED_TO_SCENE)); + + modelNode.Remove(actor); + + DALI_TEST_CHECK(!actor.GetProperty(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(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(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(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(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(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 diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ModelPrimitive.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ModelPrimitive.cpp new file mode 100644 index 0000000..3719861 --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-ModelPrimitive.cpp @@ -0,0 +1,187 @@ +/* + * 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 +#include +#include +#include + +#include + +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 diff --git a/automated-tests/src/dali-scene3d/utc-Dali-NodeDefinition.cpp b/automated-tests/src/dali-scene3d/utc-Dali-NodeDefinition.cpp index 2b7c319..1de81f7 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-NodeDefinition.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-NodeDefinition.cpp @@ -114,7 +114,7 @@ int UtcDaliNodeDefinitionProperties(void) 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()); DALI_TEST_EQUAL(nodeDef.mPosition, actor.GetProperty(Actor::Property::POSITION).Get()); DALI_TEST_EQUAL(nodeDef.mOrientation, actor.GetProperty(Actor::Property::ORIENTATION).Get()); @@ -220,7 +220,7 @@ int UtcDaliNodeDefinitionRenderable(void) 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); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Image.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Image.cpp index 6dff87b..4767977 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Image.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Image.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -77,10 +77,10 @@ int UtcDaliImageConvertFrameBufferToUrl2(void) END_TEST; } -int UtcDaliImageConvertPixelDataToUrl(void) +int UtcDaliImageConvertPixelDataToUrl01(void) { ToolkitTestApplication application; - tet_infoline("UtcDaliImageConvertPixelDataToUrl"); + tet_infoline("UtcDaliImageConvertPixelDataToUrl01"); unsigned int width(64); unsigned int height(64); @@ -94,10 +94,27 @@ int UtcDaliImageConvertPixelDataToUrl(void) 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(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); @@ -121,6 +138,33 @@ int UtcDaliImageConvertNativeImageSourceToUrl(void) 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; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageUrl.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageUrl.cpp index 658d585..d137c5d 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageUrl.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageUrl.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -24,7 +24,7 @@ using namespace Dali; using namespace Dali::Toolkit; -int UtcImageUrlConstructor(void) +int UtcImageUrlConstructor01(void) { ToolkitTestApplication application; @@ -50,3 +50,30 @@ int UtcImageUrlConstructor(void) 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; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp index 1fcd10d..43c7530 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -424,6 +424,198 @@ int UtcDaliImageVisualRemoteImageLoad(void) 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(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(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(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(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(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(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(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(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(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(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA); + DALI_TEST_EQUALS(preMultipliedAlpha, true, TEST_LOCATION); + + END_TEST; +} + int UtcDaliImageVisualWithNativeImage(void) { ToolkitTestApplication application; @@ -453,6 +645,9 @@ int UtcDaliImageVisualWithNativeImage(void) DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION); + application.SendNotification(); + application.Render(16); + Renderer renderer = actor.GetRendererAt(0); Shader shader = renderer.GetShader(); @@ -466,6 +661,62 @@ int UtcDaliImageVisualWithNativeImage(void) DALI_TEST_EQUALS(pos != std::string::npos, true, TEST_LOCATION); + // Check whether preMultipliedAlpha is false. + auto preMultipliedAlpha = renderer.GetProperty(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(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(); + + 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(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA); + DALI_TEST_EQUALS(preMultipliedAlpha, true, TEST_LOCATION); + END_TEST; } @@ -475,7 +726,7 @@ int UtcDaliImageVisualWithNativeImageCustomShader(void) 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(); @@ -531,6 +782,11 @@ int UtcDaliImageVisualWithNativeImageCustomShader(void) 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(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA); + DALI_TEST_EQUALS(preMultipliedAlpha, false, TEST_LOCATION); + END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextureManager.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextureManager.cpp index 116b489..beba867 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextureManager.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextureManager.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -47,6 +47,8 @@ int UtcDaliTextureManagerAddRemoveP(void) 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); @@ -71,6 +73,23 @@ int UtcDaliTextureManagerAddRemoveP(void) 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); @@ -102,6 +121,16 @@ int UtcDaliTextureManagerAddRemoveP(void) 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; } diff --git a/dali-scene3d/internal/common/model-cache-manager.h b/dali-scene3d/internal/common/model-cache-manager.h index 0d30b26..e0d38b4 100644 --- a/dali-scene3d/internal/common/model-cache-manager.h +++ b/dali-scene3d/internal/common/model-cache-manager.h @@ -135,7 +135,7 @@ public: 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; diff --git a/dali-scene3d/internal/controls/model/model-impl.cpp b/dali-scene3d/internal/controls/model/model-impl.cpp index 27e8bc8..2f29b25 100644 --- a/dali-scene3d/internal/controls/model/model-impl.cpp +++ b/dali-scene3d/internal/controls/model/model-impl.cpp @@ -33,6 +33,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -52,6 +53,9 @@ namespace Internal { namespace { +/** + * Creates control through type registry + */ BaseHandle Create() { return Scene3D::Model::New(std::string()); @@ -61,9 +65,6 @@ BaseHandle Create() 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; @@ -194,7 +195,7 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr Model::~Model() { - if(ModelCacheManager::Get()) + if(ModelCacheManager::Get() && !mModelUrl.empty()) { ModelCacheManager::Get().UnreferenceModelCache(mModelUrl); } @@ -215,11 +216,44 @@ Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& 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(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) @@ -417,6 +451,12 @@ bool Model::ApplyCamera(uint32_t index, Dali::CameraActor camera) const return false; } +Scene3D::ModelNode Model::FindChildModelNodeByName(std::string_view nodeName) +{ + Actor childActor = Self().FindChildByName(nodeName); + return Scene3D::ModelNode::DownCast(childActor); +} + /////////////////////////////////////////////////////////// // // Private methods @@ -430,8 +470,9 @@ void Model::OnInitialize() 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); @@ -439,6 +480,7 @@ void Model::OnSceneConnection(int depth) 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()) { @@ -458,6 +500,7 @@ void Model::OnSceneConnection(int depth) parent = parent.GetParent(); } + NotifyResourceReady(); Control::OnSceneConnection(depth); } @@ -508,6 +551,17 @@ bool Model::IsResourceReady() const 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) @@ -539,18 +593,45 @@ void Model::FitModelPosition() 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); } } @@ -569,57 +650,7 @@ void Model::UpdateImageBasedLightTexture() 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(currentIblSpecularMipmapLevels)); - } + UpdateImageBasedLightTextureRecursively(mModelRoot, currentDiffuseTexture, currentSpecularTexture, currentIblScaleFactor, currentIblSpecularMipmapLevels); } void Model::UpdateImageBasedLightScaleFactor() @@ -631,14 +662,7 @@ 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 @@ -711,7 +735,7 @@ void Model::OnModelLoadComplete() { ResetResourceTasks(); - if(ModelCacheManager::Get()) + if(ModelCacheManager::Get() && !mModelUrl.empty()) { ModelCacheManager::Get().UnreferenceModelCache(mModelUrl); } @@ -719,9 +743,11 @@ void Model::OnModelLoadComplete() return; } + if(!mModelRoot) + { + CreateModelRoot(); + } CreateModel(); - mRenderableActors.clear(); - CollectRenderableActor(mModelRoot); auto& resources = mModelLoadTask->GetResources(); auto& scene = mModelLoadTask->GetScene(); @@ -735,12 +761,6 @@ void Model::OnModelLoadComplete() 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; @@ -809,13 +829,10 @@ void Model::NotifyResourceReady() 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, {}, {}, {}}; @@ -871,7 +888,7 @@ void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene) for(auto&& animation : mModelLoadTask->GetAnimations()) { Dali::Animation anim = animation.ReAnimate(getActor); - mAnimations.push_back({animation.mName, anim}); + mAnimations.push_back({animation.GetName(), anim}); } } } diff --git a/dali-scene3d/internal/controls/model/model-impl.h b/dali-scene3d/internal/controls/model/model-impl.h index e5e36d9..23aaf61 100644 --- a/dali-scene3d/internal/controls/model/model-impl.h +++ b/dali-scene3d/internal/controls/model/model-impl.h @@ -33,6 +33,7 @@ #include #include #include +#include namespace Dali { @@ -59,7 +60,17 @@ public: /** * @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() @@ -126,6 +137,11 @@ public: */ 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. @@ -182,6 +198,11 @@ private: 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(); @@ -194,7 +215,12 @@ private: /** * @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. @@ -278,13 +304,12 @@ private: void ResetCameraParameters(); private: - std::string mModelUrl; - std::string mResourceDirectoryUrl; - Dali::Actor mModelRoot; - std::vector mAnimations; - std::vector mCameraParameters; - std::vector> mRenderableActors; - WeakHandle mParentSceneView; + std::string mModelUrl; + std::string mResourceDirectoryUrl; + Scene3D::ModelNode mModelRoot; + std::vector mAnimations; + std::vector mCameraParameters; + WeakHandle mParentSceneView; // Asynchronous loading variable ModelLoadTaskPtr mModelLoadTask; @@ -294,7 +319,6 @@ private: 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; diff --git a/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp b/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp index e975368..c606f8f 100644 --- a/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp +++ b/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp @@ -668,19 +668,10 @@ void SceneView::UpdateRenderTask() 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); diff --git a/dali-scene3d/internal/file.list b/dali-scene3d/internal/file.list index cff1bca..063c0d1 100644 --- a/dali-scene3d/internal/file.list +++ b/dali-scene3d/internal/file.list @@ -14,4 +14,8 @@ set(scene3d_src_files ${scene3d_src_files} ${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 ) diff --git a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag index 022e21b..1508bf1 100644 --- a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag +++ b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag @@ -88,9 +88,7 @@ uniform lowp float uAlphaThreshold; // 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; @@ -120,11 +118,7 @@ void main() 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 @@ -139,11 +133,7 @@ void main() #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; diff --git a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert index 238ad20..4161b3a 100644 --- a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert +++ b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert @@ -20,10 +20,7 @@ in vec4 aTangent; in vec3 aTangent; #endif -#ifdef COLOR_ATTRIBUTE in vec4 aVertexColor; -uniform lowp float uHasVertexColor; -#endif #ifdef MORPH uniform highp sampler2D sBlendShapeGeometry; @@ -31,9 +28,7 @@ uniform lowp float uHasVertexColor; out mediump vec2 vUV; out lowp mat3 vTBN; -#ifdef COLOR_ATTRIBUTE out lowp vec4 vColor; -#endif out highp vec3 vPositionToCamera; uniform highp mat4 uViewMatrix; @@ -164,9 +159,7 @@ void main() vUV = aTexCoord; #endif -#ifdef COLOR_ATTRIBUTE - vColor = mix(vec4(1.0f), aVertexColor, uHasVertexColor); -#endif + vColor = aVertexColor; gl_Position = uProjection * positionV; } diff --git a/dali-scene3d/internal/loader/dli-loader-impl.cpp b/dali-scene3d/internal/loader/dli-loader-impl.cpp index 26525e3..d684548 100644 --- a/dali-scene3d/internal/loader/dli-loader-impl.cpp +++ b/dali-scene3d/internal/loader/dli-loader-impl.cpp @@ -61,19 +61,18 @@ namespace rs = RendererState; 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"; @@ -1440,51 +1439,56 @@ void DliLoaderImpl::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadPara ++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); } } @@ -1492,21 +1496,21 @@ void DliLoaderImpl::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadPara { 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) @@ -1516,24 +1520,24 @@ void DliLoaderImpl::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadPara 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)); } @@ -1669,10 +1673,17 @@ void DliLoaderImpl::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadPara } } - 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); @@ -1681,13 +1692,6 @@ void DliLoaderImpl::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadPara { 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); - } } } diff --git a/dali-scene3d/internal/loader/gltf2-asset.cpp b/dali-scene3d/internal/loader/gltf2-asset.cpp index 1012292..c2a932f 100644 --- a/dali-scene3d/internal/loader/gltf2-asset.cpp +++ b/dali-scene3d/internal/loader/gltf2-asset.cpp @@ -1,5 +1,5 @@ /* -* 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. @@ -40,53 +40,73 @@ constexpr uint32_t ACCESSOR_TYPE_ELEMENT_COUNT[]{ static_cast(-1), }; -const std::map 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& GetAccessorTypes() +{ + static const std::map 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 ALPHA_MODE_TYPES{ - ENUM_STRING_MAPPING(AlphaMode::Type, OPAQUE), - ENUM_STRING_MAPPING(AlphaMode::Type, MASK), - ENUM_STRING_MAPPING(AlphaMode::Type, BLEND), -}; +const std::map& GetAlphaModeTypes() +{ + static const std::map 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 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& GetAttributeTypes() +{ + static const std::map 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 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& GetAnimationSamplerInterpolation() +{ + static const std::map 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 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& GetAnimationChannelTargetPathTypes() +{ + static const std::map 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) { diff --git a/dali-scene3d/internal/loader/gltf2-util.cpp b/dali-scene3d/internal/loader/gltf2-util.cpp index 68dd8bb..38ddfcf 100644 --- a/dali-scene3d/internal/loader/gltf2-util.cpp +++ b/dali-scene3d/internal/loader/gltf2-util.cpp @@ -19,6 +19,7 @@ #include // EXTERNAL INCLUDES +#include #include using namespace Dali::Scene3D::Loader; @@ -80,102 +81,162 @@ void ApplyAccessorMinMax(const gltf2::Accessor& accessor, float* values) MeshDefinition::Blob::ApplyMinMax(accessor.mMin, accessor.mMax, accessor.mCount, values); } -const auto BUFFER_READER = std::move(json::Reader() - .Register(*json::MakeProperty("byteLength", json::Read::Number, &gltf2::Buffer::mByteLength)) - .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Buffer::mUri))); - -const auto BUFFER_VIEW_READER = std::move(json::Reader() - .Register(*json::MakeProperty("buffer", gltf2::RefReader::Read, &gltf2::BufferView::mBuffer)) - .Register(*json::MakeProperty("byteOffset", json::Read::Number, &gltf2::BufferView::mByteOffset)) - .Register(*json::MakeProperty("byteLength", json::Read::Number, &gltf2::BufferView::mByteLength)) - .Register(*json::MakeProperty("byteStride", json::Read::Number, &gltf2::BufferView::mByteStride)) - .Register(*json::MakeProperty("target", json::Read::Number, &gltf2::BufferView::mTarget))); - -const auto BUFFER_VIEW_CLIENT_READER = std::move(json::Reader() - .Register(*json::MakeProperty("bufferView", gltf2::RefReader::Read, &gltf2::BufferViewClient::mBufferView)) - .Register(*json::MakeProperty("byteOffset", json::Read::Number, &gltf2::BufferViewClient::mByteOffset))); - -const auto COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER = std::move(json::Reader() - .Register(*new json::Property>("bufferView", gltf2::RefReader::Read, &gltf2::ComponentTypedBufferViewClient::mBufferView)) - .Register(*new json::Property("byteOffset", json::Read::Number, &gltf2::ComponentTypedBufferViewClient::mByteOffset)) - .Register(*json::MakeProperty("componentType", json::Read::Enum, &gltf2::ComponentTypedBufferViewClient::mComponentType))); - -const auto ACCESSOR_SPARSE_READER = std::move(json::Reader() - .Register(*json::MakeProperty("count", json::Read::Number, &gltf2::Accessor::Sparse::mCount)) - .Register(*json::MakeProperty("indices", json::ObjectReader::Read, &gltf2::Accessor::Sparse::mIndices)) - .Register(*json::MakeProperty("values", json::ObjectReader::Read, &gltf2::Accessor::Sparse::mValues))); - -const auto ACCESSOR_READER = std::move(json::Reader() - .Register(*new json::Property>("bufferView", - gltf2::RefReader::Read, - &gltf2::Accessor::mBufferView)) - .Register(*new json::Property("byteOffset", - json::Read::Number, - &gltf2::Accessor::mByteOffset)) - .Register(*new json::Property("componentType", - json::Read::Enum, - &gltf2::Accessor::mComponentType)) - .Register(*new json::Property("name", json::Read::StringView, &gltf2::Accessor::mName)) - .Register(*json::MakeProperty("count", json::Read::Number, &gltf2::Accessor::mCount)) - .Register(*json::MakeProperty("normalized", json::Read::Boolean, &gltf2::Accessor::mNormalized)) - .Register(*json::MakeProperty("type", gltf2::ReadStringEnum, &gltf2::Accessor::mType)) - .Register(*json::MakeProperty("min", json::Read::Array, &gltf2::Accessor::mMin)) - .Register(*json::MakeProperty("max", json::Read::Array, &gltf2::Accessor::mMax)) - .Register(*new json::Property("sparse", json::ObjectReader::Read, &gltf2::Accessor::SetSparse))); - -const auto IMAGE_READER = std::move(json::Reader() - .Register(*new json::Property("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::Read, &gltf2::Image::mBufferView))); - -const auto SAMPLER_READER = std::move(json::Reader() - .Register(*json::MakeProperty("minFilter", json::Read::Enum, &gltf2::Sampler::mMinFilter)) - .Register(*json::MakeProperty("magFilter", json::Read::Enum, &gltf2::Sampler::mMagFilter)) - .Register(*json::MakeProperty("wrapS", json::Read::Enum, &gltf2::Sampler::mWrapS)) - .Register(*json::MakeProperty("wrapT", json::Read::Enum, &gltf2::Sampler::mWrapT))); - -const auto TEXURE_READER = std::move(json::Reader() - .Register(*json::MakeProperty("source", gltf2::RefReader::Read, &gltf2::Texture::mSource)) - .Register(*json::MakeProperty("sampler", gltf2::RefReader::Read, &gltf2::Texture::mSampler))); - -const auto TEXURE_INFO_READER = std::move(json::Reader() - .Register(*json::MakeProperty("index", gltf2::RefReader::Read, &gltf2::TextureInfo::mTexture)) - .Register(*json::MakeProperty("texCoord", json::Read::Number, &gltf2::TextureInfo::mTexCoord)) - .Register(*json::MakeProperty("scale", json::Read::Number, &gltf2::TextureInfo::mScale)) - .Register(*json::MakeProperty("strength", json::Read::Number, &gltf2::TextureInfo::mStrength))); - -const auto MATERIAL_PBR_READER = std::move(json::Reader() - .Register(*json::MakeProperty("baseColorFactor", gltf2::ReadDaliVector, &gltf2::Material::Pbr::mBaseColorFactor)) - .Register(*json::MakeProperty("baseColorTexture", json::ObjectReader::Read, &gltf2::Material::Pbr::mBaseColorTexture)) - .Register(*json::MakeProperty("metallicFactor", json::Read::Number, &gltf2::Material::Pbr::mMetallicFactor)) - .Register(*json::MakeProperty("roughnessFactor", json::Read::Number, &gltf2::Material::Pbr::mRoughnessFactor)) - .Register(*json::MakeProperty("metallicRoughnessTexture", json::ObjectReader::Read, &gltf2::Material::Pbr::mMetallicRoughnessTexture))); - -const auto MATERIAL_SPECULAR_READER = std::move(json::Reader() - .Register(*json::MakeProperty("specularFactor", json::Read::Number, &gltf2::MaterialSpecular::mSpecularFactor)) - .Register(*json::MakeProperty("specularTexture", json::ObjectReader::Read, &gltf2::MaterialSpecular::mSpecularTexture)) - .Register(*json::MakeProperty("specularColorFactor", gltf2::ReadDaliVector, &gltf2::MaterialSpecular::mSpecularColorFactor)) - .Register(*json::MakeProperty("specularColorTexture", json::ObjectReader::Read, &gltf2::MaterialSpecular::mSpecularColorTexture))); - -const auto MATERIAL_IOR_READER = std::move(json::Reader() - .Register(*json::MakeProperty("ior", json::Read::Number, &gltf2::MaterialIor::mIor))); - -const auto MATERIAL_EXTENSION_READER = std::move(json::Reader() - .Register(*json::MakeProperty("KHR_materials_ior", json::ObjectReader::Read, &gltf2::MaterialExtensions::mMaterialIor)) - .Register(*json::MakeProperty("KHR_materials_specular", json::ObjectReader::Read, &gltf2::MaterialExtensions::mMaterialSpecular))); - -const auto MATERIAL_READER = std::move(json::Reader() - .Register(*new json::Property("name", json::Read::StringView, &gltf2::Material::mName)) - .Register(*json::MakeProperty("pbrMetallicRoughness", json::ObjectReader::Read, &gltf2::Material::mPbrMetallicRoughness)) - .Register(*json::MakeProperty("normalTexture", json::ObjectReader::Read, &gltf2::Material::mNormalTexture)) - .Register(*json::MakeProperty("occlusionTexture", json::ObjectReader::Read, &gltf2::Material::mOcclusionTexture)) - .Register(*json::MakeProperty("emissiveTexture", json::ObjectReader::Read, &gltf2::Material::mEmissiveTexture)) - .Register(*json::MakeProperty("emissiveFactor", gltf2::ReadDaliVector, &gltf2::Material::mEmissiveFactor)) - .Register(*json::MakeProperty("alphaMode", gltf2::ReadStringEnum, &gltf2::Material::mAlphaMode)) - .Register(*json::MakeProperty("alphaCutoff", json::Read::Number, &gltf2::Material::mAlphaCutoff)) - .Register(*json::MakeProperty("doubleSided", json::Read::Boolean, &gltf2::Material::mDoubleSided)) - .Register(*json::MakeProperty("extensions", json::ObjectReader::Read, &gltf2::Material::mMaterialExtensions))); +const json::Reader& GetBufferReader() +{ + static const auto BUFFER_READER = std::move(json::Reader() + .Register(*json::MakeProperty("byteLength", json::Read::Number, &gltf2::Buffer::mByteLength)) + .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Buffer::mUri))); + return BUFFER_READER; +} + +const json::Reader& GetBufferViewReader() +{ + static const auto BUFFER_VIEW_READER = std::move(json::Reader() + .Register(*json::MakeProperty("buffer", gltf2::RefReader::Read, &gltf2::BufferView::mBuffer)) + .Register(*json::MakeProperty("byteOffset", json::Read::Number, &gltf2::BufferView::mByteOffset)) + .Register(*json::MakeProperty("byteLength", json::Read::Number, &gltf2::BufferView::mByteLength)) + .Register(*json::MakeProperty("byteStride", json::Read::Number, &gltf2::BufferView::mByteStride)) + .Register(*json::MakeProperty("target", json::Read::Number, &gltf2::BufferView::mTarget))); + return BUFFER_VIEW_READER; +} + +const json::Reader& GetBufferViewClientReader() +{ + static const auto BUFFER_VIEW_CLIENT_READER = std::move(json::Reader() + .Register(*json::MakeProperty("bufferView", gltf2::RefReader::Read, &gltf2::BufferViewClient::mBufferView)) + .Register(*json::MakeProperty("byteOffset", json::Read::Number, &gltf2::BufferViewClient::mByteOffset))); + return BUFFER_VIEW_CLIENT_READER; +} + +const json::Reader& GetComponentTypedBufferViewClientReader() +{ + static const auto COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER = std::move(json::Reader() + .Register(*new json::Property>("bufferView", gltf2::RefReader::Read, &gltf2::ComponentTypedBufferViewClient::mBufferView)) + .Register(*new json::Property("byteOffset", json::Read::Number, &gltf2::ComponentTypedBufferViewClient::mByteOffset)) + .Register(*json::MakeProperty("componentType", json::Read::Enum, &gltf2::ComponentTypedBufferViewClient::mComponentType))); + return COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER; +} + +const json::Reader& GetAccessorSparseReader() +{ + static const auto ACCESSOR_SPARSE_READER = std::move(json::Reader() + .Register(*json::MakeProperty("count", json::Read::Number, &gltf2::Accessor::Sparse::mCount)) + .Register(*json::MakeProperty("indices", json::ObjectReader::Read, &gltf2::Accessor::Sparse::mIndices)) + .Register(*json::MakeProperty("values", json::ObjectReader::Read, &gltf2::Accessor::Sparse::mValues))); + return ACCESSOR_SPARSE_READER; +} + +const json::Reader& GetAccessorReader() +{ + static const auto ACCESSOR_READER = std::move(json::Reader() + .Register(*new json::Property>("bufferView", + gltf2::RefReader::Read, + &gltf2::Accessor::mBufferView)) + .Register(*new json::Property("byteOffset", + json::Read::Number, + &gltf2::Accessor::mByteOffset)) + .Register(*new json::Property("componentType", + json::Read::Enum, + &gltf2::Accessor::mComponentType)) + .Register(*new json::Property("name", json::Read::StringView, &gltf2::Accessor::mName)) + .Register(*json::MakeProperty("count", json::Read::Number, &gltf2::Accessor::mCount)) + .Register(*json::MakeProperty("normalized", json::Read::Boolean, &gltf2::Accessor::mNormalized)) + .Register(*json::MakeProperty("type", gltf2::ReadStringEnum, &gltf2::Accessor::mType)) + .Register(*json::MakeProperty("min", json::Read::Array, &gltf2::Accessor::mMin)) + .Register(*json::MakeProperty("max", json::Read::Array, &gltf2::Accessor::mMax)) + .Register(*new json::Property("sparse", json::ObjectReader::Read, &gltf2::Accessor::SetSparse))); + return ACCESSOR_READER; +} + +const json::Reader& GetImageReader() +{ + static const auto IMAGE_READER = std::move(json::Reader() + .Register(*new json::Property("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::Read, &gltf2::Image::mBufferView))); + return IMAGE_READER; +} + +const json::Reader& GetSamplerReader() +{ + static const auto SAMPLER_READER = std::move(json::Reader() + .Register(*json::MakeProperty("minFilter", json::Read::Enum, &gltf2::Sampler::mMinFilter)) + .Register(*json::MakeProperty("magFilter", json::Read::Enum, &gltf2::Sampler::mMagFilter)) + .Register(*json::MakeProperty("wrapS", json::Read::Enum, &gltf2::Sampler::mWrapS)) + .Register(*json::MakeProperty("wrapT", json::Read::Enum, &gltf2::Sampler::mWrapT))); + return SAMPLER_READER; +} + +const json::Reader& GetTextureReader() +{ + static const auto TEXURE_READER = std::move(json::Reader() + .Register(*json::MakeProperty("source", gltf2::RefReader::Read, &gltf2::Texture::mSource)) + .Register(*json::MakeProperty("sampler", gltf2::RefReader::Read, &gltf2::Texture::mSampler))); + return TEXURE_READER; +} + +const json::Reader& GetTextureInfoReader() +{ + static const auto TEXURE_INFO_READER = std::move(json::Reader() + .Register(*json::MakeProperty("index", gltf2::RefReader::Read, &gltf2::TextureInfo::mTexture)) + .Register(*json::MakeProperty("texCoord", json::Read::Number, &gltf2::TextureInfo::mTexCoord)) + .Register(*json::MakeProperty("scale", json::Read::Number, &gltf2::TextureInfo::mScale)) + .Register(*json::MakeProperty("strength", json::Read::Number, &gltf2::TextureInfo::mStrength))); + return TEXURE_INFO_READER; +} + +const json::Reader& GetMaterialPbrReader() +{ + static const auto MATERIAL_PBR_READER = std::move(json::Reader() + .Register(*json::MakeProperty("baseColorFactor", gltf2::ReadDaliVector, &gltf2::Material::Pbr::mBaseColorFactor)) + .Register(*json::MakeProperty("baseColorTexture", json::ObjectReader::Read, &gltf2::Material::Pbr::mBaseColorTexture)) + .Register(*json::MakeProperty("metallicFactor", json::Read::Number, &gltf2::Material::Pbr::mMetallicFactor)) + .Register(*json::MakeProperty("roughnessFactor", json::Read::Number, &gltf2::Material::Pbr::mRoughnessFactor)) + .Register(*json::MakeProperty("metallicRoughnessTexture", json::ObjectReader::Read, &gltf2::Material::Pbr::mMetallicRoughnessTexture))); + return MATERIAL_PBR_READER; +} + +const json::Reader& GetMaterialSpecularReader() +{ + static const auto MATERIAL_SPECULAR_READER = std::move(json::Reader() + .Register(*json::MakeProperty("specularFactor", json::Read::Number, &gltf2::MaterialSpecular::mSpecularFactor)) + .Register(*json::MakeProperty("specularTexture", json::ObjectReader::Read, &gltf2::MaterialSpecular::mSpecularTexture)) + .Register(*json::MakeProperty("specularColorFactor", gltf2::ReadDaliVector, &gltf2::MaterialSpecular::mSpecularColorFactor)) + .Register(*json::MakeProperty("specularColorTexture", json::ObjectReader::Read, &gltf2::MaterialSpecular::mSpecularColorTexture))); + return MATERIAL_SPECULAR_READER; +} + +const json::Reader& GetMaterialIorReader() +{ + static const auto MATERIAL_IOR_READER = std::move(json::Reader() + .Register(*json::MakeProperty("ior", json::Read::Number, &gltf2::MaterialIor::mIor))); + return MATERIAL_IOR_READER; +} + +const json::Reader& GetMaterialExtensionsReader() +{ + static const auto MATERIAL_EXTENSION_READER = std::move(json::Reader() + .Register(*json::MakeProperty("KHR_materials_ior", json::ObjectReader::Read, &gltf2::MaterialExtensions::mMaterialIor)) + .Register(*json::MakeProperty("KHR_materials_specular", json::ObjectReader::Read, &gltf2::MaterialExtensions::mMaterialSpecular))); + return MATERIAL_EXTENSION_READER; +} + +const json::Reader& GetMaterialReader() +{ + static const auto MATERIAL_READER = std::move(json::Reader() + .Register(*new json::Property("name", json::Read::StringView, &gltf2::Material::mName)) + .Register(*json::MakeProperty("pbrMetallicRoughness", json::ObjectReader::Read, &gltf2::Material::mPbrMetallicRoughness)) + .Register(*json::MakeProperty("normalTexture", json::ObjectReader::Read, &gltf2::Material::mNormalTexture)) + .Register(*json::MakeProperty("occlusionTexture", json::ObjectReader::Read, &gltf2::Material::mOcclusionTexture)) + .Register(*json::MakeProperty("emissiveTexture", json::ObjectReader::Read, &gltf2::Material::mEmissiveTexture)) + .Register(*json::MakeProperty("emissiveFactor", gltf2::ReadDaliVector, &gltf2::Material::mEmissiveFactor)) + .Register(*json::MakeProperty("alphaMode", gltf2::ReadStringEnum, &gltf2::Material::mAlphaMode)) + .Register(*json::MakeProperty("alphaCutoff", json::Read::Number, &gltf2::Material::mAlphaCutoff)) + .Register(*json::MakeProperty("doubleSided", json::Read::Boolean, &gltf2::Material::mDoubleSided)) + .Register(*json::MakeProperty("extensions", json::ObjectReader::Read, &gltf2::Material::mMaterialExtensions))); + return MATERIAL_READER; +} std::map> ReadMeshPrimitiveAttributes(const json_value_s& j) { @@ -209,130 +270,182 @@ std::vector>> ReadM return result; } -const auto MESH_PRIMITIVE_READER = std::move(json::Reader() - .Register(*json::MakeProperty("attributes", ReadMeshPrimitiveAttributes, &gltf2::Mesh::Primitive::mAttributes)) - .Register(*json::MakeProperty("indices", gltf2::RefReader::Read, &gltf2::Mesh::Primitive::mIndices)) - .Register(*json::MakeProperty("material", gltf2::RefReader::Read, &gltf2::Mesh::Primitive::mMaterial)) - .Register(*json::MakeProperty("mode", json::Read::Enum, &gltf2::Mesh::Primitive::mMode)) - .Register(*json::MakeProperty("targets", ReadMeshPrimitiveTargets, &gltf2::Mesh::Primitive::mTargets))); - -const auto MESH_READER = std::move(json::Reader() - .Register(*new json::Property("name", json::Read::StringView, &gltf2::Mesh::mName)) - .Register(*json::MakeProperty("primitives", - json::Read::Array::Read>, - &gltf2::Mesh::mPrimitives)) - .Register(*json::MakeProperty("weights", json::Read::Array, &gltf2::Mesh::mWeights))); - -const auto SKIN_READER = std::move(json::Reader() - .Register(*new json::Property("name", json::Read::StringView, &gltf2::Skin::mName)) - .Register(*json::MakeProperty("inverseBindMatrices", - gltf2::RefReader::Read, - &gltf2::Skin::mInverseBindMatrices)) - .Register(*json::MakeProperty("skeleton", - gltf2::RefReader::Read, - &gltf2::Skin::mSkeleton)) - .Register(*json::MakeProperty("joints", - json::Read::Array, gltf2::RefReader::Read>, - &gltf2::Skin::mJoints))); - -const auto CAMERA_PERSPECTIVE_READER = std::move(json::Reader() - .Register(*json::MakeProperty("aspectRatio", json::Read::Number, &gltf2::Camera::Perspective::mAspectRatio)) - .Register(*json::MakeProperty("yfov", json::Read::Number, &gltf2::Camera::Perspective::mYFov)) - .Register(*json::MakeProperty("zfar", json::Read::Number, &gltf2::Camera::Perspective::mZFar)) - .Register(*json::MakeProperty("znear", json::Read::Number, &gltf2::Camera::Perspective::mZNear))); // TODO: infinite perspective projection, where znear is omitted - -const auto CAMERA_ORTHOGRAPHIC_READER = std::move(json::Reader() - .Register(*json::MakeProperty("xmag", json::Read::Number, &gltf2::Camera::Orthographic::mXMag)) - .Register(*json::MakeProperty("ymag", json::Read::Number, &gltf2::Camera::Orthographic::mYMag)) - .Register(*json::MakeProperty("zfar", json::Read::Number, &gltf2::Camera::Orthographic::mZFar)) - .Register(*json::MakeProperty("znear", json::Read::Number, &gltf2::Camera::Orthographic::mZNear))); - -const auto CAMERA_READER = std::move(json::Reader() - .Register(*new json::Property("name", json::Read::StringView, &gltf2::Camera::mName)) - .Register(*json::MakeProperty("type", json::Read::StringView, &gltf2::Camera::mType)) - .Register(*json::MakeProperty("perspective", json::ObjectReader::Read, &gltf2::Camera::mPerspective)) - .Register(*json::MakeProperty("orthographic", json::ObjectReader::Read, &gltf2::Camera::mOrthographic))); - -const auto NODE_READER = std::move(json::Reader() - .Register(*new json::Property("name", json::Read::StringView, &gltf2::Node::mName)) - .Register(*json::MakeProperty("translation", gltf2::ReadDaliVector, &gltf2::Node::mTranslation)) - .Register(*json::MakeProperty("rotation", gltf2::ReadQuaternion, &gltf2::Node::mRotation)) - .Register(*json::MakeProperty("scale", gltf2::ReadDaliVector, &gltf2::Node::mScale)) - .Register(*new json::Property("matrix", gltf2::ReadDaliVector, &gltf2::Node::SetMatrix)) - .Register(*json::MakeProperty("camera", gltf2::RefReader::Read, &gltf2::Node::mCamera)) - .Register(*json::MakeProperty("children", json::Read::Array, gltf2::RefReader::Read>, &gltf2::Node::mChildren)) - .Register(*json::MakeProperty("mesh", gltf2::RefReader::Read, &gltf2::Node::mMesh)) - .Register(*json::MakeProperty("skin", gltf2::RefReader::Read, &gltf2::Node::mSkin))); - -const auto ANIMATION_SAMPLER_READER = std::move(json::Reader() - .Register(*json::MakeProperty("input", gltf2::RefReader::Read, &gltf2::Animation::Sampler::mInput)) - .Register(*json::MakeProperty("output", gltf2::RefReader::Read, &gltf2::Animation::Sampler::mOutput)) - .Register(*json::MakeProperty("interpolation", gltf2::ReadStringEnum, &gltf2::Animation::Sampler::mInterpolation))); - -const auto ANIMATION_TARGET_READER = std::move(json::Reader() - .Register(*json::MakeProperty("node", gltf2::RefReader::Read, &gltf2::Animation::Channel::Target::mNode)) - .Register(*json::MakeProperty("path", gltf2::ReadStringEnum, &gltf2::Animation::Channel::Target::mPath))); - -const auto ANIMATION_CHANNEL_READER = std::move(json::Reader() - .Register(*json::MakeProperty("target", json::ObjectReader::Read, &gltf2::Animation::Channel::mTarget)) - .Register(*json::MakeProperty("sampler", gltf2::RefReader::Read, &gltf2::Animation::Channel::mSampler))); - -const auto ANIMATION_READER = std::move(json::Reader() - .Register(*new json::Property("name", json::Read::StringView, &gltf2::Animation::mName)) - .Register(*json::MakeProperty("samplers", - json::Read::Array::Read>, - &gltf2::Animation::mSamplers)) - .Register(*json::MakeProperty("channels", - json::Read::Array::Read>, - &gltf2::Animation::mChannels))); - -const auto SCENE_READER = std::move(json::Reader() - .Register(*new json::Property("name", json::Read::StringView, &gltf2::Scene::mName)) - .Register(*json::MakeProperty("nodes", - json::Read::Array, gltf2::RefReader::Read>, - &gltf2::Scene::mNodes))); - -const auto DOCUMENT_READER = std::move(json::Reader() - .Register(*json::MakeProperty("buffers", - json::Read::Array::Read>, - &gltf2::Document::mBuffers)) - .Register(*json::MakeProperty("bufferViews", - json::Read::Array::Read>, - &gltf2::Document::mBufferViews)) - .Register(*json::MakeProperty("accessors", - json::Read::Array::Read>, - &gltf2::Document::mAccessors)) - .Register(*json::MakeProperty("images", - json::Read::Array::Read>, - &gltf2::Document::mImages)) - .Register(*json::MakeProperty("samplers", - json::Read::Array::Read>, - &gltf2::Document::mSamplers)) - .Register(*json::MakeProperty("textures", - json::Read::Array::Read>, - &gltf2::Document::mTextures)) - .Register(*json::MakeProperty("materials", - json::Read::Array::Read>, - &gltf2::Document::mMaterials)) - .Register(*json::MakeProperty("meshes", - json::Read::Array::Read>, - &gltf2::Document::mMeshes)) - .Register(*json::MakeProperty("skins", - json::Read::Array::Read>, - &gltf2::Document::mSkins)) - .Register(*json::MakeProperty("cameras", - json::Read::Array::Read>, - &gltf2::Document::mCameras)) - .Register(*json::MakeProperty("nodes", - json::Read::Array::Read>, - &gltf2::Document::mNodes)) - .Register(*json::MakeProperty("animations", - ReadAnimationArray, - &gltf2::Document::mAnimations)) - .Register(*json::MakeProperty("scenes", - json::Read::Array::Read>, - &gltf2::Document::mScenes)) - .Register(*json::MakeProperty("scene", gltf2::RefReader::Read, &gltf2::Document::mScene))); +const json::Reader& GetMeshPrimitiveReader() +{ + static const auto MESH_PRIMITIVE_READER = std::move(json::Reader() + .Register(*json::MakeProperty("attributes", ReadMeshPrimitiveAttributes, &gltf2::Mesh::Primitive::mAttributes)) + .Register(*json::MakeProperty("indices", gltf2::RefReader::Read, &gltf2::Mesh::Primitive::mIndices)) + .Register(*json::MakeProperty("material", gltf2::RefReader::Read, &gltf2::Mesh::Primitive::mMaterial)) + .Register(*json::MakeProperty("mode", json::Read::Enum, &gltf2::Mesh::Primitive::mMode)) + .Register(*json::MakeProperty("targets", ReadMeshPrimitiveTargets, &gltf2::Mesh::Primitive::mTargets))); + return MESH_PRIMITIVE_READER; +} + +const json::Reader& GetMeshReader() +{ + static const auto MESH_READER = std::move(json::Reader() + .Register(*new json::Property("name", json::Read::StringView, &gltf2::Mesh::mName)) + .Register(*json::MakeProperty("primitives", + json::Read::Array::Read>, + &gltf2::Mesh::mPrimitives)) + .Register(*json::MakeProperty("weights", json::Read::Array, &gltf2::Mesh::mWeights))); + return MESH_READER; +} + +const json::Reader& GetSkinReader() +{ + static const auto SKIN_READER = std::move(json::Reader() + .Register(*new json::Property("name", json::Read::StringView, &gltf2::Skin::mName)) + .Register(*json::MakeProperty("inverseBindMatrices", + gltf2::RefReader::Read, + &gltf2::Skin::mInverseBindMatrices)) + .Register(*json::MakeProperty("skeleton", + gltf2::RefReader::Read, + &gltf2::Skin::mSkeleton)) + .Register(*json::MakeProperty("joints", + json::Read::Array, gltf2::RefReader::Read>, + &gltf2::Skin::mJoints))); + return SKIN_READER; +} + +const json::Reader& GetCameraPerspectiveReader() +{ + static const auto CAMERA_PERSPECTIVE_READER = std::move(json::Reader() + .Register(*json::MakeProperty("aspectRatio", json::Read::Number, &gltf2::Camera::Perspective::mAspectRatio)) + .Register(*json::MakeProperty("yfov", json::Read::Number, &gltf2::Camera::Perspective::mYFov)) + .Register(*json::MakeProperty("zfar", json::Read::Number, &gltf2::Camera::Perspective::mZFar)) + .Register(*json::MakeProperty("znear", json::Read::Number, &gltf2::Camera::Perspective::mZNear))); // TODO: infinite perspective projection, where znear is omitted + return CAMERA_PERSPECTIVE_READER; +} + +const json::Reader& GetCameraOrthographicReader() +{ + static const auto CAMERA_ORTHOGRAPHIC_READER = std::move(json::Reader() + .Register(*json::MakeProperty("xmag", json::Read::Number, &gltf2::Camera::Orthographic::mXMag)) + .Register(*json::MakeProperty("ymag", json::Read::Number, &gltf2::Camera::Orthographic::mYMag)) + .Register(*json::MakeProperty("zfar", json::Read::Number, &gltf2::Camera::Orthographic::mZFar)) + .Register(*json::MakeProperty("znear", json::Read::Number, &gltf2::Camera::Orthographic::mZNear))); + return CAMERA_ORTHOGRAPHIC_READER; +} + +const json::Reader& GetCameraReader() +{ + static const auto CAMERA_READER = std::move(json::Reader() + .Register(*new json::Property("name", json::Read::StringView, &gltf2::Camera::mName)) + .Register(*json::MakeProperty("type", json::Read::StringView, &gltf2::Camera::mType)) + .Register(*json::MakeProperty("perspective", json::ObjectReader::Read, &gltf2::Camera::mPerspective)) + .Register(*json::MakeProperty("orthographic", json::ObjectReader::Read, &gltf2::Camera::mOrthographic))); + return CAMERA_READER; +} + +const json::Reader& GetNodeReader() +{ + static const auto NODE_READER = std::move(json::Reader() + .Register(*new json::Property("name", json::Read::StringView, &gltf2::Node::mName)) + .Register(*json::MakeProperty("translation", gltf2::ReadDaliVector, &gltf2::Node::mTranslation)) + .Register(*json::MakeProperty("rotation", gltf2::ReadQuaternion, &gltf2::Node::mRotation)) + .Register(*json::MakeProperty("scale", gltf2::ReadDaliVector, &gltf2::Node::mScale)) + .Register(*new json::Property("matrix", gltf2::ReadDaliVector, &gltf2::Node::SetMatrix)) + .Register(*json::MakeProperty("camera", gltf2::RefReader::Read, &gltf2::Node::mCamera)) + .Register(*json::MakeProperty("children", json::Read::Array, gltf2::RefReader::Read>, &gltf2::Node::mChildren)) + .Register(*json::MakeProperty("mesh", gltf2::RefReader::Read, &gltf2::Node::mMesh)) + .Register(*json::MakeProperty("skin", gltf2::RefReader::Read, &gltf2::Node::mSkin))); + return NODE_READER; +} + +const json::Reader& GetAnimationSamplerReader() +{ + static const auto ANIMATION_SAMPLER_READER = std::move(json::Reader() + .Register(*json::MakeProperty("input", gltf2::RefReader::Read, &gltf2::Animation::Sampler::mInput)) + .Register(*json::MakeProperty("output", gltf2::RefReader::Read, &gltf2::Animation::Sampler::mOutput)) + .Register(*json::MakeProperty("interpolation", gltf2::ReadStringEnum, &gltf2::Animation::Sampler::mInterpolation))); + return ANIMATION_SAMPLER_READER; +} + +const json::Reader& GetAnimationChannelTargetReader() +{ + static const auto ANIMATION_TARGET_READER = std::move(json::Reader() + .Register(*json::MakeProperty("node", gltf2::RefReader::Read, &gltf2::Animation::Channel::Target::mNode)) + .Register(*json::MakeProperty("path", gltf2::ReadStringEnum, &gltf2::Animation::Channel::Target::mPath))); + return ANIMATION_TARGET_READER; +} + +const json::Reader& GetAnimationChannelReader() +{ + static const auto ANIMATION_CHANNEL_READER = std::move(json::Reader() + .Register(*json::MakeProperty("target", json::ObjectReader::Read, &gltf2::Animation::Channel::mTarget)) + .Register(*json::MakeProperty("sampler", gltf2::RefReader::Read, &gltf2::Animation::Channel::mSampler))); + return ANIMATION_CHANNEL_READER; +} + +const json::Reader& GetAnimationReader() +{ + static const auto ANIMATION_READER = std::move(json::Reader() + .Register(*new json::Property("name", json::Read::StringView, &gltf2::Animation::mName)) + .Register(*json::MakeProperty("samplers", + json::Read::Array::Read>, + &gltf2::Animation::mSamplers)) + .Register(*json::MakeProperty("channels", + json::Read::Array::Read>, + &gltf2::Animation::mChannels))); + return ANIMATION_READER; +} + +const json::Reader& GetSceneReader() +{ + static const auto SCENE_READER = std::move(json::Reader() + .Register(*new json::Property("name", json::Read::StringView, &gltf2::Scene::mName)) + .Register(*json::MakeProperty("nodes", + json::Read::Array, gltf2::RefReader::Read>, + &gltf2::Scene::mNodes))); + return SCENE_READER; +} + +const json::Reader& GetDocumentReader() +{ + static const auto DOCUMENT_READER = std::move(json::Reader() + .Register(*json::MakeProperty("buffers", + json::Read::Array::Read>, + &gltf2::Document::mBuffers)) + .Register(*json::MakeProperty("bufferViews", + json::Read::Array::Read>, + &gltf2::Document::mBufferViews)) + .Register(*json::MakeProperty("accessors", + json::Read::Array::Read>, + &gltf2::Document::mAccessors)) + .Register(*json::MakeProperty("images", + json::Read::Array::Read>, + &gltf2::Document::mImages)) + .Register(*json::MakeProperty("samplers", + json::Read::Array::Read>, + &gltf2::Document::mSamplers)) + .Register(*json::MakeProperty("textures", + json::Read::Array::Read>, + &gltf2::Document::mTextures)) + .Register(*json::MakeProperty("materials", + json::Read::Array::Read>, + &gltf2::Document::mMaterials)) + .Register(*json::MakeProperty("meshes", + json::Read::Array::Read>, + &gltf2::Document::mMeshes)) + .Register(*json::MakeProperty("skins", + json::Read::Array::Read>, + &gltf2::Document::mSkins)) + .Register(*json::MakeProperty("cameras", + json::Read::Array::Read>, + &gltf2::Document::mCameras)) + .Register(*json::MakeProperty("nodes", + json::Read::Array::Read>, + &gltf2::Document::mNodes)) + .Register(*json::MakeProperty("animations", + ReadAnimationArray, + &gltf2::Document::mAnimations)) + .Register(*json::MakeProperty("scenes", + json::Read::Array::Read>, + &gltf2::Document::mScenes)) + .Register(*json::MakeProperty("scene", gltf2::RefReader::Read, &gltf2::Document::mScene))); + return DOCUMENT_READER; +} void ConvertBuffer(const gltf2::Buffer& buffer, decltype(ResourceBundle::mBuffers)& outBuffers, const std::string& resourcePath) { @@ -420,9 +533,16 @@ TextureDefinition ConvertTextureInfo(const gltf2::TextureInfo& textureInfo, Conv } } +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& imageMetaData, decltype(ResourceBundle::mMaterials)& outMaterials, ConversionContext& context) { - auto getTextureMetaData = [](const std::unordered_map& metaData, const gltf2::TextureInfo& info) { + auto getTextureMetaData = [](const std::unordered_map& metaData, const gltf2::TextureInfo& info) + { if(!info.mTexture->mSource->mUri.empty()) { if(auto search = metaData.find(info.mTexture->mSource->mUri.data()); search != metaData.end()) @@ -438,12 +558,14 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_mapsecond; + 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 @@ -780,7 +895,8 @@ void ConvertNode(gltf2::Node const& node, const Index gltfIndex, Index parentInd auto& resources = output.mResources; const auto index = scene.GetNodeCount(); - auto weakNode = scene.AddNode([&]() { + auto weakNode = scene.AddNode([&]() + { std::unique_ptr nodeDefinition{new NodeDefinition()}; nodeDefinition->mParentIdx = parentIndex; @@ -964,7 +1080,7 @@ float LoadKeyFrames(ConversionContext& context, const gltf2::Animation::Channel& return duration; } -float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation::Channel& channel, Index nodeIndex, uint32_t& propertyIndex, std::vector& 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; @@ -980,7 +1096,7 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation 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); @@ -1000,11 +1116,28 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation } animatedProperty.mTimePeriod = {0.f, duration}; + + animationDefinition.SetProperty(propertyIndex++, std::move(animatedProperty)); } return duration; } +template +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(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; @@ -1013,11 +1146,11 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte 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; @@ -1032,7 +1165,7 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte numberOfProperties++; } } - animationDef.mProperties.resize(numberOfProperties); + animationDefinition.ReserveSize(numberOfProperties); Index propertyIndex = 0u; for(const auto& channel : animation.mChannels) @@ -1044,46 +1177,22 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte { case gltf2::Animation::Channel::Target::TRANSLATION: { - AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex]; - - animatedProperty.mNodeIndex = nodeIndex; - animatedProperty.mPropertyName = POSITION_PROPERTY; - - animatedProperty.mKeyFrames = KeyFrames::New(); - duration = LoadKeyFrames(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); - - animatedProperty.mTimePeriod = {0.f, duration}; + duration = LoadAnimation(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(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); - - animatedProperty.mTimePeriod = {0.f, duration}; + duration = LoadAnimation(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(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); - - animatedProperty.mTimePeriod = {0.f, duration}; + duration = LoadAnimation(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; } @@ -1094,12 +1203,12 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte } } - 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)); } } @@ -1203,33 +1312,33 @@ void ProduceShaders(ShaderDefinitionFactory& shaderFactory, Dali::Scene3D::Loade 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) @@ -1263,7 +1372,7 @@ const std::string_view GetRendererModelIdentification() 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) diff --git a/dali-scene3d/internal/loader/gltf2-util.h b/dali-scene3d/internal/loader/gltf2-util.h index 3bd2c9a..457140e 100644 --- a/dali-scene3d/internal/loader/gltf2-util.h +++ b/dali-scene3d/internal/loader/gltf2-util.h @@ -18,7 +18,6 @@ */ // EXTERNAL INCLUDES -#include #include // INTERNAL INCLUDES diff --git a/dali-scene3d/internal/loader/json-util.cpp b/dali-scene3d/internal/loader/json-util.cpp index ec6e95f..88cfad7 100644 --- a/dali-scene3d/internal/loader/json-util.cpp +++ b/dali-scene3d/internal/loader/json-util.cpp @@ -121,43 +121,47 @@ bool ReadQuadHelper(const TreeNode* tn, const std::array& quad) return true; } -const std::map kTypeIds{ - // NONE - {"boolean", [](const TreeNode* tn) { - return ReadPrimitiveHelper(tn, ReadBool); - }}, - {"float", [](const TreeNode* tn) { - return ReadPrimitiveHelper(tn, ReadFloat); - }}, - {"integer", [](const TreeNode* tn) { - return ReadPrimitiveHelper(tn, ReadInt); - }}, - {"vector2", ReadVectorHelper}, - {"vector3", ReadVectorHelper}, - {"vector4", ReadVectorHelper}, - {"matrix3", ReadVectorHelper}, - {"matrix", ReadVectorHelper}, - {"rectangle", [](const TreeNode* tn) { - Rect value; - if(ReadQuadHelper(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(tn, {&value.start, &value.end, &value.top, &value.bottom})) - { - return Property::Value(value); - } - return Property::Value(); - }}, -}; +const std::map& GetTypeIds() +{ + static const std::map kTypeIds{ + // NONE + {"boolean", [](const TreeNode* tn) { + return ReadPrimitiveHelper(tn, ReadBool); + }}, + {"float", [](const TreeNode* tn) { + return ReadPrimitiveHelper(tn, ReadFloat); + }}, + {"integer", [](const TreeNode* tn) { + return ReadPrimitiveHelper(tn, ReadInt); + }}, + {"vector2", ReadVectorHelper}, + {"vector3", ReadVectorHelper}, + {"vector4", ReadVectorHelper}, + {"matrix3", ReadVectorHelper}, + {"matrix", ReadVectorHelper}, + {"rectangle", [](const TreeNode* tn) { + Rect value; + if(ReadQuadHelper(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(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, @@ -469,8 +473,8 @@ Property::Value ReadPropertyValue(const Toolkit::TreeNode& tn) 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")); } diff --git a/dali-scene3d/internal/model-components/material-impl.cpp b/dali-scene3d/internal/model-components/material-impl.cpp new file mode 100644 index 0000000..7cfb847 --- /dev/null +++ b/dali-scene3d/internal/model-components/material-impl.cpp @@ -0,0 +1,815 @@ +/* + * 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 + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include + +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(index) < static_cast(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(index) < static_cast(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(index) < static_cast(TextureIndex::TEXTURE_TYPE_NUMBER)) + { + mTextureInformations[index].mSampler = sampler; + } +} + +Dali::Sampler Material::GetSampler(Scene3D::Material::TextureType index) +{ + if(static_cast(index) < static_cast(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 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 diff --git a/dali-scene3d/internal/model-components/material-impl.h b/dali-scene3d/internal/model-components/material-impl.h new file mode 100644 index 0000000..563bf82 --- /dev/null +++ b/dali-scene3d/internal/model-components/material-impl.h @@ -0,0 +1,335 @@ +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +using MaterialPtr = IntrusivePtr; + +/** + * @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>; + +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; + +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(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(handle); +} + +} // namespace Scene3D + +} // namespace Dali + +#endif // DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_IMPL_H diff --git a/dali-scene3d/internal/model-components/material-modify-observer.h b/dali-scene3d/internal/model-components/material-modify-observer.h new file mode 100644 index 0000000..4b0c93d --- /dev/null +++ b/dali-scene3d/internal/model-components/material-modify-observer.h @@ -0,0 +1,72 @@ +#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 + +// INTERNAL INCLUDES +#include + +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 +{ + static const bool ENABLE = true; +}; + +} // namespace Dali + +#endif // DALI_SCENE3D_MODEL_COMPONENTS_MATERIAL_MODIFY_OBSERVER_H diff --git a/dali-scene3d/internal/model-components/model-node-data-impl.cpp b/dali-scene3d/internal/model-components/model-node-data-impl.cpp new file mode 100644 index 0000000..308dad9 --- /dev/null +++ b/dali-scene3d/internal/model-components/model-node-data-impl.cpp @@ -0,0 +1,263 @@ +/* + * 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 + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include + +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(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 diff --git a/dali-scene3d/internal/model-components/model-node-data-impl.h b/dali-scene3d/internal/model-components/model-node-data-impl.h new file mode 100644 index 0000000..b19a82f --- /dev/null +++ b/dali-scene3d/internal/model-components/model-node-data-impl.h @@ -0,0 +1,162 @@ +#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 +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include + +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; + using BoneDataContainer = std::vector; + + /** + * @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(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 diff --git a/dali-scene3d/internal/model-components/model-node-impl.cpp b/dali-scene3d/internal/model-components/model-node-impl.cpp new file mode 100644 index 0000000..60dca00 --- /dev/null +++ b/dali-scene3d/internal/model-components/model-node-impl.cpp @@ -0,0 +1,211 @@ +/* + * 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 + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +Dali::Scene3D::ModelNode ModelNode::New() +{ + // Create the implementation, temporarily owned on stack + IntrusivePtr 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(customInterface); + return impl; +} + +const ModelNode& GetImplementation(const Dali::Scene3D::ModelNode& handle) +{ + const CustomActorImpl& customInterface = handle.GetImplementation(); + // downcast to control + const ModelNode& impl = dynamic_cast(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 diff --git a/dali-scene3d/internal/model-components/model-node-impl.h b/dali-scene3d/internal/model-components/model-node-impl.h new file mode 100644 index 0000000..d216bb5 --- /dev/null +++ b/dali-scene3d/internal/model-components/model-node-impl.h @@ -0,0 +1,293 @@ +#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 +#include +#include // for std::unique_ptr + +// INTERNAL INCLUDES +#include +#include +#include + +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 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 diff --git a/dali-scene3d/internal/model-components/model-primitive-impl.cpp b/dali-scene3d/internal/model-components/model-primitive-impl.cpp new file mode 100644 index 0000000..4dbb047 --- /dev/null +++ b/dali-scene3d/internal/model-components/model-primitive-impl.cpp @@ -0,0 +1,402 @@ +/* + * 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 + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include + +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(MaterialModifyObserver::ModifyFlag::SHADER)); + if(mIsMaterialChanged || shaderFlag == static_cast(MaterialModifyObserver::ModifyFlag::SHADER)) + { + std::string vertexShader = GetImplementation(mMaterial).GetVertexShader(); + std::string fragmentShader = GetImplementation(mMaterial).GetFragmentShader(); + + std::vector 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(MaterialModifyObserver::ModifyFlag::TEXTURE)); + if(mIsMaterialChanged || textureFlag == static_cast(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(MaterialModifyObserver::ModifyFlag::UNIFORM)); + if(mIsMaterialChanged || uniformFlag == static_cast(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(mSpecularMipmapLevels)); + } +} + +void ModelPrimitive::UpdateRendererUniform() +{ + mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName().data(), mIblScaleFactor); + mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightMaxLodUniformName().data(), static_cast(mSpecularMipmapLevels)); + GetImplementation(mMaterial).SetRendererUniform(mRenderer); +} + +} // namespace Internal + +} // namespace Scene3D + +} // namespace Dali diff --git a/dali-scene3d/internal/model-components/model-primitive-impl.h b/dali-scene3d/internal/model-components/model-primitive-impl.h new file mode 100644 index 0000000..b7d26b4 --- /dev/null +++ b/dali-scene3d/internal/model-components/model-primitive-impl.h @@ -0,0 +1,259 @@ +#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 +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +using ModelPrimitivePtr = IntrusivePtr; + +/** + * @brief TODO : Explain me. + * Use Vector4 Tangent data + * Same ModelPrimitive all shares IBL + */ +class ModelPrimitive : public BaseObject, public MaterialModifyObserver +{ +private: + using ModelPrimitiveModifyObserverContainer = std::set; + +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(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(handle); +} + +} // namespace Scene3D + +} // namespace Dali + +#endif // DALI_SCENE3D_MODEL_COMPONENTS_MODEL_PRIMITIVE_IMPL_H diff --git a/dali-scene3d/internal/model-components/model-primitive-modify-observer.h b/dali-scene3d/internal/model-components/model-primitive-modify-observer.h new file mode 100644 index 0000000..a576792 --- /dev/null +++ b/dali-scene3d/internal/model-components/model-primitive-modify-observer.h @@ -0,0 +1,50 @@ +#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 + +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 diff --git a/dali-scene3d/public-api/controls/model/model.cpp b/dali-scene3d/public-api/controls/model/model.cpp index 6f01a44..1b297fb 100644 --- a/dali-scene3d/public-api/controls/model/model.cpp +++ b/dali-scene3d/public-api/controls/model/model.cpp @@ -20,6 +20,7 @@ // INTERNAL INCLUDES #include +#include namespace Dali { @@ -62,11 +63,21 @@ Model::Model(Dali::Internal::CustomActor* internal) VerifyCustomActorPointer(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); @@ -132,6 +143,11 @@ bool Model::ApplyCamera(uint32_t index, Dali::CameraActor camera) const return GetImpl(*this).ApplyCamera(index, camera); } +ModelNode Model::FindChildModelNodeByName(std::string_view nodeName) +{ + return GetImpl(*this).FindChildModelNodeByName(nodeName); +} + } // namespace Scene3D } // namespace Dali diff --git a/dali-scene3d/public-api/controls/model/model.h b/dali-scene3d/public-api/controls/model/model.h index 39e7723..9b060d9 100644 --- a/dali-scene3d/public-api/controls/model/model.h +++ b/dali-scene3d/public-api/controls/model/model.h @@ -26,6 +26,7 @@ // INTERNAL INCLUDES #include +#include namespace Dali { @@ -75,10 +76,11 @@ public: * @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. @@ -146,12 +148,29 @@ public: 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. @@ -296,6 +315,14 @@ public: */ 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 /** diff --git a/dali-scene3d/public-api/file.list b/dali-scene3d/public-api/file.list index dffdfc8..a15ea78 100644 --- a/dali-scene3d/public-api/file.list +++ b/dali-scene3d/public-api/file.list @@ -32,4 +32,7 @@ set(scene3d_src_files ${scene3d_src_files} ${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 diff --git a/dali-scene3d/public-api/loader/alpha-function-helper.cpp b/dali-scene3d/public-api/loader/alpha-function-helper.cpp index 2aecc50..9c82704 100644 --- a/dali-scene3d/public-api/loader/alpha-function-helper.cpp +++ b/dali-scene3d/public-api/loader/alpha-function-helper.cpp @@ -29,22 +29,26 @@ namespace #define DALI_ALPHA_FUNCTION_ENTRY(x) { #x, AlphaFunction::x } // clang-format on -std::unordered_map 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& GetFunctions() +{ + static std::unordered_map 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 @@ -52,8 +56,8 @@ std::unordered_map sFunctions{ 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; @@ -63,7 +67,7 @@ AlphaFunction GetAlphaFunction(const std::string& name, bool* found) 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."); } diff --git a/dali-scene3d/public-api/loader/animation-definition.cpp b/dali-scene3d/public-api/loader/animation-definition.cpp index 31c5ed1..5d8d304 100644 --- a/dali-scene3d/public-api/loader/animation-definition.cpp +++ b/dali-scene3d/public-api/loader/animation-definition.cpp @@ -45,6 +45,20 @@ AnimationDefinition::AnimationDefinition(AnimationDefinition&& other) { } +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); @@ -69,18 +83,98 @@ Animation AnimationDefinition::ReAnimate(AnimatedProperty::GetActor getActor) 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 diff --git a/dali-scene3d/public-api/loader/animation-definition.h b/dali-scene3d/public-api/loader/animation-definition.h index 27fe2ac..ff72e3f 100644 --- a/dali-scene3d/public-api/loader/animation-definition.h +++ b/dali-scene3d/public-api/loader/animation-definition.h @@ -49,6 +49,8 @@ public: // METHODS 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. @@ -61,13 +63,138 @@ public: // METHODS */ 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; @@ -84,4 +211,4 @@ struct AnimationGroupDefinition } // namespace Dali::Scene3D::Loader -#endif //DALI_SCENE3D_LOADER_ANIMATION_DEFINITION_H +#endif // DALI_SCENE3D_LOADER_ANIMATION_DEFINITION_H diff --git a/dali-scene3d/public-api/loader/blend-shape-details.cpp b/dali-scene3d/public-api/loader/blend-shape-details.cpp index d238452..4cf288c 100644 --- a/dali-scene3d/public-api/loader/blend-shape-details.cpp +++ b/dali-scene3d/public-api/loader/blend-shape-details.cpp @@ -28,33 +28,37 @@ 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& 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; @@ -62,22 +66,16 @@ void BlendShapes::ConfigureProperties(const std::pair(index))); - shader.RegisterProperty(COMPONENT_SIZE, Property::Value(static_cast(mesh.second.blendShapeBufferOffset))); + shader.RegisterProperty(COMPONENT_SIZE, Property::Value(static_cast(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); } } diff --git a/dali-scene3d/public-api/loader/blend-shape-details.h b/dali-scene3d/public-api/loader/blend-shape-details.h index a3182cf..2b304d6 100644 --- a/dali-scene3d/public-api/loader/blend-shape-details.h +++ b/dali-scene3d/public-api/loader/blend-shape-details.h @@ -19,6 +19,8 @@ // EXTERNAL INCLUDES #include +#include +#include #include #include @@ -49,22 +51,32 @@ struct DALI_SCENE3D_API BlendShapes }; }; + struct BlendShapeData + { + std::vector weights; + std::vector unnormalizeFactors; + Version version{Scene3D::Loader::BlendShapes::Version::INVALID}; + uint32_t bufferOffset{0}; + int32_t components{0x0}; + Dali::WeakHandle 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& mesh, Shader shader, Actor actor); + static void ConfigureProperties(const BlendShapeData& data, Shader shader); BlendShapes() = delete; }; diff --git a/dali-scene3d/public-api/loader/bvh-loader.cpp b/dali-scene3d/public-api/loader/bvh-loader.cpp index 93a826d..70cb297 100644 --- a/dali-scene3d/public-api/loader/bvh-loader.cpp +++ b/dali-scene3d/public-api/loader/bvh-loader.cpp @@ -287,8 +287,8 @@ AnimationDefinition GenerateAnimation(const std::string& animationName, std::sha { 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(frameCount - 1u) : Dali::Math::MACHINE_EPSILON_10; std::vector> jointList; @@ -296,16 +296,16 @@ AnimationDefinition GenerateAnimation(const std::string& animationName, std::sha 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(); @@ -316,6 +316,8 @@ AnimationDefinition GenerateAnimation(const std::string& animationName, std::sha translationProperty.mKeyFrames.Add(static_cast(j) * keyFrameInterval, (jointList[i]->translations[j] * scale)); rotationProperty.mKeyFrames.Add(static_cast(j) * keyFrameInterval, jointList[i]->rotations[j]); } + animationDefinition.SetProperty(i * 2u, std::move(translationProperty)); + animationDefinition.SetProperty(i * 2u + 1, std::move(rotationProperty)); } } diff --git a/dali-scene3d/public-api/loader/environment-definition.cpp b/dali-scene3d/public-api/loader/environment-definition.cpp index 3124a85..61e5744 100644 --- a/dali-scene3d/public-api/loader/environment-definition.cpp +++ b/dali-scene3d/public-api/loader/environment-definition.cpp @@ -21,6 +21,7 @@ // EXTERNAL INCLUDES #include #include +#include // INTERNAL INCLUDES #include @@ -35,20 +36,39 @@ std::string GetDaliImagePath() } 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); @@ -69,16 +89,12 @@ EnvironmentDefinition::LoadRaw(const std::string& environmentsPath) const 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; @@ -95,10 +111,9 @@ EnvironmentDefinition::Textures EnvironmentDefinition::Load(RawData&& raw) const 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; } @@ -108,4 +123,21 @@ float EnvironmentDefinition::GetDefaultIntensity() 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 diff --git a/dali-scene3d/public-api/loader/environment-definition.h b/dali-scene3d/public-api/loader/environment-definition.h index 577a31f..36d8ae6 100644 --- a/dali-scene3d/public-api/loader/environment-definition.h +++ b/dali-scene3d/public-api/loader/environment-definition.h @@ -65,18 +65,20 @@ struct DALI_SCENE3D_API EnvironmentDefinition 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. @@ -84,6 +86,9 @@ struct DALI_SCENE3D_API EnvironmentDefinition */ static float GetDefaultIntensity(); +private: + static void LoadBrdfTexture(); + public: // DATA std::string mDiffuseMapPath; std::string mSpecularMapPath; @@ -92,6 +97,11 @@ public: // DATA 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 diff --git a/dali-scene3d/public-api/loader/facial-animation-loader.cpp b/dali-scene3d/public-api/loader/facial-animation-loader.cpp index 2414b1b..93920a2 100644 --- a/dali-scene3d/public-api/loader/facial-animation-loader.cpp +++ b/dali-scene3d/public-api/loader/facial-animation-loader.cpp @@ -122,8 +122,8 @@ AnimationDefinition LoadFacialAnimation(const std::string& url) FACIAL_ANIMATION_READER.Read(rootObj, facialAnimation); AnimationDefinition animationDefinition; - animationDefinition.mName = std::string(facialAnimation.mName.data()); - animationDefinition.mDuration = MILLISECONDS_TO_SECONDS * static_cast(facialAnimation.mTime[facialAnimation.mNumberOfFrames - 1u]); + animationDefinition.SetName(facialAnimation.mName.data()); + animationDefinition.SetDuration(MILLISECONDS_TO_SECONDS * static_cast(facialAnimation.mTime[facialAnimation.mNumberOfFrames - 1u])); // Calculate the number of animated properties. uint32_t numberOfAnimatedProperties = 0u; @@ -131,46 +131,29 @@ AnimationDefinition LoadFacialAnimation(const std::string& url) { numberOfAnimatedProperties += blendShape.mNumberOfMorphTarget; } - animationDefinition.mProperties.resize(numberOfAnimatedProperties); + animationDefinition.ReserveSize(numberOfAnimatedProperties); - // Create the key frame instances. - for(auto& animatedProperty : animationDefinition.mProperties) - { - animatedProperty.mKeyFrames = Dali::KeyFrames::New(); - } - - // Set the property names uint32_t targets = 0u; for(const auto& blendShape : facialAnimation.mBlendShapes) { for(uint32_t morphTargetIndex = 0u; morphTargetIndex < blendShape.mNumberOfMorphTarget; ++morphTargetIndex) { - AnimatedProperty& animatedProperty = animationDefinition.mProperties[targets + morphTargetIndex]; - animatedProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.mDuration); - + AnimatedProperty animatedProperty; + animatedProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration()); animatedProperty.mNodeName = blendShape.mNodeName; - std::stringstream weightPropertyStream; weightPropertyStream << BlendShapes::WEIGHTS_UNIFORM << "[" << morphTargetIndex << "]"; animatedProperty.mPropertyName = weightPropertyStream.str(); - } - targets += blendShape.mNumberOfMorphTarget; - } - targets = 0u; - for(const auto& blendShape : facialAnimation.mBlendShapes) - { - for(uint32_t timeIndex = 0u; timeIndex < facialAnimation.mNumberOfFrames; ++timeIndex) - { - const float progress = MILLISECONDS_TO_SECONDS * static_cast(facialAnimation.mTime[timeIndex]) / animationDefinition.mDuration; - - for(uint32_t morphTargetIndex = 0u; morphTargetIndex < blendShape.mNumberOfMorphTarget; ++morphTargetIndex) + animatedProperty.mKeyFrames = Dali::KeyFrames::New(); + for(uint32_t timeIndex = 0u; timeIndex < facialAnimation.mNumberOfFrames; ++timeIndex) { - AnimatedProperty& animatedProperty = animationDefinition.mProperties[targets + morphTargetIndex]; - + const float progress = MILLISECONDS_TO_SECONDS * static_cast(facialAnimation.mTime[timeIndex]) / animationDefinition.GetDuration(); animatedProperty.mKeyFrames.Add(progress, blendShape.mKeys[timeIndex][morphTargetIndex]); } + animationDefinition.SetProperty(targets + morphTargetIndex, std::move(animatedProperty)); } + targets += blendShape.mNumberOfMorphTarget; } diff --git a/dali-scene3d/public-api/loader/material-definition.cpp b/dali-scene3d/public-api/loader/material-definition.cpp index ac6b73a..eb87ae1 100644 --- a/dali-scene3d/public-api/loader/material-definition.cpp +++ b/dali-scene3d/public-api/loader/material-definition.cpp @@ -65,7 +65,11 @@ constexpr WrapMode::Type WRAP_MODES_TO_DALI[]{ 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/"; @@ -105,6 +109,7 @@ Dali::PixelData LoadImageResource(const std::string& resourcePath, } else { + textureDefinition.mDirectoryPath = resourcePath; pixelData = SyncImageLoader::Load(resourcePath + textureDefinition.mImageUri, textureDefinition.mMinImageDimensions, fittingMode, textureDefinition.mSamplingMode, orientationCorrection); } return pixelData; @@ -206,7 +211,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) { 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 @@ -240,7 +245,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) buffer[0] = static_cast(mColor.r * 255.f); buffer[1] = static_cast(mColor.g * 255.f); buffer[2] = static_cast(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. @@ -256,7 +261,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) // 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)) @@ -270,13 +275,13 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) { 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()}); } } } diff --git a/dali-scene3d/public-api/loader/material-definition.h b/dali-scene3d/public-api/loader/material-definition.h index b40a746..b8da495 100644 --- a/dali-scene3d/public-api/loader/material-definition.h +++ b/dali-scene3d/public-api/loader/material-definition.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace Dali::Scene3D::Loader { @@ -111,6 +112,7 @@ struct DALI_SCENE3D_API SamplerFlags 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; @@ -234,6 +236,7 @@ public: // DATA 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; @@ -244,10 +247,12 @@ public: // DATA 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 mTextureStages; + Material mMaterial; }; } // namespace Dali::Scene3D::Loader diff --git a/dali-scene3d/public-api/loader/matrix-stack.h b/dali-scene3d/public-api/loader/matrix-stack.h index f34614b..58ae2c0 100644 --- a/dali-scene3d/public-api/loader/matrix-stack.h +++ b/dali-scene3d/public-api/loader/matrix-stack.h @@ -1,5 +1,5 @@ -#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. * @@ -48,4 +48,4 @@ private: } // namespace Dali::Scene3D::Loader -#endif //DALI_SCENE3D_LOADERER_MATRIX_STACK_H_ +#endif //DALI_SCENE3D_LOADER_MATRIX_STACK_H_ diff --git a/dali-scene3d/public-api/loader/mesh-definition.cpp b/dali-scene3d/public-api/loader/mesh-definition.cpp index b977c65..4d7ef4d 100644 --- a/dali-scene3d/public-api/loader/mesh-definition.cpp +++ b/dali-scene3d/public-api/loader/mesh-definition.cpp @@ -63,7 +63,7 @@ private: 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. @@ -879,6 +879,18 @@ MeshDefinition::LoadRaw(const std::string& modelsPath, BufferDefinition::Vector& raw.mAttribs.push_back({"aVertexColor", propertyType, static_cast(bufferSize / propertySize), std::move(buffer)}); } } + else + { + std::vector buffer(raw.mAttribs[0].mNumElements * sizeof(Vector4)); + auto colors = reinterpret_cast(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()) { @@ -1028,4 +1040,14 @@ MeshGeometry MeshDefinition::Load(RawData&& raw) const 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 diff --git a/dali-scene3d/public-api/loader/mesh-definition.h b/dali-scene3d/public-api/loader/mesh-definition.h index 7289b40..eceb795 100644 --- a/dali-scene3d/public-api/loader/mesh-definition.h +++ b/dali-scene3d/public-api/loader/mesh-definition.h @@ -269,6 +269,15 @@ struct DALI_SCENE3D_API MeshDefinition */ 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 mRawData; uint32_t mFlags = 0x0; @@ -288,7 +297,8 @@ public: // DATA std::vector mBlendShapes; BlendShapes::Version mBlendShapeVersion = BlendShapes::Version::INVALID; - Index mSkeletonIdx = INVALID_INDEX; + Index mSkeletonIdx = INVALID_INDEX; + ModelPrimitive mModelPrimitive; }; } // namespace Dali::Scene3D::Loader diff --git a/dali-scene3d/public-api/loader/mesh-geometry.h b/dali-scene3d/public-api/loader/mesh-geometry.h index 1ce30a7..fa2ac1d 100644 --- a/dali-scene3d/public-api/loader/mesh-geometry.h +++ b/dali-scene3d/public-api/loader/mesh-geometry.h @@ -1,5 +1,5 @@ -#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. * @@ -23,17 +23,18 @@ // INTERNAL INCLUDES #include +#include 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 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 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 diff --git a/dali-scene3d/public-api/loader/node-definition.cpp b/dali-scene3d/public-api/loader/node-definition.cpp index 03d96f4..a8632e9 100644 --- a/dali-scene3d/public-api/loader/node-definition.cpp +++ b/dali-scene3d/public-api/loader/node-definition.cpp @@ -19,16 +19,76 @@ #include // INTERNAL INCLUDES +#include +#include #include #include +#include + 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 @@ -50,7 +110,7 @@ void NodeDefinition::Renderable::ReflectResources(IResourceReflector& reflector) 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; @@ -61,45 +121,45 @@ void NodeDefinition::Renderable::OnCreate(const NodeDefinition& node, CreatePara 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(Dali::Actor::Property::ID); + ModelNode node = ModelNode::New(); + mNodeId = node.GetProperty(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 @@ -190,32 +250,19 @@ void ModelRenderable::ReflectResources(IResourceReflector& reflector) 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) { @@ -232,27 +279,54 @@ void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::Creat 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(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(); @@ -261,28 +335,58 @@ void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::Creat 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(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(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) diff --git a/dali-scene3d/public-api/loader/node-definition.h b/dali-scene3d/public-api/loader/node-definition.h index fe853ae..9b73271 100644 --- a/dali-scene3d/public-api/loader/node-definition.h +++ b/dali-scene3d/public-api/loader/node-definition.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace Dali { @@ -101,8 +102,9 @@ struct DALI_SCENE3D_API Transforms */ struct DALI_SCENE3D_API SkinningShaderConfigurationRequest { - Index mSkeletonIdx; - Shader mShader; + Index mSkeletonIdx; + Shader mShader; + ModelPrimitive mPrimitive; bool operator<(const SkinningShaderConfigurationRequest& other) const { @@ -115,9 +117,10 @@ struct DALI_SCENE3D_API SkinningShaderConfigurationRequest */ 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 { @@ -147,8 +150,8 @@ public: // TYPES struct CreateParams { public: // input - const ResourceBundle& mResources; - Transforms& mXforms; + ResourceBundle& mResources; + Transforms& mXforms; public: // output std::vector mConstrainables; @@ -167,7 +170,7 @@ public: // TYPES 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 @@ -215,10 +218,10 @@ public: // TYPES 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 @@ -257,7 +260,7 @@ public: // METHODS 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; @@ -289,7 +292,7 @@ public: // METHODS 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; }; /** @@ -307,7 +310,7 @@ public: // DATA 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 diff --git a/dali-scene3d/public-api/loader/parse-renderer-state.cpp b/dali-scene3d/public-api/loader/parse-renderer-state.cpp index 30b4d44..63b7d58 100644 --- a/dali-scene3d/public-api/loader/parse-renderer-state.cpp +++ b/dali-scene3d/public-api/loader/parse-renderer-state.cpp @@ -28,112 +28,129 @@ namespace RendererState { namespace { -std::map 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& GetComparisons() +{ + static const std::map 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 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& GetBlendFactors() +{ + static const std::map 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 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& GetBufferModes() +{ + static const std::map 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 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& GetRendererStateProcessors() +{ + static const std::map 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 @@ -150,8 +167,8 @@ Type Parse(const char* string, size_t length, StringCallback onError) { 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)); } diff --git a/dali-scene3d/public-api/loader/parse-renderer-state.h b/dali-scene3d/public-api/loader/parse-renderer-state.h index 65a6269..2379fa6 100644 --- a/dali-scene3d/public-api/loader/parse-renderer-state.h +++ b/dali-scene3d/public-api/loader/parse-renderer-state.h @@ -1,5 +1,5 @@ -#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. * @@ -43,4 +43,4 @@ DALI_SCENE3D_API Type Parse(const char* string, size_t length = 0, StringCallbac } // namespace RendererState } // namespace Dali::Scene3D::Loader -#endif //DALI_SCENE3D_LOADERERER_INTERPRET_RENDERER_STATE_H +#endif //DALI_SCENE3D_LOADERER_INTERPRET_RENDERER_STATE_H diff --git a/dali-scene3d/public-api/loader/resource-bundle.h b/dali-scene3d/public-api/loader/resource-bundle.h index fe386ca..08dea60 100644 --- a/dali-scene3d/public-api/loader/resource-bundle.h +++ b/dali-scene3d/public-api/loader/resource-bundle.h @@ -1,5 +1,5 @@ -#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. * @@ -158,4 +158,4 @@ public: // DATA } // namespace Dali::Scene3D::Loader -#endif //DALI_SCENE3D_LOADERERERERER_RESOURCE_BUNDLE_H_ +#endif //DALI_SCENE3D_LOADERERERER_RESOURCE_BUNDLE_H_ diff --git a/dali-scene3d/public-api/loader/scene-definition.cpp b/dali-scene3d/public-api/loader/scene-definition.cpp index 96420e5..8cc5385 100644 --- a/dali-scene3d/public-api/loader/scene-definition.cpp +++ b/dali-scene3d/public-api/loader/scene-definition.cpp @@ -24,12 +24,13 @@ // INTERNAL #include +#include #include #include #include -//#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 @@ -43,50 +44,53 @@ namespace Dali::Scene3D::Loader { namespace { -const std::string JOINT_MATRIX{"jointMatrix"}; - -const std::map sConstraintFactory = { - {Property::Type::BOOLEAN, - [](Actor& a, Property::Index i) { - return Constraint::New(a, i, [](bool& current, const PropertyInputContainer& inputs) { - current = inputs[0]->GetBoolean(); - }); - }}, - {Property::Type::INTEGER, - [](Actor& a, Property::Index i) { - return Constraint::New(a, i, [](int& current, const PropertyInputContainer& inputs) { - current = inputs[0]->GetInteger(); - }); - }}, - {Property::Type::FLOAT, - [](Actor& a, Property::Index i) { - return Constraint::New(a, i, EqualToConstraint()); - }}, - {Property::Type::VECTOR2, - [](Actor& a, Property::Index i) { - return Constraint::New(a, i, EqualToConstraint()); - }}, - {Property::Type::VECTOR3, - [](Actor& a, Property::Index i) { - return Constraint::New(a, i, EqualToConstraint()); - }}, - {Property::Type::VECTOR4, - [](Actor& a, Property::Index i) { - return Constraint::New(a, i, EqualToConstraint()); - }}, - {Property::Type::MATRIX, - [](Actor& a, Property::Index i) { - return Constraint::New(a, i, EqualToConstraint()); - }}, - {Property::Type::MATRIX3, - [](Actor& a, Property::Index i) { - return Constraint::New(a, i, EqualToConstraint()); - }}, - {Property::Type::ROTATION, - [](Actor& a, Property::Index i) { - return Constraint::New(a, i, EqualToConstraint()); - }}, -}; + +const std::map& GetConstraintFactory() +{ + static const std::map sConstraintFactory = { + {Property::Type::BOOLEAN, + [](Actor& a, Property::Index i) { + return Constraint::New(a, i, [](bool& current, const PropertyInputContainer& inputs) { + current = inputs[0]->GetBoolean(); + }); + }}, + {Property::Type::INTEGER, + [](Actor& a, Property::Index i) { + return Constraint::New(a, i, [](int& current, const PropertyInputContainer& inputs) { + current = inputs[0]->GetInteger(); + }); + }}, + {Property::Type::FLOAT, + [](Actor& a, Property::Index i) { + return Constraint::New(a, i, EqualToConstraint()); + }}, + {Property::Type::VECTOR2, + [](Actor& a, Property::Index i) { + return Constraint::New(a, i, EqualToConstraint()); + }}, + {Property::Type::VECTOR3, + [](Actor& a, Property::Index i) { + return Constraint::New(a, i, EqualToConstraint()); + }}, + {Property::Type::VECTOR4, + [](Actor& a, Property::Index i) { + return Constraint::New(a, i, EqualToConstraint()); + }}, + {Property::Type::MATRIX, + [](Actor& a, Property::Index i) { + return Constraint::New(a, i, EqualToConstraint()); + }}, + {Property::Type::MATRIX3, + [](Actor& a, Property::Index i) { + return Constraint::New(a, i, EqualToConstraint()); + }}, + {Property::Type::ROTATION, + [](Actor& a, Property::Index i) { + return Constraint::New(a, i, EqualToConstraint()); + }}, + }; + return sConstraintFactory; +} struct ResourceReflector : IResourceReflector { @@ -174,7 +178,7 @@ public: { mCreationContext.mXforms.modelStack.Push(n.GetLocalSpace()); - Actor a = n.CreateActor(mCreationContext); + ModelNode a = n.CreateModelNode(mCreationContext); if(!mActorStack.empty()) { mActorStack.back().Add(a); @@ -192,15 +196,15 @@ public: mCreationContext.mXforms.modelStack.Pop(); } - Actor GetRoot() const + ModelNode GetRoot() const { return mRoot; } private: NodeDefinition::CreateParams& mCreationContext; - std::vector mActorStack; - Actor mRoot; + std::vector mActorStack; + ModelNode mRoot; }; bool IsAncestor(const SceneDefinition& scene, Index ancestor, Index node, Index rootHint = INVALID_INDEX) @@ -240,10 +244,10 @@ Property::Index ConfigureJointMatrix(Actor actor, Actor ancestor, Property::Inde 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(actor, propJointMatrix, [](Matrix& output, const PropertyInputContainer& inputs) { Matrix jointMatrix{false}; jointMatrix.SetTransformComponents(Vector3::ONE, inputs[0]->GetQuaternion(), inputs[1]->GetVector3()); @@ -299,23 +303,10 @@ void SortAndDeduplicateSkinningRequests(std::vector(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; } @@ -471,7 +462,7 @@ void SceneDefinition::CountResourceRefs(Index iNode, const Customization::Choice 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); @@ -777,8 +768,8 @@ void SceneDefinition::ApplyConstraints(Actor& root, 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, @@ -965,8 +956,8 @@ void SceneDefinition::ConfigureSkeletonJoints(uint32_t iRoot, const SkeletonDefi 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(rootJoint, propJointMatrix, [](Matrix& output, const PropertyInputContainer& inputs) { output.SetTransformComponents(Vector3::ONE, inputs[0]->GetQuaternion(), inputs[1]->GetVector3()); }); @@ -1055,8 +1046,12 @@ void SceneDefinition::ConfigureSkinningShaders(const ResourceBundle& 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); } } } @@ -1111,9 +1106,27 @@ bool SceneDefinition::ConfigureBlendshapeShaders(const ResourceBundle& 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); } } } diff --git a/dali-scene3d/public-api/loader/scene-definition.h b/dali-scene3d/public-api/loader/scene-definition.h index d1ec3f1..06d24db 100644 --- a/dali-scene3d/public-api/loader/scene-definition.h +++ b/dali-scene3d/public-api/loader/scene-definition.h @@ -1,5 +1,5 @@ -#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. * @@ -105,11 +105,11 @@ public: // METHODS /* * @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 @@ -272,4 +272,4 @@ private: // DATA } // namespace Dali::Scene3D::Loader -#endif //DALI_SCENE3D_LOADERER_SCENE_DEFINITION_H_ +#endif //DALI_SCENE3D_LOADER_SCENE_DEFINITION_H_ diff --git a/dali-scene3d/public-api/loader/shader-definition-factory.cpp b/dali-scene3d/public-api/loader/shader-definition-factory.cpp index a473af1..0d1e346 100644 --- a/dali-scene3d/public-api/loader/shader-definition-factory.cpp +++ b/dali-scene3d/public-api/loader/shader-definition-factory.cpp @@ -60,16 +60,6 @@ struct ResourceReceiver : IResourceReceiver } }; -void RetrieveBlendShapeComponents(const std::vector& 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; @@ -161,7 +151,7 @@ uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& m 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"); @@ -335,7 +325,7 @@ Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& rendera bool hasPositions = false; bool hasNormals = false; bool hasTangents = false; - RetrieveBlendShapeComponents(meshDef.mBlendShapes, hasPositions, hasNormals, hasTangents); + meshDef.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents); if(hasPositions) { diff --git a/dali-scene3d/public-api/loader/shader-definition.cpp b/dali-scene3d/public-api/loader/shader-definition.cpp index 25544cd..2796340 100644 --- a/dali-scene3d/public-api/loader/shader-definition.cpp +++ b/dali-scene3d/public-api/loader/shader-definition.cpp @@ -26,9 +26,8 @@ namespace Dali::Scene3D::Loader { 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) diff --git a/dali-scene3d/public-api/loader/skeleton-definition.h b/dali-scene3d/public-api/loader/skeleton-definition.h index 7161a34..0fca023 100644 --- a/dali-scene3d/public-api/loader/skeleton-definition.h +++ b/dali-scene3d/public-api/loader/skeleton-definition.h @@ -1,5 +1,5 @@ -#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. * @@ -48,4 +48,4 @@ struct DALI_SCENE3D_API SkeletonDefinition } // namespace Dali::Scene3D::Loader -#endif //DALI_SCENE3D_LOADERER_SKELETON_H +#endif //DALI_SCENE3D_LOADER_SKELETON_H diff --git a/dali-scene3d/public-api/loader/skinning-details.cpp b/dali-scene3d/public-api/loader/skinning-details.cpp index 941bf57..fc18d40 100644 --- a/dali-scene3d/public-api/loader/skinning-details.cpp +++ b/dali-scene3d/public-api/loader/skinning-details.cpp @@ -27,5 +27,6 @@ namespace Dali::Scene3D::Loader { 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 diff --git a/dali-scene3d/public-api/loader/skinning-details.h b/dali-scene3d/public-api/loader/skinning-details.h index ab04423..ca0bdc2 100644 --- a/dali-scene3d/public-api/loader/skinning-details.h +++ b/dali-scene3d/public-api/loader/skinning-details.h @@ -19,15 +19,28 @@ // EXTERNAL INCLUDES #include +#include #include // INTERNAL INCLUDES #include +#include +#include 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. */ @@ -36,7 +49,8 @@ struct DALI_SCENE3D_API Skinning /* * @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; }; diff --git a/dali-scene3d/public-api/model-components/material.cpp b/dali-scene3d/public-api/model-components/material.cpp new file mode 100644 index 0000000..9b2fb48 --- /dev/null +++ b/dali-scene3d/public-api/model-components/material.cpp @@ -0,0 +1,99 @@ +/* + * 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 + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include + +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(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 diff --git a/dali-scene3d/public-api/model-components/material.h b/dali-scene3d/public-api/model-components/material.h new file mode 100644 index 0000000..c48edbf --- /dev/null +++ b/dali-scene3d/public-api/model-components/material.h @@ -0,0 +1,473 @@ +#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 +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +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() is equal to GetPropertyType(index). + * @see GetProperty() + */ + template + T GetProperty(Dali::Property::Index index) const + { + Dali::Property::Value value = GetProperty(index); + + return T(value.Get()); + } + + /** + * @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 diff --git a/dali-scene3d/public-api/model-components/model-node.cpp b/dali-scene3d/public-api/model-components/model-node.cpp new file mode 100644 index 0000000..152dafc --- /dev/null +++ b/dali-scene3d/public-api/model-components/model-node.cpp @@ -0,0 +1,123 @@ +/* + * 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 + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include + +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(&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(&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 diff --git a/dali-scene3d/public-api/model-components/model-node.h b/dali-scene3d/public-api/model-components/model-node.h new file mode 100644 index 0000000..b48a158 --- /dev/null +++ b/dali-scene3d/public-api/model-components/model-node.h @@ -0,0 +1,214 @@ +#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 +#include + +// INTERNAL INCLUDES +#include +#include + +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 diff --git a/dali-scene3d/public-api/model-components/model-primitive.cpp b/dali-scene3d/public-api/model-components/model-primitive.cpp new file mode 100644 index 0000000..b8d5400 --- /dev/null +++ b/dali-scene3d/public-api/model-components/model-primitive.cpp @@ -0,0 +1,84 @@ +/* + * 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 + +// INTERNAL INCLUDES +#include + +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(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 diff --git a/dali-scene3d/public-api/model-components/model-primitive.h b/dali-scene3d/public-api/model-components/model-primitive.h new file mode 100644 index 0000000..899996c --- /dev/null +++ b/dali-scene3d/public-api/model-components/model-primitive.h @@ -0,0 +1,184 @@ +#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 +#include +#include + +// INTERNAL INCLUDES +#include +#include + +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 diff --git a/dali-toolkit/devel-api/image-loader/texture-manager.cpp b/dali-toolkit/devel-api/image-loader/texture-manager.cpp index cff4718..ace107e 100644 --- a/dali-toolkit/devel-api/image-loader/texture-manager.cpp +++ b/dali-toolkit/devel-api/image-loader/texture-manager.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -26,18 +26,18 @@ namespace Toolkit { 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) diff --git a/dali-toolkit/devel-api/image-loader/texture-manager.h b/dali-toolkit/devel-api/image-loader/texture-manager.h index f18ed14..ff61916 100644 --- a/dali-toolkit/devel-api/image-loader/texture-manager.h +++ b/dali-toolkit/devel-api/image-loader/texture-manager.h @@ -2,7 +2,7 @@ #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. @@ -39,9 +39,10 @@ namespace TextureManager * @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 @@ -49,9 +50,10 @@ DALI_TOOLKIT_API std::string AddTexture(Texture& texture); * @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 diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp index 9ddab28..28ecd9f 100644 --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -70,23 +70,22 @@ namespace { #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 TreeNodeList; diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index 84d44b9..79408a2 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -51,12 +51,12 @@ 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 diff --git a/dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.cpp b/dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.cpp index 6231b64..7b3679a 100644 --- a/dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.cpp +++ b/dali-toolkit/internal/controls/scene3d-view/scene3d-view-impl.cpp @@ -35,7 +35,7 @@ namespace 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 diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index 96dc6af..f34dac7 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -70,25 +70,25 @@ const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::DevelText::DEFAULT * 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}, }; diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp index 862a69c..50d7d3d 100644 --- a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp @@ -57,7 +57,7 @@ namespace #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)); @@ -93,8 +93,8 @@ const char* const OPTION_COPY("optionCopy"); // "Copy" popup opt 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() { @@ -726,10 +726,10 @@ void TextSelectionPopup::AddPopupOptionsToToolbar(bool showIcons, bool showCapti // 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) { diff --git a/dali-toolkit/internal/image-loader/image-url-impl.cpp b/dali-toolkit/internal/image-loader/image-url-impl.cpp index fae9fc1..31dc6fc 100644 --- a/dali-toolkit/internal/image-loader/image-url-impl.cpp +++ b/dali-toolkit/internal/image-loader/image-url-impl.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -30,9 +30,9 @@ namespace Toolkit { 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) @@ -66,9 +66,9 @@ ImageUrl::~ImageUrl() } } -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; } diff --git a/dali-toolkit/internal/image-loader/image-url-impl.h b/dali-toolkit/internal/image-loader/image-url-impl.h index 99616bf..f7ae8ef 100644 --- a/dali-toolkit/internal/image-loader/image-url-impl.h +++ b/dali-toolkit/internal/image-loader/image-url-impl.h @@ -2,7 +2,7 @@ #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. @@ -41,7 +41,7 @@ public: /** * @brief Constructor. */ - ImageUrl(Texture& texture); + ImageUrl(Texture& texture, bool preMultiplied); /** * @brief Constructor. @@ -51,7 +51,7 @@ public: /** * @copydoc Dali::Toolkit::ImageUrl::New */ - static ImageUrlPtr New(Texture& texture); + static ImageUrlPtr New(Texture& texture, bool preMultiplied); /** * @copydoc Dali::Toolkit::ImageUrl::New diff --git a/dali-toolkit/internal/text/controller/text-controller-event-handler.cpp b/dali-toolkit/internal/text/controller/text-controller-event-handler.cpp index 076b4dd..f9dc67d 100644 --- a/dali-toolkit/internal/text/controller/text-controller-event-handler.cpp +++ b/dali-toolkit/internal/text/controller/text-controller-event-handler.cpp @@ -39,11 +39,11 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT 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 diff --git a/dali-toolkit/internal/text/controller/text-controller-impl.cpp b/dali-toolkit/internal/text/controller/text-controller-impl.cpp index 29bab35..9aa4a06 100644 --- a/dali-toolkit/internal/text/controller/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/controller/text-controller-impl.cpp @@ -51,7 +51,7 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT constexpr float MAX_FLOAT = std::numeric_limits::max(); -const std::string EMPTY_STRING(""); +const char* EMPTY_STRING = ""; } // namespace diff --git a/dali-toolkit/internal/text/controller/text-controller-input-font-handler.cpp b/dali-toolkit/internal/text/controller/text-controller-input-font-handler.cpp index a1e6214..f2d49d2 100644 --- a/dali-toolkit/internal/text/controller/text-controller-input-font-handler.cpp +++ b/dali-toolkit/internal/text/controller/text-controller-input-font-handler.cpp @@ -131,7 +131,7 @@ void Controller::InputFontHandler::SetInputFontFamily(Controller& controller, co } } -const std::string& Controller::InputFontHandler::GetInputFontFamily(const Controller& controller) +std::string Controller::InputFontHandler::GetInputFontFamily(const Controller& controller) { if(NULL != controller.mImpl->mEventData) { diff --git a/dali-toolkit/internal/text/controller/text-controller-input-font-handler.h b/dali-toolkit/internal/text/controller/text-controller-input-font-handler.h index 2ac7464..bf38a00 100644 --- a/dali-toolkit/internal/text/controller/text-controller-input-font-handler.h +++ b/dali-toolkit/internal/text/controller/text-controller-input-font-handler.h @@ -34,7 +34,7 @@ namespace Text 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); diff --git a/dali-toolkit/internal/text/controller/text-controller-input-properties.cpp b/dali-toolkit/internal/text/controller/text-controller-input-properties.cpp index f410187..7842d05 100644 --- a/dali-toolkit/internal/text/controller/text-controller-input-properties.cpp +++ b/dali-toolkit/internal/text/controller/text-controller-input-properties.cpp @@ -38,7 +38,7 @@ namespace { -const std::string EMPTY_STRING(""); +const char* EMPTY_STRING = ""; } namespace Dali::Toolkit::Text @@ -116,7 +116,7 @@ void Controller::InputProperties::SetInputShadowProperties(Controller& controlle } } -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; } @@ -129,7 +129,7 @@ void Controller::InputProperties::SetInputUnderlineProperties(Controller& contro } } -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; } @@ -142,7 +142,7 @@ void Controller::InputProperties::SetInputEmbossProperties(Controller& controlle } } -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(); } @@ -155,7 +155,7 @@ void Controller::InputProperties::SetInputOutlineProperties(Controller& controll } } -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(); } diff --git a/dali-toolkit/internal/text/controller/text-controller-input-properties.h b/dali-toolkit/internal/text/controller/text-controller-input-properties.h index b0736f7..9b31d22 100644 --- a/dali-toolkit/internal/text/controller/text-controller-input-properties.h +++ b/dali-toolkit/internal/text/controller/text-controller-input-properties.h @@ -39,19 +39,19 @@ struct Controller::InputProperties 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); diff --git a/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.cpp b/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.cpp index da15a43..a0f03a6 100644 --- a/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.cpp +++ b/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.cpp @@ -33,7 +33,7 @@ namespace 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"; @@ -122,7 +122,7 @@ void Controller::PlaceholderHandler::SetPlaceholderFontFamily(Controller& contro } } -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)) { diff --git a/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h b/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h index c7107c9..3bbf87b 100644 --- a/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h +++ b/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h @@ -39,7 +39,7 @@ struct Controller::PlaceholderHandler 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); diff --git a/dali-toolkit/internal/text/controller/text-controller.cpp b/dali-toolkit/internal/text/controller/text-controller.cpp index 1759095..1d91ff7 100644 --- a/dali-toolkit/internal/text/controller/text-controller.cpp +++ b/dali-toolkit/internal/text/controller/text-controller.cpp @@ -45,7 +45,7 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); #endif -const std::string EMPTY_STRING(""); +const char* EMPTY_STRING = ""; template void EnsureCreated(Type*& object) @@ -538,7 +538,7 @@ void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily) } } -const std::string& Controller::GetDefaultFontFamily() const +std::string Controller::GetDefaultFontFamily() const { return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.family : EMPTY_STRING; } @@ -548,7 +548,7 @@ void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFont PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily); } -const std::string& Controller::GetPlaceholderFontFamily() const +std::string Controller::GetPlaceholderFontFamily() const { return PlaceholderHandler::GetPlaceholderFontFamily(*this); } @@ -945,7 +945,7 @@ void Controller::SetDefaultEmbossProperties(const std::string& embossProperties) mImpl->mEmbossDefaults->properties = embossProperties; } -const std::string& Controller::GetDefaultEmbossProperties() const +std::string Controller::GetDefaultEmbossProperties() const { return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING; } @@ -956,7 +956,7 @@ void Controller::SetDefaultOutlineProperties(const std::string& outlinePropertie mImpl->mOutlineDefaults->properties = outlineProperties; } -const std::string& Controller::GetDefaultOutlineProperties() const +std::string Controller::GetDefaultOutlineProperties() const { return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING; } @@ -1006,7 +1006,7 @@ void Controller::SetInputFontFamily(const std::string& fontFamily) InputFontHandler::SetInputFontFamily(*this, fontFamily); } -const std::string& Controller::GetInputFontFamily() const +std::string Controller::GetInputFontFamily() const { return InputFontHandler::GetInputFontFamily(*this); } @@ -1081,7 +1081,7 @@ void Controller::SetInputShadowProperties(const std::string& shadowProperties) InputProperties::SetInputShadowProperties(*this, shadowProperties); } -const std::string& Controller::GetInputShadowProperties() const +std::string Controller::GetInputShadowProperties() const { return InputProperties::GetInputShadowProperties(*this); } @@ -1091,7 +1091,7 @@ void Controller::SetInputUnderlineProperties(const std::string& underlinePropert InputProperties::SetInputUnderlineProperties(*this, underlineProperties); } -const std::string& Controller::GetInputUnderlineProperties() const +std::string Controller::GetInputUnderlineProperties() const { return InputProperties::GetInputUnderlineProperties(*this); } @@ -1101,7 +1101,7 @@ void Controller::SetInputEmbossProperties(const std::string& embossProperties) InputProperties::SetInputEmbossProperties(*this, embossProperties); } -const std::string& Controller::GetInputEmbossProperties() const +std::string Controller::GetInputEmbossProperties() const { return InputProperties::GetInputEmbossProperties(*this); } @@ -1111,7 +1111,7 @@ void Controller::SetInputOutlineProperties(const std::string& outlineProperties) InputProperties::SetInputOutlineProperties(*this, outlineProperties); } -const std::string& Controller::GetInputOutlineProperties() const +std::string Controller::GetInputOutlineProperties() const { return InputProperties::GetInputOutlineProperties(*this); } @@ -1236,7 +1236,7 @@ void Controller::SetInputStrikethroughProperties(const std::string& strikethroug } } -const std::string& Controller::GetInputStrikethroughProperties() const +std::string Controller::GetInputStrikethroughProperties() const { return (NULL != mImpl->mEventData) ? mImpl->mEventData->mInputStyle.strikethroughProperties : EMPTY_STRING; } diff --git a/dali-toolkit/internal/text/controller/text-controller.h b/dali-toolkit/internal/text/controller/text-controller.h index 83b2090..c0a560f 100644 --- a/dali-toolkit/internal/text/controller/text-controller.h +++ b/dali-toolkit/internal/text/controller/text-controller.h @@ -826,7 +826,7 @@ public: // Default style & Input style * * @return The default font family. */ - const std::string& GetDefaultFontFamily() const; + std::string GetDefaultFontFamily() const; /** * @brief Sets the placeholder text font family. @@ -839,7 +839,7 @@ public: // Default style & Input style * * @return The placeholder text font family */ - const std::string& GetPlaceholderFontFamily() const; + std::string GetPlaceholderFontFamily() const; /** * @brief Sets the default font weight. @@ -1255,7 +1255,7 @@ public: // Default style & Input style * * @return The emboss's properties string. */ - const std::string& GetDefaultEmbossProperties() const; + std::string GetDefaultEmbossProperties() const; /** * @brief Sets the outline's properties string. @@ -1271,7 +1271,7 @@ public: // Default style & Input style * * @return The outline's properties string. */ - const std::string& GetDefaultOutlineProperties() const; + std::string GetDefaultOutlineProperties() const; /** * @brief Sets the default line spacing. @@ -1347,7 +1347,7 @@ public: // Default style & Input style * * @return The input text's font family name. */ - const std::string& GetInputFontFamily() const; + std::string GetInputFontFamily() const; /** * @brief Sets the input font's weight. @@ -1448,7 +1448,7 @@ public: // Default style & Input style * * @return The shadow's properties string. */ - const std::string& GetInputShadowProperties() const; + std::string GetInputShadowProperties() const; /** * @brief Sets the input underline's properties string. @@ -1464,7 +1464,7 @@ public: // Default style & Input style * * @return The underline's properties string. */ - const std::string& GetInputUnderlineProperties() const; + std::string GetInputUnderlineProperties() const; /** * @brief Sets the input emboss's properties string. @@ -1480,7 +1480,7 @@ public: // Default style & Input style * * @return The emboss's properties string. */ - const std::string& GetInputEmbossProperties() const; + std::string GetInputEmbossProperties() const; /** * @brief Sets input the outline's properties string. @@ -1496,7 +1496,7 @@ public: // Default style & Input style * * @return The outline's properties string. */ - const std::string& GetInputOutlineProperties() const; + std::string GetInputOutlineProperties() const; /** * @brief Sets the input strikethrough's properties string. @@ -1512,7 +1512,7 @@ public: // Default style & Input style * * @return The strikethrough's properties string. */ - const std::string& GetInputStrikethroughProperties() const; + std::string GetInputStrikethroughProperties() const; /** * @brief Set the control's interface. diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.cpp index 8e9ec06..f39afce 100644 --- a/dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.cpp +++ b/dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.cpp @@ -35,8 +35,7 @@ namespace Text { namespace { -const std::string NONE("none"); -const std::string MULTIPLY("multiply"); +const char* MULTIPLY = "multiply"; } // namespace void ProcessEmbeddedItem(const Tag& tag, EmbeddedItem& embeddedItem) diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-font.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-font.cpp index 133d7fa..13afaa0 100644 --- a/dali-toolkit/internal/text/markup-processor/markup-processor-font.cpp +++ b/dali-toolkit/internal/text/markup-processor/markup-processor-font.cpp @@ -37,9 +37,6 @@ namespace Text { 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 diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.cpp index b0ac16b..f7ed507 100644 --- a/dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.cpp +++ b/dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.cpp @@ -44,23 +44,23 @@ const char WEB_COLOR_TOKEN('#'); 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 diff --git a/dali-toolkit/internal/text/text-effects-style.cpp b/dali-toolkit/internal/text/text-effects-style.cpp index c15a11d..b022bb6 100644 --- a/dali-toolkit/internal/text/text-effects-style.cpp +++ b/dali-toolkit/internal/text/text-effects-style.cpp @@ -32,17 +32,16 @@ namespace Text { 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, diff --git a/dali-toolkit/internal/text/text-font-style.cpp b/dali-toolkit/internal/text/text-font-style.cpp index ce5e860..f087a1e 100644 --- a/dali-toolkit/internal/text/text-font-style.cpp +++ b/dali-toolkit/internal/text/text-font-style.cpp @@ -33,14 +33,13 @@ namespace Text { 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 diff --git a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp index fc3ffde..fc77c6f 100644 --- a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp +++ b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -16,7 +16,7 @@ */ // CLASS HEADER -#include "texture-cache-manager.h" +#include // EXTERNAL HEADERS #include @@ -193,15 +193,12 @@ Texture TextureCacheManager::GetTexture(const TextureCacheManager::TextureId& te 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) @@ -230,14 +227,14 @@ EncodedImageBuffer TextureCacheManager::GetEncodedImageBuffer(const VisualUrl& u 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)); } diff --git a/dali-toolkit/internal/texture-manager/texture-cache-manager.h b/dali-toolkit/internal/texture-manager/texture-cache-manager.h index c1f1355..75686a1 100644 --- a/dali-toolkit/internal/texture-manager/texture-cache-manager.h +++ b/dali-toolkit/internal/texture-manager/texture-cache-manager.h @@ -2,7 +2,7 @@ #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. @@ -70,13 +70,14 @@ public: 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: /** @@ -126,11 +127,11 @@ 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 @@ -149,9 +150,10 @@ public: /** * 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 @@ -300,23 +302,6 @@ private: // 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 diff --git a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp index 643fced..c52fe91 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp +++ b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -16,7 +16,7 @@ */ // CLASS HEADER -#include "texture-manager-impl.h" +#include // EXTERNAL HEADERS #include @@ -320,12 +320,18 @@ TextureSet TextureManager::LoadTexture( 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; } } } diff --git a/dali-toolkit/internal/texture-manager/texture-manager-impl.h b/dali-toolkit/internal/texture-manager/texture-manager-impl.h index 6b3f1a7..a72a3aa 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-impl.h +++ b/dali-toolkit/internal/texture-manager/texture-manager-impl.h @@ -2,7 +2,7 @@ #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. @@ -322,9 +322,9 @@ public: /** * @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); } /** diff --git a/dali-toolkit/internal/texture-manager/texture-manager-type.h b/dali-toolkit/internal/texture-manager/texture-manager-type.h index 74057fc..2d95210 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-type.h +++ b/dali-toolkit/internal/texture-manager/texture-manager-type.h @@ -2,7 +2,7 @@ #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. @@ -234,18 +234,18 @@ struct TextureInfo 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), @@ -311,6 +311,27 @@ struct TextureInfo 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 diff --git a/dali-toolkit/public-api/image-loader/image-url.cpp b/dali-toolkit/public-api/image-loader/image-url.cpp index f936fdc..05d03c6 100644 --- a/dali-toolkit/public-api/image-loader/image-url.cpp +++ b/dali-toolkit/public-api/image-loader/image-url.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -32,9 +32,9 @@ ImageUrl::~ImageUrl() { } -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()); } diff --git a/dali-toolkit/public-api/image-loader/image-url.h b/dali-toolkit/public-api/image-loader/image-url.h index 976f179..0a4a853 100644 --- a/dali-toolkit/public-api/image-loader/image-url.h +++ b/dali-toolkit/public-api/image-loader/image-url.h @@ -2,7 +2,7 @@ #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. @@ -60,9 +60,10 @@ public: * @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. diff --git a/dali-toolkit/public-api/image-loader/image.cpp b/dali-toolkit/public-api/image-loader/image.cpp index 7b91059..8ca77d2 100644 --- a/dali-toolkit/public-api/image-loader/image.cpp +++ b/dali-toolkit/public-api/image-loader/image.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -15,7 +15,7 @@ */ // CLASS HEADER -#include "image.h" +#include // INTERNAL INCLUDES #include @@ -34,29 +34,31 @@ Dali::Toolkit::ImageUrl GenerateUrl(Dali::FrameBuffer frameBuffer, Pixel::Format { 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; } diff --git a/dali-toolkit/public-api/image-loader/image.h b/dali-toolkit/public-api/image-loader/image.h index 6db6e7e..f3675ef 100644 --- a/dali-toolkit/public-api/image-loader/image.h +++ b/dali-toolkit/public-api/image-loader/image.h @@ -2,7 +2,7 @@ #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. @@ -66,18 +66,20 @@ DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::FrameBuffer fra * 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.