/* * Copyright (C) 2023 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" CORE3D_BEGIN_NAMESPACE() class MeshBuilder final : public IMeshBuilder { public: MeshBuilder() = default; ~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 BASE_NS::array_view& positions, const BASE_NS::array_view& normals, const BASE_NS::array_view& texcoords0, const BASE_NS::array_view& texcoords1, const BASE_NS::array_view& tangents, const BASE_NS::array_view& colors) override; void SetVertexData(size_t submeshIndex, const BASE_NS::array_view& positions, const BASE_NS::array_view& normals, const BASE_NS::array_view& texcoords0, const BASE_NS::array_view& texcoords1, const BASE_NS::array_view& tangents, const BASE_NS::array_view& colors) override; void SetIndexData(size_t submeshIndex, const BASE_NS::array_view& indices) override; void SetJointData(size_t submeshIndex, const BASE_NS::array_view& jointData, const BASE_NS::array_view& weightData, const BASE_NS::array_view& vertexPositions) override; void SetMorphTargetData(size_t submeshIndex, const BASE_NS::array_view& basePositions, const BASE_NS::array_view& baseNormals, const BASE_NS::array_view& baseTangents, const BASE_NS::array_view& targetPositions, const BASE_NS::array_view& targetNormals, const BASE_NS::array_view& 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 BASE_NS::array_view& 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; const BASE_NS::array_view GetSubmeshes() const override; uint32_t GetVertexCount() const override; uint32_t GetIndexCount() const 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 BufferEntities { CORE_NS::EntityReference vertexBuffer; CORE_NS::EntityReference jointBuffer; CORE_NS::EntityReference indexBuffer; CORE_NS::EntityReference morphBuffer; }; private: BufferEntities CreateBuffers(CORE_NS::IEcs& ecs) const; // 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. uint32_t vertexIndex = 0; BASE_NS::vector vertexBindingByteSize; BASE_NS::vector vertexBindingOffset; uint32_t jointBufferOffset = 0; uint32_t indexBufferOffset = 0; uint32_t morphTargetBufferOffset = 0; uint32_t morphTargetBufferSize = 0; BASE_NS::vector morphTargets; }; struct BufferSizesInBytes { size_t indexBuffer; size_t jointBuffer; size_t morphVertexData; }; BufferSizesInBytes CalculateSizes(); void GatherDeltas(SubmeshExt& submesh, uint32_t baseOffset, uint32_t indexOffset, uint32_t targetSize, const BASE_NS::array_view targetPositions, const BASE_NS::array_view targetNormals, const BASE_NS::array_view targetTangents); void CalculateJointBounds(const BASE_NS::array_view& weightData, const BASE_NS::array_view& jointData, const BASE_NS::array_view& vertexPositions); bool WriteData(const BASE_NS::array_view& data, uint32_t componentCount, const SubmeshExt& submesh, uint32_t attributeLocation, uint32_t& byteOffset, uint32_t& byteSize); void WriteFloatAttributeData(const void* destination, const void* source, size_t bufferOffset, size_t stride, size_t componentCount, size_t componentByteSize, size_t elementCount, BASE_NS::Format targetFormat); void WriteByteAttributeData(const void* destination, const void* source, size_t bufferOffset, size_t stride, size_t componentCount, size_t componentByteSize, size_t elementCount, BASE_NS::Format targetFormat); RENDER_NS::VertexInputDeclarationView vertexInputDeclaration_; BASE_NS::vector submeshInfos_; BASE_NS::vector submeshes_; uint32_t vertexCount_ = 0; uint32_t indexCount_ = 0; BASE_NS::vector vertexData_; BASE_NS::vector jointData_; BASE_NS::vector indexData_; BASE_NS::vector targetData_; 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_; uint32_t refCount_ = 0; }; CORE3D_END_NAMESPACE() #endif // CORE_UTIL_MESH_BUILDER_H