[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / mesh-definition.h
1 #ifndef DALI_SCENE3D_LOADER_MESH_DEFINITION_H
2 #define DALI_SCENE3D_LOADER_MESH_DEFINITION_H
3 /*
4  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 // EXTERNAL INCLUDES
21 #include <dali/public-api/common/vector-wrapper.h>
22 #include <memory>
23
24 // INTERNAL INCLUDES
25 #include <dali-scene3d/public-api/api.h>
26 #include <dali-scene3d/public-api/loader/blend-shape-details.h>
27 #include <dali-scene3d/public-api/loader/buffer-definition.h>
28 #include <dali-scene3d/public-api/loader/index.h>
29 #include <dali-scene3d/public-api/loader/mesh-geometry.h>
30 #include <dali-scene3d/public-api/loader/utils.h>
31
32 namespace Dali::Scene3D::Loader
33 {
34 /**
35  * @brief Defines a mesh with its attributes, the primitive type to render it as,
36  *  and the file to load it from with the offset and length information for the
37  *  individual attribute buffers.
38  * @SINCE_2_0.7
39  */
40 struct DALI_SCENE3D_API MeshDefinition
41 {
42   using Vector = std::vector<std::pair<MeshDefinition, MeshGeometry>>;
43
44   enum : uint32_t
45   {
46     INVALID = std::numeric_limits<uint32_t>::max()
47   };
48
49   enum : uint32_t
50   {
51     MAX_NUMBER_OF_JOINT_SETS = 4
52   };
53
54   enum Flags : uint32_t
55   {
56     FLIP_UVS_VERTICAL = NthBit(0),
57     U32_INDICES       = NthBit(1), // default is unsigned short
58     U8_INDICES        = NthBit(2), // default is unsigned short
59     U16_JOINT_IDS     = NthBit(3), // default is floats
60     U8_JOINT_IDS      = NthBit(4),
61     U16_WEIGHT        = NthBit(5), // default is floats
62     U8_WEIGHT         = NthBit(6),
63     S8_POSITION       = NthBit(7),  // default is floats
64     U8_POSITION       = NthBit(8),  // default is floats
65     S16_POSITION      = NthBit(9),  // default is floats
66     U16_POSITION      = NthBit(10), // default is floats
67     S8_NORMAL         = NthBit(11), // default is floats
68     S16_NORMAL        = NthBit(12), // default is floats
69     S8_TANGENT        = NthBit(13), // default is floats
70     S16_TANGENT       = NthBit(14), // default is floats
71     S8_TEXCOORD       = NthBit(15), // default is floats
72     U8_TEXCOORD       = NthBit(16), // default is floats
73     S16_TEXCOORD      = NthBit(17), // default is floats
74     U16_TEXCOORD      = NthBit(18), // default is floats
75   };
76
77   enum FlagMasks : uint32_t
78   {
79     POSITIONS_MASK = 0x780,
80     NORMALS_MASK   = 0x1800,
81     TANGENTS_MASK  = 0x6000,
82     TEXCOORDS_MASK = 0x78000,
83   };
84
85   enum Attributes
86   {
87     INDICES           = NthBit(0),
88     POSITIONS         = NthBit(1),
89     NORMALS           = NthBit(2),
90     TEX_COORDS        = NthBit(3),
91     TANGENTS          = NthBit(4),
92     LEGACY_BITANGENTS = NthBit(5), // these are ignored; we're calculating them in the (PBR) shader.
93     JOINTS_0          = NthBit(6),
94     WEIGHTS_0         = NthBit(7),
95   };
96
97   /**
98    * @brief Describes raw data in terms of its position and size in a buffer.
99    *
100    * All units in bytes.
101    * @SINCE_2_0.7
102    */
103   struct Blob
104   {
105     uint32_t           mOffset          = INVALID; // the default means that the blob is undefined.
106     uint32_t           mLength          = 0;       // if the blob is undefined, its data may still be generated. This is enabled by setting length to some non-0 value. Refer to MeshDefinition for details.
107     uint16_t           mStride          = 0;       // ignore if 0
108     uint16_t           mElementSizeHint = 0;       // ignore if 0 or stride == 0
109     std::vector<float> mMin;
110     std::vector<float> mMax;
111
112     static void ComputeMinMax(std::vector<float>& min, std::vector<float>& max, uint32_t numComponents, uint32_t count, const float* values);
113
114     static void ApplyMinMax(const std::vector<float>& min, const std::vector<float>& max, uint32_t count, float* values, std::vector<uint32_t>* sparseIndices = nullptr);
115
116     Blob() = default;
117
118     Blob(const Blob&) = default;
119     Blob& operator=(const Blob&) = default;
120
121     Blob(Blob&&)  = default;
122     Blob& operator=(Blob&&) = default;
123
124     Blob(uint32_t offset, uint32_t length, uint16_t stride = 0, uint16_t elementSizeHint = 0, const std::vector<float>& min = {}, const std::vector<float>& max = {});
125
126     /**
127      * @brief Calculates the size of a tightly-packed buffer for the elements from the blob.
128      * @SINCE_2_0.7
129      */
130     uint32_t GetBufferSize() const;
131
132     /**
133      * @brief Convenience method to tell whether a Blob has meaningful data.
134      * @SINCE_2_0.7
135      */
136     bool IsDefined() const
137     {
138       return mOffset != INVALID;
139     }
140
141     /**
142      * @brief Convenience method to tell whether the elements stored in the blob follow each other tightly.
143      *
144      * The opposite would be interleaving.
145      * @SINCE_2_0.7
146      */
147     bool IsConsecutive() const
148     {
149       return mStride == 0 || mStride == mElementSizeHint;
150     }
151
152     /**
153      * @brief Computes the min / max of the input value data.
154      *
155      * The min and max are stored in mMin and mMax.
156      * @SINCE_2_0.7
157      * @param[in] numComponents number of components of data type. e.g., 3 for Vector3.
158      * @param[in] count The number of data.
159      * @param[in] values Data for the mesh.
160      */
161     void ComputeMinMax(uint32_t numComponents, uint32_t count, float* values);
162
163     /**
164      * @brief Applies the min / max values, if they're defined in the model
165      *
166      * @SINCE_2_0.7
167      * @param[in] count The number of data.
168      * @param[in] values Data for the mesh that min / max values will be applied.
169      * @param[in] sparseIndices Pointer to array of sparse indices (or nullptr if not provided)
170      */
171     void ApplyMinMax(uint32_t count, float* values, std::vector<uint32_t>* sparseIndices = nullptr) const;
172   };
173
174   /**
175    * @brief A sparse blob describes a change in a reference Blob.
176    * @p indices describe what positions of the reference Blob change and
177    * @p values describe the new values.
178    * @SINCE_2_0.7
179    */
180   struct SparseBlob
181   {
182     SparseBlob() = default;
183
184     SparseBlob(const SparseBlob&) = default;
185     SparseBlob& operator=(const SparseBlob&) = default;
186
187     SparseBlob(SparseBlob&&) = default;
188     SparseBlob& operator=(SparseBlob&&) = default;
189
190     SparseBlob(const Blob& indices, const Blob& values, uint32_t count);
191     SparseBlob(Blob&& indices, Blob&& values, uint32_t count);
192
193     Blob     mIndices;
194     Blob     mValues;
195     uint32_t mCount = 0u;
196   };
197
198   struct Accessor
199   {
200     Blob                        mBlob;
201     std::unique_ptr<SparseBlob> mSparse;
202     Index                       mBufferIdx = INVALID_INDEX;
203     bool                        mNormalized{false};
204
205     Accessor() = default;
206
207     Accessor(const Accessor&) = delete;
208     Accessor& operator=(const Accessor&) = delete;
209
210     Accessor(Accessor&&) = default;
211     Accessor& operator=(Accessor&&) = default;
212
213     Accessor(const MeshDefinition::Blob&       blob,
214              const MeshDefinition::SparseBlob& sparse,
215              Index                             bufferIndex = INVALID_INDEX,
216              bool                              normalized = false);
217
218     Accessor(MeshDefinition::Blob&&       blob,
219              MeshDefinition::SparseBlob&& sparse,
220              Index                        bufferIndex = INVALID_INDEX,
221              bool                         normalized = false);
222
223     bool IsDefined() const
224     {
225       return mBlob.IsDefined() || (mSparse && (mSparse->mIndices.IsDefined() && mSparse->mValues.IsDefined()));
226     }
227   };
228
229   /**
230    * @brief Stores a blend shape.
231    * @SINCE_2_0.7
232    */
233   struct BlendShape
234   {
235     std::string name;
236     Accessor    deltas;
237     Accessor    normals;
238     Accessor    tangents;
239     float       weight = 0.f;
240     uint32_t    mFlags = 0x0;
241   };
242
243   struct RawData
244   {
245     struct Attrib
246     {
247       std::string          mName;
248       Property::Type       mType;
249       uint32_t             mNumElements;
250       std::vector<uint8_t> mData;
251
252       void AttachBuffer(Geometry& g) const;
253     };
254
255     std::vector<uint16_t> mIndices;
256     std::vector<Attrib>   mAttribs;
257
258     unsigned int        mBlendShapeBufferOffset{0};
259     Dali::Vector<float> mBlendShapeUnnormalizeFactor;
260     PixelData           mBlendShapeData;
261   };
262
263   MeshDefinition() = default;
264
265   MeshDefinition(const MeshDefinition&) = delete;
266   MeshDefinition& operator=(const MeshDefinition&) = delete;
267
268   MeshDefinition(MeshDefinition&&) = default;
269   MeshDefinition& operator=(MeshDefinition&&) = default;
270
271   /**
272    * @brief Determines whether the mesh definition is that of a quad.
273    * @SINCE_2_0.7
274    */
275   bool IsQuad() const;
276
277   /**
278    * @brief Determines whether the mesh is used for skeletal animation.
279    * @SINCE_2_0.7
280    */
281   bool IsSkinned() const;
282
283   /**
284    * @brief Determines if the mesh has any vertex colors
285    */
286   bool HasVertexColor() const;
287
288   /**
289    * @brief Returns the number of joint sets defined by the mesh
290    *
291    * @SINCE_2_2.52
292    * @note Clamped to 4 to minimise GPU attrs.
293    */
294   uint32_t GetNumberOfJointSets() const;
295
296   /**
297    * @brief Whether the mesh has blend shapes.
298    * @SINCE_2_0.7
299    */
300   bool HasBlendShapes() const;
301
302   /**
303    * @brief Requests normals to be generated.
304    * @SINCE_2_0.7
305    * @note Generation happens in LoadRaw().
306    * @note Must have Vector3 positions defined.
307    */
308   void RequestNormals();
309
310   /**
311    * @brief Requests tangents to be generated.
312    * @SINCE_2_0.7
313    * @note Generation happens in LoadRaw().
314    * @note Must have Vector3 normals defined.
315    */
316   void RequestTangents();
317
318   /**
319    * @brief Loads raw geometry data, which includes index (optional) and attribute buffers, as well as blend shape data.
320    *
321    * This is then returned.
322    * @SINCE_2_0.7
323    * @note This can be done on any thread.
324    */
325   RawData LoadRaw(const std::string& modelsPath, BufferDefinition::Vector& buffers);
326
327   /**
328    * @brief Creates a MeshGeometry based firstly on the value of the uri member:
329    *  if it is "quad", a textured quad is created; otherwise it uses the
330    *  attribute (and index) buffers and blend shape information (if available)
331    *  from @a raw.
332    *  If mFlipVertical was set, the UVs are flipped in Y, i.e. v = 1.0 - v.
333    * @SINCE_2_0.7
334    */
335   MeshGeometry Load(RawData&& raw) const;
336
337   /**
338    * @brief Retrieves what Components information is in this mesh's BlendShape.
339    *
340    * @SINCE_2_2.21
341    * @param[out] hasPositions True if the BlendShape has position components
342    * @param[out] hasNormals True if the BlendShape has normal components
343    * @param[out] hasTangents True if the BlendShape has tangent components
344    */
345   void RetrieveBlendShapeComponents(bool& hasPositions, bool& hasNormals, bool& hasTangents) const;
346
347 public: // DATA
348   std::shared_ptr<RawData> mRawData;
349   uint32_t                 mFlags         = 0x0;
350   Geometry::Type           mPrimitiveType = Geometry::TRIANGLES;
351   std::string              mUri; // When the mesh data is loaded from embedded resources, this URI is used as a data stream.
352   Accessor                 mIndices;
353   Accessor                 mPositions;
354   Accessor                 mNormals;  // data can be generated based on positions
355   Accessor                 mTangents; // data can be generated based on normals and texCoords (the latter isn't mandatory; the results will be better if available)
356   std::vector<Accessor>    mTexCoords;
357   std::vector<Accessor>    mColors;
358   std::vector<Accessor>    mJoints;
359   std::vector<Accessor>    mWeights;
360   Property::Type           mTangentType{Property::VECTOR3};
361
362   Blob                    mBlendShapeHeader;
363   std::vector<BlendShape> mBlendShapes;
364   BlendShapes::Version    mBlendShapeVersion = BlendShapes::Version::INVALID;
365
366   Index          mSkeletonIdx = INVALID_INDEX;
367   ModelPrimitive mModelPrimitive;
368 };
369
370 } // namespace Dali::Scene3D::Loader
371
372 #endif //DALI_SCENE3D_LOADER_MESH_DEFINITION_H