1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef CORE_UTIL_MESH_BUILDER_H 17 #define CORE_UTIL_MESH_BUILDER_H 18 19 #include <3d/util/intf_mesh_builder.h> 20 #include <base/util/formats.h> 21 #include <core/namespace.h> 22 #include <render/resource_handle.h> 23 24 #include "gltf/gltf2_util.h" 25 26 RENDER_BEGIN_NAMESPACE() 27 class IRenderContext; 28 RENDER_END_NAMESPACE() 29 30 CORE3D_BEGIN_NAMESPACE() 31 class MeshBuilder final : public IMeshBuilder { 32 public: 33 MeshBuilder(RENDER_NS::IRenderContext& renderContext); 34 35 ~MeshBuilder() override = default; 36 37 void Initialize(const RENDER_NS::VertexInputDeclarationView& vertexInputDeclaration, size_t submeshCount) override; 38 39 void AddSubmesh(const MeshBuilder::Submesh& submesh) override; 40 41 const Submesh& GetSubmesh(size_t index) const override; 42 43 void Allocate() override; 44 45 void SetVertexData(size_t submeshIndex, const DataBuffer& positions, const DataBuffer& normals, 46 const DataBuffer& texcoords0, const DataBuffer& texcoords1, const DataBuffer& tangents, 47 const DataBuffer& colors) override; 48 49 void SetIndexData(size_t submeshIndex, const DataBuffer& indices) override; 50 51 void SetJointData(size_t submeshIndex, const DataBuffer& jointData, const DataBuffer& weightData, 52 const DataBuffer& vertexPositions) override; 53 54 void SetMorphTargetData(size_t submeshIndex, const DataBuffer& basePositions, const DataBuffer& baseNormals, 55 const DataBuffer& baseTangents, const DataBuffer& targetPositions, const DataBuffer& targetNormals, 56 const DataBuffer& targetTangents) override; 57 58 void SetAABB(size_t submeshIndex, const BASE_NS::Math::Vec3& min, const BASE_NS::Math::Vec3& max) override; 59 void CalculateAABB(size_t submeshIndex, const DataBuffer& positions) override; 60 61 BASE_NS::array_view<const uint8_t> GetVertexData() const override; 62 BASE_NS::array_view<const uint8_t> GetIndexData() const override; 63 BASE_NS::array_view<const uint8_t> GetJointData() const override; 64 BASE_NS::array_view<const uint8_t> GetMorphTargetData() const override; 65 66 BASE_NS::array_view<const float> GetJointBoundsData() const override; 67 68 BASE_NS::array_view<const MeshComponent::Submesh> GetSubmeshes() const override; 69 70 uint32_t GetVertexCount() const override; 71 uint32_t GetIndexCount() const override; 72 73 void CreateGpuResources() override; 74 void CreateGpuResources(const GpuBufferCreateInfo& createInfo) override; 75 76 CORE_NS::Entity CreateMesh(CORE_NS::IEcs& ecs) const override; 77 78 // IInterface 79 const IInterface* GetInterface(const BASE_NS::Uid& uid) const override; 80 IInterface* GetInterface(const BASE_NS::Uid& uid) override; 81 82 void Ref() override; 83 void Unref() override; 84 85 struct BufferHandles { 86 RENDER_NS::RenderHandleReference vertexBuffer; 87 RENDER_NS::RenderHandleReference jointBuffer; 88 RENDER_NS::RenderHandleReference indexBuffer; 89 RENDER_NS::RenderHandleReference morphBuffer; 90 }; 91 92 struct BufferEntities { 93 CORE_NS::EntityReference vertexBuffer; 94 CORE_NS::EntityReference jointBuffer; 95 CORE_NS::EntityReference indexBuffer; 96 CORE_NS::EntityReference morphBuffer; 97 }; 98 99 // Morph target descriptor 100 struct MorphTargetDesc { 101 // Offset to morph target data from submesh's morphTargetOffset. 102 uint32_t offset { 0 }; 103 // Byte size of morph target data. 104 uint32_t byteSize { 0 }; 105 }; 106 107 // Extend submesh info with offset-data. 108 struct SubmeshExt { 109 MeshBuilder::Submesh info; 110 111 // Automatically calculated by builder. 112 BASE_NS::vector<uint32_t> vertexBindingByteSize; 113 BASE_NS::vector<uint32_t> vertexBindingOffset; 114 BASE_NS::vector<MorphTargetDesc> morphTargets; 115 uint32_t jointBufferOffset = 0; 116 uint32_t indexBufferOffset = 0; 117 uint32_t morphTargetBufferOffset = 0; 118 uint32_t morphTargetBufferSize = 0; 119 bool hasNormals = false; 120 bool hasUv0 = false; 121 bool hasTangents = false; 122 int32_t positionOffset = -1; 123 uint32_t positionSize = 0; 124 int32_t normalOffset = -1; 125 uint32_t normalSize = 0; 126 int32_t uvOffset = -1; 127 uint32_t uvSize = 0; 128 int32_t tangentsOffset = -1; 129 uint32_t tangentSize = 0; 130 int32_t indexOffset = -1; 131 uint32_t indexSize = 0; 132 }; 133 134 private: 135 BufferEntities CreateBuffers(CORE_NS::IEcs& ecs) const; 136 void GenerateMissingAttributes() const; 137 138 struct BufferSizesInBytes { 139 size_t indexBuffer; 140 size_t jointBuffer; 141 size_t morphVertexData; 142 }; 143 144 BufferSizesInBytes CalculateSizes(); 145 146 static void GatherDeltasP(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset, 147 uint32_t targetSize, const DataBuffer& targetPositions); 148 static void GatherDeltasPN(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset, 149 uint32_t targetSize, const DataBuffer& targetPositions, const DataBuffer& targetNormals); 150 static void GatherDeltasPT(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset, 151 uint32_t targetSize, const DataBuffer& targetPositions, const MeshBuilder::DataBuffer& targetTangents); 152 static void GatherDeltasPNT(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset, 153 uint32_t targetSize, const DataBuffer& targetPositions, const DataBuffer& targetNormals, 154 const DataBuffer& targetTangents); 155 156 void CalculateJointBounds( 157 const DataBuffer& jointData, const DataBuffer& weightData, const DataBuffer& vertexPositions); 158 159 bool WriteData(const DataBuffer& data, const SubmeshExt& submesh, uint32_t attributeLocation, uint32_t& byteOffset, 160 uint32_t& byteSize, uint8_t* dst) const; 161 162 RENDER_NS::IRenderContext& renderContext_; 163 RENDER_NS::VertexInputDeclarationView vertexInputDeclaration_; 164 165 mutable BASE_NS::vector<SubmeshExt> submeshInfos_; 166 mutable BASE_NS::vector<MeshComponent::Submesh> submeshes_; 167 168 uint32_t vertexCount_ = 0; 169 uint32_t indexCount_ = 0; 170 171 size_t vertexDataSize_ = 0; 172 size_t indexDataSize_ = 0; 173 size_t jointDataSize_ = 0; 174 size_t targetDataSize_ = 0; 175 BufferHandles bufferHandles_; 176 RENDER_NS::RenderHandleReference stagingBuffer_; 177 uint8_t* stagingPtr_ = nullptr; 178 179 struct Bounds { 180 BASE_NS::Math::Vec3 min; 181 BASE_NS::Math::Vec3 max; 182 }; 183 // Bounds for each joint is 6 floats (3 min & 3 max). 184 static_assert(sizeof(Bounds) == (sizeof(float) * 6)); 185 BASE_NS::vector<Bounds> jointBoundsData_; 186 187 mutable BASE_NS::vector<uint8_t> vertexData_; 188 BASE_NS::vector<uint8_t> indexData_; 189 uint32_t refCount_ = 0; 190 }; 191 CORE3D_END_NAMESPACE() 192 193 #endif // CORE_UTIL_MESH_BUILDER_H 194