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