X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-scene3d%2Fpublic-api%2Floader%2Fmesh-definition.cpp;h=6cc3d6a11de22ed2b9fb16a1b5634ba59684034d;hb=9bbca96c9151fb1a96b47e17f09c720b7c05adc2;hp=f7c606ef495243affa1f35836fc0cf06c9e6271c;hpb=b4b0e14f550ed243a65d56e2ba1eccc66c6c3dd9;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-scene3d/public-api/loader/mesh-definition.cpp b/dali-scene3d/public-api/loader/mesh-definition.cpp index f7c606e..6cc3d6a 100644 --- a/dali-scene3d/public-api/loader/mesh-definition.cpp +++ b/dali-scene3d/public-api/loader/mesh-definition.cpp @@ -90,11 +90,11 @@ bool ReadBlob(const MeshDefinition::Blob& descriptor, std::istream& source, uint uint32_t readSize = 0; uint32_t totalSize = (descriptor.mLength / descriptor.mElementSizeHint) * descriptor.mStride; while(readSize < totalSize && - source.read(reinterpret_cast(target), descriptor.mElementSizeHint) && - source.seekg(diff, std::istream::cur)) + source.read(reinterpret_cast(target), descriptor.mElementSizeHint)) { readSize += descriptor.mStride; target += descriptor.mElementSizeHint; + source.seekg(diff, std::istream::cur); } return readSize == totalSize; } @@ -113,7 +113,7 @@ void ReadValues(const std::vector& valuesBuffer, const std::vector* sparseIndices) { bool success = false; @@ -152,31 +152,63 @@ bool ReadAccessor(const MeshDefinition::Accessor& accessor, std::istream& source return false; } + // If non-null sparse indices vector, prepare it for output + if(sparseIndices) + { + sparseIndices->resize(accessor.mSparse->mCount); + } + switch(indices.mElementSizeHint) { case 1u: { ReadValues(valuesBuffer, indicesBuffer, target, accessor.mSparse->mCount, values.mElementSizeHint); + if(sparseIndices) + { + // convert 8-bit indices into 32-bit + std::transform(indicesBuffer.begin(), indicesBuffer.end(), sparseIndices->begin(), [](const uint8_t& value) { return uint32_t(value); }); + } break; } case 2u: { ReadValues(valuesBuffer, indicesBuffer, target, accessor.mSparse->mCount, values.mElementSizeHint); + if(sparseIndices) + { + // convert 16-bit indices into 32-bit + std::transform(reinterpret_cast(indicesBuffer.data()), + reinterpret_cast(indicesBuffer.data()) + accessor.mSparse->mCount, + sparseIndices->begin(), + [](const uint16_t& value) { + return uint32_t(value); + }); + } break; } case 4u: { ReadValues(valuesBuffer, indicesBuffer, target, accessor.mSparse->mCount, values.mElementSizeHint); + if(sparseIndices) + { + std::copy(indicesBuffer.begin(), indicesBuffer.end(), reinterpret_cast(sparseIndices->data())); + } break; } default: + { DALI_ASSERT_DEBUG(!"Unsupported type for an index"); + } } } return success; } +bool ReadAccessor(const MeshDefinition::Accessor& accessor, std::istream& source, uint8_t* target) +{ + return ReadAccessor(accessor, source, target, nullptr); +} + template void ReadJointAccessor(MeshDefinition::RawData& raw, const MeshDefinition::Accessor& accessor, std::istream& source, const std::string& meshPath) { @@ -211,6 +243,41 @@ void ReadJointAccessor(MeshDefinition::RawData& raw, const MeshDefinition::Acces raw.mAttribs.push_back({"aJoints", Property::VECTOR4, static_cast(outBufferSize / sizeof(Vector4)), std::move(buffer)}); } +template +void ReadWeightAccessor(MeshDefinition::RawData& raw, const MeshDefinition::Accessor& accessor, std::istream& source, const std::string& meshPath) +{ + constexpr auto sizeofBlobUnit = sizeof(T) * 4; + + DALI_ASSERT_ALWAYS(((accessor.mBlob.mLength % sizeofBlobUnit == 0) || + accessor.mBlob.mStride >= sizeofBlobUnit) && + "weights buffer length not a multiple of element size"); + const auto inBufferSize = accessor.mBlob.GetBufferSize(); + const auto outBufferSize = (sizeof(Vector4) / sizeofBlobUnit) * inBufferSize; + + std::vector buffer(outBufferSize); + auto inBuffer = buffer.data() + outBufferSize - inBufferSize; + if(!ReadAccessor(accessor, source, inBuffer)) + { + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read weights from '" << meshPath << "'."; + } + + if constexpr(sizeofBlobUnit != sizeof(Vector4)) + { + auto floats = reinterpret_cast(buffer.data()); + const auto end = inBuffer + inBufferSize; + while(inBuffer != end) + { + const auto value = *reinterpret_cast(inBuffer); + // Normalize weight value. value /= 255 for uint8_t weight, and value /= 65535 for uint16_t weight. + *floats = static_cast(value) / static_cast((1 << (sizeof(T) * 8)) - 1); + + inBuffer += sizeof(T); + ++floats; + } + } + raw.mAttribs.push_back({"aWeights", Property::VECTOR4, static_cast(outBufferSize / sizeof(Vector4)), std::move(buffer)}); +} + template> bool GenerateNormals(MeshDefinition::RawData& raw) { @@ -382,7 +449,7 @@ void CalculateTextureSize(uint32_t totalTextureSize, uint32_t& textureWidth, uin void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, const std::vector& blendShapes, uint32_t numberOfVertices, float& blendShapeUnnormalizeFactor, BufferDefinition::Vector& buffers) { uint32_t geometryBufferIndex = 0u; - float maxDistance = 0.f; + float maxDistanceSquared = 0.f; Vector3* geometryBufferV3 = reinterpret_cast(geometryBuffer); for(const auto& blendShape : blendShapes) { @@ -392,21 +459,41 @@ void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, const std::vector= sizeof(Vector3)) && "Blend Shape position buffer length not a multiple of element size"); - const auto bufferSize = blendShape.deltas.mBlob.GetBufferSize(); - std::vector buffer(bufferSize); - if(ReadAccessor(blendShape.deltas, buffers[blendShape.deltas.mBufferIdx].GetBufferStream(), buffer.data())) + const auto bufferSize = blendShape.deltas.mBlob.GetBufferSize(); + std::vector buffer(bufferSize); + std::vector sparseIndices{}; + + if(ReadAccessor(blendShape.deltas, buffers[blendShape.deltas.mBufferIdx].GetBufferStream(), buffer.data(), &sparseIndices)) { - blendShape.deltas.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data())); + blendShape.deltas.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data()), &sparseIndices); + // Calculate the difference with the original mesh. // Find the max distance to normalize the deltas. - const Vector3* const deltasBuffer = reinterpret_cast(buffer.data()); + const auto* const deltasBuffer = reinterpret_cast(buffer.data()); - for(uint32_t index = 0u; index < numberOfVertices; ++index) - { - Vector3& delta = geometryBufferV3[geometryBufferIndex++]; - delta = deltasBuffer[index]; + auto ProcessVertex = [&geometryBufferV3, &deltasBuffer, &maxDistanceSquared](uint32_t geometryBufferIndex, uint32_t deltaIndex) { + Vector3& delta = geometryBufferV3[geometryBufferIndex] = deltasBuffer[deltaIndex]; + delta = deltasBuffer[deltaIndex]; + return std::max(maxDistanceSquared, delta.LengthSquared()); + }; - maxDistance = std::max(maxDistance, delta.LengthSquared()); + if(sparseIndices.empty()) + { + for(uint32_t index = 0u; index < numberOfVertices; ++index) + { + maxDistanceSquared = ProcessVertex(geometryBufferIndex++, index); + } + } + else + { + // initialize blendshape texture + // TODO: there may be a case when sparse accessor uses a base buffer view for initial values. + std::fill(geometryBufferV3 + geometryBufferIndex, geometryBufferV3 + geometryBufferIndex + numberOfVertices, Vector3::ZERO); + for(auto index : sparseIndices) + { + maxDistanceSquared = ProcessVertex(geometryBufferIndex + index, index); + } + geometryBufferIndex += numberOfVertices; } } } @@ -417,20 +504,18 @@ void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, const std::vector= sizeof(Vector3)) && "Blend Shape normals buffer length not a multiple of element size"); - const auto bufferSize = blendShape.normals.mBlob.GetBufferSize(); - std::vector buffer(bufferSize); - if(ReadAccessor(blendShape.normals, buffers[blendShape.normals.mBufferIdx].GetBufferStream(), buffer.data())) + const auto bufferSize = blendShape.normals.mBlob.GetBufferSize(); + std::vector buffer(bufferSize); + std::vector sparseIndices; + + if(ReadAccessor(blendShape.normals, buffers[blendShape.normals.mBufferIdx].GetBufferStream(), buffer.data(), &sparseIndices)) { - blendShape.normals.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data())); + blendShape.normals.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data()), &sparseIndices); // Calculate the difference with the original mesh, and translate to make all values positive. - const Vector3* const deltasBuffer = reinterpret_cast(buffer.data()); - - for(uint32_t index = 0u; index < numberOfVertices; ++index) - { - Vector3& delta = geometryBufferV3[geometryBufferIndex++]; - delta = deltasBuffer[index]; - + const Vector3* const deltasBuffer = reinterpret_cast(buffer.data()); + auto ProcessVertex = [&geometryBufferV3, &deltasBuffer, &maxDistanceSquared](uint32_t geometryBufferIndex, uint32_t deltaIndex) { + Vector3& delta = geometryBufferV3[geometryBufferIndex] = deltasBuffer[deltaIndex]; delta.x *= 0.5f; delta.y *= 0.5f; delta.z *= 0.5f; @@ -438,6 +523,23 @@ void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, const std::vector= sizeof(Vector3)) && "Blend Shape tangents buffer length not a multiple of element size"); - const auto bufferSize = blendShape.tangents.mBlob.GetBufferSize(); - std::vector buffer(bufferSize); - if(ReadAccessor(blendShape.tangents, buffers[blendShape.tangents.mBufferIdx].GetBufferStream(), buffer.data())) + const auto bufferSize = blendShape.tangents.mBlob.GetBufferSize(); + std::vector buffer(bufferSize); + std::vector sparseIndices; + + if(ReadAccessor(blendShape.tangents, buffers[blendShape.tangents.mBufferIdx].GetBufferStream(), buffer.data(), &sparseIndices)) { - blendShape.tangents.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data())); + blendShape.tangents.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data()), &sparseIndices); // Calculate the difference with the original mesh, and translate to make all values positive. - const Vector3* const deltasBuffer = reinterpret_cast(buffer.data()); - - for(uint32_t index = 0u; index < numberOfVertices; ++index) - { - Vector3& delta = geometryBufferV3[geometryBufferIndex++]; - delta = deltasBuffer[index]; - + const Vector3* const deltasBuffer = reinterpret_cast(buffer.data()); + auto ProcessVertex = [&geometryBufferV3, &deltasBuffer, &maxDistanceSquared](uint32_t geometryBufferIndex, uint32_t deltaIndex) { + Vector3& delta = geometryBufferV3[geometryBufferIndex] = deltasBuffer[deltaIndex]; delta.x *= 0.5f; delta.y *= 0.5f; delta.z *= 0.5f; @@ -469,12 +569,37 @@ void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, const std::vector& min, std::vector& min, const std::vector& max, uint32_t count, float* values) +void MeshDefinition::Blob::ApplyMinMax(const std::vector& min, const std::vector& max, uint32_t count, float* values, std::vector* sparseIndices) { DALI_ASSERT_DEBUG(max.size() == min.size() || max.size() * min.size() == 0); const auto numComponents = std::max(min.size(), max.size()); @@ -613,9 +733,9 @@ void MeshDefinition::Blob::ComputeMinMax(uint32_t numComponents, uint32_t count, ComputeMinMax(mMin, mMax, numComponents, count, values); } -void MeshDefinition::Blob::ApplyMinMax(uint32_t count, float* values) const +void MeshDefinition::Blob::ApplyMinMax(uint32_t count, float* values, std::vector* sparseIndices) const { - ApplyMinMax(mMin, mMax, count, values); + ApplyMinMax(mMin, mMax, count, values, sparseIndices); } void MeshDefinition::RawData::Attrib::AttachBuffer(Geometry& g) const @@ -944,20 +1064,20 @@ MeshDefinition::LoadRaw(const std::string& modelsPath, BufferDefinition::Vector& ReadJointAccessor(raw, mJoints0, streamJoint, pathJoint); } - DALI_ASSERT_ALWAYS(((mWeights0.mBlob.mLength % sizeof(Vector4) == 0) || - mWeights0.mBlob.mStride >= sizeof(Vector4)) && - "Weights buffer length not a multiple of element size"); - const auto bufferSize = mWeights0.mBlob.GetBufferSize(); - std::vector buffer(bufferSize); - std::string pathWeight; auto& streamWeight = GetAvailableData(fileStream, meshPath, buffers[mWeights0.mBufferIdx], pathWeight); - if(!ReadAccessor(mWeights0, streamWeight, buffer.data())) + if(MaskMatch(mFlags, U16_WEIGHT)) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read weights from '" << pathWeight << "'."; + ReadWeightAccessor(raw, mWeights0, streamWeight, pathWeight); + } + else if(MaskMatch(mFlags, U8_WEIGHT)) + { + ReadWeightAccessor(raw, mWeights0, streamWeight, pathWeight); + } + else + { + ReadWeightAccessor(raw, mWeights0, streamWeight, pathWeight); } - - raw.mAttribs.push_back({"aWeights", Property::VECTOR4, static_cast(bufferSize / sizeof(Vector4)), std::move(buffer)}); } // Calculate the Blob for the blend shapes.