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_Shape.cpp
42/// \brief Parsing data from nodes of "Shape" 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// <Shape
55// DEF="" ID
56// USE="" IDREF
57// bboxCenter="0 0 0" SFVec3f [initializeOnly]
58// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
59// >
60// <!-- ShapeChildContentModel -->
61// "ShapeChildContentModel is the child-node content model corresponding to X3DShapeNode. ShapeChildContentModel can contain a single Appearance node and a
62// single geometry node, in any order.
63// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
64// </Shape>
65// A Shape node is unlit if either of the following is true:
66// The shape's appearance field is NULL (default).
67// The material field in the Appearance node is NULL (default).
68// NOTE Geometry nodes that represent lines or points do not support lighting.
69void X3DImporter::ParseNode_Shape_Shape()
70{
71 std::string use, def;
72 CX3DImporter_NodeElement* ne( nullptr );
73
74 MACRO_ATTRREAD_LOOPBEG;
75 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
76 MACRO_ATTRREAD_LOOPEND;
77
78 // if "USE" defined then find already defined element.
79 if(!use.empty())
80 {
81 MACRO_USE_CHECKANDAPPLY(def, use, ENET_Shape, ne);
82 }
83 else
84 {
85 // create and if needed - define new geometry object.
86 ne = new CX3DImporter_NodeElement_Shape(NodeElement_Cur);
87 if(!def.empty()) ne->ID = def;
88
89 // check for child nodes
90 if(!mReader->isEmptyElement())
91 {
92 ParseHelper_Node_Enter(ne);
93 MACRO_NODECHECK_LOOPBEGIN("Shape");
94 // check for appearance node
95 if(XML_CheckNode_NameEqual("Appearance")) { ParseNode_Shape_Appearance(); continue; }
96 // check for X3DGeometryNodes
97 if(XML_CheckNode_NameEqual("Arc2D")) { ParseNode_Geometry2D_Arc2D(); continue; }
98 if(XML_CheckNode_NameEqual("ArcClose2D")) { ParseNode_Geometry2D_ArcClose2D(); continue; }
99 if(XML_CheckNode_NameEqual("Circle2D")) { ParseNode_Geometry2D_Circle2D(); continue; }
100 if(XML_CheckNode_NameEqual("Disk2D")) { ParseNode_Geometry2D_Disk2D(); continue; }
101 if(XML_CheckNode_NameEqual("Polyline2D")) { ParseNode_Geometry2D_Polyline2D(); continue; }
102 if(XML_CheckNode_NameEqual("Polypoint2D")) { ParseNode_Geometry2D_Polypoint2D(); continue; }
103 if(XML_CheckNode_NameEqual("Rectangle2D")) { ParseNode_Geometry2D_Rectangle2D(); continue; }
104 if(XML_CheckNode_NameEqual("TriangleSet2D")) { ParseNode_Geometry2D_TriangleSet2D(); continue; }
105 if(XML_CheckNode_NameEqual("Box")) { ParseNode_Geometry3D_Box(); continue; }
106 if(XML_CheckNode_NameEqual("Cone")) { ParseNode_Geometry3D_Cone(); continue; }
107 if(XML_CheckNode_NameEqual("Cylinder")) { ParseNode_Geometry3D_Cylinder(); continue; }
108 if(XML_CheckNode_NameEqual("ElevationGrid")) { ParseNode_Geometry3D_ElevationGrid(); continue; }
109 if(XML_CheckNode_NameEqual("Extrusion")) { ParseNode_Geometry3D_Extrusion(); continue; }
110 if(XML_CheckNode_NameEqual("IndexedFaceSet")) { ParseNode_Geometry3D_IndexedFaceSet(); continue; }
111 if(XML_CheckNode_NameEqual("Sphere")) { ParseNode_Geometry3D_Sphere(); continue; }
112 if(XML_CheckNode_NameEqual("IndexedLineSet")) { ParseNode_Rendering_IndexedLineSet(); continue; }
113 if(XML_CheckNode_NameEqual("LineSet")) { ParseNode_Rendering_LineSet(); continue; }
114 if(XML_CheckNode_NameEqual("PointSet")) { ParseNode_Rendering_PointSet(); continue; }
115 if(XML_CheckNode_NameEqual("IndexedTriangleFanSet")) { ParseNode_Rendering_IndexedTriangleFanSet(); continue; }
116 if(XML_CheckNode_NameEqual("IndexedTriangleSet")) { ParseNode_Rendering_IndexedTriangleSet(); continue; }
117 if(XML_CheckNode_NameEqual("IndexedTriangleStripSet")) { ParseNode_Rendering_IndexedTriangleStripSet(); continue; }
118 if(XML_CheckNode_NameEqual("TriangleFanSet")) { ParseNode_Rendering_TriangleFanSet(); continue; }
119 if(XML_CheckNode_NameEqual("TriangleSet")) { ParseNode_Rendering_TriangleSet(); continue; }
120 if(XML_CheckNode_NameEqual("TriangleStripSet")) { ParseNode_Rendering_TriangleStripSet(); continue; }
121 // check for X3DMetadataObject
122 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Shape");
123
124 MACRO_NODECHECK_LOOPEND("Shape");
125 ParseHelper_Node_Exit();
126 }// if(!mReader->isEmptyElement())
127 else
128 {
129 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
130 }
131
132 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
133 }// if(!use.empty()) else
134}
135
136// <Appearance
137// DEF="" ID
138// USE="" IDREF
139// >
140// <!-- AppearanceChildContentModel -->
141// "Child-node content model corresponding to X3DAppearanceChildNode. Appearance can contain FillProperties, LineProperties, Material, any Texture node and
142// any TextureTransform node, in any order. No more than one instance of these nodes is allowed. Appearance may also contain multiple shaders (ComposedShader,
143// PackagedShader, ProgramShader).
144// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
145// </Appearance>
146void X3DImporter::ParseNode_Shape_Appearance()
147{
148 std::string use, def;
149 CX3DImporter_NodeElement* ne( nullptr );
150
151 MACRO_ATTRREAD_LOOPBEG;
152 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
153 MACRO_ATTRREAD_LOOPEND;
154
155 // if "USE" defined then find already defined element.
156 if(!use.empty())
157 {
158 MACRO_USE_CHECKANDAPPLY(def, use, ENET_Appearance, ne);
159 }
160 else
161 {
162 // create and if needed - define new geometry object.
163 ne = new CX3DImporter_NodeElement_Appearance(NodeElement_Cur);
164 if(!def.empty()) ne->ID = def;
165
166 // check for child nodes
167 if(!mReader->isEmptyElement())
168 {
169 ParseHelper_Node_Enter(ne);
170 MACRO_NODECHECK_LOOPBEGIN("Appearance");
171 if(XML_CheckNode_NameEqual("Material")) { ParseNode_Shape_Material(); continue; }
172 if(XML_CheckNode_NameEqual("ImageTexture")) { ParseNode_Texturing_ImageTexture(); continue; }
173 if(XML_CheckNode_NameEqual("TextureTransform")) { ParseNode_Texturing_TextureTransform(); continue; }
174 // check for X3DMetadataObject
175 if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Appearance");
176
177 MACRO_NODECHECK_LOOPEND("Appearance");
178 ParseHelper_Node_Exit();
179 }// if(!mReader->isEmptyElement())
180 else
181 {
182 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
183 }
184
185 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
186 }// if(!use.empty()) else
187}
188
189// <Material
190// DEF="" ID
191// USE="" IDREF
192// ambientIntensity="0.2" SFFloat [inputOutput]
193// diffuseColor="0.8 0.8 0.8" SFColor [inputOutput]
194// emissiveColor="0 0 0" SFColor [inputOutput]
195// shininess="0.2" SFFloat [inputOutput]
196// specularColor="0 0 0" SFColor [inputOutput]
197// transparency="0" SFFloat [inputOutput]
198// />
199void X3DImporter::ParseNode_Shape_Material()
200{
201 std::string use, def;
202 float ambientIntensity = 0.2f;
203 float shininess = 0.2f;
204 float transparency = 0;
205 aiColor3D diffuseColor(0.8f, 0.8f, 0.8f);
206 aiColor3D emissiveColor(0, 0, 0);
207 aiColor3D specularColor(0, 0, 0);
208 CX3DImporter_NodeElement* ne( nullptr );
209
210 MACRO_ATTRREAD_LOOPBEG;
211 MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
212 MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
213 MACRO_ATTRREAD_CHECK_RET("shininess", shininess, XML_ReadNode_GetAttrVal_AsFloat);
214 MACRO_ATTRREAD_CHECK_RET("transparency", transparency, XML_ReadNode_GetAttrVal_AsFloat);
215 MACRO_ATTRREAD_CHECK_REF("diffuseColor", diffuseColor, XML_ReadNode_GetAttrVal_AsCol3f);
216 MACRO_ATTRREAD_CHECK_REF("emissiveColor", emissiveColor, XML_ReadNode_GetAttrVal_AsCol3f);
217 MACRO_ATTRREAD_CHECK_REF("specularColor", specularColor, XML_ReadNode_GetAttrVal_AsCol3f);
218 MACRO_ATTRREAD_LOOPEND;
219
220 // if "USE" defined then find already defined element.
221 if(!use.empty())
222 {
223 MACRO_USE_CHECKANDAPPLY(def, use, ENET_Material, ne);
224 }
225 else
226 {
227 // create and if needed - define new geometry object.
228 ne = new CX3DImporter_NodeElement_Material(NodeElement_Cur);
229 if(!def.empty()) ne->ID = def;
230
231 ((CX3DImporter_NodeElement_Material*)ne)->AmbientIntensity = ambientIntensity;
232 ((CX3DImporter_NodeElement_Material*)ne)->Shininess = shininess;
233 ((CX3DImporter_NodeElement_Material*)ne)->Transparency = transparency;
234 ((CX3DImporter_NodeElement_Material*)ne)->DiffuseColor = diffuseColor;
235 ((CX3DImporter_NodeElement_Material*)ne)->EmissiveColor = emissiveColor;
236 ((CX3DImporter_NodeElement_Material*)ne)->SpecularColor = specularColor;
237 // check for child nodes
238 if(!mReader->isEmptyElement())
239 ParseNode_Metadata(ne, "Material");
240 else
241 NodeElement_Cur->Child.push_back(ne);// add made object as child to current element
242
243 NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
244 }// if(!use.empty()) else
245}
246
247}// namespace Assimp
248
249#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
250