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 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     /** Submesh attributes */
44     struct Submesh {
45         /** Vertex count */
46         uint32_t vertexCount { 0 };
47         /** Index count */
48         uint32_t indexCount { 0 };
49         /** Instance count */
50         uint32_t instanceCount { 1 };
51         /** Morph target count */
52         uint32_t morphTargetCount { 0 };
53         /** Index type */
54         RENDER_NS::IndexType indexType { RENDER_NS::IndexType::CORE_INDEX_TYPE_UINT32 };
55 
56         /** Material */
57         CORE_NS::Entity material {};
58         /** Tangents */
59         bool tangents { false };
60         /** Colors */
61         bool colors { false };
62         /** Joints */
63         bool joints { false };
64     };
65 
66     /** GPU buffer create info */
67     struct GpuBufferCreateInfo {
68         /** Vertex buffer additional usage flags */
69         RENDER_NS::BufferUsageFlags vertexBufferFlags { 0U };
70         /** Index buffer additional usage flags */
71         RENDER_NS::BufferUsageFlags indexBufferFlags { 0U };
72         /** Morph buffer additional usage flags */
73         RENDER_NS::BufferUsageFlags morphBufferFlags { 0U };
74     };
75 
76     /** Setup vertex declaration and submesh count for the builder. Also resets the builder for re-use.
77      */
78     virtual void Initialize(
79         const RENDER_NS::VertexInputDeclarationView& vertexInputDeclaration, size_t submeshCount) = 0;
80 
81     /** Add a submesh and related import info to this mesh.
82      * @param submesh Submesh import information that is used to determine memory requirements etc.
83      */
84     virtual void AddSubmesh(const Submesh& submesh) = 0;
85 
86     /** Returns Import info for given submesh.
87      * @param index Index of the submesh.
88      * @return Import information for the given submesh.
89      */
90     virtual const Submesh& GetSubmesh(size_t index) const = 0;
91 
92     /** Allocates memory for this mesh, should be called after all submeshes have been added to this mesh and before
93      * data is being fed to submeshes. */
94     virtual void Allocate() = 0;
95 
96     /** Struct for passing data to the mesh builder.*/
97     struct DataBuffer {
98         /** Format of each element in buffer. e.g. three float values per element would be R32G32B32_SFLOAT. */
99         BASE_NS::Format format;
100         /** Offset between elements. This should match the size of one element for tightly packed values. */
101         uint32_t stride;
102         /** Byte arrays which will be interpreted based on format and stride. */
103         BASE_NS::array_view<const uint8_t> buffer;
104     };
105 
106     /** Set geometry data for a given submesh.
107      * @param submeshIndex Index of the submesh.
108      * @param positions Position data (3 * vertexCount values), this parameter is required.
109      * @param normals Normal data (3 * vertexCount values), this parameter is required.
110      * @param texcoords0 Texture coordinate 0 data (2 * vertexCount values), this parameter is required.
111      * @param texcoords1 Texture coordinate 1 data (2 * vertexCount values), this parameter is optional.
112      * @param tangents Tangent data (4 * vertexCount values), this parameter is optional.
113      * @param colors Vertex color data  (4 * vertexCount values), this parameter is optional.
114      */
115     virtual void SetVertexData(size_t submeshIndex, const DataBuffer& positions, const DataBuffer& normals,
116         const DataBuffer& texcoords0, const DataBuffer& texcoords1, const DataBuffer& tangents,
117         const DataBuffer& colors) = 0;
118 
119     /** Set Axis-aligned bounding box for a submesh.
120      * @param submeshIndex Index of the submesh.
121      * @param min Minimum corner.
122      * @param max Minimum corner.
123      */
124     virtual void SetAABB(size_t submeshIndex, const BASE_NS::Math::Vec3& min, const BASE_NS::Math::Vec3& max) = 0;
125 
126     /** Calculate Axis-aligned bounding box for a submesh.
127      * @param submeshIndex Index of the submesh.
128      * @param positions Array of vertex positions in submesh.
129      */
130     virtual void CalculateAABB(size_t submeshIndex, const DataBuffer& positions) = 0;
131 
132     /** Set triangle indices for a submesh.
133      * @param submeshIndex Index of the submesh.
134      * @param indices Index data.
135      */
136     virtual void SetIndexData(size_t submeshIndex, const DataBuffer& indices) = 0;
137 
138     /** Set Joint data for a submesh.
139      * @param submeshIndex Index of the submesh.
140      * @param jointData Joint indices per vertex, (4 indices per bone).
141      * @param weightData Joint weights per vertex , (4 weights per bone).
142      * @param vertexPositions Position data that is used for skin bounds calculations (3 * vertexCount
143      * values), this data should match the data set with SetVertexData().
144      */
145     virtual void SetJointData(size_t submeshIndex, const DataBuffer& jointData, const DataBuffer& weightData,
146         const DataBuffer& vertexPositions) = 0;
147 
148     /** Set Morph targets for a submesh.
149      * @param submeshIndex Index of the submesh.
150      * @param basePositions Initial vertex positions (base pose).
151      * @param baseNormals Initial vertex normals (base pose).
152      * @param baseTangents Initial vertex tangents (base pose).
153      * @param targetPositions Morph target vertex positions (delta offsets from base vertex, total size of array is
154      * target_count * vertex_count).
155      * @param targetNormals Morph target vertex normals (delta offsets from base vertex, total size of array is
156      * target_count * vertex_count).
157      * @param targetTangents Morph target vertex tangents (delta offsets from base vertex, total size of array is
158      * target_count * vertex_count).
159      */
160     virtual void SetMorphTargetData(size_t submeshIndex, const DataBuffer& basePositions, const DataBuffer& baseNormals,
161         const DataBuffer& baseTangents, const DataBuffer& targetPositions, const DataBuffer& targetNormals,
162         const DataBuffer& targetTangents) = 0;
163 
164     /** Returns all vertex data of this mesh. */
165     virtual BASE_NS::array_view<const uint8_t> GetVertexData() const = 0;
166 
167     /** Returns all index data of this mesh. */
168     virtual BASE_NS::array_view<const uint8_t> GetIndexData() const = 0;
169 
170     /** Returns all joint data of this mesh. */
171     virtual BASE_NS::array_view<const uint8_t> GetJointData() const = 0;
172 
173     /** Returns all morph target data of this mesh. */
174     virtual BASE_NS::array_view<const uint8_t> GetMorphTargetData() const = 0;
175 
176     /**
177      * Returns an array of joint bounds data. Each joint that is referenced by the vertex joint data will
178      * be represented by 6 values defining the min and max bounds defining the bounds for that joint.
179      */
180     virtual BASE_NS::array_view<const float> GetJointBoundsData() const = 0;
181 
182     /** Returns all submeshes of this mesh. */
183     virtual BASE_NS::array_view<const MeshComponent::Submesh> GetSubmeshes() const = 0;
184 
185     /** Returns total vertex count in this mesh, note that this function should be called after Allocate() has been
186      * called. */
187     virtual uint32_t GetVertexCount() const = 0;
188 
189     /** Returns total index count in this mesh, note that 16bit indices are packed (two per one 32-bit slot) and there
190      * might be padding involved. */
191     virtual uint32_t GetIndexCount() const = 0;
192 
193     /** Creates GPU buffers and copies the data passed in by the Set*Data calls.
194      */
195     virtual void CreateGpuResources() = 0;
196 
197     /** Creates GPU buffers and copies the data passed in by the Set*Data calls.
198      * @param Additional create info with additional flags for buffers.
199      */
200     virtual void CreateGpuResources(const GpuBufferCreateInfo& createInfo) = 0;
201 
202     /** Helper for creating an entity with a mesh component. The mesh component is filled using the previously given
203      * data (submeshes, vertex data, index data, etc.). NOTE: the mesh component owns the attached GPU resources.
204      */
205     virtual CORE_NS::Entity CreateMesh(CORE_NS::IEcs& ecs) const = 0;
206 
207 protected:
208     IMeshBuilder() = default;
209     virtual ~IMeshBuilder() = default;
210 };
211 
GetName(const IMeshBuilder *)212 inline constexpr BASE_NS::string_view GetName(const IMeshBuilder*)
213 {
214     return "IMeshBuilder";
215 }
216 CORE3D_END_NAMESPACE()
217 
218 #endif // API_3D_UTIL_IMESH_BUILDER_H
219