1/*
2---------------------------------------------------------------------------
3Open Asset Import Library (assimp)
4---------------------------------------------------------------------------
5
6Copyright (c) 2006-2017, assimp team
7
8
9All rights reserved.
10
11Redistribution and use of this software in source and binary forms,
12with or without modification, are permitted provided that the following
13conditions are met:
14
15* Redistributions of source code must retain the above
16copyright notice, this list of conditions and the
17following disclaimer.
18
19* Redistributions in binary form must reproduce the above
20copyright notice, this list of conditions and the
21following disclaimer in the documentation and/or other
22materials provided with the distribution.
23
24* Neither the name of the assimp team, nor the names of its
25contributors may be used to endorse or promote products
26derived from this software without specific prior
27written permission of the assimp team.
28
29THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40---------------------------------------------------------------------------
41*/
42
43/// \file AMFImporter_Geometry.cpp
44/// \brief Parsing data from geometry nodes.
45/// \date 2016
46/// \author smal.root@gmail.com
47
48#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
49
50#include "AMFImporter.hpp"
51#include "AMFImporter_Macro.hpp"
52
53namespace Assimp
54{
55
56// <mesh>
57// </mesh>
58// A 3D mesh hull.
59// Multi elements - Yes.
60// Parent element - <object>.
61void AMFImporter::ParseNode_Mesh()
62{
63CAMFImporter_NodeElement* ne;
64
65 // create new mesh object.
66 ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur);
67 // Check for child nodes
68 if(!mReader->isEmptyElement())
69 {
70 bool vert_read = false;
71
72 ParseHelper_Node_Enter(ne);
73 MACRO_NODECHECK_LOOPBEGIN("mesh");
74 if(XML_CheckNode_NameEqual("vertices"))
75 {
76 // Check if data already defined.
77 if(vert_read) Throw_MoreThanOnceDefined("vertices", "Only one vertices set can be defined for <mesh>.");
78 // read data and set flag about it
79 ParseNode_Vertices();
80 vert_read = true;
81
82 continue;
83 }
84
85 if(XML_CheckNode_NameEqual("volume")) { ParseNode_Volume(); continue; }
86 MACRO_NODECHECK_LOOPEND("mesh");
87 ParseHelper_Node_Exit();
88 }// if(!mReader->isEmptyElement())
89 else
90 {
91 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
92 }// if(!mReader->isEmptyElement()) else
93
94 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
95}
96
97// <vertices>
98// </vertices>
99// The list of vertices to be used in defining triangles.
100// Multi elements - No.
101// Parent element - <mesh>.
102void AMFImporter::ParseNode_Vertices()
103{
104CAMFImporter_NodeElement* ne;
105
106 // create new mesh object.
107 ne = new CAMFImporter_NodeElement_Vertices(mNodeElement_Cur);
108 // Check for child nodes
109 if(!mReader->isEmptyElement())
110 {
111 ParseHelper_Node_Enter(ne);
112 MACRO_NODECHECK_LOOPBEGIN("vertices");
113 if(XML_CheckNode_NameEqual("vertex")) { ParseNode_Vertex(); continue; }
114 MACRO_NODECHECK_LOOPEND("vertices");
115 ParseHelper_Node_Exit();
116 }// if(!mReader->isEmptyElement())
117 else
118 {
119 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
120 }// if(!mReader->isEmptyElement()) else
121
122 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
123}
124
125// <vertex>
126// </vertex>
127// A vertex to be referenced in triangles.
128// Multi elements - Yes.
129// Parent element - <vertices>.
130void AMFImporter::ParseNode_Vertex()
131{
132CAMFImporter_NodeElement* ne;
133
134 // create new mesh object.
135 ne = new CAMFImporter_NodeElement_Vertex(mNodeElement_Cur);
136 // Check for child nodes
137 if(!mReader->isEmptyElement())
138 {
139 bool col_read = false;
140 bool coord_read = false;
141
142 ParseHelper_Node_Enter(ne);
143 MACRO_NODECHECK_LOOPBEGIN("vertex");
144 if(XML_CheckNode_NameEqual("color"))
145 {
146 // Check if data already defined.
147 if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <vertex>.");
148 // read data and set flag about it
149 ParseNode_Color();
150 col_read = true;
151
152 continue;
153 }
154
155 if(XML_CheckNode_NameEqual("coordinates"))
156 {
157 // Check if data already defined.
158 if(coord_read) Throw_MoreThanOnceDefined("coordinates", "Only one coordinates set can be defined for <vertex>.");
159 // read data and set flag about it
160 ParseNode_Coordinates();
161 coord_read = true;
162
163 continue;
164 }
165
166 if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
167 MACRO_NODECHECK_LOOPEND("vertex");
168 ParseHelper_Node_Exit();
169 }// if(!mReader->isEmptyElement())
170 else
171 {
172 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
173 }// if(!mReader->isEmptyElement()) else
174
175 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
176}
177
178// <coordinates>
179// </coordinates>
180// Specifies the 3D location of this vertex.
181// Multi elements - No.
182// Parent element - <vertex>.
183//
184// Children elements:
185// <x>, <y>, <z>
186// Multi elements - No.
187// X, Y, or Z coordinate, respectively, of a vertex position in space.
188void AMFImporter::ParseNode_Coordinates()
189{
190CAMFImporter_NodeElement* ne;
191
192 // create new color object.
193 ne = new CAMFImporter_NodeElement_Coordinates(mNodeElement_Cur);
194
195 CAMFImporter_NodeElement_Coordinates& als = *((CAMFImporter_NodeElement_Coordinates*)ne);// alias for convenience
196
197 // Check for child nodes
198 if(!mReader->isEmptyElement())
199 {
200 bool read_flag[3] = { false, false, false };
201
202 ParseHelper_Node_Enter(ne);
203 MACRO_NODECHECK_LOOPBEGIN("coordinates");
204 MACRO_NODECHECK_READCOMP_F("x", read_flag[0], als.Coordinate.x);
205 MACRO_NODECHECK_READCOMP_F("y", read_flag[1], als.Coordinate.y);
206 MACRO_NODECHECK_READCOMP_F("z", read_flag[2], als.Coordinate.z);
207 MACRO_NODECHECK_LOOPEND("coordinates");
208 ParseHelper_Node_Exit();
209 // check that all components was defined
210 if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all coordinate's components are defined.");
211
212 }// if(!mReader->isEmptyElement())
213 else
214 {
215 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
216 }// if(!mReader->isEmptyElement()) else
217
218 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
219}
220
221// <volume
222// materialid="" - Which material to use.
223// type="" - What this volume describes can be “region” or “support”. If none specified, “object” is assumed. If support, then the geometric
224// requirements 1-8 listed in section 5 do not need to be maintained.
225// >
226// </volume>
227// Defines a volume from the established vertex list.
228// Multi elements - Yes.
229// Parent element - <mesh>.
230void AMFImporter::ParseNode_Volume()
231{
232std::string materialid;
233std::string type;
234CAMFImporter_NodeElement* ne;
235
236 // Read attributes for node <color>.
237 MACRO_ATTRREAD_LOOPBEG;
238 MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mReader->getAttributeValue);
239 MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
240 MACRO_ATTRREAD_LOOPEND;
241
242 // create new object.
243 ne = new CAMFImporter_NodeElement_Volume(mNodeElement_Cur);
244 // and assign read data
245 ((CAMFImporter_NodeElement_Volume*)ne)->MaterialID = materialid;
246 ((CAMFImporter_NodeElement_Volume*)ne)->Type = type;
247 // Check for child nodes
248 if(!mReader->isEmptyElement())
249 {
250 bool col_read = false;
251
252 ParseHelper_Node_Enter(ne);
253 MACRO_NODECHECK_LOOPBEGIN("volume");
254 if(XML_CheckNode_NameEqual("color"))
255 {
256 // Check if data already defined.
257 if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <volume>.");
258 // read data and set flag about it
259 ParseNode_Color();
260 col_read = true;
261
262 continue;
263 }
264
265 if(XML_CheckNode_NameEqual("triangle")) { ParseNode_Triangle(); continue; }
266 if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
267 MACRO_NODECHECK_LOOPEND("volume");
268 ParseHelper_Node_Exit();
269 }// if(!mReader->isEmptyElement())
270 else
271 {
272 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
273 }// if(!mReader->isEmptyElement()) else
274
275 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
276}
277
278// <triangle>
279// </triangle>
280// Defines a 3D triangle from three vertices, according to the right-hand rule (counter-clockwise when looking from the outside).
281// Multi elements - Yes.
282// Parent element - <volume>.
283//
284// Children elements:
285// <v1>, <v2>, <v3>
286// Multi elements - No.
287// Index of the desired vertices in a triangle or edge.
288void AMFImporter::ParseNode_Triangle()
289{
290CAMFImporter_NodeElement* ne;
291
292 // create new color object.
293 ne = new CAMFImporter_NodeElement_Triangle(mNodeElement_Cur);
294
295 CAMFImporter_NodeElement_Triangle& als = *((CAMFImporter_NodeElement_Triangle*)ne);// alias for convenience
296
297 // Check for child nodes
298 if(!mReader->isEmptyElement())
299 {
300 bool col_read = false, tex_read = false;
301 bool read_flag[3] = { false, false, false };
302
303 ParseHelper_Node_Enter(ne);
304 MACRO_NODECHECK_LOOPBEGIN("triangle");
305 if(XML_CheckNode_NameEqual("color"))
306 {
307 // Check if data already defined.
308 if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <triangle>.");
309 // read data and set flag about it
310 ParseNode_Color();
311 col_read = true;
312
313 continue;
314 }
315
316 if(XML_CheckNode_NameEqual("texmap"))// new name of node: "texmap".
317 {
318 // Check if data already defined.
319 if(tex_read) Throw_MoreThanOnceDefined("texmap", "Only one texture coordinate can be defined for <triangle>.");
320 // read data and set flag about it
321 ParseNode_TexMap();
322 tex_read = true;
323
324 continue;
325 }
326 else if(XML_CheckNode_NameEqual("map"))// old name of node: "map".
327 {
328 // Check if data already defined.
329 if(tex_read) Throw_MoreThanOnceDefined("map", "Only one texture coordinate can be defined for <triangle>.");
330 // read data and set flag about it
331 ParseNode_TexMap(true);
332 tex_read = true;
333
334 continue;
335 }
336
337 MACRO_NODECHECK_READCOMP_U32("v1", read_flag[0], als.V[0]);
338 MACRO_NODECHECK_READCOMP_U32("v2", read_flag[1], als.V[1]);
339 MACRO_NODECHECK_READCOMP_U32("v3", read_flag[2], als.V[2]);
340 MACRO_NODECHECK_LOOPEND("triangle");
341 ParseHelper_Node_Exit();
342 // check that all components was defined
343 if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all vertices of the triangle are defined.");
344
345 }// if(!mReader->isEmptyElement())
346 else
347 {
348 mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
349 }// if(!mReader->isEmptyElement()) else
350
351 mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
352}
353
354}// namespace Assimp
355
356#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER
357