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