Coverage Report

Created: 2025-06-22 07:30

/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