/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * 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.
// Enable debug log for test coverage
#define DEBUG_ENABLED 1
+#include <dali-test-suite-utils.h>
+#include <string_view>
+#include "dali-scene-loader/public-api/gltf2-loader.h"
+#include "dali-scene-loader/public-api/load-result.h"
#include "dali-scene-loader/public-api/resource-bundle.h"
#include "dali-scene-loader/public-api/scene-definition.h"
-#include "dali-scene-loader/public-api/load-result.h"
-#include "dali-scene-loader/public-api/gltf2-loader.h"
#include "dali-scene-loader/public-api/shader-definition-factory.h"
-#include <dali-test-suite-utils.h>
-#include <string_view>
using namespace Dali;
using namespace Dali::SceneLoader;
#define DALI_TEST_THROW(expression, exception, predicate) \
- {\
- bool daliTestThrowSuccess__ = false;\
- try\
- {\
- do { expression; } while(0);\
- printf("No exception was thrown.\n");\
- }\
- catch (std::decay<exception>::type& ex)\
- {\
- daliTestThrowSuccess__ = predicate(ex);\
- }\
- catch (...)\
- {\
- printf("Wrong type of exception thrown.\n");\
- }\
- DALI_TEST_CHECK(daliTestThrowSuccess__);\
+ { \
+ bool daliTestThrowSuccess__ = false; \
+ try \
+ { \
+ do \
+ { \
+ expression; \
+ } while(0); \
+ printf("No exception was thrown.\n"); \
+ } \
+ catch(std::decay<exception>::type & ex) \
+ { \
+ daliTestThrowSuccess__ = predicate(ex); \
+ } \
+ catch(...) \
+ { \
+ printf("Wrong type of exception thrown.\n"); \
+ } \
+ DALI_TEST_CHECK(daliTestThrowSuccess__); \
}
namespace
{
struct Context
{
- ResourceBundle resources;
+ ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type) {
+ return TEST_RESOURCE_DIR "/";
+ };
+
+ ResourceBundle resources;
SceneDefinition scene;
- std::vector<AnimationDefinition> animations;
+ std::vector<AnimationDefinition> animations;
std::vector<AnimationGroupDefinition> animationGroups;
- std::vector<CameraParameters> cameras;
- std::vector<LightParameters> lights;
+ std::vector<CameraParameters> cameras;
+ std::vector<LightParameters> lights;
- LoadResult loadResult {
+ LoadResult loadResult{
resources,
scene,
animations,
animationGroups,
cameras,
- lights
- };
+ lights};
};
struct ExceptionMessageStartsWith
bool operator()(const std::runtime_error& e)
{
const bool success = (0 == strncmp(e.what(), expected.data(), expected.size()));
- if (!success)
+ if(!success)
{
printf("Expected: %s, got: %s.\n", expected.data(), e.what());
}
}
};
-}
+} // namespace
int UtcDaliGltfLoaderFailedToLoad(void)
{
sdf.SetResources(ctx.resources);
DALI_TEST_THROW(LoadGltfScene("non-existent.gltf", sdf, ctx.loadResult),
- std::runtime_error,
- ExceptionMessageStartsWith{"Failed to load"});
+ std::runtime_error,
+ ExceptionMessageStartsWith{"Failed to load"});
DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
sdf.SetResources(ctx.resources);
DALI_TEST_THROW(LoadGltfScene(TEST_RESOURCE_DIR "/invalid.gltf", sdf, ctx.loadResult),
- std::runtime_error,
- ExceptionMessageStartsWith{"Failed to parse"});
+ std::runtime_error,
+ ExceptionMessageStartsWith{"Failed to parse"});
DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
DALI_TEST_EQUAL(0, ctx.scene.GetNodeCount());
auto& materials = ctx.resources.mMaterials;
DALI_TEST_EQUAL(2u, materials.size());
- const MaterialDefinition materialGroundTruth[] {
- {
- MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
- MaterialDefinition::NORMAL | MaterialDefinition::TRANSPARENCY | MaterialDefinition::GLTF_CHANNELS |
- (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
- 0,
- Vector4(1.f, .766f, .336f, 1.f),
- 1.f,
- 0.f,
- {
- { MaterialDefinition::ALBEDO,
- { "AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT) } },
- { MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
- { "AnimatedCube_MetallicRoughness.png",
- SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT) } },
- { MaterialDefinition::NORMAL,
- { "AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT) } },
- }
- },
- {
- MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
- MaterialDefinition::NORMAL | MaterialDefinition::GLTF_CHANNELS,
- 0,
- Vector4(1.f, .766f, .336f, 1.f),
- 1.f,
- 0.f,
- {
- { MaterialDefinition::ALBEDO,
- { "AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT) } },
- { MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
- { "AnimatedCube_MetallicRoughness.png",
- SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT) } },
- { MaterialDefinition::NORMAL,
- { "AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT) } },
- }
- },
+ const MaterialDefinition materialGroundTruth[]{
+ {MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
+ MaterialDefinition::NORMAL | MaterialDefinition::TRANSPARENCY | MaterialDefinition::GLTF_CHANNELS |
+ (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
+ 0,
+ Vector4(1.f, .766f, .336f, 1.f),
+ 1.f,
+ 0.f,
+ {
+ {MaterialDefinition::ALBEDO,
+ {"AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+ {MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+ {"AnimatedCube_MetallicRoughness.png",
+ SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT)}},
+ {MaterialDefinition::NORMAL,
+ {"AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+ }},
+ {MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
+ MaterialDefinition::NORMAL | MaterialDefinition::GLTF_CHANNELS,
+ 0,
+ Vector4(1.f, .766f, .336f, 1.f),
+ 1.f,
+ 0.f,
+ {
+ {MaterialDefinition::ALBEDO,
+ {"AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+ {MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+ {"AnimatedCube_MetallicRoughness.png",
+ SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT)}},
+ {MaterialDefinition::NORMAL,
+ {"AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+ }},
};
auto iMaterial = materials.begin();
- for (auto& m : materialGroundTruth)
+ for(auto& m : materialGroundTruth)
{
printf("material %ld\n", iMaterial - materials.begin());
auto& md = iMaterial->first;
DALI_TEST_EQUAL(md.mTextureStages.size(), m.mTextureStages.size());
auto iTexture = md.mTextureStages.begin();
- for (auto& ts: m.mTextureStages)
+ for(auto& ts : m.mTextureStages)
{
printf("texture %ld\n", iTexture - md.mTextureStages.begin());
DALI_TEST_EQUAL(iTexture->mSemantic, ts.mSemantic);
auto& meshes = ctx.resources.mMeshes;
DALI_TEST_EQUAL(2u, meshes.size());
- using Blob = MeshDefinition::Blob;
+ using Blob = MeshDefinition::Blob;
using Accessor = MeshDefinition::Accessor;
- const MeshDefinition meshGroundTruth[] {
+ const MeshDefinition meshGroundTruth[]{
{
0,
Geometry::TRIANGLES,
"AnimatedCube.bin",
- Accessor{ Blob{ 0, 0 }, {} },
- Accessor{ Blob{ 0, 0 }, {} },
- Accessor{ Blob{ 0, 0 }, {} },
- Accessor{ Blob{ 0, 0 }, {} },
- Accessor{ Blob{ 0, 0 }, {} },
+ Accessor{Blob{0, 0}, {}},
+ Accessor{Blob{0, 0}, {}},
+ Accessor{Blob{0, 0}, {}},
+ Accessor{Blob{0, 0}, {}},
+ Accessor{Blob{0, 0}, {}},
},
{
0,
Geometry::TRIANGLES,
"AnimatedCube.bin",
- Accessor{ Blob{ 0, 0 }, {} },
- Accessor{ Blob{ 0, 0 }, {} },
- Accessor{ Blob{ 0, 0 }, {} },
- Accessor{ Blob{ 0, 0 }, {} },
- Accessor{ Blob{ 0, 0 }, {} },
+ Accessor{Blob{0, 0}, {}},
+ Accessor{Blob{0, 0}, {}},
+ Accessor{Blob{0, 0}, {}},
+ Accessor{Blob{0, 0}, {}},
+ Accessor{Blob{0, 0}, {}},
},
};
auto iMesh = meshes.begin();
- for (auto& m : meshGroundTruth)
+ for(auto& m : meshGroundTruth)
{
printf("mesh %ld\n", iMesh - meshes.begin());
auto& md = iMesh->first;
DALI_TEST_EQUAL(md.mFlags, m.mFlags);
DALI_TEST_EQUAL(md.mPrimitiveType, m.mPrimitiveType);
- for (auto mp: {
- &MeshDefinition::mIndices,
- &MeshDefinition::mPositions,
- &MeshDefinition::mNormals,
- &MeshDefinition::mTexCoords,
- &MeshDefinition::mTangents,
- &MeshDefinition::mJoints0,
- &MeshDefinition::mWeights0
- })
+ for(auto mp : {
+ &MeshDefinition::mIndices,
+ &MeshDefinition::mPositions,
+ &MeshDefinition::mNormals,
+ &MeshDefinition::mTexCoords,
+ &MeshDefinition::mTangents,
+ &MeshDefinition::mJoints0,
+ &MeshDefinition::mWeights0})
{
DALI_TEST_EQUAL((md.*mp).IsDefined(), (m.*mp).IsDefined());
DALI_TEST_EQUAL((md.*mp).mBlob.IsDefined(), (m.*mp).mBlob.IsDefined());
TestApplication app;
const std::string resourcePath = TEST_RESOURCE_DIR "/";
- auto pathProvider = [resourcePath](ResourceType::Value) {
+ auto pathProvider = [resourcePath](ResourceType::Value) {
return resourcePath;
};
Customization::Choices choices;
- for (auto modelName : {
- "2CylinderEngine",
- "AnimatedMorphCube",
- "AnimatedMorphSphere",
- "AnimatedTriangle",
- "BoxAnimated",
- "CesiumMan",
- "CesiumMilkTruck",
- "EnvironmentTest",
- "MetalRoughSpheres",
- "MorphPrimitivesTest",
- "SimpleSparseAccessor",
- })
+ for(auto modelName : {
+ "2CylinderEngine",
+ "AnimatedMorphCube",
+ "AnimatedMorphSphere",
+ "AnimatedTriangle",
+ "BoxAnimated",
+ "CesiumMan",
+ "CesiumMilkTruck",
+ "EnvironmentTest",
+ "MetalRoughSpheres",
+ "MorphPrimitivesTest",
+ "MRendererTest",
+ "SimpleSparseAccessor",
+ })
{
Context ctx;
DALI_TEST_CHECK(ctx.scene.GetNodeCount() > 0);
auto& scene = ctx.scene;
- for (auto iRoot : scene.GetRoots())
+ for(auto iRoot : scene.GetRoots())
{
- struct Visitor: NodeDefinition::IVisitor
+ struct Visitor : NodeDefinition::IVisitor
{
- struct ResourceReceiver: IResourceReceiver
+ struct ResourceReceiver : IResourceReceiver
{
std::vector<bool> mCounts;
void Register(ResourceType::Value type, Index id) override
{
- if (type == ResourceType::Mesh)
+ if(type == ResourceType::Mesh)
{
mCounts[id] = true;
}
void Start(NodeDefinition& n) override
{
- if (n.mRenderable)
+ if(n.mRenderable)
{
n.mRenderable->RegisterResources(receiver);
}
}
void Finish(NodeDefinition& n) override
- {}
+ {
+ }
} visitor;
visitor.receiver.mCounts.resize(resources.mMeshes.size(), false);
scene.Visit(iRoot, choices, visitor);
- for (uint32_t i0 = 0, i1 = resources.mMeshes.size(); i0 < i1; ++i0)
+ for(uint32_t i0 = 0, i1 = resources.mMeshes.size(); i0 < i1; ++i0)
{
- if (visitor.receiver.mCounts[i0])
+ if(visitor.receiver.mCounts[i0])
{
auto raw = resources.mMeshes[i0].first.LoadRaw(resourcePath);
DALI_TEST_CHECK(!raw.mAttribs.empty());
END_TEST;
}
+
+int UtcDaliGltfLoaderMRendererTest(void)
+{
+ Context ctx;
+
+ ShaderDefinitionFactory sdf;
+ sdf.SetResources(ctx.resources);
+ auto& resources = ctx.resources;
+ resources.mEnvironmentMaps.push_back({});
+
+ LoadGltfScene(TEST_RESOURCE_DIR "/MRendererTest.gltf", sdf, ctx.loadResult);
+
+ auto& scene = ctx.scene;
+ auto& roots = scene.GetRoots();
+ DALI_TEST_EQUAL(roots.size(), 1u);
+ DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "RootNode");
+ DALI_TEST_EQUAL(scene.GetNode(roots[0])->mScale, Vector3(1.0f, 1.0f, 1.0f));
+
+ DALI_TEST_EQUAL(scene.GetNodeCount(), 1u);
+
+ ViewProjection viewProjection;
+ Transforms xforms{
+ MatrixStack{},
+ viewProjection};
+ NodeDefinition::CreateParams nodeParams{
+ resources,
+ xforms,
+ };
+
+ Customization::Choices choices;
+
+ TestApplication app;
+
+ Actor root = Actor::New();
+ SetActorCentered(root);
+ for(auto iRoot : roots)
+ {
+ auto resourceRefs = resources.CreateRefCounter();
+ scene.CountResourceRefs(iRoot, choices, resourceRefs);
+ resources.CountEnvironmentReferences(resourceRefs);
+ resources.LoadResources(resourceRefs, ctx.pathProvider);
+ if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
+ {
+ scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
+ scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
+ scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
+ root.Add(actor);
+ }
+ }
+
+ DALI_TEST_EQUAL(root.GetChildCount(), 1u);
+ DALI_TEST_EQUAL(root.GetChildAt(0).GetProperty(Actor::Property::NAME).Get<std::string>(), "RootNode");
+ DALI_TEST_EQUAL(root.GetChildAt(0).GetProperty(Actor::Property::SCALE).Get<Vector3>(), Vector3(1.0f, 1.0f, 1.0f));
+
+ END_TEST;
+}
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
const std::string SCALE_PROPERTY("scale");
const std::string BLEND_SHAPE_WEIGHTS_UNIFORM("uBlendShapeWeight");
+const std::string MRENDERER_MODEL_IDENTIFICATION("M-Renderer");
+
+const std::string ROOT_NODE_NAME("RootNode");
+const Vector3 SCALE_TO_ADJUST(100.0f, 100.0f, 100.0f);
+
const Geometry::Type GLTF2_TO_DALI_PRIMITIVES[]{
Geometry::POINTS,
Geometry::LINES,
}
}
-void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& cctx)
+void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& cctx, bool isMRendererModel)
{
auto& output = cctx.mOutput;
auto& scene = output.mScene;
nodeDef->mPosition = node.mTranslation;
nodeDef->mOrientation = node.mRotation;
nodeDef->mScale = node.mScale;
+
+ if(isMRendererModel && node.mName == ROOT_NODE_NAME && node.mScale == SCALE_TO_ADJUST)
+ {
+ nodeDef->mScale *= 0.01f;
+ }
}
return nodeDef;
for(auto& n : node.mChildren)
{
- ConvertNode(*n, n.GetIndex(), idx, cctx);
+ ConvertNode(*n, n.GetIndex(), idx, cctx, isMRendererModel);
}
}
-void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx)
+void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx, bool isMRendererModel)
{
auto& outScene = cctx.mOutput.mScene;
Index rootIdx = outScene.GetNodeCount();
break;
case 1:
- ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, cctx);
+ ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, cctx, isMRendererModel);
outScene.AddRootNode(rootIdx);
break;
for(auto& n : scene.mNodes)
{
- ConvertNode(*n, n.GetIndex(), rootIdx, cctx);
+ ConvertNode(*n, n.GetIndex(), rootIdx, cctx, isMRendererModel);
}
break;
}
}
}
-void ConvertNodes(const gt::Document& doc, ConversionContext& cctx)
+void ConvertNodes(const gt::Document& doc, ConversionContext& cctx, bool isMRendererModel)
{
- ConvertSceneNodes(*doc.mScene, cctx);
+ ConvertSceneNodes(*doc.mScene, cctx, isMRendererModel);
for(uint32_t i = 0, i1 = doc.mScene.GetIndex(); i < i1; ++i)
{
- ConvertSceneNodes(doc.mScenes[i], cctx);
+ ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel);
}
for(uint32_t i = doc.mScene.GetIndex() + 1; i < doc.mScenes.size(); ++i)
{
- ConvertSceneNodes(doc.mScenes[i], cctx);
+ ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel);
}
}
gt::Document doc;
- auto& rootObj = js::Cast<json_object_s>(*root);
- auto jsAsset = js::FindObjectChild("asset", rootObj);
- auto jsAssetVersion = js::FindObjectChild("version", js::Cast<json_object_s>(*jsAsset));
- doc.mAsset.mVersion = js::Read::StringView(*jsAssetVersion);
+ auto& rootObj = js::Cast<json_object_s>(*root);
+ auto jsAsset = js::FindObjectChild("asset", rootObj);
+
+ auto jsAssetVersion = js::FindObjectChild("version", js::Cast<json_object_s>(*jsAsset));
+ if(jsAssetVersion)
+ {
+ doc.mAsset.mVersion = js::Read::StringView(*jsAssetVersion);
+ }
+
+ bool isMRendererModel(false);
+ auto jsAssetGenerator = js::FindObjectChild("generator", js::Cast<json_object_s>(*jsAsset));
+ if(jsAssetGenerator)
+ {
+ doc.mAsset.mGenerator = js::Read::StringView(*jsAssetGenerator);
+ isMRendererModel = (doc.mAsset.mGenerator.find(MRENDERER_MODEL_IDENTIFICATION) != std::string_view::npos);
+ }
+
gt::SetRefReaderObject(doc);
DOCUMENT_READER.Read(rootObj, doc);
ConvertMaterials(doc, cctx);
ConvertMeshes(doc, cctx);
- ConvertNodes(doc, cctx);
+ ConvertNodes(doc, cctx, isMRendererModel);
ConvertAnimations(doc, cctx);
ProcessSkins(doc, cctx);