1 /*
2 * Copyright (c) 2022 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 API_3D_UTIL_IMESH_BUILDER_H
17 #define API_3D_UTIL_IMESH_BUILDER_H
18
19 #include <cstddef>
20
21 #include <3d/ecs/components/mesh_component.h>
22 #include <base/containers/refcnt_ptr.h>
23 #include <base/util/formats.h>
24 #include <core/ecs/entity.h>
25 #include <core/namespace.h>
26 #include <core/plugin/intf_interface.h>
27 #include <render/device/pipeline_state_desc.h>
28 #include <render/resource_handle.h>
29
30 CORE_BEGIN_NAMESPACE()
31 class IEcs;
32 CORE_END_NAMESPACE()
33
CORE3D_BEGIN_NAMESPACE()34 CORE3D_BEGIN_NAMESPACE()
35 /** @ingroup group_util_imeshbuilder */
36 /** Mesh builder interface for building meshes */
37 class IMeshBuilder : public CORE_NS::IInterface {
38 public:
39 static constexpr auto UID = BASE_NS::Uid { "8d2892a4-77e5-4304-a5aa-38f866b7c788" };
40
41 using Ptr = BASE_NS::refcnt_ptr<IMeshBuilder>;
42
43 enum ConfigurationFlagBits : uint32_t {
44 /** Don't use staging buffer. Requires less memory and avoids copying data from staging to final buffers, but
45 this implies host visible buffers which can have . */
46 NO_STAGING_BUFFER = 0x1,
47 };
48
49 /** Initialization parameters. */
50 struct Configuration {
51 /** Defines the expected vertex input layout i.e. how the mesh data should be stored in buffers. */
52 RENDER_NS::VertexInputDeclarationView vertexInputDeclaration;
53 /** Number of submeshes in the next mesh. */
54 size_t submeshCount;
55 uint32_t flags;
56 };
57
58 /** Submesh attributes */
59 struct Submesh {
60 /** Vertex count */
61 uint32_t vertexCount { 0 };
62 /** Index count */
63 uint32_t indexCount { 0 };
64 /** Instance count */
65 uint32_t instanceCount { 1 };
66 /** Morph target count */
67 uint32_t morphTargetCount { 0 };
68 /** Index type */
69 RENDER_NS::IndexType indexType { RENDER_NS::IndexType::CORE_INDEX_TYPE_UINT32 };
70
71 /** Material */
72 CORE_NS::Entity material {};
73 /** Tangents */
74 bool tangents { false };
75 /** Colors */
76 bool colors { false };
77 /** Joints */
78 bool joints { false };
79
80 /** Optional input assembly. Will be filled to Submesh */
81 RENDER_NS::GraphicsState::InputAssembly inputAssembly { false,
82 RENDER_NS::PrimitiveTopology::CORE_PRIMITIVE_TOPOLOGY_MAX_ENUM };
83 };
84
85 /** GPU buffer create info */
86 struct GpuBufferCreateInfo {
87 /** Additional usage flags */
88 RENDER_NS::BufferUsageFlags usage { 0U };
89 /** Engine creation flags */
90 RENDER_NS::EngineBufferCreationFlags engineCreation { 0U };
91 /** Memory property flags */
92 RENDER_NS::MemoryPropertyFlags memoryFlags { 0U };
93 };
94
95 /** Prepare the builder for adding submeshes. Also resets the builder for re-use.
96 */
97 virtual void Initialize(
98 const RENDER_NS::VertexInputDeclarationView& vertexInputDeclaration, size_t submeshCount) = 0;
99
100 /** Prepare the builder for adding submeshes. Also resets the builder for re-use.
101 * @param config Configuration parameters.
102 */
103 virtual void Initialize(const Configuration& config) = 0;
104
105 /** Add a submesh and related import info to this mesh.
106 * @param submesh Submesh import information that is used to determine memory requirements etc.
107 */
108 virtual void AddSubmesh(const Submesh& submesh) = 0;
109
110 /** Returns Import info for given submesh.
111 * @param index Index of the submesh.
112 * @return Import information for the given submesh.
113 */
114 virtual const Submesh& GetSubmesh(size_t index) const = 0;
115
116 /** Allocates memory for this mesh, should be called after all submeshes have been added to this mesh and before
117 * data is being fed to submeshes. */
118 virtual void Allocate() = 0;
119
120 /** Struct for passing data to the mesh builder.*/
121 struct DataBuffer {
122 /** Format of each element in buffer. e.g. three float values per element would be R32G32B32_SFLOAT. */
123 BASE_NS::Format format;
124 /** Offset between elements. This should match the size of one element for tightly packed values. */
125 uint32_t stride;
126 /** Byte arrays which will be interpreted based on format and stride. */
127 BASE_NS::array_view<const uint8_t> buffer;
128 };
129
130 /** Set geometry data for a given submesh.
131 * @param submeshIndex Index of the submesh.
132 * @param positions Position data (3 * vertexCount values), this parameter is required.
133 * @param normals Normal data (3 * vertexCount values), this parameter is required.
134 * @param texcoords0 Texture coordinate 0 data (2 * vertexCount values), this parameter is required.
135 * @param texcoords1 Texture coordinate 1 data (2 * vertexCount values), this parameter is optional.
136 * @param tangents Tangent data (4 * vertexCount values), this parameter is optional.
137 * @param colors Vertex color data (4 * vertexCount values), this parameter is optional.
138 */
139 virtual void SetVertexData(size_t submeshIndex, const DataBuffer& positions, const DataBuffer& normals,
140 const DataBuffer& texcoords0, const DataBuffer& texcoords1, const DataBuffer& tangents,
141 const DataBuffer& colors) = 0;
142
143 /** Set Axis-aligned bounding box for a submesh.
144 * @param submeshIndex Index of the submesh.
145 * @param min Minimum corner.
146 * @param max Minimum corner.
147 */
148 virtual void SetAABB(size_t submeshIndex, const BASE_NS::Math::Vec3& min, const BASE_NS::Math::Vec3& max) = 0;
149
150 /** Calculate Axis-aligned bounding box for a submesh.
151 * @param submeshIndex Index of the submesh.
152 * @param positions Array of vertex positions in submesh.
153 */
154 virtual void CalculateAABB(size_t submeshIndex, const DataBuffer& positions) = 0;
155
156 /** Set triangle indices for a submesh.
157 * @param submeshIndex Index of the submesh.
158 * @param indices Index data.
159 */
160 virtual void SetIndexData(size_t submeshIndex, const DataBuffer& indices) = 0;
161
162 /** Set Joint data for a submesh.
163 * @param submeshIndex Index of the submesh.
164 * @param jointData Joint indices per vertex, (4 indices per bone).
165 * @param weightData Joint weights per vertex , (4 weights per bone).
166 * @param vertexPositions Position data that is used for skin bounds calculations (3 * vertexCount
167 * values), this data should match the data set with SetVertexData().
168 */
169 virtual void SetJointData(size_t submeshIndex, const DataBuffer& jointData, const DataBuffer& weightData,
170 const DataBuffer& vertexPositions) = 0;
171
172 /** Set Morph targets for a submesh.
173 * @param submeshIndex Index of the submesh.
174 * @param basePositions Initial vertex positions (base pose).
175 * @param baseNormals Initial vertex normals (base pose).
176 * @param baseTangents Initial vertex tangents (base pose).
177 * @param targetPositions Morph target vertex positions (delta offsets from base vertex, total size of array is
178 * target_count * vertex_count).
179 * @param targetNormals Morph target vertex normals (delta offsets from base vertex, total size of array is
180 * target_count * vertex_count).
181 * @param targetTangents Morph target vertex tangents (delta offsets from base vertex, total size of array is
182 * target_count * vertex_count).
183 */
184 virtual void SetMorphTargetData(size_t submeshIndex, const DataBuffer& basePositions, const DataBuffer& baseNormals,
185 const DataBuffer& baseTangents, const DataBuffer& targetPositions, const DataBuffer& targetNormals,
186 const DataBuffer& targetTangents) = 0;
187
188 /** Returns all vertex data of this mesh. */
189 virtual BASE_NS::array_view<const uint8_t> GetVertexData() const = 0;
190
191 /** Returns all index data of this mesh. */
192 virtual BASE_NS::array_view<const uint8_t> GetIndexData() const = 0;
193
194 /** Returns all joint data of this mesh. */
195 virtual BASE_NS::array_view<const uint8_t> GetJointData() const = 0;
196
197 /** Returns all morph target data of this mesh. */
198 virtual BASE_NS::array_view<const uint8_t> GetMorphTargetData() const = 0;
199
200 /**
201 * Returns an array of joint bounds data. Each joint that is referenced by the vertex joint data will
202 * be represented by 6 values defining the min and max bounds defining the bounds for that joint.
203 */
204 virtual BASE_NS::array_view<const float> GetJointBoundsData() const = 0;
205
206 /** Returns all submeshes of this mesh. */
207 virtual BASE_NS::array_view<const MeshComponent::Submesh> GetSubmeshes() const = 0;
208
209 /** Returns total vertex count in this mesh, note that this function should be called after Allocate() has been
210 * called. */
211 virtual uint32_t GetVertexCount() const = 0;
212
213 /** Returns total index count in this mesh, note that 16bit indices are packed (two per one 32-bit slot) and there
214 * might be padding involved. */
215 virtual uint32_t GetIndexCount() const = 0;
216
217 /** Creates GPU buffers and copies the data passed in by the Set*Data calls.
218 */
219 virtual void CreateGpuResources() = 0;
220
221 /** Creates GPU buffers and copies the data passed in by the Set*Data calls.
222 * @param Additional create info with additional flags for buffers.
223 */
224 virtual void CreateGpuResources(const GpuBufferCreateInfo& createInfo) = 0;
225
226 /** Create a mesh entity with a mesh component from the previously given data (submeshes, vertices, indices etc).
227 * @param ecs The ECS instance.
228 * @return The created entity, or an invalid entity if there is no mesh data or if an error occurred.
229 * @note The mesh component owns the attached GPU resources.
230 */
231 virtual CORE_NS::Entity CreateMesh(CORE_NS::IEcs& ecs) const = 0;
232
233 /** Create a mesh entity with a mesh component from the previously given data (submeshes, vertices, indices etc).
234 * @param ecs The ECS instance.
235 * @param meshEntity If valid, append to the mesh component of this entity (or create a new component).
236 * @return The created entity, or an invalid entity if there is no mesh data or if an error occurred.
237 * @note The mesh component owns the attached GPU resources.
238 */
239 virtual CORE_NS::Entity CreateMesh(CORE_NS::IEcs& ecs, CORE_NS::Entity meshEntity) const = 0;
240
241 protected:
242 IMeshBuilder() = default;
243 virtual ~IMeshBuilder() = default;
244 };
245
GetName(const IMeshBuilder *)246 inline constexpr BASE_NS::string_view GetName(const IMeshBuilder*)
247 {
248 return "IMeshBuilder";
249 }
250 CORE3D_END_NAMESPACE()
251
252 #endif // API_3D_UTIL_IMESH_BUILDER_H
253