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