1 #ifndef DALI_SCENE3D_LOADER_MESH_DEFINITION_H
2 #define DALI_SCENE3D_LOADER_MESH_DEFINITION_H
4 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <dali/public-api/common/vector-wrapper.h>
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>
32 namespace Dali::Scene3D::Loader
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.
40 struct DALI_SCENE3D_API MeshDefinition
42 using Vector = std::vector<std::pair<MeshDefinition, MeshGeometry>>;
46 INVALID = std::numeric_limits<uint32_t>::max()
51 MAX_NUMBER_OF_JOINT_SETS = 4
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
77 enum FlagMasks : uint32_t
79 POSITIONS_MASK = 0x780,
80 NORMALS_MASK = 0x1800,
81 TANGENTS_MASK = 0x6000,
82 TEXCOORDS_MASK = 0x78000,
88 POSITIONS = NthBit(1),
90 TEX_COORDS = NthBit(3),
92 LEGACY_BITANGENTS = NthBit(5), // these are ignored; we're calculating them in the (PBR) shader.
94 WEIGHTS_0 = NthBit(7),
98 * @brief Describes raw data in terms of its position and size in a buffer.
100 * All units in bytes.
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;
112 static void ComputeMinMax(std::vector<float>& min, std::vector<float>& max, uint32_t numComponents, uint32_t count, const float* values);
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);
118 Blob(const Blob&) = default;
119 Blob& operator=(const Blob&) = default;
121 Blob(Blob&&) = default;
122 Blob& operator=(Blob&&) = default;
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 = {});
127 * @brief Calculates the size of a tightly-packed buffer for the elements from the blob.
130 uint32_t GetBufferSize() const;
133 * @brief Convenience method to tell whether a Blob has meaningful data.
136 bool IsDefined() const
138 return mOffset != INVALID;
142 * @brief Convenience method to tell whether the elements stored in the blob follow each other tightly.
144 * The opposite would be interleaving.
147 bool IsConsecutive() const
149 return mStride == 0 || mStride == mElementSizeHint;
153 * @brief Computes the min / max of the input value data.
155 * The min and max are stored in mMin and mMax.
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.
161 void ComputeMinMax(uint32_t numComponents, uint32_t count, float* values);
164 * @brief Applies the min / max values, if they're defined in the model
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)
171 void ApplyMinMax(uint32_t count, float* values, std::vector<uint32_t>* sparseIndices = nullptr) const;
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.
182 SparseBlob() = default;
184 SparseBlob(const SparseBlob&) = default;
185 SparseBlob& operator=(const SparseBlob&) = default;
187 SparseBlob(SparseBlob&&) = default;
188 SparseBlob& operator=(SparseBlob&&) = default;
190 SparseBlob(const Blob& indices, const Blob& values, uint32_t count);
191 SparseBlob(Blob&& indices, Blob&& values, uint32_t count);
195 uint32_t mCount = 0u;
201 std::unique_ptr<SparseBlob> mSparse;
202 Index mBufferIdx = INVALID_INDEX;
203 bool mNormalized{false};
205 Accessor() = default;
207 Accessor(const Accessor&) = delete;
208 Accessor& operator=(const Accessor&) = delete;
210 Accessor(Accessor&&) = default;
211 Accessor& operator=(Accessor&&) = default;
213 Accessor(const MeshDefinition::Blob& blob,
214 const MeshDefinition::SparseBlob& sparse,
215 Index bufferIndex = INVALID_INDEX,
216 bool normalized = false);
218 Accessor(MeshDefinition::Blob&& blob,
219 MeshDefinition::SparseBlob&& sparse,
220 Index bufferIndex = INVALID_INDEX,
221 bool normalized = false);
223 bool IsDefined() const
225 return mBlob.IsDefined() || (mSparse && (mSparse->mIndices.IsDefined() && mSparse->mValues.IsDefined()));
230 * @brief Stores a blend shape.
240 uint32_t mFlags = 0x0;
248 Property::Type mType;
249 uint32_t mNumElements;
250 std::vector<uint8_t> mData;
252 void AttachBuffer(Geometry& g) const;
255 std::vector<uint16_t> mIndices;
256 std::vector<Attrib> mAttribs;
258 unsigned int mBlendShapeBufferOffset{0};
259 Dali::Vector<float> mBlendShapeUnnormalizeFactor;
260 PixelData mBlendShapeData;
263 MeshDefinition() = default;
265 MeshDefinition(const MeshDefinition&) = delete;
266 MeshDefinition& operator=(const MeshDefinition&) = delete;
268 MeshDefinition(MeshDefinition&&) = default;
269 MeshDefinition& operator=(MeshDefinition&&) = default;
272 * @brief Determines whether the mesh definition is that of a quad.
278 * @brief Determines whether the mesh is used for skeletal animation.
281 bool IsSkinned() const;
284 * @brief Determines if the mesh has any vertex colors
286 bool HasVertexColor() const;
289 * @brief Returns the number of joint sets defined by the mesh
292 * @note Clamped to 4 to minimise GPU attrs.
294 uint32_t GetNumberOfJointSets() const;
297 * @brief Whether the mesh has blend shapes.
300 bool HasBlendShapes() const;
303 * @brief Requests normals to be generated.
305 * @note Generation happens in LoadRaw().
306 * @note Must have Vector3 positions defined.
308 void RequestNormals();
311 * @brief Requests tangents to be generated.
313 * @note Generation happens in LoadRaw().
314 * @note Must have Vector3 normals defined.
316 void RequestTangents();
319 * @brief Loads raw geometry data, which includes index (optional) and attribute buffers, as well as blend shape data.
321 * This is then returned.
323 * @note This can be done on any thread.
325 RawData LoadRaw(const std::string& modelsPath, BufferDefinition::Vector& buffers);
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)
332 * If mFlipVertical was set, the UVs are flipped in Y, i.e. v = 1.0 - v.
335 MeshGeometry Load(RawData&& raw) const;
338 * @brief Retrieves what Components information is in this mesh's BlendShape.
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
345 void RetrieveBlendShapeComponents(bool& hasPositions, bool& hasNormals, bool& hasTangents) const;
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.
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};
362 Blob mBlendShapeHeader;
363 std::vector<BlendShape> mBlendShapes;
364 BlendShapes::Version mBlendShapeVersion = BlendShapes::Version::INVALID;
366 Index mSkeletonIdx = INVALID_INDEX;
367 ModelPrimitive mModelPrimitive;
370 } // namespace Dali::Scene3D::Loader
372 #endif //DALI_SCENE3D_LOADER_MESH_DEFINITION_H