1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
4 
5 Copyright (c) 2006-2021, assimp team
6 
7 
8 All rights reserved.
9 
10 Redistribution and use of this software in source and binary forms,
11 with or without modification, are permitted provided that the
12 following conditions are met:
13 
14 * Redistributions of source code must retain the above
15   copyright notice, this list of conditions and the
16   following disclaimer.
17 
18 * Redistributions in binary form must reproduce the above
19   copyright notice, this list of conditions and the
20   following disclaimer in the documentation and/or other
21   materials provided with the distribution.
22 
23 * Neither the name of the assimp team, nor the names of its
24   contributors may be used to endorse or promote products
25   derived from this software without specific prior
26   written permission of the assimp team.
27 
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 
40 ----------------------------------------------------------------------
41 */
42 
43 /** @file ColladaExporter.h
44  * Declares the exporter class to write a scene to a Collada file
45  */
46 #ifndef AI_COLLADAEXPORTER_H_INC
47 #define AI_COLLADAEXPORTER_H_INC
48 
49 #include <assimp/ai_assert.h>
50 #include <assimp/material.h>
51 
52 #include <array>
53 #include <map>
54 #include <sstream>
55 #include <unordered_set>
56 #include <vector>
57 
58 struct aiScene;
59 struct aiNode;
60 struct aiLight;
61 struct aiBone;
62 
63 namespace Assimp {
64 
65 class IOSystem;
66 
67 /// Helper class to export a given scene to a Collada file. Just for my personal
68 /// comfort when implementing it.
69 class ColladaExporter {
70 public:
71     /// Constructor for a specific scene to export
72     ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file);
73 
74     /// Destructor
75     virtual ~ColladaExporter();
76 
77 protected:
78     /// Starts writing the contents
79     void WriteFile();
80 
81     /// Writes the asset header
82     void WriteHeader();
83 
84     /// Writes the embedded textures
85     void WriteTextures();
86 
87     /// Writes the material setup
88     void WriteMaterials();
89 
90     /// Writes the cameras library
91     void WriteCamerasLibrary();
92 
93     // Write a camera entry
94     void WriteCamera(size_t pIndex);
95 
96     /// Writes the cameras library
97     void WriteLightsLibrary();
98 
99     // Write a camera entry
100     void WriteLight(size_t pIndex);
101     void WritePointLight(const aiLight *const light);
102     void WriteDirectionalLight(const aiLight *const light);
103     void WriteSpotLight(const aiLight *const light);
104     void WriteAmbienttLight(const aiLight *const light);
105 
106     /// Writes the controller library
107     void WriteControllerLibrary();
108 
109     /// Writes a skin controller of the given mesh
110     void WriteController(size_t pIndex);
111 
112     /// Writes the geometry library
113     void WriteGeometryLibrary();
114 
115     /// Writes the given mesh
116     void WriteGeometry(size_t pIndex);
117 
118     //enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight };
119     // customized to add animation related type
120     enum FloatDataType { FloatType_Vector,
121         FloatType_TexCoord2,
122         FloatType_TexCoord3,
123         FloatType_Color,
124         FloatType_Mat4x4,
125         FloatType_Weight,
126         FloatType_Time };
127 
128     /// Writes a float array of the given type
129     void WriteFloatArray(const std::string &pIdString, FloatDataType pType, const ai_real *pData, size_t pElementCount);
130 
131     /// Writes the scene library
132     void WriteSceneLibrary();
133 
134     // customized, Writes the animation library
135     void WriteAnimationsLibrary();
136     void WriteAnimationLibrary(size_t pIndex);
137     std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call.
138 
139     /// Recursively writes the given node
140     void WriteNode(const aiNode *pNode);
141 
142     /// Enters a new xml element, which increases the indentation
PushTag()143     void PushTag() { startstr.append("  "); }
144     /// Leaves an element, decreasing the indentation
PopTag()145     void PopTag() {
146         ai_assert(startstr.length() > 1);
147         startstr.erase(startstr.length() - 2);
148     }
149 
150     void CreateNodeIds(const aiNode *node);
151 
152     /// Get or Create a unique Node ID string for the given Node
153     std::string GetNodeUniqueId(const aiNode *node);
154     std::string GetNodeName(const aiNode *node);
155 
156     std::string GetBoneUniqueId(const aiBone *bone);
157 
158     enum class AiObjectType {
159         Mesh,
160         Material,
161         Animation,
162         Light,
163         Camera,
164         Count,
165     };
166     /// Get or Create a unique ID string for the given scene object index
167     std::string GetObjectUniqueId(AiObjectType type, size_t pIndex);
168     /// Get or Create a name string for the given scene object index
169     std::string GetObjectName(AiObjectType type, size_t pIndex);
170 
171     typedef std::map<size_t, std::string> IndexIdMap;
172     typedef std::pair<std::string, std::string> NameIdPair;
173     NameIdPair AddObjectIndexToMaps(AiObjectType type, size_t pIndex);
174 
175     // Helpers
GetObjectIdMap(AiObjectType type)176     inline IndexIdMap &GetObjectIdMap(AiObjectType type) { return mObjectIdMap[static_cast<size_t>(type)]; }
GetObjectNameMap(AiObjectType type)177     inline IndexIdMap &GetObjectNameMap(AiObjectType type) { return mObjectNameMap[static_cast<size_t>(type)]; }
178 
179 private:
180     std::unordered_set<std::string> mUniqueIds; // Cache of used unique ids
181     std::map<const void *, std::string> mNodeIdMap; // Cache of encoded node and bone ids
182     std::array<IndexIdMap, static_cast<size_t>(AiObjectType::Count)> mObjectIdMap; // Cache of encoded unique IDs
183     std::array<IndexIdMap, static_cast<size_t>(AiObjectType::Count)> mObjectNameMap; // Cache of encoded names
184 
185 public:
186     /// Stringstream to write all output into
187     std::stringstream mOutput;
188 
189     /// The IOSystem for output
190     IOSystem *mIOSystem;
191 
192     /// Path of the directory where the scene will be exported
193     const std::string mPath;
194 
195     /// Name of the file (without extension) where the scene will be exported
196     const std::string mFile;
197 
198     /// The scene to be written
199     const aiScene *const mScene;
200     std::string mSceneId;
201     bool mAdd_root_node = false;
202 
203     /// current line start string, contains the current indentation for simple stream insertion
204     std::string startstr;
205     /// current line end string for simple stream insertion
206     const std::string endstr;
207 
208     // pair of color and texture - texture precedences color
209     struct Surface {
210         bool exist;
211         aiColor4D color;
212         std::string texture;
213         size_t channel;
SurfaceSurface214         Surface() {
215             exist = false;
216             channel = 0;
217         }
218     };
219 
220     struct Property {
221         bool exist;
222         ai_real value;
PropertyProperty223         Property() :
224                 exist(false),
225                 value(0.0) {}
226     };
227 
228     // summarize a material in an convenient way.
229     struct Material {
230         std::string id;
231         std::string name;
232         std::string shading_model;
233         Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
234         Property shininess, transparency, index_refraction;
235 
MaterialMaterial236         Material() {}
237     };
238 
239     std::map<unsigned int, std::string> textures;
240 
241 public:
242     /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions
243     /// Reads a single surface entry from the given material keys
244     bool ReadMaterialSurface(Surface &poSurface, const aiMaterial &pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex);
245     /// Writes an image entry for the given surface
246     void WriteImageEntry(const Surface &pSurface, const std::string &imageId);
247     /// Writes the two parameters necessary for referencing a texture in an effect entry
248     void WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &materialId);
249     /// Writes a color-or-texture entry into an effect definition
250     void WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &imageId);
251     /// Writes a scalar property
252     void WriteFloatEntry(const Property &pProperty, const std::string &pTypeName);
253 };
254 
255 } // namespace Assimp
256 
257 #endif // !! AI_COLLADAEXPORTER_H_INC
258