1/*
2Open Asset Import Library (assimp)
3----------------------------------------------------------------------
4
5Copyright (c) 2006-2017, assimp team
6
7All rights reserved.
8
9Redistribution and use of this software in source and binary forms,
10with or without modification, are permitted provided that the
11following conditions are met:
12
13* Redistributions of source code must retain the above
14copyright notice, this list of conditions and the
15following disclaimer.
16
17* Redistributions in binary form must reproduce the above
18copyright notice, this list of conditions and the
19following disclaimer in the documentation and/or other
20materials provided with the distribution.
21
22* Neither the name of the assimp team, nor the names of its
23contributors may be used to endorse or promote products
24derived from this software without specific prior
25written permission of the assimp team.
26
27THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39----------------------------------------------------------------------
40*/
41/// \file X3DImporter_Rendering.cpp
42/// \brief Parsing data from nodes of "Rendering" set of X3D.
43/// \date 2015-2016
44/// \author smal.root@gmail.com
45
46#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
47
48#include "X3DImporter.hpp"
49#include "X3DImporter_Macro.hpp"
50
51namespace Assimp
52{
53
54// <Color
55// DEF="" ID
56// USE="" IDREF
57// color="" MFColor [inputOutput]
58// />
59void X3DImporter::ParseNode_Rendering_Color()
60{
61 std::string use, def;
62 std::list<aiColor3D> color;
63 CX3DImporter_NodeElement* ne( nullptr );
64
65 MACRO_ATTRREAD_LOOPBEG;
66 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
67 MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsListCol3f);
68 MACRO_ATTRREAD_LOOPEND;
69
70 // if "USE" defined then find already defined element.
71 if(!use.empty())
72 {
73 MACRO_USE_CHECKANDAPPLY(def, use, ENET_Color, ne);
74 }
75 else
76 {
77 // create and if needed - define new geometry object.
78 ne = new CX3DImporter_NodeElement_Color(NodeElement_Cur);
79 if(!def.empty()) ne->ID = def;
80
81 ((CX3DImporter_NodeElement_Color*)ne)->Value = color;
82 // check for X3DMetadataObject childs.
83 if(!mReader->isEmptyElement())
84 ParseNode_Metadata(ne, "Color");
85 else
86 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
87
88 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
89 }// if(!use.empty()) else
90}
91
92// <ColorRGBA
93// DEF="" ID
94// USE="" IDREF
95// color="" MFColorRGBA [inputOutput]
96// />
97void X3DImporter::ParseNode_Rendering_ColorRGBA()
98{
99 std::string use, def;
100 std::list<aiColor4D> color;
101 CX3DImporter_NodeElement* ne( nullptr );
102
103 MACRO_ATTRREAD_LOOPBEG;
104 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
105 MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsListCol4f);
106 MACRO_ATTRREAD_LOOPEND;
107
108 // if "USE" defined then find already defined element.
109 if(!use.empty())
110 {
111 MACRO_USE_CHECKANDAPPLY(def, use, ENET_ColorRGBA, ne);
112 }
113 else
114 {
115 // create and if needed - define new geometry object.
116 ne = new CX3DImporter_NodeElement_ColorRGBA(NodeElement_Cur);
117 if(!def.empty()) ne->ID = def;
118
119 ((CX3DImporter_NodeElement_ColorRGBA*)ne)->Value = color;
120 // check for X3DMetadataObject childs.
121 if(!mReader->isEmptyElement())
122 ParseNode_Metadata(ne, "ColorRGBA");
123 else
124 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
125
126 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
127 }// if(!use.empty()) else
128}
129
130// <Coordinate
131// DEF="" ID
132// USE="" IDREF
133// point="" MFVec3f [inputOutput]
134// />
135void X3DImporter::ParseNode_Rendering_Coordinate()
136{
137 std::string use, def;
138 std::list<aiVector3D> point;
139 CX3DImporter_NodeElement* ne( nullptr );
140
141 MACRO_ATTRREAD_LOOPBEG;
142 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
143 MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec3f);
144 MACRO_ATTRREAD_LOOPEND;
145
146 // if "USE" defined then find already defined element.
147 if(!use.empty())
148 {
149 MACRO_USE_CHECKANDAPPLY(def, use, ENET_Coordinate, ne);
150 }
151 else
152 {
153 // create and if needed - define new geometry object.
154 ne = new CX3DImporter_NodeElement_Coordinate(NodeElement_Cur);
155 if(!def.empty()) ne->ID = def;
156
157 ((CX3DImporter_NodeElement_Coordinate*)ne)->Value = point;
158 // check for X3DMetadataObject childs.
159 if(!mReader->isEmptyElement())
160 ParseNode_Metadata(ne, "Coordinate");
161 else
162 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
163
164 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
165 }// if(!use.empty()) else
166}
167
168// <IndexedLineSet
169// DEF="" ID
170// USE="" IDREF
171// colorIndex="" MFInt32 [initializeOnly]
172// colorPerVertex="true" SFBool [initializeOnly]
173// coordIndex="" MFInt32 [initializeOnly]
174// >
175// <!-- ColorCoordinateContentModel -->
176// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
177// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
178// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
179// </IndexedLineSet>
180void X3DImporter::ParseNode_Rendering_IndexedLineSet()
181{
182 std::string use, def;
183 std::vector<int32_t> colorIndex;
184 bool colorPerVertex = true;
185 std::vector<int32_t> coordIndex;
186 CX3DImporter_NodeElement* ne( nullptr );
187
188 MACRO_ATTRREAD_LOOPBEG;
189 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
190 MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32);
191 MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
192 MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
193 MACRO_ATTRREAD_LOOPEND;
194
195 // if "USE" defined then find already defined element.
196 if(!use.empty())
197 {
198 MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedLineSet, ne);
199 }
200 else
201 {
202 // check data
203 if((coordIndex.size() < 2) || ((coordIndex.back() == (-1)) && (coordIndex.size() < 3)))
204 throw DeadlyImportError("IndexedLineSet must contain not empty \"coordIndex\" attribute.");
205
206 // create and if needed - define new geometry object.
207 ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedLineSet, NodeElement_Cur);
208 if(!def.empty()) ne->ID = def;
209
210 CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
211
212 ne_alias.ColorIndex = colorIndex;
213 ne_alias.ColorPerVertex = colorPerVertex;
214 ne_alias.CoordIndex = coordIndex;
215 // check for child nodes
216 if(!mReader->isEmptyElement())
217 {
218 ParseHelper_Node_Enter(ne);
219 MACRO_NODECHECK_LOOPBEGIN("IndexedLineSet");
220 // check for Color and Coordinate nodes
221 if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
222 if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
223 if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
224 // check for X3DMetadataObject
225 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedLineSet");
226
227 MACRO_NODECHECK_LOOPEND("IndexedLineSet");
228 ParseHelper_Node_Exit();
229 }// if(!mReader->isEmptyElement())
230 else
231 {
232 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
233 }
234
235 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
236 }// if(!use.empty()) else
237}
238
239// <IndexedTriangleFanSet
240// DEF="" ID
241// USE="" IDREF
242// ccw="true" SFBool [initializeOnly]
243// colorPerVertex="true" SFBool [initializeOnly]
244// index="" MFInt32 [initializeOnly]
245// normalPerVertex="true" SFBool [initializeOnly]
246// solid="true" SFBool [initializeOnly]
247// >
248// <!-- ComposedGeometryContentModel -->
249// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
250// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
251// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
252// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
253// </IndexedTriangleFanSet>
254void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet()
255{
256 std::string use, def;
257 bool ccw = true;
258 bool colorPerVertex = true;
259 std::vector<int32_t> index;
260 bool normalPerVertex = true;
261 bool solid = true;
262 CX3DImporter_NodeElement* ne( nullptr );
263
264 MACRO_ATTRREAD_LOOPBEG;
265 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
266 MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
267 MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
268 MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
269 MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
270 MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
271 MACRO_ATTRREAD_LOOPEND;
272
273 // if "USE" defined then find already defined element.
274 if(!use.empty())
275 {
276 MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedTriangleFanSet, ne);
277 }
278 else
279 {
280 // check data
281 if(index.size() == 0) throw DeadlyImportError("IndexedTriangleFanSet must contain not empty \"index\" attribute.");
282
283 // create and if needed - define new geometry object.
284 ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet, NodeElement_Cur);
285 if(!def.empty()) ne->ID = def;
286
287 CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
288
289 ne_alias.CCW = ccw;
290 ne_alias.ColorPerVertex = colorPerVertex;
291 ne_alias.NormalPerVertex = normalPerVertex;
292 ne_alias.Solid = solid;
293
294 ne_alias.CoordIndex.clear();
295 int counter = 0;
296 int32_t idx[3];
297 for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
298 {
299 idx[2] = *idx_it;
300 if (idx[2] < 0)
301 {
302 counter = 0;
303 }
304 else
305 {
306 if (counter >= 2)
307 {
308 if(ccw)
309 {
310 ne_alias.CoordIndex.push_back(idx[0]);
311 ne_alias.CoordIndex.push_back(idx[1]);
312 ne_alias.CoordIndex.push_back(idx[2]);
313 }
314 else
315 {
316 ne_alias.CoordIndex.push_back(idx[0]);
317 ne_alias.CoordIndex.push_back(idx[2]);
318 ne_alias.CoordIndex.push_back(idx[1]);
319 }
320 ne_alias.CoordIndex.push_back(-1);
321 idx[1] = idx[2];
322 }
323 else
324 {
325 idx[counter] = idx[2];
326 }
327 ++counter;
328 }
329 }// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
330
331 // check for child nodes
332 if(!mReader->isEmptyElement())
333 {
334 ParseHelper_Node_Enter(ne);
335 MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleFanSet");
336 // check for X3DComposedGeometryNodes
337 if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
338 if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
339 if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
340 if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
341 if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
342 // check for X3DMetadataObject
343 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleFanSet");
344
345 MACRO_NODECHECK_LOOPEND("IndexedTriangleFanSet");
346 ParseHelper_Node_Exit();
347 }// if(!mReader->isEmptyElement())
348 else
349 {
350 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
351 }
352
353 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
354 }// if(!use.empty()) else
355}
356
357// <IndexedTriangleSet
358// DEF="" ID
359// USE="" IDREF
360// ccw="true" SFBool [initializeOnly]
361// colorPerVertex="true" SFBool [initializeOnly]
362// index="" MFInt32 [initializeOnly]
363// normalPerVertex="true" SFBool [initializeOnly]
364// solid="true" SFBool [initializeOnly]
365// >
366// <!-- ComposedGeometryContentModel -->
367// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
368// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
369// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
370// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
371// </IndexedTriangleSet>
372void X3DImporter::ParseNode_Rendering_IndexedTriangleSet()
373{
374 std::string use, def;
375 bool ccw = true;
376 bool colorPerVertex = true;
377 std::vector<int32_t> index;
378 bool normalPerVertex = true;
379 bool solid = true;
380 CX3DImporter_NodeElement* ne( nullptr );
381
382 MACRO_ATTRREAD_LOOPBEG;
383 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
384 MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
385 MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
386 MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
387 MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
388 MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
389 MACRO_ATTRREAD_LOOPEND;
390
391 // if "USE" defined then find already defined element.
392 if(!use.empty())
393 {
394 MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedTriangleSet, ne);
395 }
396 else
397 {
398 // check data
399 if(index.size() == 0) throw DeadlyImportError("IndexedTriangleSet must contain not empty \"index\" attribute.");
400
401 // create and if needed - define new geometry object.
402 ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedTriangleSet, NodeElement_Cur);
403 if(!def.empty()) ne->ID = def;
404
405 CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
406
407 ne_alias.CCW = ccw;
408 ne_alias.ColorPerVertex = colorPerVertex;
409 ne_alias.NormalPerVertex = normalPerVertex;
410 ne_alias.Solid = solid;
411
412 ne_alias.CoordIndex.clear();
413 int counter = 0;
414 int32_t idx[3];
415 for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
416 {
417 idx[counter++] = *idx_it;
418 if (counter > 2)
419 {
420 counter = 0;
421 if(ccw)
422 {
423 ne_alias.CoordIndex.push_back(idx[0]);
424 ne_alias.CoordIndex.push_back(idx[1]);
425 ne_alias.CoordIndex.push_back(idx[2]);
426 }
427 else
428 {
429 ne_alias.CoordIndex.push_back(idx[0]);
430 ne_alias.CoordIndex.push_back(idx[2]);
431 ne_alias.CoordIndex.push_back(idx[1]);
432 }
433 ne_alias.CoordIndex.push_back(-1);
434 }
435 }// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
436
437 // check for child nodes
438 if(!mReader->isEmptyElement())
439 {
440 ParseHelper_Node_Enter(ne);
441 MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleSet");
442 // check for X3DComposedGeometryNodes
443 if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
444 if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
445 if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
446 if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
447 if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
448 // check for X3DMetadataObject
449 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleSet");
450
451 MACRO_NODECHECK_LOOPEND("IndexedTriangleSet");
452 ParseHelper_Node_Exit();
453 }// if(!mReader->isEmptyElement())
454 else
455 {
456 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
457 }
458
459 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
460 }// if(!use.empty()) else
461}
462
463// <IndexedTriangleStripSet
464// DEF="" ID
465// USE="" IDREF
466// ccw="true" SFBool [initializeOnly]
467// colorPerVertex="true" SFBool [initializeOnly]
468// index="" MFInt32 [initializeOnly]
469// normalPerVertex="true" SFBool [initializeOnly]
470// solid="true" SFBool [initializeOnly]
471// >
472// <!-- ComposedGeometryContentModel -->
473// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
474// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
475// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
476// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
477// </IndexedTriangleStripSet>
478void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet()
479{
480 std::string use, def;
481 bool ccw = true;
482 bool colorPerVertex = true;
483 std::vector<int32_t> index;
484 bool normalPerVertex = true;
485 bool solid = true;
486 CX3DImporter_NodeElement* ne( nullptr );
487
488 MACRO_ATTRREAD_LOOPBEG;
489 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
490 MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
491 MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
492 MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
493 MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
494 MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
495 MACRO_ATTRREAD_LOOPEND;
496
497 // if "USE" defined then find already defined element.
498 if(!use.empty())
499 {
500 MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedTriangleStripSet, ne);
501 }
502 else
503 {
504 // check data
505 if(index.size() == 0) throw DeadlyImportError("IndexedTriangleStripSet must contain not empty \"index\" attribute.");
506
507 // create and if needed - define new geometry object.
508 ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet, NodeElement_Cur);
509 if(!def.empty()) ne->ID = def;
510
511 CX3DImporter_NodeElement_IndexedSet& ne_alias = *((CX3DImporter_NodeElement_IndexedSet*)ne);
512
513 ne_alias.CCW = ccw;
514 ne_alias.ColorPerVertex = colorPerVertex;
515 ne_alias.NormalPerVertex = normalPerVertex;
516 ne_alias.Solid = solid;
517
518 ne_alias.CoordIndex.clear();
519 int counter = 0;
520 int32_t idx[3];
521 for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
522 {
523 idx[2] = *idx_it;
524 if (idx[2] < 0)
525 {
526 counter = 0;
527 }
528 else
529 {
530 if (counter >= 2)
531 {
532 if(ccw)
533 {
534 ne_alias.CoordIndex.push_back(idx[0]);
535 ne_alias.CoordIndex.push_back(idx[1]);
536 ne_alias.CoordIndex.push_back(idx[2]);
537 }
538 else
539 {
540 ne_alias.CoordIndex.push_back(idx[0]);
541 ne_alias.CoordIndex.push_back(idx[2]);
542 ne_alias.CoordIndex.push_back(idx[1]);
543 }
544 ne_alias.CoordIndex.push_back(-1);
545 }
546 idx[counter & 1] = idx[2];
547 ++counter;
548 }
549 }// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
550
551 // check for child nodes
552 if(!mReader->isEmptyElement())
553 {
554 ParseHelper_Node_Enter(ne);
555 MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleStripSet");
556 // check for X3DComposedGeometryNodes
557 if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
558 if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
559 if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
560 if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
561 if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
562 // check for X3DMetadataObject
563 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleStripSet");
564
565 MACRO_NODECHECK_LOOPEND("IndexedTriangleStripSet");
566 ParseHelper_Node_Exit();
567 }// if(!mReader->isEmptyElement())
568 else
569 {
570 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
571 }
572
573 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
574 }// if(!use.empty()) else
575}
576
577// <LineSet
578// DEF="" ID
579// USE="" IDREF
580// vertexCount="" MFInt32 [initializeOnly]
581// >
582// <!-- ColorCoordinateContentModel -->
583// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
584// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
585// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
586// </LineSet>
587void X3DImporter::ParseNode_Rendering_LineSet()
588{
589 std::string use, def;
590 std::vector<int32_t> vertexCount;
591 CX3DImporter_NodeElement* ne( nullptr );
592
593 MACRO_ATTRREAD_LOOPBEG;
594 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
595 MACRO_ATTRREAD_CHECK_REF("vertexCount", vertexCount, XML_ReadNode_GetAttrVal_AsArrI32);
596 MACRO_ATTRREAD_LOOPEND;
597
598 // if "USE" defined then find already defined element.
599 if(!use.empty())
600 {
601 MACRO_USE_CHECKANDAPPLY(def, use, ENET_LineSet, ne);
602 }
603 else
604 {
605 // check data
606 if(vertexCount.size() == 0) throw DeadlyImportError("LineSet must contain not empty \"vertexCount\" attribute.");
607
608 // create and if needed - define new geometry object.
609 ne = new CX3DImporter_NodeElement_Set(CX3DImporter_NodeElement::ENET_LineSet, NodeElement_Cur);
610 if(!def.empty()) ne->ID = def;
611
612 CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
613
614 ne_alias.VertexCount = vertexCount;
615 // create CoordIdx
616 size_t coord_num = 0;
617
618 ne_alias.CoordIndex.clear();
619 for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
620 {
621 if(*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two.");
622
623 for(int32_t i = 0; i < *vc_it; i++) ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num++));// add vertices indices
624
625 ne_alias.CoordIndex.push_back(-1);// add face delimiter.
626 }
627
628 // check for child nodes
629 if(!mReader->isEmptyElement())
630 {
631 ParseHelper_Node_Enter(ne);
632 MACRO_NODECHECK_LOOPBEGIN("LineSet");
633 // check for X3DComposedGeometryNodes
634 if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
635 if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
636 if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
637 // check for X3DMetadataObject
638 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("LineSet");
639
640 MACRO_NODECHECK_LOOPEND("LineSet");
641 ParseHelper_Node_Exit();
642 }// if(!mReader->isEmptyElement())
643 else
644 {
645 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
646 }
647
648 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
649 }// if(!use.empty()) else
650}
651
652// <PointSet
653// DEF="" ID
654// USE="" IDREF
655// >
656// <!-- ColorCoordinateContentModel -->
657// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
658// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
659// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
660// </PointSet>
661void X3DImporter::ParseNode_Rendering_PointSet()
662{
663 std::string use, def;
664 CX3DImporter_NodeElement* ne( nullptr );
665
666 MACRO_ATTRREAD_LOOPBEG;
667 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
668 MACRO_ATTRREAD_LOOPEND;
669
670 // if "USE" defined then find already defined element.
671 if(!use.empty())
672 {
673 MACRO_USE_CHECKANDAPPLY(def, use, ENET_PointSet, ne);
674 }
675 else
676 {
677 // create and if needed - define new geometry object.
678 ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_PointSet, NodeElement_Cur);
679 if(!def.empty()) ne->ID = def;
680
681 // check for child nodes
682 if(!mReader->isEmptyElement())
683 {
684 ParseHelper_Node_Enter(ne);
685 MACRO_NODECHECK_LOOPBEGIN("PointSet");
686 // check for X3DComposedGeometryNodes
687 if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
688 if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
689 if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
690 // check for X3DMetadataObject
691 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("PointSet");
692
693 MACRO_NODECHECK_LOOPEND("PointSet");
694 ParseHelper_Node_Exit();
695 }// if(!mReader->isEmptyElement())
696 else
697 {
698 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
699 }
700
701 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
702 }// if(!use.empty()) else
703}
704
705// <TriangleFanSet
706// DEF="" ID
707// USE="" IDREF
708// ccw="true" SFBool [initializeOnly]
709// colorPerVertex="true" SFBool [initializeOnly]
710// fanCount="" MFInt32 [inputOutput]
711// normalPerVertex="true" SFBool [initializeOnly]
712// solid="true" SFBool [initializeOnly]
713// >
714// <!-- ComposedGeometryContentModel -->
715// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
716// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
717// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
718// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
719// </TriangleFanSet>
720void X3DImporter::ParseNode_Rendering_TriangleFanSet()
721{
722 std::string use, def;
723 bool ccw = true;
724 bool colorPerVertex = true;
725 std::vector<int32_t> fanCount;
726 bool normalPerVertex = true;
727 bool solid = true;
728 CX3DImporter_NodeElement* ne( nullptr );
729
730 MACRO_ATTRREAD_LOOPBEG;
731 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
732 MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
733 MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
734 MACRO_ATTRREAD_CHECK_REF("fanCount", fanCount, XML_ReadNode_GetAttrVal_AsArrI32);
735 MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
736 MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
737 MACRO_ATTRREAD_LOOPEND;
738
739 // if "USE" defined then find already defined element.
740 if(!use.empty())
741 {
742 MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleFanSet, ne);
743 }
744 else
745 {
746 // check data
747 if(fanCount.size() == 0) throw DeadlyImportError("TriangleFanSet must contain not empty \"fanCount\" attribute.");
748
749 // create and if needed - define new geometry object.
750 ne = new CX3DImporter_NodeElement_Set(CX3DImporter_NodeElement::ENET_TriangleFanSet, NodeElement_Cur);
751 if(!def.empty()) ne->ID = def;
752
753 CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
754
755 ne_alias.CCW = ccw;
756 ne_alias.ColorPerVertex = colorPerVertex;
757 ne_alias.VertexCount = fanCount;
758 ne_alias.NormalPerVertex = normalPerVertex;
759 ne_alias.Solid = solid;
760 // create CoordIdx
761 size_t coord_num_first, coord_num_prev;
762
763 ne_alias.CoordIndex.clear();
764 // assign indices for first triangle
765 coord_num_first = 0;
766 coord_num_prev = 1;
767 for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
768 {
769 if(*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three.");
770
771 for(int32_t vc = 2; vc < *vc_it; vc++)
772 {
773 if(ccw)
774 {
775 // 2 1
776 // 0
777 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first));// first vertex is a center and always is [0].
778 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
779 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev));
780 }
781 else
782 {
783 // 1 2
784 // 0
785 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first));// first vertex is a center and always is [0].
786 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev + 1));
787 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
788 }// if(ccw) else
789
790 ne_alias.CoordIndex.push_back(-1);// add face delimiter.
791 }// for(int32_t vc = 2; vc < *vc_it; vc++)
792
793 coord_num_prev++;// that index will be center of next fan
794 coord_num_first = coord_num_prev++;// forward to next point - second point of fan
795 }// for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
796 // check for child nodes
797 if(!mReader->isEmptyElement())
798 {
799 ParseHelper_Node_Enter(ne);
800 MACRO_NODECHECK_LOOPBEGIN("TriangleFanSet");
801 // check for X3DComposedGeometryNodes
802 if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
803 if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
804 if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
805 if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
806 if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
807 // check for X3DMetadataObject
808 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleFanSet");
809
810 MACRO_NODECHECK_LOOPEND("TriangleFanSet");
811 ParseHelper_Node_Exit();
812 }// if(!mReader->isEmptyElement())
813 else
814 {
815 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
816 }
817
818 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
819 }// if(!use.empty()) else
820}
821
822// <TriangleSet
823// DEF="" ID
824// USE="" IDREF
825// ccw="true" SFBool [initializeOnly]
826// colorPerVertex="true" SFBool [initializeOnly]
827// normalPerVertex="true" SFBool [initializeOnly]
828// solid="true" SFBool [initializeOnly]
829// >
830// <!-- ComposedGeometryContentModel -->
831// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
832// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
833// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
834// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
835// </TriangleSet>
836void X3DImporter::ParseNode_Rendering_TriangleSet()
837{
838 std::string use, def;
839 bool ccw = true;
840 bool colorPerVertex = true;
841 bool normalPerVertex = true;
842 bool solid = true;
843 CX3DImporter_NodeElement* ne( nullptr );
844
845 MACRO_ATTRREAD_LOOPBEG;
846 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
847 MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
848 MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
849 MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
850 MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
851 MACRO_ATTRREAD_LOOPEND;
852
853 // if "USE" defined then find already defined element.
854 if(!use.empty())
855 {
856 MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleSet, ne);
857 }
858 else
859 {
860 // create and if needed - define new geometry object.
861 ne = new CX3DImporter_NodeElement_IndexedSet(CX3DImporter_NodeElement::ENET_TriangleSet, NodeElement_Cur);
862 if(!def.empty()) ne->ID = def;
863
864 CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
865
866 ne_alias.CCW = ccw;
867 ne_alias.ColorPerVertex = colorPerVertex;
868 ne_alias.NormalPerVertex = normalPerVertex;
869 ne_alias.Solid = solid;
870 // check for child nodes
871 if(!mReader->isEmptyElement())
872 {
873 ParseHelper_Node_Enter(ne);
874 MACRO_NODECHECK_LOOPBEGIN("TriangleSet");
875 // check for X3DComposedGeometryNodes
876 if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
877 if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
878 if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
879 if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
880 if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
881 // check for X3DMetadataObject
882 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleSet");
883
884 MACRO_NODECHECK_LOOPEND("TriangleSet");
885 ParseHelper_Node_Exit();
886 }// if(!mReader->isEmptyElement())
887 else
888 {
889 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
890 }
891
892 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
893 }// if(!use.empty()) else
894}
895
896// <TriangleStripSet
897// DEF="" ID
898// USE="" IDREF
899// ccw="true" SFBool [initializeOnly]
900// colorPerVertex="true" SFBool [initializeOnly]
901// normalPerVertex="true" SFBool [initializeOnly]
902// solid="true" SFBool [initializeOnly]
903// stripCount="" MFInt32 [inputOutput]
904// >
905// <!-- ComposedGeometryContentModel -->
906// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
907// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
908// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
909// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
910// </TriangleStripSet>
911void X3DImporter::ParseNode_Rendering_TriangleStripSet()
912{
913 std::string use, def;
914 bool ccw = true;
915 bool colorPerVertex = true;
916 std::vector<int32_t> stripCount;
917 bool normalPerVertex = true;
918 bool solid = true;
919 CX3DImporter_NodeElement* ne( nullptr );
920
921 MACRO_ATTRREAD_LOOPBEG;
922 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
923 MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
924 MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
925 MACRO_ATTRREAD_CHECK_REF("stripCount", stripCount, XML_ReadNode_GetAttrVal_AsArrI32);
926 MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
927 MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
928 MACRO_ATTRREAD_LOOPEND;
929
930 // if "USE" defined then find already defined element.
931 if(!use.empty())
932 {
933 MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleStripSet, ne);
934 }
935 else
936 {
937 // check data
938 if(stripCount.size() == 0) throw DeadlyImportError("TriangleStripSet must contain not empty \"stripCount\" attribute.");
939
940 // create and if needed - define new geometry object.
941 ne = new CX3DImporter_NodeElement_Set(CX3DImporter_NodeElement::ENET_TriangleStripSet, NodeElement_Cur);
942 if(!def.empty()) ne->ID = def;
943
944 CX3DImporter_NodeElement_Set& ne_alias = *((CX3DImporter_NodeElement_Set*)ne);
945
946 ne_alias.CCW = ccw;
947 ne_alias.ColorPerVertex = colorPerVertex;
948 ne_alias.VertexCount = stripCount;
949 ne_alias.NormalPerVertex = normalPerVertex;
950 ne_alias.Solid = solid;
951 // create CoordIdx
952 size_t coord_num0, coord_num1, coord_num2;// indices of current triangle
953 bool odd_tri;// sequence of current triangle
954 size_t coord_num_sb;// index of first point of strip
955
956 ne_alias.CoordIndex.clear();
957 coord_num_sb = 0;
958 for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
959 {
960 if(*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three.");
961
962 // set initial values for first triangle
963 coord_num0 = coord_num_sb;
964 coord_num1 = coord_num_sb + 1;
965 coord_num2 = coord_num_sb + 2;
966 odd_tri = true;
967
968 for(int32_t vc = 2; vc < *vc_it; vc++)
969 {
970 if(ccw)
971 {
972 // 0 2
973 // 1
974 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
975 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
976 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
977 }
978 else
979 {
980 // 0 1
981 // 2
982 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
983 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
984 ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
985 }// if(ccw) else
986
987 ne_alias.CoordIndex.push_back(-1);// add face delimiter.
988 // prepare values for next triangle
989 if(odd_tri)
990 {
991 coord_num0 = coord_num2;
992 coord_num2++;
993 }
994 else
995 {
996 coord_num1 = coord_num2;
997 coord_num2 = coord_num1 + 1;
998 }
999
1000 odd_tri = !odd_tri;
1001 coord_num_sb = coord_num2;// that index will be start of next strip
1002 }// for(int32_t vc = 2; vc < *vc_it; vc++)
1003 }// for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
1004 // check for child nodes
1005 if(!mReader->isEmptyElement())
1006 {
1007 ParseHelper_Node_Enter(ne);
1008 MACRO_NODECHECK_LOOPBEGIN("TriangleStripSet");
1009 // check for X3DComposedGeometryNodes
1010 if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
1011 if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
1012 if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
1013 if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
1014 if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
1015 // check for X3DMetadataObject
1016 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleStripSet");
1017
1018 MACRO_NODECHECK_LOOPEND("TriangleStripSet");
1019 ParseHelper_Node_Exit();
1020 }// if(!mReader->isEmptyElement())
1021 else
1022 {
1023 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
1024 }
1025
1026 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
1027 }// if(!use.empty()) else
1028}
1029
1030// <Normal
1031// DEF="" ID
1032// USE="" IDREF
1033// vector="" MFVec3f [inputOutput]
1034// />
1035void X3DImporter::ParseNode_Rendering_Normal()
1036{
1037std::string use, def;
1038std::list<aiVector3D> vector;
1039CX3DImporter_NodeElement* ne;
1040
1041 MACRO_ATTRREAD_LOOPBEG;
1042 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
1043 MACRO_ATTRREAD_CHECK_REF("vector", vector, XML_ReadNode_GetAttrVal_AsListVec3f);
1044 MACRO_ATTRREAD_LOOPEND;
1045
1046 // if "USE" defined then find already defined element.
1047 if(!use.empty())
1048 {
1049 MACRO_USE_CHECKANDAPPLY(def, use, ENET_Normal, ne);
1050 }
1051 else
1052 {
1053 // create and if needed - define new geometry object.
1054 ne = new CX3DImporter_NodeElement_Normal(NodeElement_Cur);
1055 if(!def.empty()) ne->ID = def;
1056
1057 ((CX3DImporter_NodeElement_Normal*)ne)->Value = vector;
1058 // check for X3DMetadataObject childs.
1059 if(!mReader->isEmptyElement())
1060 ParseNode_Metadata(ne, "Normal");
1061 else
1062 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
1063
1064 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
1065 }// if(!use.empty()) else
1066}
1067
1068}// namespace Assimp
1069
1070#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
1071