/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CORE_UTIL_MESH_BUILDER_H #define CORE_UTIL_MESH_BUILDER_H #include <3d/util/intf_mesh_builder.h> #include #include #include #include "gltf/gltf2_util.h" RENDER_BEGIN_NAMESPACE() class IRenderContext; RENDER_END_NAMESPACE() CORE3D_BEGIN_NAMESPACE() class MeshBuilder final : public IMeshBuilder { public: MeshBuilder(RENDER_NS::IRenderContext& renderContext); ~MeshBuilder() override = default; void Initialize(const RENDER_NS::VertexInputDeclarationView& vertexInputDeclaration, size_t submeshCount) override; void AddSubmesh(const MeshBuilder::Submesh& submesh) override; const Submesh& GetSubmesh(size_t index) const override; void Allocate() override; void SetVertexData(size_t submeshIndex, const DataBuffer& positions, const DataBuffer& normals, const DataBuffer& texcoords0, const DataBuffer& texcoords1, const DataBuffer& tangents, const DataBuffer& colors) override; void SetIndexData(size_t submeshIndex, const DataBuffer& indices) override; void SetJointData(size_t submeshIndex, const DataBuffer& jointData, const DataBuffer& weightData, const DataBuffer& vertexPositions) override; void SetMorphTargetData(size_t submeshIndex, const DataBuffer& basePositions, const DataBuffer& baseNormals, const DataBuffer& baseTangents, const DataBuffer& targetPositions, const DataBuffer& targetNormals, const DataBuffer& targetTangents) override; void SetAABB(size_t submeshIndex, const BASE_NS::Math::Vec3& min, const BASE_NS::Math::Vec3& max) override; void CalculateAABB(size_t submeshIndex, const DataBuffer& positions) override; BASE_NS::array_view GetVertexData() const override; BASE_NS::array_view GetIndexData() const override; BASE_NS::array_view GetJointData() const override; BASE_NS::array_view GetMorphTargetData() const override; BASE_NS::array_view GetJointBoundsData() const override; BASE_NS::array_view GetSubmeshes() const override; uint32_t GetVertexCount() const override; uint32_t GetIndexCount() const override; void CreateGpuResources() override; void CreateGpuResources(const GpuBufferCreateInfo& createInfo) override; CORE_NS::Entity CreateMesh(CORE_NS::IEcs& ecs) const override; // IInterface const IInterface* GetInterface(const BASE_NS::Uid& uid) const override; IInterface* GetInterface(const BASE_NS::Uid& uid) override; void Ref() override; void Unref() override; struct BufferHandles { RENDER_NS::RenderHandleReference vertexBuffer; RENDER_NS::RenderHandleReference jointBuffer; RENDER_NS::RenderHandleReference indexBuffer; RENDER_NS::RenderHandleReference morphBuffer; }; struct BufferEntities { CORE_NS::EntityReference vertexBuffer; CORE_NS::EntityReference jointBuffer; CORE_NS::EntityReference indexBuffer; CORE_NS::EntityReference morphBuffer; }; // Morph target descriptor struct MorphTargetDesc { // Offset to morph target data from submesh's morphTargetOffset. uint32_t offset { 0 }; // Byte size of morph target data. uint32_t byteSize { 0 }; }; // Extend submesh info with offset-data. struct SubmeshExt { MeshBuilder::Submesh info; // Automatically calculated by builder. BASE_NS::vector vertexBindingByteSize; BASE_NS::vector vertexBindingOffset; BASE_NS::vector morphTargets; uint32_t jointBufferOffset = 0; uint32_t indexBufferOffset = 0; uint32_t morphTargetBufferOffset = 0; uint32_t morphTargetBufferSize = 0; bool hasNormals = false; bool hasUv0 = false; bool hasTangents = false; int32_t positionOffset = -1; uint32_t positionSize = 0; int32_t normalOffset = -1; uint32_t normalSize = 0; int32_t uvOffset = -1; uint32_t uvSize = 0; int32_t tangentsOffset = -1; uint32_t tangentSize = 0; int32_t indexOffset = -1; uint32_t indexSize = 0; }; private: BufferEntities CreateBuffers(CORE_NS::IEcs& ecs) const; void GenerateMissingAttributes() const; struct BufferSizesInBytes { size_t indexBuffer; size_t jointBuffer; size_t morphVertexData; }; BufferSizesInBytes CalculateSizes(); static void GatherDeltasP(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset, uint32_t targetSize, const DataBuffer& targetPositions); static void GatherDeltasPN(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset, uint32_t targetSize, const DataBuffer& targetPositions, const DataBuffer& targetNormals); static void GatherDeltasPT(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset, uint32_t targetSize, const DataBuffer& targetPositions, const MeshBuilder::DataBuffer& targetTangents); static void GatherDeltasPNT(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset, uint32_t targetSize, const DataBuffer& targetPositions, const DataBuffer& targetNormals, const DataBuffer& targetTangents); void CalculateJointBounds( const DataBuffer& jointData, const DataBuffer& weightData, const DataBuffer& vertexPositions); bool WriteData(const DataBuffer& data, const SubmeshExt& submesh, uint32_t attributeLocation, uint32_t& byteOffset, uint32_t& byteSize, uint8_t* dst) const; RENDER_NS::IRenderContext& renderContext_; RENDER_NS::VertexInputDeclarationView vertexInputDeclaration_; mutable BASE_NS::vector submeshInfos_; mutable BASE_NS::vector submeshes_; uint32_t vertexCount_ = 0; uint32_t indexCount_ = 0; size_t vertexDataSize_ = 0; size_t indexDataSize_ = 0; size_t jointDataSize_ = 0; size_t targetDataSize_ = 0; BufferHandles bufferHandles_; RENDER_NS::RenderHandleReference stagingBuffer_; uint8_t* stagingPtr_ = nullptr; struct Bounds { BASE_NS::Math::Vec3 min; BASE_NS::Math::Vec3 max; }; // Bounds for each joint is 6 floats (3 min & 3 max). static_assert(sizeof(Bounds) == (sizeof(float) * 6)); BASE_NS::vector jointBoundsData_; mutable BASE_NS::vector vertexData_; BASE_NS::vector indexData_; uint32_t refCount_ = 0; }; CORE3D_END_NAMESPACE() #endif // CORE_UTIL_MESH_BUILDER_H