X3DImporter_Rendering.cpp 40 KB

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