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
CORE3D_BEGIN_NAMESPACE()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 void Initialize(const Configuration& config) override;
39
40 void AddSubmesh(const MeshBuilder::Submesh& submesh) override;
41
42 const Submesh& GetSubmesh(size_t index) const override;
43
44 void Allocate() override;
45
46 void SetVertexData(size_t submeshIndex, const DataBuffer& positions, const DataBuffer& normals,
47 const DataBuffer& texcoords0, const DataBuffer& texcoords1, const DataBuffer& tangents,
48 const DataBuffer& colors) override;
49
50 void SetIndexData(size_t submeshIndex, const DataBuffer& indices) override;
51
52 void SetJointData(size_t submeshIndex, const DataBuffer& jointData, const DataBuffer& weightData,
53 const DataBuffer& vertexPositions) override;
54
55 void SetMorphTargetData(size_t submeshIndex, const DataBuffer& basePositions, const DataBuffer& baseNormals,
56 const DataBuffer& baseTangents, const DataBuffer& targetPositions, const DataBuffer& targetNormals,
57 const DataBuffer& targetTangents) override;
58
59 void SetAABB(size_t submeshIndex, const BASE_NS::Math::Vec3& min, const BASE_NS::Math::Vec3& max) override;
60 void CalculateAABB(size_t submeshIndex, const DataBuffer& positions) override;
61
62 BASE_NS::array_view<const uint8_t> GetVertexData() const override;
63 BASE_NS::array_view<const uint8_t> GetIndexData() const override;
64 BASE_NS::array_view<const uint8_t> GetJointData() const override;
65 BASE_NS::array_view<const uint8_t> GetMorphTargetData() const override;
66
67 BASE_NS::array_view<const float> GetJointBoundsData() const override;
68
69 BASE_NS::array_view<const MeshComponent::Submesh> GetSubmeshes() const override;
70
71 uint32_t GetVertexCount() const override;
72 uint32_t GetIndexCount() const override;
73
74 void CreateGpuResources() override;
75 void CreateGpuResources(const GpuBufferCreateInfo& createInfo) override;
76
77 CORE_NS::Entity CreateMesh(CORE_NS::IEcs& ecs) const override;
78 CORE_NS::Entity CreateMesh(CORE_NS::IEcs& ecs, CORE_NS::Entity meshEntity) const override;
79
80 // IInterface
81 const IInterface* GetInterface(const BASE_NS::Uid& uid) const override;
82 IInterface* GetInterface(const BASE_NS::Uid& uid) override;
83
84 void Ref() override;
85 void Unref() override;
86
87 void EnablePrimitiveRestart(size_t index);
88
89 struct BufferHandles {
90 RENDER_NS::RenderHandleReference vertexBuffer;
91 };
92
93 struct BufferEntities {
94 CORE_NS::EntityReference vertexBuffer;
95 CORE_NS::EntityReference jointBuffer;
96 CORE_NS::EntityReference indexBuffer;
97 CORE_NS::EntityReference morphBuffer;
98 };
99
100 // Morph target descriptor
101 struct MorphTargetDesc {
102 // Offset to morph target data from submesh's morphTargetOffset.
103 uint32_t offset { 0 };
104 // Byte size of morph target data.
105 uint32_t byteSize { 0 };
106 };
107
108 // Extend submesh info with offset-data.
109 struct SubmeshExt {
110 MeshBuilder::Submesh info;
111
112 // Automatically calculated by builder.
113 BASE_NS::vector<uint32_t> vertexBindingByteSize;
114 BASE_NS::vector<uint32_t> vertexBindingOffset;
115 BASE_NS::vector<MorphTargetDesc> morphTargets;
116 uint32_t jointBufferOffset = 0;
117 uint32_t indexBufferOffset = 0;
118 uint32_t morphTargetBufferOffset = 0;
119 uint32_t morphTargetBufferSize = 0;
120 bool hasNormals = false;
121 bool hasUv0 = false;
122 bool hasTangents = false;
123 int32_t positionOffset = -1;
124 uint32_t positionSize = 0;
125 int32_t normalOffset = -1;
126 uint32_t normalSize = 0;
127 int32_t uvOffset = -1;
128 uint32_t uvSize = 0;
129 int32_t tangentsOffset = -1;
130 uint32_t tangentSize = 0;
131 int32_t indexOffset = -1;
132 uint32_t indexSize = 0;
133 };
134
135 private:
136 BufferEntities CreateBuffers(CORE_NS::IEcs& ecs) const;
137 void GenerateMissingAttributes() const;
138
139 struct BufferSizesInBytes {
140 size_t indexBuffer;
141 size_t jointBuffer;
142 size_t morphVertexData;
143 };
144
145 BufferSizesInBytes CalculateSizes();
146
147 static void GatherDeltasP(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset,
148 uint32_t targetSize, const DataBuffer& targetPositions);
149 static void GatherDeltasPN(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset,
150 uint32_t targetSize, const DataBuffer& targetPositions, const DataBuffer& targetNormals);
151 static void GatherDeltasPT(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset,
152 uint32_t targetSize, const DataBuffer& targetPositions, const MeshBuilder::DataBuffer& targetTangents);
153 static void GatherDeltasPNT(SubmeshExt& submesh, uint8_t* dst, uint32_t baseOffset, uint32_t indexOffset,
154 uint32_t targetSize, const DataBuffer& targetPositions, const DataBuffer& targetNormals,
155 const DataBuffer& targetTangents);
156
157 void CalculateJointBounds(
158 const DataBuffer& jointData, const DataBuffer& weightData, const DataBuffer& vertexPositions);
159
160 bool WriteData(const DataBuffer& data, const SubmeshExt& submesh, uint32_t attributeLocation, uint32_t& byteOffset,
161 uint32_t& byteSize, uint8_t* dst) const;
162
163 RENDER_NS::IRenderContext& renderContext_;
164 RENDER_NS::VertexInputDeclarationView vertexInputDeclaration_;
165
166 mutable BASE_NS::vector<SubmeshExt> submeshInfos_;
167 mutable BASE_NS::vector<MeshComponent::Submesh> submeshes_;
168
169 uint32_t vertexCount_ = 0;
170 uint32_t indexCount_ = 0;
171
172 size_t vertexDataSize_ = 0;
173 size_t indexDataSize_ = 0;
174 size_t jointDataSize_ = 0;
175 size_t targetDataSize_ = 0;
176 BufferHandles bufferHandles_;
177 RENDER_NS::RenderHandleReference stagingBuffer_;
178 uint8_t* stagingPtr_ = nullptr;
179 uint8_t* vertexPtr_ = nullptr;
180
181 struct Bounds {
182 BASE_NS::Math::Vec3 min;
183 BASE_NS::Math::Vec3 max;
184 };
185 // Bounds for each joint is 6 floats (3 min & 3 max).
186 static_assert(sizeof(Bounds) == (sizeof(float) * 6));
187 BASE_NS::vector<Bounds> jointBoundsData_;
188
189 mutable BASE_NS::vector<uint8_t> vertexData_;
190 BASE_NS::vector<uint8_t> indexData_;
191 uint32_t flags_ = 0;
192 uint32_t refCount_ = 0;
193 };
194 CORE3D_END_NAMESPACE()
195
196 #endif // CORE_UTIL_MESH_BUILDER_H
197