Merge "Compute min/max value if min/max is not defined." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene-loader / public-api / mesh-definition.cpp
index de37e30..75b19a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -454,6 +454,21 @@ MeshDefinition::Accessor::Accessor(const MeshDefinition::Blob&       blob,
 {
 }
 
+void MeshDefinition::Blob::ComputeMinMax(std::vector<float>& min, std::vector<float>& max, uint32_t numComponents, uint32_t count, const float* values)
+{
+  min.assign(numComponents, MAXFLOAT);
+  max.assign(numComponents, -MAXFLOAT);
+  for(uint32_t i = 0; i < count; ++i)
+  {
+    for(uint32_t j = 0; j < numComponents; ++j)
+    {
+      min[j] = std::min(min[j], *values);
+      max[j] = std::max(max[j], *values);
+      values++;
+    }
+  }
+}
+
 void MeshDefinition::Blob::ApplyMinMax(const std::vector<float>& min, const std::vector<float>& max, uint32_t count, float* values)
 {
   DALI_ASSERT_DEBUG(max.size() == min.size() || max.size() * min.size() == 0);
@@ -504,6 +519,11 @@ uint32_t MeshDefinition::Blob::GetBufferSize() const
   return IsConsecutive() ? mLength : (mLength * mElementSizeHint / mStride);
 }
 
+void MeshDefinition::Blob::ComputeMinMax(uint32_t numComponents, uint32_t count, float* values)
+{
+  ComputeMinMax(mMin, mMax, numComponents, count, values);
+}
+
 void MeshDefinition::Blob::ApplyMinMax(uint32_t count, float* values) const
 {
   ApplyMinMax(mMin, mMax, count, values);
@@ -545,7 +565,7 @@ void MeshDefinition::RequestTangents()
 }
 
 MeshDefinition::RawData
-MeshDefinition::LoadRaw(const std::string& modelsPath) const
+MeshDefinition::LoadRaw(const std::string& modelsPath)
 {
   RawData raw;
   if(IsQuad())
@@ -613,7 +633,14 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) const
     }
 
     uint32_t numVector3 = bufferSize / sizeof(Vector3);
-    mPositions.mBlob.ApplyMinMax(numVector3, reinterpret_cast<float*>(buffer.data()));
+    if(mPositions.mBlob.mMin.size() != 3u || mPositions.mBlob.mMax.size() != 3u)
+    {
+      mPositions.mBlob.ComputeMinMax(3u, numVector3, reinterpret_cast<float*>(buffer.data()));
+    }
+    else
+    {
+      mPositions.mBlob.ApplyMinMax(numVector3, reinterpret_cast<float*>(buffer.data()));
+    }
 
     if(HasBlendShapes())
     {
@@ -681,8 +708,9 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) const
 
   if(mTangents.IsDefined())
   {
-    DALI_ASSERT_ALWAYS(((mTangents.mBlob.mLength % sizeof(Vector3) == 0) ||
-                        mTangents.mBlob.mStride >= sizeof(Vector3)) &&
+    uint32_t propertySize = (mTangentType == Property::VECTOR4) ? sizeof(Vector4) : sizeof(Vector3);
+    DALI_ASSERT_ALWAYS(((mTangents.mBlob.mLength % propertySize == 0) ||
+                        mTangents.mBlob.mStride >= propertySize) &&
                        "Tangents buffer length not a multiple of element size");
     const auto           bufferSize = mTangents.mBlob.GetBufferSize();
     std::vector<uint8_t> buffer(bufferSize);
@@ -690,10 +718,9 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) const
     {
       ExceptionFlinger(ASSERT_LOCATION) << "Failed to read tangents from '" << meshPath << "'.";
     }
+    mTangents.mBlob.ApplyMinMax(bufferSize / propertySize, reinterpret_cast<float*>(buffer.data()));
 
-    mTangents.mBlob.ApplyMinMax(bufferSize / sizeof(Vector3), reinterpret_cast<float*>(buffer.data()));
-
-    raw.mAttribs.push_back({"aTangent", Property::VECTOR3, static_cast<uint32_t>(bufferSize / sizeof(Vector3)), std::move(buffer)});
+    raw.mAttribs.push_back({"aTangent", mTangentType, static_cast<uint32_t>(bufferSize / propertySize), std::move(buffer)});
   }
   else if(mTangents.mBlob.mLength != 0 && hasNormals && isTriangles)
   {
@@ -701,6 +728,27 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) const
     hasUvs ? GenerateTangentsWithUvs(raw) : GenerateTangents(raw);
   }
 
+  if(mColors.IsDefined())
+  {
+    uint32_t propertySize = mColors.mBlob.mElementSizeHint;
+    Property::Type propertyType = (propertySize == sizeof(Vector4)) ? Property::VECTOR4 : ((propertySize == sizeof(Vector3)) ? Property::VECTOR3 : Property::NONE);
+    if(propertyType != Property::NONE)
+    {
+      DALI_ASSERT_ALWAYS(((mColors.mBlob.mLength % propertySize == 0) ||
+                          mColors.mBlob.mStride >= propertySize) &&
+                         "Colors buffer length not a multiple of element size");
+      const auto           bufferSize = mColors.mBlob.GetBufferSize();
+      std::vector<uint8_t> buffer(bufferSize);
+      if(!ReadAccessor(mColors, binFile, buffer.data()))
+      {
+        ExceptionFlinger(ASSERT_LOCATION) << "Failed to read colors from '" << meshPath << "'.";
+      }
+      mColors.mBlob.ApplyMinMax(bufferSize / propertySize, reinterpret_cast<float*>(buffer.data()));
+
+      raw.mAttribs.push_back({"aVertexColor", propertyType, static_cast<uint32_t>(bufferSize / propertySize), std::move(buffer)});
+    }
+  }
+
   if(IsSkinned())
   {
     if(MaskMatch(mFlags, U16_JOINT_IDS))