From: Seungho BAEK Date: Tue, 29 Nov 2022 06:35:48 +0000 (+0000) Subject: Merge "Enable multiple primitives in a mesh(glTF)" into devel/master X-Git-Tag: dali_2.2.4~5 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=92440595066877ace09a343f87ee875a927732b4;hp=78bfa8d0cf516736b2f410c28e96136b80bd20fd Merge "Enable multiple primitives in a mesh(glTF)" into devel/master --- diff --git a/automated-tests/resources/simpleMultiplePrimitiveTest.gltf b/automated-tests/resources/simpleMultiplePrimitiveTest.gltf new file mode 100644 index 0000000..9345fbe --- /dev/null +++ b/automated-tests/resources/simpleMultiplePrimitiveTest.gltf @@ -0,0 +1,109 @@ +{ + "scene" : 0, + "scenes" : [ + { + "nodes" : [ 0 ] + } + ], + + "nodes" : [ + { + "name" : "rootNode", + "mesh" : 0, + "rotation" : [ 0.0, 0.0, 0.0, 1.0 ] + } + ], + + "meshes" : [ + { + "primitives" : [ + { + "attributes" : { + "POSITION" : 1 + }, + "indices" : 0 + }, + { + "attributes" : { + "POSITION" : 1 + }, + "indices" : 0 + } + ] + } + ], + + "buffers" : [ + { + "uri" : "simpleTriangle.bin", + "byteLength" : 44 + }, + { + "uri" : "animation.bin", + "byteLength" : 100 + } + ], + + "bufferViews" : [ + { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 6, + "target" : 34963 + }, + { + "buffer" : 0, + "byteOffset" : 8, + "byteLength" : 36, + "target" : 34962 + }, + { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 100 + } + ], + + "accessors" : [ + { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 3, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 0 ] + }, + { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 3, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, + { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 5, + "type" : "SCALAR", + "max" : [ 1.0 ], + "min" : [ 0.0 ] + }, + { + "bufferView" : 2, + "byteOffset" : 20, + "componentType" : 5126, + "count" : 5, + "type" : "VEC4", + "max" : [ 0.0, 0.0, 1.0, 1.0 ], + "min" : [ 0.0, 0.0, 0.0, -0.707 ] + } + ], + + "asset" : { + "version" : "2.0" + } +} diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp index a9ba508..b48ec38 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp @@ -168,7 +168,7 @@ int UtcDaliGltfLoaderSuccess1(void) DALI_TEST_EQUAL(2u, materials.size()); const MaterialDefinition materialGroundTruth[]{ {MaterialDefinition::ALBEDO | MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION | - MaterialDefinition::NORMAL | MaterialDefinition::TRANSPARENCY | + MaterialDefinition::NORMAL | (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT), 0, Color::WHITE, @@ -181,6 +181,7 @@ int UtcDaliGltfLoaderSuccess1(void) true, false, true, + false, { {MaterialDefinition::ALBEDO, {"AnimatedCube_BaseColor.png", @@ -209,6 +210,7 @@ int UtcDaliGltfLoaderSuccess1(void) true, true, true, + false, { {MaterialDefinition::ALBEDO, {"AnimatedCube_BaseColor.png", @@ -386,9 +388,9 @@ int UtcDaliGltfLoaderSuccessShort(void) void Start(NodeDefinition& n) override { - if(n.mRenderable) + for(auto& renderable : n.mRenderables) { - n.mRenderable->RegisterResources(receiver); + renderable->RegisterResources(receiver); } } diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp index 25d2624..b52aa62 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp @@ -47,9 +47,10 @@ const bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false; * Donated by Norbert Nopper for glTF testing. * Take from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AnimatedCube */ -const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf"; -const char* TEST_GLTF_ANIMATION_TEST_FILE_NAME = TEST_RESOURCE_DIR "/animationTest.gltf"; -const char* TEST_DLI_FILE_NAME = TEST_RESOURCE_DIR "/arc.dli"; +const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf"; +const char* TEST_GLTF_ANIMATION_TEST_FILE_NAME = TEST_RESOURCE_DIR "/animationTest.gltf"; +const char* TEST_GLTF_MULTIPLE_PRIMITIVE_FILE_NAME = TEST_RESOURCE_DIR "/simpleMultiplePrimitiveTest.gltf"; +const char* TEST_DLI_FILE_NAME = TEST_RESOURCE_DIR "/arc.dli"; /** * For the diffuse and specular cube map texture. * These textures are based off version of Wave engine sample @@ -828,6 +829,26 @@ int UtcDaliModelAnimation02(void) END_TEST; } +int UtcDaliModelMultiplePrimitives(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_MULTIPLE_PRIMITIVE_FILE_NAME); + model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50)); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + Actor actor = model.FindChildByName("rootNode"); + + DALI_TEST_EQUALS(0, actor.GetChildCount(), TEST_LOCATION); + DALI_TEST_EQUALS(2, actor.GetRendererCount(), TEST_LOCATION); + + END_TEST; +} + // For ResourceReady namespace { diff --git a/automated-tests/src/dali-scene3d/utc-Dali-NodeDefinition.cpp b/automated-tests/src/dali-scene3d/utc-Dali-NodeDefinition.cpp index 835fdbf..415e2e1 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-NodeDefinition.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-NodeDefinition.cpp @@ -18,11 +18,11 @@ // Enable debug log for test coverage #define DEBUG_ENABLED 1 -#include "dali-scene3d/public-api/loader/node-definition.h" -#include "dali-scene3d/public-api/loader/view-projection.h" -#include #include +#include #include +#include "dali-scene3d/public-api/loader/node-definition.h" +#include "dali-scene3d/public-api/loader/view-projection.h" using namespace Dali; using namespace Dali::Scene3D::Loader; @@ -35,20 +35,19 @@ struct Context ResourceBundle resources; ViewProjection viewProjection; - Transforms transforms { MatrixStack{}, viewProjection }; + Transforms transforms{MatrixStack{}, viewProjection}; - NodeDefinition::CreateParams createParams { + NodeDefinition::CreateParams createParams{ resources, - transforms - }; + transforms}; }; -} +} // namespace int UtcDaliConstraintDefinitionsCompare(void) { - ConstraintDefinition cd1{ "orientation", 0 }; - ConstraintDefinition cd2{ "position", 1 }; + ConstraintDefinition cd1{"orientation", 0}; + ConstraintDefinition cd2{"position", 1}; DALI_TEST_CHECK(cd1 < cd2); DALI_TEST_CHECK(!(cd2 < cd1)); @@ -58,9 +57,9 @@ int UtcDaliConstraintDefinitionsCompare(void) DALI_TEST_CHECK(cd1 == cd1); DALI_TEST_CHECK(cd2 == cd2); - ConstraintDefinition cd3{ "position", 0 }; - ConstraintDefinition cd4{ "scale", 1 }; - ConstraintDefinition cd5{ "position", 1 }; + ConstraintDefinition cd3{"position", 0}; + ConstraintDefinition cd4{"scale", 1}; + ConstraintDefinition cd5{"position", 1}; DALI_TEST_CHECK(cd2 != cd3); DALI_TEST_CHECK(cd2 != cd4); DALI_TEST_CHECK(cd2 == cd5); @@ -71,13 +70,10 @@ int UtcDaliConstraintDefinitionsCompare(void) int UtcDaliBlendshapeShaderConfigurationRequestsCompare(void) { - TestApplication app; - BlendshapeShaderConfigurationRequest bsscr1{ "", 0, Shader(nullptr) }; + TestApplication app; + BlendshapeShaderConfigurationRequest bsscr1{"", 0, Shader(nullptr)}; - BlendshapeShaderConfigurationRequest bsscr2{ "", 0, Shader::New( - "void main(){ gl_Position = vec4(0.); }", - "void main(){ gl_FragColor = vec4(1.); }" - ) }; + BlendshapeShaderConfigurationRequest bsscr2{"", 0, Shader::New("void main(){ gl_Position = vec4(0.); }", "void main(){ gl_FragColor = vec4(1.); }")}; DALI_TEST_CHECK(bsscr1 < bsscr2); DALI_TEST_CHECK(!(bsscr2 < bsscr1)); @@ -89,8 +85,8 @@ int UtcDaliBlendshapeShaderConfigurationRequestsCompare(void) int UtcDaliNodeDefinitionExtrasCompare(void) { - NodeDefinition::Extra e1{ "alpha", Vector3::XAXIS * 2.f }; - NodeDefinition::Extra e2{ "beta", 8 }; + NodeDefinition::Extra e1{"alpha", Vector3::XAXIS * 2.f}; + NodeDefinition::Extra e2{"beta", 8}; DALI_TEST_CHECK(e1 < e2); DALI_TEST_CHECK(!(e1 < e1)); @@ -103,21 +99,21 @@ int UtcDaliNodeDefinitionExtrasCompare(void) int UtcDaliNodeDefinitionProperties(void) { TestApplication testApp; - NodeDefinition nodeDef{ + NodeDefinition nodeDef{ "testRootNode", - Vector3{ -100.f, 100.f, -500.f }, - Quaternion{ Radian(Degree(45.f)), Vector3::ZAXIS }, - Vector3{ 2.f, 4.f, 8.f }, - Vector3{ 100.f, 50.f, 25.f }, + Vector3{-100.f, 100.f, -500.f}, + Quaternion{Radian(Degree(45.f)), Vector3::ZAXIS}, + Vector3{2.f, 4.f, 8.f}, + Vector3{100.f, 50.f, 25.f}, false, }; Quaternion frobnicateFactor(0.f, 1.f, 2.f, 3.f); frobnicateFactor.Normalize(); // because it will be (by DALi) once it's set as a property. - nodeDef.mExtras.push_back(NodeDefinition::Extra{ "frobnicateFactor", frobnicateFactor }); + nodeDef.mExtras.push_back(NodeDefinition::Extra{"frobnicateFactor", frobnicateFactor}); Context ctx; - auto actor = nodeDef.CreateActor(ctx.createParams); + auto actor = nodeDef.CreateActor(ctx.createParams); DALI_TEST_EQUAL(nodeDef.mName, actor.GetProperty(Actor::Property::NAME).Get()); DALI_TEST_EQUAL(nodeDef.mPosition, actor.GetProperty(Actor::Property::POSITION).Get()); DALI_TEST_EQUAL(nodeDef.mOrientation, actor.GetProperty(Actor::Property::ORIENTATION).Get()); @@ -142,30 +138,30 @@ int UtcDaliNodeDefinitionRenderableRegisterResources(void) { NodeDefinition nodeDef; - auto renderable = new NodeDefinition::Renderable(); - renderable->mShaderIdx = 0; - nodeDef.mRenderable.reset(renderable); + std::unique_ptr renderable = std::unique_ptr(new NodeDefinition::Renderable()); + nodeDef.mRenderables.push_back(std::move(renderable)); + nodeDef.mRenderables[0]->mShaderIdx = 0; struct : IResourceReceiver { std::vector shaders; - uint32_t otherResources = 0; + uint32_t otherResources = 0; void Register(ResourceType::Value type, Index id) override { switch(type) { - case ResourceType::Shader: - shaders.push_back(id); - break; + case ResourceType::Shader: + shaders.push_back(id); + break; - default: - ++otherResources; + default: + ++otherResources; } } } resourceReceiver; - nodeDef.mRenderable->RegisterResources(resourceReceiver); + nodeDef.mRenderables[0]->RegisterResources(resourceReceiver); DALI_TEST_EQUAL(1u, resourceReceiver.shaders.size()); DALI_TEST_EQUAL(0, resourceReceiver.shaders[0]); DALI_TEST_EQUAL(0, resourceReceiver.otherResources); @@ -177,32 +173,32 @@ int UtcDaliNodeDefinitionRenderableReflectResources(void) { NodeDefinition nodeDef; - auto renderable = new NodeDefinition::Renderable(); - renderable->mShaderIdx = 0; - nodeDef.mRenderable.reset(renderable); + std::unique_ptr renderable = std::unique_ptr(new NodeDefinition::Renderable()); + nodeDef.mRenderables.push_back(std::move(renderable)); + nodeDef.mRenderables[0]->mShaderIdx = 0; struct : IResourceReflector { std::vector shaders; - uint32_t otherResources = 0; + uint32_t otherResources = 0; void Reflect(ResourceType::Value type, Index& id) override { switch(type) { - case ResourceType::Shader: - shaders.push_back(&id); - break; + case ResourceType::Shader: + shaders.push_back(&id); + break; - default: - ++otherResources; + default: + ++otherResources; } } } resourceReflector; - nodeDef.mRenderable->ReflectResources(resourceReflector); + nodeDef.mRenderables[0]->ReflectResources(resourceReflector); DALI_TEST_EQUAL(1u, resourceReflector.shaders.size()); - DALI_TEST_EQUAL(&renderable->mShaderIdx, resourceReflector.shaders[0]); + DALI_TEST_EQUAL(&nodeDef.mRenderables[0]->mShaderIdx, resourceReflector.shaders[0]); DALI_TEST_EQUAL(0, resourceReflector.otherResources); END_TEST; @@ -211,17 +207,17 @@ int UtcDaliNodeDefinitionRenderableReflectResources(void) int UtcDaliNodeDefinitionRenderable(void) { TestApplication testApp; - NodeDefinition nodeDef; + NodeDefinition nodeDef; - auto renderable = new NodeDefinition::Renderable(); - renderable->mShaderIdx = 0; - nodeDef.mRenderable.reset(renderable); + std::unique_ptr renderable = std::unique_ptr(new NodeDefinition::Renderable()); + nodeDef.mRenderables.push_back(std::move(renderable)); + nodeDef.mRenderables[0]->mShaderIdx = 0; - Context ctx; - const auto VSH = "void main() { gl_Position = vec4(0.); }"; - const auto FSH = "void main() { gl_FragColor = vec4(1.); }"; - auto shader = Shader::New(VSH, FSH); - ctx.resources.mShaders.push_back({ ShaderDefinition{}, shader }); + Context ctx; + const auto VSH = "void main() { gl_Position = vec4(0.); }"; + const auto FSH = "void main() { gl_FragColor = vec4(1.); }"; + auto shader = Shader::New(VSH, FSH); + ctx.resources.mShaders.push_back({ShaderDefinition{}, shader}); auto actor = nodeDef.CreateActor(ctx.createParams); DALI_TEST_EQUAL(1, actor.GetRendererCount()); diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp index b8e6357..10aadbf 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp @@ -91,9 +91,9 @@ int UtcDaliShaderDefinitionFactoryProduceShaderInvalid(void) Context ctx; NodeDefinition nodeDef; - nodeDef.mRenderable.reset(new NodeDefinition::Renderable()); + std::unique_ptr renderable = std::unique_ptr(new NodeDefinition::Renderable()); + nodeDef.mRenderables.push_back(std::move(renderable)); - DALI_TEST_EQUAL(INVALID_INDEX, ctx.factory.ProduceShader(nodeDef)); DALI_TEST_CHECK(ctx.resources.mShaders.empty()); END_TEST; @@ -250,12 +250,14 @@ int UtcDaliShaderDefinitionFactoryProduceShader(void) for(auto& ps : permSets) { - auto modelNode = new ModelNode(); - modelNode->mMeshIdx = 0; - modelNode->mMaterialIdx = 0; + auto modelRenderable = new ModelRenderable(); + modelRenderable->mMeshIdx = 0; + modelRenderable->mMaterialIdx = 0; NodeDefinition nodeDef; - nodeDef.mRenderable.reset(modelNode); + std::unique_ptr renderable; + renderable.reset(modelRenderable); + nodeDef.mRenderables.push_back(std::move(renderable)); auto& meshDef = NewMeshDefinition(ctx.resources); auto& materialDef = NewMaterialDefinition(ctx.resources); @@ -270,35 +272,38 @@ int UtcDaliShaderDefinitionFactoryProduceShader(void) rendererState = (rendererState | p->rendererStateSet) & ~p->rendererStateClear; } - auto shaderIdx = ctx.factory.ProduceShader(nodeDef); - DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx); + for(auto& renderable : nodeDef.mRenderables) + { + auto shaderIdx = ctx.factory.ProduceShader(*renderable); + DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx); - auto& shaderDef = ctx.resources.mShaders[shaderIdx].first; - DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState); + auto& shaderDef = ctx.resources.mShaders[shaderIdx].first; + DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState); - uint32_t definesUnmatched = shaderDef.mDefines.size(); - for(auto& define : shaderDef.mDefines) - { - auto iFind = defines.find(define); - if(iFind != defines.end()) - { - defines.erase(iFind); - --definesUnmatched; - } - else + uint32_t definesUnmatched = shaderDef.mDefines.size(); + for(auto& define : shaderDef.mDefines) { - break; + auto iFind = defines.find(define); + if(iFind != defines.end()) + { + defines.erase(iFind); + --definesUnmatched; + } + else + { + break; + } } - } - DALI_TEST_CHECK(defines.empty()); - DALI_TEST_EQUAL(0, definesUnmatched); + DALI_TEST_CHECK(defines.empty()); + DALI_TEST_EQUAL(0, definesUnmatched); - auto uMaxLOD = shaderDef.mUniforms["uMaxLOD"]; - DALI_TEST_EQUAL(uMaxLOD.GetType(), Property::FLOAT); + auto uMaxLOD = shaderDef.mUniforms["uMaxLOD"]; + DALI_TEST_EQUAL(uMaxLOD.GetType(), Property::FLOAT); - auto uCubeMatrix = shaderDef.mUniforms["uCubeMatrix"]; - DALI_TEST_EQUAL(uCubeMatrix.GetType(), Property::MATRIX); + auto uCubeMatrix = shaderDef.mUniforms["uCubeMatrix"]; + DALI_TEST_EQUAL(uCubeMatrix.GetType(), Property::MATRIX); + } ClearMeshesAndMaterials(ctx.resources); } diff --git a/dali-scene3d/public-api/loader/dli-loader.cpp b/dali-scene3d/public-api/loader/dli-loader.cpp index 133e62c..70c59d2 100644 --- a/dali-scene3d/public-api/loader/dli-loader.cpp +++ b/dali-scene3d/public-api/loader/dli-loader.cpp @@ -145,7 +145,7 @@ RendererState::Type ReadRendererState(const TreeNode& tnRendererState) } ///@brief Reads arc properties. -void ReadArcField(const TreeNode* eArc, ArcNode& arc) +void ReadArcField(const TreeNode* eArc, ArcRenderable& arc) { ReadBool(eArc->GetChild("antiAliasing"), arc.mAntiAliasing); ReadInt(eArc->GetChild("arcCaps"), arc.mArcCaps); @@ -301,7 +301,7 @@ void ParseProperties(const Toolkit::TreeNode& node, Property::Array& array) } } -} //namespace +} // namespace struct DliLoader::Impl { @@ -485,7 +485,8 @@ void DliLoader::Impl::ParseScene(LoadParams& params) void DliLoader::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) { @@ -568,7 +569,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(); @@ -587,7 +589,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) { @@ -934,7 +937,7 @@ void DliLoader::Impl::ParseMaterials(const TreeNode* materials, ConvertColorCode } } - //TODO : need to consider AGIF + // TODO : need to consider AGIF std::vector texturePaths; std::string texturePath; if(ReadString(node.GetChild("albedoMap"), texturePath)) @@ -1077,9 +1080,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; } @@ -1159,7 +1161,7 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde else // something renderable maybe { std::unique_ptr renderable; - ModelNode* modelNode = nullptr; // no ownership, aliasing renderable for the right type. + ModelRenderable* modelRenderable = nullptr; // no ownership, aliasing renderable for the right type. const TreeNode* eRenderable = nullptr; if((eRenderable = node->GetChild("model"))) @@ -1171,10 +1173,10 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde ExceptionFlinger(ASSERT_LOCATION) << "node " << nodeDef.mName << ": Missing mesh definition."; } - modelNode = new ModelNode(); - renderable.reset(modelNode); + modelRenderable = new ModelRenderable(); + renderable.reset(modelRenderable); - resourceIds.push_back({ResourceType::Mesh, eMesh, modelNode->mMeshIdx}); + resourceIds.push_back({ResourceType::Mesh, eMesh, modelRenderable->mMeshIdx}); } else if((eRenderable = node->GetChild("arc"))) { @@ -1185,13 +1187,13 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde ExceptionFlinger(ASSERT_LOCATION) << "node " << nodeDef.mName << ": Missing mesh definition."; } - auto arcNode = new ArcNode; - renderable.reset(arcNode); - modelNode = arcNode; + auto arcRenderable = new ArcRenderable; + renderable.reset(arcRenderable); + modelRenderable = arcRenderable; - resourceIds.push_back({ResourceType::Mesh, eMesh, arcNode->mMeshIdx}); + resourceIds.push_back({ResourceType::Mesh, eMesh, arcRenderable->mMeshIdx}); - ReadArcField(eRenderable, *arcNode); + ReadArcField(eRenderable, *arcRenderable); } if(renderable && eRenderable != nullptr) // process common properties of all renderables + register payload @@ -1205,22 +1207,22 @@ void DliLoader::Impl::ParseNodesInternal(const TreeNode* const nodes, Index inde } // color - if(modelNode) + if(modelRenderable) { - modelNode->mMaterialIdx = 0; // must offer default of 0 - auto eMaterial = eRenderable->GetChild("material"); + modelRenderable->mMaterialIdx = 0; // must offer default of 0 + auto eMaterial = eRenderable->GetChild("material"); if(eMaterial) { - resourceIds.push_back({ResourceType::Material, eMaterial, modelNode->mMaterialIdx}); + resourceIds.push_back({ResourceType::Material, eMaterial, modelRenderable->mMaterialIdx}); } - if(!ReadColorCodeOrColor(eRenderable, modelNode->mColor, params.input.mConvertColorCode)) + if(!ReadColorCodeOrColor(eRenderable, modelRenderable->mColor, params.input.mConvertColorCode)) { - ReadColorCodeOrColor(node, modelNode->mColor, params.input.mConvertColorCode); + ReadColorCodeOrColor(node, modelRenderable->mColor, params.input.mConvertColorCode); } } - nodeDef.mRenderable = std::move(renderable); + nodeDef.mRenderables.push_back(std::move(renderable)); } } @@ -1426,9 +1428,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) { @@ -1556,10 +1557,10 @@ void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams& animProp.mKeyFrames = KeyFrames::New(); - //In binary animation file only is saved the position, rotation, scale and blend shape weight keys. - //so, if it is vector3 we assume is position or scale keys, if it is vector4 we assume is rotation, - // otherwise are blend shape weight keys. - // TODO support for binary header with size information + // In binary animation file only is saved the position, rotation, scale and blend shape weight keys. + // so, if it is vector3 we assume is position or scale keys, if it is vector4 we assume is rotation, + // otherwise are blend shape weight keys. + // TODO support for binary header with size information Property::Type propType = Property::FLOAT; // assume blend shape weights if(animProp.mPropertyName == "orientation") { @@ -1570,8 +1571,8 @@ void DliLoader::Impl::ParseAnimations(const TreeNode* tnAnimations, LoadParams& propType = Property::VECTOR3; } - //alphafunction is reserved for future implementation - // NOTE: right now we're just using AlphaFunction::LINEAR. + // alphafunction is reserved for future implementation + // NOTE: right now we're just using AlphaFunction::LINEAR. unsigned char dummyAlphaFunction; float progress; @@ -1694,9 +1695,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())); diff --git a/dali-scene3d/public-api/loader/gltf2-loader.cpp b/dali-scene3d/public-api/loader/gltf2-loader.cpp index 60f6970..36c1639 100644 --- a/dali-scene3d/public-api/loader/gltf2-loader.cpp +++ b/dali-scene3d/public-api/loader/gltf2-loader.cpp @@ -14,15 +14,16 @@ * limitations under the License. * */ -#include "dali-scene3d/public-api/loader/gltf2-loader.h" #include -#include "dali-scene3d/internal/loader/gltf2-asset.h" -#include "dali-scene3d/public-api/loader/load-result.h" -#include "dali-scene3d/public-api/loader/resource-bundle.h" -#include "dali-scene3d/public-api/loader/scene-definition.h" -#include "dali-scene3d/public-api/loader/shader-definition-factory.h" -#include "dali-scene3d/public-api/loader/utils.h" -#include "dali/public-api/math/quaternion.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #define ENUM_STRING_MAPPING(t, x) \ { \ @@ -176,7 +177,8 @@ const auto MATERIAL_READER = std::move(js::Reader() .Register(*js::MakeProperty("emissiveTexture", js::ObjectReader::Read, >::Material::mEmissiveTexture)) .Register(*js::MakeProperty("emissiveFactor", gt::ReadDaliVector, >::Material::mEmissiveFactor)) .Register(*js::MakeProperty("alphaMode", gt::ReadStringEnum, >::Material::mAlphaMode)) - .Register(*js::MakeProperty("alphaCutoff", js::Read::Number, >::Material::mAlphaCutoff))); + .Register(*js::MakeProperty("alphaCutoff", js::Read::Number, >::Material::mAlphaCutoff)) + .Register(*js::MakeProperty("doubleSided", js::Read::Boolean, >::Material::mDoubleSided))); std::map> ReadMeshPrimitiveAttributes(const json_value_s& j) { @@ -425,24 +427,24 @@ TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm) return TextureDefinition{std::string(mm.mTexture->mSource->mUri), ConvertSampler(mm.mTexture->mSampler)}; } -void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials)& outMaterials) +void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMaterials)& outMaterials) { MaterialDefinition matDef; - auto& pbr = m.mPbrMetallicRoughness; - if(m.mAlphaMode != gt::AlphaMode::OPAQUE || pbr.mBaseColorFactor.a < 1.f) + auto& pbr = material.mPbrMetallicRoughness; + if(pbr.mBaseColorFactor.a < 1.f) { matDef.mFlags |= MaterialDefinition::TRANSPARENCY; } - if(m.mAlphaMode == gt::AlphaMode::MASK) + if(material.mAlphaMode == gt::AlphaMode::MASK) { - matDef.SetAlphaCutoff(std::min(1.f, std::max(0.f, m.mAlphaCutoff))); + matDef.SetAlphaCutoff(std::min(1.f, std::max(0.f, material.mAlphaCutoff))); } matDef.mBaseColorFactor = pbr.mBaseColorFactor; - matDef.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!m.mNormalTexture + !!m.mOcclusionTexture + !!m.mEmissiveTexture); + matDef.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!material.mNormalTexture + !!material.mOcclusionTexture + !!material.mEmissiveTexture); if(pbr.mBaseColorTexture) { const auto semantic = MaterialDefinition::ALBEDO; @@ -471,11 +473,11 @@ void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials) matDef.mNeedMetallicRoughnessTexture = false; } - matDef.mNormalScale = m.mNormalTexture.mScale; - if(m.mNormalTexture) + matDef.mNormalScale = material.mNormalTexture.mScale; + if(material.mNormalTexture) { const auto semantic = MaterialDefinition::NORMAL; - matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mNormalTexture)}); + matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mNormalTexture)}); // TODO: and there had better be one matDef.mFlags |= semantic; } @@ -484,31 +486,32 @@ void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials) matDef.mNeedNormalTexture = false; } - // TODO: handle doubleSided - if(m.mOcclusionTexture) + if(material.mOcclusionTexture) { const auto semantic = MaterialDefinition::OCCLUSION; - matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mOcclusionTexture)}); + matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mOcclusionTexture)}); // TODO: and there had better be one matDef.mFlags |= semantic; - matDef.mOcclusionStrength = m.mOcclusionTexture.mStrength; + matDef.mOcclusionStrength = material.mOcclusionTexture.mStrength; } - if(m.mEmissiveTexture) + if(material.mEmissiveTexture) { const auto semantic = MaterialDefinition::EMISSIVE; - matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mEmissiveTexture)}); + matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mEmissiveTexture)}); // TODO: and there had better be one matDef.mFlags |= semantic; - matDef.mEmissiveFactor = m.mEmissiveFactor; + matDef.mEmissiveFactor = material.mEmissiveFactor; } + matDef.mDoubleSided = material.mDoubleSided; + outMaterials.emplace_back(std::move(matDef), TextureSet()); } -void ConvertMaterials(const gt::Document& doc, ConversionContext& cctx) +void ConvertMaterials(const gt::Document& doc, ConversionContext& context) { - auto& outMaterials = cctx.mOutput.mResources.mMaterials; + auto& outMaterials = context.mOutput.mResources.mMaterials; outMaterials.reserve(doc.mMaterials.size()); for(auto& m : doc.mMaterials) @@ -570,33 +573,33 @@ MeshDefinition::Accessor ConvertMeshPrimitiveAccessor(const gt::Accessor& acc) std::move(sparseBlob)}; } -void ConvertMeshes(const gt::Document& doc, ConversionContext& cctx) +void ConvertMeshes(const gt::Document& doc, ConversionContext& context) { uint32_t meshCount = 0; - cctx.mMeshIds.reserve(doc.mMeshes.size()); - for(auto& m : doc.mMeshes) + context.mMeshIds.reserve(doc.mMeshes.size()); + for(auto& mesh : doc.mMeshes) { - cctx.mMeshIds.push_back(meshCount); - meshCount += m.mPrimitives.size(); + context.mMeshIds.push_back(meshCount); + meshCount += mesh.mPrimitives.size(); } - auto& outMeshes = cctx.mOutput.mResources.mMeshes; + auto& outMeshes = context.mOutput.mResources.mMeshes; outMeshes.reserve(meshCount); - for(auto& m : doc.mMeshes) + for(auto& mesh : doc.mMeshes) { - for(auto& p : m.mPrimitives) + for(auto& primitive : mesh.mPrimitives) { - MeshDefinition meshDef; + MeshDefinition meshDefinition; - auto& attribs = p.mAttributes; - meshDef.mUri = attribs.begin()->second->mBufferView->mBuffer->mUri; - meshDef.mPrimitiveType = GLTF2_TO_DALI_PRIMITIVES[p.mMode]; + auto& attribs = primitive.mAttributes; + meshDefinition.mUri = attribs.begin()->second->mBufferView->mBuffer->mUri; + meshDefinition.mPrimitiveType = GLTF2_TO_DALI_PRIMITIVES[primitive.mMode]; auto& accPositions = *attribs.find(gt::Attribute::POSITION)->second; - meshDef.mPositions = ConvertMeshPrimitiveAccessor(accPositions); + meshDefinition.mPositions = ConvertMeshPrimitiveAccessor(accPositions); // glTF2 support vector4 tangent for mesh. // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#meshes-overview - meshDef.mTangentType = Property::VECTOR4; + meshDefinition.mTangentType = Property::VECTOR4; const bool needNormalsTangents = accPositions.mType == gt::AccessorType::VEC3; for(auto& am : ATTRIBUTE_MAPPINGS) @@ -604,14 +607,14 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& cctx) auto iFind = attribs.find(am.mType); if(iFind != attribs.end()) { - DALI_ASSERT_DEBUG(iFind->second->mBufferView->mBuffer->mUri.compare(meshDef.mUri) == 0); - auto& accessor = meshDef.*(am.mAccessor); + DALI_ASSERT_DEBUG(iFind->second->mBufferView->mBuffer->mUri.compare(meshDefinition.mUri) == 0); + auto& accessor = meshDefinition.*(am.mAccessor); accessor = ConvertMeshPrimitiveAccessor(*iFind->second); if(iFind->first == gt::Attribute::JOINTS_0) { - meshDef.mFlags |= (iFind->second->mComponentType == gt::Component::UNSIGNED_SHORT) * MeshDefinition::U16_JOINT_IDS; - DALI_ASSERT_DEBUG(MaskMatch(meshDef.mFlags, MeshDefinition::U16_JOINT_IDS) || iFind->second->mComponentType == gt::Component::FLOAT); + meshDefinition.mFlags |= (iFind->second->mComponentType == gt::Component::UNSIGNED_SHORT) * MeshDefinition::U16_JOINT_IDS; + DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U16_JOINT_IDS) || iFind->second->mComponentType == gt::Component::FLOAT); } } else if(needNormalsTangents) @@ -619,11 +622,11 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& cctx) switch(am.mType) { case gt::Attribute::NORMAL: - meshDef.RequestNormals(); + meshDefinition.RequestNormals(); break; case gt::Attribute::TANGENT: - meshDef.RequestTangents(); + meshDefinition.RequestTangents(); break; default: @@ -632,18 +635,18 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& cctx) } } - if(p.mIndices) + if(primitive.mIndices) { - meshDef.mIndices = ConvertMeshPrimitiveAccessor(*p.mIndices); - meshDef.mFlags |= (p.mIndices->mComponentType == gt::Component::UNSIGNED_INT) * MeshDefinition::U32_INDICES; - DALI_ASSERT_DEBUG(MaskMatch(meshDef.mFlags, MeshDefinition::U32_INDICES) || p.mIndices->mComponentType == gt::Component::UNSIGNED_SHORT); + meshDefinition.mIndices = ConvertMeshPrimitiveAccessor(*primitive.mIndices); + meshDefinition.mFlags |= (primitive.mIndices->mComponentType == gt::Component::UNSIGNED_INT) * MeshDefinition::U32_INDICES; + DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U32_INDICES) || primitive.mIndices->mComponentType == gt::Component::UNSIGNED_SHORT); } - if(!p.mTargets.empty()) + if(!primitive.mTargets.empty()) { - meshDef.mBlendShapes.reserve(p.mTargets.size()); - meshDef.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0; - for(const auto& target : p.mTargets) + meshDefinition.mBlendShapes.reserve(primitive.mTargets.size()); + meshDefinition.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0; + for(const auto& target : primitive.mTargets) { MeshDefinition::BlendShape blendShape; @@ -664,44 +667,44 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& cctx) blendShape.tangents = ConvertMeshPrimitiveAccessor(*it->second); } - if(!m.mWeights.empty()) + if(!mesh.mWeights.empty()) { - blendShape.weight = m.mWeights[meshDef.mBlendShapes.size()]; + blendShape.weight = mesh.mWeights[meshDefinition.mBlendShapes.size()]; } - meshDef.mBlendShapes.push_back(std::move(blendShape)); + meshDefinition.mBlendShapes.push_back(std::move(blendShape)); } } - outMeshes.push_back({std::move(meshDef), MeshGeometry{}}); + outMeshes.push_back({std::move(meshDefinition), MeshGeometry{}}); } } } -ModelNode* MakeModelNode(const gt::Mesh::Primitive& prim, ConversionContext& cctx) +ModelRenderable* MakeModelRenderable(const gt::Mesh::Primitive& prim, ConversionContext& context) { - auto modelNode = new ModelNode(); + auto modelRenderable = new ModelRenderable(); - modelNode->mShaderIdx = 0; // TODO: further thought + modelRenderable->mShaderIdx = 0; // TODO: further thought auto materialIdx = prim.mMaterial.GetIndex(); if(INVALID_INDEX == materialIdx) { // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#default-material - if(INVALID_INDEX == cctx.mDefaultMaterial) + if(INVALID_INDEX == context.mDefaultMaterial) { - auto& outMaterials = cctx.mOutput.mResources.mMaterials; - cctx.mDefaultMaterial = outMaterials.size(); + auto& outMaterials = context.mOutput.mResources.mMaterials; + context.mDefaultMaterial = outMaterials.size(); ConvertMaterial(gt::Material{}, outMaterials); } - materialIdx = cctx.mDefaultMaterial; + materialIdx = context.mDefaultMaterial; } - modelNode->mMaterialIdx = materialIdx; + modelRenderable->mMaterialIdx = materialIdx; - return modelNode; + return modelRenderable; } void ConvertCamera(const gt::Camera& camera, CameraParameters& camParams) @@ -725,9 +728,9 @@ void ConvertCamera(const gt::Camera& camera, CameraParameters& camParams) } } -void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& cctx, bool isMRendererModel) +void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& context, bool isMRendererModel) { - auto& output = cctx.mOutput; + auto& output = context.mOutput; auto& scene = output.mScene; auto& resources = output.mResources; @@ -762,42 +765,27 @@ void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, Con ExceptionFlinger(ASSERT_LOCATION) << "Node name '" << node.mName << "' is not unique; scene is invalid."; } - cctx.mNodeIndices.RegisterMapping(gltfIdx, idx); + context.mNodeIndices.RegisterMapping(gltfIdx, idx); Index skeletonIdx = node.mSkin ? node.mSkin.GetIndex() : INVALID_INDEX; - if(node.mMesh && !node.mMesh->mPrimitives.empty()) + if(node.mMesh) { - auto& mesh = *node.mMesh; - - auto iPrim = mesh.mPrimitives.begin(); - auto modelNode = MakeModelNode(*iPrim, cctx); - auto meshIdx = cctx.mMeshIds[node.mMesh.GetIndex()]; - modelNode->mMeshIdx = meshIdx; - - weakNode->mRenderable.reset(modelNode); - - DALI_ASSERT_DEBUG(resources.mMeshes[meshIdx].first.mSkeletonIdx == INVALID_INDEX || - resources.mMeshes[meshIdx].first.mSkeletonIdx == skeletonIdx); - resources.mMeshes[meshIdx].first.mSkeletonIdx = skeletonIdx; - - // As does model-exporter, we'll create anonymous child nodes for additional mesh( primitiv)es. - while(++iPrim != mesh.mPrimitives.end()) + auto& mesh = *node.mMesh; + uint32_t primitiveCount = mesh.mPrimitives.size(); + auto meshIdx = context.mMeshIds[node.mMesh.GetIndex()]; + weakNode->mRenderables.reserve(primitiveCount); + for(uint32_t i = 0; i < primitiveCount; ++i) { - std::unique_ptr child{new NodeDefinition}; - child->mParentIdx = idx; + std::unique_ptr renderable; + auto modelRenderable = MakeModelRenderable(mesh.mPrimitives[i], context); + modelRenderable->mMeshIdx = meshIdx + i; - auto childModel = MakeModelNode(*iPrim, cctx); + DALI_ASSERT_DEBUG(resources.mMeshes[modelRenderable->mMeshIdx].first.mSkeletonIdx == INVALID_INDEX || + resources.mMeshes[modelRenderable->mMeshIdx].first.mSkeletonIdx == skeletonIdx); + resources.mMeshes[modelRenderable->mMeshIdx].first.mSkeletonIdx = skeletonIdx; - ++meshIdx; - childModel->mMeshIdx = meshIdx; - - child->mRenderable.reset(childModel); - - scene.AddNode(std::move(child)); - - DALI_ASSERT_DEBUG(resources.mMeshes[meshIdx].first.mSkeletonIdx == INVALID_INDEX || - resources.mMeshes[meshIdx].first.mSkeletonIdx == skeletonIdx); - resources.mMeshes[meshIdx].first.mSkeletonIdx = skeletonIdx; + renderable.reset(modelRenderable); + weakNode->mRenderables.push_back(std::move(renderable)); } } @@ -812,13 +800,13 @@ void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, Con for(auto& n : node.mChildren) { - ConvertNode(*n, n.GetIndex(), idx, cctx, isMRendererModel); + ConvertNode(*n, n.GetIndex(), idx, context, isMRendererModel); } } -void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx, bool isMRendererModel) +void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& context, bool isMRendererModel) { - auto& outScene = cctx.mOutput.mScene; + auto& outScene = context.mOutput.mScene; Index rootIdx = outScene.GetNodeCount(); switch(scene.mNodes.size()) { @@ -826,7 +814,7 @@ void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx, bool isM break; case 1: - ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, cctx, isMRendererModel); + ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, context, isMRendererModel); outScene.AddRootNode(rootIdx); break; @@ -840,25 +828,25 @@ void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx, bool isM for(auto& n : scene.mNodes) { - ConvertNode(*n, n.GetIndex(), rootIdx, cctx, isMRendererModel); + ConvertNode(*n, n.GetIndex(), rootIdx, context, isMRendererModel); } break; } } } -void ConvertNodes(const gt::Document& doc, ConversionContext& cctx, bool isMRendererModel) +void ConvertNodes(const gt::Document& doc, ConversionContext& context, bool isMRendererModel) { - ConvertSceneNodes(*doc.mScene, cctx, isMRendererModel); + ConvertSceneNodes(*doc.mScene, context, isMRendererModel); for(uint32_t i = 0, i1 = doc.mScene.GetIndex(); i < i1; ++i) { - ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel); + ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel); } for(uint32_t i = doc.mScene.GetIndex() + 1; i < doc.mScenes.size(); ++i) { - ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel); + ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel); } } @@ -946,9 +934,9 @@ float LoadBlendShapeKeyFrames(const std::string& path, const gt::Animation::Chan return duration; } -void ConvertAnimations(const gt::Document& doc, ConversionContext& cctx) +void ConvertAnimations(const gt::Document& doc, ConversionContext& context) { - auto& output = cctx.mOutput; + auto& output = context.mOutput; output.mAnimationDefinitions.reserve(output.mAnimationDefinitions.size() + doc.mAnimations.size()); @@ -979,8 +967,8 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& cctx) } else { - Index index = cctx.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex()); - nodeName = cctx.mOutput.mScene.GetNode(index)->mName; + Index index = context.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex()); + nodeName = context.mOutput.mScene.GetNode(index)->mName; } float duration = 0.f; @@ -995,7 +983,7 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& cctx) animatedProperty.mPropertyName = POSITION_PROPERTY; animatedProperty.mKeyFrames = KeyFrames::New(); - duration = LoadKeyFrames(cctx.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); + duration = LoadKeyFrames(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); animatedProperty.mTimePeriod = {0.f, duration}; break; @@ -1008,7 +996,7 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& cctx) animatedProperty.mPropertyName = ORIENTATION_PROPERTY; animatedProperty.mKeyFrames = KeyFrames::New(); - duration = LoadKeyFrames(cctx.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); + duration = LoadKeyFrames(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); animatedProperty.mTimePeriod = {0.f, duration}; break; @@ -1021,14 +1009,14 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& cctx) animatedProperty.mPropertyName = SCALE_PROPERTY; animatedProperty.mKeyFrames = KeyFrames::New(); - duration = LoadKeyFrames(cctx.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); + duration = LoadKeyFrames(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); animatedProperty.mTimePeriod = {0.f, duration}; break; } case gt::Animation::Channel::Target::WEIGHTS: { - duration = LoadBlendShapeKeyFrames(cctx.mPath, channel, nodeName, propertyIndex, animationDef.mProperties); + duration = LoadBlendShapeKeyFrames(context.mPath, channel, nodeName, propertyIndex, animationDef.mProperties); break; } @@ -1048,7 +1036,7 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& cctx) } } -void ProcessSkins(const gt::Document& doc, ConversionContext& cctx) +void ProcessSkins(const gt::Document& doc, ConversionContext& context) { // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skininversebindmatrices // If an inverseBindMatrices accessor was provided, we'll load the joint data from the buffer, @@ -1090,7 +1078,7 @@ void ProcessSkins(const gt::Document& doc, ConversionContext& cctx) } }; - auto& resources = cctx.mOutput.mResources; + auto& resources = context.mOutput.mResources; resources.mSkeletons.reserve(doc.mSkins.size()); for(auto& s : doc.mSkins) @@ -1098,7 +1086,7 @@ void ProcessSkins(const gt::Document& doc, ConversionContext& cctx) std::unique_ptr ibmProvider; if(s.mInverseBindMatrices) { - ibmProvider.reset(new InverseBindMatrixAccessor(*s.mInverseBindMatrices, cctx.mPath)); + ibmProvider.reset(new InverseBindMatrixAccessor(*s.mInverseBindMatrices, context.mPath)); } else { @@ -1108,14 +1096,14 @@ void ProcessSkins(const gt::Document& doc, ConversionContext& cctx) SkeletonDefinition skeleton; if(s.mSkeleton.GetIndex() != INVALID_INDEX) { - skeleton.mRootNodeIdx = cctx.mNodeIndices.GetRuntimeId(s.mSkeleton.GetIndex()); + skeleton.mRootNodeIdx = context.mNodeIndices.GetRuntimeId(s.mSkeleton.GetIndex()); } skeleton.mJoints.resize(s.mJoints.size()); auto iJoint = skeleton.mJoints.begin(); for(auto& j : s.mJoints) { - iJoint->mNodeIdx = cctx.mNodeIndices.GetRuntimeId(j.GetIndex()); + iJoint->mNodeIdx = context.mNodeIndices.GetRuntimeId(j.GetIndex()); ibmProvider->Provide(iJoint->mInverseBindMatrix); @@ -1128,12 +1116,16 @@ void ProcessSkins(const gt::Document& doc, ConversionContext& cctx) void ProduceShaders(ShaderDefinitionFactory& shaderFactory, SceneDefinition& scene) { - for(size_t i0 = 0, i1 = scene.GetNodeCount(); i0 != i1; ++i0) + uint32_t nodeCount = scene.GetNodeCount(); + for(uint32_t i = 0; i < nodeCount; ++i) { - auto nodeDef = scene.GetNode(i0); - if(auto renderable = nodeDef->mRenderable.get()) + auto nodeDef = scene.GetNode(i); + for(auto& renderable : nodeDef->mRenderables) { - renderable->mShaderIdx = shaderFactory.ProduceShader(*nodeDef); + if(shaderFactory.ProduceShader(*renderable) == INVALID_INDEX) + { + DALI_LOG_ERROR("Fail to produce shader\n"); + } } } } @@ -1166,12 +1158,12 @@ void SetObjectReaders() js::SetObjectReader(SCENE_READER); } -void SetDefaultEnvironmentMap(const gt::Document& doc, ConversionContext& cctx) +void SetDefaultEnvironmentMap(const gt::Document& doc, ConversionContext& context) { EnvironmentDefinition envDef; envDef.mUseBrdfTexture = true; envDef.mIblIntensity = Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity(); - cctx.mOutput.mResources.mEnvironmentMaps.push_back({std::move(envDef), EnvironmentDefinition::Textures()}); + context.mOutput.mResources.mEnvironmentMaps.push_back({std::move(envDef), EnvironmentDefinition::Textures()}); } } // namespace @@ -1222,18 +1214,18 @@ void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactor DOCUMENT_READER.Read(rootObj, doc); auto path = url.substr(0, url.rfind('/') + 1); - ConversionContext cctx{params, path, INVALID_INDEX}; + ConversionContext context{params, path, INVALID_INDEX}; - ConvertMaterials(doc, cctx); - ConvertMeshes(doc, cctx); - ConvertNodes(doc, cctx, isMRendererModel); - ConvertAnimations(doc, cctx); - ProcessSkins(doc, cctx); + ConvertMaterials(doc, context); + ConvertMeshes(doc, context); + ConvertNodes(doc, context, isMRendererModel); + ConvertAnimations(doc, context); + ProcessSkins(doc, context); ProduceShaders(shaderFactory, params.mScene); params.mScene.EnsureUniqueSkinningShaderInstances(params.mResources); // Set Default Environment map - SetDefaultEnvironmentMap(doc, cctx); + SetDefaultEnvironmentMap(doc, context); } } // namespace Loader diff --git a/dali-scene3d/public-api/loader/material-definition.h b/dali-scene3d/public-api/loader/material-definition.h index d96d888..e45b69b 100644 --- a/dali-scene3d/public-api/loader/material-definition.h +++ b/dali-scene3d/public-api/loader/material-definition.h @@ -234,6 +234,7 @@ public: // DATA bool mNeedAlbedoTexture = true; bool mNeedMetallicRoughnessTexture = true; bool mNeedNormalTexture = true; + bool mDoubleSided = false; std::vector mTextureStages; }; diff --git a/dali-scene3d/public-api/loader/node-definition.cpp b/dali-scene3d/public-api/loader/node-definition.cpp index c83fc44..87fc246 100644 --- a/dali-scene3d/public-api/loader/node-definition.cpp +++ b/dali-scene3d/public-api/loader/node-definition.cpp @@ -77,9 +77,9 @@ Actor NodeDefinition::CreateActor(CreateParams& params) const actor.RegisterProperty(ORIGINAL_MATRIX_PROPERTY_NAME, GetLocalSpace(), Property::AccessMode::READ_ONLY); - if(mRenderable) + for(auto& renderable : mRenderables) { - mRenderable->OnCreate(*this, params, actor); + renderable->OnCreate(*this, params, actor); } for(auto& e : mExtras) @@ -114,20 +114,38 @@ std::string_view NodeDefinition::GetIblYDirectionUniformName() bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const { - if(mRenderable) + if(mRenderables.empty()) { - if(!mRenderable->GetExtents(resources, min, max)) + return false; + } + + bool useModelExtents = false; + for(auto& renderable : mRenderables) + { + Vector3 renderableMin(Vector3::ONE * MAXFLOAT), renderableMax(-Vector3::ONE * MAXFLOAT); + if(!renderable->GetExtents(resources, renderableMin, renderableMax)) { - // If the renderable node don't have mesh accessor, use size to compute extents. - min = -mSize / 2.0f; - max = mSize / 2.0f; + useModelExtents = false; + break; } - return true; + useModelExtents = true; + min.x = std::min(min.x, renderableMin.x); + min.y = std::min(min.y, renderableMin.y); + min.z = std::min(min.z, renderableMin.z); + max.x = std::max(max.x, renderableMax.x); + max.y = std::max(max.y, renderableMax.y); + max.z = std::max(max.z, renderableMax.z); } - return false; + if(!useModelExtents) + { + // If the renderable node don't have mesh accessor, use size to compute extents. + min = -mSize / 2.0f; + max = mSize / 2.0f; + } + return true; } -bool ModelNode::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const +bool ModelRenderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const { auto& mesh = resources.mMeshes[mMeshIdx]; uint32_t minSize = mesh.first.mPositions.mBlob.mMin.size(); @@ -146,21 +164,21 @@ bool ModelNode::GetExtents(const ResourceBundle& resources, Vector3& min, Vector return false; } -void ModelNode::RegisterResources(IResourceReceiver& receiver) const +void ModelRenderable::RegisterResources(IResourceReceiver& receiver) const { Renderable::RegisterResources(receiver); receiver.Register(ResourceType::Mesh, mMeshIdx); receiver.Register(ResourceType::Material, mMaterialIdx); } -void ModelNode::ReflectResources(IResourceReflector& reflector) +void ModelRenderable::ReflectResources(IResourceReflector& reflector) { Renderable::ReflectResources(reflector); reflector.Reflect(ResourceType::Mesh, mMeshIdx); reflector.Reflect(ResourceType::Material, mMaterialIdx); } -void ModelNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const +void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const { DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX); Renderable::OnCreate(node, params, actor); @@ -168,7 +186,7 @@ void ModelNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParam auto& resources = params.mResources; auto& mesh = resources.mMeshes[mMeshIdx]; - auto renderer = actor.GetRendererAt(0); + auto renderer = actor.GetRendererAt(actor.GetRendererCount() - 1u); Geometry geometry = mesh.second.geometry; renderer.SetGeometry(geometry); @@ -203,29 +221,25 @@ void ModelNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParam textures = newTextureSet; } - renderer.SetTextures(textures); - - actor.SetProperty(Actor::Property::COLOR, mColor); - - actor.RegisterProperty("uHasVertexColor", static_cast(mesh.first.mColors.IsDefined())); + renderer.RegisterProperty("uHasVertexColor", static_cast(mesh.first.mColors.IsDefined())); auto& matDef = resources.mMaterials[mMaterialIdx].first; - actor.RegisterProperty("uColorFactor", matDef.mBaseColorFactor); - actor.RegisterProperty("uMetallicFactor", matDef.mMetallic); - actor.RegisterProperty("uRoughnessFactor", matDef.mRoughness); - actor.RegisterProperty("uNormalScale", matDef.mNormalScale); + renderer.RegisterProperty("uColorFactor", matDef.mBaseColorFactor); + renderer.RegisterProperty("uMetallicFactor", matDef.mMetallic); + renderer.RegisterProperty("uRoughnessFactor", matDef.mRoughness); + renderer.RegisterProperty("uNormalScale", matDef.mNormalScale); if(matDef.mFlags & MaterialDefinition::OCCLUSION) { - actor.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength); + renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength); } if(matDef.mFlags & MaterialDefinition::EMISSIVE) { - actor.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor); + renderer.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor); } Index envIdx = matDef.mEnvironmentIdx; - actor.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity); - actor.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection); + renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity); + renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection); float opaque = 0.0f; float mask = 0.0f; @@ -241,14 +255,18 @@ void ModelNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParam mask = 1.0f; } } - actor.RegisterProperty("uOpaque", opaque); - actor.RegisterProperty("uMask", mask); - actor.RegisterProperty("uAlphaThreshold", alphaCutoff); + renderer.RegisterProperty("uOpaque", opaque); + renderer.RegisterProperty("uMask", mask); + renderer.RegisterProperty("uAlphaThreshold", alphaCutoff); + + renderer.SetTextures(textures); + + actor.SetProperty(Actor::Property::COLOR, mColor); } -void ArcNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const +void ArcRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const { - ModelNode::OnCreate(node, params, actor); + ModelRenderable::OnCreate(node, params, actor); actor.RegisterProperty("antiAliasing", mAntiAliasing ? 1 : 0); actor.RegisterProperty("arcCaps", mArcCaps); @@ -263,13 +281,13 @@ void ArcNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& actor.RegisterProperty("endAngle", endPolar); } -void ArcNode::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector) +void ArcRenderable::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector) { float endAngle = 0.f; if(diffAngle <= 0.001f) { - //0.001 is used to ensure is empty arc when startAngle = endAngle + 360 * N + // 0.001 is used to ensure is empty arc when startAngle = endAngle + 360 * N endAngle = startAngle + 0.001f; } else if(diffAngle >= 360.f) diff --git a/dali-scene3d/public-api/loader/node-definition.h b/dali-scene3d/public-api/loader/node-definition.h index a86d7e9..fde74e2 100644 --- a/dali-scene3d/public-api/loader/node-definition.h +++ b/dali-scene3d/public-api/loader/node-definition.h @@ -261,7 +261,7 @@ public: // DATA bool mIsVisible = true; - std::unique_ptr mRenderable; + std::vector> mRenderables; std::unique_ptr mCustomization; std::vector mExtras; std::vector mConstraints; @@ -270,7 +270,7 @@ public: // DATA Index mParentIdx = INVALID_INDEX; }; -class DALI_SCENE3D_API ModelNode : public NodeDefinition::Renderable +class DALI_SCENE3D_API ModelRenderable : public NodeDefinition::Renderable { public: // DATA Vector4 mColor = Color::WHITE; @@ -287,7 +287,7 @@ public: // METHODS /** * @brief Parameters for an Arc node. */ -class DALI_SCENE3D_API ArcNode : public ModelNode +class DALI_SCENE3D_API ArcRenderable : public ModelRenderable { public: // DATA bool mAntiAliasing = true; @@ -306,4 +306,4 @@ public: // METHODS } // namespace Scene3D } // namespace Dali -#endif //DALI_SCENE3D_LOADER_NODE_DEFINITION_H_ +#endif // DALI_SCENE3D_LOADER_NODE_DEFINITION_H_ diff --git a/dali-scene3d/public-api/loader/scene-definition.cpp b/dali-scene3d/public-api/loader/scene-definition.cpp index 6e26c0f..a117e1e 100644 --- a/dali-scene3d/public-api/loader/scene-definition.cpp +++ b/dali-scene3d/public-api/loader/scene-definition.cpp @@ -453,9 +453,9 @@ void SceneDefinition::CountResourceRefs(Index iNode, const Customization::Choice void Start(const NodeDefinition& n) { - if(n.mRenderable) + for(auto& renderable : n.mRenderables) { - n.mRenderable->RegisterResources(counter); + renderable->RegisterResources(counter); } } @@ -526,7 +526,7 @@ void SceneDefinition::GetCustomizationOptions(const Customization::Choices& choi NodeDefinition* SceneDefinition::AddNode(std::unique_ptr&& nodeDef) { - if(FindNode(nodeDef->mName)) + if(!nodeDef->mName.empty() && FindNode(nodeDef->mName)) { return nullptr; } @@ -991,10 +991,10 @@ void SceneDefinition::EnsureUniqueSkinningShaderInstances(ResourceBundle& resour std::map>> skinningShaderUsers; for(auto& node : mNodes) { - if(node->mRenderable) + for(auto& renderable : node->mRenderables) { ResourceReflector reflector; - node->mRenderable->ReflectResources(reflector); + renderable->ReflectResources(reflector); if(reflector.iMesh) { @@ -1045,21 +1045,21 @@ void SceneDefinition::ConfigureSkinningShaders(const ResourceBundle& SortAndDeduplicateSkinningRequests(requests); - for(auto& i : requests) + for(auto& request : requests) { - auto& skeleton = resources.mSkeletons[i.mSkeletonIdx]; + auto& skeleton = resources.mSkeletons[request.mSkeletonIdx]; if(skeleton.mJoints.empty()) { - LOGD(("Skeleton %d has no joints.", i.mSkeletonIdx)); + LOGD(("Skeleton %d has no joints.", request.mSkeletonIdx)); continue; } Index boneIdx = 0; - for(auto& j : skeleton.mJoints) + for(auto& joint : skeleton.mJoints) { - auto node = GetNode(j.mNodeIdx); + auto node = GetNode(joint.mNodeIdx); Actor actor = rootActor.FindChildByName(node->mName); - ConfigureBoneMatrix(j.mInverseBindMatrix, actor, i.mShader, boneIdx); + ConfigureBoneMatrix(joint.mInverseBindMatrix, actor, request.mShader, boneIdx); } } } @@ -1129,10 +1129,10 @@ void SceneDefinition::EnsureUniqueBlendShapeShaderInstances(ResourceBundle& reso std::map>> blendShapeShaderUsers; for(auto& node : mNodes) { - if(node->mRenderable) + for(auto& renderable : node->mRenderables) { ResourceReflector reflector; - node->mRenderable->ReflectResources(reflector); + renderable->ReflectResources(reflector); if(reflector.iMesh) { diff --git a/dali-scene3d/public-api/loader/shader-definition-factory.cpp b/dali-scene3d/public-api/loader/shader-definition-factory.cpp index 59dd3b4..ec41ef4 100644 --- a/dali-scene3d/public-api/loader/shader-definition-factory.cpp +++ b/dali-scene3d/public-api/loader/shader-definition-factory.cpp @@ -68,7 +68,7 @@ void RetrieveBlendShapeComponents(const std::vector& } } -uint64_t HashNode(const NodeDefinition& nodeDef, const MaterialDefinition& materialDef, const MeshDefinition& meshDef) +uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& meshDef) { Hash hash; @@ -173,145 +173,155 @@ void ShaderDefinitionFactory::SetResources(ResourceBundle& resources) mImpl->mShaderMap.clear(); } -Index ShaderDefinitionFactory::ProduceShader(const NodeDefinition& nodeDef) +Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& renderable) { - DALI_ASSERT_DEBUG(nodeDef.mRenderable); + auto& resources = *mImpl->mResources; - auto& resources = *mImpl->mResources; ResourceReceiver receiver{resources}; - nodeDef.mRenderable->RegisterResources(receiver); + renderable.RegisterResources(receiver); + if(!(receiver.mMeshDef && receiver.mMaterialDef)) { + renderable.mShaderIdx = INVALID_INDEX; return INVALID_INDEX; } auto& shaderMap = mImpl->mShaderMap; - uint64_t hash = HashNode(nodeDef, *receiver.mMaterialDef, *receiver.mMeshDef); + uint64_t hash = HashNode(*receiver.mMaterialDef, *receiver.mMeshDef); auto iFind = shaderMap.find(hash); if(iFind != shaderMap.end()) { - return iFind->second; - } - - ShaderDefinition shaderDef; - shaderDef.mUseBuiltInShader = true; - shaderDef.mRendererState = RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE | RendererState::CULL_BACK; - - auto& materialDef = *receiver.mMaterialDef; - const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY); - if(hasTransparency) - { - // TODO: this requires more granularity - shaderDef.mRendererState = (shaderDef.mRendererState | RendererState::ALPHA_BLEND) & ~RendererState::DEPTH_WRITE; + renderable.mShaderIdx = iFind->second; } - - if(hasTransparency || - !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) || - !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS)) - + else { - shaderDef.mDefines.push_back("THREE_TEX"); + ShaderDefinition shaderDef; + shaderDef.mUseBuiltInShader = true; + shaderDef.mRendererState = RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE; - // For the glTF, each of basecolor, metallic_roughness, normal texture is not essential. - if(MaskMatch(materialDef.mFlags, MaterialDefinition::ALBEDO)) + auto& materialDef = *receiver.mMaterialDef; + if(!materialDef.mDoubleSided) { - shaderDef.mDefines.push_back("BASECOLOR_TEX"); + shaderDef.mRendererState |= RendererState::CULL_BACK; } - if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS)) + const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY); + if(hasTransparency) { - shaderDef.mDefines.push_back("METALLIC_ROUGHNESS_TEX"); + // TODO: this requires more granularity + shaderDef.mRendererState = (shaderDef.mRendererState | RendererState::ALPHA_BLEND) & ~RendererState::DEPTH_WRITE; } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL)) - { - shaderDef.mDefines.push_back("NORMAL_TEX"); - } - } + if(hasTransparency || + !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) || + !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS)) - if(materialDef.GetAlphaCutoff() > 0.f) - { - shaderDef.mDefines.push_back("ALPHA_TEST"); - } + { + shaderDef.mDefines.push_back("THREE_TEX"); - if(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE)) - { - shaderDef.mDefines.push_back("SSS"); - } + // For the glTF, each of basecolor, metallic_roughness, normal texture is not essential. + if(MaskMatch(materialDef.mFlags, MaterialDefinition::ALBEDO)) + { + shaderDef.mDefines.push_back("BASECOLOR_TEX"); + } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION)) - { - shaderDef.mDefines.push_back("OCCLUSION"); - } + if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS)) + { + shaderDef.mDefines.push_back("METALLIC_ROUGHNESS_TEX"); + } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE)) - { - shaderDef.mDefines.push_back("EMISSIVE"); - } + if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL)) + { + shaderDef.mDefines.push_back("NORMAL_TEX"); + } + } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS)) - { - shaderDef.mDefines.push_back("GLTF_CHANNELS"); - } + if(materialDef.GetAlphaCutoff() > 0.f) + { + shaderDef.mDefines.push_back("ALPHA_TEST"); + } - const auto& meshDef = *receiver.mMeshDef; - if(meshDef.IsSkinned()) - { - shaderDef.mDefines.push_back("SKINNING"); - } + if(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE)) + { + shaderDef.mDefines.push_back("SSS"); + } - if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL)) - { - shaderDef.mDefines.push_back("FLIP_V"); - } + if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION)) + { + shaderDef.mDefines.push_back("OCCLUSION"); + } - if(meshDef.HasBlendShapes()) - { - bool hasPositions = false; - bool hasNormals = false; - bool hasTangents = false; - RetrieveBlendShapeComponents(meshDef.mBlendShapes, hasPositions, hasNormals, hasTangents); + if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE)) + { + shaderDef.mDefines.push_back("EMISSIVE"); + } - if(hasPositions) + if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS)) { - shaderDef.mDefines.push_back("MORPH_POSITION"); + shaderDef.mDefines.push_back("GLTF_CHANNELS"); } - if(hasNormals) + const auto& meshDef = *receiver.mMeshDef; + if(meshDef.IsSkinned()) { - shaderDef.mDefines.push_back("MORPH_NORMAL"); + shaderDef.mDefines.push_back("SKINNING"); } - if(hasTangents) + if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL)) { - shaderDef.mDefines.push_back("MORPH_TANGENT"); + shaderDef.mDefines.push_back("FLIP_V"); } - if(hasPositions || hasNormals || hasTangents) + if(meshDef.HasBlendShapes()) { - shaderDef.mDefines.push_back("MORPH"); + bool hasPositions = false; + bool hasNormals = false; + bool hasTangents = false; + RetrieveBlendShapeComponents(meshDef.mBlendShapes, hasPositions, hasNormals, hasTangents); - if(BlendShapes::Version::VERSION_2_0 == meshDef.mBlendShapeVersion) + if(hasPositions) + { + shaderDef.mDefines.push_back("MORPH_POSITION"); + } + + if(hasNormals) { - shaderDef.mDefines.push_back("MORPH_VERSION_2_0"); + shaderDef.mDefines.push_back("MORPH_NORMAL"); + } + + if(hasTangents) + { + shaderDef.mDefines.push_back("MORPH_TANGENT"); + } + + if(hasPositions || hasNormals || hasTangents) + { + shaderDef.mDefines.push_back("MORPH"); + + if(BlendShapes::Version::VERSION_2_0 == meshDef.mBlendShapeVersion) + { + shaderDef.mDefines.push_back("MORPH_VERSION_2_0"); + } } } - } - if(meshDef.mTangentType == Property::VECTOR4) - { - shaderDef.mDefines.push_back("VEC4_TANGENT"); - } + if(meshDef.mTangentType == Property::VECTOR4) + { + shaderDef.mDefines.push_back("VEC4_TANGENT"); + } - shaderDef.mUniforms["uMaxLOD"] = 6.f; - shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY; + shaderDef.mUniforms["uMaxLOD"] = 6.f; + shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY; - Index result = resources.mShaders.size(); - shaderMap[hash] = result; + Index result = resources.mShaders.size(); + shaderMap[hash] = result; - resources.mShaders.emplace_back(std::move(shaderDef), Shader()); + resources.mShaders.emplace_back(std::move(shaderDef), Shader()); + + renderable.mShaderIdx = result; + } - return result; + return renderable.mShaderIdx; } } // namespace Loader diff --git a/dali-scene3d/public-api/loader/shader-definition-factory.h b/dali-scene3d/public-api/loader/shader-definition-factory.h index 8c4434a..b7e9195 100644 --- a/dali-scene3d/public-api/loader/shader-definition-factory.h +++ b/dali-scene3d/public-api/loader/shader-definition-factory.h @@ -20,6 +20,7 @@ // INTERNAL INCLUDES #include "dali-scene3d/public-api/api.h" #include "dali-scene3d/public-api/loader/index.h" +#include // EXTERNAL INCLUDER #include @@ -51,7 +52,7 @@ public: * already existing in the ResourceBundle are ignored), otherwise the index of the previously * created shader will be returned. */ - Index ProduceShader(const NodeDefinition& nodeDef); + Index ProduceShader(NodeDefinition::Renderable& renderable); private: struct Impl;