diff --git a/src/osgPlugins/vrml/CMakeLists.txt b/src/osgPlugins/vrml/CMakeLists.txt index 10c885545..a57ce6ca6 100644 --- a/src/osgPlugins/vrml/CMakeLists.txt +++ b/src/osgPlugins/vrml/CMakeLists.txt @@ -11,7 +11,15 @@ ELSE(WIN32) SET(TARGET_LIBRARIES_VARS OPENVRML_LIBRARY) ENDIF(WIN32) -SET(TARGET_SRC ReaderWriterVRML2.cpp ) +SET(TARGET_SRC + IndexedFaceSet.cpp + Primitives.cpp + ReaderWriterVRML2.cpp +) + +SET(TARGET_H + ReaderWriterVRML2.h +) #### end var setup ### SETUP_PLUGIN(vrml) diff --git a/src/osgPlugins/vrml/IndexedFaceSet.cpp b/src/osgPlugins/vrml/IndexedFaceSet.cpp new file mode 100644 index 000000000..3ae4c5f04 --- /dev/null +++ b/src/osgPlugins/vrml/IndexedFaceSet.cpp @@ -0,0 +1,329 @@ +// -*-c++-*- + +#include "ReaderWriterVRML2.h" + + +#if defined(_MSC_VER) +# pragma warning(disable: 4250) +# pragma warning(disable: 4290) +# pragma warning(disable: 4800) +#endif + +#include +#include +#include +#include +#include + +#include + + +osg::ref_ptr ReaderWriterVRML2::convertVRML97IndexedFaceSet(openvrml::vrml97_node::indexed_face_set_node *vrml_ifs) +{ + osg::ref_ptr osg_geom = new osg::Geometry(); + + osg_geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON)); + osg::StateSet *osg_stateset = osg_geom->getOrCreateStateSet(); + + // get array of vertex coordinate_nodes + { + const openvrml::field_value& fv = vrml_ifs->field("coord"); + const openvrml::sfnode& sfn = dynamic_cast(fv); + openvrml::vrml97_node::coordinate_node* vrml_coord_node = dynamic_cast(sfn.value.get()); + + const std::vector& vrml_coord = vrml_coord_node->point(); + osg::ref_ptr osg_vertices = new osg::Vec3Array(); + + unsigned i; + for (i = 0; i < vrml_coord.size(); i++) + { + openvrml::vec3f vec = vrml_coord[i]; + osg_vertices->push_back(osg::Vec3(vec[0], vec[1], vec[2])); + } + + osg_geom->setVertexArray(osg_vertices.get()); + + // get array of vertex indices + const openvrml::field_value &fv2 = vrml_ifs->field("coordIndex"); + const openvrml::mfint32 &vrml_coord_index = dynamic_cast(fv2); + + osg::ref_ptr osg_vert_index = new osg::IntArray(); + + int num_vert = 0; + for (i = 0; i < vrml_coord_index.value.size(); i++) + { + int index = vrml_coord_index.value[i]; + if (index == -1) + { + static_cast(osg_geom->getPrimitiveSet(0))->push_back(num_vert); + num_vert = 0; + } + else + { + osg_vert_index->push_back(index); + ++num_vert; + } + } + if (num_vert) + { + //GvdB: Last coordIndex wasn't -1 + static_cast(osg_geom->getPrimitiveSet(0))->push_back(num_vert); + } + + osg_geom->setVertexIndices(osg_vert_index.get()); + } + + { + // get texture coordinate_nodes + const openvrml::field_value &fv = vrml_ifs->field("texCoord"); + const openvrml::sfnode &sfn = dynamic_cast(fv); + openvrml::vrml97_node::texture_coordinate_node *vrml_tex_coord_node = + dynamic_cast(sfn.value.get()); + + if (vrml_tex_coord_node != 0) // if no texture, node is NULL pointer + { + const std::vector &vrml_tex_coord = vrml_tex_coord_node->point(); + osg::ref_ptr osg_texcoords = new osg::Vec2Array(); + + unsigned i; + for (i = 0; i < vrml_tex_coord.size(); i++) + { + openvrml::vec2f vec = vrml_tex_coord[i]; + osg_texcoords->push_back(osg::Vec2(vec[0], vec[1])); + } + + osg_geom->setTexCoordArray(0, osg_texcoords.get()); + + // get array of texture indices + const openvrml::field_value &fv2 = vrml_ifs->field("texCoordIndex"); + const openvrml::mfint32 &vrml_tex_coord_index = dynamic_cast(fv2); + + osg::ref_ptr osg_tex_coord_index = new osg::IntArray(); + + if(vrml_tex_coord_index.value.size() > 0) + { + for (i = 0; i < vrml_tex_coord_index.value.size(); i++) + { + int index = vrml_tex_coord_index.value[i]; + if (index != -1) { + osg_tex_coord_index->push_back(index); + } + } + osg_geom->setTexCoordIndices(0, osg_tex_coord_index.get()); + } else + // no indices defined, use coordIndex + osg_geom->setTexCoordIndices(0, osg_geom->getVertexIndices()); + } + } + + // get array of normals per vertex (if specified) + { + const openvrml::field_value& fv = vrml_ifs->field("normal"); + const openvrml::sfnode& sfn = dynamic_cast(fv); + openvrml::vrml97_node::normal_node* vrml_normal_node = dynamic_cast(sfn.value.get()); + + if (vrml_normal_node != 0) // if no normals, node is NULL pointer + { + const std::vector& vrml_normal_coord = vrml_normal_node->vector(); + + osg::ref_ptr osg_normalcoords = new osg::Vec3Array(); + + unsigned i; + for (i = 0; i < vrml_normal_coord.size(); i++) + { + const openvrml::vec3f vec = vrml_normal_coord[i]; + osg_normalcoords->push_back(osg::Vec3(vec[0], vec[1], vec[2])); + } + osg_geom->setNormalArray(osg_normalcoords.get()); + + // get array of normal indices + const openvrml::field_value& fv2 = vrml_ifs->field("normalIndex"); + const openvrml::mfint32& vrml_normal_index = dynamic_cast(fv2); + + osg::ref_ptr osg_normal_index = new osg::IntArray(); + + if (vrml_normal_index.value.size() > 0) + { + for (i = 0; i < vrml_normal_index.value.size(); i++) + { + int index = vrml_normal_index.value[i]; + if (index != -1) + { + osg_normal_index->push_back(index); + } + } + osg_geom->setNormalIndices(osg_normal_index.get()); + } + else + // unspecified, use the coordIndex field + osg_geom->setNormalIndices(osg_geom->getVertexIndices()); + + // get normal binding + const openvrml::field_value &fv3 = vrml_ifs->field("normalPerVertex"); + const openvrml::sfbool &vrml_norm_per_vertex = dynamic_cast(fv3); + + if (vrml_norm_per_vertex.value) + { + osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + } else + { + osg_geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); + } + } + } + + // get array of colours per vertex (if specified) + { + const openvrml::field_value &fv = vrml_ifs->field("color"); + const openvrml::sfnode &sfn = dynamic_cast(fv); + openvrml::vrml97_node::color_node *vrml_color_node = + dynamic_cast(sfn.value.get()); + + if (vrml_color_node != 0) // if no colors, node is NULL pointer + { + const std::vector &vrml_colors = vrml_color_node->color(); + + osg::ref_ptr osg_colors = new osg::Vec3Array(); + + unsigned i; + for (i = 0; i < vrml_colors.size(); i++) + { + const openvrml::color color = vrml_colors[i]; + osg_colors->push_back(osg::Vec3(color.r(), color.g(), color.b())); + } + osg_geom->setColorArray(osg_colors.get()); + + // get array of color indices + const openvrml::field_value &fv2 = vrml_ifs->field("colorIndex"); + const openvrml::mfint32 &vrml_color_index = dynamic_cast(fv2); + + osg::ref_ptr osg_color_index = new osg::IntArray(); + + if(vrml_color_index.value.size() > 0) + { + for (i = 0; i < vrml_color_index.value.size(); i++) + { + int index = vrml_color_index.value[i]; + if (index != -1) { + osg_color_index->push_back(index); + } + } + osg_geom->setColorIndices(osg_color_index.get()); + } else + // unspecified, use coordIndices field + osg_geom->setColorIndices(osg_geom->getVertexIndices()); + + // get color binding + const openvrml::field_value &fv3 = vrml_ifs->field("colorPerVertex"); + const openvrml::sfbool &vrml_color_per_vertex = dynamic_cast(fv3); + + if (vrml_color_per_vertex.value) + { + osg_geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); + } else + { + osg_geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE); + } + } + } + + if (static_cast(vrml_ifs->field("solid")).value) + { + osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + } + + if (!osg_geom->getNormalArray()) + { +#if 0 + // GvdB: This is what I wanted to do, but got zero normals since the triangles were considered temporaries (?) + osgUtil::SmoothingVisitor().smooth(*osg_geom); +#else + // GvdB: So I ended up computing the smoothing normals myself. Also, I might add support for "creaseAngle" if a big need for it rises. + // However, for now I can perfectly live with the fact that all edges are smoothed despite the use of a crease angle. + osg::Vec3Array& coords = *static_cast(osg_geom->getVertexArray()); + assert(coords.size()); + + osg::Vec3Array* normals = new osg::Vec3Array(coords.size()); + + for (osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it) + { + (*it).set(0.0f, 0.0f, 0.0f); + } + + + osg::IntArray& indices = *static_cast(osg_geom->getVertexIndices()); + osg::DrawArrayLengths& lengths = *static_cast(osg_geom->getPrimitiveSet(0)); + int index = 0; + + for (osg::DrawArrayLengths::iterator it = lengths.begin(); it != lengths.end(); ++it) + { + assert(*it >= 3); + const osg::Vec3& v0 = coords[indices[index]]; + const osg::Vec3& v1 = coords[indices[index + 1]]; + const osg::Vec3& v2 = coords[indices[index + 2]]; + + osg::Vec3 normal = (v1 - v0) ^ (v2 - v0); + normal.normalize(); + + for (int i = 0; i != *it; ++i) + { + (*normals)[indices[index + i]] += normal; + } + + index += *it; + } + + assert(index == indices.size()); + + for(osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it) + { + (*it).normalize(); + } + + osg_geom->setNormalArray(normals); + osg_geom->setNormalIndices(osg_geom->getVertexIndices()); + osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + +#endif + } + + + osg::DrawArrayLengths& lengths = *static_cast(osg_geom->getPrimitiveSet(0)); + + osg::DrawArrayLengths::iterator it = lengths.begin(); + if (it != lengths.end()) + { + switch (*it) + { + case 3: + while (++it != lengths.end() && *it == 3) + ; + + if (it == lengths.end()) + { + // All polys are triangles + osg::ref_ptr mesh = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES); + mesh->setCount(lengths.size() * 3); + osg_geom->removePrimitiveSet(0); + osg_geom->addPrimitiveSet(mesh.get()); + } + break; + + case 4: + while (++it != lengths.end() && *it == 4) + ; + + if (it == lengths.end()) + { + // All polys are quads + osg::ref_ptr mesh = new osg::DrawArrays(osg::PrimitiveSet::QUADS); + mesh->setCount(lengths.size() * 4); + osg_geom->removePrimitiveSet(0); + osg_geom->addPrimitiveSet(mesh.get()); + } + + break; + } + } + return osg_geom.get(); +} diff --git a/src/osgPlugins/vrml/Primitives.cpp b/src/osgPlugins/vrml/Primitives.cpp new file mode 100644 index 000000000..76c86c7a8 --- /dev/null +++ b/src/osgPlugins/vrml/Primitives.cpp @@ -0,0 +1,395 @@ +// -*-c++-*- + +#include "ReaderWriterVRML2.h" + +#include + +#if defined(_MSC_VER) +# pragma warning(disable: 4250) +# pragma warning(disable: 4290) +# pragma warning(disable: 4800) +#endif + +#include +#include +#include +#include +#include + +#include + +osg::ref_ptr ReaderWriterVRML2::convertVRML97Box(openvrml::vrml97_node::box_node* vrml_box) +{ + osg::ref_ptr osg_geom = new osg::Geometry(); + + const openvrml::vec3f& size = static_cast(vrml_box->field("size")).value; + + osg::Vec3 halfSize(size[0] * 0.5f, size[1] * 0.5f, size[2] * 0.5f); + + osg::ref_ptr osg_vertices = new osg::Vec3Array(); + osg::ref_ptr osg_texcoords = new osg::Vec2Array(); + osg::ref_ptr osg_normals = new osg::Vec3Array(); + + osg::ref_ptr box = new osg::DrawArrays(osg::PrimitiveSet::QUADS); + + osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2])); + osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2])); + + osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2])); + osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2])); + osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2])); + + osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2])); + + osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2])); + osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2])); + osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2])); + osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2])); + + osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2])); + osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2])); + + osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2])); + osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2])); + osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2])); + + for (int i = 0; i != 6; ++i) + { + osg_texcoords->push_back(osg::Vec2(0.0f, 1.0f)); + osg_texcoords->push_back(osg::Vec2(0.0f, 0.0f)); + osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f)); + osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f)); + } + + osg_normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f)); + osg_normals->push_back(osg::Vec3(0.0f, 0.0f, -1.0f)); + osg_normals->push_back(osg::Vec3(1.0f, 0.0f, 0.0f)); + osg_normals->push_back(osg::Vec3(-1.0f, 0.0f, 0.0f)); + osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f)); + osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); + + box->setCount(osg_vertices->size()); + + osg_geom->addPrimitiveSet(box.get()); + + osg_geom->setVertexArray(osg_vertices.get()); + osg_geom->setTexCoordArray(0, osg_texcoords.get()); + osg_geom->setNormalArray(osg_normals.get()); + osg_geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); + + osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + + return osg_geom.get(); +} + + +osg::ref_ptr ReaderWriterVRML2::convertVRML97Sphere(openvrml::vrml97_node::sphere_node* vrml_sphere) +{ + osg::ref_ptr osg_geom = new osg::Geometry(); + + float radius = static_cast(vrml_sphere->field("radius")).value; + + osg::ref_ptr osg_vertices = new osg::Vec3Array(); + osg::ref_ptr osg_texcoords = new osg::Vec2Array(); + osg::ref_ptr osg_normals = new osg::Vec3Array(); + + unsigned int numSegments = 40; + unsigned int numRows = 20; + + const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments); + const float texCoordSDelta = 1.0f / float(numSegments); + const float phiDelta = float(osg::PI) / float(numRows); + const float texCoordTDelta = 1.0f / float(numRows); + + float phi = -0.5f * float(osg::PI); + float texCoordT = 0.0f; + + osg::ref_ptr sphere = new osg::DrawArrayLengths(osg::PrimitiveSet::QUAD_STRIP); + + for (unsigned int i = 0; i < numRows; ++i, phi += phiDelta, texCoordT += texCoordTDelta) + { + std::complex latBottom = std::polar(1.0f, phi); + std::complex latTop = std::polar(1.0f, phi + phiDelta); + std::complex eBottom = latBottom * radius; + std::complex eTop = latTop * radius; + + float theta = 0.0f; + float texCoordS = 0.0f; + + for (unsigned int j = 0; j < numSegments; ++j, theta += thetaDelta, texCoordS += texCoordSDelta) + { + std::complex n = -std::polar(1.0f, theta); + + osg_normals->push_back(osg::Vec3(latTop.real() * n.imag(), latTop.imag(), latTop.real() * n.real())); + osg_normals->push_back(osg::Vec3(latBottom.real() * n.imag(), latBottom.imag(), latBottom.real() * n.real())); + + osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT + texCoordTDelta)); + osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT)); + + osg_vertices->push_back(osg::Vec3(eTop.real() * n.imag(), eTop.imag(), eTop.real() * n.real())); + osg_vertices->push_back(osg::Vec3(eBottom.real() * n.imag(), eBottom.imag(), eBottom.real() * n.real())); + } + + osg_normals->push_back(osg::Vec3(0.0f, latTop.imag(), -latTop.real())); + osg_normals->push_back(osg::Vec3(0.0f, latBottom.imag(), -latBottom.real())); + + osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT + texCoordTDelta)); + osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT)); + + osg_vertices->push_back(osg::Vec3(0.0f, eTop.imag(), -eTop.real())); + osg_vertices->push_back(osg::Vec3(0.0f, eBottom.imag(), -eBottom.real())); + + sphere->push_back(numSegments * 2 + 2); + } + + osg_geom->addPrimitiveSet(sphere.get()); + + osg_geom->setVertexArray(osg_vertices.get()); + osg_geom->setTexCoordArray(0, osg_texcoords.get()); + osg_geom->setNormalArray(osg_normals.get()); + osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + + osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + + return osg_geom.get(); +} + + +osg::ref_ptr ReaderWriterVRML2::convertVRML97Cone(openvrml::vrml97_node::cone_node* vrml_cone) +{ + osg::ref_ptr osg_geom = new osg::Geometry(); + + float height = static_cast(vrml_cone->field("height")).value; + float radius = static_cast(vrml_cone->field("bottomRadius")).value; + + osg::ref_ptr osg_vertices = new osg::Vec3Array(); + osg::ref_ptr osg_texcoords = new osg::Vec2Array(); + osg::ref_ptr osg_normals = new osg::Vec3Array(); + + unsigned int numSegments = 40; + + const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments); + + float topY = height * 0.5f; + float bottomY = height * -0.5f; + + if (static_cast(vrml_cone->field("side")).value) + { + osg::ref_ptr side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP); + + const float texCoordDelta = 1.0f / float(numSegments); + float theta = 0.0f; + float texCoord = 0.0f; + + for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta) + { + std::complex n = -std::polar(1.0f, theta); + std::complex e = n * radius; + + osg::Vec3 normal(n.imag() * height, radius, n.real() * height); + normal.normalize(); + + osg_normals->push_back(normal); + osg_normals->push_back(normal); + + osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f)); + osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f)); + + osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f)); + osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real())); + } + + // do last point by hand to ensure no round off errors. + + osg::Vec3 normal(0.0f, radius, -height); + normal.normalize(); + + osg_normals->push_back(normal); + osg_normals->push_back(normal); + + osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f)); + osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f)); + + osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f)); + osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius)); + + side->setCount(osg_vertices->size()); + osg_geom->addPrimitiveSet(side.get()); + } + + if (static_cast(vrml_cone->field("bottom")).value) + { + osg::ref_ptr bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN); + + + size_t first = osg_vertices->size(); + bottom->setFirst(first); + + float theta = 0.0f; + + for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta) + { + std::complex n = -std::polar(1.0f, theta); + std::complex e = n * radius; + + osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); + osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real())); + osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real())); + } + + // do last point by hand to ensure no round off errors. + + osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); + osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f)); + osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius)); + + bottom->setCount(osg_vertices->size() - first); + osg_geom->addPrimitiveSet(bottom.get()); + } + + osg_geom->setVertexArray(osg_vertices.get()); + osg_geom->setTexCoordArray(0, osg_texcoords.get()); + osg_geom->setNormalArray(osg_normals.get()); + osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + + osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + + return osg_geom.get(); +} + +osg::ref_ptr ReaderWriterVRML2::convertVRML97Cylinder(openvrml::vrml97_node::cylinder_node* vrml_cylinder) +{ + osg::ref_ptr osg_geom = new osg::Geometry(); + + float height = static_cast(vrml_cylinder->field("height")).value; + float radius = static_cast(vrml_cylinder->field("radius")).value; + + osg::ref_ptr osg_vertices = new osg::Vec3Array(); + osg::ref_ptr osg_texcoords = new osg::Vec2Array(); + osg::ref_ptr osg_normals = new osg::Vec3Array(); + + unsigned int numSegments = 40; + + const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments); + + + float topY = height * 0.5f; + float bottomY = height * -0.5f; + + if (static_cast(vrml_cylinder->field("side")).value) + { + osg::ref_ptr side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP); + + const float texCoordDelta = 1.0f / float(numSegments); + float theta = 0.0f; + float texCoord = 0.0f; + + for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta) + { + std::complex n = -std::polar(1.0f, theta); + std::complex e = n * radius; + + osg::Vec3 normal(n.imag(), 0.0f, n.real()); + + osg_normals->push_back(normal); + osg_normals->push_back(normal); + + osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f)); + osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f)); + + osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real())); + osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real())); + } + + // do last point by hand to ensure no round off errors. + + osg::Vec3 normal(0.0f, 0.0f, -1.0f); + osg_normals->push_back(normal); + osg_normals->push_back(normal); + + osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f)); + osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f)); + + osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius)); + osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius)); + + side->setCount(osg_vertices->size()); + osg_geom->addPrimitiveSet(side.get()); + } + + if (static_cast(vrml_cylinder->field("bottom")).value) + { + osg::ref_ptr bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN); + + size_t first = osg_vertices->size(); + bottom->setFirst(first); + + float theta = 0.0f; + + for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta) + { + std::complex n = -std::polar(1.0f, theta); + std::complex e = n * radius; + + osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); + osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real())); + osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real())); + } + + // do last point by hand to ensure no round off errors. + + osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); + osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f)); + osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius)); + + bottom->setCount(osg_vertices->size() - first); + osg_geom->addPrimitiveSet(bottom.get()); + } + + if (static_cast(vrml_cylinder->field("top")).value) + { + osg::ref_ptr top = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN); + + size_t first = osg_vertices->size(); + top->setFirst(first); + + float theta = 0.0f; + + for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta) + { + std::complex n = -std::polar(1.0f, theta); + std::complex e = n * radius; + + osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f)); + osg_texcoords->push_back(osg::Vec2(0.5f + 0.5f * n.imag(), 0.5f - 0.5f * n.real())); + osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real())); + } + + // do last point by hand to ensure no round off errors. + + osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f)); + osg_texcoords->push_back(osg::Vec2(0.5f, 1.0f)); + osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius)); + + top->setCount(osg_vertices->size() - first); + osg_geom->addPrimitiveSet(top.get()); + } + + osg_geom->setVertexArray(osg_vertices.get()); + osg_geom->setTexCoordArray(0, osg_texcoords.get()); + osg_geom->setNormalArray(osg_normals.get()); + osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + + osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + + return osg_geom.get(); +} diff --git a/src/osgPlugins/vrml/ReaderWriterVRML2.cpp b/src/osgPlugins/vrml/ReaderWriterVRML2.cpp index 02ad6ab7b..03066922b 100644 --- a/src/osgPlugins/vrml/ReaderWriterVRML2.cpp +++ b/src/osgPlugins/vrml/ReaderWriterVRML2.cpp @@ -14,10 +14,16 @@ * */ +#include "ReaderWriterVRML2.h" + #include #include -#include -#include + +#if defined(_MSC_VER) +# pragma warning(disable: 4250) +# pragma warning(disable: 4290) +# pragma warning(disable: 4800) +#endif #include #include @@ -50,29 +56,6 @@ #include -/** - * OpenSceneGraph plugin wrapper/converter. - */ -class ReaderWriterVRML2 : public osgDB::ReaderWriter -{ - public: - ReaderWriterVRML2() { } - - virtual const char* className() - { - return "VRML2 Reader/Writer"; - } - - virtual bool acceptsExtension(const std::string& extension) - { - return osgDB::equalCaseInsensitive(extension, "wrl") ? true : false; - } - - virtual ReadResult readNode(const std::string&, const osgDB::ReaderWriter::Options *options = NULL) const; - private: - osg::ref_ptr convertFromVRML(openvrml::node *obj) const; -}; - // Register with Registry to instantiate the above reader/writer. REGISTER_OSGPLUGIN(vrml, ReaderWriterVRML2) @@ -95,6 +78,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNode(const std::string &f else // relative path fileName = unixFileName; + + std::fstream null; openvrml::browser *browser = new openvrml::browser(null, null); @@ -115,17 +100,17 @@ osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNode(const std::string &f 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1)); - + osgDB::getDataFilePathList().push_front(osgDB::getFilePath(unixFileName)); for (unsigned i = 0; i < mfn.size(); i++) { openvrml::node *vrml_node = mfn[i].get(); osg_root->addChild(convertFromVRML(vrml_node).get()); } - + osgDB::getDataFilePathList().pop_front(); return osg_root.get(); } } -osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const +osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) { std::string name = obj->id(); static int osgLightNum = 0; //light @@ -158,7 +143,8 @@ osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) return osg_group.get(); - } else if (obj->type.id == "Transform") // Handle transforms + } + else if (obj->type.id == "Transform") // Handle transforms { openvrml::vrml97_node::transform_node *vrml_transform; vrml_transform = dynamic_cast(obj); @@ -185,16 +171,10 @@ osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) return osg_m.get(); - } else if (obj->type.id == "Shape") // Handle Shape node + } + else if (obj->type.id == "Shape") // Handle Shape node { - osg::ref_ptr osg_geode = new osg::Geode(); - osg::ref_ptr osg_geom = new osg::Geometry(); - osg_geode->addDrawable(osg_geom.get()); - osg::StateSet *osg_stateset = osg_geom->getOrCreateStateSet(); - - osg::ref_ptr osg_mat = new osg::Material(); - osg_stateset->setAttributeAndModes(osg_mat.get()); - osg_mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); + osg::ref_ptr osg_geom; // parse the geometry { @@ -210,663 +190,23 @@ osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) if (openvrml::vrml97_node::indexed_face_set_node *vrml_ifs = dynamic_cast(vrml_geom)) { - osg_geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON)); - - // get array of vertex coordinate_nodes - { - const openvrml::field_value& fv = vrml_ifs->field("coord"); - const openvrml::sfnode& sfn = dynamic_cast(fv); - openvrml::vrml97_node::coordinate_node* vrml_coord_node = dynamic_cast(sfn.value.get()); - - const std::vector& vrml_coord = vrml_coord_node->point(); - osg::ref_ptr osg_vertices = new osg::Vec3Array(); - - unsigned i; - for (i = 0; i < vrml_coord.size(); i++) - { - openvrml::vec3f vec = vrml_coord[i]; - osg_vertices->push_back(osg::Vec3(vec[0], vec[1], vec[2])); - } - - osg_geom->setVertexArray(osg_vertices.get()); - - // get array of vertex indices - const openvrml::field_value &fv2 = vrml_ifs->field("coordIndex"); - const openvrml::mfint32 &vrml_coord_index = dynamic_cast(fv2); - - osg::ref_ptr osg_vert_index = new osg::IntArray(); - - int num_vert = 0; - for (i = 0; i < vrml_coord_index.value.size(); i++) - { - int index = vrml_coord_index.value[i]; - if (index == -1) - { - static_cast(osg_geom->getPrimitiveSet(0))->push_back(num_vert); - num_vert = 0; - } - else - { - osg_vert_index->push_back(index); - ++num_vert; - } - } - if (num_vert) - { - //GvdB: Last coordIndex wasn't -1 - static_cast(osg_geom->getPrimitiveSet(0))->push_back(num_vert); - } - - osg_geom->setVertexIndices(osg_vert_index.get()); - } - - { - // get texture coordinate_nodes - const openvrml::field_value &fv = vrml_ifs->field("texCoord"); - const openvrml::sfnode &sfn = dynamic_cast(fv); - openvrml::vrml97_node::texture_coordinate_node *vrml_tex_coord_node = - dynamic_cast(sfn.value.get()); - - if (vrml_tex_coord_node != 0) // if no texture, node is NULL pointer - { - const std::vector &vrml_tex_coord = vrml_tex_coord_node->point(); - osg::ref_ptr osg_texcoords = new osg::Vec2Array(); - - unsigned i; - for (i = 0; i < vrml_tex_coord.size(); i++) - { - openvrml::vec2f vec = vrml_tex_coord[i]; - osg_texcoords->push_back(osg::Vec2(vec[0], vec[1])); - } - - osg_geom->setTexCoordArray(0, osg_texcoords.get()); - - // get array of texture indices - const openvrml::field_value &fv2 = vrml_ifs->field("texCoordIndex"); - const openvrml::mfint32 &vrml_tex_coord_index = dynamic_cast(fv2); - - osg::ref_ptr osg_tex_coord_index = new osg::IntArray(); - - if(vrml_tex_coord_index.value.size() > 0) - { - for (i = 0; i < vrml_tex_coord_index.value.size(); i++) - { - int index = vrml_tex_coord_index.value[i]; - if (index != -1) { - osg_tex_coord_index->push_back(index); - } - } - osg_geom->setTexCoordIndices(0, osg_tex_coord_index.get()); - } else - // no indices defined, use coordIndex - osg_geom->setTexCoordIndices(0, osg_geom->getVertexIndices()); - } - } - - // get array of normals per vertex (if specified) - { - const openvrml::field_value& fv = vrml_ifs->field("normal"); - const openvrml::sfnode& sfn = dynamic_cast(fv); - openvrml::vrml97_node::normal_node* vrml_normal_node = dynamic_cast(sfn.value.get()); - - if (vrml_normal_node != 0) // if no normals, node is NULL pointer - { - const std::vector& vrml_normal_coord = vrml_normal_node->vector(); - - osg::ref_ptr osg_normalcoords = new osg::Vec3Array(); - - unsigned i; - for (i = 0; i < vrml_normal_coord.size(); i++) - { - const openvrml::vec3f vec = vrml_normal_coord[i]; - osg_normalcoords->push_back(osg::Vec3(vec[0], vec[1], vec[2])); - } - osg_geom->setNormalArray(osg_normalcoords.get()); - - // get array of normal indices - const openvrml::field_value& fv2 = vrml_ifs->field("normalIndex"); - const openvrml::mfint32& vrml_normal_index = dynamic_cast(fv2); - - osg::ref_ptr osg_normal_index = new osg::IntArray(); - - if (vrml_normal_index.value.size() > 0) - { - for (i = 0; i < vrml_normal_index.value.size(); i++) - { - int index = vrml_normal_index.value[i]; - if (index != -1) - { - osg_normal_index->push_back(index); - } - } - osg_geom->setNormalIndices(osg_normal_index.get()); - } - else - // unspecified, use the coordIndex field - osg_geom->setNormalIndices(osg_geom->getVertexIndices()); - - // get normal binding - const openvrml::field_value &fv3 = vrml_ifs->field("normalPerVertex"); - const openvrml::sfbool &vrml_norm_per_vertex = dynamic_cast(fv3); - - if (vrml_norm_per_vertex.value) - { - osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); - } else - { - osg_geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); - } - } - } - - // get array of colours per vertex (if specified) - { - const openvrml::field_value &fv = vrml_ifs->field("color"); - const openvrml::sfnode &sfn = dynamic_cast(fv); - openvrml::vrml97_node::color_node *vrml_color_node = - dynamic_cast(sfn.value.get()); - - if (vrml_color_node != 0) // if no colors, node is NULL pointer - { - const std::vector &vrml_colors = vrml_color_node->color(); - - osg::ref_ptr osg_colors = new osg::Vec3Array(); - - unsigned i; - for (i = 0; i < vrml_colors.size(); i++) - { - const openvrml::color color = vrml_colors[i]; - osg_colors->push_back(osg::Vec3(color.r(), color.g(), color.b())); - } - osg_geom->setColorArray(osg_colors.get()); - - // get array of color indices - const openvrml::field_value &fv2 = vrml_ifs->field("colorIndex"); - const openvrml::mfint32 &vrml_color_index = dynamic_cast(fv2); - - osg::ref_ptr osg_color_index = new osg::IntArray(); - - if(vrml_color_index.value.size() > 0) - { - for (i = 0; i < vrml_color_index.value.size(); i++) - { - int index = vrml_color_index.value[i]; - if (index != -1) { - osg_color_index->push_back(index); - } - } - osg_geom->setColorIndices(osg_color_index.get()); - } else - // unspecified, use coordIndices field - osg_geom->setColorIndices(osg_geom->getVertexIndices()); - - // get color binding - const openvrml::field_value &fv3 = vrml_ifs->field("colorPerVertex"); - const openvrml::sfbool &vrml_color_per_vertex = dynamic_cast(fv3); - - if (vrml_color_per_vertex.value) - { - osg_geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); - } else - { - osg_geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE); - } - } - } - - if (static_cast(vrml_ifs->field("solid")).value) - { - osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); - } - - if (!osg_geom->getNormalArray()) - { -#if 0 - // GvdB: This is what I wanted to do, but got zero normals since the triangles were considered temporaries (?) - osgUtil::SmoothingVisitor().smooth(*osg_geom); -#else - // GvdB: So I ended up computing the smoothing normals myself. Also, I might add support for "creaseAngle" if a big need for it rises. - // However, for now I can perfectly live with the fact that all edges are smoothed despite the use of a crease angle. - osg::Vec3Array& coords = *static_cast(osg_geom->getVertexArray()); - assert(coords.size()); - - osg::Vec3Array* normals = new osg::Vec3Array(coords.size()); - - for (osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it) - { - (*it).set(0.0f, 0.0f, 0.0f); - } - - - osg::IntArray& indices = *static_cast(osg_geom->getVertexIndices()); - osg::DrawArrayLengths& lengths = *static_cast(osg_geom->getPrimitiveSet(0)); - int index = 0; - - for (osg::DrawArrayLengths::iterator it = lengths.begin(); it != lengths.end(); ++it) - { - assert(*it >= 3); - const osg::Vec3& v0 = coords[indices[index]]; - const osg::Vec3& v1 = coords[indices[index + 1]]; - const osg::Vec3& v2 = coords[indices[index + 2]]; - - osg::Vec3 normal = (v1 - v0) ^ (v2 - v0); - normal.normalize(); - - for (int i = 0; i != *it; ++i) - { - (*normals)[indices[index + i]] += normal; - } - - index += *it; - } - - assert(index == indices.size()); - - for(osg::Vec3Array::iterator it = normals->begin(); it != normals->end(); ++it) - { - (*it).normalize(); - } - - osg_geom->setNormalArray(normals); - osg_geom->setNormalIndices(osg_geom->getVertexIndices()); - osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); - -#endif - } - - - osg::DrawArrayLengths& lengths = *static_cast(osg_geom->getPrimitiveSet(0)); - - osg::DrawArrayLengths::iterator it = lengths.begin(); - if (it != lengths.end()) - { - switch (*it) - { - case 3: - while (++it != lengths.end() && *it == 3) - ; - - if (it == lengths.end()) - { - // All polys are triangles - osg::ref_ptr mesh = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES); - mesh->setCount(lengths.size() * 3); - osg_geom->removePrimitiveSet(0); - osg_geom->addPrimitiveSet(mesh.get()); - } - break; - - case 4: - while (++it != lengths.end() && *it == 4) - ; - - if (it == lengths.end()) - { - // All polys are quads - osg::ref_ptr mesh = new osg::DrawArrays(osg::PrimitiveSet::QUADS); - mesh->setCount(lengths.size() * 4); - osg_geom->removePrimitiveSet(0); - osg_geom->addPrimitiveSet(mesh.get()); - } - - break; - } - } + osg_geom = convertVRML97IndexedFaceSet(vrml_ifs); } else if (openvrml::vrml97_node::box_node* vrml_box = dynamic_cast(vrml_geom)) { - const openvrml::vec3f& size = static_cast(vrml_box->field("size")).value; - - osg::Vec3 halfSize(size[0] * 0.5f, size[1] * 0.5f, size[2] * 0.5f); - - osg::ref_ptr osg_vertices = new osg::Vec3Array(); - osg::ref_ptr osg_texcoords = new osg::Vec2Array(); - osg::ref_ptr osg_normals = new osg::Vec3Array(); - - osg::ref_ptr box = new osg::DrawArrays(osg::PrimitiveSet::QUADS); - - osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2])); - osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2])); - - osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2])); - osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2])); - osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2])); - - osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2])); - - osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2])); - osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2])); - osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2])); - osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2])); - - osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], -halfSize[2])); - osg_vertices->push_back(osg::Vec3(-halfSize[0], halfSize[1], halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], halfSize[1], -halfSize[2])); - - osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], halfSize[2])); - osg_vertices->push_back(osg::Vec3(-halfSize[0], -halfSize[1], -halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], -halfSize[2])); - osg_vertices->push_back(osg::Vec3(halfSize[0], -halfSize[1], halfSize[2])); - - for (int i = 0; i != 6; ++i) - { - osg_texcoords->push_back(osg::Vec2(0.0f, 1.0f)); - osg_texcoords->push_back(osg::Vec2(0.0f, 0.0f)); - osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f)); - osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f)); - } - - osg_normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f)); - osg_normals->push_back(osg::Vec3(0.0f, 0.0f, -1.0f)); - osg_normals->push_back(osg::Vec3(1.0f, 0.0f, 0.0f)); - osg_normals->push_back(osg::Vec3(-1.0f, 0.0f, 0.0f)); - osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f)); - osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); - - box->setCount(osg_vertices->size()); - - osg_geom->addPrimitiveSet(box.get()); - - osg_geom->setVertexArray(osg_vertices.get()); - osg_geom->setTexCoordArray(0, osg_texcoords.get()); - osg_geom->setNormalArray(osg_normals.get()); - osg_geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); - - osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + osg_geom = convertVRML97Box(vrml_box); } else if (openvrml::vrml97_node::sphere_node* vrml_sphere = dynamic_cast(vrml_geom)) { - float radius = static_cast(vrml_sphere->field("radius")).value; - - osg::ref_ptr osg_vertices = new osg::Vec3Array(); - osg::ref_ptr osg_texcoords = new osg::Vec2Array(); - osg::ref_ptr osg_normals = new osg::Vec3Array(); - - unsigned int numSegments = 40; - unsigned int numRows = 20; - - const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments); - const float texCoordSDelta = 1.0f / float(numSegments); - const float phiDelta = float(osg::PI) / float(numRows); - const float texCoordTDelta = 1.0f / float(numRows); - - float phi = -0.5f * float(osg::PI); - float texCoordT = 0.0f; - - osg::ref_ptr sphere = new osg::DrawArrayLengths(osg::PrimitiveSet::QUAD_STRIP); - - for (unsigned int i = 0; i < numRows; ++i, phi += phiDelta, texCoordT += texCoordTDelta) - { - std::complex latBottom = std::polar(1.0f, phi); - std::complex latTop = std::polar(1.0f, phi + phiDelta); - std::complex eBottom = latBottom * radius; - std::complex eTop = latTop * radius; - - float theta = 0.0f; - float texCoordS = 0.0f; - - for (unsigned int j = 0; j < numSegments; ++j, theta += thetaDelta, texCoordS += texCoordSDelta) - { - std::complex n = -std::polar(1.0f, theta); - - osg_normals->push_back(osg::Vec3(latTop.real() * n.imag(), latTop.imag(), latTop.real() * n.real())); - osg_normals->push_back(osg::Vec3(latBottom.real() * n.imag(), latBottom.imag(), latBottom.real() * n.real())); - - osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT + texCoordTDelta)); - osg_texcoords->push_back(osg::Vec2(texCoordS, texCoordT)); - - osg_vertices->push_back(osg::Vec3(eTop.real() * n.imag(), eTop.imag(), eTop.real() * n.real())); - osg_vertices->push_back(osg::Vec3(eBottom.real() * n.imag(), eBottom.imag(), eBottom.real() * n.real())); - } - - osg_normals->push_back(osg::Vec3(0.0f, latTop.imag(), -latTop.real())); - osg_normals->push_back(osg::Vec3(0.0f, latBottom.imag(), -latBottom.real())); - - osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT + texCoordTDelta)); - osg_texcoords->push_back(osg::Vec2(1.0f, texCoordT)); - - osg_vertices->push_back(osg::Vec3(0.0f, eTop.imag(), -eTop.real())); - osg_vertices->push_back(osg::Vec3(0.0f, eBottom.imag(), -eBottom.real())); - - sphere->push_back(numSegments * 2 + 2); - } - - osg_geom->addPrimitiveSet(sphere.get()); - - osg_geom->setVertexArray(osg_vertices.get()); - osg_geom->setTexCoordArray(0, osg_texcoords.get()); - osg_geom->setNormalArray(osg_normals.get()); - osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); - - osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); - + osg_geom = convertVRML97Sphere(vrml_sphere); } else if (openvrml::vrml97_node::cone_node* vrml_cone = dynamic_cast(vrml_geom)) { - float height = static_cast(vrml_cone->field("height")).value; - float radius = static_cast(vrml_cone->field("bottomRadius")).value; - - osg::ref_ptr osg_vertices = new osg::Vec3Array(); - osg::ref_ptr osg_texcoords = new osg::Vec2Array(); - osg::ref_ptr osg_normals = new osg::Vec3Array(); - - unsigned int numSegments = 40; - - const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments); - - float topY = height * 0.5f; - float bottomY = height * -0.5f; - - if (static_cast(vrml_cone->field("side")).value) - { - osg::ref_ptr side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP); - - const float texCoordDelta = 1.0f / float(numSegments); - float theta = 0.0f; - float texCoord = 0.0f; - - for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta) - { - std::complex n = -std::polar(1.0f, theta); - std::complex e = n * radius; - - osg::Vec3 normal(n.imag() * height, radius, n.real() * height); - normal.normalize(); - - osg_normals->push_back(normal); - osg_normals->push_back(normal); - - osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f)); - osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f)); - - osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f)); - osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real())); - } - - // do last point by hand to ensure no round off errors. - - osg::Vec3 normal(0.0f, radius, -height); - normal.normalize(); - - osg_normals->push_back(normal); - osg_normals->push_back(normal); - - osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f)); - osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f)); - - osg_vertices->push_back(osg::Vec3(0.0f, topY, 0.0f)); - osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius)); - - side->setCount(osg_vertices->size()); - osg_geom->addPrimitiveSet(side.get()); - } - - if (static_cast(vrml_cone->field("bottom")).value) - { - osg::ref_ptr bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN); - - - size_t first = osg_vertices->size(); - bottom->setFirst(first); - - float theta = 0.0f; - - for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta) - { - std::complex n = -std::polar(1.0f, theta); - std::complex e = n * radius; - - osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); - osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real())); - osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real())); - } - - // do last point by hand to ensure no round off errors. - - osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); - osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f)); - osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius)); - - bottom->setCount(osg_vertices->size() - first); - osg_geom->addPrimitiveSet(bottom.get()); - } - - osg_geom->setVertexArray(osg_vertices.get()); - osg_geom->setTexCoordArray(0, osg_texcoords.get()); - osg_geom->setNormalArray(osg_normals.get()); - osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); - - osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + osg_geom = convertVRML97Cone(vrml_cone); } else if (openvrml::vrml97_node::cylinder_node* vrml_cylinder = dynamic_cast(vrml_geom)) { - float height = static_cast(vrml_cylinder->field("height")).value; - float radius = static_cast(vrml_cylinder->field("radius")).value; - - osg::ref_ptr osg_vertices = new osg::Vec3Array(); - osg::ref_ptr osg_texcoords = new osg::Vec2Array(); - osg::ref_ptr osg_normals = new osg::Vec3Array(); - - unsigned int numSegments = 40; - - const float thetaDelta = 2.0f * float(osg::PI) / float(numSegments); - - - float topY = height * 0.5f; - float bottomY = height * -0.5f; - - if (static_cast(vrml_cylinder->field("side")).value) - { - osg::ref_ptr side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP); - - const float texCoordDelta = 1.0f / float(numSegments); - float theta = 0.0f; - float texCoord = 0.0f; - - for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta, texCoord += texCoordDelta) - { - std::complex n = -std::polar(1.0f, theta); - std::complex e = n * radius; - - osg::Vec3 normal(n.imag(), 0.0f, n.real()); - - osg_normals->push_back(normal); - osg_normals->push_back(normal); - - osg_texcoords->push_back(osg::Vec2(texCoord, 1.0f)); - osg_texcoords->push_back(osg::Vec2(texCoord, 0.0f)); - - osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real())); - osg_vertices->push_back(osg::Vec3(e.imag(), bottomY, e.real())); - } - - // do last point by hand to ensure no round off errors. - - osg::Vec3 normal(0.0f, 0.0f, -1.0f); - osg_normals->push_back(normal); - osg_normals->push_back(normal); - - osg_texcoords->push_back(osg::Vec2(1.0f, 1.0f)); - osg_texcoords->push_back(osg::Vec2(1.0f, 0.0f)); - - osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius)); - osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius)); - - side->setCount(osg_vertices->size()); - osg_geom->addPrimitiveSet(side.get()); - } - - if (static_cast(vrml_cylinder->field("bottom")).value) - { - osg::ref_ptr bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN); - - size_t first = osg_vertices->size(); - bottom->setFirst(first); - - float theta = 0.0f; - - for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta) - { - std::complex n = -std::polar(1.0f, theta); - std::complex e = n * radius; - - osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); - osg_texcoords->push_back(osg::Vec2(0.5f - 0.5f * n.imag(), 0.5f + 0.5f * n.real())); - osg_vertices->push_back(osg::Vec3(-e.imag(), bottomY, e.real())); - } - - // do last point by hand to ensure no round off errors. - - osg_normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); - osg_texcoords->push_back(osg::Vec2(0.5f, 0.0f)); - osg_vertices->push_back(osg::Vec3(0.0f, bottomY, -radius)); - - bottom->setCount(osg_vertices->size() - first); - osg_geom->addPrimitiveSet(bottom.get()); - } - - if (static_cast(vrml_cylinder->field("top")).value) - { - osg::ref_ptr top = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN); - - size_t first = osg_vertices->size(); - top->setFirst(first); - - float theta = 0.0f; - - for (unsigned int i = 0; i < numSegments; ++i, theta += thetaDelta) - { - std::complex n = -std::polar(1.0f, theta); - std::complex e = n * radius; - - osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f)); - osg_texcoords->push_back(osg::Vec2(0.5f + 0.5f * n.imag(), 0.5f - 0.5f * n.real())); - osg_vertices->push_back(osg::Vec3(e.imag(), topY, e.real())); - } - - // do last point by hand to ensure no round off errors. - - osg_normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f)); - osg_texcoords->push_back(osg::Vec2(0.5f, 1.0f)); - osg_vertices->push_back(osg::Vec3(0.0f, topY, -radius)); - - top->setCount(osg_vertices->size() - first); - osg_geom->addPrimitiveSet(top.get()); - } - - osg_geom->setVertexArray(osg_vertices.get()); - osg_geom->setTexCoordArray(0, osg_texcoords.get()); - osg_geom->setNormalArray(osg_normals.get()); - osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); - - osg_stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + osg_geom = convertVRML97Cylinder(vrml_cylinder); } else { @@ -875,6 +215,15 @@ osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) } } + osg::ref_ptr osg_geode = new osg::Geode(); + osg_geode->addDrawable(osg_geom.get()); + osg::StateSet *osg_stateset = osg_geode->getOrCreateStateSet(); + + osg::ref_ptr osg_mat = new osg::Material(); + osg_stateset->setAttributeAndModes(osg_mat.get()); + osg_mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); + + // parse the appearance { const openvrml::field_value &fv = obj->field("appearance"); @@ -985,7 +334,8 @@ osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) osg_stateset->setTextureAttributeAndModes(0, texture.get()); //osg_stateset->setMode(GL_BLEND,osg::StateAttribute::ON); //bhbn - } else { + } + else { std::cerr << "texture file " << url << " not found !" << std::endl << std::flush; } } @@ -993,7 +343,9 @@ osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) } return osg_geode.get(); - } else { + } + else + { return 0; } diff --git a/src/osgPlugins/vrml/ReaderWriterVRML2.h b/src/osgPlugins/vrml/ReaderWriterVRML2.h new file mode 100644 index 000000000..844eff71b --- /dev/null +++ b/src/osgPlugins/vrml/ReaderWriterVRML2.h @@ -0,0 +1,71 @@ +// -*-c++-*- + +/* + * + * VRML2 file converter for OpenSceneGraph. + * + * authors : Jan Ciger (jan.ciger@gmail.com), + * Tolga Abaci (tolga.abaci@gmail.com), + * Bruno Herbelin (bruno.herbelin@gmail.com) + * + * (c) VRlab EPFL, Switzerland, 2004-2006 + * + * Gino van den Bergen, DTECTA (gino@dtecta.com) + * + */ + +#include + +#include +#include + +#include +#include +#include +#include + +namespace openvrml +{ + class node; + + namespace vrml97_node + { + class indexed_face_set_node; + class box_node; + class sphere_node; + class cone_node; + class cylinder_node; + } +} + +/** + * OpenSceneGraph plugin wrapper/converter. + */ +class ReaderWriterVRML2 + : public osgDB::ReaderWriter +{ +public: + ReaderWriterVRML2() + {} + + virtual const char* className() + { + return "VRML2 Reader/Writer"; + } + + virtual bool acceptsExtension(const std::string& extension) + { + return osgDB::equalCaseInsensitive(extension, "wrl"); + } + + virtual ReadResult readNode(const std::string&, const osgDB::ReaderWriter::Options *options = NULL) const; + +private: + static osg::ref_ptr convertFromVRML(openvrml::node *obj); + + static osg::ref_ptr convertVRML97IndexedFaceSet(openvrml::vrml97_node::indexed_face_set_node *vrml_ifs); + static osg::ref_ptr convertVRML97Box(openvrml::vrml97_node::box_node* vrml_box); + static osg::ref_ptr convertVRML97Sphere(openvrml::vrml97_node::sphere_node* vrml_sphere); + static osg::ref_ptr convertVRML97Cone(openvrml::vrml97_node::cone_node* vrml_cone); + static osg::ref_ptr convertVRML97Cylinder(openvrml::vrml97_node::cylinder_node* vrml_cylinder); +};