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