Coverage Report

Created: 2024-08-02 07:04

/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