[dali_2.2.12] 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 // INTERNAL INCLUDES
21 #include "dali-scene3d/public-api/api.h"
22 #include "dali-scene3d/public-api/loader/blend-shape-details.h"
23 #include "dali-scene3d/public-api/loader/index.h"
24 #include "dali-scene3d/public-api/loader/mesh-geometry.h"
25 #include "dali-scene3d/public-api/loader/utils.h"
26 #include <dali-scene3d/public-api/loader/buffer-definition.h>
27
28 // EXTERNAL INCLUDES
29 #include <memory>
30 #include "dali/public-api/common/vector-wrapper.h"
31
32 namespace Dali
33 {
34 namespace Scene3D
35 {
36 namespace Loader
37 {
38 /**
39  * @brief Defines a mesh with its attributes, the primitive type to render it as,
40  *  and the file to load it from with the offset and length information for the
41  *  individual attribute buffers.
42  */
43 struct DALI_SCENE3D_API MeshDefinition
44 {
45   using Vector = std::vector<std::pair<MeshDefinition, MeshGeometry>>;
46
47   enum : uint32_t
48   {
49     INVALID = std::numeric_limits<uint32_t>::max()
50   };
51
52   enum Flags : uint16_t
53   {
54     FLIP_UVS_VERTICAL = NthBit(0),
55     U32_INDICES       = NthBit(1), // default is unsigned short
56     U8_INDICES        = NthBit(2), // default is unsigned short
57     U16_JOINT_IDS     = NthBit(3), // default is floats
58     U8_JOINT_IDS      = NthBit(4),
59   };
60
61   enum Attributes
62   {
63     INDICES           = NthBit(0),
64     POSITIONS         = NthBit(1),
65     NORMALS           = NthBit(2),
66     TEX_COORDS        = NthBit(3),
67     TANGENTS          = NthBit(4),
68     LEGACY_BITANGENTS = NthBit(5), // these are ignored; we're calculating them in the (PBR) shader.
69     JOINTS_0          = NthBit(6),
70     WEIGHTS_0         = NthBit(7),
71   };
72
73   /**
74    * @brief Describes raw data in terms of its position and size in a buffer.
75    *  All units in bytes.
76    */
77   struct Blob
78   {
79     uint32_t           mOffset          = INVALID; // the default means that the blob is undefined.
80     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.
81     uint16_t           mStride          = 0;       // ignore if 0
82     uint16_t           mElementSizeHint = 0;       // ignore if 0 or stride == 0
83     std::vector<float> mMin;
84     std::vector<float> mMax;
85
86     static void ComputeMinMax(std::vector<float>& min, std::vector<float>& max, uint32_t numComponents, uint32_t count, const float* values);
87
88     static void ApplyMinMax(const std::vector<float>& min, const std::vector<float>& max, uint32_t count, float* values);
89
90     Blob() = default;
91
92     Blob(const Blob&) = default;
93     Blob& operator=(const Blob&) = default;
94
95     Blob(Blob&&)  = default;
96     Blob& operator=(Blob&&) = default;
97
98     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 = {});
99
100     /**
101      * @brief Calculates the size of a tightly-packed buffer for the elements from the blob.
102      */
103     uint32_t GetBufferSize() const;
104
105     /**
106      * @brief Convenience method to tell whether a Blob has meaningful data.
107      */
108     bool IsDefined() const
109     {
110       return mOffset != INVALID;
111     }
112
113     /**
114      * @brief Convenience method to tell whether the elements stored in the blob follow each
115      *  other tightly. The opposite would be interleaving.
116      */
117     bool IsConsecutive() const
118     {
119       return mStride == 0 || mStride == mElementSizeHint;
120     }
121
122     /**
123      * @brief Computes the min / max of the input value data.
124      * The min and max are stored in mMin and mMax.
125      *
126      * @param[in] numComponents number of components of data type. e.g., 3 for Vector3.
127      * @param[in] count The number of data.
128      * @param[in] values Data for the mesh.
129      */
130     void ComputeMinMax(uint32_t numComponents, uint32_t count, float* values);
131
132     /**
133      * @brief Applies the min / max values, if they're defined in the model
134      *
135      * @param[in] count The number of data.
136      * @param[in] values Data for the mesh that min / max values will be applied.
137      */
138     void ApplyMinMax(uint32_t count, float* values) const;
139   };
140
141   /**
142    * @brief A sparse blob describes a change in a reference Blob.
143    * @p indices describe what positions of the reference Blob change and
144    * @p values describe the new values.
145    */
146   struct SparseBlob
147   {
148     SparseBlob() = default;
149
150     SparseBlob(const SparseBlob&) = default;
151     SparseBlob& operator=(const SparseBlob&) = default;
152
153     SparseBlob(SparseBlob&&) = default;
154     SparseBlob& operator=(SparseBlob&&) = default;
155
156     SparseBlob(const Blob& indices, const Blob& values, uint32_t count);
157     SparseBlob(Blob&& indices, Blob&& values, uint32_t count);
158
159     Blob     mIndices;
160     Blob     mValues;
161     uint32_t mCount = 0u;
162   };
163
164   struct Accessor
165   {
166     Blob                        mBlob;
167     std::unique_ptr<SparseBlob> mSparse;
168     Index                       mBufferIdx = INVALID_INDEX;
169
170     Accessor() = default;
171
172     Accessor(const Accessor&) = delete;
173     Accessor& operator=(const Accessor&) = delete;
174
175     Accessor(Accessor&&) = default;
176     Accessor& operator=(Accessor&&) = default;
177
178     Accessor(const MeshDefinition::Blob&       blob,
179              const MeshDefinition::SparseBlob& sparse,
180              Index bufferIndex = INVALID_INDEX);
181     Accessor(MeshDefinition::Blob&&       blob,
182              MeshDefinition::SparseBlob&& sparse,
183              Index bufferIndex = INVALID_INDEX);
184
185     bool IsDefined() const
186     {
187       return mBlob.IsDefined() || (mSparse && (mSparse->mIndices.IsDefined() && mSparse->mValues.IsDefined()));
188     }
189   };
190
191   /**
192    * @brief Stores a blend shape.
193    */
194   struct BlendShape
195   {
196     std::string name;
197     Accessor    deltas;
198     Accessor    normals;
199     Accessor    tangents;
200     float       weight = 0.f;
201   };
202
203   struct RawData
204   {
205     struct Attrib
206     {
207       std::string          mName;
208       Property::Type       mType;
209       uint32_t             mNumElements;
210       std::vector<uint8_t> mData;
211
212       void AttachBuffer(Geometry& g) const;
213     };
214
215     std::vector<uint16_t> mIndices;
216     std::vector<Attrib>   mAttribs;
217
218     unsigned int        mBlendShapeBufferOffset{0};
219     Dali::Vector<float> mBlendShapeUnnormalizeFactor;
220     PixelData           mBlendShapeData;
221   };
222
223   MeshDefinition() = default;
224
225   MeshDefinition(const MeshDefinition&) = delete;
226   MeshDefinition& operator=(const MeshDefinition&) = delete;
227
228   MeshDefinition(MeshDefinition&&) = default;
229   MeshDefinition& operator=(MeshDefinition&&) = default;
230
231   /**
232    * @brief Determines whether the mesh definition is that of a quad.
233    */
234   bool IsQuad() const;
235
236   /**
237    * @brief Determines whether the mesh is used for skeletal animation.
238    */
239   bool IsSkinned() const;
240
241   /**
242    * @brief Whether the mesh has blend shapes.
243    */
244   bool HasBlendShapes() const;
245
246   /**
247    * @brief Requests normals to be generated.
248    * @note Generation happens in LoadRaw().
249    * @note Must have Vector3 positions defined.
250    */
251   void RequestNormals();
252
253   /**
254    * @brief Requests tangents to be generated.
255    * @note Generation happens in LoadRaw().
256    * @note Must have Vector3 normals defined.
257    */
258   void RequestTangents();
259
260   /**
261    * @brief Loads raw geometry data, which includes index (optional) and
262    *  attribute buffers, as well as blend shape data. This is then returned.
263    * @note This can be done on any thread.
264    */
265   RawData LoadRaw(const std::string& modelsPath, BufferDefinition::Vector& buffers);
266
267   /**
268    * @brief Creates a MeshGeometry based firstly on the value of the uri member:
269    *  if it is "quad", a textured quad is created; otherwise it uses the
270    *  attribute (and index) buffers and blend shape information (if available)
271    *  from @a raw.
272    *  If mFlipVertical was set, the UVs are flipped in Y, i.e. v = 1.0 - v.
273    */
274   MeshGeometry Load(RawData&& raw) const;
275
276 public: // DATA
277   std::shared_ptr<RawData> mRawData;
278   uint32_t                 mFlags         = 0x0;
279   Geometry::Type           mPrimitiveType = Geometry::TRIANGLES;
280   std::string              mUri; // When the mesh data is loaded from embedded resources, this URI is used as a data stream.
281   Accessor                 mIndices;
282   Accessor                 mPositions;
283   Accessor                 mNormals; // data can be generated based on positions
284   Accessor                 mTexCoords;
285   Accessor                 mColors;
286   Accessor                 mTangents; // data can be generated based on normals and texCoords (the latter isn't mandatory; the results will be better if available)
287   Accessor                 mJoints0;
288   Accessor                 mWeights0;
289   Property::Type           mTangentType{Property::VECTOR3};
290
291   Blob                    mBlendShapeHeader;
292   std::vector<BlendShape> mBlendShapes;
293   BlendShapes::Version    mBlendShapeVersion = BlendShapes::Version::INVALID;
294
295   Index mSkeletonIdx = INVALID_INDEX;
296 };
297
298 } // namespace Loader
299 } // namespace Scene3D
300 } // namespace Dali
301
302 #endif //DALI_SCENE3D_LOADER_MESH_DEFINITION_H