Hi Robert,

I have attached an updated version of the VRML2 loader.
That change is the result of the '[osgPlugins] VRML plugin - "file" url'
discussion on osg-users.

The attached change avoids rewriting file names into some kind of file urls 
and then use the url for opening an fstream. Instead just use the given file 
name to open the stream.
Also this change adds some Notify output for the error paths.

The change is based on rev 12705.

Please apply to mainline and most probably also the release branch.

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;

    std::fstream null;
    resource_fetcher fetcher;
    openvrml::browser *b = new openvrml::browser(fetcher, null, null);

    osgDB::ifstream vrml_stream(fileName.c_str());
    if (!vrml_stream.is_open())
    {
        OSG_INFO << "ReaderWriterVRML2: Could not open \"" << fileName << "\"" << std::endl;
        return ReadResult::FILE_NOT_FOUND;
    }

    try
    {
        const std::vector< boost::intrusive_ptr< openvrml::node > > & mfn = b->create_vrml_from_stream(vrml_stream);

        if(mfn.empty())
        {
            OSG_INFO << "ReaderWriterVRML2: OpenVRML library did not return any vrml nodes." << std::endl;
            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(fileName));
            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 (const openvrml::invalid_vrml& e)
    {
        OSG_INFO << "ReaderWriterVRML2: Invalid VRML in line " << e.line << " at column " << e.column << ": \"" << e.what() << "\"" << std::endl;
        return ReadResult::FILE_NOT_HANDLED;
    }
    catch (const std::invalid_argument& e)
    {
        OSG_INFO << "ReaderWriterVRML2: Invalid argument: \"" << e.what() << "\"" << std::endl;
        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

Reply via email to