Coverage Report

Created: 2025-08-03 06:54

/src/assimp/code/AssetLib/Collada/ColladaParser.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 Open Asset Import Library (assimp)
3
 ----------------------------------------------------------------------
4
5
 Copyright (c) 2006-2025, assimp team
6
7
 All rights reserved.
8
9
 Redistribution and use of this software in source and binary forms,
10
 with or without modification, are permitted provided that the
11
 following conditions are met:
12
13
 * Redistributions of source code must retain the above
14
 copyright notice, this list of conditions and the
15
 following disclaimer.
16
17
 * Redistributions in binary form must reproduce the above
18
 copyright notice, this list of conditions and the
19
 following disclaimer in the documentation and/or other
20
 materials provided with the distribution.
21
22
 * Neither the name of the assimp team, nor the names of its
23
 contributors may be used to endorse or promote products
24
 derived from this software without specific prior
25
 written permission of the assimp team.
26
27
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30
 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31
 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32
 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39
 ----------------------------------------------------------------------
40
 */
41
42
/** @file ColladaParser.h
43
 *  @brief Defines the parser helper class for the collada loader
44
 */
45
46
#pragma once
47
#ifndef AI_COLLADAPARSER_H_INC
48
#define AI_COLLADAPARSER_H_INC
49
50
#include "ColladaHelper.h"
51
#include <assimp/ai_assert.h>
52
#include <assimp/XmlParser.h>
53
54
#include <map>
55
56
namespace Assimp {
57
58
class ZipArchiveIOSystem;
59
60
// ------------------------------------------------------------------------------------------
61
/** Parser helper class for the Collada loader.
62
     *
63
     *  Does all the XML reading and builds internal data structures from it,
64
     *  but leaves the resolving of all the references to the loader.
65
     */
66
class ColladaParser {
67
    friend class ColladaLoader;
68
69
public:
70
    /// Map for generic metadata as aiString.
71
    using StringMetaData = std::map<std::string, aiString>;
72
73
    /// Constructor from XML file.
74
    ColladaParser(IOSystem *pIOHandler, const std::string &pFile);
75
76
    /// Destructor
77
    ~ColladaParser();
78
79
    /// Attempts to read the ZAE manifest and returns the DAE to open
80
    static std::string ReadZaeManifest(ZipArchiveIOSystem &zip_archive);
81
82
    /// Reads the contents of the file
83
    void ReadContents(XmlNode &node);
84
85
    /// Reads the structure of the file
86
    void ReadStructure(XmlNode &node);
87
88
    /// Reads asset information such as coordinate system information and legal blah
89
    void ReadAssetInfo(XmlNode &node);
90
91
    /// Reads contributor information such as author and legal blah
92
    void ReadContributorInfo(XmlNode &node);
93
94
    /// Reads the animation library
95
    void ReadAnimationLibrary(XmlNode &node);
96
97
    /// Reads the animation clip library
98
    void ReadAnimationClipLibrary(XmlNode &node);
99
100
    /// Unwrap controllers dependency hierarchy
101
    void PostProcessControllers();
102
103
    /// Re-build animations from animation clip library, if present, otherwise combine single-channel animations
104
    void PostProcessRootAnimations();
105
106
    /// Reads an animation into the given parent structure
107
    void ReadAnimation(XmlNode &node, Collada::Animation *pParent);
108
109
    /// Reads the skeleton controller library
110
    void ReadControllerLibrary(XmlNode &node);
111
112
    /// Reads a controller into the given mesh structure
113
    void ReadController(XmlNode &node, Collada::Controller &pController);
114
115
    /// Reads the image library contents
116
    void ReadImageLibrary(const XmlNode &node);
117
118
    /// Reads an image entry into the given image
119
    void ReadImage(const XmlNode &node, Collada::Image &pImage) const;
120
121
    /// Reads the material library
122
    void ReadMaterialLibrary(XmlNode &node);
123
124
    /// Reads the camera library
125
    void ReadCameraLibrary(XmlNode &node);
126
127
    /// Reads the light library
128
    void ReadLightLibrary(XmlNode &node);
129
130
    /// Reads the effect library
131
    void ReadEffectLibrary(XmlNode &node);
132
133
    /// Reads an effect entry into the given effect
134
    void ReadEffect(XmlNode &node, Collada::Effect &pEffect);
135
136
    /// Reads an COMMON effect profile
137
    void ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEffect);
138
139
    /// Read sampler properties
140
    void ReadSamplerProperties(XmlNode &node, Collada::Sampler &pSampler);
141
142
    /// Reads an effect entry containing a color or a texture defining that color
143
    void ReadEffectColor(XmlNode &node, aiColor4D &pColor, Collada::Sampler &pSampler);
144
145
    /// Reads an effect entry containing a float
146
    void ReadEffectFloat(XmlNode &node, ai_real &pFloat);
147
148
    /// Reads an effect parameter specification of any kind
149
    void ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam);
