Fix gltf animation's 0 frame behavior.
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / gltf2-loader.cpp
index 1c633c8..532bbb6 100644 (file)
 #include <dali-scene3d/public-api/loader/gltf2-loader.h>
 
 // EXTERNAL INCLUDES
+#include <dali/devel-api/threading/mutex.h>
 #include <dali/integration-api/debug.h>
 #include <dali/public-api/images/image-operations.h>
 #include <dali/public-api/math/quaternion.h>
-#include <dali/devel-api/threading/mutex.h>
 #include <memory>
 
 // INTERNAL INCLUDES
@@ -467,7 +467,7 @@ SamplerFlags::Type ConvertSampler(const gt::Ref<gt::Sampler>& sampler)
 TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm, ConversionContext& context, const ImageMetadata& metaData = ImageMetadata())
 {
   TextureDefinition textureDefinition;
-  std::string uri = std::string(mm.mTexture->mSource->mUri);
+  std::string       uri = std::string(mm.mTexture->mSource->mUri);
   if(uri.empty())
   {
     uint32_t bufferIndex = mm.mTexture->mSource->mBufferView->mBuffer.GetIndex();
@@ -478,7 +478,7 @@ TextureDefinition ConvertTextureInfo(const gt::TextureInfo& mm, ConversionContex
       stream.seekg(mm.mTexture->mSource->mBufferView->mByteOffset, stream.beg);
       std::vector<uint8_t> dataBuffer;
       dataBuffer.resize(mm.mTexture->mSource->mBufferView->mByteLength);
-      stream.read(reinterpret_cast<char*>(dataBuffer.data()), mm.mTexture->mSource->mBufferView->mByteLength);
+      stream.read(reinterpret_cast<char*>(dataBuffer.data()), static_cast<std::streamsize>(static_cast<size_t>(mm.mTexture->mSource->mBufferView->mByteLength)));
       return TextureDefinition{std::move(dataBuffer), ConvertSampler(mm.mTexture->mSampler), metaData.mMinSize, metaData.mSamplingMode};
     }
     return TextureDefinition();
@@ -669,7 +669,7 @@ MeshDefinition::Accessor ConvertMeshPrimitiveAccessor(const gt::Accessor& acc)
                                    acc.mMin,
                                    acc.mMax}),
     std::move(sparseBlob),
-    acc.mBufferView->mBuffer.GetIndex()};
+    acc.mBufferView ? acc.mBufferView->mBuffer.GetIndex() : 0};
 }
 
 void ConvertMeshes(const gt::Document& doc, ConversionContext& context)
@@ -974,7 +974,7 @@ void LoadDataFromAccessor(ConversionContext& context, uint32_t bufferIndex, Vect
   auto& stream = buffer.GetBufferStream();
   stream.clear();
   stream.seekg(offset, stream.beg);
-  stream.read(reinterpret_cast<char*>(dataBuffer.Begin()), size);
+  stream.read(reinterpret_cast<char*>(dataBuffer.Begin()), static_cast<std::streamsize>(static_cast<size_t>(size)));
 }
 
 template<typename T>
@@ -988,6 +988,7 @@ float LoadDataFromAccessors(ConversionContext& context, const gltf2::Accessor& i
 
   LoadDataFromAccessor<float>(context, output.mBufferView->mBuffer.GetIndex(), inputDataBuffer, input.mBufferView->mByteOffset + input.mByteOffset, inputDataBufferSize);
   LoadDataFromAccessor<T>(context, output.mBufferView->mBuffer.GetIndex(), outputDataBuffer, output.mBufferView->mByteOffset + output.mByteOffset, outputDataBufferSize);
+  ApplyAccessorMinMax(input, reinterpret_cast<float*>(inputDataBuffer.begin()));
   ApplyAccessorMinMax(output, reinterpret_cast<float*>(outputDataBuffer.begin()));
 
   return inputDataBuffer[input.mCount - 1u];
@@ -1004,6 +1005,12 @@ float LoadKeyFrames(ConversionContext& context, const gt::Animation::Channel& ch
 
   const float duration = std::max(LoadDataFromAccessors<T>(context, input, output, inputDataBuffer, outputDataBuffer), AnimationDefinition::MIN_DURATION_SECONDS);
 
+  // Set first frame value as first keyframe (gltf animation spec)
+  if(input.mCount > 0 && !Dali::EqualsZero(inputDataBuffer[0]))
+  {
+    keyFrames.Add(0.0f, outputDataBuffer[0]);
+  }
+
   for(uint32_t i = 0; i < input.mCount; ++i)
   {
     keyFrames.Add(inputDataBuffer[i] / duration, outputDataBuffer[i]);
@@ -1020,7 +1027,7 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gt::Animation::C
   Vector<float> inputDataBuffer;
   Vector<float> outputDataBuffer;
 
-  const float duration = LoadDataFromAccessors<float>(context, input, output, inputDataBuffer, outputDataBuffer);
+  const float duration = std::max(LoadDataFromAccessors<float>(context, input, output, inputDataBuffer, outputDataBuffer), AnimationDefinition::MIN_DURATION_SECONDS);
 
   char        weightNameBuffer[32];
   auto        prefixSize    = snprintf(weightNameBuffer, sizeof(weightNameBuffer), "%s[", BLEND_SHAPE_WEIGHTS_UNIFORM.c_str());
@@ -1035,6 +1042,13 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gt::Animation::C
     animatedProperty.mPropertyName = std::string(weightNameBuffer);
 
     animatedProperty.mKeyFrames = KeyFrames::New();
+
+    // Set first frame value as first keyframe (gltf animation spec)
+    if(input.mCount > 0 && !Dali::EqualsZero(inputDataBuffer[0]))
+    {
+      animatedProperty.mKeyFrames.Add(0.0f, outputDataBuffer[weightIndex]);
+    }
+
     for(uint32_t i = 0; i < input.mCount; ++i)
     {
       animatedProperty.mKeyFrames.Add(inputDataBuffer[i] / duration, outputDataBuffer[i * endWeightIndex + weightIndex]);
@@ -1178,7 +1192,7 @@ void ProcessSkins(const gt::Document& doc, ConversionContext& context)
 
     virtual void Provide(Matrix& ibm) override
     {
-      DALI_ASSERT_ALWAYS(mStream.read(reinterpret_cast<char*>(ibm.AsFloat()), mElementSizeBytes));
+      DALI_ASSERT_ALWAYS(mStream.read(reinterpret_cast<char*>(ibm.AsFloat()), static_cast<std::streamsize>(static_cast<size_t>(mElementSizeBytes))));
     }
   };