root/OpenSceneGraph/trunk/src/osgPlugins/vrml/IndexedFaceSet.cpp @ 13557

Revision 13557, 12.3 kB (checked in by robert, 106 minutes ago)

Added if () block to avoid script variables set to NOT-Found being used in searching

  • Property svn:eol-style set to native
Line 
1// -*-c++-*-
2
3#include "ReaderWriterVRML2.h"
4
5
6#if defined(_MSC_VER)
7#   pragma warning(disable: 4250)
8#   pragma warning(disable: 4290)
9#   pragma warning(disable: 4800)
10#endif
11
12#include <openvrml/node.h>
13
14#include <osg/CullFace>
15
16osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97IndexedFaceSet(openvrml::node *vrml_ifs) const
17{
18    osg::ref_ptr<deprecated_osg::Geometry> osg_geom = new deprecated_osg::Geometry();
19
20    osg_geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON));
21
22    // get array of vertex coordinate_nodes
23    if(vrml_ifs->type().id() == "IndexedFaceSet")
24    {
25        std::auto_ptr<openvrml::field_value> fv = vrml_ifs->field("coord");
26        const openvrml::sfnode *sfn = dynamic_cast<const openvrml::sfnode *>(fv.get());
27
28        openvrml::coordinate_node *vrml_coord_node = dynamic_cast<openvrml::coordinate_node *>((sfn->value()).get());
29        const std::vector<openvrml::vec3f> &vrml_coord = vrml_coord_node->point();
30
31        osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
32
33        unsigned i;
34        for (i = 0; i < vrml_coord.size(); i++)
35        {
36            openvrml::vec3f vec = vrml_coord[i];
37            osg_vertices->push_back(osg::Vec3(vec[0], vec[1], vec[2]));
38        }
39
40        osg_geom->setVertexArray(osg_vertices.get());
41
42        // get array of vertex indices
43        std::auto_ptr<openvrml::field_value> fv2 = vrml_ifs->field("coordIndex");
44        const openvrml::mfint32 *vrml_coord_index = dynamic_cast<const openvrml::mfint32 *>(fv2.get());
45
46        osg::ref_ptr<osg::IntArray> osg_vert_index = new osg::IntArray();
47
48        int num_vert = 0;
49        for (i = 0; i < vrml_coord_index->value().size(); i++)
50        {
51            int index = vrml_coord_index->value()[i];
52            if (index == -1)
53            {
54                static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0))->push_back(num_vert);
55                num_vert = 0;
56            }
57            else
58            {
59                osg_vert_index->push_back(index);
60                ++num_vert;
61            }
62        }
63
64        if (num_vert)
65        {
66            //GvdB: Last coordIndex wasn't -1
67            static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0))->push_back(num_vert);
68        }
69
70        osg_geom->setVertexIndices(osg_vert_index.get());
71    }
72
73    {
74        // get texture coordinate_nodes
75        std::auto_ptr<openvrml::field_value> fv = vrml_ifs->field("texCoord");
76        const openvrml::sfnode *sfn = dynamic_cast<const openvrml::sfnode *>(fv.get());
77        openvrml::texture_coordinate_node *vrml_tex_coord_node = dynamic_cast<openvrml::texture_coordinate_node *>(sfn->value().get());
78
79        if (vrml_tex_coord_node != 0) // if no texture, node is NULL pointer
80        {
81            const std::vector<openvrml::vec2f> &vrml_tex_coord = vrml_tex_coord_node->point();
82            osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
83
84            unsigned i;
85            for (i = 0; i < vrml_tex_coord.size(); i++)
86            {
87                openvrml::vec2f vec = vrml_tex_coord[i];
88                osg_texcoords->push_back(osg::Vec2(vec[0], vec[1]));
89            }
90
91            osg_geom->setTexCoordArray(0, osg_texcoords.get());
92
93            // get array of texture indices
94            std::auto_ptr<openvrml::field_value> fv2 = vrml_ifs->field("texCoordIndex");
95            const openvrml::mfint32 *vrml_tex_coord_index = dynamic_cast<const openvrml::mfint32 *>(fv2.get());
96
97            osg::ref_ptr<osg::IntArray> osg_tex_coord_index = new osg::IntArray();
98
99            if(vrml_tex_coord_index->value().size() > 0)
100            {
101                for (i = 0; i < vrml_tex_coord_index->value().size(); i++)
102                {
103                    int index = vrml_tex_coord_index->value()[i];
104                    if (index != -1) {
105                        osg_tex_coord_index->push_back(index);
106                    }
107                }
108                osg_geom->setTexCoordIndices(0, osg_tex_coord_index.get());
109            } else
110                // no indices defined, use coordIndex
111                osg_geom->setTexCoordIndices(0, const_cast<osg::IndexArray*>(osg_geom->getVertexIndices()));
112        }
113    }
114
115    // get array of normals per vertex (if specified)
116    {
117        std::auto_ptr<openvrml::field_value> fv = vrml_ifs->field("normal");
118        const openvrml::sfnode *sfn = dynamic_cast<const openvrml::sfnode *>(fv.get());
119        openvrml::normal_node *vrml_normal_node = dynamic_cast<openvrml::normal_node *>(sfn->value().get());
120
121        if (vrml_normal_node != 0) // if no normals, node is NULL pointer
122        {
123            const std::vector<openvrml::vec3f>& vrml_normal_coord = vrml_normal_node->vector();
124
125            osg::ref_ptr<osg::Vec3Array> osg_normalcoords = new osg::Vec3Array();
126
127            unsigned i;
128            for (i = 0; i < vrml_normal_coord.size(); i++)
129            {
130                const openvrml::vec3f vec = vrml_normal_coord[i];
131                osg_normalcoords->push_back(osg::Vec3(vec[0], vec[1], vec[2]));
132            }
133            osg_geom->setNormalArray(osg_normalcoords.get());
134
135            // get array of normal indices
136            std::auto_ptr<openvrml::field_value> fv2 = vrml_ifs->field("normalIndex");
137            const openvrml::mfint32 *vrml_normal_index = dynamic_cast<const openvrml::mfint32 *>(fv2.get());
138
139            osg::ref_ptr<osg::IntArray> osg_normal_index = new osg::IntArray();
140
141            if (vrml_normal_index->value().size() > 0)
142            {
143                for (i = 0; i < vrml_normal_index->value().size(); i++)
144                {
145                    int index = vrml_normal_index->value()[i];
146                    if (index != -1)
147                    {
148                        osg_normal_index->push_back(index);
149                    }
150                }
151                osg_geom->setNormalIndices(osg_normal_index.get());
152            }
153            else
154                // unspecified, use the coordIndex field
155                osg_geom->setNormalIndices(const_cast<osg::IndexArray*>(osg_geom->getVertexIndices()));
156
157            // get normal binding
158            std::auto_ptr<openvrml::field_value> fv3 = vrml_ifs->field("normalPerVertex");
159            const openvrml::sfbool *vrml_norm_per_vertex = dynamic_cast<const openvrml::sfbool *>(fv3.get());
160
161            if (vrml_norm_per_vertex->value())
162            {
163                osg_geom->setNormalBinding(deprecated_osg::Geometry::BIND_PER_VERTEX);
164            } else
165            {
166                osg_geom->setNormalBinding(deprecated_osg::Geometry::BIND_PER_PRIMITIVE);
167            }
168        }
169    }
170
171    // get array of colours per vertex (if specified)
172    {
173        std::auto_ptr<openvrml::field_value> fv = vrml_ifs->field("color");
174        const openvrml::sfnode *sfn = dynamic_cast<const openvrml::sfnode *>(fv.get());
175        openvrml::color_node *vrml_color_node = dynamic_cast<openvrml::color_node *>(sfn->value().get());
176
177        if (vrml_color_node != 0) // if no colors, node is NULL pointer
178        {
179            const std::vector<openvrml::color> &vrml_colors = vrml_color_node->color();
180
181            osg::ref_ptr<osg::Vec3Array> osg_colors = new osg::Vec3Array();
182
183            unsigned i;
184            for (i = 0; i < vrml_colors.size(); i++)
185            {
186                const openvrml::color color = vrml_colors[i];
187                osg_colors->push_back(osg::Vec3(color.r(), color.g(), color.b()));
188            }
189            osg_geom->setColorArray(osg_colors.get());
190
191            // get array of color indices
192            std::auto_ptr<openvrml::field_value> fv2 = vrml_ifs->field("colorIndex");
193            const openvrml::mfint32 *vrml_color_index = dynamic_cast<const openvrml::mfint32 *>(fv2.get());
194
195            osg::ref_ptr<osg::IntArray> osg_color_index = new osg::IntArray();
196
197            if(vrml_color_index->value().size() > 0)
198            {
199                for (i = 0; i < vrml_color_index->value().size(); i++)
200                {
201                    int index = vrml_color_index->value()[i];
202                    if (index != -1) {
203                        osg_color_index->push_back(index);
204                    }
205                }
206                osg_geom->setColorIndices(osg_color_index.get());
207            } else
208                // unspecified, use coordIndices field
209                osg_geom->setColorIndices(const_cast<osg::IndexArray*>(osg_geom->getVertexIndices()));
210
211            // get color binding
212            std::auto_ptr<openvrml::field_value> fv3 = vrml_ifs->field("colorPerVertex");
213            const openvrml::sfbool *vrml_color_per_vertex = dynamic_cast<const openvrml::sfbool *>(fv3.get());
214
215            if (vrml_color_per_vertex->value())
216            {
217                osg_geom->setColorBinding(deprecated_osg::Geometry::BIND_PER_VERTEX);
218            } else
219            {
220                osg_geom->setColorBinding(deprecated_osg::Geometry::BIND_PER_PRIMITIVE);
221            }
222        }
223    }
224
225
226    // normal smoothing
227    std::auto_ptr<openvrml::field_value> fv_solid = vrml_ifs->field("solid");
228    const openvrml::sfbool *solid = dynamic_cast<const openvrml::sfbool *>(fv_solid.get());
229    if (solid->value())
230    {
231        osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
232    }
233
234    if (!osg_geom->getNormalArray())
235    {
236#if 0
237        // GvdB: This is what I wanted to do, but got zero normals since the triangles were considered temporaries (?)
238        osgUtil::SmoothingVisitor().smooth(*osg_geom);
239#else
240        // GvdB: So I ended up computing the smoothing normals myself. Also, I might add support for "creaseAngle" if a big need for it rises.
241        //       However, for now I can perfectly live with the fact that all edges are smoothed despite the use of a crease angle.
242        osg::Vec3Array& coords = *static_cast<osg::Vec3Array*>(osg_geom->getVertexArray());
243        assert(coords.size());
244
245        osg::Vec3Array* normals = new osg::Vec3Array(coords.size());
246
247        for (osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it)
248        {
249            (*it).set(0.0f, 0.0f, 0.0f);
250        }
251
252
253        const osg::IntArray& indices = *static_cast<const osg::IntArray*>(osg_geom->getVertexIndices());
254        osg::DrawArrayLengths& lengths = *static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0));
255        unsigned index = 0;
256
257        for (osg::DrawArrayLengths::iterator it = lengths.begin(); it != lengths.end(); ++it)
258        {
259            assert(*it >= 3);
260            const osg::Vec3& v0 = coords[indices[index]];
261            const osg::Vec3& v1 = coords[indices[index + 1]];
262            const osg::Vec3& v2 = coords[indices[index + 2]];
263
264            osg::Vec3 normal = (v1 - v0) ^ (v2 - v0);
265            normal.normalize();
266
267            for (int i = 0; i != *it; ++i)
268            {
269                (*normals)[indices[index + i]] += normal;
270            }
271
272            index += *it;
273        }
274
275        assert(index == indices.size());
276
277        for(osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it)
278        {
279            (*it).normalize();
280        }
281
282        osg_geom->setNormalArray(normals);
283        osg_geom->setNormalIndices(const_cast<osg::IndexArray*>(osg_geom->getVertexIndices()));
284        osg_geom->setNormalBinding(deprecated_osg::Geometry::BIND_PER_VERTEX);
285
286#endif
287    }
288
289    osg::DrawArrayLengths& lengths = *static_cast<osg::DrawArrayLengths*>(osg_geom->getPrimitiveSet(0));
290
291    osg::DrawArrayLengths::iterator it = lengths.begin();
292    if (it != lengths.end())
293    {
294        switch (*it)
295        {
296        case 3:
297            while (++it != lengths.end() && *it == 3)
298                ;
299
300            if (it == lengths.end())
301            {
302                // All polys are triangles
303                osg::ref_ptr<osg::DrawArrays> mesh = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES);
304                mesh->setCount(lengths.size() * 3);
305                osg_geom->removePrimitiveSet(0);
306                osg_geom->addPrimitiveSet(mesh.get());
307            }
308            break;
309
310        case 4:
311            while (++it != lengths.end() && *it == 4)
312                ;
313
314            if (it == lengths.end())
315            {
316                // All polys are quads
317                osg::ref_ptr<osg::DrawArrays> mesh = new osg::DrawArrays(osg::PrimitiveSet::QUADS);
318                mesh->setCount(lengths.size() * 4);
319                osg_geom->removePrimitiveSet(0);
320                osg_geom->addPrimitiveSet(mesh.get());
321            }
322
323            break;
324        }
325    }
326
327    return osg_geom.get();
328}
Note: See TracBrowser for help on using the browser.