150
151
    /// Reads the geometry library contents
152
    void ReadGeometryLibrary(XmlNode &node);
153
154
    /// Reads a geometry from the geometry library.
155
    void ReadGeometry(XmlNode &node, Collada::Mesh &pMesh);
156
157
    /// Reads a mesh from the geometry library
158
    void ReadMesh(XmlNode &node, Collada::Mesh &pMesh);
159
160
    /// Reads a source element - a combination of raw data and an accessor defining
161
    ///things that should not be definable. Yes, that's another rant.
162
    void ReadSource(XmlNode &node);
163
164
    /// Reads a data array holding a number of elements, and stores it in the global library.
165
    /// Currently supported are array of floats and arrays of strings.
166
    void ReadDataArray(XmlNode &node);
167
168
    /// Reads an accessor and stores it in the global library under the given ID -
169
    /// accessors use the ID of the parent <source> element
170
    void ReadAccessor(XmlNode &node, const std::string &pID);
171
172
    /// Reads input declarations of per-vertex mesh data into the given mesh
173
    void ReadVertexData(XmlNode &node, Collada::Mesh &pMesh);
174
175
    /// Reads input declarations of per-index mesh data into the given mesh
176
    void ReadIndexData(XmlNode &node, Collada::Mesh &pMesh);
177
178
    /// Reads a single input channel element and stores it in the given array, if valid
179
    void ReadInputChannel(XmlNode &node, std::vector<Collada::InputChannel> &poChannels);
180
181
    /// Reads a <p> primitive index list and assembles the mesh data into the given mesh
182
    size_t ReadPrimitives(XmlNode &node, Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
183
            size_t pNumPrimitives, const std::vector<size_t> &pVCount, Collada::PrimitiveType pPrimType);
184
185
    /// Copies the data for a single primitive into the mesh, based on the InputChannels
186
    void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
187
            Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
188
            size_t currentPrimitive, const std::vector<size_t> &indices);
189
190
    /// Reads one triangle of a tristrip into the mesh
191
    void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh &pMesh,
192
            std::vector<Collada::InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices);
193
194
    /// Extracts a single object from an input channel and stores it in the appropriate mesh data array
195
    void ExtractDataObjectFromChannel(const Collada::InputChannel &pInput, size_t pLocalIndex, Collada::Mesh &pMesh);
196
197
    /// Reads the library of node hierarchies and scene parts
198
    void ReadSceneLibrary(XmlNode &node);
199
200
    /// Reads a scene node's contents including children and stores it in the given node
201
    void ReadSceneNode(XmlNode &node, Collada::Node *pNode);
202
    
203
    /// Reads a mesh reference in a node and adds it to the node's mesh list
204
    void ReadNodeGeometry(XmlNode &node, Collada::Node *pNode);
205
206
    /// Reads the collada scene
207
    void ReadScene(XmlNode &node);
208
209
    /// Processes bind_vertex_input and bind elements
210
    void ReadMaterialVertexInputBinding(XmlNode &node, Collada::SemanticMappingTable &tbl);
211
212
    /// Reads embedded textures from a ZAE archive
213
    void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
214
215
protected:
216
    /// Converts a path read from a collada file to the usual representation
217
    static void UriDecodePath(aiString &ss);
218
219
    /// Calculates the resulting transformation from all the given transform steps
220
    aiMatrix4x4 CalculateResultTransform(const std::vector<Collada::Transform> &pTransforms) const;
221
222
    /// Determines the input data type for the given semantic string
223
    Collada::InputType GetTypeForSemantic(const std::string &pSemantic);
224
225
    /// Finds the item in the given library by its reference, throws if not found
226
    template <typename Type>
227
    const Type &ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const;
228
229
private:
230
    /// Filename, for a verbose error message
231
    std::string mFileName;
