X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-scene3d%2Fpublic-api%2Floader%2Fgltf2-loader.cpp;h=69bcd515f2e58a2ddee693437a90f273295149c9;hb=3da64a8d34ca7d92e78f018b583b8a15a52816bf;hp=6d209d24232014113e50649f67c5197cfff165f1;hpb=9660fccbe1c9b4a902a236eeb5b2988b94c64c1d;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 6d209d2..69bcd51 100644 --- a/dali-scene3d/public-api/loader/gltf2-loader.cpp +++ b/dali-scene3d/public-api/loader/gltf2-loader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,11 @@ #include // EXTERNAL INCLUDES +#include #include #include #include -#include -#include +#include // INTERNAL INCLUDES #include @@ -407,9 +407,31 @@ struct ConversionContext NodeIndexMapper mNodeIndices; }; -SamplerFlags::Type ConvertWrapMode(gt::Wrap::Type w) +void ConvertBuffer(const gt::Buffer& buffer, decltype(ResourceBundle::mBuffers)& outBuffers, const std::string& resourcePath) +{ + BufferDefinition bufferDefinition; + + bufferDefinition.mResourcePath = resourcePath; + bufferDefinition.mUri = buffer.mUri; + bufferDefinition.mByteLength = buffer.mByteLength; + + outBuffers.emplace_back(std::move(bufferDefinition)); +} + +void ConvertBuffers(const gt::Document& doc, ConversionContext& context) { - switch(w) + auto& outBuffers = context.mOutput.mResources.mBuffers; + outBuffers.reserve(doc.mBuffers.size()); + + for(auto& buffer : doc.mBuffers) + { + ConvertBuffer(buffer, outBuffers, context.mPath); + } +} + +SamplerFlags::Type ConvertWrapMode(gt::Wrap::Type wrapMode) +{ + switch(wrapMode) { case gt::Wrap::REPEAT: return SamplerFlags::WRAP_REPEAT; @@ -422,14 +444,14 @@ SamplerFlags::Type ConvertWrapMode(gt::Wrap::Type w) } } -SamplerFlags::Type ConvertSampler(const gt::Ref& s) +SamplerFlags::Type ConvertSampler(const gt::Ref& sampler) { - if(s) + if(sampler) { - 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 ((sampler->mMinFilter < gt::Filter::NEAREST_MIPMAP_NEAREST) ? (sampler->mMinFilter - gt::Filter::NEAREST) : ((sampler->mMinFilter - gt::Filter::NEAREST_MIPMAP_NEAREST) + 2)) | + ((sampler->mMagFilter - gt::Filter::NEAREST) << SamplerFlags::FILTER_MAG_SHIFT) | + (ConvertWrapMode(sampler->mWrapS) << SamplerFlags::WRAP_S_SHIFT) | + (ConvertWrapMode(sampler->mWrapT) << SamplerFlags::WRAP_T_SHIFT); } else { @@ -442,22 +464,42 @@ SamplerFlags::Type ConvertSampler(const gt::Ref& s) } } -TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm, const ImageMetadata& metaData = ImageMetadata()) +TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm, ConversionContext& context, const ImageMetadata& metaData = ImageMetadata()) { - return TextureDefinition{std::string(mm.mTexture->mSource->mUri), ConvertSampler(mm.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode}; + TextureDefinition textureDefinition; + std::string uri = std::string(mm.mTexture->mSource->mUri); + if(uri.empty()) + { + uint32_t bufferIndex = mm.mTexture->mSource->mBufferView->mBuffer.GetIndex(); + if(bufferIndex != INVALID_INDEX && context.mOutput.mResources.mBuffers[bufferIndex].IsAvailable()) + { + auto& stream = context.mOutput.mResources.mBuffers[bufferIndex].GetBufferStream(); + stream.clear(); + stream.seekg(mm.mTexture->mSource->mBufferView->mByteOffset, stream.beg); + std::vector dataBuffer; + dataBuffer.resize(mm.mTexture->mSource->mBufferView->mByteLength); + stream.read(reinterpret_cast(dataBuffer.data()), static_cast(static_cast(mm.mTexture->mSource->mBufferView->mByteLength))); + return TextureDefinition{std::move(dataBuffer), ConvertSampler(mm.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode}; + } + return TextureDefinition(); + } + else + { + return TextureDefinition{uri, ConvertSampler(mm.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode}; + } } -void ConvertMaterial(const gt::Material& material, const std::unordered_map& imageMetaData, decltype(ResourceBundle::mMaterials)& outMaterials) +void ConvertMaterial(const gt::Material& material, const std::unordered_map& imageMetaData, decltype(ResourceBundle::mMaterials)& outMaterials, ConversionContext& context) { auto getTextureMetaData = [](const std::unordered_map& metaData, const gt::TextureInfo& info) { - if(auto search = metaData.find(info.mTexture->mSource->mUri.data()); search != metaData.end()) - { - return search->second; - } - else + if(!info.mTexture->mSource->mUri.empty()) { - return ImageMetadata(); + if(auto search = metaData.find(info.mTexture->mSource->mUri.data()); search != metaData.end()) + { + return search->second; + } } + return ImageMetadata(); }; MaterialDefinition matDef; @@ -480,7 +522,7 @@ void ConvertMaterial(const gt::Material& material, const std::unordered_map(acc.GetElementSizeBytes()), acc.mMin, acc.mMax}), - std::move(sparseBlob)}; + std::move(sparseBlob), + acc.mBufferView ? acc.mBufferView->mBuffer.GetIndex() : 0}; } void ConvertMeshes(const gt::Document& doc, ConversionContext& context) @@ -648,7 +691,6 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& context) MeshDefinition meshDefinition; 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; @@ -663,14 +705,14 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& context) auto iFind = attribs.find(am.mType); if(iFind != attribs.end()) { - 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) { 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); + meshDefinition.mFlags |= (iFind->second->mComponentType == gt::Component::UNSIGNED_BYTE) * MeshDefinition::U8_JOINT_IDS; + DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U16_JOINT_IDS) || MaskMatch(meshDefinition.mFlags, MeshDefinition::U8_JOINT_IDS) || iFind->second->mComponentType == gt::Component::FLOAT); } } else if(needNormalsTangents) @@ -695,7 +737,8 @@ void ConvertMeshes(const gt::Document& doc, ConversionContext& context) { 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); + meshDefinition.mFlags |= (primitive.mIndices->mComponentType == gt::Component::UNSIGNED_BYTE) * MeshDefinition::U8_INDICES; + DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U32_INDICES) || MaskMatch(meshDefinition.mFlags, MeshDefinition::U8_INDICES) || primitive.mIndices->mComponentType == gt::Component::UNSIGNED_SHORT); } if(!primitive.mTargets.empty()) @@ -752,7 +795,7 @@ ModelRenderable* MakeModelRenderable(const gt::Mesh::Primitive& prim, Conversion auto& outMaterials = context.mOutput.mResources.mMaterials; context.mDefaultMaterial = outMaterials.size(); - ConvertMaterial(gt::Material{}, context.mOutput.mSceneMetadata.mImageMetadata, outMaterials); + ConvertMaterial(gt::Material{}, context.mOutput.mSceneMetadata.mImageMetadata, outMaterials, context); } materialIdx = context.mDefaultMaterial; @@ -915,22 +958,27 @@ void ConvertNodes(const gt::Document& doc, ConversionContext& context, bool isMR } template -void LoadDataFromAccessor(const std::string& path, Vector& dataBuffer, uint32_t offset, uint32_t size) +void LoadDataFromAccessor(ConversionContext& context, uint32_t bufferIndex, Vector& dataBuffer, uint32_t offset, uint32_t size) { - std::ifstream animationBinaryFile(path, std::ifstream::binary); - - if(!animationBinaryFile.is_open()) + if(bufferIndex >= context.mOutput.mResources.mBuffers.size()) { - throw std::runtime_error("Failed to load " + path); + DALI_LOG_ERROR("Invailid buffer index\n"); + return; } - animationBinaryFile.seekg(offset); - animationBinaryFile.read(reinterpret_cast(dataBuffer.Begin()), size); - animationBinaryFile.close(); + auto& buffer = context.mOutput.mResources.mBuffers[bufferIndex]; + if(!buffer.IsAvailable()) + { + DALI_LOG_ERROR("Failed to load from buffer stream.\n"); + } + auto& stream = buffer.GetBufferStream(); + stream.clear(); + stream.seekg(offset, stream.beg); + stream.read(reinterpret_cast(dataBuffer.Begin()), static_cast(static_cast(size))); } template -float LoadDataFromAccessors(const std::string& path, const gltf2::Accessor& input, const gltf2::Accessor& output, Vector& inputDataBuffer, Vector& outputDataBuffer) +float LoadDataFromAccessors(ConversionContext& context, const gltf2::Accessor& input, const gltf2::Accessor& output, Vector& inputDataBuffer, Vector& outputDataBuffer) { inputDataBuffer.Resize(input.mCount); outputDataBuffer.Resize(output.mCount); @@ -938,15 +986,15 @@ float LoadDataFromAccessors(const std::string& path, const gltf2::Accessor& inpu const uint32_t inputDataBufferSize = input.GetBytesLength(); const uint32_t outputDataBufferSize = output.GetBytesLength(); - LoadDataFromAccessor(path + std::string(input.mBufferView->mBuffer->mUri), inputDataBuffer, input.mBufferView->mByteOffset + input.mByteOffset, inputDataBufferSize); - LoadDataFromAccessor(path + std::string(output.mBufferView->mBuffer->mUri), outputDataBuffer, output.mBufferView->mByteOffset + output.mByteOffset, outputDataBufferSize); + LoadDataFromAccessor(context, output.mBufferView->mBuffer.GetIndex(), inputDataBuffer, input.mBufferView->mByteOffset + input.mByteOffset, inputDataBufferSize); + LoadDataFromAccessor(context, output.mBufferView->mBuffer.GetIndex(), outputDataBuffer, output.mBufferView->mByteOffset + output.mByteOffset, outputDataBufferSize); ApplyAccessorMinMax(output, reinterpret_cast(outputDataBuffer.begin())); return inputDataBuffer[input.mCount - 1u]; } template -float LoadKeyFrames(const std::string& path, const gt::Animation::Channel& channel, KeyFrames& keyFrames, gt::Animation::Channel::Target::Type type) +float LoadKeyFrames(ConversionContext& context, const gt::Animation::Channel& channel, KeyFrames& keyFrames, gt::Animation::Channel::Target::Type type) { const gltf2::Accessor& input = *channel.mSampler->mInput; const gltf2::Accessor& output = *channel.mSampler->mOutput; @@ -954,7 +1002,7 @@ float LoadKeyFrames(const std::string& path, const gt::Animation::Channel& chann Vector inputDataBuffer; Vector outputDataBuffer; - const float duration = LoadDataFromAccessors(path, input, output, inputDataBuffer, outputDataBuffer); + const float duration = std::max(LoadDataFromAccessors(context, input, output, inputDataBuffer, outputDataBuffer), AnimationDefinition::MIN_DURATION_SECONDS); for(uint32_t i = 0; i < input.mCount; ++i) { @@ -964,7 +1012,7 @@ float LoadKeyFrames(const std::string& path, const gt::Animation::Channel& chann return duration; } -float LoadBlendShapeKeyFrames(const std::string& path, const gt::Animation::Channel& channel, Index nodeIndex, uint32_t& propertyIndex, std::vector& properties) +float LoadBlendShapeKeyFrames(ConversionContext& context, const gt::Animation::Channel& channel, Index nodeIndex, uint32_t& propertyIndex, std::vector& properties) { const gltf2::Accessor& input = *channel.mSampler->mInput; const gltf2::Accessor& output = *channel.mSampler->mOutput; @@ -972,7 +1020,7 @@ float LoadBlendShapeKeyFrames(const std::string& path, const gt::Animation::Chan Vector inputDataBuffer; Vector outputDataBuffer; - const float duration = LoadDataFromAccessors(path, input, output, inputDataBuffer, outputDataBuffer); + const float duration = LoadDataFromAccessors(context, input, output, inputDataBuffer, outputDataBuffer); char weightNameBuffer[32]; auto prefixSize = snprintf(weightNameBuffer, sizeof(weightNameBuffer), "%s[", BLEND_SHAPE_WEIGHTS_UNIFORM.c_str()); @@ -1030,8 +1078,8 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& context) Index propertyIndex = 0u; for(const auto& channel : animation.mChannels) { - Index nodeIndex = context.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex()); - float duration = 0.f; + Index nodeIndex = context.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex()); + float duration = 0.f; switch(channel.mTarget.mPath) { @@ -1043,7 +1091,7 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& context) animatedProperty.mPropertyName = POSITION_PROPERTY; animatedProperty.mKeyFrames = KeyFrames::New(); - duration = LoadKeyFrames(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); + duration = LoadKeyFrames(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); animatedProperty.mTimePeriod = {0.f, duration}; break; @@ -1056,7 +1104,7 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& context) animatedProperty.mPropertyName = ORIENTATION_PROPERTY; animatedProperty.mKeyFrames = KeyFrames::New(); - duration = LoadKeyFrames(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); + duration = LoadKeyFrames(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); animatedProperty.mTimePeriod = {0.f, duration}; break; @@ -1069,14 +1117,14 @@ void ConvertAnimations(const gt::Document& doc, ConversionContext& context) animatedProperty.mPropertyName = SCALE_PROPERTY; animatedProperty.mKeyFrames = KeyFrames::New(); - duration = LoadKeyFrames(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); + duration = LoadKeyFrames(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath); animatedProperty.mTimePeriod = {0.f, duration}; break; } case gt::Animation::Channel::Target::WEIGHTS: { - duration = LoadBlendShapeKeyFrames(context.mPath, channel, nodeIndex, propertyIndex, animationDef.mProperties); + duration = LoadBlendShapeKeyFrames(context, channel, nodeIndex, propertyIndex, animationDef.mProperties); break; } @@ -1111,22 +1159,26 @@ void ProcessSkins(const gt::Document& doc, ConversionContext& context) struct InverseBindMatrixAccessor : public IInverseBindMatrixProvider { - std::ifstream mStream; + std::istream& mStream; const uint32_t mElementSizeBytes; - InverseBindMatrixAccessor(const gt::Accessor& accessor, const std::string& path) - : mStream(path + std::string(accessor.mBufferView->mBuffer->mUri), std::ios::binary), + InverseBindMatrixAccessor(const gt::Accessor& accessor, ConversionContext& context) + : mStream(context.mOutput.mResources.mBuffers[accessor.mBufferView->mBuffer.GetIndex()].GetBufferStream()), mElementSizeBytes(accessor.GetElementSizeBytes()) { - DALI_ASSERT_ALWAYS(mStream); DALI_ASSERT_DEBUG(accessor.mType == gt::AccessorType::MAT4 && accessor.mComponentType == gt::Component::FLOAT); - mStream.seekg(accessor.mBufferView->mByteOffset + accessor.mByteOffset); + if(!mStream.rdbuf()->in_avail()) + { + DALI_LOG_ERROR("Failed to load from stream\n"); + } + mStream.clear(); + mStream.seekg(accessor.mBufferView->mByteOffset + accessor.mByteOffset, mStream.beg); } virtual void Provide(Matrix& ibm) override { - DALI_ASSERT_ALWAYS(mStream.read(reinterpret_cast(ibm.AsFloat()), mElementSizeBytes)); + DALI_ASSERT_ALWAYS(mStream.read(reinterpret_cast(ibm.AsFloat()), static_cast(static_cast(mElementSizeBytes)))); } }; @@ -1141,12 +1193,12 @@ void ProcessSkins(const gt::Document& doc, ConversionContext& context) auto& resources = context.mOutput.mResources; resources.mSkeletons.reserve(doc.mSkins.size()); - for(auto& s : doc.mSkins) + for(auto& skin : doc.mSkins) { std::unique_ptr ibmProvider; - if(s.mInverseBindMatrices) + if(skin.mInverseBindMatrices) { - ibmProvider.reset(new InverseBindMatrixAccessor(*s.mInverseBindMatrices, context.mPath)); + ibmProvider.reset(new InverseBindMatrixAccessor(*skin.mInverseBindMatrices, context)); } else { @@ -1154,16 +1206,16 @@ void ProcessSkins(const gt::Document& doc, ConversionContext& context) } SkeletonDefinition skeleton; - if(s.mSkeleton.GetIndex() != INVALID_INDEX) + if(skin.mSkeleton.GetIndex() != INVALID_INDEX) { - skeleton.mRootNodeIdx = context.mNodeIndices.GetRuntimeId(s.mSkeleton.GetIndex()); + skeleton.mRootNodeIdx = context.mNodeIndices.GetRuntimeId(skin.mSkeleton.GetIndex()); } - skeleton.mJoints.resize(s.mJoints.size()); + skeleton.mJoints.resize(skin.mJoints.size()); auto iJoint = skeleton.mJoints.begin(); - for(auto& j : s.mJoints) + for(auto& joint : skin.mJoints) { - iJoint->mNodeIdx = context.mNodeIndices.GetRuntimeId(j.GetIndex()); + iJoint->mNodeIdx = context.mNodeIndices.GetRuntimeId(joint.GetIndex()); ibmProvider->Provide(iJoint->mInverseBindMatrix); @@ -1289,6 +1341,7 @@ void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactor auto path = url.substr(0, url.rfind('/') + 1); ConversionContext context{params, path, INVALID_INDEX}; + ConvertBuffers(doc, context); ConvertMaterials(doc, context); ConvertMeshes(doc, context); ConvertNodes(doc, context, isMRendererModel);