1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
5 
6 Copyright (c) 2006-2017, assimp team
7 
8 
9 All rights reserved.
10 
11 Redistribution and use of this software in source and binary forms,
12 with or without modification, are permitted provided that the following
13 conditions are met:
14 
15 * Redistributions of source code must retain the above
16 copyright notice, this list of conditions and the
17 following disclaimer.
18 
19 * Redistributions in binary form must reproduce the above
20 copyright notice, this list of conditions and the
21 following disclaimer in the documentation and/or other
22 materials provided with the distribution.
23 
24 * Neither the name of the assimp team, nor the names of its
25 contributors may be used to endorse or promote products
26 derived from this software without specific prior
27 written permission of the assimp team.
28 
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 OF 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 
53 namespace Assimp
54 {
55 
56 // <mesh>
57 // </mesh>
58 // A 3D mesh hull.
59 // Multi elements - Yes.
60 // Parent element - <object>.
ParseNode_Mesh()61 void AMFImporter::ParseNode_Mesh()
62 {
63 CAMFImporter_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>.
ParseNode_Vertices()102 void AMFImporter::ParseNode_Vertices()
103 {
104 CAMFImporter_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>.
ParseNode_Vertex()130 void AMFImporter::ParseNode_Vertex()
131 {
132 CAMFImporter_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.
ParseNode_Coordinates()188 void AMFImporter::ParseNode_Coordinates()
189 {
190 CAMFImporter_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>.
ParseNode_Volume()230 void AMFImporter::ParseNode_Volume()
231 {
232 std::string materialid;
233 std::string type;
234 CAMFImporter_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.
ParseNode_Triangle()288 void AMFImporter::ParseNode_Triangle()
289 {
290 CAMFImporter_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