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