From 27815de83c807c84e63231e131bc4fadb810366e Mon Sep 17 00:00:00 2001 From: seungho baek Date: Mon, 20 Feb 2023 17:19:39 +0900 Subject: [PATCH] Add model-loader to abstract gltf2-loader and dli-loader - Like glb, we need to add some new type of model. - This abstraction can make easy to add new model file format. Change-Id: Ib84dd28c082903295ff1295a5c2d4da9a74ef8ca --- .../src/dali-scene3d-internal/CMakeLists.txt | 2 + .../utc-Dali-DliLoaderImpl.cpp} | 83 ++++++----- .../utc-Dali-Gltf2LoaderImpl.cpp} | 77 ++++------ automated-tests/src/dali-scene3d/CMakeLists.txt | 2 - .../src/dali-scene3d/utc-Dali-ResourceBundle.cpp | 17 ++- .../utc-Dali-ShaderDefinitionFactory.cpp | 1 - .../internal/common/model-cache-manager.cpp | 13 -- dali-scene3d/internal/common/model-cache-manager.h | 8 - dali-scene3d/internal/common/model-load-task.cpp | 157 ++++++-------------- dali-scene3d/internal/common/model-load-task.h | 49 +++++-- .../internal/controls/model/model-impl.cpp | 51 +++---- dali-scene3d/internal/controls/model/model-impl.h | 5 - dali-scene3d/internal/file.list | 2 + .../loader/dli-loader-impl.cpp} | 162 ++++++++++++--------- dali-scene3d/internal/loader/dli-loader-impl.h | 84 +++++++++++ .../loader/gltf2-loader-impl.cpp} | 49 ++++--- dali-scene3d/internal/loader/gltf2-loader-impl.h | 59 ++++++++ dali-scene3d/internal/loader/model-loader-impl.h | 69 +++++++++ dali-scene3d/public-api/file.list | 3 +- .../public-api/loader/dli-input-parameter.h | 95 ++++++++++++ dali-scene3d/public-api/loader/dli-loader.h | 144 ------------------ dali-scene3d/public-api/loader/gltf2-loader.h | 54 ------- dali-scene3d/public-api/loader/model-loader.cpp | 155 ++++++++++++++++++++ dali-scene3d/public-api/loader/model-loader.h | 126 ++++++++++++++++ dali-scene3d/public-api/loader/resource-bundle.cpp | 38 ++--- dali-scene3d/public-api/loader/resource-bundle.h | 19 +-- 26 files changed, 936 insertions(+), 588 deletions(-) rename automated-tests/src/{dali-scene3d/utc-Dali-DliLoader.cpp => dali-scene3d-internal/utc-Dali-DliLoaderImpl.cpp} (92%) rename automated-tests/src/{dali-scene3d/utc-Dali-Gltf2Loader.cpp => dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp} (91%) rename dali-scene3d/{public-api/loader/dli-loader.cpp => internal/loader/dli-loader-impl.cpp} (90%) create mode 100644 dali-scene3d/internal/loader/dli-loader-impl.h rename dali-scene3d/{public-api/loader/gltf2-loader.cpp => internal/loader/gltf2-loader-impl.cpp} (98%) create mode 100644 dali-scene3d/internal/loader/gltf2-loader-impl.h create mode 100644 dali-scene3d/internal/loader/model-loader-impl.h create mode 100644 dali-scene3d/public-api/loader/dli-input-parameter.h delete mode 100644 dali-scene3d/public-api/loader/dli-loader.h delete mode 100644 dali-scene3d/public-api/loader/gltf2-loader.h create mode 100644 dali-scene3d/public-api/loader/model-loader.cpp create mode 100644 dali-scene3d/public-api/loader/model-loader.h diff --git a/automated-tests/src/dali-scene3d-internal/CMakeLists.txt b/automated-tests/src/dali-scene3d-internal/CMakeLists.txt index 5af964f..0109332 100755 --- a/automated-tests/src/dali-scene3d-internal/CMakeLists.txt +++ b/automated-tests/src/dali-scene3d-internal/CMakeLists.txt @@ -7,7 +7,9 @@ SET(CAPI_LIB "dali-scene3d") # List of test case sources (Only these get parsed for test cases) SET(TC_SOURCES + utc-Dali-DliLoaderImpl.cpp utc-Dali-Gltf2Asset.cpp + utc-Dali-Gltf2LoaderImpl.cpp utc-Dali-Hash.cpp utc-Dali-JsonReader.cpp utc-Dali-JsonUtil.cpp diff --git a/automated-tests/src/dali-scene3d/utc-Dali-DliLoader.cpp b/automated-tests/src/dali-scene3d-internal/utc-Dali-DliLoaderImpl.cpp similarity index 92% rename from automated-tests/src/dali-scene3d/utc-Dali-DliLoader.cpp rename to automated-tests/src/dali-scene3d-internal/utc-Dali-DliLoaderImpl.cpp index 9d67ab4..0610deb 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-DliLoader.cpp +++ b/automated-tests/src/dali-scene3d-internal/utc-Dali-DliLoaderImpl.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. @@ -18,8 +18,8 @@ // Enable debug log for test coverage #define DEBUG_ENABLED 1 +#include #include -#include #include #include #include @@ -34,7 +34,8 @@ namespace void ConfigureBlendShapeShaders(ResourceBundle& resources, const SceneDefinition& scene, Actor root, std::vector&& requests) { std::vector errors; - auto onError = [&errors](const std::string& msg) { + auto onError = [&errors](const std::string& msg) + { errors.push_back(msg); }; @@ -50,7 +51,8 @@ void ConfigureBlendShapeShaders(ResourceBundle& resources, const SceneDefinition struct Context { - ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type) { + ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type) + { return TEST_RESOURCE_DIR "/"; }; @@ -72,26 +74,21 @@ struct Context cameraParameters, lights}; - DliLoader::InputParams input{ - pathProvider(ResourceType::Mesh), - nullptr, - {}, - {}, - nullptr, - }; - DliLoader::LoadParams loadParams{input, output}; - - std::vector errors; - DliLoader loader; + Dali::Scene3D::Loader::DliInputParameter input; + std::vector errors; + Dali::Scene3D::Loader::Internal::DliLoaderImpl loader; - StringCallback onError = [this](const std::string& error) { + StringCallback onError = [this](const std::string& error) + { errors.push_back(error); printf("%s\n", error.c_str()); }; Context() { + input.mAnimationsPath = pathProvider(ResourceType::Mesh); loader.SetErrorCallback(onError); + loader.SetInputParameter(input); } }; @@ -115,7 +112,7 @@ int UtcDaliDliLoaderLoadSceneNotFound(void) { Context ctx; - DALI_TEST_EQUAL(ctx.loader.LoadScene("does_not_exist.dli", ctx.loadParams), false); + DALI_TEST_EQUAL(ctx.loader.LoadModel("does_not_exist.dli", ctx.output), false); auto error = ctx.loader.GetParseError(); DALI_TEST_CHECK(StringHasTokens(error.c_str(), {"Empty source buffer to parse."})); @@ -128,7 +125,7 @@ int UtcDaliDliLoaderLoadSceneFailParse(void) Context ctx; auto path = ctx.pathProvider(ResourceType::Mesh) + "invalid.gltf"; - DALI_TEST_EQUAL(ctx.loader.LoadScene(path, ctx.loadParams), false); + DALI_TEST_EQUAL(ctx.loader.LoadModel(path, ctx.output), false); auto error = ctx.loader.GetParseError(); DALI_TEST_CHECK(StringHasTokens(error.c_str(), {"Unexpected character."})); @@ -177,7 +174,7 @@ int UtcDaliDliLoaderLoadSceneAssertions(void) auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/" + i.first + ".dli"; printf("\n\n%s: %s\n", path.c_str(), i.second.c_str()); - DALI_TEST_ASSERTION(ctx.loader.LoadScene(path, ctx.loadParams), i.second.c_str()); + DALI_TEST_ASSERTION(ctx.loader.LoadModel(path, ctx.output), i.second.c_str()); } END_TEST; @@ -188,7 +185,7 @@ int UtcDaliDliLoaderLoadSceneExercise(void) Context ctx; auto path = ctx.pathProvider(ResourceType::Mesh) + "exercise.dli"; - DALI_TEST_CHECK(ctx.loader.LoadScene(path, ctx.loadParams)); + DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output)); DALI_TEST_CHECK(ctx.errors.empty()); auto& scene = ctx.scene; @@ -230,8 +227,9 @@ int UtcDaliDliLoaderLoadSceneExercise(void) { auto resourceRefs = resources.CreateRefCounter(); scene.CountResourceRefs(iRoot, choices, resourceRefs); - resources.CountEnvironmentReferences(resourceRefs); - resources.LoadResources(resourceRefs, ctx.pathProvider); + resources.mReferenceCounts = std::move(resourceRefs); + resources.CountEnvironmentReferences(); + resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); @@ -256,7 +254,8 @@ int UtcDaliDliLoaderLoadSceneMorph(void) std::vector metadata; uint32_t metadataCount = 0; ctx.input.mPreNodeCategoryProcessors.push_back({"metadata", - [&](const Property::Array& array, StringCallback) { + [&](const Property::Array& array, StringCallback) + { std::string key, value; for(uint32_t i0 = 0, i1 = array.Count(); i0 < i1; ++i0) { @@ -277,7 +276,8 @@ int UtcDaliDliLoaderLoadSceneMorph(void) std::vector behaviors; uint32_t behaviorCount = 0; ctx.input.mPostNodeCategoryProcessors.push_back({"behaviors", - [&](const Property::Array& array, StringCallback) { + [&](const Property::Array& array, StringCallback) + { for(uint32_t i0 = 0, i1 = array.Count(); i0 < i1; ++i0) { auto& data = array.GetElementAt(i0); @@ -295,12 +295,13 @@ int UtcDaliDliLoaderLoadSceneMorph(void) }}); size_t numNodes = 0; - ctx.input.mNodePropertyProcessor = [&](const NodeDefinition&, const Property::Map&, StringCallback) { + ctx.input.mNodePropertyProcessor = [&](const NodeDefinition&, const Property::Map&, StringCallback) + { ++numNodes; }; auto path = ctx.pathProvider(ResourceType::Mesh) + "morph.dli"; - DALI_TEST_CHECK(ctx.loader.LoadScene(path, ctx.loadParams)); + DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output)); DALI_TEST_CHECK(ctx.errors.empty()); auto& scene = ctx.scene; @@ -345,8 +346,9 @@ int UtcDaliDliLoaderLoadSceneMorph(void) { auto resourceRefs = resources.CreateRefCounter(); scene.CountResourceRefs(iRoot, choices, resourceRefs); - resources.CountEnvironmentReferences(resourceRefs); - resources.LoadResources(resourceRefs, ctx.pathProvider); + resources.mReferenceCounts = std::move(resourceRefs); + resources.CountEnvironmentReferences(); + resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); @@ -368,7 +370,7 @@ int UtcDaliDliLoaderLoadSceneArc(void) Context ctx; auto path = ctx.pathProvider(ResourceType::Mesh) + "arc.dli"; - DALI_TEST_CHECK(ctx.loader.LoadScene(path, ctx.loadParams)); + DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output)); DALI_TEST_CHECK(ctx.errors.empty()); auto& scene = ctx.scene; @@ -409,8 +411,9 @@ int UtcDaliDliLoaderLoadSceneArc(void) { auto resourceRefs = resources.CreateRefCounter(); scene.CountResourceRefs(iRoot, choices, resourceRefs); - resources.CountEnvironmentReferences(resourceRefs); - resources.LoadResources(resourceRefs, ctx.pathProvider); + resources.mReferenceCounts = std::move(resourceRefs); + resources.CountEnvironmentReferences(); + resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); @@ -432,7 +435,7 @@ int UtcDaliDliLoaderLoadSceneShaderUniforms(void) Context ctx; auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/shader-uniforms.dli"; - DALI_TEST_CHECK(ctx.loader.LoadScene(path, ctx.loadParams)); + DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output)); DALI_TEST_EQUAL(ctx.errors.size(), 1u); DALI_TEST_CHECK(ctx.errors[0].find("failed to infer type") != std::string::npos); @@ -475,7 +478,7 @@ int UtcDaliDliLoaderLoadSceneExtras(void) Context ctx; auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/extras.dli"; - DALI_TEST_CHECK(ctx.loader.LoadScene(path, ctx.loadParams)); + DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output)); DALI_TEST_EQUAL(ctx.errors.size(), 3u); DALI_TEST_CHECK(ctx.errors[0].find("already defined; overriding") != std::string::npos); DALI_TEST_CHECK(ctx.errors[1].find("empty string is invalid for name") != std::string::npos); @@ -518,7 +521,7 @@ int UtcDaliDliLoaderLoadSceneConstraints(void) Context ctx; auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/constraints.dli"; - DALI_TEST_CHECK(ctx.loader.LoadScene(path, ctx.loadParams)); + DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output)); DALI_TEST_EQUAL(ctx.errors.size(), 1u); DALI_TEST_CHECK(ctx.errors[0].find("invalid", ctx.errors[0].find("node ID")) != std::string::npos); @@ -576,12 +579,13 @@ int UtcDaliDliLoaderNodeProcessor(void) Context ctx; std::vector nodeMaps; - ctx.input.mNodePropertyProcessor = [&](const NodeDefinition&, Property::Map&& map, StringCallback) { + ctx.input.mNodePropertyProcessor = [&](const NodeDefinition&, Property::Map&& map, StringCallback) + { nodeMaps.push_back(map); }; auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/node-processor.dli"; - DALI_TEST_CHECK(ctx.loader.LoadScene(path, ctx.loadParams)); + DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output)); DALI_TEST_EQUAL(nodeMaps.size(), 2u); DALI_TEST_EQUAL(nodeMaps[0].Count(), 5u); @@ -636,7 +640,7 @@ int UtcDaliDliLoaderLoadCoverageTest(void) Context ctx; auto path = ctx.pathProvider(ResourceType::Mesh) + "coverageTest.dli"; - DALI_TEST_CHECK(ctx.loader.LoadScene(path, ctx.loadParams)); + DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output)); DALI_TEST_CHECK(ctx.errors.empty()); auto& scene = ctx.scene; @@ -688,8 +692,9 @@ int UtcDaliDliLoaderLoadCoverageTest(void) { auto resourceRefs = resources.CreateRefCounter(); scene.CountResourceRefs(iRoot, choices, resourceRefs); - resources.CountEnvironmentReferences(resourceRefs); - resources.LoadResources(resourceRefs, ctx.pathProvider); + resources.mReferenceCounts = std::move(resourceRefs); + resources.CountEnvironmentReferences(); + resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp b/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp similarity index 91% rename from automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp rename to automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp index bcb61b5..38f8e1e 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp +++ b/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp @@ -18,7 +18,7 @@ // Enable debug log for test coverage #define DEBUG_ENABLED 1 -#include +#include #include #include #include @@ -76,6 +76,8 @@ struct Context animationGroups, cameras, lights}; + + Dali::Scene3D::Loader::Internal::Gltf2LoaderImpl loader; }; struct ExceptionMessageStartsWith @@ -99,13 +101,7 @@ int UtcDaliGltfLoaderFailedToLoad(void) { Context ctx; - ShaderDefinitionFactory sdf; - sdf.SetResources(ctx.resources); - - InitializeGltfLoader(); - DALI_TEST_THROW(LoadGltfScene("non-existent.gltf", sdf, ctx.loadResult), - std::runtime_error, - ExceptionMessageStartsWith{"Failed to load"}); + DALI_TEST_EQUAL(ctx.loader.LoadModel("non-existent.gltf", ctx.loadResult), false); DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size()); DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount()); @@ -131,10 +127,7 @@ int UtcDaliGltfLoaderFailedToParse(void) ShaderDefinitionFactory sdf; sdf.SetResources(ctx.resources); - InitializeGltfLoader(); - DALI_TEST_THROW(LoadGltfScene(TEST_RESOURCE_DIR "/invalid.gltf", sdf, ctx.loadResult), - std::runtime_error, - ExceptionMessageStartsWith{"Failed to parse"}); + DALI_TEST_EQUAL(ctx.loader.LoadModel(TEST_RESOURCE_DIR "/invalid.gltf", ctx.loadResult), false); DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size()); DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount()); @@ -172,11 +165,7 @@ int UtcDaliGltfLoaderSuccess1(void) ++metaData; } - ShaderDefinitionFactory sdf; - sdf.SetResources(ctx.resources); - - InitializeGltfLoader(); - LoadGltfScene(TEST_RESOURCE_DIR "/AnimatedCube.gltf", sdf, ctx.loadResult); + ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AnimatedCube.gltf", ctx.loadResult); DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size()); DALI_TEST_EQUAL(9u, ctx.scene.GetNodeCount()); @@ -191,8 +180,9 @@ int UtcDaliGltfLoaderSuccess1(void) { auto resourceRefs = ctx.resources.CreateRefCounter(); ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs); - ctx.resources.CountEnvironmentReferences(resourceRefs); - ctx.resources.LoadResources(resourceRefs, ctx.pathProvider); + ctx.resources.mReferenceCounts = std::move(resourceRefs); + ctx.resources.CountEnvironmentReferences(); + ctx.resources.LoadResources(ctx.pathProvider); } auto& materials = ctx.resources.mMaterials; @@ -466,8 +456,7 @@ int UtcDaliGltfLoaderSuccess2(void) ShaderDefinitionFactory sdf; sdf.SetResources(ctx.resources); - InitializeGltfLoader(); - LoadGltfScene(TEST_RESOURCE_DIR "/AnimatedCubeStride.gltf", sdf, ctx.loadResult); + ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AnimatedCubeStride.gltf", ctx.loadResult); DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size()); DALI_TEST_EQUAL(1u, ctx.scene.GetNodeCount()); @@ -479,7 +468,8 @@ int UtcDaliGltfLoaderSuccess2(void) { auto resourceRefs = ctx.resources.CreateRefCounter(); ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs); - ctx.resources.LoadResources(resourceRefs, ctx.pathProvider); + ctx.resources.mReferenceCounts = std::move(resourceRefs); + ctx.resources.LoadResources(ctx.pathProvider); } DALI_TEST_EQUAL(true, ctx.resources.mMeshes[0u].first.mPositions.IsDefined()); @@ -517,16 +507,11 @@ int UtcDaliGltfLoaderSuccessShort(void) { Context ctx; - ShaderDefinitionFactory sdf; - auto& resources = ctx.resources; resources.mEnvironmentMaps.push_back({}); - sdf.SetResources(resources); - printf("%s\n", modelName); - InitializeGltfLoader(); - LoadGltfScene(resourcePath + modelName + ".gltf", sdf, ctx.loadResult); + ctx.loader.LoadModel(resourcePath + modelName + ".gltf", ctx.loadResult); DALI_TEST_CHECK(ctx.scene.GetNodeCount() > 0); auto& scene = ctx.scene; @@ -587,8 +572,7 @@ int UtcDaliGltfLoaderMRendererTest(void) sdf.SetResources(ctx.resources); auto& resources = ctx.resources; - InitializeGltfLoader(); - LoadGltfScene(TEST_RESOURCE_DIR "/MRendererTest.gltf", sdf, ctx.loadResult); + ctx.loader.LoadModel(TEST_RESOURCE_DIR "/MRendererTest.gltf", ctx.loadResult); auto& scene = ctx.scene; auto& roots = scene.GetRoots(); @@ -617,8 +601,9 @@ int UtcDaliGltfLoaderMRendererTest(void) { auto resourceRefs = resources.CreateRefCounter(); scene.CountResourceRefs(iRoot, choices, resourceRefs); - resources.CountEnvironmentReferences(resourceRefs); - resources.LoadResources(resourceRefs, ctx.pathProvider); + ctx.resources.mReferenceCounts = std::move(resourceRefs); + ctx.resources.CountEnvironmentReferences(); + ctx.resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); @@ -646,12 +631,9 @@ int UtcDaliGltfLoaderAnimationLoadingTest(void) { Context ctx; - ShaderDefinitionFactory sdf; - sdf.SetResources(ctx.resources); auto& resources = ctx.resources; - InitializeGltfLoader(); - LoadGltfScene(TEST_RESOURCE_DIR "/CesiumMan_e.gltf", sdf, ctx.loadResult); + ctx.loader.LoadModel(TEST_RESOURCE_DIR "/CesiumMan_e.gltf", ctx.loadResult); auto& scene = ctx.scene; auto& roots = scene.GetRoots(); @@ -676,8 +658,9 @@ int UtcDaliGltfLoaderAnimationLoadingTest(void) { auto resourceRefs = resources.CreateRefCounter(); scene.CountResourceRefs(iRoot, choices, resourceRefs); - resources.CountEnvironmentReferences(resourceRefs); - resources.LoadResources(resourceRefs, ctx.pathProvider); + resources.mReferenceCounts = std::move(resourceRefs); + resources.CountEnvironmentReferences(); + resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); @@ -704,8 +687,7 @@ int UtcDaliGltfLoaderImageFromBufferView(void) sdf.SetResources(ctx.resources); auto& resources = ctx.resources; - InitializeGltfLoader(); - LoadGltfScene(TEST_RESOURCE_DIR "/EnvironmentTest_b.gltf", sdf, ctx.loadResult); + ctx.loader.LoadModel(TEST_RESOURCE_DIR "/EnvironmentTest_b.gltf", ctx.loadResult); auto& scene = ctx.scene; auto& roots = scene.GetRoots(); @@ -730,8 +712,9 @@ int UtcDaliGltfLoaderImageFromBufferView(void) { auto resourceRefs = resources.CreateRefCounter(); scene.CountResourceRefs(iRoot, choices, resourceRefs); - resources.CountEnvironmentReferences(resourceRefs); - resources.LoadResources(resourceRefs, ctx.pathProvider); + resources.mReferenceCounts = std::move(resourceRefs); + resources.CountEnvironmentReferences(); + resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); @@ -752,12 +735,9 @@ int UtcDaliGltfLoaderUint8Indices(void) { Context ctx; - ShaderDefinitionFactory sdf; - sdf.SetResources(ctx.resources); auto& resources = ctx.resources; - InitializeGltfLoader(); - LoadGltfScene(TEST_RESOURCE_DIR "/AlphaBlendModeTest.gltf", sdf, ctx.loadResult); + ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AlphaBlendModeTest.gltf", ctx.loadResult); auto& scene = ctx.scene; auto& roots = scene.GetRoots(); @@ -782,8 +762,9 @@ int UtcDaliGltfLoaderUint8Indices(void) { auto resourceRefs = resources.CreateRefCounter(); scene.CountResourceRefs(iRoot, choices, resourceRefs); - resources.CountEnvironmentReferences(resourceRefs); - resources.LoadResources(resourceRefs, ctx.pathProvider); + resources.mReferenceCounts = std::move(resourceRefs); + resources.CountEnvironmentReferences(); + resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); diff --git a/automated-tests/src/dali-scene3d/CMakeLists.txt b/automated-tests/src/dali-scene3d/CMakeLists.txt index 707bdd5..66a766a 100755 --- a/automated-tests/src/dali-scene3d/CMakeLists.txt +++ b/automated-tests/src/dali-scene3d/CMakeLists.txt @@ -13,10 +13,8 @@ SET(TC_SOURCES utc-Dali-BvhLoader.cpp utc-Dali-CameraParameters.cpp utc-Dali-EnvironmentMapLoader.cpp - utc-Dali-DliLoader.cpp utc-Dali-EnvironmentDefinition.cpp utc-Dali-FacialAnimation.cpp - utc-Dali-Gltf2Loader.cpp utc-Dali-KtxLoader.cpp utc-Dali-Model.cpp utc-Dali-SceneView.cpp diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ResourceBundle.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ResourceBundle.cpp index 20c1bcb..162e48e 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-ResourceBundle.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-ResourceBundle.cpp @@ -18,10 +18,10 @@ // Enable debug log for test coverage #define DEBUG_ENABLED 1 -#include "dali-scene3d/public-api/loader/resource-bundle.h" -#include "dali-scene3d/public-api/loader/utils.h" #include #include +#include "dali-scene3d/public-api/loader/resource-bundle.h" +#include "dali-scene3d/public-api/loader/utils.h" using namespace Dali; using namespace Dali::Scene3D::Loader; @@ -34,9 +34,9 @@ int UtcDaliResourceRefCounts(void) resourceBundle.mMeshes.resize(17); resourceBundle.mMaterials.resize(19); - int i = 0; + int i = 0; std::vector testEnvironmentReferences(resourceBundle.mEnvironmentMaps.size()); - for (auto& m : resourceBundle.mMaterials) + for(auto& m : resourceBundle.mMaterials) { Index iEnv = 0; iEnv += (i % 3) == 0; @@ -56,9 +56,12 @@ int UtcDaliResourceRefCounts(void) DALI_TEST_EQUAL(counter[ResourceType::Material].Size(), resourceBundle.mMaterials.size()); std::fill(counter[ResourceType::Material].begin(), counter[ResourceType::Material].end(), 1u); - resourceBundle.CountEnvironmentReferences(counter); - i = 0; - for (auto& er: counter[ResourceType::Environment]) + resourceBundle.mReferenceCounts = std::move(counter); + resourceBundle.CountEnvironmentReferences(); + + const ResourceRefCounts& referenceCounts = resourceBundle.mReferenceCounts; + i = 0; + for(auto& er : referenceCounts[ResourceType::Environment]) { DALI_TEST_EQUAL(er, testEnvironmentReferences[i]); ++i; diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp index 12f9605..0a269a5 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp @@ -24,7 +24,6 @@ #include #include #include -#include "dali-scene3d/public-api/loader/gltf2-loader.h" #include "dali-scene3d/public-api/loader/node-definition.h" #include "dali-scene3d/public-api/loader/resource-bundle.h" #include "dali-scene3d/public-api/loader/shader-definition-factory.h" diff --git a/dali-scene3d/internal/common/model-cache-manager.cpp b/dali-scene3d/internal/common/model-cache-manager.cpp index 01d2eba..0a26bcc 100644 --- a/dali-scene3d/internal/common/model-cache-manager.cpp +++ b/dali-scene3d/internal/common/model-cache-manager.cpp @@ -57,12 +57,6 @@ public: return cache.loadSceneConditionalWait; } - Dali::ConditionalWait& GetLoadRawResourceConditionalWaitInstance(std::string modelUri) - { - ModelCache& cache = mModelCache[modelUri]; - return cache.loadRawResourceConditionalWait; - } - void ReferenceModelCache(std::string modelUri) { ModelCache& cache = mModelCache[modelUri]; @@ -129,7 +123,6 @@ private: uint32_t refCount{0}; ///< The reference count of this model cache. Dali::ConditionalWait loadSceneConditionalWait{}; ///< The conditionalWait instance used to synchronise the loading of the scene for the same model in different threads. - Dali::ConditionalWait loadRawResourceConditionalWait{}; ///< The conditionalWait instance used to synchronise the loading of the shared raw resources for the same model in different threads. bool isSceneLoaded{false}; ///< Whether the scene of the model has been loaded. bool isSceneLoading{false}; ///< Whether the scene loading of the model is in progress. @@ -192,12 +185,6 @@ Dali::ConditionalWait& ModelCacheManager::GetLoadSceneConditionalWaitInstance(st return impl.GetLoadSceneConditionalWaitInstance(modelUri); } -Dali::ConditionalWait& ModelCacheManager::GetLoadRawResourceConditionalWaitInstance(std::string modelUri) -{ - ModelCacheManager::Impl& impl = static_cast(GetBaseObject()); - return impl.GetLoadRawResourceConditionalWaitInstance(modelUri); -} - void ModelCacheManager::ReferenceModelCache(std::string modelUri) { ModelCacheManager::Impl& impl = static_cast(GetBaseObject()); diff --git a/dali-scene3d/internal/common/model-cache-manager.h b/dali-scene3d/internal/common/model-cache-manager.h index a427945..0d30b26 100644 --- a/dali-scene3d/internal/common/model-cache-manager.h +++ b/dali-scene3d/internal/common/model-cache-manager.h @@ -86,14 +86,6 @@ public: Dali::ConditionalWait& GetLoadSceneConditionalWaitInstance(std::string modelUri); /** - * @brief Retrieves the ConditionalWait object to synchronize the raw resources loading of the - * model with the given URI between multiple threads. - * @param[in] modelUri The unique model URI with its absolute path. - * @return The ConditionalWait object. - */ - Dali::ConditionalWait& GetLoadRawResourceConditionalWaitInstance(std::string modelUri); - - /** * @brief Reference the cache of the model with the given URI. * This will increment the reference count of the load result by 1. * @param[in] modelUri The model URI. diff --git a/dali-scene3d/internal/common/model-load-task.cpp b/dali-scene3d/internal/common/model-load-task.cpp index aaec429..b979c22 100644 --- a/dali-scene3d/internal/common/model-load-task.cpp +++ b/dali-scene3d/internal/common/model-load-task.cpp @@ -22,16 +22,6 @@ #include #include -// INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include -#include - namespace Dali { namespace Scene3D @@ -41,20 +31,15 @@ namespace Internal namespace { static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f); - -static constexpr std::string_view OBJ_EXTENSION = ".obj"; -static constexpr std::string_view GLTF_EXTENSION = ".gltf"; -static constexpr std::string_view DLI_EXTENSION = ".dli"; -static constexpr std::string_view METADATA_EXTENSION = "metadata"; } // namespace ModelLoadTask::ModelLoadTask(const std::string& modelUrl, const std::string& resourceDirectoryUrl, CallbackBase* callback) : AsyncTask(callback), mModelUrl(modelUrl), mResourceDirectoryUrl(resourceDirectoryUrl), - mHasSucceeded(false), - mModelCacheManager(ModelCacheManager::Get()), - mLoadResult(mModelCacheManager.GetModelLoadResult(modelUrl)) + mModelCacheManager(Scene3D::Internal::ModelCacheManager::Get()), + mLoadResult(mModelCacheManager.GetModelLoadResult(mModelUrl)), + mHasSucceeded(false) { } @@ -64,124 +49,51 @@ ModelLoadTask::~ModelLoadTask() void ModelLoadTask::Process() { - uint32_t cacheRefCount = mModelCacheManager.GetModelCacheRefCount(mModelUrl); - Dali::ConditionalWait& loadSceneConditionalWait = mModelCacheManager.GetLoadSceneConditionalWaitInstance(mModelUrl); - Dali::ConditionalWait& loadRawResourceConditionalWait = mModelCacheManager.GetLoadRawResourceConditionalWaitInstance(mModelUrl); - - std::filesystem::path modelUrl(mModelUrl); if(mResourceDirectoryUrl.empty()) { + std::filesystem::path modelUrl(mModelUrl); mResourceDirectoryUrl = std::string(modelUrl.parent_path()) + "/"; } - std::string extension = modelUrl.extension(); - std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); - Dali::Scene3D::Loader::ResourceBundle::PathProvider pathProvider = [&](Dali::Scene3D::Loader::ResourceType::Value type) { + Dali::Scene3D::Loader::ResourceBundle::PathProvider pathProvider = [&](Dali::Scene3D::Loader::ResourceType::Value type) + { return mResourceDirectoryUrl; }; + mModelLoader = std::make_shared(mModelUrl, mResourceDirectoryUrl, mLoadResult); + + bool loadSucceeded = false; + Dali::ConditionalWait& loadSceneConditionalWait = mModelCacheManager.GetLoadSceneConditionalWaitInstance(mModelUrl); { ConditionalWait::ScopedLock lock(loadSceneConditionalWait); - - while(cacheRefCount > 1 && mModelCacheManager.IsSceneLoading(mModelUrl)) + if(mModelCacheManager.IsSceneLoaded(mModelUrl)) { - loadSceneConditionalWait.Wait(); + loadSucceeded = true; } - } - - { - ConditionalWait::ScopedLock lock(loadSceneConditionalWait); - - if(!mModelCacheManager.IsSceneLoaded(mModelUrl)) + else { mModelCacheManager.SetSceneLoading(mModelUrl, true); - std::filesystem::path metaDataUrl = modelUrl; - metaDataUrl.replace_extension(METADATA_EXTENSION.data()); - - Dali::Scene3D::Loader::LoadSceneMetadata(metaDataUrl.c_str(), mLoadResult.mSceneMetadata); - - mLoadResult.mAnimationDefinitions.clear(); + loadSucceeded = mModelLoader->LoadModel(pathProvider, true); - if(extension == DLI_EXTENSION) + // Mesh of glTF and dli is defined in right hand coordinate system, with positive Y for Up direction. + // Because DALi uses left hand system, Y direciton will be flipped for environment map sampling. + for(auto&& env : GetResources().mEnvironmentMaps) { - Dali::Scene3D::Loader::DliLoader loader; - Dali::Scene3D::Loader::DliLoader::InputParams input{ - pathProvider(Dali::Scene3D::Loader::ResourceType::Mesh), - nullptr, - {}, - {}, - nullptr, - {}}; - Dali::Scene3D::Loader::DliLoader::LoadParams loadParams{input, mLoadResult}; - if(!loader.LoadScene(mModelUrl, loadParams)) - { - DALI_LOG_ERROR("Failed to load scene from '%s': %s\n", mModelUrl.c_str(), loader.GetParseError().c_str()); - - mModelCacheManager.SetSceneLoaded(mModelUrl, false); - mModelCacheManager.SetSceneLoading(mModelUrl, false); - mModelCacheManager.UnreferenceModelCache(mModelUrl); - - return; - } + env.first.mYDirection = Y_DIRECTION; } - else if(extension == GLTF_EXTENSION) - { - Dali::Scene3D::Loader::ShaderDefinitionFactory sdf; - sdf.SetResources(mLoadResult.mResources); - Dali::Scene3D::Loader::LoadGltfScene(mModelUrl, sdf, mLoadResult); - } - else - { - DALI_LOG_ERROR("Unsupported model type.\n"); - - mModelCacheManager.SetSceneLoaded(mModelUrl, false); - mModelCacheManager.SetSceneLoading(mModelUrl, false); - mModelCacheManager.UnreferenceModelCache(mModelUrl); - return; - } - - mModelCacheManager.SetSceneLoaded(mModelUrl, true); mModelCacheManager.SetSceneLoading(mModelUrl, false); + mModelCacheManager.SetSceneLoaded(mModelUrl, loadSucceeded); } } - loadSceneConditionalWait.Notify(); - + if(!loadSucceeded) { - ConditionalWait::ScopedLock lock(loadRawResourceConditionalWait); - - while(cacheRefCount > 1 && mLoadResult.mResources.mRawResourcesLoading) - { - loadRawResourceConditionalWait.Wait(); - } + DALI_LOG_ERROR("Failed to load scene from '%s'\n", mModelUrl.c_str()); + return; } - { - ConditionalWait::ScopedLock lock(loadRawResourceConditionalWait); - - mResourceRefCount = std::move(mLoadResult.mResources.CreateRefCounter()); - - for(auto iRoot : mLoadResult.mScene.GetRoots()) - { - mLoadResult.mScene.CountResourceRefs(iRoot, mResourceChoices, mResourceRefCount); - } - - mLoadResult.mResources.CountEnvironmentReferences(mResourceRefCount); - - mLoadResult.mResources.LoadRawResources(mResourceRefCount, pathProvider); - - // glTF Mesh is defined in right hand coordinate system, with positive Y for Up direction. - // Because DALi uses left hand system, Y direciton will be flipped for environment map sampling. - for(auto&& env : mLoadResult.mResources.mEnvironmentMaps) - { - env.first.mYDirection = Y_DIRECTION; - } - } - - loadRawResourceConditionalWait.Notify(); - mHasSucceeded = true; } @@ -195,6 +107,31 @@ bool ModelLoadTask::HasSucceeded() const return mHasSucceeded; } +Dali::Scene3D::Loader::SceneDefinition& ModelLoadTask::GetScene() const +{ + return mModelLoader->GetScene(); +} + +Dali::Scene3D::Loader::ResourceBundle& ModelLoadTask::GetResources() const +{ + return mModelLoader->GetResources(); +} + +std::vector& ModelLoadTask::GetAnimations() const +{ + return mModelLoader->GetAnimations(); +} + +std::vector& ModelLoadTask::GetCameras() const +{ + return mModelLoader->GetCameras(); +} + +Dali::Scene3D::Loader::Customization::Choices& ModelLoadTask::GetResourceChoices() +{ + return mModelLoader->GetResourceChoices(); +} + } // namespace Internal } // namespace Scene3D diff --git a/dali-scene3d/internal/common/model-load-task.h b/dali-scene3d/internal/common/model-load-task.h index bfafeb0..a880748 100644 --- a/dali-scene3d/internal/common/model-load-task.h +++ b/dali-scene3d/internal/common/model-load-task.h @@ -18,6 +18,7 @@ */ // EXTERNAL INCLUDES +#include #include #include #include @@ -26,9 +27,9 @@ // INTERNAL INCLUDES #include #include +#include #include #include -#include namespace Dali { @@ -72,6 +73,36 @@ public: */ bool HasSucceeded() const; + /** + * @brief Retrieves loaded scene + * @return SceneDefinition that is loaded from file + */ + Dali::Scene3D::Loader::SceneDefinition& GetScene() const; + + /** + * @brief Retrieves resource bunder that includes resource information + * @return ResourceBundle for model resources + */ + Dali::Scene3D::Loader::ResourceBundle& GetResources() const; + + /** + * @brief Retrieves loaded AnimationDefinition + * @return AnimationDefinition that is loaded from file + */ + std::vector& GetAnimations() const; + + /** + * @brief Retrieves loaded CameraParameters + * @return CameraParameters list that is loaded from file + */ + std::vector& GetCameras() const; + + /** + * @brief Retrieves ResourceChoices + * @return Choices for loaded Resources + */ + Dali::Scene3D::Loader::Customization::Choices& GetResourceChoices(); + private: // Undefined ModelLoadTask(const ModelLoadTask& task) = delete; @@ -79,16 +110,12 @@ private: // Undefined ModelLoadTask& operator=(const ModelLoadTask& task) = delete; -public: - std::string mModelUrl; - std::string mResourceDirectoryUrl; - - Dali::Scene3D::Loader::Customization::Choices mResourceChoices; - Dali::Scene3D::Loader::ResourceRefCounts mResourceRefCount; - bool mHasSucceeded; - - ModelCacheManager mModelCacheManager; - Dali::Scene3D::Loader::LoadResult mLoadResult; + std::string mModelUrl; + std::string mResourceDirectoryUrl; + std::shared_ptr mModelLoader; + ModelCacheManager mModelCacheManager; + Dali::Scene3D::Loader::LoadResult mLoadResult; + bool mHasSucceeded; }; } // namespace Internal diff --git a/dali-scene3d/internal/controls/model/model-impl.cpp b/dali-scene3d/internal/controls/model/model-impl.cpp index b7cb6ef..5aa4a5f 100644 --- a/dali-scene3d/internal/controls/model/model-impl.cpp +++ b/dali-scene3d/internal/controls/model/model-impl.cpp @@ -36,8 +36,6 @@ #include #include #include -#include -#include #include #include #include @@ -117,7 +115,8 @@ void ConfigureBlendShapeShaders( Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector&& requests) { std::vector errors; - auto onError = [&errors](const std::string& msg) { errors.push_back(msg); }; + auto onError = [&errors](const std::string& msg) + { errors.push_back(msg); }; if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError)) { Dali::Scene3D::Loader::ExceptionFlinger flinger(ASSERT_LOCATION); @@ -447,8 +446,6 @@ void Model::OnSceneConnection(int depth) { ModelCacheManager::Get().ReferenceModelCache(mModelUrl); } - - Scene3D::Loader::InitializeGltfLoader(); mModelLoadTask = new ModelLoadTask(mModelUrl, mResourceDirectoryUrl, MakeCallback(this, &Model::OnModelLoadComplete)); Dali::AsyncTaskManager::Get().AddTask(mModelLoadTask); } @@ -732,13 +729,14 @@ void Model::OnModelLoadComplete() mRenderableActors.clear(); CollectRenderableActor(mModelRoot); - CreateAnimations(mModelLoadTask->mLoadResult.mScene); + auto& resources = mModelLoadTask->GetResources(); + auto& scene = mModelLoadTask->GetScene(); + CreateAnimations(scene); ResetCameraParameters(); - - if(!mModelLoadTask->mLoadResult.mResources.mEnvironmentMaps.empty()) + if(!resources.mEnvironmentMaps.empty()) { - mDefaultDiffuseTexture = mModelLoadTask->mLoadResult.mResources.mEnvironmentMaps.front().second.mDiffuse; - mDefaultSpecularTexture = mModelLoadTask->mLoadResult.mResources.mEnvironmentMaps.front().second.mSpecular; + mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse; + mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular; } UpdateImageBasedLightTexture(); @@ -820,26 +818,28 @@ void Model::CreateModel() 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(); Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}}; - Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{mModelLoadTask->mLoadResult.mResources, xforms, {}, {}, {}}; + Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}}; // Generate Dali handles from resource bundle. Note that we generate all scene's resouce immediatly. - mModelLoadTask->mLoadResult.mResources.GenerateResources(mModelLoadTask->mResourceRefCount); - - for(auto iRoot : mModelLoadTask->mLoadResult.mScene.GetRoots()) + resources.GenerateResources(); + for(auto iRoot : scene.GetRoots()) { - if(auto actor = mModelLoadTask->mLoadResult.mScene.CreateNodes(iRoot, mModelLoadTask->mResourceChoices, nodeParams)) + if(auto actor = scene.CreateNodes(iRoot, resourceChoices, nodeParams)) { - mModelLoadTask->mLoadResult.mScene.ConfigureSkeletonJoints(iRoot, mModelLoadTask->mLoadResult.mResources.mSkeletons, actor); - mModelLoadTask->mLoadResult.mScene.ConfigureSkinningShaders(mModelLoadTask->mLoadResult.mResources, actor, std::move(nodeParams.mSkinnables)); - ConfigureBlendShapeShaders(mModelLoadTask->mLoadResult.mResources, mModelLoadTask->mLoadResult.mScene, actor, std::move(nodeParams.mBlendshapeRequests)); + scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); + scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); + ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); - mModelLoadTask->mLoadResult.mScene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); + scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); mModelRoot.Add(actor); } - AddModelTreeToAABB(AABB, mModelLoadTask->mLoadResult.mScene, mModelLoadTask->mResourceChoices, iRoot, nodeParams, Matrix::IDENTITY); + AddModelTreeToAABB(AABB, scene, resourceChoices, iRoot, nodeParams, Matrix::IDENTITY); } mNaturalSize = AABB.CalculateSize(); @@ -857,9 +857,10 @@ void Model::CreateModel() void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene) { mAnimations.clear(); - if(!mModelLoadTask->mLoadResult.mAnimationDefinitions.empty()) + if(!mModelLoadTask->GetAnimations().empty()) { - auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) { + auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) + { if(property.mNodeIndex == Scene3D::Loader::INVALID_INDEX) { return mModelRoot.FindChildByName(property.mNodeName); @@ -872,7 +873,7 @@ void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene) return mModelRoot.FindChildById(node->mNodeId); }; - for(auto&& animation : mModelLoadTask->mLoadResult.mAnimationDefinitions) + for(auto&& animation : mModelLoadTask->GetAnimations()) { Dali::Animation anim = animation.ReAnimate(getActor); mAnimations.push_back({animation.mName, anim}); @@ -883,10 +884,10 @@ void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene) void Model::ResetCameraParameters() { mCameraParameters.clear(); - if(!mModelLoadTask->mLoadResult.mCameraParameters.empty()) + if(!mModelLoadTask->GetCameras().empty()) { // Copy camera parameters. - std::copy(mModelLoadTask->mLoadResult.mCameraParameters.begin(), mModelLoadTask->mLoadResult.mCameraParameters.end(), std::back_inserter(mCameraParameters)); + std::copy(mModelLoadTask->GetCameras().begin(), mModelLoadTask->GetCameras().end(), std::back_inserter(mCameraParameters)); } } diff --git a/dali-scene3d/internal/controls/model/model-impl.h b/dali-scene3d/internal/controls/model/model-impl.h index cd1daf5..939de84 100644 --- a/dali-scene3d/internal/controls/model/model-impl.h +++ b/dali-scene3d/internal/controls/model/model-impl.h @@ -263,11 +263,6 @@ private: void ResetResourceTask(IntrusivePtr asyncTask); /** - * @brief Request to load a Ibl texture asynchronously - */ - void RequestLoadIblTexture(EnvironmentMapLoadTaskPtr asyncLoadTask, const std::string& url); - - /** * @brief Notify Resource Ready signal. */ void NotifyResourceReady(); diff --git a/dali-scene3d/internal/file.list b/dali-scene3d/internal/file.list index 85b5cbc..f9d8182 100644 --- a/dali-scene3d/internal/file.list +++ b/dali-scene3d/internal/file.list @@ -10,7 +10,9 @@ set(scene3d_src_files ${scene3d_src_files} ${scene3d_internal_dir}/common/model-load-task.cpp ${scene3d_internal_dir}/controls/model/model-impl.cpp ${scene3d_internal_dir}/controls/scene-view/scene-view-impl.cpp + ${scene3d_internal_dir}/loader/dli-loader-impl.cpp ${scene3d_internal_dir}/loader/gltf2-asset.cpp + ${scene3d_internal_dir}/loader/gltf2-loader-impl.cpp ${scene3d_internal_dir}/loader/hash.cpp ${scene3d_internal_dir}/loader/json-reader.cpp ${scene3d_internal_dir}/loader/json-util.cpp diff --git a/dali-scene3d/public-api/loader/dli-loader.cpp b/dali-scene3d/internal/loader/dli-loader-impl.cpp similarity index 90% rename from dali-scene3d/public-api/loader/dli-loader.cpp rename to dali-scene3d/internal/loader/dli-loader-impl.cpp index 1a087c9..90c5e1d 100644 --- a/dali-scene3d/public-api/loader/dli-loader.cpp +++ b/dali-scene3d/internal/loader/dli-loader-impl.cpp @@ -16,11 +16,12 @@ */ // CLASS HEADER -#include "dali-scene3d/public-api/loader/dli-loader.h" +#include // EXTERNAL INCLUDES #include #include +#include #include #include #include @@ -30,18 +31,18 @@ #include "dali/public-api/object/property-array.h" // INTERNAL INCLUDES -#include "dali-scene3d/internal/loader/json-util.h" -#include "dali-scene3d/public-api/loader/alpha-function-helper.h" -#include "dali-scene3d/public-api/loader/animation-definition.h" -#include "dali-scene3d/public-api/loader/blend-shape-details.h" -#include "dali-scene3d/public-api/loader/camera-parameters.h" -#include "dali-scene3d/public-api/loader/ktx-loader.h" -#include "dali-scene3d/public-api/loader/light-parameters.h" -#include "dali-scene3d/public-api/loader/load-result.h" -#include "dali-scene3d/public-api/loader/parse-renderer-state.h" -#include "dali-scene3d/public-api/loader/scene-definition.h" -#include "dali-scene3d/public-api/loader/skinning-details.h" -#include "dali-scene3d/public-api/loader/utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define DLI_0_1_COMPATIBILITY @@ -53,6 +54,8 @@ namespace Scene3D { namespace Loader { +namespace Internal +{ namespace rs = RendererState; namespace @@ -109,7 +112,7 @@ bool ReadAttribAccessor(const TreeNode* node, MeshDefinition::Accessor& accessor return ReadBlob(node, accessor.mBlob.mOffset, accessor.mBlob.mLength); } -bool ReadColorCode(const TreeNode* node, Vector4& color, DliLoader::ConvertColorCode convertColorCode) +bool ReadColorCode(const TreeNode* node, Vector4& color, DliInputParameter::ConvertColorCode convertColorCode) { if(!node || !convertColorCode) { @@ -121,7 +124,7 @@ bool ReadColorCode(const TreeNode* node, Vector4& color, DliLoader::ConvertColor return true; } -bool ReadColorCodeOrColor(const TreeNode* node, Vector4& color, DliLoader::ConvertColorCode convertColorCode) +bool ReadColorCodeOrColor(const TreeNode* node, Vector4& color, DliInputParameter::ConvertColorCode convertColorCode) { return ReadColorCode(node->GetChild("colorCode"), color, convertColorCode) || ReadColor(node->GetChild("color"), color); @@ -302,7 +305,7 @@ void ParseProperties(const Toolkit::TreeNode& node, Property::Array& array) } // namespace -struct DliLoader::Impl +struct DliLoaderImpl::Impl { StringCallback mOnError = DefaultErrorCallback; Toolkit::JsonParser mParser; @@ -342,9 +345,9 @@ private: */ void ParseSceneInternal(Index iScene, const Toolkit::TreeNode* tnScenes, const Toolkit::TreeNode* tnNodes, LoadParams& params); - void ParseSkeletons(const Toolkit::TreeNode* skeletons, SceneDefinition& scene, ResourceBundle& resources); - void ParseEnvironments(const Toolkit::TreeNode* environments, ResourceBundle& resources); - void ParseMaterials(const Toolkit::TreeNode* materials, ConvertColorCode convertColorCode, ResourceBundle& resources); + void ParseSkeletons(const Toolkit::TreeNode* skeletons, Dali::Scene3D::Loader::SceneDefinition& scene, Dali::Scene3D::Loader::ResourceBundle& resources); + void ParseEnvironments(const Toolkit::TreeNode* environments, Dali::Scene3D::Loader::ResourceBundle& resources); + void ParseMaterials(const Toolkit::TreeNode* materials, DliInputParameter::ConvertColorCode convertColorCode, Dali::Scene3D::Loader::ResourceBundle& resources); void ParseNodes(const Toolkit::TreeNode* nodes, Index index, LoadParams& params); void ParseNodesInternal(const Toolkit::TreeNode* nodes, Index index, std::vector& inOutParentStack, LoadParams& params, IIndexMapper& indexMapper); @@ -352,26 +355,26 @@ private: void ParseAnimations(const Toolkit::TreeNode* animations, LoadParams& params); void ParseAnimationGroups(const Toolkit::TreeNode* animationGroups, LoadParams& params); - void ParseShaders(const Toolkit::TreeNode* shaders, ResourceBundle& resources); - void ParseMeshes(const Toolkit::TreeNode* meshes, ResourceBundle& resources); + void ParseShaders(const Toolkit::TreeNode* shaders, Dali::Scene3D::Loader::ResourceBundle& resources); + void ParseMeshes(const Toolkit::TreeNode* meshes, Dali::Scene3D::Loader::ResourceBundle& resources); - void GetCameraParameters(std::vector& cameras) const; - void GetLightParameters(std::vector& lights) const; + void GetCameraParameters(std::vector& cameras) const; + void GetLightParameters(std::vector& lights) const; }; -DliLoader::DliLoader() +DliLoaderImpl::DliLoaderImpl() : mImpl{new Impl} { } -DliLoader::~DliLoader() = default; +DliLoaderImpl::~DliLoaderImpl() = default; -void DliLoader::SetErrorCallback(StringCallback onError) +void DliLoaderImpl::SetErrorCallback(StringCallback onError) { mImpl->mOnError = onError; } -bool DliLoader::LoadScene(const std::string& uri, LoadParams& params) +bool DliLoaderImpl::LoadModel(const std::string& uri, Dali::Scene3D::Loader::LoadResult& result) { std::string daliBuffer = LoadTextFile(uri.c_str()); @@ -382,11 +385,25 @@ bool DliLoader::LoadScene(const std::string& uri, LoadParams& params) return false; } - mImpl->ParseScene(params); + std::filesystem::path modelPath(uri); + Dali::Scene3D::Loader::DliInputParameter input; + LoadParams loadParams; + if(mInputParameter) + { + loadParams.input = static_cast(mInputParameter); + } + else + { + input.mAnimationsPath = std::string(modelPath.parent_path()) + "/"; + loadParams.input = &input; + } + loadParams.output = &result; + + mImpl->ParseScene(loadParams); return true; } -std::string DliLoader::GetParseError() const +std::string DliLoaderImpl::GetParseError() const { std::stringstream stream; @@ -399,10 +416,10 @@ std::string DliLoader::GetParseError() const return stream.str(); } -void DliLoader::Impl::ParseScene(LoadParams& params) +void DliLoaderImpl::Impl::ParseScene(LoadParams& params) { - auto& input = params.input; - auto& output = params.output; + auto& input = *params.input; + auto& output = *params.output; // get index of root node. auto docRoot = mParser.GetRoot(); @@ -482,9 +499,10 @@ void DliLoader::Impl::ParseScene(LoadParams& params) } } -void DliLoader::Impl::ParseSceneInternal(Index iScene, const Toolkit::TreeNode* tnScenes, const Toolkit::TreeNode* tnNodes, LoadParams& params) +void DliLoaderImpl::Impl::ParseSceneInternal(Index iScene, const Toolkit::TreeNode* tnScenes, const Toolkit::TreeNode* tnNodes, LoadParams& params) { - auto getSceneRootIdx = [tnScenes, tnNodes](Index iScene) { + auto getSceneRootIdx = [tnScenes, tnNodes](Index iScene) + { auto tn = GetNthChild(tnScenes, iScene); // now a "scene" object if(!tn) { @@ -526,7 +544,7 @@ void DliLoader::Impl::ParseSceneInternal(Index iScene, const Toolkit::TreeNode* Index iRootNode = getSceneRootIdx(iScene); ParseNodes(tnNodes, iRootNode, params); - auto& scene = params.output.mScene; + auto& scene = params.output->mScene; scene.AddRootNode(0); for(Index i = 0; i < iScene; ++i) @@ -547,7 +565,7 @@ void DliLoader::Impl::ParseSceneInternal(Index iScene, const Toolkit::TreeNode* } } -void DliLoader::Impl::ParseSkeletons(const TreeNode* skeletons, SceneDefinition& scene, ResourceBundle& resources) +void DliLoaderImpl::Impl::ParseSkeletons(const TreeNode* skeletons, Dali::Scene3D::Loader::SceneDefinition& scene, Dali::Scene3D::Loader::ResourceBundle& resources) { if(skeletons) { @@ -567,7 +585,8 @@ void DliLoader::Impl::ParseSkeletons(const TreeNode* skeletons, SceneDefinition& uint32_t jointCount = 0; std::function visitFn; auto& ibms = mInverseBindMatrices; - visitFn = [&](Index id) { + visitFn = [&](Index id) + { auto node = scene.GetNode(id); jointCount += ibms.find(id) != ibms.end(); @@ -586,7 +605,8 @@ void DliLoader::Impl::ParseSkeletons(const TreeNode* skeletons, SceneDefinition& skeleton.mJoints.reserve(jointCount); - visitFn = [&](Index id) { + visitFn = [&](Index id) + { auto iFind = ibms.find(id); if(iFind != ibms.end() && skeleton.mJoints.size() < Skinning::MAX_JOINTS) { @@ -611,7 +631,7 @@ void DliLoader::Impl::ParseSkeletons(const TreeNode* skeletons, SceneDefinition& } } -void DliLoader::Impl::ParseEnvironments(const TreeNode* environments, ResourceBundle& resources) +void DliLoaderImpl::Impl::ParseEnvironments(const TreeNode* environments, Dali::Scene3D::Loader::ResourceBundle& resources) { Matrix cubeOrientation(Matrix::IDENTITY); @@ -641,7 +661,7 @@ void DliLoader::Impl::ParseEnvironments(const TreeNode* environments, ResourceBu } } -void DliLoader::Impl::ParseShaders(const TreeNode* shaders, ResourceBundle& resources) +void DliLoaderImpl::Impl::ParseShaders(const TreeNode* shaders, Dali::Scene3D::Loader::ResourceBundle& resources) { uint32_t iShader = 0; for(auto i0 = shaders->CBegin(), i1 = shaders->CEnd(); i0 != i1; ++i0, ++iShader) @@ -760,7 +780,7 @@ void DliLoader::Impl::ParseShaders(const TreeNode* shaders, ResourceBundle& reso } } -void DliLoader::Impl::ParseMeshes(const TreeNode* meshes, ResourceBundle& resources) +void DliLoaderImpl::Impl::ParseMeshes(const TreeNode* meshes, Dali::Scene3D::Loader::ResourceBundle& resources) { for(auto i0 = meshes->CBegin(), i1 = meshes->CEnd(); i0 != i1; ++i0) { @@ -918,7 +938,7 @@ void DliLoader::Impl::ParseMeshes(const TreeNode* meshes, ResourceBundle& resour } } -void DliLoader::Impl::ParseMaterials(const TreeNode* materials, ConvertColorCode convertColorCode, ResourceBundle& resources) +void DliLoaderImpl::Impl::ParseMaterials(const TreeNode* materials, DliInputParameter::ConvertColorCode convertColorCode, Dali::Scene3D::Loader::ResourceBundle& resources) { for(auto i0 = materials->CBegin(), i1 = materials->CEnd(); i0 != i1; ++i0) { @@ -1048,7 +1068,7 @@ void DliLoader::Impl::ParseMaterials(const TreeNode* materials, ConvertColorCode } } -void DliLoader::Impl::ParseNodes(const TreeNode* const nodes, Index index, LoadParams& params) +void DliLoaderImpl::Impl::ParseNodes(const TreeNode* const nodes, Index index, LoadParams& params) { std::vector parents; parents.reserve(8); @@ -1077,7 +1097,8 @@ void DliLoader::Impl::ParseNodes(const TreeNode* const nodes, Index index, LoadP virtual unsigned int Resolve(Index iDli) override { - auto iFind = std::lower_bound(mIndices.begin(), mIndices.end(), iDli, [](const Entry& idx, Index iDli) { return idx.iDli < iDli; }); + auto iFind = std::lower_bound(mIndices.begin(), mIndices.end(), iDli, [](const Entry& idx, Index iDli) + { return idx.iDli < iDli; }); DALI_ASSERT_ALWAYS(iFind != mIndices.end()); return iFind->iScene; } @@ -1097,7 +1118,7 @@ void DliLoader::Impl::ParseNodes(const TreeNode* const nodes, Index index, LoadP } mapper(nodes->Size()); ParseNodesInternal(nodes, index, parents, params, mapper); - auto& scene = params.output.mScene; + auto& scene = params.output->mScene; for(size_t i0 = 0, i1 = scene.GetNodeCount(); i0 < i1; ++i0) { for(auto& c : scene.GetNode(i0)->mConstraints) @@ -1107,7 +1128,7 @@ void DliLoader::Impl::ParseNodes(const TreeNode* const nodes, Index index, LoadP } } -void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index index, std::vector& inOutParentStack, LoadParams& params, IIndexMapper& mapper) +void DliLoaderImpl::Impl::ParseNodesInternal(const TreeNode* const nodes, Index index, std::vector& inOutParentStack, LoadParams& params, IIndexMapper& mapper) { // Properties that may be resolved from a JSON value with ReadInt() -- or default to 0. struct IndexProperty @@ -1121,7 +1142,7 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde if(auto node = GetNthChild(nodes, index)) { - NodeDefinition nodeDef; + Dali::Scene3D::Loader::NodeDefinition nodeDef; nodeDef.mParentIdx = inOutParentStack.empty() ? INVALID_INDEX : inOutParentStack.back(); // name @@ -1151,13 +1172,13 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde std::string tag; if(ReadString(eCustomization->GetChild("tag"), tag)) { - nodeDef.mCustomization.reset(new NodeDefinition::CustomizationDefinition{tag}); + nodeDef.mCustomization.reset(new Dali::Scene3D::Loader::NodeDefinition::CustomizationDefinition{tag}); } } else // something renderable maybe { - std::unique_ptr renderable; - ModelRenderable* modelRenderable = nullptr; // no ownership, aliasing renderable for the right type. + std::unique_ptr renderable; + ModelRenderable* modelRenderable = nullptr; // no ownership, aliasing renderable for the right type. const TreeNode* eRenderable = nullptr; if((eRenderable = node->GetChild("model"))) @@ -1212,9 +1233,9 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde resourceIds.push_back({ResourceType::Material, eMaterial, modelRenderable->mMaterialIdx}); } - if(!ReadColorCodeOrColor(eRenderable, modelRenderable->mColor, params.input.mConvertColorCode)) + if(!ReadColorCodeOrColor(eRenderable, modelRenderable->mColor, params.input->mConvertColorCode)) { - ReadColorCodeOrColor(node, modelRenderable->mColor, params.input.mConvertColorCode); + ReadColorCodeOrColor(node, modelRenderable->mColor, params.input->mConvertColorCode); } } @@ -1230,15 +1251,15 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde switch(idRes.type) { case ResourceType::Shader: - iCheck = output.mResources.mShaders.size(); + iCheck = output->mResources.mShaders.size(); break; case ResourceType::Mesh: - iCheck = output.mResources.mMeshes.size(); + iCheck = output->mResources.mMeshes.size(); break; case ResourceType::Material: - iCheck = output.mResources.mMaterials.size(); + iCheck = output->mResources.mMaterials.size(); break; default: @@ -1273,7 +1294,7 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde for(auto i0 = eExtras->CBegin(), i1 = eExtras->CEnd(); i0 != i1; ++i0) { - NodeDefinition::Extra e; + Dali::Scene3D::Loader::NodeDefinition::Extra e; auto eExtra = *i0; e.mKey = eExtra.first; @@ -1350,7 +1371,7 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde } // Determine index for mapping - const unsigned int myIndex = output.mScene.GetNodeCount(); + const unsigned int myIndex = output->mScene.GetNodeCount(); if(!mapper.Map(index, myIndex)) { mOnError(FormatString("node %d: error mapping dli index %d: node has multiple parents. Ignoring subtree.", index, myIndex)); @@ -1365,7 +1386,7 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde } // Register nodeDef - auto rawDef = output.mScene.AddNode(std::make_unique(std::move(nodeDef))); + auto rawDef = output->mScene.AddNode(std::make_unique(std::move(nodeDef))); if(rawDef) // NOTE: no ownership. Guaranteed to stay in scope. { // ...And only then parse children. @@ -1396,7 +1417,7 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde mOnError(FormatString("node %d: not an actual customization without children.", index)); } - if(auto proc = params.input.mNodePropertyProcessor) // optional processing + if(auto proc = params.input->mNodePropertyProcessor) // optional processing { // WARNING: constraint IDs are not resolved at this point. Property::Map nodeData; @@ -1411,9 +1432,9 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde } } -void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams& params) +void DliLoaderImpl::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams& params) { - auto& definitions = params.output.mAnimationDefinitions; + auto& definitions = params.output->mAnimationDefinitions; definitions.reserve(definitions.size() + tnAnimations->Size()); for(TreeNode::ConstIterator iAnim = tnAnimations->CBegin(), iAnimEnd = tnAnimations->CEnd(); @@ -1424,7 +1445,8 @@ void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams& AnimationDefinition animDef; ReadString(tnAnim.GetChild(NAME), animDef.mName); - auto iFind = std::lower_bound(definitions.begin(), definitions.end(), animDef, [](const AnimationDefinition& ad0, const AnimationDefinition& ad1) { return ad0.mName < ad1.mName; }); + 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; if(overwrite) { @@ -1532,7 +1554,7 @@ void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams& std::string animationFilename; if(ReadString(tnKeyFramesBin->GetChild(URL), animationFilename)) { - std::string animationFullPath = params.input.mAnimationsPath + animationFilename; + std::string animationFullPath = params.input->mAnimationsPath + animationFilename; binAniFile.open(animationFullPath, std::ios::binary); if(binAniFile.fail()) { @@ -1663,7 +1685,7 @@ void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams& iFind = definitions.insert(iFind, std::move(animDef)); } - if(auto proc = params.input.mAnimationPropertyProcessor) // optional processing + if(auto proc = params.input->mAnimationPropertyProcessor) // optional processing { Property::Map map; ParseProperties(tnAnim, map); @@ -1672,9 +1694,9 @@ void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams& } } -void DliLoader::Impl::ParseAnimationGroups(const Toolkit::TreeNode* tnAnimationGroups, LoadParams& params) +void DliLoaderImpl::Impl::ParseAnimationGroups(const Toolkit::TreeNode* tnAnimationGroups, LoadParams& params) { - auto& animGroups = params.output.mAnimationGroupDefinitions; + auto& animGroups = params.output->mAnimationGroupDefinitions; int numGroups = 0; for(auto iGroups = tnAnimationGroups->CBegin(), iGroupsEnd = tnAnimationGroups->CEnd(); @@ -1690,7 +1712,8 @@ void DliLoader::Impl::ParseAnimationGroups(const Toolkit::TreeNode* tnAnimationG continue; } - auto iFind = std::lower_bound(animGroups.begin(), animGroups.end(), groupName, [](const AnimationGroupDefinition& group, const std::string& name) { return group.mName < name; }); + auto iFind = std::lower_bound(animGroups.begin(), animGroups.end(), groupName, [](const AnimationGroupDefinition& group, const std::string& name) + { return group.mName < name; }); if(iFind != animGroups.end() && iFind->mName == groupName) { mOnError(FormatString("Animation group with name '%s' already exists; new entries will be merged.", groupName.c_str())); @@ -1715,7 +1738,7 @@ void DliLoader::Impl::ParseAnimationGroups(const Toolkit::TreeNode* tnAnimationG } } -void DliLoader::Impl::GetCameraParameters(std::vector& cameras) const +void DliLoaderImpl::Impl::GetCameraParameters(std::vector& cameras) const { if(mParser.GetRoot()) { @@ -1751,7 +1774,7 @@ void DliLoader::Impl::GetCameraParameters(std::vector& cameras } } -void DliLoader::Impl::GetLightParameters(std::vector& lights) const +void DliLoaderImpl::Impl::GetLightParameters(std::vector& lights) const { if(mParser.GetRoot()) { @@ -1821,6 +1844,7 @@ void DliLoader::Impl::GetLightParameters(std::vector& lights) c } } +} // namespace Internal } // namespace Loader } // namespace Scene3D } // namespace Dali diff --git a/dali-scene3d/internal/loader/dli-loader-impl.h b/dali-scene3d/internal/loader/dli-loader-impl.h new file mode 100644 index 0000000..a68432c --- /dev/null +++ b/dali-scene3d/internal/loader/dli-loader-impl.h @@ -0,0 +1,84 @@ +#ifndef DALI_SCENE3D_LOADER_DLI_LOADER_IMPL_H +#define DALI_SCENE3D_LOADER_DLI_LOADER_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. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +// EXTERNAL INCLUDES +#include "dali/public-api/common/vector-wrapper.h" + +namespace Dali +{ +namespace Scene3D +{ +namespace Loader +{ +namespace Internal +{ +typedef std::pair Metadata; + +// Forward declarations +struct LoadResult; + +class DliLoaderImpl : public ModelLoaderImpl +{ +public: + struct LoadParams + { + Dali::Scene3D::Loader::DliInputParameter* input; + Dali::Scene3D::Loader::LoadResult* output; + }; + + DliLoaderImpl(); + ~DliLoaderImpl(); + + /** + * @brief Sets the callback that messages from non-fatal errors get posted to. + * Uses DefaultErrorCallback by default. + */ + void SetErrorCallback(StringCallback onError); + + /** + * @copydoc Dali::Scene3D::Loader::Internal::ModelLoaderImpl() + */ + bool LoadModel(const std::string& uri, Dali::Scene3D::Loader::LoadResult& result) override; + + /** + * @return The error string describing how the parse has failed, if any. + */ + std::string GetParseError() const; + +private: + struct Impl; + const std::unique_ptr mImpl; +}; + +} // namespace Internal +} // namespace Loader +} // namespace Scene3D +} // namespace Dali + +#endif // DALI_SCENE3D_LOADER_DLI_LOADER_IMPL_H diff --git a/dali-scene3d/public-api/loader/gltf2-loader.cpp b/dali-scene3d/internal/loader/gltf2-loader-impl.cpp similarity index 98% rename from dali-scene3d/public-api/loader/gltf2-loader.cpp rename to dali-scene3d/internal/loader/gltf2-loader-impl.cpp index c0ca6cd..f6282a8 100644 --- a/dali-scene3d/public-api/loader/gltf2-loader.cpp +++ b/dali-scene3d/internal/loader/gltf2-loader-impl.cpp @@ -16,10 +16,9 @@ */ // FILE HEADER -#include +#include // EXTERNAL INCLUDES -#include #include #include #include @@ -42,10 +41,10 @@ namespace Scene3D { namespace Loader { +namespace Internal +{ namespace { -Dali::Mutex gInitializeMutex; -Dali::Mutex gReadMutex; const char* POSITION_PROPERTY("position"); const char* ORIENTATION_PROPERTY("orientation"); @@ -480,8 +479,8 @@ bool operator<(const NodeMapping& mapping, Index gltfIdx) class NodeIndexMapper { public: - NodeIndexMapper() = default; - NodeIndexMapper(const NodeIndexMapper&) = delete; + NodeIndexMapper() = default; + NodeIndexMapper(const NodeIndexMapper&) = delete; NodeIndexMapper& operator=(const NodeIndexMapper&) = delete; ///@brief Registers a mapping of the @a gltfIdx of a node to its @a runtimeIdx . @@ -603,7 +602,8 @@ TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm, ConversionContex void ConvertMaterial(const gt::Material& material, const std::unordered_map& imageMetaData, decltype(ResourceBundle::mMaterials)& outMaterials, ConversionContext& context) { - auto getTextureMetaData = [](const std::unordered_map& metaData, const gt::TextureInfo& info) { + auto getTextureMetaData = [](const std::unordered_map& metaData, const gt::TextureInfo& info) + { if(!info.mTexture->mSource->mUri.empty()) { if(auto search = metaData.find(info.mTexture->mSource->mUri.data()); search != metaData.end()) @@ -961,7 +961,8 @@ void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, Con auto& resources = output.mResources; const auto idx = scene.GetNodeCount(); - auto weakNode = scene.AddNode([&]() { + auto weakNode = scene.AddNode([&]() + { std::unique_ptr nodeDef{new NodeDefinition()}; nodeDef->mParentIdx = parentIdx; @@ -984,8 +985,7 @@ void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, Con } } - return nodeDef; - }()); + return nodeDef; }()); if(!weakNode) { ExceptionFlinger(ASSERT_LOCATION) << "Node name '" << node.mName << "' is not unique; scene is invalid."; @@ -1424,12 +1424,13 @@ void SetDefaultEnvironmentMap(const gt::Document& doc, ConversionContext& contex } // namespace -void InitializeGltfLoader() +void Gltf2LoaderImpl::InitializeGltfLoader() { + static Dali::Mutex mInitializeMutex; // Set ObjectReader only once (for all gltf loading). static bool setObjectReadersRequired = true; { - Mutex::ScopedLock lock(gInitializeMutex); + Mutex::ScopedLock lock(mInitializeMutex); if(setObjectReadersRequired) { // NOTE: only referencing own, anonymous namespace, const objects; the pointers will never need to change. @@ -1439,23 +1440,28 @@ void InitializeGltfLoader() } } -void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactory, LoadResult& params) +bool Gltf2LoaderImpl::LoadModel(const std::string& url, Dali::Scene3D::Loader::LoadResult& result) { bool failed = false; auto js = LoadTextFile(url.c_str(), &failed); if(failed) { - throw std::runtime_error("Failed to load " + url); + DALI_LOG_ERROR("Failed to load %s\n", url.c_str()); + return false; } json::unique_ptr root(json_parse(js.c_str(), js.size())); if(!root) { - throw std::runtime_error("Failed to parse " + url); + DALI_LOG_ERROR("Failed to parse %s\n", url.c_str()); + return false; } gt::Document doc; + Dali::Scene3D::Loader::ShaderDefinitionFactory shaderFactory; + shaderFactory.SetResources(result.mResources); + auto& rootObj = js::Cast(*root); auto jsAsset = js::FindObjectChild("asset", rootObj); @@ -1473,14 +1479,16 @@ void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactor isMRendererModel = (doc.mAsset.mGenerator.find(MRENDERER_MODEL_IDENTIFICATION) != std::string_view::npos); } + InitializeGltfLoader(); { - Mutex::ScopedLock lock(gReadMutex); + static Dali::Mutex mReadMutex; + Mutex::ScopedLock lock(mReadMutex); gt::SetRefReaderObject(doc); GetDocumentReader().Read(rootObj, doc); } auto path = url.substr(0, url.rfind('/') + 1); - ConversionContext context{params, path, INVALID_INDEX}; + ConversionContext context{result, path, INVALID_INDEX}; ConvertBuffers(doc, context); ConvertMaterials(doc, context); @@ -1488,13 +1496,16 @@ void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactor ConvertNodes(doc, context, isMRendererModel); ConvertAnimations(doc, context); ProcessSkins(doc, context); - ProduceShaders(shaderFactory, params.mScene); - params.mScene.EnsureUniqueSkinningShaderInstances(params.mResources); + ProduceShaders(shaderFactory, result.mScene); + result.mScene.EnsureUniqueSkinningShaderInstances(result.mResources); // Set Default Environment map SetDefaultEnvironmentMap(doc, context); + + return true; } +} // namespace Internal } // namespace Loader } // namespace Scene3D } // namespace Dali diff --git a/dali-scene3d/internal/loader/gltf2-loader-impl.h b/dali-scene3d/internal/loader/gltf2-loader-impl.h new file mode 100644 index 0000000..2b96608 --- /dev/null +++ b/dali-scene3d/internal/loader/gltf2-loader-impl.h @@ -0,0 +1,59 @@ +#ifndef DALI_SCENE3D_LOADER_GLTF2_LOADER_IMPL_H +#define DALI_SCENE3D_LOADER_GLTF2_LOADER_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. + * + */ + +// INTERNAL INCLUDES +#include +#include + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Loader +{ +namespace Internal +{ + +class Gltf2LoaderImpl : public ModelLoaderImpl +{ +public: + + /** + * @copydoc Dali::Scene3D::Loader::Internal::ModelLoaderImpl() + */ + bool LoadModel(const std::string& url, Dali::Scene3D::Loader::LoadResult& result) override; + +private: + /** + * @brief Initialize glTF Loader. + * @note This method should be called once before LoadGltfScene() is called. + */ + void InitializeGltfLoader(); +}; + +} // namespace Internal +} // namespace Loader +} // namespace Scene3D +} // namespace Dali + +#endif // DALI_SCENE3D_LOADER_GLTF2_LOADER_IMPL_H diff --git a/dali-scene3d/internal/loader/model-loader-impl.h b/dali-scene3d/internal/loader/model-loader-impl.h new file mode 100644 index 0000000..619cacb --- /dev/null +++ b/dali-scene3d/internal/loader/model-loader-impl.h @@ -0,0 +1,69 @@ +#ifndef DALI_SCENE3D_LOADER_MODEL_LOADER_IMPL_H +#define DALI_SCENE3D_LOADER_MODEL_LOADER_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. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Loader +{ +namespace Internal +{ +class ModelLoaderImpl +{ +public: + ModelLoaderImpl() = default; + + /** + * @brief Set InputParameter. + * Thie method store only a pointer of InputParameter. + * The object of InputParameter should not be deleted until it is no longer used. + * @param[in] inputParameter Input parameters those can be used for model loading. + */ + void SetInputParameter(Dali::Scene3D::Loader::ModelLoader::InputParameter& inputParameter) + { + mInputParameter = &inputParameter; + } + + /** + * @brief Request to load model from url. + * @param[in] url model file url. + * @param[out] result loaded model data. + * @return True if model loading is successfully finished. + */ + virtual bool LoadModel(const std::string& url, Dali::Scene3D::Loader::LoadResult& result) = 0; + +protected: + Dali::Scene3D::Loader::ModelLoader::InputParameter* mInputParameter{nullptr}; +}; +} // namespace Internal +} // namespace Loader +} // namespace Scene3D +} // namespace Dali + +#endif // DALI_SCENE3D_LOADER_MODEL_LOADER_IMPL_H diff --git a/dali-scene3d/public-api/file.list b/dali-scene3d/public-api/file.list index 95363dc..e812ae7 100644 --- a/dali-scene3d/public-api/file.list +++ b/dali-scene3d/public-api/file.list @@ -16,15 +16,14 @@ set(scene3d_src_files ${scene3d_src_files} ${scene3d_public_api_dir}/loader/environment-map-data.cpp ${scene3d_public_api_dir}/loader/environment-map-loader.cpp ${scene3d_public_api_dir}/loader/customization.cpp - ${scene3d_public_api_dir}/loader/dli-loader.cpp ${scene3d_public_api_dir}/loader/environment-definition.cpp ${scene3d_public_api_dir}/loader/facial-animation-loader.cpp - ${scene3d_public_api_dir}/loader/gltf2-loader.cpp ${scene3d_public_api_dir}/loader/ktx-loader.cpp ${scene3d_public_api_dir}/loader/load-scene-metadata.cpp ${scene3d_public_api_dir}/loader/material-definition.cpp ${scene3d_public_api_dir}/loader/matrix-stack.cpp ${scene3d_public_api_dir}/loader/mesh-definition.cpp + ${scene3d_public_api_dir}/loader/model-loader.cpp ${scene3d_public_api_dir}/loader/navigation-mesh-factory.cpp ${scene3d_public_api_dir}/loader/node-definition.cpp ${scene3d_public_api_dir}/loader/parse-renderer-state.cpp diff --git a/dali-scene3d/public-api/loader/dli-input-parameter.h b/dali-scene3d/public-api/loader/dli-input-parameter.h new file mode 100644 index 0000000..a81ba0c --- /dev/null +++ b/dali-scene3d/public-api/loader/dli-input-parameter.h @@ -0,0 +1,95 @@ +#ifndef DALI_SCENE3D_LOADER_DLI_INPUT_PARAMETER_H +#define DALI_SCENE3D_LOADER_DLI_INPUT_PARAMETER_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 +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Loader +{ + +class DliInputParameter : public ModelLoader::InputParameter +{ +public: + using ConvertFontCode = void (*)(const std::string& code, std::string& fontFamily, std::string& slant, std::string& weight, float& size); + using ConvertColorCode = Vector4 (*)(const std::string& code); + using CategoryProcessor = std::function; + using CategoryProcessorVector = std::vector>; + using NodeProcessor = std::function; + using AnimationProcessor = std::function; + +public: + /** + * @brief The absolute path of animation binaries referenced in the .dli. + */ + std::string mAnimationsPath; + + /** + * @brief Provides a facility to determine a color from a code instead of RGB(A) values. + */ + ConvertColorCode mConvertColorCode{nullptr}; + + /** + * @brief A collection of handlers, mapped to the names of the top level (i.e. below + * root) element, whom they will attempt to process. This will take place before + * the parsing of scene Nodes and Animations, but after skeletons, environment, mesh, + * shader and material resources. + */ + CategoryProcessorVector mPreNodeCategoryProcessors; + + /** + * @brief A collection of handlers, mapped to the names of the top level (i.e. below + * root) element, whom they will attempt to process. This will take place after + * the parsing of the scene Nodes and Animations. + */ + CategoryProcessorVector mPostNodeCategoryProcessors; + + /** + * @brief Provides an extension point to nodes. If provided, this function will be + * called with each JSON element and definition, of a scene node. + * @note Constraints rely on ID resolution (from .dli to scene definition), which + * takes place after the parsing of the nodes; therefore AT THIS POINT the node + * IDs seen in constraints will still be the .dli IDs - NOT to be relied on for + * indexing into mScene. + */ + NodeProcessor mNodePropertyProcessor{nullptr}; + + /** + * @brief Provides an extension point to animations. If provided, this function will be + * called with each JSON element and fully processed definition, of an animation. + */ + AnimationProcessor mAnimationPropertyProcessor; +}; + +} // namespace Loader +} // namespace Scene3D +} // namespace Dali + +#endif // DALI_SCENE3D_LOADER_DLI_INPUT_PARAMETER_H diff --git a/dali-scene3d/public-api/loader/dli-loader.h b/dali-scene3d/public-api/loader/dli-loader.h deleted file mode 100644 index c516f9a..0000000 --- a/dali-scene3d/public-api/loader/dli-loader.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef DALI_SCENE3D_LOADER_DLI_LOADER_H -#define DALI_SCENE3D_LOADER_DLI_LOADER_H -/* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// INTERNAL INCLUDES -#include "dali-scene3d/public-api/api.h" -#include "dali-scene3d/public-api/loader/animation-definition.h" -#include "dali-scene3d/public-api/loader/customization.h" -#include "dali-scene3d/public-api/loader/index.h" -#include "dali-scene3d/public-api/loader/string-callback.h" - -// EXTERNAL INCLUDES -#include "dali/public-api/common/vector-wrapper.h" - -namespace Dali -{ -namespace Scene3D -{ -namespace Loader -{ -typedef std::pair Metadata; - -// Forward declarations -struct LoadResult; -struct CameraParameters; -struct LightParameters; -struct TextParameters; - -class ResourceBundle; -struct NodeDefinition; -class SceneDefinition; - -class DALI_SCENE3D_API DliLoader -{ -public: - using ConvertFontCode = void (*)(const std::string& code, std::string& fontFamily, std::string& slant, std::string& weight, float& size); - using ConvertColorCode = Vector4 (*)(const std::string& code); - - using CategoryProcessor = std::function; - using CategoryProcessorVector = std::vector>; - - using NodeProcessor = std::function; - - using AnimationProcessor = std::function; - - struct InputParams - { - /** - * @brief The absolute path of animation binaries referenced in the .dli. - */ - std::string mAnimationsPath; - - /** - * @brief Provides a facility to determine a color from a code instead of RGB(A) values. - */ - ConvertColorCode mConvertColorCode; - - /** - * @brief A collection of handlers, mapped to the names of the top level (i.e. below - * root) element, whom they will attempt to process. This will take place before - * the parsing of scene Nodes and Animations, but after skeletons, environment, mesh, - * shader and material resources. - */ - CategoryProcessorVector mPreNodeCategoryProcessors; - - /** - * @brief A collection of handlers, mapped to the names of the top level (i.e. below - * root) element, whom they will attempt to process. This will take place after - * the parsing of the scene Nodes and Animations. - */ - CategoryProcessorVector mPostNodeCategoryProcessors; - - /** - * @brief Provides an extension point to nodes. If provided, this function will be - * called with each JSON element and definition, of a scene node. - * @note Constraints rely on ID resolution (from .dli to scene definition), which - * takes place after the parsing of the nodes; therefore AT THIS POINT the node - * IDs seen in constraints will still be the .dli IDs - NOT to be relied on for - * indexing into mScene. - */ - NodeProcessor mNodePropertyProcessor; - - /** - * @brief Provides an extension point to animations. If provided, this function will be - * called with each JSON element and fully processed definition, of an animation. - */ - AnimationProcessor mAnimationPropertyProcessor; - }; - - struct LoadParams - { - InputParams const& input; - LoadResult& output; - }; - - DliLoader(); - ~DliLoader(); - - /** - * @brief Sets the callback that messages from non-fatal errors get posted to. - * Uses DefaultErrorCallback by default. - */ - void SetErrorCallback(StringCallback onError); - - /** - * @brief Attempts to load and parse a .dli document into a DOM tree. - * @return Whether the operation was successful. - */ - bool LoadScene(const std::string& uri, LoadParams& params); - - /** - * @return The error string describing how the parse has failed, if any. - */ - std::string GetParseError() const; - -private: - struct Impl; - const std::unique_ptr mImpl; -}; - -} // namespace Loader -} // namespace Scene3D -} // namespace Dali - -#endif // DALI_SCENE3D_LOADER_DLI_LOADER_H diff --git a/dali-scene3d/public-api/loader/gltf2-loader.h b/dali-scene3d/public-api/loader/gltf2-loader.h deleted file mode 100644 index dc7becf..0000000 --- a/dali-scene3d/public-api/loader/gltf2-loader.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef DALI_SCENE3D_LOADER_GLTF2_LOADER_H -#define DALI_SCENE3D_LOADER_GLTF2_LOADER_H -/* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// INTERNAL INCLUDES -#include "dali-scene3d/public-api/api.h" - -// EXTERNAL INCLUDES -#include - -namespace Dali -{ -namespace Scene3D -{ -namespace Loader -{ -struct CameraParameters; -struct LoadResult; -class ShaderDefinitionFactory; - -/** - * @brief Initialize glTF Loader. - * @note This method should be called once before LoadGltfScene() is called. - */ -DALI_SCENE3D_API void InitializeGltfLoader(); - -/** - * @brief Loads the scene from the glTF file located at @a url, storing the results in @a params. - * @note Will throw std::runtime_error for JSON entities with types mismatching expectations, carrying - * invalid values, or I/O errors. - * @note InitializeGltfLoader() should be called once before this function is called. - */ -DALI_SCENE3D_API void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactory, LoadResult& params); - -} // namespace Loader -} // namespace Scene3D -} // namespace Dali - -#endif //DALI_SCENE3D_LOADER_GLTF2_LOADER_H diff --git a/dali-scene3d/public-api/loader/model-loader.cpp b/dali-scene3d/public-api/loader/model-loader.cpp new file mode 100644 index 0000000..5ca930f --- /dev/null +++ b/dali-scene3d/public-api/loader/model-loader.cpp @@ -0,0 +1,155 @@ +/* + * 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. + * + */ + +// FILE HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Loader +{ +namespace +{ +static constexpr std::string_view OBJ_EXTENSION = ".obj"; +static constexpr std::string_view GLTF_EXTENSION = ".gltf"; +static constexpr std::string_view DLI_EXTENSION = ".dli"; +static constexpr std::string_view METADATA_EXTENSION = "metadata"; +} // namespace + +ModelLoader::ModelLoader(const std::string& modelUrl, const std::string& resourceDirectoryUrl, Dali::Scene3D::Loader::LoadResult& loadResult) +: mModelUrl(modelUrl), + mResourceDirectoryUrl(resourceDirectoryUrl), + mLoadResult(loadResult) +{ + CreateModelLoader(); +} + +bool ModelLoader::LoadModel(Dali::Scene3D::Loader::ResourceBundle::PathProvider& pathProvider, bool loadOnlyRawResource) +{ + if(!mImpl) + { + return false; + } + + bool loadSucceeded = false; + + mLoadResult.mAnimationDefinitions.clear(); + std::filesystem::path metaDataUrl(mModelUrl); + metaDataUrl.replace_extension(METADATA_EXTENSION.data()); + + Dali::Scene3D::Loader::LoadSceneMetadata(metaDataUrl.c_str(), mLoadResult.mSceneMetadata); + loadSucceeded = mImpl->LoadModel(mModelUrl, mLoadResult); + LoadResource(pathProvider, loadOnlyRawResource); + + return loadSucceeded; +} + +void ModelLoader::SetInputParameter(InputParameter& inputParameter) +{ + mImpl->SetInputParameter(inputParameter); +} + +Dali::Scene3D::Loader::SceneDefinition& ModelLoader::GetScene() +{ + return mLoadResult.mScene; +} + +Dali::Scene3D::Loader::ResourceBundle& ModelLoader::GetResources() +{ + return mLoadResult.mResources; +} + +std::vector& ModelLoader::GetAnimations() +{ + return mLoadResult.mAnimationDefinitions; +} + +std::vector& ModelLoader::GetCameras() +{ + return mLoadResult.mCameraParameters; +} + +Dali::Scene3D::Loader::Customization::Choices& ModelLoader::GetResourceChoices() +{ + return mResourceChoices; +} + +void ModelLoader::CreateModelLoader() +{ + std::filesystem::path modelPath(mModelUrl); + if(mResourceDirectoryUrl.empty()) + { + mResourceDirectoryUrl = std::string(modelPath.parent_path()) + "/"; + } + std::string extension = modelPath.extension(); + std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + + if(extension == DLI_EXTENSION) + { + mImpl = std::make_shared(); + } + else if(extension == GLTF_EXTENSION) + { + mImpl = std::make_shared(); + } + else + { + DALI_LOG_ERROR("Not supported model format : %s\n", extension.c_str()); + } +} + +void ModelLoader::LoadResource(Dali::Scene3D::Loader::ResourceBundle::PathProvider& pathProvider, bool loadOnlyRawResource) +{ + if(GetResources().mRawResourcesLoaded && loadOnlyRawResource) + { + return; + } + + Dali::Scene3D::Loader::ResourceRefCounts resourceRefCount = std::move(mLoadResult.mResources.CreateRefCounter()); + for(auto iRoot : GetScene().GetRoots()) + { + GetScene().CountResourceRefs(iRoot, mResourceChoices, resourceRefCount); + } + + GetResources().mReferenceCounts = std::move(resourceRefCount); + GetResources().CountEnvironmentReferences(); + + if(loadOnlyRawResource) + { + GetResources().LoadRawResources(pathProvider); + } + else + { + GetResources().LoadResources(pathProvider); + } +} + +} // namespace Loader +} // namespace Scene3D +} // namespace Dali diff --git a/dali-scene3d/public-api/loader/model-loader.h b/dali-scene3d/public-api/loader/model-loader.h new file mode 100644 index 0000000..7cec995 --- /dev/null +++ b/dali-scene3d/public-api/loader/model-loader.h @@ -0,0 +1,126 @@ +#ifndef DALI_SCENE3D_LOADER_MODEL_LOADER_H +#define DALI_SCENE3D_LOADER_MODEL_LOADER_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 +#include +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Loader +{ +namespace Internal +{ +class ModelLoaderImpl; +} + +class DALI_SCENE3D_API ModelLoader +{ +public: + class InputParameter + { + }; + + /** + * @brief ModelLoader Constructor. + * @param[in] modelUrl Url of the model file to be loaded + * @param[in] resourceDirectoryUrl Url of directory that contains resources. + * @param[out] loadResult Loaded result that includes scene tree and resources. + */ + ModelLoader(const std::string& modelUrl, const std::string& resourceDirectoryUrl, Dali::Scene3D::Loader::LoadResult& loadResult); + + /** + * @brief Request to load model from model url. + * @param[in] pathProvider Path provider that defines resource paths. + * @param[in] loadOnlyRawResource If true, load Raw resource only, and do not create Dali::Handle + * If false, this loader load Raw resource and create Dali::Handle too. + * Default value is false; + * @return True if model loading is successfully finished. + */ + bool LoadModel(Dali::Scene3D::Loader::ResourceBundle::PathProvider& pathProvider, bool loadOnlyRawResource = false); + + /** + * @brief Set InputParameter. + * Thie method store only a pointer of InputParameter. + * The object of InputParameter should not be deleted until it is no longer used. + * @param[in] inputParameter Input parameters that can be used in loading time. + */ + void SetInputParameter(InputParameter& inputParameter); + + /** + * @brief Retrieves loaded scene + * @return SceneDefinition that is loaded from file + */ + Dali::Scene3D::Loader::SceneDefinition& GetScene(); + + /** + * @brief Retrieves resource bundle that includes resource information + * @return ResourceBundle for model resources + */ + Dali::Scene3D::Loader::ResourceBundle& GetResources(); + + /** + * @brief Retrieves loaded AnimationDefinition + * @return AnimationDefinition that is loaded from file + */ + std::vector& GetAnimations(); + + /** + * @brief Retrieves loaded CameraParameters + * @return CameraParameters list that is loaded from file + */ + std::vector& GetCameras(); + + /** + * @brief Retrieves ResourceChoices + * @return Choices for loaded Resources + */ + Dali::Scene3D::Loader::Customization::Choices& GetResourceChoices(); + +private: + /** + * @brief Create model loader for each file format. + */ + void CreateModelLoader(); + + /** + * @brief Load resource of the model. + */ + void LoadResource(Dali::Scene3D::Loader::ResourceBundle::PathProvider& pathProvider, bool loadOnlyRawResource); + +private: + std::string mModelUrl; + std::string mResourceDirectoryUrl; + + Dali::Scene3D::Loader::LoadResult mLoadResult; + Dali::Scene3D::Loader::Customization::Choices mResourceChoices; + + std::shared_ptr mImpl; +}; +} // namespace Loader +} // namespace Scene3D +} // namespace Dali + +#endif // DALI_SCENE3D_LOADER_MODEL_LOADER_H diff --git a/dali-scene3d/public-api/loader/resource-bundle.cpp b/dali-scene3d/public-api/loader/resource-bundle.cpp index 98c8de6..c414c1f 100644 --- a/dali-scene3d/public-api/loader/resource-bundle.cpp +++ b/dali-scene3d/public-api/loader/resource-bundle.cpp @@ -67,11 +67,11 @@ ResourceRefCounts ResourceBundle::CreateRefCounter() const return refCounts; } -void ResourceBundle::CountEnvironmentReferences(ResourceRefCounts& refCounts) const +void ResourceBundle::CountEnvironmentReferences() { - auto& environmentRefCounts = refCounts[ResourceType::Environment]; + auto& environmentRefCounts = mReferenceCounts[ResourceType::Environment]; - const auto& materialRefs = refCounts[ResourceType::Material]; + const auto& materialRefs = mReferenceCounts[ResourceType::Material]; for(uint32_t i = 0, iEnd = materialRefs.Size(); i != iEnd; ++i) { if(materialRefs[i] > 0) @@ -81,7 +81,7 @@ void ResourceBundle::CountEnvironmentReferences(ResourceRefCounts& refCounts) co } } -void ResourceBundle::LoadResources(const ResourceRefCounts& refCounts, PathProvider pathProvider, Options::Type options) +void ResourceBundle::LoadResources(PathProvider pathProvider, Options::Type options) { mRawResourcesLoading = true; mResourcesGenerating = true; @@ -89,7 +89,7 @@ void ResourceBundle::LoadResources(const ResourceRefCounts& refCounts, PathProvi const auto kForceLoad = MaskMatch(options, Options::ForceReload); const auto kKeepUnused = MaskMatch(options, Options::KeepUnused); - const auto& refCountEnvMaps = refCounts[ResourceType::Environment]; + const auto& refCountEnvMaps = mReferenceCounts[ResourceType::Environment]; auto environmentsPath = pathProvider(ResourceType::Environment); for(uint32_t i = 0, iEnd = refCountEnvMaps.Size(); i != iEnd; ++i) { @@ -107,7 +107,7 @@ void ResourceBundle::LoadResources(const ResourceRefCounts& refCounts, PathProvi } } - const auto& refCountShaders = refCounts[ResourceType::Shader]; + const auto& refCountShaders = mReferenceCounts[ResourceType::Shader]; auto shadersPath = pathProvider(ResourceType::Shader); for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i) { @@ -124,7 +124,7 @@ void ResourceBundle::LoadResources(const ResourceRefCounts& refCounts, PathProvi } } - const auto& refCountMeshes = refCounts[ResourceType::Mesh]; + const auto& refCountMeshes = mReferenceCounts[ResourceType::Mesh]; auto modelsPath = pathProvider(ResourceType::Mesh); for(uint32_t i = 0, iEnd = refCountMeshes.Size(); i != iEnd; ++i) { @@ -141,7 +141,7 @@ void ResourceBundle::LoadResources(const ResourceRefCounts& refCounts, PathProvi } } - const auto& refCountMaterials = refCounts[ResourceType::Material]; + const auto& refCountMaterials = mReferenceCounts[ResourceType::Material]; auto imagesPath = pathProvider(ResourceType::Material); for(uint32_t i = 0, iEnd = refCountMaterials.Size(); i != iEnd; ++i) { @@ -165,7 +165,7 @@ void ResourceBundle::LoadResources(const ResourceRefCounts& refCounts, PathProvi mResourcesGenerated = true; } -void ResourceBundle::LoadRawResources(const ResourceRefCounts& refCounts, PathProvider pathProvider, Options::Type options) +void ResourceBundle::LoadRawResources(PathProvider pathProvider, Options::Type options) { const auto kForceLoad = MaskMatch(options, Options::ForceReload); @@ -173,7 +173,7 @@ void ResourceBundle::LoadRawResources(const ResourceRefCounts& refCounts, PathPr { mRawResourcesLoading = true; - const auto& refCountEnvMaps = refCounts[ResourceType::Environment]; + const auto& refCountEnvMaps = mReferenceCounts[ResourceType::Environment]; auto environmentsPath = pathProvider(ResourceType::Environment); for(uint32_t i = 0, iEnd = refCountEnvMaps.Size(); i != iEnd; ++i) { @@ -185,7 +185,7 @@ void ResourceBundle::LoadRawResources(const ResourceRefCounts& refCounts, PathPr } } - const auto& refCountShaders = refCounts[ResourceType::Shader]; + const auto& refCountShaders = mReferenceCounts[ResourceType::Shader]; auto shadersPath = pathProvider(ResourceType::Shader); for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i) { @@ -197,7 +197,7 @@ void ResourceBundle::LoadRawResources(const ResourceRefCounts& refCounts, PathPr } } - const auto& refCountMeshes = refCounts[ResourceType::Mesh]; + const auto& refCountMeshes = mReferenceCounts[ResourceType::Mesh]; auto modelsPath = pathProvider(ResourceType::Mesh); for(uint32_t i = 0, iEnd = refCountMeshes.Size(); i != iEnd; ++i) { @@ -209,7 +209,7 @@ void ResourceBundle::LoadRawResources(const ResourceRefCounts& refCounts, PathPr } } - const auto& refCountMaterials = refCounts[ResourceType::Material]; + const auto& refCountMaterials = mReferenceCounts[ResourceType::Material]; auto imagesPath = pathProvider(ResourceType::Material); for(uint32_t i = 0, iEnd = refCountMaterials.Size(); i != iEnd; ++i) { @@ -226,7 +226,7 @@ void ResourceBundle::LoadRawResources(const ResourceRefCounts& refCounts, PathPr } } -void ResourceBundle::GenerateResources(const ResourceRefCounts& refCounts, Options::Type options) +void ResourceBundle::GenerateResources(Options::Type options) { const auto kForceLoad = MaskMatch(options, Options::ForceReload); @@ -236,7 +236,7 @@ void ResourceBundle::GenerateResources(const ResourceRefCounts& refCounts, Optio { mResourcesGenerating = true; - const auto& refCountEnvMaps = refCounts[ResourceType::Environment]; + const auto& refCountEnvMaps = mReferenceCounts[ResourceType::Environment]; for(uint32_t i = 0, iEnd = refCountEnvMaps.Size(); i != iEnd; ++i) { auto refCount = refCountEnvMaps[i]; @@ -255,7 +255,7 @@ void ResourceBundle::GenerateResources(const ResourceRefCounts& refCounts, Optio } } - const auto& refCountShaders = refCounts[ResourceType::Shader]; + const auto& refCountShaders = mReferenceCounts[ResourceType::Shader]; for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i) { auto refCount = refCountShaders[i]; @@ -273,7 +273,7 @@ void ResourceBundle::GenerateResources(const ResourceRefCounts& refCounts, Optio } } - const auto& refCountMeshes = refCounts[ResourceType::Mesh]; + const auto& refCountMeshes = mReferenceCounts[ResourceType::Mesh]; for(uint32_t i = 0, iEnd = refCountMeshes.Size(); i != iEnd; ++i) { auto refCount = refCountMeshes[i]; @@ -291,7 +291,7 @@ void ResourceBundle::GenerateResources(const ResourceRefCounts& refCounts, Optio } } - const auto& refCountMaterials = refCounts[ResourceType::Material]; + const auto& refCountMaterials = mReferenceCounts[ResourceType::Material]; for(uint32_t i = 0, iEnd = refCountMaterials.Size(); i != iEnd; ++i) { auto refCount = refCountMaterials[i]; @@ -316,7 +316,7 @@ void ResourceBundle::GenerateResources(const ResourceRefCounts& refCounts, Optio { mResourcesGenerating = true; - const auto& refCountShaders = refCounts[ResourceType::Shader]; + const auto& refCountShaders = mReferenceCounts[ResourceType::Shader]; for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i) { auto refCount = refCountShaders[i]; diff --git a/dali-scene3d/public-api/loader/resource-bundle.h b/dali-scene3d/public-api/loader/resource-bundle.h index 95c8609..ee56e70 100644 --- a/dali-scene3d/public-api/loader/resource-bundle.h +++ b/dali-scene3d/public-api/loader/resource-bundle.h @@ -103,7 +103,7 @@ public: * count of materials therein, it will calculate the reference count of * environment maps. */ - void CountEnvironmentReferences(ResourceRefCounts& refCounts) const; + void CountEnvironmentReferences(); /** * @brief Performs the loading of all resources based on their respective @@ -111,14 +111,12 @@ public: * loaded unless we already have a handle to them (OR the ForceReload option was specified). * Any handles we have to resources that come in with a zero ref count will be reset, * UNLESS the KeepUnused option was specified. - * @param[in] refCounts Reference Count that denote how many the resource is used. * @param[in] pathProvider path provider for resource data. * @param[in] options Option to load resource * @note This method creates DALi objects like Dali::Texture, Dali::Geometry, etc. */ - void LoadResources(const ResourceRefCounts& refCounts, - PathProvider pathProvider, - Options::Type options = Options::None); + void LoadResources(PathProvider pathProvider, + Options::Type options = Options::None); /** * @brief Loads of all resources based on their respective @@ -127,29 +125,26 @@ public: * Any handles we have to resources that come in with a zero ref count will be reset, * UNLESS the KeepUnused option was specified. * @note This method don't create any of DALi objects. - * @param[in] refCounts Reference Count that denote how many the resource is used. * @param[in] pathProvider path provider for resource data. * @param[in] options Option to load resource * @note This method only loads raw data from resource file, and * doesn't create any of DALi objects. GenerateResources() method is required to be called * after this method to create DALi objects. */ - void LoadRawResources(const ResourceRefCounts& refCounts, - PathProvider pathProvider, - Options::Type options = Options::None); + void LoadRawResources(PathProvider pathProvider, + Options::Type options = Options::None); /** * @brief Generates DALi objects from already loaded Raw Resources. - * @param[in] refCounts Reference Count that denote how many the resource is used. * @param[in] options Option to load resource * @note This method generates DALi objects from raw data that is already * loaded by LoadRawResources method. Therefore, LoadRawResources should be called first * before this method is called. */ - void GenerateResources(const ResourceRefCounts& refCounts, - Options::Type options = Options::None); + void GenerateResources(Options::Type options = Options::None); public: // DATA + ResourceRefCounts mReferenceCounts; EnvironmentDefinition::Vector mEnvironmentMaps; ShaderDefinition::Vector mShaders; MeshDefinition::Vector mMeshes; -- 2.7.4