1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
5
6 Copyright (c) 2006-2019, assimp team
7
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 following
14 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 /// \file AMFImporter_Geometry.cpp
45 /// \brief Parsing data from geometry nodes.
46 /// \date 2016
47 /// \author smal.root@gmail.com
48
49 #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
50
51 #include "AMFImporter.hpp"
52 #include "AMFImporter_Macro.hpp"
53
54 namespace Assimp
55 {
56
57 // <mesh>
58 // </mesh>
59 // A 3D mesh hull.
60 // Multi elements - Yes.
61 // Parent element - <object>.
ParseNode_Mesh()62 void AMFImporter::ParseNode_Mesh()
63 {
64 CAMFImporter_NodeElement* ne;
65
66 // create new mesh object.
67 ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur);
68 // Check for child nodes
69 if(!mReader->isEmptyElement())
70 {
71 bool vert_read = false;
72
73 ParseHelper_Node_Enter(ne);
74 MACRO_NODECHECK_LOOPBEGIN("mesh");
75 if(XML_CheckNode_NameEqual("vertices"))
76 {
77 // Check if data already defined.
78 if(vert_read) Throw_MoreThanOnceDefined("vertices", "Only one vertices set can be defined for <mesh>.");
79 // read data and set flag about it
80 ParseNode_Vertices();
81 vert_read = true;
82
83 continue;
84 }
85
86 if(XML_CheckNode_NameEqual("volume")) { ParseNode_Volume(); continue; }
87 MACRO_NODECHECK_LOOPEND("mesh");
88 ParseHelper_Node_Exit();
89 }// if(!mReader->isEmptyElement())
90 else
91 {
92 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
93 }// if(!mReader->isEmptyElement()) else
94
95 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
96 }
97
98 // <vertices>
99 // </vertices>
100 // The list of vertices to be used in defining triangles.
101 // Multi elements - No.
102 // Parent element - <mesh>.
ParseNode_Vertices()103 void AMFImporter::ParseNode_Vertices()
104 {
105 CAMFImporter_NodeElement* ne;
106
107 // create new mesh object.
108 ne = new CAMFImporter_NodeElement_Vertices(mNodeElement_Cur);
109 // Check for child nodes
110 if(!mReader->isEmptyElement())
111 {
112 ParseHelper_Node_Enter(ne);
113 MACRO_NODECHECK_LOOPBEGIN("vertices");
114 if(XML_CheckNode_NameEqual("vertex")) { ParseNode_Vertex(); continue; }
115 MACRO_NODECHECK_LOOPEND("vertices");
116 ParseHelper_Node_Exit();
117 }// if(!mReader->isEmptyElement())
118 else
119 {
120 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
121 }// if(!mReader->isEmptyElement()) else
122
123 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
124 }
125
126 // <vertex>
127 // </vertex>
128 // A vertex to be referenced in triangles.
129 // Multi elements - Yes.
130 // Parent element - <vertices>.
ParseNode_Vertex()131 void AMFImporter::ParseNode_Vertex()
132 {
133 CAMFImporter_NodeElement* ne;
134
135 // create new mesh object.
136 ne = new CAMFImporter_NodeElement_Vertex(mNodeElement_Cur);
137 // Check for child nodes
138 if(!mReader->isEmptyElement())
139 {
140 bool col_read = false;
141 bool coord_read = false;
142
143 ParseHelper_Node_Enter(ne);
144 MACRO_NODECHECK_LOOPBEGIN("vertex");
145 if(XML_CheckNode_NameEqual("color"))
146 {
147 // Check if data already defined.
148 if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <vertex>.");
149 // read data and set flag about it
150 ParseNode_Color();
151 col_read = true;
152
153 continue;
154 }
155
156 if(XML_CheckNode_NameEqual("coordinates"))
157 {
158 // Check if data already defined.
159 if(coord_read) Throw_MoreThanOnceDefined("coordinates", "Only one coordinates set can be defined for <vertex>.");
160 // read data and set flag about it
161 ParseNode_Coordinates();
162 coord_read = true;
163
164 continue;
165 }
166
167 if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
168 MACRO_NODECHECK_LOOPEND("vertex");
169 ParseHelper_Node_Exit();
170 }// if(!mReader->isEmptyElement())
171 else
172 {
173 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
174 }// if(!mReader->isEmptyElement()) else
175
176 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
177 }
178
179 // <coordinates>
180 // </coordinates>
181 // Specifies the 3D location of this vertex.
182 // Multi elements - No.
183 // Parent element - <vertex>.
184 //
185 // Children elements:
186 // <x>, <y>, <z>
187 // Multi elements - No.
188 // X, Y, or Z coordinate, respectively, of a vertex position in space.
ParseNode_Coordinates()189 void AMFImporter::ParseNode_Coordinates()
190 {
191 CAMFImporter_NodeElement* ne;
192
193 // create new color object.
194 ne = new CAMFImporter_NodeElement_Coordinates(mNodeElement_Cur);
195
196 CAMFImporter_NodeElement_Coordinates& als = *((CAMFImporter_NodeElement_Coordinates*)ne);// alias for convenience
197
198 // Check for child nodes
199 if(!mReader->isEmptyElement())
200 {
201 bool read_flag[3] = { false, false, false };
202
203 ParseHelper_Node_Enter(ne);
204 MACRO_NODECHECK_LOOPBEGIN("coordinates");
205 MACRO_NODECHECK_READCOMP_F("x", read_flag[0], als.Coordinate.x);
206 MACRO_NODECHECK_READCOMP_F("y", read_flag[1], als.Coordinate.y);
207 MACRO_NODECHECK_READCOMP_F("z", read_flag[2], als.Coordinate.z);
208 MACRO_NODECHECK_LOOPEND("coordinates");
209 ParseHelper_Node_Exit();
210 // check that all components was defined
211 if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all coordinate's components are defined.");
212
213 }// if(!mReader->isEmptyElement())
214 else
215 {
216 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
217 }// if(!mReader->isEmptyElement()) else
218
219 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
220 }
221
222 // <volume
223 // materialid="" - Which material to use.
224 // type="" - What this volume describes can be “region” or “support”. If none specified, “object” is assumed. If support, then the geometric
225 // requirements 1-8 listed in section 5 do not need to be maintained.
226 // >
227 // </volume>
228 // Defines a volume from the established vertex list.
229 // Multi elements - Yes.
230 // Parent element - <mesh>.
ParseNode_Volume()231 void AMFImporter::ParseNode_Volume()
232 {
233 std::string materialid;
234 std::string type;
235 CAMFImporter_NodeElement* ne;
236
237 // Read attributes for node <color>.
238 MACRO_ATTRREAD_LOOPBEG;
239 MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mReader->getAttributeValue);
240 MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
241 MACRO_ATTRREAD_LOOPEND;
242
243 // create new object.
244 ne = new CAMFImporter_NodeElement_Volume(mNodeElement_Cur);
245 // and assign read data
246 ((CAMFImporter_NodeElement_Volume*)ne)->MaterialID = materialid;
247 ((CAMFImporter_NodeElement_Volume*)ne)->Type = type;
248 // Check for child nodes
249 if(!mReader->isEmptyElement())
250 {
251 bool col_read = false;
252
253 ParseHelper_Node_Enter(ne);
254 MACRO_NODECHECK_LOOPBEGIN("volume");
255 if(XML_CheckNode_NameEqual("color"))
256 {
257 // Check if data already defined.
258 if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <volume>.");
259 // read data and set flag about it
260 ParseNode_Color();
261 col_read = true;
262
263 continue;
264 }
265
266 if(XML_CheckNode_NameEqual("triangle")) { ParseNode_Triangle(); continue; }
267 if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
268 MACRO_NODECHECK_LOOPEND("volume");
269 ParseHelper_Node_Exit();
270 }// if(!mReader->isEmptyElement())
271 else
272 {
273 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
274 }// if(!mReader->isEmptyElement()) else
275
276 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
277 }
278
279 // <triangle>
280 // </triangle>
281 // Defines a 3D triangle from three vertices, according to the right-hand rule (counter-clockwise when looking from the outside).
282 // Multi elements - Yes.
283 // Parent element - <volume>.
284 //
285 // Children elements:
286 // <v1>, <v2>, <v3>
287 // Multi elements - No.
288 // Index of the desired vertices in a triangle or edge.
ParseNode_Triangle()289 void AMFImporter::ParseNode_Triangle()
290 {
291 CAMFImporter_NodeElement* ne;
292
293 // create new color object.
294 ne = new CAMFImporter_NodeElement_Triangle(mNodeElement_Cur);
295
296 CAMFImporter_NodeElement_Triangle& als = *((CAMFImporter_NodeElement_Triangle*)ne);// alias for convenience
297
298 // Check for child nodes
299 if(!mReader->isEmptyElement())
300 {
301 bool col_read = false, tex_read = false;
302 bool read_flag[3] = { false, false, false };
303
304 ParseHelper_Node_Enter(ne);
305 MACRO_NODECHECK_LOOPBEGIN("triangle");
306 if(XML_CheckNode_NameEqual("color"))
307 {
308 // Check if data already defined.
309 if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <triangle>.");
310 // read data and set flag about it
311 ParseNode_Color();
312 col_read = true;
313
314 continue;
315 }
316
317 if(XML_CheckNode_NameEqual("texmap"))// new name of node: "texmap".
318 {
319 // Check if data already defined.
320 if(tex_read) Throw_MoreThanOnceDefined("texmap", "Only one texture coordinate can be defined for <triangle>.");
321 // read data and set flag about it
322 ParseNode_TexMap();
323 tex_read = true;
324
325 continue;
326 }
327 else if(XML_CheckNode_NameEqual("map"))// old name of node: "map".
328 {
329 // Check if data already defined.
330 if(tex_read) Throw_MoreThanOnceDefined("map", "Only one texture coordinate can be defined for <triangle>.");
331 // read data and set flag about it
332 ParseNode_TexMap(true);
333 tex_read = true;
334
335 continue;
336 }
337
338 MACRO_NODECHECK_READCOMP_U32("v1", read_flag[0], als.V[0]);
339 MACRO_NODECHECK_READCOMP_U32("v2", read_flag[1], als.V[1]);
340 MACRO_NODECHECK_READCOMP_U32("v3", read_flag[2], als.V[2]);
341 MACRO_NODECHECK_LOOPEND("triangle");
342 ParseHelper_Node_Exit();
343 // check that all components was defined
344 if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all vertices of the triangle are defined.");
345
346 }// if(!mReader->isEmptyElement())
347 else
348 {
349 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
350 }// if(!mReader->isEmptyElement()) else
351
352 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
353 }
354
355 }// namespace Assimp
356
357 #endif // !ASSIMP_BUILD_NO_AMF_IMPORTER
358