232
233
    /// XML reader, member for everyday use
234
    XmlParser mXmlParser;
235
236
    /// All data arrays found in the file by ID. Might be referred to by actually
237
    ///     everyone. Collada, you are a steaming pile of indirection.
238
    using DataLibrary = std::map<std::string, Collada::Data> ;
239
    DataLibrary mDataLibrary;
240
241
    /// Same for accessors which define how the data in a data array is accessed.
242
    using AccessorLibrary = std::map<std::string, Collada::Accessor> ;
243
    AccessorLibrary mAccessorLibrary;
244
245
    /// Mesh library: mesh by ID
246
    using MeshLibrary = std::map<std::string, Collada::Mesh *>;
247
    MeshLibrary mMeshLibrary;
248
249
    /// node library: root node of the hierarchy part by ID
250
    using NodeLibrary = std::map<std::string, Collada::Node *>;
251
    NodeLibrary mNodeLibrary;
252
253
    /// Image library: stores texture properties by ID
254
    using ImageLibrary = std::map<std::string, Collada::Image> ;
255
    ImageLibrary mImageLibrary;
256
257
    /// Effect library: surface attributes by ID
258
    using EffectLibrary = std::map<std::string, Collada::Effect> ;
259
    EffectLibrary mEffectLibrary;
260
261
    /// Material library: surface material by ID
262
    using MaterialLibrary = std::map<std::string, Collada::Material> ;
263
    MaterialLibrary mMaterialLibrary;
264
265
    /// Light library: surface light by ID
266
    using LightLibrary = std::map<std::string, Collada::Light> ;
267
    LightLibrary mLightLibrary;
268
269
    /// Camera library: surface material by ID
270
    using CameraLibrary = std::map<std::string, Collada::Camera> ;
271
    CameraLibrary mCameraLibrary;
272
273
    /// Controller library: joint controllers by ID
274
    using ControllerLibrary = std::map<std::string, Collada::Controller> ;
275
    ControllerLibrary mControllerLibrary;
276
277
    /// Animation library: animation references by ID
278
    using AnimationLibrary = std::map<std::string, Collada::Animation *> ;
279
    AnimationLibrary mAnimationLibrary;
280
281
    /// Animation clip library: clip animation references by ID
282
    using AnimationClipLibrary = std::vector<std::pair<std::string, std::vector<std::string>>> ;
283
    AnimationClipLibrary mAnimationClipLibrary;
284
285
    /// Pointer to the root node. Don't delete, it just points to one of the nodes in the node library.
286
    Collada::Node *mRootNode;
287
288
    /// Root animation container
289
    Collada::Animation mAnims;
290
291
    /// Size unit: how large compared to a meter
292
    ai_real mUnitSize;
293
294
    /// Which is the up vector
295
    enum { UP_X,
296
        UP_Y,
297
        UP_Z } mUpDirection;
298
299
    /// Asset metadata (global for scene)
300
    StringMetaData mAssetMetaData;
301
302
    /// Collada file format version
303
    Collada::FormatVersion mFormat;
304
};
305
306
// ------------------------------------------------------------------------------------------------
307
// Finds the item in the given library by its reference, throws if not found
308
template <typename Type>
309
0
const Type &ColladaParser::ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const {
310
0
    typename std::map<std::string, Type>::const_iterator it = pLibrary.find(pURL);
311
0
    if (it == pLibrary.end()) {
312
0
        throw DeadlyImportError("Unable to resolve library reference \"", pURL, "\".");
313
0
    }
314
0
    return it->second;
315
0
}
Unexecuted instantiation: Assimp::Collada::Mesh* const& Assimp::ColladaParser::ResolveLibraryReference<Assimp::Collada::Mesh*>(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, Assimp::Collada::Mesh*, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, Assimp::Collada::Mesh*> > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
Unexecuted instantiation: Assimp::Collada::Accessor const& Assimp::ColladaParser::ResolveLibraryReference<Assimp::Collada::Accessor>(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, Assimp::Collada::Accessor, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, Assimp::Collada::Accessor> > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
Unexecuted instantiation: Assimp::Collada::Data const& Assimp::ColladaParser::ResolveLibraryReference<Assimp::Collada::Data>(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, Assimp::Collada::Data, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, Assimp::Collada::Data> > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const
316
317
} // end of namespace Assimp
318
319
#endif // AI_COLLADAPARSER_H_INC