1 /** Defines the collada loader class */
2 
3 /*
4 Open Asset Import Library (assimp)
5 ----------------------------------------------------------------------
6 
7 Copyright (c) 2006-2019, assimp team
8 
9 
10 All rights reserved.
11 
12 Redistribution and use of this software in source and binary forms,
13 with or without modification, are permitted provided that the
14 following conditions are met:
15 
16 * Redistributions of source code must retain the above
17 copyright notice, this list of conditions and the
18 following disclaimer.
19 
20 * Redistributions in binary form must reproduce the above
21 copyright notice, this list of conditions and the
22 following disclaimer in the documentation and/or other
23 materials provided with the distribution.
24 
25 * Neither the name of the assimp team, nor the names of its
26 contributors may be used to endorse or promote products
27 derived from this software without specific prior
28 written permission of the assimp team.
29 
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 
42 ----------------------------------------------------------------------
43 */
44 
45 #ifndef AI_COLLADALOADER_H_INC
46 #define AI_COLLADALOADER_H_INC
47 
48 #include <assimp/BaseImporter.h>
49 #include "ColladaParser.h"
50 
51 struct aiNode;
52 struct aiCamera;
53 struct aiLight;
54 struct aiTexture;
55 struct aiAnimation;
56 
57 namespace Assimp
58 {
59 
60 struct ColladaMeshIndex
61 {
62     std::string mMeshID;
63     size_t mSubMesh;
64     std::string mMaterial;
ColladaMeshIndexColladaMeshIndex65     ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial)
66         : mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial)
67     {   }
68 
69     bool operator < (const ColladaMeshIndex& p) const
70     {
71         if( mMeshID == p.mMeshID)
72         {
73             if( mSubMesh == p.mSubMesh)
74                 return mMaterial < p.mMaterial;
75             else
76                 return mSubMesh < p.mSubMesh;
77         } else
78         {
79             return mMeshID < p.mMeshID;
80         }
81     }
82 };
83 
84 /** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing
85  * more useless stuff, so I limited the data to what I think is useful for games.
86 */
87 class ColladaLoader : public BaseImporter
88 {
89 public:
90     ColladaLoader();
91     ~ColladaLoader();
92 
93 
94 public:
95     /** Returns whether the class can handle the format of the given file.
96      * See BaseImporter::CanRead() for details. */
97     bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
98 
99 protected:
100     /** Return importer meta information.
101      * See #BaseImporter::GetInfo for the details
102      */
103     const aiImporterDesc* GetInfo () const override;
104 
105     void SetupProperties(const Importer* pImp) override;
106 
107     /** Imports the given file into the given scene structure.
108      * See BaseImporter::InternReadFile() for details
109      */
110     void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
111 
112     /** Recursively constructs a scene node for the given parser node and returns it. */
113     aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
114 
115     /** Resolve node instances */
116     void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
117         std::vector<const Collada::Node*>& resolved);
118 
119     /** Builds meshes for the given node and references them */
120     void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode,
121         aiNode* pTarget);
122 
123     aiMesh *findMesh(const std::string& meshid);
124 
125     /** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */
126     aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
127         const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace);
128 
129     /** Builds cameras for the given node and references them */
130     void BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode,
131         aiNode* pTarget);
132 
133     /** Builds lights for the given node and references them */
134     void BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode,
135         aiNode* pTarget);
136 
137     /** Stores all meshes in the given scene */
138     void StoreSceneMeshes( aiScene* pScene);
139 
140     /** Stores all materials in the given scene */
141     void StoreSceneMaterials( aiScene* pScene);
142 
143     /** Stores all lights in the given scene */
144     void StoreSceneLights( aiScene* pScene);
145 
146     /** Stores all cameras in the given scene */
147     void StoreSceneCameras( aiScene* pScene);
148 
149     /** Stores all textures in the given scene */
150     void StoreSceneTextures( aiScene* pScene);
151 
152     /** Stores all animations
153      * @param pScene target scene to store the anims
154      */
155     void StoreAnimations( aiScene* pScene, const ColladaParser& pParser);
156 
157     /** Stores all animations for the given source anim and its nested child animations
158      * @param pScene target scene to store the anims
159      * @param pSrcAnim the source animation to process
160      * @param pPrefix Prefix to the name in case of nested animations
161      */
162     void StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pPrefix);
163 
164     /** Constructs the animation for the given source anim */
165     void CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName);
166 
167     /** Constructs materials from the collada material definitions */
168     void BuildMaterials( ColladaParser& pParser, aiScene* pScene);
169 
170     /** Fill materials from the collada material definitions */
171     void FillMaterials( const ColladaParser& pParser, aiScene* pScene);
172 
173     /** Resolve UV channel mappings*/
174     void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
175         const Collada::SemanticMappingTable& table);
176 
177     /** Add a texture and all of its sampling properties to a material*/
178     void AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
179         const Collada::Effect& effect,
180         const Collada::Sampler& sampler,
181         aiTextureType type, unsigned int idx = 0);
182 
183     /** Resolves the texture name for the given effect texture entry */
184     aiString FindFilenameForEffectTexture( const ColladaParser& pParser,
185         const Collada::Effect& pEffect, const std::string& pName);
186 
187     /** Reads a float value from an accessor and its data array.
188      * @param pAccessor The accessor to use for reading
189      * @param pData The data array to read from
190      * @param pIndex The index of the element to retrieve
191      * @param pOffset Offset into the element, for multipart elements such as vectors or matrices
192      * @return the specified value
193      */
194     ai_real ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const;
195 
196     /** Reads a string value from an accessor and its data array.
197      * @param pAccessor The accessor to use for reading
198      * @param pData The data array to read from
199      * @param pIndex The index of the element to retrieve
200      * @return the specified value
201      */
202     const std::string& ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const;
203 
204     /** Recursively collects all nodes into the given array */
205     void CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const;
206 
207     /** Finds a node in the collada scene by the given name */
208     const Collada::Node* FindNode( const Collada::Node* pNode, const std::string& pName) const;
209     /** Finds a node in the collada scene by the given SID */
210     const Collada::Node* FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const;
211 
212     /** Finds a proper name for a node derived from the collada-node's properties */
213     std::string FindNameForNode( const Collada::Node* pNode);
214 
215 protected:
216     /** Filename, for a verbose error message */
217     std::string mFileName;
218 
219     /** Which mesh-material compound was stored under which mesh ID */
220     std::map<ColladaMeshIndex, size_t> mMeshIndexByID;
221 
222     /** Which material was stored under which index in the scene */
223     std::map<std::string, size_t> mMaterialIndexByName;
224 
225     /** Accumulated meshes for the target scene */
226     std::vector<aiMesh*> mMeshes;
227 
228     /** Accumulated morph target meshes */
229     std::vector<aiMesh*> mTargetMeshes;
230 
231     /** Temporary material list */
232     std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats;
233 
234     /** Temporary camera list */
235     std::vector<aiCamera*> mCameras;
236 
237     /** Temporary light list */
238     std::vector<aiLight*> mLights;
239 
240     /** Temporary texture list */
241     std::vector<aiTexture*> mTextures;
242 
243     /** Accumulated animations for the target scene */
244     std::vector<aiAnimation*> mAnims;
245 
246     bool noSkeletonMesh;
247     bool ignoreUpDirection;
248     bool useColladaName;
249 
250     /** Used by FindNameForNode() to generate unique node names */
251     unsigned int mNodeNameCounter;
252 };
253 
254 } // end of namespace Assimp
255 
256 #endif // AI_COLLADALOADER_H_INC
257