root/OpenSceneGraph/trunk/src/osgPlugins/vrml/Primitives.cpp @ 10785

Revision 10785, 16.4 kB (checked in by robert, 4 years ago)

From Jan Ciger, build fixes to work with OpenVRML 0.18.3.

Tweaks to this submission from Robert Osfield to fix missing elements in submission.

Line 
1// -*-c++-*-
2
3#include "ReaderWriterVRML2.h"
4
5#include <complex>
6
7#if defined(_MSC_VER)
8#   pragma warning(disable: 4250)
9#   pragma warning(disable: 4290)
10#   pragma warning(disable: 4800)
11#endif
12
13#include <openvrml/node.h>
14
15#include <osg/CullFace>
16
17osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97Box(openvrml::node* vrml_box) const
18{
19    std::auto_ptr<openvrml::field_value> fv = vrml_box->field("size");
20    const openvrml::vec3f &size = static_cast<const openvrml::sfvec3f *> (fv.get())->value();
21
22    osg::Vec3 halfSize(size[0] * 0.5f, size[1] * 0.5f, size[2] * 0.5f);
23
24    BoxLibrary::const_iterator it = m_boxLibrary.find(halfSize);
25    if (it != m_boxLibrary.end())
26    {
27        return (*it).second.get();
28    }
29
30    osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
31    osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
32    osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
33    osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
34
35    osg::ref_ptr<osg::DrawArrays> box = new osg::DrawArrays(osg::PrimitiveSet::QUADS);
36
37    osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2]));
38    osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2]));
39    osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2]));
40    osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2]));
41
42    osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2]));
43    osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2]));
44    osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2]));
45    osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2]));
46
47    osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2]));
48    osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2]));
49    osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2]));
50    osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2]));
51
52    osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2]));
53    osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2]));
54    osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2]));
55    osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2]));
56
57    osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2]));
58    osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2]));
59    osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2]));
60    osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2]));
61
62    osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2]));
63    osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2]));
64    osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2]));
65    osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2]));
66
67    for (int i = 0; i != 6; ++i)
68    {
69        osg_texcoords->push_back(osg::Vec2(0.0f, 1.0f));
70        osg_texcoords->push_back(osg::Vec2(0.0f, 0.0f));
71        osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f));
72        osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f));
73    }
74
75    osg_normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
76    osg_normals->push_back(osg::Vec3(0.0f, 0.0f, -1.0f));
77    osg_normals->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
78    osg_normals->push_back(osg::Vec3(-1.0f, 0.0f, 0.0f));
79    osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
80    osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
81
82    box->setCount(osg_vertices->size());
83
84    osg_geom->addPrimitiveSet(box.get());
85
86    osg_geom->setVertexArray(osg_vertices.get());
87    osg_geom->setTexCoordArray(0, osg_texcoords.get());
88    osg_geom->setNormalArray(osg_normals.get());
89    osg_geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
90
91    osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
92
93    m_boxLibrary[halfSize] = osg_geom;
94
95    return osg_geom.get();
96}
97
98osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97Sphere(openvrml::node* vrml_sphere) const
99{
100    std::auto_ptr<openvrml::field_value> fv = vrml_sphere->field("radius");
101    const float radius = static_cast<const openvrml::sffloat *> (fv.get())->value();
102
103    SphereLibrary::const_iterator it = m_sphereLibrary.find(radius);
104    if (it != m_sphereLibrary.end())
105    {
106        return (*it).second.get();
107    }
108
109    osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
110    osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
111    osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
112    osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
113
114    unsigned int numSegments = 40;
115    unsigned int numRows = 20;
116
117    const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments);
118    const float texCoordSDelta = 1.0f / float(numSegments);
119    const float phiDelta = float(osg::PI) / float(numRows);
120    const float texCoordTDelta = 1.0f / float(numRows);
121
122    float phi = -0.5f * float(osg::PI);
123    float texCoordT = 0.0f;
124
125    osg::ref_ptr<osg::DrawArrayLengths> sphere = new osg::DrawArrayLengths(osg::PrimitiveSet::QUAD_STRIP);
126
127    for (unsigned int i = 0; i < numRows; ++i, phi += phiDelta, texCoordT += texCoordTDelta)
128    {
129        std::complex<float> latBottom = std::polar(1.0f, phi);
130        std::complex<float> latTop = std::polar(1.0f, phi + phiDelta);
131        std::complex<float> eBottom = latBottom * radius;
132        std::complex<float> eTop = latTop * radius;
133
134        float theta = 0.0f;
135        float texCoordS = 0.0f;
136
137        for (unsigned int j = 0; j < numSegments; ++j, theta += thetaDelta, texCoordS += texCoordSDelta)
138        {
139            std::complex<float> n = -std::polar(1.0f, theta);
140
141            osg_normals->push_back(osg::Vec3(latTop.real() * n.imag(), latTop.imag(), latTop.real() * n.real()));
142            osg_normals->push_back(osg::Vec3(latBottom.real() * n.imag(), latBottom.imag(), latBottom.real() * n.real()));
143
144            osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT + texCoordTDelta));
145            osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT));
146
147            osg_vertices->push_back(osg::Vec3(eTop.real() * n.imag(), eTop.imag(), eTop.real() * n.real()));
148            osg_vertices->push_back(osg::Vec3(eBottom.real() * n.imag(), eBottom.imag(), eBottom.real() * n.real()));
149        }
150
151        osg_normals->push_back(osg::Vec3(0.0f, latTop.imag(), -latTop.real()));
152        osg_normals->push_back(osg::Vec3(0.0f, latBottom.imag(), -latBottom.real()));
153
154        osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT + texCoordTDelta));
155        osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT));
156
157        osg_vertices->push_back(osg::Vec3(0.0f, eTop.imag(), -eTop.real()));
158        osg_vertices->push_back(osg::Vec3(0.0f, eBottom.imag(), -eBottom.real()));
159
160        sphere->push_back(numSegments * 2 + 2);
161    }
162
163    osg_geom->addPrimitiveSet(sphere.get());
164
165    osg_geom->setVertexArray(osg_vertices.get());
166    osg_geom->setTexCoordArray(0, osg_texcoords.get());
167    osg_geom->setNormalArray(osg_normals.get());
168    osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
169
170    osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
171
172    m_sphereLibrary[radius] = osg_geom;
173
174    return osg_geom.get();
175}
176
177osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97Cone(openvrml::node* vrml_cone) const
178{
179    float height = static_cast<const openvrml::sffloat*>(vrml_cone->field("height").get())->value();
180    float radius = static_cast<const openvrml::sffloat*>(vrml_cone->field("bottomRadius").get())->value();
181    bool bottom = static_cast<const openvrml::sfbool*>(vrml_cone->field("bottom").get())->value();
182    bool side = static_cast<const openvrml::sfbool*>(vrml_cone->field("side").get())->value();
183
184    QuadricKey key(height, radius, bottom, side, false);
185
186    ConeLibrary::const_iterator it = m_coneLibrary.find(key);
187    if (it != m_coneLibrary.end())
188    {
189        return (*it).second.get();
190    }
191
192    osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
193    osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
194    osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
195    osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
196
197    unsigned int numSegments = 40;
198
199    const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments);
200
201    float topY = height * 0.5f;
202    float bottomY = height * -0.5f;
203
204    if (side)
205    {
206        osg::ref_ptr<osg::DrawArrays> side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP);
207
208        const float texCoordDelta = 1.0f / float(numSegments);
209        float theta = 0.0f;
210        float texCoord = 0.0f;
211
212        for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta)
213        {
214            std::complex<float> n = -std::polar(1.0f, theta);
215            std::complex<float> e = n * radius;
216
217            osg::Vec3 normal(n.imag() * height, radius, n.real() * height);
218            normal.normalize();
219
220            osg_normals->push_back(normal);
221            osg_normals->push_back(normal);
222
223            osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f));
224            osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f));
225
226            osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f));
227            osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real()));
228        }
229
230        // do last point by hand to ensure no round off errors.
231
232        osg::Vec3 normal(0.0f, radius, -height);
233        normal.normalize();
234
235        osg_normals->push_back(normal);
236        osg_normals->push_back(normal);
237
238        osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f));
239        osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f));
240
241        osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f));
242        osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
243
244        side->setCount(osg_vertices->size());
245        osg_geom->addPrimitiveSet(side.get());
246    }
247
248    if (bottom)
249    {
250        osg::ref_ptr<osg::DrawArrays> bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN);
251
252        size_t first = osg_vertices->size();
253        bottom->setFirst(first);
254
255        float theta = 0.0f;
256
257        for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta)
258        {
259            std::complex<float> n = -std::polar(1.0f, theta);
260            std::complex<float> e = n * radius;
261
262            osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
263            osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real()));
264            osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real()));
265        }
266
267        // do last point by hand to ensure no round off errors.
268
269        osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
270        osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f));
271        osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
272
273        bottom->setCount(osg_vertices->size() - first);
274        osg_geom->addPrimitiveSet(bottom.get());
275    }
276
277    osg_geom->setVertexArray(osg_vertices.get());
278    osg_geom->setTexCoordArray(0, osg_texcoords.get());
279    osg_geom->setNormalArray(osg_normals.get());
280    osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
281
282    osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
283
284    m_coneLibrary[key] = osg_geom;
285
286    return osg_geom.get();
287}
288
289osg::ref_ptr<osg::Geometry> ReaderWriterVRML2::convertVRML97Cylinder(openvrml::node* vrml_cylinder) const
290{
291    float height = static_cast<const openvrml::sffloat*>(vrml_cylinder->field("height").get())->value();
292    float radius = static_cast<const openvrml::sffloat*>(vrml_cylinder->field("radius").get())->value();
293    bool bottom = static_cast<const openvrml::sfbool*>(vrml_cylinder->field("bottom").get())->value();
294    bool side = static_cast<const openvrml::sfbool*>(vrml_cylinder->field("side").get())->value();
295    bool top = static_cast<const openvrml::sfbool*>(vrml_cylinder->field("top").get())->value();
296
297    QuadricKey key(height, radius, bottom, side, top);
298
299    CylinderLibrary::const_iterator it = m_cylinderLibrary.find(key);
300    if (it != m_cylinderLibrary.end())
301    {
302        return (*it).second.get();
303    }
304
305    osg::ref_ptr<osg::Geometry> osg_geom = new osg::Geometry();
306    osg::ref_ptr<osg::Vec3Array> osg_vertices = new osg::Vec3Array();
307    osg::ref_ptr<osg::Vec2Array> osg_texcoords = new osg::Vec2Array();
308    osg::ref_ptr<osg::Vec3Array> osg_normals = new osg::Vec3Array();
309
310    unsigned int numSegments = 40;
311
312    const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments);
313
314    float topY = height * 0.5f;
315    float bottomY = height * -0.5f;
316
317    if (side)
318    {
319        osg::ref_ptr<osg::DrawArrays> side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP);
320
321        const float texCoordDelta = 1.0f / float(numSegments);
322        float theta = 0.0f;
323        float texCoord = 0.0f;
324
325        for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta)
326        {
327            std::complex<float> n = -std::polar(1.0f, theta);
328            std::complex<float> e = n * radius;
329
330            osg::Vec3 normal(n.imag(), 0.0f, n.real());
331
332            osg_normals->push_back(normal);
333            osg_normals->push_back(normal);
334
335            osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f));
336            osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f));
337
338            osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real()));
339            osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real()));
340        }
341
342        // do last point by hand to ensure no round off errors.
343
344        osg::Vec3 normal(0.0f, 0.0f, -1.0f);
345        osg_normals->push_back(normal);
346        osg_normals->push_back(normal);
347
348        osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f));
349        osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f));
350
351        osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius));
352        osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
353
354        side->setCount(osg_vertices->size());
355        osg_geom->addPrimitiveSet(side.get());
356    }
357
358    if (bottom)
359    {
360        osg::ref_ptr<osg::DrawArrays> bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN);
361
362        size_t first = osg_vertices->size();
363        bottom->setFirst(first);
364
365        float theta = 0.0f;
366
367        for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta)
368        {
369            std::complex<float> n = -std::polar(1.0f, theta);
370            std::complex<float> e = n * radius;
371
372            osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
373            osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real()));
374            osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real()));
375        }
376
377        // do last point by hand to ensure no round off errors.
378
379        osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
380        osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f));
381        osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius));
382
383        bottom->setCount(osg_vertices->size() - first);
384        osg_geom->addPrimitiveSet(bottom.get());
385    }
386
387    if (top)
388    {
389        osg::ref_ptr<osg::DrawArrays> top = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN);
390
391        size_t first = osg_vertices->size();
392        top->setFirst(first);
393
394        float theta = 0.0f;
395
396        for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta)
397        {
398            std::complex<float> n = -std::polar(1.0f, theta);
399            std::complex<float> e = n * radius;
400
401            osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
402            osg_texcoords->push_back(osg::Vec2(0.5f + 0.5f * n.imag(), 0.5f - 0.5f * n.real()));
403            osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real()));
404        }
405
406        // do last point by hand to ensure no round off errors.
407
408        osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
409        osg_texcoords->push_back(osg::Vec2(0.5f, 1.0f));
410        osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius));
411
412        top->setCount(osg_vertices->size() - first);
413        osg_geom->addPrimitiveSet(top.get());
414    }
415
416    osg_geom->setVertexArray(osg_vertices.get());
417    osg_geom->setTexCoordArray(0, osg_texcoords.get());
418    osg_geom->setNormalArray(osg_normals.get());
419    osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
420
421    osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
422
423    m_cylinderLibrary[key] = osg_geom;
424
425    return osg_geom.get();
426}
Note: See TracBrowser for help on using the browser.