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
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