X3DImporter_Group.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /// \file X3DImporter_Group.cpp
  2. /// \brief Parsing data from nodes of "Grouping" set of X3D.
  3. /// \date 2015-2016
  4. /// \author [email protected]
  5. #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
  6. #include "X3DImporter.hpp"
  7. #include "X3DImporter_Macro.hpp"
  8. namespace Assimp
  9. {
  10. // <Group
  11. // DEF="" ID
  12. // USE="" IDREF
  13. // bboxCenter="0 0 0" SFVec3f [initializeOnly]
  14. // bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
  15. // >
  16. // <!-- ChildContentModel -->
  17. // ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
  18. // other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
  19. // precise palette of legal nodes that are available depends on assigned profile and components.
  20. // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
  21. // </Group>
  22. // A Group node contains children nodes without introducing a new transformation. It is equivalent to a Transform node containing an identity transform.
  23. void X3DImporter::ParseNode_Grouping_Group()
  24. {
  25. std::string def, use;
  26. MACRO_ATTRREAD_LOOPBEG;
  27. MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
  28. MACRO_ATTRREAD_LOOPEND;
  29. // if "USE" defined then find already defined element.
  30. if(!use.empty())
  31. {
  32. CX3DImporter_NodeElement* ne;
  33. MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
  34. }
  35. else
  36. {
  37. ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
  38. // at this place new group mode created and made current, so we can name it.
  39. if(!def.empty()) NodeElement_Cur->ID = def;
  40. // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
  41. // for empty element exit from node in that place
  42. if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
  43. }// if(!use.empty()) else
  44. }
  45. void X3DImporter::ParseNode_Grouping_GroupEnd()
  46. {
  47. ParseHelper_Node_Exit();// go up in scene graph
  48. }
  49. // <StaticGroup
  50. // DEF="" ID
  51. // USE="" IDREF
  52. // bboxCenter="0 0 0" SFVec3f [initializeOnly]
  53. // bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
  54. // >
  55. // <!-- ChildContentModel -->
  56. // ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
  57. // other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
  58. // precise palette of legal nodes that are available depends on assigned profile and components.
  59. // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
  60. // </StaticGroup>
  61. // The StaticGroup node contains children nodes which cannot be modified. StaticGroup children are guaranteed to not change, send events, receive events or
  62. // contain any USE references outside the StaticGroup.
  63. void X3DImporter::ParseNode_Grouping_StaticGroup()
  64. {
  65. std::string def, use;
  66. MACRO_ATTRREAD_LOOPBEG;
  67. MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
  68. MACRO_ATTRREAD_LOOPEND;
  69. // if "USE" defined then find already defined element.
  70. if(!use.empty())
  71. {
  72. CX3DImporter_NodeElement* ne;
  73. MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
  74. }
  75. else
  76. {
  77. ParseHelper_Group_Begin(true);// create new grouping element and go deeper if node has children.
  78. // at this place new group mode created and made current, so we can name it.
  79. if(!def.empty()) NodeElement_Cur->ID = def;
  80. // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
  81. // for empty element exit from node in that place
  82. if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
  83. }// if(!use.empty()) else
  84. }
  85. void X3DImporter::ParseNode_Grouping_StaticGroupEnd()
  86. {
  87. ParseHelper_Node_Exit();// go up in scene graph
  88. }
  89. // <Switch
  90. // DEF="" ID
  91. // USE="" IDREF
  92. // bboxCenter="0 0 0" SFVec3f [initializeOnly]
  93. // bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
  94. // whichChoice="-1" SFInt32 [inputOutput]
  95. // >
  96. // <!-- ChildContentModel -->
  97. // ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
  98. // other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
  99. // precise palette of legal nodes that are available depends on assigned profile and components.
  100. // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
  101. // </Switch>
  102. // The Switch grouping node traverses zero or one of the nodes specified in the children field. The whichChoice field specifies the index of the child
  103. // to traverse, with the first child having index 0. If whichChoice is less than zero or greater than the number of nodes in the children field, nothing
  104. // is chosen.
  105. void X3DImporter::ParseNode_Grouping_Switch()
  106. {
  107. std::string def, use;
  108. int32_t whichChoice = -1;
  109. MACRO_ATTRREAD_LOOPBEG;
  110. MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
  111. MACRO_ATTRREAD_CHECK_RET("whichChoice", whichChoice, XML_ReadNode_GetAttrVal_AsI32);
  112. MACRO_ATTRREAD_LOOPEND;
  113. // if "USE" defined then find already defined element.
  114. if(!use.empty())
  115. {
  116. CX3DImporter_NodeElement* ne;
  117. MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
  118. }
  119. else
  120. {
  121. ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
  122. // at this place new group mode created and made current, so we can name it.
  123. if(!def.empty()) NodeElement_Cur->ID = def;
  124. // also set values specific to this type of group
  125. ((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->UseChoice = true;
  126. ((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->Choice = whichChoice;
  127. // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
  128. // for empty element exit from node in that place
  129. if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
  130. }// if(!use.empty()) else
  131. }
  132. void X3DImporter::ParseNode_Grouping_SwitchEnd()
  133. {
  134. // just exit from node. Defined choice will be accepted at postprocessing stage.
  135. ParseHelper_Node_Exit();// go up in scene graph
  136. }
  137. // <Transform
  138. // DEF="" ID
  139. // USE="" IDREF
  140. // bboxCenter="0 0 0" SFVec3f [initializeOnly]
  141. // bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
  142. // center="0 0 0" SFVec3f [inputOutput]
  143. // rotation="0 0 1 0" SFRotation [inputOutput]
  144. // scale="1 1 1" SFVec3f [inputOutput]
  145. // scaleOrientation="0 0 1 0" SFRotation [inputOutput]
  146. // translation="0 0 0" SFVec3f [inputOutput]
  147. // >
  148. // <!-- ChildContentModel -->
  149. // ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
  150. // other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
  151. // precise palette of legal nodes that are available depends on assigned profile and components.
  152. // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
  153. // </Transform>
  154. // The Transform node is a grouping node that defines a coordinate system for its children that is relative to the coordinate systems of its ancestors.
  155. // Given a 3-dimensional point P and Transform node, P is transformed into point P' in its parent's coordinate system by a series of intermediate
  156. // transformations. In matrix transformation notation, where C (center), SR (scaleOrientation), T (translation), R (rotation), and S (scale) are the
  157. // equivalent transformation matrices,
  158. // P' = T * C * R * SR * S * -SR * -C * P
  159. void X3DImporter::ParseNode_Grouping_Transform()
  160. {
  161. aiVector3D center(0, 0, 0);
  162. float rotation[4] = {0, 0, 1, 0};
  163. aiVector3D scale(1, 1, 1);// A value of zero indicates that any child geometry shall not be displayed
  164. float scale_orientation[4] = {0, 0, 1, 0};
  165. aiVector3D translation(0, 0, 0);
  166. aiMatrix4x4 matr, tmatr;
  167. std::string use, def;
  168. MACRO_ATTRREAD_LOOPBEG;
  169. MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
  170. MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec3f);
  171. MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec3f);
  172. MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec3f);
  173. if(an == "rotation")
  174. {
  175. std::vector<float> tvec;
  176. XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
  177. if(tvec.size() != 4) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
  178. memcpy(rotation, tvec.data(), sizeof(rotation));
  179. continue;
  180. }
  181. if(an == "scaleOrientation")
  182. {
  183. std::vector<float> tvec;
  184. XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
  185. if(tvec.size() != 4) throw DeadlyImportError("<Transform>: scaleOrientation vector must have 4 elements.");
  186. memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation));
  187. continue;
  188. }
  189. MACRO_ATTRREAD_LOOPEND;
  190. // if "USE" defined then find already defined element.
  191. if(!use.empty())
  192. {
  193. CX3DImporter_NodeElement* ne;
  194. MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
  195. }
  196. else
  197. {
  198. ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
  199. // at this place new group mode created and made current, so we can name it.
  200. if(!def.empty()) NodeElement_Cur->ID = def;
  201. //
  202. // also set values specific to this type of group
  203. //
  204. // calculate tranformation matrix
  205. aiMatrix4x4::Translation(translation, matr);// T
  206. aiMatrix4x4::Translation(center, tmatr);// C
  207. matr *= tmatr;
  208. aiMatrix4x4::Rotation(rotation[3], aiVector3D(rotation[0], rotation[1], rotation[2]), tmatr);// R
  209. matr *= tmatr;
  210. aiMatrix4x4::Rotation(scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// SR
  211. matr *= tmatr;
  212. aiMatrix4x4::Scaling(scale, tmatr);// S
  213. matr *= tmatr;
  214. aiMatrix4x4::Rotation(-scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// -SR
  215. matr *= tmatr;
  216. aiMatrix4x4::Translation(-center, tmatr);// -C
  217. matr *= tmatr;
  218. // and assign it
  219. ((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->Transformation = matr;
  220. // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
  221. // for empty element exit from node in that place
  222. if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
  223. }// if(!use.empty()) else
  224. }
  225. void X3DImporter::ParseNode_Grouping_TransformEnd()
  226. {
  227. ParseHelper_Node_Exit();// go up in scene graph
  228. }
  229. }// namespace Assimp
  230. #endif // !ASSIMP_BUILD_NO_X3D_IMPORTER