From 21f65054a0bd2bb51bd5b25603848313f47eca0d Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 13 Aug 2007 10:27:35 +0000 Subject: [PATCH] From Jan Ciger, "I am attaching an improved version of the OpenVRML plugin. It still uses OpenVRML 0.14.3 and is without the Boost dependency. The changes: - - Fixed loading of textures and normals when no corresponding indices are specified. It uses vertex indices now, compliant with the VRML spec. - - Added colour per vertex support. - - Added group node support. - - Changed the code to use osg::ref_ptr instead of naked pointers to avoid memory leaks. - - Fixed breakage for loading files specified by relative path." --- src/osgPlugins/vrml/ReaderWriterVRML2.cpp | 199 ++++++++++++++++------ src/osgWrappers/osgSim/OverlayNode.cpp | 9 + 2 files changed, 155 insertions(+), 53 deletions(-) diff --git a/src/osgPlugins/vrml/ReaderWriterVRML2.cpp b/src/osgPlugins/vrml/ReaderWriterVRML2.cpp index 465cda6d0..a968fd559 100644 --- a/src/osgPlugins/vrml/ReaderWriterVRML2.cpp +++ b/src/osgPlugins/vrml/ReaderWriterVRML2.cpp @@ -65,7 +65,7 @@ class ReaderWriterVRML2 : public osgDB::ReaderWriter virtual ReadResult readNode(const std::string&, const osgDB::ReaderWriter::Options *options = NULL) const; private: - osg::Node* convertFromVRML(openvrml::node *obj) const; + osg::ref_ptr convertFromVRML(openvrml::node *obj) const; }; // Register with Registry to instantiate the above reader/writer. @@ -78,7 +78,12 @@ osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNode(const std::string &f // convert possible Windows backslashes to Unix slashes // OpenVRML doesn't like backslashes, even on Windows - fileName = "file:///" + osgDB::convertFileNameToUnixStyle(fileName); + std::string unixFileName = osgDB::convertFileNameToUnixStyle(fileName); + + if(unixFileName[0] == '/') // absolute path + fileName = "file://" + unixFileName; + else // relative path + fileName = unixFileName; std::fstream null; openvrml::browser *browser = new openvrml::browser(null, null); @@ -95,34 +100,33 @@ osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNode(const std::string &f return ReadResult::FILE_NOT_HANDLED; } else { - osg::MatrixTransform *osg_root = new osg::MatrixTransform(osg::Matrix(1, 0, 0, 0, + osg::ref_ptr osg_root = new osg::MatrixTransform(osg::Matrix(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1)); for (unsigned i = 0; i < mfn.size(); i++) { openvrml::node *vrml_node = mfn[i].get(); - osg_root->addChild(convertFromVRML(vrml_node)); + osg_root->addChild(convertFromVRML(vrml_node).get()); } - return osg_root; + return osg_root.get(); } } -osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const +osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const { std::string name = obj->id(); static int osgLightNum = 0; //light - //std::cout << obj->type.id << " Node " << " ["<< name <<']' << std::endl; + // std::cout << obj->type.id << " Node " << " ["<< name <<']' << std::endl; - if (obj->type.id == "Transform") // Handle transforms + if (obj->type.id == "Group") // Group node { - openvrml::vrml97_node::transform_node *vrml_transform; - vrml_transform = dynamic_cast(obj); + openvrml::vrml97_node::group_node *vrml_group; + vrml_group = dynamic_cast(obj); - openvrml::mat4f vrml_m = vrml_transform->transform(); - osg::MatrixTransform *osg_m = new osg::MatrixTransform(osg::Matrix(vrml_m[0][0], vrml_m[0][1], vrml_m[0][2], vrml_m[0][3], vrml_m[1][0], vrml_m[1][1], vrml_m[1][2], vrml_m[1][3], vrml_m[2][0], vrml_m[2][1], vrml_m[2][2], vrml_m[2][3], vrml_m[3][0], vrml_m[3][1], vrml_m[3][2], vrml_m[3][3])); + osg::ref_ptr osg_group = new osg::Group; try { @@ -132,7 +136,7 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const const openvrml::mfnode &mfn = dynamic_cast(fv); for (unsigned i = 0; i < mfn.value.size(); i++) { openvrml::node *node = mfn.value[i].get(); - osg_m->addChild(convertFromVRML(node)); + osg_group->addChild(convertFromVRML(node).get()); } } } catch (openvrml::unsupported_interface &e) @@ -140,13 +144,44 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const // no children } - return osg_m; + return osg_group.get(); + + } else if (obj->type.id == "Transform") // Handle transforms + { + openvrml::vrml97_node::transform_node *vrml_transform; + vrml_transform = dynamic_cast(obj); + + openvrml::mat4f vrml_m = vrml_transform->transform(); + osg::ref_ptr osg_m = new osg::MatrixTransform(osg::Matrix(vrml_m[0][0], vrml_m[0][1], vrml_m[0][2], vrml_m[0][3], vrml_m[1][0], vrml_m[1][1], vrml_m[1][2], vrml_m[1][3], vrml_m[2][0], vrml_m[2][1], vrml_m[2][2], vrml_m[2][3], vrml_m[3][0], vrml_m[3][1], vrml_m[3][2], vrml_m[3][3])); + + try + { + const openvrml::field_value &fv = obj->field("children"); + + if ( fv.type() == openvrml::field_value::mfnode_id ) { + const openvrml::mfnode &mfn = dynamic_cast(fv); + for (unsigned i = 0; i < mfn.value.size(); i++) { + openvrml::node *node = mfn.value[i].get(); + osg_m->addChild(convertFromVRML(node).get()); + } + } + } catch (openvrml::unsupported_interface &e) + { + // no children + } + + return osg_m.get(); } else if (obj->type.id == "Shape") // Handle Shape node { - osg::Geode *osg_geode = new osg::Geode(); - osg::Geometry *osg_geom = new osg::Geometry(); - osg_geode->addDrawable(osg_geom); + 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_geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON)); @@ -168,7 +203,7 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const dynamic_cast(sfn.value.get()); const std::vector &vrml_coord = vrml_coord_node->point(); - osg::Vec3Array *osg_vertices = new osg::Vec3Array(); + osg::ref_ptr osg_vertices = new osg::Vec3Array(); unsigned i; for (i = 0; i < vrml_coord.size(); i++) @@ -177,13 +212,13 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const osg_vertices->push_back(osg::Vec3(vec[0], vec[1], vec[2])); } - osg_geom->setVertexArray(osg_vertices); + 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::IntArray *osg_vert_index = new osg::IntArray(); + osg::ref_ptr osg_vert_index = new osg::IntArray(); int num_vert = 0; for (i = 0; i < vrml_coord_index.value.size(); i++) @@ -198,7 +233,7 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const } } - osg_geom->setVertexIndices(osg_vert_index); + osg_geom->setVertexIndices(osg_vert_index.get()); } { @@ -211,7 +246,7 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const 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::Vec2Array *osg_texcoords = new osg::Vec2Array(); + osg::ref_ptr osg_texcoords = new osg::Vec2Array(); unsigned i; for (i = 0; i < vrml_tex_coord.size(); i++) @@ -220,25 +255,28 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const osg_texcoords->push_back(osg::Vec2(vec[0], vec[1])); } - osg_geom->setTexCoordArray(0, osg_texcoords); + 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::IntArray *osg_tex_coord_index = new osg::IntArray(); + osg::ref_ptr osg_tex_coord_index = new osg::IntArray(); - for (i = 0; i < vrml_tex_coord_index.value.size(); i++) + if(vrml_tex_coord_index.value.size() > 0) { - int index = vrml_tex_coord_index.value[i]; - if (index != -1) { - osg_tex_coord_index->push_back(index); + 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); + 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) @@ -252,7 +290,7 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const { const std::vector &vrml_normal_coord = vrml_normal_node->vector(); - osg::Vec3Array *osg_normalcoords = new osg::Vec3Array(); + osg::ref_ptr osg_normalcoords = new osg::Vec3Array(); unsigned i; for (i = 0; i < vrml_normal_coord.size(); i++) @@ -260,28 +298,32 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const 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 texture indices + // get array of normal indices const openvrml::field_value &fv2 = vrml_ifs->field("normalIndex"); const openvrml::mfint32 &vrml_normal_index = dynamic_cast(fv2); - osg::IntArray *osg_normal_index = new osg::IntArray(); + osg::ref_ptr osg_normal_index = new osg::IntArray(); - for (i = 0; i < vrml_normal_index.value.size(); i++) + if(vrml_normal_index.value.size() > 0) { - int index = vrml_normal_index.value[i]; - if (index != -1) { - osg_normal_index->push_back(index); + 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); - osg_geom->setNormalArray(osg_normalcoords); - osg_geom->setNormalIndices(osg_normal_index); - if (vrml_norm_per_vertex.value) { osg_geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); @@ -291,6 +333,61 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const } } } + + // 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); + } + } + } } else { // other geometry types not handled yet } @@ -303,8 +400,6 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const if (fv.type() == openvrml::field_value::sfnode_id) { - osg::StateSet *osg_stateset = osg_geom->getOrCreateStateSet(); - const openvrml::sfnode &sfn = dynamic_cast(fv); // std::cerr << "FV->sfnode OK" << std::endl << std::flush; @@ -320,7 +415,6 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const // std::cerr << "sfnode->Material OK" << std::endl << std::flush; if (vrml_material != NULL) { - osg::Material *osg_mat = new osg::Material(); osg_mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(vrml_material->ambient_intensity(), vrml_material->ambient_intensity(), vrml_material->ambient_intensity(), @@ -345,7 +439,7 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const //osg_mat->setColorMode(osg::Material::OFF); - osg_stateset->setAttributeAndModes(osg_mat); + osg_stateset->setAttributeAndModes(osg_mat.get()); osg_stateset->setMode(GL_BLEND, osg::StateAttribute::ON); //bhbn } @@ -362,12 +456,11 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const const std::string &url = mfs.value[0]; - osg::Image* image = 0; - image = osgDB::readImageFile(url); + osg::ref_ptr image = osgDB::readImageFile(url); if (image != 0) { - osg::Texture2D *texture = new osg::Texture2D; - texture->setImage(image); + osg::ref_ptr texture = new osg::Texture2D; + texture->setImage(image.get()); // defaults texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); @@ -398,7 +491,7 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const // nothing specified } - osg_stateset->setTextureAttributeAndModes(0, texture); + osg_stateset->setTextureAttributeAndModes(0, texture.get()); //osg_stateset->setMode(GL_BLEND,osg::StateAttribute::ON); //bhbn } else { @@ -408,7 +501,7 @@ osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const } } - return osg_geode; + return osg_geode.get(); } else { return 0; } diff --git a/src/osgWrappers/osgSim/OverlayNode.cpp b/src/osgWrappers/osgSim/OverlayNode.cpp index a8770835c..d86478a38 100644 --- a/src/osgWrappers/osgSim/OverlayNode.cpp +++ b/src/osgWrappers/osgSim/OverlayNode.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -90,6 +91,11 @@ BEGIN_OBJECT_REFLECTOR(osgSim::OverlayNode) __OverlayTechnique__getOverlayTechnique, "", ""); + I_Method1(void, setRenderTargetImplementation, IN, osg::Camera::RenderTargetImplementation, impl, + Properties::NON_VIRTUAL, + __void__setRenderTargetImplementation__osg_Camera_RenderTargetImplementation, + "Set the implementation to be used when creating the overlay texture. ", + ""); I_Method1(void, setOverlaySubgraph, IN, osg::Node *, node, Properties::NON_VIRTUAL, __void__setOverlaySubgraph__osg_Node_P1, @@ -254,6 +260,9 @@ BEGIN_OBJECT_REFLECTOR(osgSim::OverlayNode) I_SimpleProperty(unsigned int, OverlayTextureUnit, __unsigned_int__getOverlayTextureUnit, __void__setOverlayTextureUnit__unsigned_int); + I_SimpleProperty(osg::Camera::RenderTargetImplementation, RenderTargetImplementation, + 0, + __void__setRenderTargetImplementation__osg_Camera_RenderTargetImplementation); I_SimpleProperty(GLenum, TexEnvMode, __GLenum__getTexEnvMode, __void__setTexEnvMode__GLenum);