X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-scene3d%2Fpublic-api%2Floader%2Fmesh-definition.cpp;h=45ab5ff531b5b52717e69de6d06863c5b0391979;hb=e4c8362431523550a745b190c67c0c8e3f25ac4d;hp=5c9655ad3c119032f67e9194b85730d1ba1b7c9e;hpb=42b12368d0e630722a62c69ffd8dbcef96393d0d;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 5c9655a..45ab5ff 100644 --- a/dali-scene3d/public-api/loader/mesh-definition.cpp +++ b/dali-scene3d/public-api/loader/mesh-definition.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,6 +19,8 @@ #include "dali-scene3d/public-api/loader/mesh-definition.h" // EXTERNAL INCLUDES +#include +#include #include #include #include "dali/devel-api/adaptor-framework/pixel-buffer.h" @@ -31,8 +33,6 @@ namespace Loader { namespace { -using Uint16Vector4 = uint16_t[4]; - class IndexProvider { public: @@ -65,12 +65,13 @@ private: uint16_t (*mFunc)(uintptr_t&); }; -const std::string QUAD("quad"); +const char* QUAD("quad"); ///@brief Reads a blob from the given stream @a source into @a target, which must have /// at least @a descriptor.length bytes. bool ReadBlob(const MeshDefinition::Blob& descriptor, std::istream& source, uint8_t* target) { + source.clear(); if(!source.seekg(descriptor.mOffset, std::istream::beg)) { return false; @@ -78,7 +79,7 @@ bool ReadBlob(const MeshDefinition::Blob& descriptor, std::istream& source, uint if(descriptor.IsConsecutive()) { - return !!source.read(reinterpret_cast(target), descriptor.mLength); + return !!source.read(reinterpret_cast(target), static_cast(static_cast(descriptor.mLength))); } else { @@ -175,6 +176,40 @@ bool ReadAccessor(const MeshDefinition::Accessor& accessor, std::istream& source return success; } +template +void ReadJointAccessor(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) && + "Joints 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 joints 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); + *floats = static_cast(value); + + inBuffer += sizeof(T); + ++floats; + } + } + raw.mAttribs.push_back({"aJoints", Property::VECTOR4, static_cast(outBufferSize / sizeof(Vector4)), std::move(buffer)}); +} + void GenerateNormals(MeshDefinition::RawData& raw) { auto& attribs = raw.mAttribs; @@ -315,7 +350,7 @@ void CalculateTextureSize(uint32_t totalTextureSize, uint32_t& textureWidth, uin textureHeight = 1u << powHeight; } -void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, std::ifstream& binFile, const std::vector& blendShapes, uint32_t numberOfVertices, float& blendShapeUnnormalizeFactor) +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; @@ -330,7 +365,7 @@ void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, std::ifstream& binFile, const auto bufferSize = blendShape.deltas.mBlob.GetBufferSize(); std::vector buffer(bufferSize); - if(ReadAccessor(blendShape.deltas, binFile, buffer.data())) + if(ReadAccessor(blendShape.deltas, buffers[blendShape.deltas.mBufferIdx].GetBufferStream(), buffer.data())) { blendShape.deltas.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data())); // Calculate the difference with the original mesh. @@ -355,7 +390,7 @@ void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, std::ifstream& binFile, const auto bufferSize = blendShape.normals.mBlob.GetBufferSize(); std::vector buffer(bufferSize); - if(ReadAccessor(blendShape.normals, binFile, buffer.data())) + if(ReadAccessor(blendShape.normals, buffers[blendShape.normals.mBufferIdx].GetBufferStream(), buffer.data())) { blendShape.normals.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data())); @@ -386,7 +421,7 @@ void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, std::ifstream& binFile, const auto bufferSize = blendShape.tangents.mBlob.GetBufferSize(); std::vector buffer(bufferSize); - if(ReadAccessor(blendShape.tangents, binFile, buffer.data())) + if(ReadAccessor(blendShape.tangents, buffers[blendShape.tangents.mBufferIdx].GetBufferStream(), buffer.data())) { blendShape.tangents.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data())); @@ -444,6 +479,13 @@ void CalculateGltf2BlendShapes(uint8_t* geometryBuffer, std::ifstream& binFile, } } +std::iostream& GetAvailableData(std::fstream& meshStream, const std::string& meshPath, BufferDefinition& buffer, std::string& availablePath) +{ + auto& stream = (meshStream.is_open()) ? meshStream : buffer.GetBufferStream(); + availablePath = (meshStream.is_open()) ? meshPath : buffer.GetUri(); + return stream; +} + } // namespace MeshDefinition::SparseBlob::SparseBlob(const Blob& indices, const Blob& values, uint32_t count) @@ -461,16 +503,20 @@ MeshDefinition::SparseBlob::SparseBlob(Blob&& indices, Blob&& values, uint32_t c } MeshDefinition::Accessor::Accessor(const MeshDefinition::Blob& blob, - const MeshDefinition::SparseBlob& sparse) + const MeshDefinition::SparseBlob& sparse, + Index bufferIndex) : mBlob{blob}, - mSparse{(sparse.mIndices.IsDefined() && sparse.mValues.IsDefined()) ? new SparseBlob{sparse} : nullptr} + mSparse{(sparse.mIndices.IsDefined() && sparse.mValues.IsDefined()) ? new SparseBlob{sparse} : nullptr}, + mBufferIdx(bufferIndex) { } MeshDefinition::Accessor::Accessor(MeshDefinition::Blob&& blob, - MeshDefinition::SparseBlob&& sparse) + MeshDefinition::SparseBlob&& sparse, + Index bufferIndex) : mBlob{std::move(blob)}, - mSparse{(sparse.mIndices.IsDefined() && sparse.mValues.IsDefined()) ? new SparseBlob{std::move(sparse)} : nullptr} + mSparse{(sparse.mIndices.IsDefined() && sparse.mValues.IsDefined()) ? new SparseBlob{std::move(sparse)} : nullptr}, + mBufferIdx(bufferIndex) { } @@ -495,15 +541,9 @@ void MeshDefinition::Blob::ApplyMinMax(const std::vector& min, const std: 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(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([](const float* min, const float* max, uint32_t i, float& value) { - value = std::min(std::max(min[i], value), max[i]); - })); + ClampFn clampFn = min.empty() ? (max.empty() ? static_cast(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([](const float* min, const float* max, uint32_t i, float& value) { value = std::min(std::max(min[i], value), max[i]); })); if(!clampFn) { @@ -585,7 +625,7 @@ void MeshDefinition::RequestTangents() } MeshDefinition::RawData -MeshDefinition::LoadRaw(const std::string& modelsPath) +MeshDefinition::LoadRaw(const std::string& modelsPath, BufferDefinition::Vector& buffers) { RawData raw; if(IsQuad()) @@ -593,11 +633,16 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) return raw; } - const std::string meshPath = modelsPath + mUri; - std::ifstream binFile(meshPath, std::ios::binary); - if(!binFile) + std::string meshPath; + meshPath = modelsPath + mUri; + std::fstream fileStream; + if(!mUri.empty()) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read geometry data from '" << meshPath << "'"; + 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()); + } } if(mIndices.IsDefined()) @@ -609,9 +654,12 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) "Index buffer length not a multiple of element size"); const auto indexCount = mIndices.mBlob.GetBufferSize() / sizeof(uint32_t); raw.mIndices.resize(indexCount * 2); // NOTE: we need space for uint32_ts initially. - if(!ReadAccessor(mIndices, binFile, reinterpret_cast(raw.mIndices.data()))) + + std::string path; + auto& stream = GetAvailableData(fileStream, meshPath, buffers[mIndices.mBufferIdx], path); + if(!ReadAccessor(mIndices, stream, reinterpret_cast(raw.mIndices.data()))) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read indices from '" << meshPath << "'."; + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read indices from '" << path << "'."; } auto u16s = raw.mIndices.data(); @@ -626,15 +674,43 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) raw.mIndices.resize(indexCount); } + else if(MaskMatch(mFlags, U8_INDICES)) + { + DALI_ASSERT_ALWAYS(((mIndices.mBlob.mLength % sizeof(uint8_t) == 0) || + mIndices.mBlob.mStride >= sizeof(uint8_t)) && + "Index buffer length not a multiple of element size"); + const auto indexCount = mIndices.mBlob.GetBufferSize() / sizeof(uint8_t); + raw.mIndices.resize(indexCount); // NOTE: we need space for uint32_ts initially. + + std::string path; + auto u8s = reinterpret_cast(raw.mIndices.data()) + indexCount; + auto& stream = GetAvailableData(fileStream, meshPath, buffers[mIndices.mBufferIdx], path); + if(!ReadAccessor(mIndices, stream, u8s)) + { + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read indices from '" << path << "'."; + } + + auto u16s = raw.mIndices.data(); + auto end = u8s + indexCount; + while(u8s != end) + { + *u16s = static_cast(*u8s); + ++u16s; + ++u8s; + } + } else { DALI_ASSERT_ALWAYS(((mIndices.mBlob.mLength % sizeof(unsigned short) == 0) || mIndices.mBlob.mStride >= sizeof(unsigned short)) && "Index buffer length not a multiple of element size"); raw.mIndices.resize(mIndices.mBlob.mLength / sizeof(unsigned short)); - if(!ReadAccessor(mIndices, binFile, reinterpret_cast(raw.mIndices.data()))) + + std::string path; + auto& stream = GetAvailableData(fileStream, meshPath, buffers[mIndices.mBufferIdx], path); + if(!ReadAccessor(mIndices, stream, reinterpret_cast(raw.mIndices.data()))) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read indices from '" << meshPath << "'."; + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read indices from '" << path << "'."; } } } @@ -647,9 +723,12 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) "Position buffer length not a multiple of element size"); const auto bufferSize = mPositions.mBlob.GetBufferSize(); std::vector buffer(bufferSize); - if(!ReadAccessor(mPositions, binFile, buffer.data())) + + std::string path; + auto& stream = GetAvailableData(fileStream, meshPath, buffers[mPositions.mBufferIdx], path); + if(!ReadAccessor(mPositions, stream, buffer.data())) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read positions from '" << meshPath << "'."; + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read positions from '" << path << "'."; } uint32_t numVector3 = static_cast(bufferSize / sizeof(Vector3)); @@ -680,9 +759,12 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) "Normal buffer length not a multiple of element size"); const auto bufferSize = mNormals.mBlob.GetBufferSize(); std::vector buffer(bufferSize); - if(!ReadAccessor(mNormals, binFile, buffer.data())) + + std::string path; + auto& stream = GetAvailableData(fileStream, meshPath, buffers[mNormals.mBufferIdx], path); + if(!ReadAccessor(mNormals, stream, buffer.data())) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read normals from '" << meshPath << "'."; + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read normals from '" << path << "'."; } mNormals.mBlob.ApplyMinMax(static_cast(bufferSize / sizeof(Vector3)), reinterpret_cast(buffer.data())); @@ -704,9 +786,12 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) "Normal buffer length not a multiple of element size"); const auto bufferSize = mTexCoords.mBlob.GetBufferSize(); std::vector buffer(bufferSize); - if(!ReadAccessor(mTexCoords, binFile, buffer.data())) + + std::string path; + auto& stream = GetAvailableData(fileStream, meshPath, buffers[mTexCoords.mBufferIdx], path); + if(!ReadAccessor(mTexCoords, stream, buffer.data())) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read uv-s from '" << meshPath << "'."; + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read uv-s from '" << path << "'."; } const auto uvCount = bufferSize / sizeof(Vector2); @@ -734,9 +819,12 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) "Tangents buffer length not a multiple of element size"); const auto bufferSize = mTangents.mBlob.GetBufferSize(); std::vector buffer(bufferSize); - if(!ReadAccessor(mTangents, binFile, buffer.data())) + + std::string path; + auto& stream = GetAvailableData(fileStream, meshPath, buffers[mTangents.mBufferIdx], path); + if(!ReadAccessor(mTangents, stream, buffer.data())) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read tangents from '" << meshPath << "'."; + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read tangents from '" << path << "'."; } mTangents.mBlob.ApplyMinMax(bufferSize / propertySize, reinterpret_cast(buffer.data())); @@ -759,9 +847,12 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) "Colors buffer length not a multiple of element size"); const auto bufferSize = mColors.mBlob.GetBufferSize(); std::vector buffer(bufferSize); - if(!ReadAccessor(mColors, binFile, buffer.data())) + + std::string path; + auto& stream = GetAvailableData(fileStream, meshPath, buffers[mColors.mBufferIdx], path); + if(!ReadAccessor(mColors, stream, buffer.data())) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read colors from '" << meshPath << "'."; + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read colors from '" << path << "'."; } mColors.mBlob.ApplyMinMax(bufferSize / propertySize, reinterpret_cast(buffer.data())); @@ -771,44 +862,19 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) if(IsSkinned()) { + std::string pathJoint; + auto& streamJoint = GetAvailableData(fileStream, meshPath, buffers[mJoints0.mBufferIdx], pathJoint); if(MaskMatch(mFlags, U16_JOINT_IDS)) { - DALI_ASSERT_ALWAYS(((mJoints0.mBlob.mLength % sizeof(Uint16Vector4) == 0) || - mJoints0.mBlob.mStride >= sizeof(Uint16Vector4)) && - "Joints buffer length not a multiple of element size"); - const auto inBufferSize = mJoints0.mBlob.GetBufferSize(); - std::vector buffer(inBufferSize * 2); - auto u16s = buffer.data() + inBufferSize; - if(!ReadAccessor(mJoints0, binFile, u16s)) - { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read joints from '" << meshPath << "'."; - } - - auto floats = reinterpret_cast(buffer.data()); - auto end = u16s + inBufferSize; - while(u16s != end) - { - auto value = *reinterpret_cast(u16s); - *floats = static_cast(value); - - u16s += sizeof(uint16_t); - ++floats; - } - raw.mAttribs.push_back({"aJoints", Property::VECTOR4, static_cast(buffer.size() / sizeof(Vector4)), std::move(buffer)}); + ReadJointAccessor(raw, mJoints0, streamJoint, pathJoint); + } + else if(MaskMatch(mFlags, U8_JOINT_IDS)) + { + ReadJointAccessor(raw, mJoints0, streamJoint, pathJoint); } else { - DALI_ASSERT_ALWAYS(((mJoints0.mBlob.mLength % sizeof(Vector4) == 0) || - mJoints0.mBlob.mStride >= sizeof(Vector4)) && - "Joints buffer length not a multiple of element size"); - const auto bufferSize = mJoints0.mBlob.GetBufferSize(); - std::vector buffer(bufferSize); - if(!ReadAccessor(mJoints0, binFile, buffer.data())) - { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read joints from '" << meshPath << "'."; - } - - raw.mAttribs.push_back({"aJoints", Property::VECTOR4, static_cast(bufferSize / sizeof(Vector4)), std::move(buffer)}); + ReadJointAccessor(raw, mJoints0, streamJoint, pathJoint); } DALI_ASSERT_ALWAYS(((mWeights0.mBlob.mLength % sizeof(Vector4) == 0) || @@ -816,9 +882,12 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) "Weights buffer length not a multiple of element size"); const auto bufferSize = mWeights0.mBlob.GetBufferSize(); std::vector buffer(bufferSize); - if(!ReadAccessor(mWeights0, binFile, buffer.data())) + + std::string pathWeight; + auto& streamWeight = GetAvailableData(fileStream, meshPath, buffers[mWeights0.mBufferIdx], pathWeight); + if(!ReadAccessor(mWeights0, streamWeight, buffer.data())) { - ExceptionFlinger(ASSERT_LOCATION) << "Failed to read weights from '" << meshPath << "'."; + ExceptionFlinger(ASSERT_LOCATION) << "Failed to read weights from '" << pathWeight << "'."; } raw.mAttribs.push_back({"aWeights", Property::VECTOR4, static_cast(bufferSize / sizeof(Vector4)), std::move(buffer)}); @@ -860,7 +929,7 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) else { uint16_t header[2u]; - ReadBlob(mBlendShapeHeader, binFile, reinterpret_cast(header)); + ReadBlob(mBlendShapeHeader, fileStream, reinterpret_cast(header)); textureWidth = header[0u]; textureHeight = header[1u]; } @@ -873,7 +942,7 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) if(calculateGltf2BlendShapes) { - CalculateGltf2BlendShapes(geometryBuffer, binFile, mBlendShapes, numberOfVertices, raw.mBlendShapeUnnormalizeFactor[0u]); + CalculateGltf2BlendShapes(geometryBuffer, mBlendShapes, numberOfVertices, raw.mBlendShapeUnnormalizeFactor[0u], buffers); } else { @@ -882,7 +951,7 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) if(blendShapesBlob.IsDefined()) { - if(ReadBlob(blendShapesBlob, binFile, geometryBuffer)) + if(ReadBlob(blendShapesBlob, fileStream, geometryBuffer)) { unnormalizeFactorBlob.mOffset = blendShapesBlob.mOffset + blendShapesBlob.mLength; } @@ -891,7 +960,7 @@ MeshDefinition::LoadRaw(const std::string& modelsPath) // Read the unnormalize factors. if(unnormalizeFactorBlob.IsDefined()) { - ReadBlob(unnormalizeFactorBlob, binFile, reinterpret_cast(&raw.mBlendShapeUnnormalizeFactor[0u])); + ReadBlob(unnormalizeFactorBlob, fileStream, reinterpret_cast(&raw.mBlendShapeUnnormalizeFactor[0u])); } } raw.mBlendShapeData = Devel::PixelBuffer::Convert(geometryPixelBuffer);