123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /*
- Open Asset Import Library (assimp)
- ----------------------------------------------------------------------
- Copyright (c) 2006-2020, assimp team
- All rights reserved.
- Redistribution and use of this software in source and binary forms,
- with or without modification, are permitted provided that the
- following conditions are met:
- * Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
- * Neither the name of the assimp team, nor the names of its
- contributors may be used to endorse or promote products
- derived from this software without specific prior
- written permission of the assimp team.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ----------------------------------------------------------------------
- */
- /// \file X3DImporter_Group.cpp
- /// \brief Parsing data from nodes of "Grouping" set of X3D.
- /// \date 2015-2016
- /// \author [email protected]
- #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
- #include "X3DImporter.hpp"
- #include "X3DImporter_Macro.hpp"
- namespace Assimp
- {
- // <Group
- // DEF="" ID
- // USE="" IDREF
- // bboxCenter="0 0 0" SFVec3f [initializeOnly]
- // bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
- // >
- // <!-- ChildContentModel -->
- // ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
- // other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
- // precise palette of legal nodes that are available depends on assigned profile and components.
- // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
- // </Group>
- // A Group node contains children nodes without introducing a new transformation. It is equivalent to a Transform node containing an identity transform.
- void X3DImporter::ParseNode_Grouping_Group()
- {
- std::string def, use;
- MACRO_ATTRREAD_LOOPBEG;
- MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
- MACRO_ATTRREAD_LOOPEND;
- // if "USE" defined then find already defined element.
- if(!use.empty())
- {
- CX3DImporter_NodeElement* ne;
- MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
- }
- else
- {
- ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
- // at this place new group mode created and made current, so we can name it.
- if(!def.empty()) NodeElement_Cur->ID = def;
- // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
- // for empty element exit from node in that place
- if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
- }// if(!use.empty()) else
- }
- void X3DImporter::ParseNode_Grouping_GroupEnd()
- {
- ParseHelper_Node_Exit();// go up in scene graph
- }
- // <StaticGroup
- // DEF="" ID
- // USE="" IDREF
- // bboxCenter="0 0 0" SFVec3f [initializeOnly]
- // bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
- // >
- // <!-- ChildContentModel -->
- // ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
- // other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
- // precise palette of legal nodes that are available depends on assigned profile and components.
- // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
- // </StaticGroup>
- // The StaticGroup node contains children nodes which cannot be modified. StaticGroup children are guaranteed to not change, send events, receive events or
- // contain any USE references outside the StaticGroup.
- void X3DImporter::ParseNode_Grouping_StaticGroup()
- {
- std::string def, use;
- MACRO_ATTRREAD_LOOPBEG;
- MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
- MACRO_ATTRREAD_LOOPEND;
- // if "USE" defined then find already defined element.
- if(!use.empty())
- {
- CX3DImporter_NodeElement* ne;
- MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
- }
- else
- {
- ParseHelper_Group_Begin(true);// create new grouping element and go deeper if node has children.
- // at this place new group mode created and made current, so we can name it.
- if(!def.empty()) NodeElement_Cur->ID = def;
- // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
- // for empty element exit from node in that place
- if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
- }// if(!use.empty()) else
- }
- void X3DImporter::ParseNode_Grouping_StaticGroupEnd()
- {
- ParseHelper_Node_Exit();// go up in scene graph
- }
- // <Switch
- // DEF="" ID
- // USE="" IDREF
- // bboxCenter="0 0 0" SFVec3f [initializeOnly]
- // bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
- // whichChoice="-1" SFInt32 [inputOutput]
- // >
- // <!-- ChildContentModel -->
- // ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
- // other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
- // precise palette of legal nodes that are available depends on assigned profile and components.
- // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
- // </Switch>
- // 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
- // 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
- // is chosen.
- void X3DImporter::ParseNode_Grouping_Switch()
- {
- std::string def, use;
- int32_t whichChoice = -1;
- MACRO_ATTRREAD_LOOPBEG;
- MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
- MACRO_ATTRREAD_CHECK_RET("whichChoice", whichChoice, XML_ReadNode_GetAttrVal_AsI32);
- MACRO_ATTRREAD_LOOPEND;
- // if "USE" defined then find already defined element.
- if(!use.empty())
- {
- CX3DImporter_NodeElement* ne;
- MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
- }
- else
- {
- ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
- // at this place new group mode created and made current, so we can name it.
- if(!def.empty()) NodeElement_Cur->ID = def;
- // also set values specific to this type of group
- ((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->UseChoice = true;
- ((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->Choice = whichChoice;
- // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
- // for empty element exit from node in that place
- if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
- }// if(!use.empty()) else
- }
- void X3DImporter::ParseNode_Grouping_SwitchEnd()
- {
- // just exit from node. Defined choice will be accepted at postprocessing stage.
- ParseHelper_Node_Exit();// go up in scene graph
- }
- // <Transform
- // DEF="" ID
- // USE="" IDREF
- // bboxCenter="0 0 0" SFVec3f [initializeOnly]
- // bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
- // center="0 0 0" SFVec3f [inputOutput]
- // rotation="0 0 1 0" SFRotation [inputOutput]
- // scale="1 1 1" SFVec3f [inputOutput]
- // scaleOrientation="0 0 1 0" SFRotation [inputOutput]
- // translation="0 0 0" SFVec3f [inputOutput]
- // >
- // <!-- ChildContentModel -->
- // ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
- // other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
- // precise palette of legal nodes that are available depends on assigned profile and components.
- // A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
- // </Transform>
- // 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.
- // 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
- // transformations. In matrix transformation notation, where C (center), SR (scaleOrientation), T (translation), R (rotation), and S (scale) are the
- // equivalent transformation matrices,
- // P' = T * C * R * SR * S * -SR * -C * P
- void X3DImporter::ParseNode_Grouping_Transform()
- {
- aiVector3D center(0, 0, 0);
- float rotation[4] = {0, 0, 1, 0};
- aiVector3D scale(1, 1, 1);// A value of zero indicates that any child geometry shall not be displayed
- float scale_orientation[4] = {0, 0, 1, 0};
- aiVector3D translation(0, 0, 0);
- aiMatrix4x4 matr, tmatr;
- std::string use, def;
- MACRO_ATTRREAD_LOOPBEG;
- MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
- MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec3f);
- MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec3f);
- MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec3f);
- if(an == "rotation")
- {
- std::vector<float> tvec;
- XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
- if(tvec.size() != 4) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
- memcpy(rotation, tvec.data(), sizeof(rotation));
- continue;
- }
- if(an == "scaleOrientation")
- {
- std::vector<float> tvec;
- XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
- if ( tvec.size() != 4 )
- {
- throw DeadlyImportError( "<Transform>: scaleOrientation vector must have 4 elements." );
- }
- ::memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation) );
- continue;
- }
- MACRO_ATTRREAD_LOOPEND;
- // if "USE" defined then find already defined element.
- if(!use.empty())
- {
- CX3DImporter_NodeElement* ne( nullptr );
- MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
- }
- else
- {
- ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
- // at this place new group mode created and made current, so we can name it.
- if ( !def.empty() )
- {
- NodeElement_Cur->ID = def;
- }
- //
- // also set values specific to this type of group
- //
- // calculate transformation matrix
- aiMatrix4x4::Translation(translation, matr);// T
- aiMatrix4x4::Translation(center, tmatr);// C
- matr *= tmatr;
- aiMatrix4x4::Rotation(rotation[3], aiVector3D(rotation[0], rotation[1], rotation[2]), tmatr);// R
- matr *= tmatr;
- aiMatrix4x4::Rotation(scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// SR
- matr *= tmatr;
- aiMatrix4x4::Scaling(scale, tmatr);// S
- matr *= tmatr;
- aiMatrix4x4::Rotation(-scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// -SR
- matr *= tmatr;
- aiMatrix4x4::Translation(-center, tmatr);// -C
- matr *= tmatr;
- // and assign it
- ((CX3DImporter_NodeElement_Group*)NodeElement_Cur)->Transformation = matr;
- // in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
- // for empty element exit from node in that place
- if ( mReader->isEmptyElement() )
- {
- ParseHelper_Node_Exit();
- }
- }// if(!use.empty()) else
- }
- void X3DImporter::ParseNode_Grouping_TransformEnd()
- {
- ParseHelper_Node_Exit();// go up in scene graph
- }
- }// namespace Assimp
- #endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|