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_Postprocess.cpp |
42 | /// \brief Convert built scenegraph and objects to Assimp scenegraph. |
43 | /// \date 2015-2016 |
44 | /// \author smal.root@gmail.com |
45 | |
46 | #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER |
47 | |
48 | #include "X3DImporter.hpp" |
49 | |
50 | // Header files, Assimp. |
51 | #include <assimp/ai_assert.h> |
52 | #include "StandardShapes.h" |
53 | #include "StringUtils.h" |
54 | |
55 | // Header files, stdlib. |
56 | #include <algorithm> |
57 | #include <iterator> |
58 | #include <string> |
59 | |
60 | namespace Assimp |
61 | { |
62 | |
63 | aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const |
64 | { |
65 | CX3DImporter_NodeElement* cur_node; |
66 | std::list<aiMatrix4x4> matr; |
67 | aiMatrix4x4 out_matr; |
68 | |
69 | // starting walk from current element to root |
70 | cur_node = NodeElement_Cur; |
71 | if(cur_node != nullptr) |
72 | { |
73 | do |
74 | { |
75 | // if cur_node is group then store group transformation matrix in list. |
76 | if(cur_node->Type == CX3DImporter_NodeElement::ENET_Group) matr.push_back(((CX3DImporter_NodeElement_Group*)cur_node)->Transformation); |
77 | |
78 | cur_node = cur_node->Parent; |
79 | } while(cur_node != nullptr); |
80 | } |
81 | |
82 | // multiplicate all matrices in reverse order |
83 | for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); rit++) out_matr = out_matr * (*rit); |
84 | |
85 | return out_matr; |
86 | } |
87 | |
88 | void X3DImporter::PostprocessHelper_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, std::list<CX3DImporter_NodeElement*>& pList) const |
89 | { |
90 | // walk through childs and find for metadata. |
91 | for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++) |
92 | { |
93 | if(((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble) || |
94 | ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger) || |
95 | ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaString)) |
96 | { |
97 | pList.push_back(*el_it); |
98 | } |
99 | else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaSet) |
100 | { |
101 | PostprocessHelper_CollectMetadata(**el_it, pList); |
102 | } |
103 | }// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++) |
104 | } |
105 | |
106 | bool X3DImporter::PostprocessHelper_ElementIsMetadata(const CX3DImporter_NodeElement::EType pType) const |
107 | { |
108 | if((pType == CX3DImporter_NodeElement::ENET_MetaBoolean) || (pType == CX3DImporter_NodeElement::ENET_MetaDouble) || |
109 | (pType == CX3DImporter_NodeElement::ENET_MetaFloat) || (pType == CX3DImporter_NodeElement::ENET_MetaInteger) || |
110 | (pType == CX3DImporter_NodeElement::ENET_MetaString) || (pType == CX3DImporter_NodeElement::ENET_MetaSet)) |
111 | { |
112 | return true; |
113 | } |
114 | else |
115 | { |
116 | return false; |
117 | } |
118 | } |
119 | |
120 | bool X3DImporter::PostprocessHelper_ElementIsMesh(const CX3DImporter_NodeElement::EType pType) const |
121 | { |
122 | if((pType == CX3DImporter_NodeElement::ENET_Arc2D) || (pType == CX3DImporter_NodeElement::ENET_ArcClose2D) || |
123 | (pType == CX3DImporter_NodeElement::ENET_Box) || (pType == CX3DImporter_NodeElement::ENET_Circle2D) || |
124 | (pType == CX3DImporter_NodeElement::ENET_Cone) || (pType == CX3DImporter_NodeElement::ENET_Cylinder) || |
125 | (pType == CX3DImporter_NodeElement::ENET_Disk2D) || (pType == CX3DImporter_NodeElement::ENET_ElevationGrid) || |
126 | (pType == CX3DImporter_NodeElement::ENET_Extrusion) || (pType == CX3DImporter_NodeElement::ENET_IndexedFaceSet) || |
127 | (pType == CX3DImporter_NodeElement::ENET_IndexedLineSet) || (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || |
128 | (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleSet) || (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet) || |
129 | (pType == CX3DImporter_NodeElement::ENET_PointSet) || (pType == CX3DImporter_NodeElement::ENET_LineSet) || |
130 | (pType == CX3DImporter_NodeElement::ENET_Polyline2D) || (pType == CX3DImporter_NodeElement::ENET_Polypoint2D) || |
131 | (pType == CX3DImporter_NodeElement::ENET_Rectangle2D) || (pType == CX3DImporter_NodeElement::ENET_Sphere) || |
132 | (pType == CX3DImporter_NodeElement::ENET_TriangleFanSet) || (pType == CX3DImporter_NodeElement::ENET_TriangleSet) || |
133 | (pType == CX3DImporter_NodeElement::ENET_TriangleSet2D) || (pType == CX3DImporter_NodeElement::ENET_TriangleStripSet)) |
134 | { |
135 | return true; |
136 | } |
137 | else |
138 | { |
139 | return false; |
140 | } |
141 | } |
142 | |
143 | void X3DImporter::Postprocess_BuildLight(const CX3DImporter_NodeElement& pNodeElement, std::list<aiLight*>& pSceneLightList) const |
144 | { |
145 | const CX3DImporter_NodeElement_Light& ne = *( ( CX3DImporter_NodeElement_Light* ) &pNodeElement ); |
146 | aiMatrix4x4 transform_matr = PostprocessHelper_Matrix_GlobalToCurrent(); |
147 | aiLight* new_light = new aiLight; |
148 | |
149 | new_light->mName = ne.ID; |
150 | new_light->mColorAmbient = ne.Color * ne.AmbientIntensity; |
151 | new_light->mColorDiffuse = ne.Color * ne.Intensity; |
152 | new_light->mColorSpecular = ne.Color * ne.Intensity; |
153 | switch(pNodeElement.Type) |
154 | { |
155 | case CX3DImporter_NodeElement::ENET_DirectionalLight: |
156 | new_light->mType = aiLightSource_DIRECTIONAL; |
157 | new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr; |
158 | |
159 | break; |
160 | case CX3DImporter_NodeElement::ENET_PointLight: |
161 | new_light->mType = aiLightSource_POINT; |
162 | new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr; |
163 | new_light->mAttenuationConstant = ne.Attenuation.x; |
164 | new_light->mAttenuationLinear = ne.Attenuation.y; |
165 | new_light->mAttenuationQuadratic = ne.Attenuation.z; |
166 | |
167 | break; |
168 | case CX3DImporter_NodeElement::ENET_SpotLight: |
169 | new_light->mType = aiLightSource_SPOT; |
170 | new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr; |
171 | new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr; |
172 | new_light->mAttenuationConstant = ne.Attenuation.x; |
173 | new_light->mAttenuationLinear = ne.Attenuation.y; |
174 | new_light->mAttenuationQuadratic = ne.Attenuation.z; |
175 | new_light->mAngleInnerCone = ne.BeamWidth; |
176 | new_light->mAngleOuterCone = ne.CutOffAngle; |
177 | |
178 | break; |
179 | default: |
180 | throw DeadlyImportError("Postprocess_BuildLight. Unknown type of light: " + to_string(pNodeElement.Type) + "." ); |
181 | } |
182 | |
183 | pSceneLightList.push_back(new_light); |
184 | } |
185 | |
186 | void X3DImporter::Postprocess_BuildMaterial(const CX3DImporter_NodeElement& pNodeElement, aiMaterial** pMaterial) const |
187 | { |
188 | // check argument |
189 | if(pMaterial == nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. pMaterial is nullptr." ); |
190 | if(*pMaterial != nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. *pMaterial must be nullptr." ); |
191 | |
192 | *pMaterial = new aiMaterial; |
193 | aiMaterial& taimat = **pMaterial;// creating alias for convenience. |
194 | |
195 | // at this point pNodeElement point to <Appearance> node. Walk through childs and add all stored data. |
196 | for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++) |
197 | { |
198 | if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material) |
199 | { |
200 | aiColor3D tcol3; |
201 | float tvalf; |
202 | CX3DImporter_NodeElement_Material& tnemat = *((CX3DImporter_NodeElement_Material*)*el_it); |
203 | |
204 | tcol3.r = tnemat.AmbientIntensity, tcol3.g = tnemat.AmbientIntensity, tcol3.b = tnemat.AmbientIntensity; |
205 | taimat.AddProperty(&tcol3, 1, AI_MATKEY_COLOR_AMBIENT); |
206 | taimat.AddProperty(&tnemat.DiffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE); |
207 | taimat.AddProperty(&tnemat.EmissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE); |
208 | taimat.AddProperty(&tnemat.SpecularColor, 1, AI_MATKEY_COLOR_SPECULAR); |
209 | tvalf = 1; |
210 | taimat.AddProperty(&tvalf, 1, AI_MATKEY_SHININESS_STRENGTH); |
211 | taimat.AddProperty(&tnemat.Shininess, 1, AI_MATKEY_SHININESS); |
212 | tvalf = 1.0f - tnemat.Transparency; |
213 | taimat.AddProperty(&tvalf, 1, AI_MATKEY_OPACITY); |
214 | }// if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material) |
215 | else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_ImageTexture) |
216 | { |
217 | CX3DImporter_NodeElement_ImageTexture& tnetex = *((CX3DImporter_NodeElement_ImageTexture*)*el_it); |
218 | aiString url_str(tnetex.URL.c_str()); |
219 | int mode = aiTextureOp_Multiply; |
220 | |
221 | taimat.AddProperty(&url_str, AI_MATKEY_TEXTURE_DIFFUSE(0)); |
222 | taimat.AddProperty(&tnetex.RepeatS, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0)); |
223 | taimat.AddProperty(&tnetex.RepeatT, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0)); |
224 | taimat.AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0)); |
225 | }// else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_ImageTexture) |
226 | else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_TextureTransform) |
227 | { |
228 | aiUVTransform trans; |
229 | CX3DImporter_NodeElement_TextureTransform& tnetextr = *((CX3DImporter_NodeElement_TextureTransform*)*el_it); |
230 | |
231 | trans.mTranslation = tnetextr.Translation - tnetextr.Center; |
232 | trans.mScaling = tnetextr.Scale; |
233 | trans.mRotation = tnetextr.Rotation; |
234 | taimat.AddProperty(&trans, 1, AI_MATKEY_UVTRANSFORM_DIFFUSE(0)); |
235 | }// else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_TextureTransform) |
236 | }// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++) |
237 | } |
238 | |
239 | void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeElement, aiMesh** pMesh) const |
240 | { |
241 | // check argument |
242 | if(pMesh == nullptr) throw DeadlyImportError("Postprocess_BuildMesh. pMesh is nullptr." ); |
243 | if(*pMesh != nullptr) throw DeadlyImportError("Postprocess_BuildMesh. *pMesh must be nullptr." ); |
244 | |
245 | /************************************************************************************************************************************/ |
246 | /************************************************************ Geometry2D ************************************************************/ |
247 | /************************************************************************************************************************************/ |
248 | if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_Arc2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_ArcClose2D) || |
249 | (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Circle2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Disk2D) || |
250 | (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Polyline2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Polypoint2D) || |
251 | (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Rectangle2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet2D)) |
252 | { |
253 | CX3DImporter_NodeElement_Geometry2D& tnemesh = *((CX3DImporter_NodeElement_Geometry2D*)&pNodeElement);// create alias for convenience |
254 | std::vector<aiVector3D> tarr; |
255 | |
256 | tarr.reserve(tnemesh.Vertices.size()); |
257 | for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); it++) tarr.push_back(*it); |
258 | *pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help. |
259 | |
260 | return;// mesh is build, nothing to do anymore. |
261 | } |
262 | /************************************************************************************************************************************/ |
263 | /************************************************************ Geometry3D ************************************************************/ |
264 | /************************************************************************************************************************************/ |
265 | // |
266 | // Predefined figures |
267 | // |
268 | if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_Box) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Cone) || |
269 | (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Cylinder) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Sphere)) |
270 | { |
271 | CX3DImporter_NodeElement_Geometry3D& tnemesh = *((CX3DImporter_NodeElement_Geometry3D*)&pNodeElement);// create alias for convenience |
272 | std::vector<aiVector3D> tarr; |
273 | |
274 | tarr.reserve(tnemesh.Vertices.size()); |
275 | for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); it++) tarr.push_back(*it); |
276 | |
277 | *pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help. |
278 | |
279 | return;// mesh is build, nothing to do anymore. |
280 | } |
281 | // |
282 | // Parametric figures |
283 | // |
284 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid) |
285 | { |
286 | CX3DImporter_NodeElement_ElevationGrid& tnemesh = *((CX3DImporter_NodeElement_ElevationGrid*)&pNodeElement);// create alias for convenience |
287 | |
288 | // at first create mesh from existing vertices. |
289 | *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIdx, tnemesh.Vertices); |
290 | // copy additional information from children |
291 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
292 | { |
293 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) |
294 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); |
295 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) |
296 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex); |
297 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal) |
298 | MeshGeometry_AddNormal(**pMesh, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value, tnemesh.NormalPerVertex); |
299 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) |
300 | MeshGeometry_AddTexCoord(**pMesh, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); |
301 | else |
302 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + to_string((*ch_it)->Type) + "." ); |
303 | }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
304 | |
305 | return;// mesh is build, nothing to do anymore. |
306 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid) |
307 | // |
308 | // Indexed primitives sets |
309 | // |
310 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet) |
311 | { |
312 | CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience |
313 | |
314 | // at first search for <Coordinate> node and create mesh. |
315 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
316 | { |
317 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
318 | { |
319 | *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value); |
320 | } |
321 | } |
322 | |
323 | // copy additional information from children |
324 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
325 | { |
326 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) |
327 | MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); |
328 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) |
329 | MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, |
330 | tnemesh.ColorPerVertex); |
331 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
332 | {} // skip because already read when mesh created. |
333 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal) |
334 | MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value, |
335 | tnemesh.NormalPerVertex); |
336 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) |
337 | MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); |
338 | else |
339 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + to_string((*ch_it)->Type) + "." ); |
340 | }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
341 | |
342 | return;// mesh is build, nothing to do anymore. |
343 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet) |
344 | |
345 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet) |
346 | { |
347 | CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience |
348 | |
349 | // at first search for <Coordinate> node and create mesh. |
350 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
351 | { |
352 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
353 | { |
354 | *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value); |
355 | } |
356 | } |
357 | |
358 | // copy additional information from children |
359 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
360 | { |
361 | ai_assert(*pMesh); |
362 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) |
363 | MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); |
364 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) |
365 | MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, |
366 | tnemesh.ColorPerVertex); |
367 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
368 | {} // skip because already read when mesh created. |
369 | else |
370 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + to_string((*ch_it)->Type) + "." ); |
371 | }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
372 | |
373 | return;// mesh is build, nothing to do anymore. |
374 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet) |
375 | |
376 | if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleSet) || |
377 | (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || |
378 | (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet)) |
379 | { |
380 | CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience |
381 | |
382 | // at first search for <Coordinate> node and create mesh. |
383 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
384 | { |
385 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
386 | { |
387 | *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value); |
388 | } |
389 | } |
390 | |
391 | // copy additional information from children |
392 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
393 | { |
394 | ai_assert(*pMesh); |
395 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) |
396 | MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); |
397 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) |
398 | MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, |
399 | tnemesh.ColorPerVertex); |
400 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
401 | {} // skip because already read when mesh created. |
402 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal) |
403 | MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value, |
404 | tnemesh.NormalPerVertex); |
405 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) |
406 | MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); |
407 | else |
408 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \ |
409 | IndexedTriangleStripSet: " + to_string((*ch_it)->Type) + "." ); |
410 | }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
411 | |
412 | return;// mesh is build, nothing to do anymore. |
413 | }// if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet)) |
414 | |
415 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion) |
416 | { |
417 | CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience |
418 | |
419 | *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, tnemesh.Vertices); |
420 | |
421 | return;// mesh is build, nothing to do anymore. |
422 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion) |
423 | |
424 | // |
425 | // Primitives sets |
426 | // |
427 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet) |
428 | { |
429 | CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience |
430 | |
431 | // at first search for <Coordinate> node and create mesh. |
432 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
433 | { |
434 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
435 | { |
436 | std::vector<aiVector3D> vec_copy; |
437 | |
438 | vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size()); |
439 | for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin(); |
440 | it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++) |
441 | { |
442 | vec_copy.push_back(*it); |
443 | } |
444 | |
445 | *pMesh = StandardShapes::MakeMesh(vec_copy, 1); |
446 | } |
447 | } |
448 | |
449 | // copy additional information from children |
450 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
451 | { |
452 | ai_assert(*pMesh); |
453 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) |
454 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true); |
455 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) |
456 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, true); |
457 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
458 | {} // skip because already read when mesh created. |
459 | else |
460 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + to_string((*ch_it)->Type) + "." ); |
461 | }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
462 | |
463 | return;// mesh is build, nothing to do anymore. |
464 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet) |
465 | |
466 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet) |
467 | { |
468 | CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience |
469 | |
470 | // at first search for <Coordinate> node and create mesh. |
471 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
472 | { |
473 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
474 | { |
475 | *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value); |
476 | } |
477 | } |
478 | |
479 | // copy additional information from children |
480 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
481 | { |
482 | ai_assert(*pMesh); |
483 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) |
484 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true); |
485 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) |
486 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, true); |
487 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
488 | {} // skip because already read when mesh created. |
489 | else |
490 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + to_string((*ch_it)->Type) + "." ); |
491 | }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
492 | |
493 | return;// mesh is build, nothing to do anymore. |
494 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet) |
495 | |
496 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet) |
497 | { |
498 | CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience |
499 | |
500 | // at first search for <Coordinate> node and create mesh. |
501 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
502 | { |
503 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
504 | { |
505 | *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value); |
506 | } |
507 | } |
508 | |
509 | // copy additional information from children |
510 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
511 | { |
512 | if ( nullptr == *pMesh ) { |
513 | break; |
514 | } |
515 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) |
516 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value,tnemesh.ColorPerVertex); |
517 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) |
518 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex); |
519 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
520 | {} // skip because already read when mesh created. |
521 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal) |
522 | MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value, |
523 | tnemesh.NormalPerVertex); |
524 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) |
525 | MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); |
526 | else |
527 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + to_string((*ch_it)->Type) + "." ); |
528 | }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
529 | |
530 | return;// mesh is build, nothing to do anymore. |
531 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet) |
532 | |
533 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet) |
534 | { |
535 | CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience |
536 | |
537 | // at first search for <Coordinate> node and create mesh. |
538 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
539 | { |
540 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
541 | { |
542 | std::vector<aiVector3D> vec_copy; |
543 | |
544 | vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size()); |
545 | for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin(); |
546 | it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++) |
547 | { |
548 | vec_copy.push_back(*it); |
549 | } |
550 | |
551 | *pMesh = StandardShapes::MakeMesh(vec_copy, 3); |
552 | } |
553 | } |
554 | |
555 | // copy additional information from children |
556 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
557 | { |
558 | ai_assert(*pMesh); |
559 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) |
560 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); |
561 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) |
562 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex); |
563 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
564 | {} // skip because already read when mesh created. |
565 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal) |
566 | MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value, |
567 | tnemesh.NormalPerVertex); |
568 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) |
569 | MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); |
570 | else |
571 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + to_string((*ch_it)->Type) + "." ); |
572 | }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
573 | |
574 | return;// mesh is build, nothing to do anymore. |
575 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet) |
576 | |
577 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet) |
578 | { |
579 | CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience |
580 | |
581 | // at first search for <Coordinate> node and create mesh. |
582 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
583 | { |
584 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
585 | { |
586 | *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value); |
587 | } |
588 | } |
589 | |
590 | // copy additional information from children |
591 | for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
592 | { |
593 | ai_assert(*pMesh); |
594 | if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) |
595 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); |
596 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) |
597 | MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex); |
598 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate) |
599 | {} // skip because already read when mesh created. |
600 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal) |
601 | MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value, |
602 | tnemesh.NormalPerVertex); |
603 | else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate) |
604 | MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value); |
605 | else |
606 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + to_string((*ch_it)->Type) + "." ); |
607 | }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) |
608 | |
609 | return;// mesh is build, nothing to do anymore. |
610 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet) |
611 | |
612 | throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: " + to_string(pNodeElement.Type) + "." ); |
613 | } |
614 | |
615 | void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList, |
616 | std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const |
617 | { |
618 | std::list<CX3DImporter_NodeElement*>::const_iterator chit_begin = pNodeElement.Child.begin(); |
619 | std::list<CX3DImporter_NodeElement*>::const_iterator chit_end = pNodeElement.Child.end(); |
620 | std::list<aiNode*> SceneNode_Child; |
621 | std::list<unsigned int> SceneNode_Mesh; |
622 | |
623 | // At first read all metadata |
624 | Postprocess_CollectMetadata(pNodeElement, pSceneNode); |
625 | // check if we have deal with grouping node. Which can contain transformation or switch |
626 | if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group) |
627 | { |
628 | const CX3DImporter_NodeElement_Group& tne_group = *((CX3DImporter_NodeElement_Group*)&pNodeElement);// create alias for convenience |
629 | |
630 | pSceneNode.mTransformation = tne_group.Transformation; |
631 | if(tne_group.UseChoice) |
632 | { |
633 | // If Choice is less than zero or greater than the number of nodes in the children field, nothing is chosen. |
634 | if((tne_group.Choice < 0) || ((size_t)tne_group.Choice >= pNodeElement.Child.size())) |
635 | { |
636 | chit_begin = pNodeElement.Child.end(); |
637 | chit_end = pNodeElement.Child.end(); |
638 | } |
639 | else |
640 | { |
641 | for(size_t i = 0; i < (size_t)tne_group.Choice; i++) chit_begin++;// forward iterator to chosen node. |
642 | |
643 | chit_end = chit_begin; |
644 | chit_end++;// point end iterator to next element after chosen node. |
645 | } |
646 | }// if(tne_group.UseChoice) |
647 | }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group) |
648 | |
649 | // Reserve memory for fast access and check children. |
650 | for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++) |
651 | {// in this loop we do not read metadata because it's already read at begin. |
652 | if((*it)->Type == CX3DImporter_NodeElement::ENET_Group) |
653 | { |
654 | // if child is group then create new node and do recursive call. |
655 | aiNode* new_node = new aiNode; |
656 | |
657 | new_node->mName = (*it)->ID; |
658 | new_node->mParent = &pSceneNode; |
659 | SceneNode_Child.push_back(new_node); |
660 | Postprocess_BuildNode(**it, *new_node, pSceneMeshList, pSceneMaterialList, pSceneLightList); |
661 | } |
662 | else if((*it)->Type == CX3DImporter_NodeElement::ENET_Shape) |
663 | { |
664 | // shape can contain only one geometry and one appearance nodes. |
665 | Postprocess_BuildShape(*((CX3DImporter_NodeElement_Shape*)*it), SceneNode_Mesh, pSceneMeshList, pSceneMaterialList); |
666 | } |
667 | else if(((*it)->Type == CX3DImporter_NodeElement::ENET_DirectionalLight) || ((*it)->Type == CX3DImporter_NodeElement::ENET_PointLight) || |
668 | ((*it)->Type == CX3DImporter_NodeElement::ENET_SpotLight)) |
669 | { |
670 | Postprocess_BuildLight(*((CX3DImporter_NodeElement_Light*)*it), pSceneLightList); |
671 | } |
672 | else if(!PostprocessHelper_ElementIsMetadata((*it)->Type))// skip metadata |
673 | { |
674 | throw DeadlyImportError("Postprocess_BuildNode. Unknown type: " + to_string((*it)->Type) + "." ); |
675 | } |
676 | }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++) |
677 | |
678 | // copy data about children and meshes to aiNode. |
679 | if(SceneNode_Child.size() > 0) |
680 | { |
681 | std::list<aiNode*>::const_iterator it = SceneNode_Child.begin(); |
682 | |
683 | pSceneNode.mNumChildren = static_cast<unsigned int>(SceneNode_Child.size()); |
684 | pSceneNode.mChildren = new aiNode*[pSceneNode.mNumChildren]; |
685 | for(size_t i = 0; i < pSceneNode.mNumChildren; i++) pSceneNode.mChildren[i] = *it++; |
686 | } |
687 | |
688 | if(SceneNode_Mesh.size() > 0) |
689 | { |
690 | std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin(); |
691 | |
692 | pSceneNode.mNumMeshes = static_cast<unsigned int>(SceneNode_Mesh.size()); |
693 | pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes]; |
694 | for(size_t i = 0; i < pSceneNode.mNumMeshes; i++) pSceneNode.mMeshes[i] = *it++; |
695 | } |
696 | |
697 | // that's all. return to previous deals |
698 | } |
699 | |
700 | void X3DImporter::Postprocess_BuildShape(const CX3DImporter_NodeElement_Shape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd, |
701 | std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const |
702 | { |
703 | aiMaterial* tmat = nullptr; |
704 | aiMesh* tmesh = nullptr; |
705 | CX3DImporter_NodeElement::EType mesh_type = CX3DImporter_NodeElement::ENET_Invalid; |
706 | unsigned int mat_ind = 0; |
707 | |
708 | for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++) |
709 | { |
710 | if(PostprocessHelper_ElementIsMesh((*it)->Type)) |
711 | { |
712 | Postprocess_BuildMesh(**it, &tmesh); |
713 | if(tmesh != nullptr) |
714 | { |
715 | // if mesh successfully built then add data about it to arrays |
716 | pNodeMeshInd.push_back(static_cast<unsigned int>(pSceneMeshList.size())); |
717 | pSceneMeshList.push_back(tmesh); |
718 | // keep mesh type. Need above for texture coordinate generation. |
719 | mesh_type = (*it)->Type; |
720 | } |
721 | } |
722 | else if((*it)->Type == CX3DImporter_NodeElement::ENET_Appearance) |
723 | { |
724 | Postprocess_BuildMaterial(**it, &tmat); |
725 | if(tmat != nullptr) |
726 | { |
727 | // if material successfully built then add data about it to array |
728 | mat_ind = static_cast<unsigned int>(pSceneMaterialList.size()); |
729 | pSceneMaterialList.push_back(tmat); |
730 | } |
731 | } |
732 | }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++) |
733 | |
734 | // associate read material with read mesh. |
735 | if((tmesh != nullptr) && (tmat != nullptr)) |
736 | { |
737 | tmesh->mMaterialIndex = mat_ind; |
738 | // Check texture mapping. If material has texture but mesh has no texture coordinate then try to ask Assimp to generate texture coordinates. |
739 | if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0)) |
740 | { |
741 | int32_t tm; |
742 | aiVector3D tvec3; |
743 | |
744 | switch(mesh_type) |
745 | { |
746 | case CX3DImporter_NodeElement::ENET_Box: |
747 | tm = aiTextureMapping_BOX; |
748 | break; |
749 | case CX3DImporter_NodeElement::ENET_Cone: |
750 | case CX3DImporter_NodeElement::ENET_Cylinder: |
751 | tm = aiTextureMapping_CYLINDER; |
752 | break; |
753 | case CX3DImporter_NodeElement::ENET_Sphere: |
754 | tm = aiTextureMapping_SPHERE; |
755 | break; |
756 | default: |
757 | tm = aiTextureMapping_PLANE; |
758 | break; |
759 | }// switch(mesh_type) |
760 | |
761 | tmat->AddProperty(&tm, 1, AI_MATKEY_MAPPING_DIFFUSE(0)); |
762 | }// if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0)) |
763 | }// if((tmesh != nullptr) && (tmat != nullptr)) |
764 | } |
765 | |
766 | void X3DImporter::Postprocess_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode) const |
767 | { |
768 | std::list<CX3DImporter_NodeElement*> meta_list; |
769 | size_t meta_idx; |
770 | |
771 | PostprocessHelper_CollectMetadata(pNodeElement, meta_list);// find metadata in current node element. |
772 | if ( !meta_list.empty() ) |
773 | { |
774 | if ( pSceneNode.mMetaData != nullptr ) { |
775 | throw DeadlyImportError( "Postprocess. MetaData member in node are not nullptr. Something went wrong." ); |
776 | } |
777 | |
778 | // copy collected metadata to output node. |
779 | pSceneNode.mMetaData = aiMetadata::Alloc( static_cast<unsigned int>(meta_list.size()) ); |
780 | meta_idx = 0; |
781 | for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++, meta_idx++) |
782 | { |
783 | CX3DImporter_NodeElement_Meta* cur_meta = (CX3DImporter_NodeElement_Meta*)*it; |
784 | |
785 | // due to limitations we can add only first element of value list. |
786 | // Add an element according to its type. |
787 | if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean) |
788 | { |
789 | if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0) |
790 | pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.begin())); |
791 | } |
792 | else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble) |
793 | { |
794 | if(((CX3DImporter_NodeElement_MetaDouble*)cur_meta)->Value.size() > 0) |
795 | pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, (float)*(((CX3DImporter_NodeElement_MetaDouble*)cur_meta)->Value.begin())); |
796 | } |
797 | else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat) |
798 | { |
799 | if(((CX3DImporter_NodeElement_MetaFloat*)cur_meta)->Value.size() > 0) |
800 | pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((CX3DImporter_NodeElement_MetaFloat*)cur_meta)->Value.begin())); |
801 | } |
802 | else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger) |
803 | { |
804 | if(((CX3DImporter_NodeElement_MetaInteger*)cur_meta)->Value.size() > 0) |
805 | pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((CX3DImporter_NodeElement_MetaInteger*)cur_meta)->Value.begin())); |
806 | } |
807 | else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaString) |
808 | { |
809 | if(((CX3DImporter_NodeElement_MetaString*)cur_meta)->Value.size() > 0) |
810 | { |
811 | aiString tstr(((CX3DImporter_NodeElement_MetaString*)cur_meta)->Value.begin()->data()); |
812 | |
813 | pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, tstr); |
814 | } |
815 | } |
816 | else |
817 | { |
818 | throw DeadlyImportError("Postprocess. Unknown metadata type." ); |
819 | }// if((*it)->Type == CX3DImporter_NodeElement::ENET_Meta*) else |
820 | }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++) |
821 | }// if( !meta_list.empty() ) |
822 | } |
823 | |
824 | }// namespace Assimp |
825 | |
826 | #endif // !ASSIMP_BUILD_NO_X3D_IMPORTER |
827 | |