Hi Robert, the attached patch adds an additional null pointer check that showed up with one of the vrml files here.
Based on rev12507 Please apply, Thanks Mathias -- Dr. Mathias Fröhlich, science + computing ag, Software Solutions Hagellocher Weg 71-75, D-72070 Tuebingen, Germany Phone: +49 7071 9457-268, Fax: +49 7071 9457-511 -- Vorstand/Board of Management: Dr. Bernd Finkbeiner, Dr. Roland Niemeier, Dr. Arno Steitz, Dr. Ingrid Zech Vorsitzender des Aufsichtsrats/ Chairman of the Supervisory Board: Philippe Miltin Sitz/Registered Office: Tuebingen Registergericht/Registration Court: Stuttgart Registernummer/Commercial Register No.: HRB 382196
// -*-c++-*- /* * * VRML2 file converter for OpenSceneGraph. * * authors : * Johan Nouvel ([email protected]) for the writeNode function. * * Jan Ciger ([email protected]), * Tolga Abaci ([email protected]), * Bruno Herbelin ([email protected]) * * (c) VRlab EPFL, Switzerland, 2004-2006 * * Gino van den Bergen, DTECTA ([email protected]) * Xiangxian Wang ([email protected]) * */ #include "ReaderWriterVRML2.h" #include "ConvertToVRML.h" #include <iostream> #include <fstream> #include <boost/algorithm/string/predicate.hpp> #include <boost/utility.hpp> #if defined(_MSC_VER) # pragma warning(disable: 4250) # pragma warning(disable: 4290) # pragma warning(disable: 4800) #endif #include <openvrml/browser.h> #include <openvrml/node.h> #include <osg/TexEnv> #include <osg/CullFace> #include <osg/Geode> #include <osg/Geometry> #include <osg/Material> #include <osg/Image> #include <osg/Texture2D> #include <osg/Group> #include <osg/MatrixTransform> #include <osg/Light> #include <osg/LightSource> #include <osg/Depth> #include <osg/Notify> #include <osgDB/Registry> #include <osgDB/ReadFile> #include <osgDB/FileNameUtils> #include <osgDB/FileUtils> #include <assert.h> #include <map> // ------------------------------------------------------------------------------------- // OpenVRML helper class // ------------------------------------------------------------------------------------- class resource_fetcher: public openvrml::resource_fetcher { private: virtual std::auto_ptr<openvrml::resource_istream> do_get_resource(const std::string & uri) { using std::auto_ptr; using std::invalid_argument; using std::string; using openvrml::resource_istream; class file_resource_istream: public resource_istream { std::string url_; std::filebuf buf_; public: explicit file_resource_istream(const std::string & path) : resource_istream(&this->buf_) { // // Note that the failbit is set in the constructor if no data // can be read from the stream. This is important. If the // failbit is not set on such a stream, OpenVRML will attempt // to read data from a stream that cannot provide it. // if (!this->buf_.open(path.c_str(), ios_base::in | ios_base::binary)) { this->setstate(ios_base::badbit); } } void url(const std::string & str) throw (std::bad_alloc) { this->url_ = str; } private: virtual const std::string do_url() const throw () { return this->url_; } virtual const std::string do_type() const throw () { // // A real application should use OS facilities for this; // however, that is beyond the scope of this example (which // is intended to be portable and stupid). // using std::find; using std::string; using boost::algorithm::iequals; string media_type = "application/octet-stream"; const string::const_reverse_iterator dot_pos = find(this->url_.rbegin(), this->url_.rend(), '.'); if (dot_pos == this->url_.rend() || boost::next(dot_pos.base()) == this->url_.end()) { return media_type; } const string::const_iterator hash_pos = find(boost::next(dot_pos.base()), this->url_.end(), '#'); const string ext(dot_pos.base(), hash_pos); if (iequals(ext, "wrl") || iequals(ext, "vrml")) { media_type = "model/vrml"; } else if (iequals(ext, "png")) { media_type = "image/png"; } else if (iequals(ext, "jpg") || iequals(ext, "jpeg")) { media_type = "image/jpeg"; } return media_type; } virtual bool do_data_available() const throw () { return !!(*this); } }; const string scheme = uri.substr(0, uri.find_first_of(':')); if (scheme != "file") { throw invalid_argument('\"' + scheme + "\" URI scheme not " "supported"); } // // file:// // ^ // 01234567 // string path = uri.substr(uri.find_first_of('/', 7)); auto_ptr<resource_istream> in(new file_resource_istream(path)); static_cast<file_resource_istream *> (in.get())->url(uri); return in; } }; // ------------------------------------------------------------------------------------- // Register with Registry to instantiate the above reader/writer. REGISTER_OSGPLUGIN(vrml, ReaderWriterVRML2) osgDB::ReaderWriter::ReadResult ReaderWriterVRML2::readNode(const std::string& fname, const osgDB::Options* opt) const { std::string fileName = osgDB::findDataFile(fname, opt); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; // convert possible Windows backslashes to Unix slashes // OpenVRML doesn't like backslashes, even on Windows std::string unixFileName = osgDB::convertFileNameToUnixStyle(fileName); #ifdef WIN32 if(unixFileName[1] == ':') // absolute path fileName = "file:///" + unixFileName; #else if (unixFileName[0] == '/') // absolute path fileName = "file://" + unixFileName; #endif else // relative path fileName = unixFileName; std::fstream null; resource_fetcher fetcher; openvrml::browser *b = new openvrml::browser(fetcher, null, null); osgDB::ifstream vrml_stream(fileName.c_str()); try { const std::vector< boost::intrusive_ptr< openvrml::node > > & mfn = b->create_vrml_from_stream(vrml_stream); if(mfn.empty()) return ReadResult::FILE_NOT_HANDLED; else { osg::ref_ptr<osg::MatrixTransform> osg_root = new osg::MatrixTransform(osg::Matrix( 1, 0, 0, 0, 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)); } osgDB::getDataFilePathList().pop_front(); return osg_root.get(); } } catch (openvrml::invalid_vrml) { return ReadResult::FILE_NOT_HANDLED; } catch (std::invalid_argument) { return ReadResult::FILE_NOT_HANDLED; } } osgDB::ReaderWriter::WriteResult ReaderWriterVRML2::writeNode(const osg::Node& root,const std::string& filename, const osgDB::ReaderWriter::Options *options) const { std::string ext = osgDB::getLowerCaseFileExtension(filename); if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; osg::notify(osg::INFO) << "osgDB::ReaderWriterVRML::writeNode() Writing file " << filename << std::endl; return(convertToVRML(root,filename,options)); } osg::Node* ReaderWriterVRML2::convertFromVRML(openvrml::node *obj) const { //static int osgLightNum = 0; //light if (obj->type().id() == "Group") // Group node { openvrml::grouping_node *vrml_group; vrml_group = dynamic_cast<openvrml::grouping_node *>(obj); osg::ref_ptr<osg::Group> osg_group = new osg::Group; try { std::auto_ptr<openvrml::field_value> fv = obj->field("children"); if ( fv->type() == openvrml::field_value::mfnode_id ) { const openvrml::mfnode* mfn = dynamic_cast<const openvrml::mfnode *>(fv.get()); openvrml::mfnode::value_type node_ptr_vector = mfn->value(); openvrml::mfnode::value_type::iterator it_npv; for (it_npv = node_ptr_vector.begin(); it_npv != node_ptr_vector.end(); it_npv++) { openvrml::node *node = (*(it_npv)).get(); osg_group->addChild(convertFromVRML(node)); } } } catch (openvrml::unsupported_interface&) { // no children } return osg_group.release(); } else if (obj->type().id() == "Transform") // Handle transforms { openvrml::transform_node *vrml_transform; vrml_transform = dynamic_cast<openvrml::transform_node *>(obj); openvrml::mat4f vrml_m = vrml_transform->transform(); osg::ref_ptr<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])); try { std::auto_ptr<openvrml::field_value> fv = obj->field("children"); if ( fv->type() == openvrml::field_value::mfnode_id ) { const openvrml::mfnode* mfn = dynamic_cast<const openvrml::mfnode *>(fv.get()); openvrml::mfnode::value_type node_ptr_vector = mfn->value(); openvrml::mfnode::value_type::iterator it_npv; for (it_npv = node_ptr_vector.begin(); it_npv != node_ptr_vector.end(); it_npv++) { openvrml::node *node = (*(it_npv)).get(); osg_m->addChild(convertFromVRML(node)); } } } catch (openvrml::unsupported_interface&) { // no children } return osg_m.release(); } else if ((obj->type()).id() == "Shape") // Handle Shape node { osg::ref_ptr<osg::Geometry> osg_geom; // parse the geometry { std::auto_ptr<openvrml::field_value> fv = obj->field("geometry"); if (fv->type() == openvrml::field_value::sfnode_id) { const openvrml::sfnode * sfn = dynamic_cast<const openvrml::sfnode *>(fv.get()); openvrml::sfnode::value_type node_ptr = sfn->value(); if (node_ptr.get()) { // is it indexed_face_set_node ? if (node_ptr->type().id()=="IndexedFaceSet") osg_geom = convertVRML97IndexedFaceSet(node_ptr.get()); else if (node_ptr->type().id()=="IndexedLineSet") osg_geom = convertVRML97IndexedLineSet(node_ptr.get()); else if (node_ptr->type().id() == "Box") osg_geom = convertVRML97Box(node_ptr.get()); else if (node_ptr->type().id() == "Sphere") osg_geom = convertVRML97Sphere(node_ptr.get()); else if (node_ptr->type().id() == "Cone") osg_geom = convertVRML97Cone(node_ptr.get()); else if (node_ptr->type().id() == "Cylinder") osg_geom = convertVRML97Cylinder(node_ptr.get()); else { // other geometry types not handled yet } } } } osg::ref_ptr<osg::Geode> osg_geode = new osg::Geode(); osg_geode->addDrawable(osg_geom.get()); osg::StateSet *osg_stateset = osg_geode->getOrCreateStateSet(); osg::ref_ptr<osg::Material> osg_mat = new osg::Material(); osg_stateset->setAttributeAndModes(osg_mat.get()); osg_mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); // parse the appearance { std::auto_ptr<openvrml::field_value> fv = obj->field("appearance"); if (fv->type() == openvrml::field_value::sfnode_id) { const openvrml::sfnode *sfn = dynamic_cast<const openvrml::sfnode *>(fv.get()); openvrml::appearance_node *vrml_app = dynamic_cast<openvrml::appearance_node *>(sfn->value().get()); const boost::intrusive_ptr<openvrml::node> vrml_material_node = vrml_app->material(); const boost::intrusive_ptr<openvrml::texture_node> vrml_texture_node = openvrml::node_cast<openvrml::texture_node*>(vrml_app->texture().get()); const openvrml::material_node *vrml_material = dynamic_cast<const openvrml::material_node *>(vrml_material_node.get()); if (vrml_material != NULL) { osg_mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(vrml_material->ambient_intensity(), vrml_material->ambient_intensity(), vrml_material->ambient_intensity(), 1.0)); osg_mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(vrml_material->diffuse_color().r(), vrml_material->diffuse_color().g(), vrml_material->diffuse_color().b(), 1.0)); osg_mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(vrml_material->emissive_color().r(), vrml_material->emissive_color().g(), vrml_material->emissive_color().b(), 1.0)); osg_mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(vrml_material->specular_color().r(), vrml_material->specular_color().g(), vrml_material->specular_color().b(), 1.0)); osg_mat->setShininess(osg::Material::FRONT_AND_BACK, vrml_material->shininess() ); if (vrml_material->transparency() > 0.0f) { osg_mat->setTransparency(osg::Material::FRONT_AND_BACK, vrml_material->transparency()); osg_stateset->setMode(GL_BLEND, osg::StateAttribute::ON); osg_stateset->setAttribute(new osg::Depth(osg::Depth::LESS, 0.0, 1.0, false)); // GvdB: transparent objects do not write depth osg_stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } else { osg_stateset->setMode(GL_BLEND, osg::StateAttribute::OFF); osg_stateset->setRenderingHint(osg::StateSet::OPAQUE_BIN); } osg_stateset->setAttributeAndModes(osg_mat.get()); } // if texture is provided if (vrml_texture_node != 0) { osg::ref_ptr<osg::Image> image; if (vrml_texture_node->type().id() == "ImageTexture") { try { std::auto_ptr<openvrml::field_value> texture_url_fv = vrml_texture_node->field("url"); const openvrml::mfstring *mfs = dynamic_cast<const openvrml::mfstring *>(texture_url_fv.get()); const std::string &url = mfs->value()[0]; image = osgDB::readRefImageFile(url); if (!image.valid()) { std::cerr << "texture file " << url << " not found !" << std::endl << std::flush; } } catch (openvrml::unsupported_interface&) { // no url field in the texture } } if (!image.valid()) { // If we cannot read the image try the openvrml builtin mechanisms to read the image. // This includes PixelTexture fields. const openvrml::image& vrml_image = vrml_texture_node->image(); // Convert to an osg image image = new osg::Image; image->allocateImage(vrml_image.x(), vrml_image.y(), 1, GL_RGBA, GL_UNSIGNED_BYTE); for (std::size_t y = 0; y < vrml_image.y(); ++y) { for (std::size_t x = 0; x < vrml_image.x(); ++x) { openvrml::int32 p = vrml_image.pixel(x, y); unsigned char* data = image->data(x, y); data[0] = 0xff & (p >> 24); data[1] = 0xff & (p >> 16); data[2] = 0xff & (p >> 8); data[3] = 0xff & (p >> 0); } } } if (image.valid()) { osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D; texture->setImage(image.get()); // get the real texture wrapping parameters if (vrml_texture_node->repeat_s()) { texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); } else { texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP); } if (vrml_texture_node->repeat_t()) { texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); } else { texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP); } texture->setWrap(osg::Texture::WRAP_R, osg::Texture::REPEAT); osg_stateset->setTextureAttributeAndModes(0, texture.get()); if (image->isImageTranslucent()) { osg_stateset->setMode(GL_BLEND, osg::StateAttribute::ON); osg_stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } } } } } return osg_geode.release(); } else { return 0; } #if 0 /* } else if(obj->type.id == "DirectionalLight") // Handle lights { osg::Group* lightGroup = new osg::Group; openvrml::vrml97_node::directional_light_node *vrml_light; vrml_light = dynamic_cast<openvrml::vrml97_node::directional_light_node *>(obj); // create light with global params osg::Light* myLight = new osg::Light; myLight->setLightNum(osgLightNum); myLight->setAmbient(osg::Vec4(vrml_light->ambient_intensity(),vrml_light->ambient_intensity(),vrml_light->ambient_intensity(),vrml_light->ambient_intensity())); float osgR = vrml_light->color().r()*vrml_light->intensity(); float osgG = vrml_light->color().g()*vrml_light->intensity(); float osgB = vrml_light->color().b()*vrml_light->intensity(); myLight->setDiffuse(osg::Vec4(osgR, osgG, osgB, 1.0f)); myLight->setSpecular(osg::Vec4(osgR, osgG, osgB, 1.0f)); // configure light as DIRECTIONAL openvrml::sfvec3f &dir = vrml_light->direction_; myLight->setDirection(osg::Vec3(dir.value[0],dir.value[1],dir.value[2])); myLight->setPosition(osg::Vec4(dir.value[0],dir.value[1],dir.value[2], 0.0f)); // add the light in the scenegraph osg::LightSource* lightS = new osg::LightSource; lightS->setLight(myLight); if (vrml_light->on()) { lightS->setLocalStateSetModes(osg::StateAttribute::ON); //lightS->setStateSetModes(*rootStateSet,osg::StateAttribute::ON); } lightGroup->addChild(lightS); osgLightNum++; return lightGroup; } else if(obj->type.id == "PointLight") // Handle lights { osg::Group* lightGroup = new osg::Group; openvrml::vrml97_node::point_light_node *vrml_light; vrml_light = dynamic_cast<openvrml::vrml97_node::point_light_node *>(obj); // create light with global params osg::Light* myLight = new osg::Light; myLight->setLightNum(osgLightNum); //std::cout<<"lightnum = "<<osgLightNum; openvrml::sfvec3f &pos = vrml_light->location_; myLight->setPosition(osg::Vec4(pos.value[0], pos.value[1], pos.value[2], 1.0f)); myLight->setAmbient(osg::Vec4(vrml_light->ambient_intensity(),vrml_light->ambient_intensity(),vrml_light->ambient_intensity(),vrml_light->ambient_intensity())); float osgR = vrml_light->color().r()*vrml_light->intensity(); float osgG = vrml_light->color().g()*vrml_light->intensity(); float osgB = vrml_light->color().b()*vrml_light->intensity(); myLight->setDiffuse(osg::Vec4(osgR, osgG, osgB, 1.0f)); myLight->setSpecular(osg::Vec4(osgR, osgG, osgB, 1.0f)); // configure light as POINT myLight->setDirection(osg::Vec3(0.f,0.f,0.f)); // add the light in the scenegraph osg::LightSource* lightS = new osg::LightSource; lightS->setLight(myLight); if (vrml_light->on()) { lightS->setLocalStateSetModes(osg::StateAttribute::ON); //lightS->setStateSetModes(*rootStateSet,osg::StateAttribute::ON); } lightGroup->addChild(lightS); osgLightNum++; return lightGroup; } else if(obj->type.id == "SpotLight") // Handle lights { osg::Group* lightGroup = new osg::Group; openvrml::vrml97_node::spot_light_node *vrml_light; vrml_light = dynamic_cast<openvrml::vrml97_node::spot_light_node *>(obj); // create light with global params osg::Light* myLight = new osg::Light; myLight->setLightNum(osgLightNum); myLight->setPosition(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); myLight->setAmbient(osg::Vec4(vrml_light->ambient_intensity(),vrml_light->ambient_intensity(),vrml_light->ambient_intensity(),vrml_light->ambient_intensity())); float osgR = vrml_light->color().r()*vrml_light->intensity(); float osgG = vrml_light->color().g()*vrml_light->intensity(); float osgB = vrml_light->color().b()*vrml_light->intensity(); myLight->setDiffuse(osg::Vec4(osgR, osgG, osgB, 1.0f)); myLight->setSpecular(osg::Vec4(osgR, osgG, osgB, 1.0f)); // configure light as SPOT openvrml::sfvec3f &dir = vrml_light->direction_; myLight->setDirection(osg::Vec3(dir.value[0],dir.value[1],dir.value[2])); // The cutOff value in osg ranges from 0 to 90, we need // to divide by 2 to avoid openGL error. // myLight->setSpotCutoff(ls.fallsize/2.0f); // The bigger the differens is between fallsize and hotsize // the bigger the exponent should be. // float diff = ls.fallsize - ls.hotsize; // myLight->setSpotExponent(diff); // add the light in the scenegraph osg::LightSource* lightS = new osg::LightSource; lightS->setLight(myLight); if (vrml_light->on()) { lightS->setLocalStateSetModes(osg::StateAttribute::ON); //lightS->setStateSetModes(*rootStateSet,osg::StateAttribute::ON); } lightGroup->addChild(lightS); osgLightNum++; return lightGroup; } else { return NULL; } */ #endif return 0; }
_______________________________________________ osg-submissions mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
