1 | /* |
2 | Open Asset Import Library (assimp) |
3 | ---------------------------------------------------------------------- |
4 | |
5 | Copyright (c) 2006-2017, assimp team |
6 | |
7 | All rights reserved. |
8 | |
9 | Redistribution and use of this software in source and binary forms, |
10 | with or without modification, are permitted provided that the |
11 | following conditions are met: |
12 | |
13 | * Redistributions of source code must retain the above |
14 | copyright notice, this list of conditions and the |
15 | following disclaimer. |
16 | |
17 | * Redistributions in binary form must reproduce the above |
18 | copyright notice, this list of conditions and the |
19 | following disclaimer in the documentation and/or other |
20 | materials provided with the distribution. |
21 | |
22 | * Neither the name of the assimp team, nor the names of its |
23 | contributors may be used to endorse or promote products |
24 | derived from this software without specific prior |
25 | written permission of the assimp team. |
26 | |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | OF 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 | |
51 | namespace 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. |
69 | void 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> |
146 | void 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 | // /> |
199 | void 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 | |