+ rawData.mBlendShapeData = Devel::PixelBuffer::Convert(geometryPixelBuffer);
+ }
+}
+
+constexpr uint32_t MINIMUM_SHADER_VERSION_SUPPORT_VERTEX_ID = 300;
+
+} // namespace
+
+MeshDefinition::SparseBlob::SparseBlob(const Blob& indices, const Blob& values, uint32_t count)
+: mIndices{indices},
+ mValues{values},
+ mCount{count}
+{
+}
+
+MeshDefinition::SparseBlob::SparseBlob(Blob&& indices, Blob&& values, uint32_t count)
+: mIndices(std::move(indices)),
+ mValues(std::move(values)),
+ mCount{count}
+{
+}
+
+MeshDefinition::Accessor::Accessor(const MeshDefinition::Blob& blob,
+ const MeshDefinition::SparseBlob& sparse,
+ Index bufferIndex,
+ bool normalized)
+: mBlob{blob},
+ mSparse{(sparse.mIndices.IsDefined() && sparse.mValues.IsDefined()) ? new SparseBlob{sparse} : nullptr},
+ mBufferIdx(bufferIndex),
+ mNormalized(normalized)
+{
+}
+
+MeshDefinition::Accessor::Accessor(MeshDefinition::Blob&& blob,
+ MeshDefinition::SparseBlob&& sparse,
+ Index bufferIndex,
+ bool normalized)
+: mBlob{std::move(blob)},
+ mSparse{(sparse.mIndices.IsDefined() && sparse.mValues.IsDefined()) ? new SparseBlob{std::move(sparse)} : nullptr},
+ mBufferIdx(bufferIndex),
+ mNormalized(normalized)
+{
+}
+
+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, std::vector<uint32_t>* sparseIndices)
+{
+ DALI_ASSERT_DEBUG(max.size() == min.size() || max.size() * min.size() == 0);
+ const auto numComponents = std::max(min.size(), max.size());
+
+ using ClampFn = void (*)(const float*, const float*, uint32_t, float&);
+ ClampFn clampFn = min.empty() ? (max.empty() ? static_cast<ClampFn>(nullptr) : [](const float* min, const float* max, uint32_t i, float& value) { value = std::min(max[i], value); })
+ : (max.empty() ? [](const float* min, const float* max, uint32_t i, float& value) { value = std::max(min[i], value); }
+ : static_cast<ClampFn>([](const float* min, const float* max, uint32_t i, float& value) { value = std::min(std::max(min[i], value), max[i]); }));
+
+ if(!clampFn)
+ {
+ return;
+ }
+
+ auto end = values + count * numComponents;
+ while(values != end)
+ {
+ auto nextElement = values + numComponents;
+ uint32_t i = 0;
+ while(values != nextElement)
+ {
+ clampFn(min.data(), max.data(), i, *values);
+ ++values;
+ ++i;
+ }
+ }
+}
+
+MeshDefinition::Blob::Blob(uint32_t offset, uint32_t length, uint16_t stride, uint16_t elementSizeHint, const std::vector<float>& min, const std::vector<float>& max)
+: mOffset(offset),
+ mLength(length),
+ mStride(stride),
+ mElementSizeHint(elementSizeHint),
+ mMin(min),
+ mMax(max)
+{
+}
+
+uint32_t MeshDefinition::Blob::GetBufferSize() const
+{
+ return mLength;
+}
+
+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, std::vector<uint32_t>* sparseIndices) const
+{
+ ApplyMinMax(mMin, mMax, count, values, sparseIndices);
+}
+
+void MeshDefinition::RawData::Attrib::AttachBuffer(Geometry& g) const
+{
+ Property::Map attribMap;
+ attribMap[mName] = mType;
+ VertexBuffer attribBuffer = VertexBuffer::New(attribMap);
+ attribBuffer.SetData(mData.data(), mNumElements);
+
+ g.AddVertexBuffer(attribBuffer);
+}
+
+bool MeshDefinition::IsQuad() const
+{
+ return CaseInsensitiveStringCompare(QUAD, mUri);
+}
+
+bool MeshDefinition::IsSkinned() const
+{
+ return !mJoints.empty() && !mWeights.empty();
+}
+
+bool MeshDefinition::HasVertexColor() const
+{
+ return !mColors.empty();
+}
+
+uint32_t MeshDefinition::GetNumberOfJointSets() const
+{
+ uint32_t number = static_cast<uint32_t>(mJoints.size());
+ if(number > MeshDefinition::MAX_NUMBER_OF_JOINT_SETS)
+ {
+ number = MeshDefinition::MAX_NUMBER_OF_JOINT_SETS;
+ }
+ return number;
+}
+
+bool MeshDefinition::HasBlendShapes() const
+{
+ return !mBlendShapes.empty();
+}
+
+void MeshDefinition::RequestNormals()
+{
+ mNormals.mBlob.mLength = mPositions.mBlob.GetBufferSize();
+}
+
+void MeshDefinition::RequestTangents()
+{
+ mTangents.mBlob.mLength = mNormals.mBlob.GetBufferSize();
+}
+
+MeshDefinition::RawData
+MeshDefinition::LoadRaw(const std::string& modelsPath, BufferDefinition::Vector& buffers)
+{
+ RawData raw;
+ if(IsQuad())
+ {
+ return raw;
+ }
+
+ std::string meshPath;
+ meshPath = modelsPath + mUri;
+ std::fstream fileStream;
+ if(!mUri.empty())
+ {
+ fileStream.open(meshPath, std::ios::in | std::ios::binary);
+ if(!fileStream.is_open())
+ {
+ DALI_LOG_ERROR("Fail to open buffer from %s.\n", meshPath.c_str());
+ }