From bc79df7cd8c2e87a97514cae300c6cb11d975a43 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 18 Jun 2008 10:51:02 +0000 Subject: [PATCH] From Gino van den Bergen, "Added support for vrml primitive caching" --- src/osgPlugins/vrml/IndexedFaceSet.cpp | 2 +- src/osgPlugins/vrml/Primitives.cpp | 77 +++++++++++++++++------ src/osgPlugins/vrml/ReaderWriterVRML2.cpp | 2 +- src/osgPlugins/vrml/ReaderWriterVRML2.h | 48 ++++++++++++-- 4 files changed, 101 insertions(+), 28 deletions(-) diff --git a/src/osgPlugins/vrml/IndexedFaceSet.cpp b/src/osgPlugins/vrml/IndexedFaceSet.cpp index 3ae4c5f04..66032b829 100644 --- a/src/osgPlugins/vrml/IndexedFaceSet.cpp +++ b/src/osgPlugins/vrml/IndexedFaceSet.cpp @@ -18,7 +18,7 @@ #include -osg::ref_ptr ReaderWriterVRML2::convertVRML97IndexedFaceSet(openvrml::vrml97_node::indexed_face_set_node *vrml_ifs) +osg::ref_ptr ReaderWriterVRML2::convertVRML97IndexedFaceSet(openvrml::vrml97_node::indexed_face_set_node *vrml_ifs) const { osg::ref_ptr osg_geom = new osg::Geometry(); diff --git a/src/osgPlugins/vrml/Primitives.cpp b/src/osgPlugins/vrml/Primitives.cpp index 76c86c7a8..d29160d76 100644 --- a/src/osgPlugins/vrml/Primitives.cpp +++ b/src/osgPlugins/vrml/Primitives.cpp @@ -18,14 +18,19 @@ #include -osg::ref_ptr ReaderWriterVRML2::convertVRML97Box(openvrml::vrml97_node::box_node* vrml_box) +osg::ref_ptr ReaderWriterVRML2::convertVRML97Box(openvrml::vrml97_node::box_node* vrml_box) const { - 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); - + + BoxLibrary::const_iterator it = m_boxLibrary.find(halfSize); + if (it != m_boxLibrary.end()) + { + return (*it).second.get(); + } + + osg::ref_ptr osg_geom = new osg::Geometry(); osg::ref_ptr osg_vertices = new osg::Vec3Array(); osg::ref_ptr osg_texcoords = new osg::Vec2Array(); osg::ref_ptr osg_normals = new osg::Vec3Array(); @@ -88,16 +93,23 @@ osg::ref_ptr ReaderWriterVRML2::convertVRML97Box(openvrml::vrml97 osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + m_boxLibrary[halfSize] = osg_geom; + return osg_geom.get(); } -osg::ref_ptr ReaderWriterVRML2::convertVRML97Sphere(openvrml::vrml97_node::sphere_node* vrml_sphere) +osg::ref_ptr ReaderWriterVRML2::convertVRML97Sphere(openvrml::vrml97_node::sphere_node* vrml_sphere) const { - osg::ref_ptr osg_geom = new osg::Geometry(); - float radius = static_cast(vrml_sphere->field("radius")).value; - + + SphereLibrary::const_iterator it = m_sphereLibrary.find(radius); + if (it != m_sphereLibrary.end()) + { + return (*it).second.get(); + } + + osg::ref_ptr osg_geom = new osg::Geometry(); osg::ref_ptr osg_vertices = new osg::Vec3Array(); osg::ref_ptr osg_texcoords = new osg::Vec2Array(); osg::ref_ptr osg_normals = new osg::Vec3Array(); @@ -160,17 +172,28 @@ osg::ref_ptr ReaderWriterVRML2::convertVRML97Sphere(openvrml::vrm osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + m_sphereLibrary[radius] = osg_geom; + return osg_geom.get(); } -osg::ref_ptr ReaderWriterVRML2::convertVRML97Cone(openvrml::vrml97_node::cone_node* vrml_cone) +osg::ref_ptr ReaderWriterVRML2::convertVRML97Cone(openvrml::vrml97_node::cone_node* vrml_cone) const { - 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; + bool bottom = static_cast(vrml_cone->field("bottom")).value; + bool side = static_cast(vrml_cone->field("side")).value; + + QuadricKey key(height, radius, bottom, side, false); + + ConeLibrary::const_iterator it = m_coneLibrary.find(key); + if (it != m_coneLibrary.end()) + { + return (*it).second.get(); + } + osg::ref_ptr osg_geom = new osg::Geometry(); osg::ref_ptr osg_vertices = new osg::Vec3Array(); osg::ref_ptr osg_texcoords = new osg::Vec2Array(); osg::ref_ptr osg_normals = new osg::Vec3Array(); @@ -182,7 +205,7 @@ osg::ref_ptr ReaderWriterVRML2::convertVRML97Cone(openvrml::vrml9 float topY = height * 0.5f; float bottomY = height * -0.5f; - if (static_cast(vrml_cone->field("side")).value) + if (side) { osg::ref_ptr side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP); @@ -226,7 +249,7 @@ osg::ref_ptr ReaderWriterVRML2::convertVRML97Cone(openvrml::vrml9 osg_geom->addPrimitiveSet(side.get()); } - if (static_cast(vrml_cone->field("bottom")).value) + if (bottom) { osg::ref_ptr bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN); @@ -263,16 +286,28 @@ osg::ref_ptr ReaderWriterVRML2::convertVRML97Cone(openvrml::vrml9 osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + m_coneLibrary[key] = osg_geom; + return osg_geom.get(); } -osg::ref_ptr ReaderWriterVRML2::convertVRML97Cylinder(openvrml::vrml97_node::cylinder_node* vrml_cylinder) +osg::ref_ptr ReaderWriterVRML2::convertVRML97Cylinder(openvrml::vrml97_node::cylinder_node* vrml_cylinder) const { - 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; - + bool bottom = static_cast(vrml_cylinder->field("bottom")).value; + bool side = static_cast(vrml_cylinder->field("side")).value; + bool top = static_cast(vrml_cylinder->field("top")).value; + + QuadricKey key(height, radius, bottom, side, top); + + CylinderLibrary::const_iterator it = m_cylinderLibrary.find(key); + if (it != m_cylinderLibrary.end()) + { + return (*it).second.get(); + } + + osg::ref_ptr osg_geom = new osg::Geometry(); osg::ref_ptr osg_vertices = new osg::Vec3Array(); osg::ref_ptr osg_texcoords = new osg::Vec2Array(); osg::ref_ptr osg_normals = new osg::Vec3Array(); @@ -285,7 +320,7 @@ osg::ref_ptr ReaderWriterVRML2::convertVRML97Cylinder(openvrml::v float topY = height * 0.5f; float bottomY = height * -0.5f; - if (static_cast(vrml_cylinder->field("side")).value) + if (side) { osg::ref_ptr side = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP); @@ -326,7 +361,7 @@ osg::ref_ptr ReaderWriterVRML2::convertVRML97Cylinder(openvrml::v osg_geom->addPrimitiveSet(side.get()); } - if (static_cast(vrml_cylinder->field("bottom")).value) + if (bottom) { osg::ref_ptr bottom = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN); @@ -355,7 +390,7 @@ osg::ref_ptr ReaderWriterVRML2::convertVRML97Cylinder(openvrml::v osg_geom->addPrimitiveSet(bottom.get()); } - if (static_cast(vrml_cylinder->field("top")).value) + if (top) { osg::ref_ptr top = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN); @@ -391,5 +426,7 @@ osg::ref_ptr ReaderWriterVRML2::convertVRML97Cylinder(openvrml::v osg_geom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + m_cylinderLibrary[key] = osg_geom; + return osg_geom.get(); } diff --git a/src/osgPlugins/vrml/ReaderWriterVRML2.cpp b/src/osgPlugins/vrml/ReaderWriterVRML2.cpp index 03066922b..61bce3859 100644 --- a/src/osgPlugins/vrml/ReaderWriterVRML2.cpp +++ b/src/osgPlugins/vrml/ReaderWriterVRML2.cpp @@ -110,7 +110,7 @@ osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNode(const std::string &f } } -osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) +osg::ref_ptr ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const { std::string name = obj->id(); static int osgLightNum = 0; //light diff --git a/src/osgPlugins/vrml/ReaderWriterVRML2.h b/src/osgPlugins/vrml/ReaderWriterVRML2.h index 844eff71b..4c6759256 100644 --- a/src/osgPlugins/vrml/ReaderWriterVRML2.h +++ b/src/osgPlugins/vrml/ReaderWriterVRML2.h @@ -15,6 +15,7 @@ */ #include +#include #include #include @@ -38,6 +39,31 @@ namespace openvrml } } +class QuadricKey +{ +public: + QuadricKey(float height, float radius, unsigned bottom, unsigned side, unsigned top) + : m_height(height) + , m_radius(radius) + , m_flags(bottom | (side << 1) | (top << 2)) + {} + + bool operator<(const QuadricKey& rhs) const + { + return m_height < rhs.m_height || + (m_height == rhs.m_height && (m_radius < rhs.m_radius || + (m_radius == rhs.m_radius && m_flags < rhs.m_flags))); + } + +private: + float m_height; + float m_radius; + unsigned m_flags; +}; + + + + /** * OpenSceneGraph plugin wrapper/converter. */ @@ -61,11 +87,21 @@ public: virtual ReadResult readNode(const std::string&, const osgDB::ReaderWriter::Options *options = NULL) const; private: - static osg::ref_ptr convertFromVRML(openvrml::node *obj); + typedef std::map > SphereLibrary; + typedef std::map > BoxLibrary; + typedef std::map > ConeLibrary; + typedef std::map > CylinderLibrary; - 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); + osg::ref_ptr convertFromVRML(openvrml::node *obj) const; + + osg::ref_ptr convertVRML97IndexedFaceSet(openvrml::vrml97_node::indexed_face_set_node *vrml_ifs) const; + osg::ref_ptr convertVRML97Box(openvrml::vrml97_node::box_node* vrml_box) const; + osg::ref_ptr convertVRML97Sphere(openvrml::vrml97_node::sphere_node* vrml_sphere) const; + osg::ref_ptr convertVRML97Cone(openvrml::vrml97_node::cone_node* vrml_cone) const; + osg::ref_ptr convertVRML97Cylinder(openvrml::vrml97_node::cylinder_node* vrml_cylinder) const; + + mutable BoxLibrary m_boxLibrary; + mutable SphereLibrary m_sphereLibrary; + mutable ConeLibrary m_coneLibrary; + mutable CylinderLibrary m_cylinderLibrary; };