X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-scene3d%2Fpublic-api%2Floader%2Fgltf2-loader.cpp;h=15f207a6294a2a2be05fcaebff2f7f389e6e87aa;hb=6262255ee1dd731f10400d3e2ba7176febf87b62;hp=918bb358e05363b34893cc3d2eef2fd5a64afae8;hpb=9c86dc1ea5d8ec24c79da0abf05c5c23301c8a3a;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-scene3d/public-api/loader/gltf2-loader.cpp b/dali-scene3d/public-api/loader/gltf2-loader.cpp index 918bb35..15f207a 100644 --- a/dali-scene3d/public-api/loader/gltf2-loader.cpp +++ b/dali-scene3d/public-api/loader/gltf2-loader.cpp @@ -14,20 +14,23 @@ * limitations under the License. * */ -#include "dali-scene3d/public-api/loader/gltf2-loader.h" + +// FILE HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include #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" - -#define ENUM_STRING_MAPPING(t, x) \ - { \ -#x, t::x \ - } + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include namespace gt = gltf2; namespace js = json; @@ -48,8 +51,6 @@ 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); -constexpr float DEFAULT_INTENSITY = 0.5f; - const Geometry::Type GLTF2_TO_DALI_PRIMITIVES[]{ Geometry::POINTS, Geometry::LINES, @@ -170,6 +171,19 @@ const auto MATERIAL_PBR_READER = std::move(js::Reader() .Register(*js::MakeProperty("roughnessFactor", js::Read::Number, >::Material::Pbr::mRoughnessFactor)) .Register(*js::MakeProperty("metallicRoughnessTexture", js::ObjectReader::Read, >::Material::Pbr::mMetallicRoughnessTexture))); +const auto MATERIAL_SPECULAR_READER = std::move(js::Reader() + .Register(*js::MakeProperty("specularFactor", js::Read::Number, >::MaterialSpecular::mSpecularFactor)) + .Register(*js::MakeProperty("specularTexture", js::ObjectReader::Read, >::MaterialSpecular::mSpecularTexture)) + .Register(*js::MakeProperty("specularColorFactor", gt::ReadDaliVector, >::MaterialSpecular::mSpecularColorFactor)) + .Register(*js::MakeProperty("specularColorTexture", js::ObjectReader::Read, >::MaterialSpecular::mSpecularColorTexture))); + +const auto MATERIAL_IOR_READER = std::move(js::Reader() + .Register(*js::MakeProperty("ior", js::Read::Number, >::MaterialIor::mIor))); + +const auto MATERIAL_EXTENSION_READER = std::move(js::Reader() + .Register(*js::MakeProperty("KHR_materials_ior", js::ObjectReader::Read, >::MaterialExtensions::mMaterialIor)) + .Register(*js::MakeProperty("KHR_materials_specular", js::ObjectReader::Read, >::MaterialExtensions::mMaterialSpecular))); + const auto MATERIAL_READER = std::move(js::Reader() .Register(*new js::Property("name", js::Read::StringView, >::Material::mName)) .Register(*js::MakeProperty("pbrMetallicRoughness", js::ObjectReader::Read, >::Material::mPbrMetallicRoughness)) @@ -178,7 +192,9 @@ 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)) + .Register(*js::MakeProperty("extensions", js::ObjectReader::Read, >::Material::mMaterialExtensions))); std::map> ReadMeshPrimitiveAttributes(const json_value_s& j) { @@ -409,7 +425,10 @@ SamplerFlags::Type ConvertSampler(const gt::Ref& s) { if(s) { - return (s->mMinFilter < gt::Filter::NEAREST_MIPMAP_NEAREST) ? (s->mMinFilter - gt::Filter::NEAREST) : ((s->mMinFilter - gt::Filter::NEAREST_MIPMAP_NEAREST) + 2) | ((s->mMagFilter - gt::Filter::NEAREST) << SamplerFlags::FILTER_MAG_SHIFT) | (ConvertWrapMode(s->mWrapS) << SamplerFlags::WRAP_S_SHIFT) | (ConvertWrapMode(s->mWrapT) << SamplerFlags::WRAP_T_SHIFT); + return ((s->mMinFilter < gt::Filter::NEAREST_MIPMAP_NEAREST) ? (s->mMinFilter - gt::Filter::NEAREST) : ((s->mMinFilter - gt::Filter::NEAREST_MIPMAP_NEAREST) + 2)) | + ((s->mMagFilter - gt::Filter::NEAREST) << SamplerFlags::FILTER_MAG_SHIFT) | + (ConvertWrapMode(s->mWrapS) << SamplerFlags::WRAP_S_SHIFT) | + (ConvertWrapMode(s->mWrapT) << SamplerFlags::WRAP_T_SHIFT); } else { @@ -422,33 +441,45 @@ SamplerFlags::Type ConvertSampler(const gt::Ref& s) } } -TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm) +TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm, const ImageMetadata& metaData = ImageMetadata()) { - return TextureDefinition{std::string(mm.mTexture->mSource->mUri), ConvertSampler(mm.mTexture->mSampler)}; + return TextureDefinition{std::string(mm.mTexture->mSource->mUri), ConvertSampler(mm.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode}; } -void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials)& outMaterials) +void ConvertMaterial(const gt::Material& material, const std::unordered_map& imageMetaData, decltype(ResourceBundle::mMaterials)& outMaterials) { + auto getTextureMetaData = [](const std::unordered_map& metaData, const gt::TextureInfo& info) { + if(auto search = metaData.find(info.mTexture->mSource->mUri.data()); search != metaData.end()) + { + return search->second; + } + else + { + return ImageMetadata(); + } + }; + MaterialDefinition matDef; - auto& pbr = m.mPbrMetallicRoughness; - if(m.mAlphaMode != gt::AlphaMode::OPAQUE || pbr.mBaseColorFactor.a < 1.f) + auto& pbr = material.mPbrMetallicRoughness; + if(material.mAlphaMode == gt::AlphaMode::BLEND) { + matDef.mIsOpaque = false; matDef.mFlags |= MaterialDefinition::TRANSPARENCY; } - - if(m.mAlphaMode == gt::AlphaMode::MASK) + else if(material.mAlphaMode == gt::AlphaMode::MASK) { - matDef.SetAlphaCutoff(std::min(1.f, std::max(0.f, m.mAlphaCutoff))); + matDef.mIsMask = true; + 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.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mBaseColorTexture)}); + matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mBaseColorTexture, getTextureMetaData(imageMetaData, pbr.mBaseColorTexture))}); // TODO: and there had better be one matDef.mFlags |= semantic; } @@ -464,7 +495,7 @@ void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials) { const auto semantic = MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS; - matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mMetallicRoughnessTexture)}); + matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mMetallicRoughnessTexture, getTextureMetaData(imageMetaData, pbr.mMetallicRoughnessTexture))}); // TODO: and there had better be one matDef.mFlags |= semantic; } @@ -473,11 +504,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, getTextureMetaData(imageMetaData, material.mNormalTexture))}); // TODO: and there had better be one matDef.mFlags |= semantic; } @@ -486,36 +517,61 @@ 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, getTextureMetaData(imageMetaData, 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, getTextureMetaData(imageMetaData, material.mEmissiveTexture))}); // TODO: and there had better be one matDef.mFlags |= semantic; - matDef.mEmissiveFactor = m.mEmissiveFactor; + matDef.mEmissiveFactor = material.mEmissiveFactor; + } + + if(material.mMaterialExtensions.mMaterialIor.mIor < MAXFLOAT) + { + float ior = material.mMaterialExtensions.mMaterialIor.mIor; + matDef.mDielectricSpecular = powf((ior - 1.0f) / (ior + 1.0f), 2.0f); + } + matDef.mSpecularFactor = material.mMaterialExtensions.mMaterialSpecular.mSpecularFactor; + matDef.mSpecularColorFactor = material.mMaterialExtensions.mMaterialSpecular.mSpecularColorFactor; + + if(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture) + { + const auto semantic = MaterialDefinition::SPECULAR; + matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture))}); + matDef.mFlags |= semantic; + } + + if(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture) + { + const auto semantic = MaterialDefinition::SPECULAR_COLOR; + matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture))}); + matDef.mFlags |= semantic; } + 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& imageMetaData = context.mOutput.mSceneMetadata.mImageMetadata; + + auto& outMaterials = context.mOutput.mResources.mMaterials; outMaterials.reserve(doc.mMaterials.size()); for(auto& m : doc.mMaterials) { - ConvertMaterial(m, outMaterials); + ConvertMaterial(m, imageMetaData, outMaterials); } } @@ -572,33 +628,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); + auto& accPositions = *attribs.find(gt::Attribute::POSITION)->second; + meshDefinition.mPositions = ConvertMeshPrimitiveAccessor(accPositions); // glTF2 support vector4 tangent for mesh. // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#meshes-overview - meshDef.mTangentType = Property::VECTOR4; + meshDefinition.mTangentType = Property::VECTOR4; const bool needNormalsTangents = accPositions.mType == gt::AccessorType::VEC3; for(auto& am : ATTRIBUTE_MAPPINGS) @@ -606,14 +662,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) @@ -621,11 +677,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: @@ -634,18 +690,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; @@ -666,44 +722,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); + ConvertMaterial(gt::Material{}, context.mOutput.mSceneMetadata.mImageMetadata, 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) @@ -720,15 +776,16 @@ void ConvertCamera(const gt::Camera& camera, CameraParameters& camParams) else { auto& ortho = camera.mOrthographic; - camParams.orthographicSize = Vector4(-ortho.mXMag, ortho.mXMag, ortho.mYMag, -ortho.mYMag) * .5f; + camParams.orthographicSize = ortho.mYMag * .5f; + camParams.aspectRatio = ortho.mXMag / ortho.mYMag; camParams.zNear = ortho.mZNear; camParams.zFar = ortho.mZFar; } } -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; @@ -763,42 +820,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; - - auto childModel = MakeModelNode(*iPrim, cctx); - - ++meshIdx; - childModel->mMeshIdx = meshIdx; - - child->mRenderable.reset(childModel); + std::unique_ptr renderable; + auto modelRenderable = MakeModelRenderable(mesh.mPrimitives[i], context); + modelRenderable->mMeshIdx = meshIdx + i; - scene.AddNode(std::move(child)); + 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; - 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)); } } @@ -813,13 +855,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()) { @@ -827,7 +869,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; @@ -841,25 +883,33 @@ 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); - - for(uint32_t i = 0, i1 = doc.mScene.GetIndex(); i < i1; ++i) + if(!doc.mScenes.empty()) { - ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel); - } + uint32_t rootSceneIndex = 0u; + if(doc.mScene) + { + rootSceneIndex = doc.mScene.GetIndex(); + } + ConvertSceneNodes(doc.mScenes[rootSceneIndex], context, isMRendererModel); - for(uint32_t i = doc.mScene.GetIndex() + 1; i < doc.mScenes.size(); ++i) - { - ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel); + for(uint32_t i = 0, i1 = rootSceneIndex; i < i1; ++i) + { + ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel); + } + + for(uint32_t i = rootSceneIndex + 1; i < doc.mScenes.size(); ++i) + { + ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel); + } } } @@ -947,9 +997,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()); @@ -980,8 +1030,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; @@ -996,7 +1046,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; @@ -1009,7 +1059,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; @@ -1022,14 +1072,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; } @@ -1049,7 +1099,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, @@ -1091,7 +1141,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) @@ -1099,7 +1149,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 { @@ -1109,14 +1159,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); @@ -1129,12 +1179,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"); + } } } } @@ -1152,6 +1206,9 @@ void SetObjectReaders() js::SetObjectReader(TEXURE_READER); js::SetObjectReader(TEXURE_INFO_READER); js::SetObjectReader(MATERIAL_PBR_READER); + js::SetObjectReader(MATERIAL_SPECULAR_READER); + js::SetObjectReader(MATERIAL_IOR_READER); + js::SetObjectReader(MATERIAL_EXTENSION_READER); js::SetObjectReader(MATERIAL_READER); js::SetObjectReader(MESH_PRIMITIVE_READER); js::SetObjectReader(MESH_READER); @@ -1167,12 +1224,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 = DEFAULT_INTENSITY; - cctx.mOutput.mResources.mEnvironmentMaps.push_back({std::move(envDef), EnvironmentDefinition::Textures()}); + envDef.mIblIntensity = Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity(); + context.mOutput.mResources.mEnvironmentMaps.push_back({std::move(envDef), EnvironmentDefinition::Textures()}); } } // namespace @@ -1223,18 +1280,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