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