--- /dev/null
+{\r
+ "scene" : 0,\r
+ "scenes" : [\r
+ {\r
+ "nodes" : [ 0 ]\r
+ }\r
+ ],\r
+\r
+ "nodes" : [\r
+ {\r
+ "name" : "rootNode",\r
+ "mesh" : 0,\r
+ "rotation" : [ 0.0, 0.0, 0.0, 1.0 ]\r
+ }\r
+ ],\r
+\r
+ "meshes" : [\r
+ {\r
+ "primitives" : [\r
+ {\r
+ "attributes" : {\r
+ "POSITION" : 1\r
+ },\r
+ "indices" : 0\r
+ },\r
+ {\r
+ "attributes" : {\r
+ "POSITION" : 1\r
+ },\r
+ "indices" : 0\r
+ }\r
+ ]\r
+ }\r
+ ],\r
+\r
+ "buffers" : [\r
+ {\r
+ "uri" : "simpleTriangle.bin",\r
+ "byteLength" : 44\r
+ },\r
+ {\r
+ "uri" : "animation.bin",\r
+ "byteLength" : 100\r
+ }\r
+ ],\r
+\r
+ "bufferViews" : [\r
+ {\r
+ "buffer" : 0,\r
+ "byteOffset" : 0,\r
+ "byteLength" : 6,\r
+ "target" : 34963\r
+ },\r
+ {\r
+ "buffer" : 0,\r
+ "byteOffset" : 8,\r
+ "byteLength" : 36,\r
+ "target" : 34962\r
+ },\r
+ {\r
+ "buffer" : 1,\r
+ "byteOffset" : 0,\r
+ "byteLength" : 100\r
+ }\r
+ ],\r
+\r
+ "accessors" : [\r
+ {\r
+ "bufferView" : 0,\r
+ "byteOffset" : 0,\r
+ "componentType" : 5123,\r
+ "count" : 3,\r
+ "type" : "SCALAR",\r
+ "max" : [ 2 ],\r
+ "min" : [ 0 ]\r
+ },\r
+ {\r
+ "bufferView" : 1,\r
+ "byteOffset" : 0,\r
+ "componentType" : 5126,\r
+ "count" : 3,\r
+ "type" : "VEC3",\r
+ "max" : [ 1.0, 1.0, 0.0 ],\r
+ "min" : [ 0.0, 0.0, 0.0 ]\r
+ },\r
+ {\r
+ "bufferView" : 2,\r
+ "byteOffset" : 0,\r
+ "componentType" : 5126,\r
+ "count" : 5,\r
+ "type" : "SCALAR",\r
+ "max" : [ 1.0 ],\r
+ "min" : [ 0.0 ]\r
+ },\r
+ {\r
+ "bufferView" : 2,\r
+ "byteOffset" : 20,\r
+ "componentType" : 5126,\r
+ "count" : 5,\r
+ "type" : "VEC4",\r
+ "max" : [ 0.0, 0.0, 1.0, 1.0 ],\r
+ "min" : [ 0.0, 0.0, 0.0, -0.707 ]\r
+ }\r
+ ],\r
+\r
+ "asset" : {\r
+ "version" : "2.0"\r
+ }\r
+}\r
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,
true,
false,
true,
+ false,
{
{MaterialDefinition::ALBEDO,
{"AnimatedCube_BaseColor.png",
true,
true,
true,
+ false,
{
{MaterialDefinition::ALBEDO,
{"AnimatedCube_BaseColor.png",
void Start(NodeDefinition& n) override
{
- if(n.mRenderable)
+ for(auto& renderable : n.mRenderables)
{
- n.mRenderable->RegisterResources(receiver);
+ renderable->RegisterResources(receiver);
}
}
* 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
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
{
// 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 <toolkit-test-application.h>
#include <dali-test-suite-utils.h>
+#include <toolkit-test-application.h>
#include <string_view>
+#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;
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));
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);
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));
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));
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<std::string>());
DALI_TEST_EQUAL(nodeDef.mPosition, actor.GetProperty(Actor::Property::POSITION).Get<Vector3>());
DALI_TEST_EQUAL(nodeDef.mOrientation, actor.GetProperty(Actor::Property::ORIENTATION).Get<Quaternion>());
{
NodeDefinition nodeDef;
- auto renderable = new NodeDefinition::Renderable();
- renderable->mShaderIdx = 0;
- nodeDef.mRenderable.reset(renderable);
+ std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(new NodeDefinition::Renderable());
+ nodeDef.mRenderables.push_back(std::move(renderable));
+ nodeDef.mRenderables[0]->mShaderIdx = 0;
struct : IResourceReceiver
{
std::vector<Index> 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);
{
NodeDefinition nodeDef;
- auto renderable = new NodeDefinition::Renderable();
- renderable->mShaderIdx = 0;
- nodeDef.mRenderable.reset(renderable);
+ std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(new NodeDefinition::Renderable());
+ nodeDef.mRenderables.push_back(std::move(renderable));
+ nodeDef.mRenderables[0]->mShaderIdx = 0;
struct : IResourceReflector
{
std::vector<Index*> 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;
int UtcDaliNodeDefinitionRenderable(void)
{
TestApplication testApp;
- NodeDefinition nodeDef;
+ NodeDefinition nodeDef;
- auto renderable = new NodeDefinition::Renderable();
- renderable->mShaderIdx = 0;
- nodeDef.mRenderable.reset(renderable);
+ std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(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());
Context ctx;
NodeDefinition nodeDef;
- nodeDef.mRenderable.reset(new NodeDefinition::Renderable());
+ std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(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;
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<NodeDefinition::Renderable> renderable;
+ renderable.reset(modelRenderable);
+ nodeDef.mRenderables.push_back(std::move(renderable));
auto& meshDef = NewMeshDefinition(ctx.resources);
auto& materialDef = NewMaterialDefinition(ctx.resources);
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);
}
}
///@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);
}
}
-} //namespace
+} // namespace
struct DliLoader::Impl
{
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)
{
uint32_t jointCount = 0;
std::function<void(Index)> visitFn;
auto& ibms = mInverseBindMatrices;
- visitFn = [&](Index id) {
+ visitFn = [&](Index id)
+ {
auto node = scene.GetNode(id);
jointCount += ibms.find(id) != ibms.end();
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)
{
}
}
- //TODO : need to consider AGIF
+ // TODO : need to consider AGIF
std::vector<std::string> texturePaths;
std::string texturePath;
if(ReadString(node.GetChild("albedoMap"), texturePath))
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;
}
else // something renderable maybe
{
std::unique_ptr<NodeDefinition::Renderable> 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")))
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")))
{
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
}
// 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));
}
}
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)
{
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")
{
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;
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()));
* limitations under the License.
*
*/
-#include "dali-scene3d/public-api/loader/gltf2-loader.h"
#include <fstream>
-#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 <dali-scene3d/public-api/loader/gltf2-loader.h>
+#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 <dali/integration-api/debug.h>
#define ENUM_STRING_MAPPING(t, x) \
{ \
.Register(*js::MakeProperty("emissiveTexture", js::ObjectReader<gt::TextureInfo>::Read, >::Material::mEmissiveTexture))
.Register(*js::MakeProperty("emissiveFactor", gt::ReadDaliVector<Vector3>, >::Material::mEmissiveFactor))
.Register(*js::MakeProperty("alphaMode", gt::ReadStringEnum<gt::AlphaMode>, >::Material::mAlphaMode))
- .Register(*js::MakeProperty("alphaCutoff", js::Read::Number<float>, >::Material::mAlphaCutoff)));
+ .Register(*js::MakeProperty("alphaCutoff", js::Read::Number<float>, >::Material::mAlphaCutoff))
+ .Register(*js::MakeProperty("doubleSided", js::Read::Boolean, >::Material::mDoubleSided)));
std::map<gt::Attribute::Type, gt::Ref<gt::Accessor>> ReadMeshPrimitiveAttributes(const json_value_s& j)
{
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;
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;
}
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)
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)
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)
switch(am.mType)
{
case gt::Attribute::NORMAL:
- meshDef.RequestNormals();
+ meshDefinition.RequestNormals();
break;
case gt::Attribute::TANGENT:
- meshDef.RequestTangents();
+ meshDefinition.RequestTangents();
break;
default:
}
}
- 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;
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)
}
}
-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;
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<NodeDefinition> child{new NodeDefinition};
- child->mParentIdx = idx;
+ std::unique_ptr<NodeDefinition::Renderable> 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));
}
}
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())
{
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;
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);
}
}
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());
}
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;
animatedProperty.mPropertyName = POSITION_PROPERTY;
animatedProperty.mKeyFrames = KeyFrames::New();
- duration = LoadKeyFrames<Vector3>(cctx.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
+ duration = LoadKeyFrames<Vector3>(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
animatedProperty.mTimePeriod = {0.f, duration};
break;
animatedProperty.mPropertyName = ORIENTATION_PROPERTY;
animatedProperty.mKeyFrames = KeyFrames::New();
- duration = LoadKeyFrames<Quaternion>(cctx.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
+ duration = LoadKeyFrames<Quaternion>(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
animatedProperty.mTimePeriod = {0.f, duration};
break;
animatedProperty.mPropertyName = SCALE_PROPERTY;
animatedProperty.mKeyFrames = KeyFrames::New();
- duration = LoadKeyFrames<Vector3>(cctx.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
+ duration = LoadKeyFrames<Vector3>(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;
}
}
}
-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,
}
};
- auto& resources = cctx.mOutput.mResources;
+ auto& resources = context.mOutput.mResources;
resources.mSkeletons.reserve(doc.mSkins.size());
for(auto& s : doc.mSkins)
std::unique_ptr<IInverseBindMatrixProvider> ibmProvider;
if(s.mInverseBindMatrices)
{
- ibmProvider.reset(new InverseBindMatrixAccessor(*s.mInverseBindMatrices, cctx.mPath));
+ ibmProvider.reset(new InverseBindMatrixAccessor(*s.mInverseBindMatrices, context.mPath));
}
else
{
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);
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");
+ }
}
}
}
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
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
bool mNeedAlbedoTexture = true;
bool mNeedMetallicRoughnessTexture = true;
bool mNeedNormalTexture = true;
+ bool mDoubleSided = false;
std::vector<TextureStage> mTextureStages;
};
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)
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();
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);
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);
textures = newTextureSet;
}
- renderer.SetTextures(textures);
-
- actor.SetProperty(Actor::Property::COLOR, mColor);
-
- actor.RegisterProperty("uHasVertexColor", static_cast<float>(mesh.first.mColors.IsDefined()));
+ renderer.RegisterProperty("uHasVertexColor", static_cast<float>(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;
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);
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)
bool mIsVisible = true;
- std::unique_ptr<Renderable> mRenderable;
+ std::vector<std::unique_ptr<Renderable>> mRenderables;
std::unique_ptr<CustomizationDefinition> mCustomization;
std::vector<Extra> mExtras;
std::vector<ConstraintDefinition> mConstraints;
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;
/**
* @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;
} // namespace Scene3D
} // namespace Dali
-#endif //DALI_SCENE3D_LOADER_NODE_DEFINITION_H_
+#endif // DALI_SCENE3D_LOADER_NODE_DEFINITION_H_
void Start(const NodeDefinition& n)
{
- if(n.mRenderable)
+ for(auto& renderable : n.mRenderables)
{
- n.mRenderable->RegisterResources(counter);
+ renderable->RegisterResources(counter);
}
}
NodeDefinition* SceneDefinition::AddNode(std::unique_ptr<NodeDefinition>&& nodeDef)
{
- if(FindNode(nodeDef->mName))
+ if(!nodeDef->mName.empty() && FindNode(nodeDef->mName))
{
return nullptr;
}
std::map<Index, std::map<Index, std::vector<Index*>>> 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)
{
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);
}
}
}
std::map<Index, std::map<std::string, std::vector<Index*>>> 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)
{
}
}
-uint64_t HashNode(const NodeDefinition& nodeDef, const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
+uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
{
Hash hash;
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
// INTERNAL INCLUDES
#include "dali-scene3d/public-api/api.h"
#include "dali-scene3d/public-api/loader/index.h"
+#include <dali-scene3d/public-api/loader/node-definition.h>
// EXTERNAL INCLUDER
#include <memory>
* 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;