⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readerwriterobj.cpp

📁 最新osg包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// -*-c++-*-/* * Wavefront OBJ loader for Open Scene Graph * * Copyright (C) 2001,2007 Ulrich Hertlein <u.hertlein@sandbox.de> * * Modified by Robert Osfield to support per Drawable coord, normal and * texture coord arrays, bug fixes, and support for texture mapping. * * Writing support added 2007 by Stephan Huber, http://digitalmind.de,  * some ideas taken from the dae-plugin * * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for  * real-time rendering of large 3D photo-realistic models.  * The OSG homepage is http://www.openscenegraph.org/ */#if defined(_MSC_VER)    #pragma warning( disable : 4786 )#endif#include <string>#include <osg/Notify>#include <osg/Node>#include <osg/MatrixTransform>#include <osg/Geode>#include <osg/Geometry>#include <osg/StateSet>#include <osg/Material>#include <osg/Texture2D>#include <osg/TexGen>#include <osg/TexMat>#include <osgDB/Registry>#include <osgDB/ReadFile>#include <osgDB/FileUtils>#include <osgDB/FileNameUtils>#include <osgDB/fstream>#include <osgUtil/TriStripVisitor>#include <osgUtil/SmoothingVisitor>#include <osgUtil/Tessellator>#include "obj.h"#include "OBJWriterNodeVisitor.h"#include <map>#include <set>class ReaderWriterOBJ : public osgDB::ReaderWriter{public:    ReaderWriterOBJ():_fixBlackMaterials(true)    {        supportsExtension("obj","Alias Wavefront OBJ format");        supportsOption("noRotation","Do not do the default rotate about X axis");        supportsOption("noTesselateLargePolygons","Do not do the default tesselation of large polygons");        supportsOption("noTriStripPolygons","Do not do the default tri stripping of polygons");    }    virtual const char* className() const { return "Wavefront OBJ Reader"; }    virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const;    virtual ReadResult readNode(std::istream& fin, const Options* options) const;        virtual WriteResult writeObject(const osg::Object& obj,const std::string& fileName,const Options* options=NULL) const     {        const osg::Node* node = dynamic_cast<const osg::Node*>(&obj);        if (node)            return writeNode(*node, fileName, options);        else             return WriteResult(WriteResult::FILE_NOT_HANDLED);     }        virtual WriteResult writeNode(const osg::Node& node,const std::string& fileName,const Options* options =NULL) const     {         if (!acceptsExtension(osgDB::getFileExtension(fileName)))            return WriteResult(WriteResult::FILE_NOT_HANDLED);                     osgDB::ofstream f(fileName.c_str());        std::string materialFile = osgDB::getNameLessExtension(fileName) + ".mtl";        OBJWriterNodeVisitor nv(f, osgDB::getSimpleFileName(materialFile));                // we must cast away constness        (const_cast<osg::Node*>(&node))->accept(nv);                osgDB::ofstream mf(materialFile.c_str());        nv.writeMaterials(mf);                 return WriteResult(WriteResult::FILE_SAVED);     }        virtual WriteResult writeObject(const osg::Object& obj,std::ostream& fout,const Options* options=NULL) const     {        const osg::Node* node = dynamic_cast<const osg::Node*>(&obj);        if (node)            return writeNode(*node, fout, options);        else             return WriteResult(WriteResult::FILE_NOT_HANDLED);     }    virtual WriteResult writeNode(const osg::Node& node,std::ostream& fout,const Options* =NULL) const     {         // writing to a stream does not support materials                OBJWriterNodeVisitor nv(fout);                // we must cast away constness        (const_cast<osg::Node*>(&node))->accept(nv);            return WriteResult(WriteResult::FILE_SAVED);     }protected:    typedef std::map< std::string, osg::ref_ptr<osg::StateSet> > MaterialToStateSetMap;        void buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToSetSetMap) const;        osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, bool& rotate) const;        osg::Node* convertModelToSceneGraph(obj::Model& model, bool& rotate,        bool& noTesselateLargePolygons, bool& noTriStripPolygons) const;    inline osg::Vec3 transformVertex(const osg::Vec3& vec, const bool rotate) const ;    inline osg::Vec3 transformNormal(const osg::Vec3& vec, const bool rotate) const ;        bool _fixBlackMaterials;};inline osg::Vec3 ReaderWriterOBJ::transformVertex(const osg::Vec3& vec, const bool rotate) const{    if(rotate==true)    {        return osg::Vec3(vec.x(),-vec.z(),vec.y());    }    else    {        return vec;    }}inline osg::Vec3 ReaderWriterOBJ::transformNormal(const osg::Vec3& vec, const bool rotate) const{    if(rotate==true)    {        return osg::Vec3(vec.x(),-vec.z(),vec.y());    }    else    {        return vec;    }}// register with Registry to instantiate the above reader/writer.REGISTER_OSGPLUGIN(obj, ReaderWriterOBJ)static void load_material_texture( obj::Model &model,                            obj::Material &material,                            osg::StateSet *stateset,                            const std::string & filename,                            const unsigned int texture_unit  ){    if (!filename.empty())    {        osg::ref_ptr< osg::Image > image;        if ( !model.getDatabasePath().empty() )         {            // first try with database path of parent.             image = osgDB::readImageFile(model.getDatabasePath()+'/'+filename);        }                if ( !image.valid() )        {            // if not already set then try the filename as is.            image = osgDB::readImageFile(filename);        }        if ( image.valid() )        {            osg::Texture2D* texture = new osg::Texture2D( image.get() );            osg::Texture::WrapMode textureWrapMode = osg::Texture::REPEAT;            texture->setWrap(osg::Texture2D::WRAP_R, textureWrapMode);            texture->setWrap(osg::Texture2D::WRAP_S, textureWrapMode);            texture->setWrap(osg::Texture2D::WRAP_T, textureWrapMode);            stateset->setTextureAttributeAndModes( texture_unit, texture,osg::StateAttribute::ON );                        if ( material.textureReflection )            {                osg::TexGen* texgen = new osg::TexGen;                texgen->setMode(osg::TexGen::SPHERE_MAP);                stateset->setTextureAttributeAndModes( texture_unit,texgen,osg::StateAttribute::ON );            }                        if  ( image->isImageTranslucent())            {                osg::notify(osg::INFO)<<"Found transparent image"<<std::endl;                stateset->setMode(GL_BLEND, osg::StateAttribute::ON);                stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);            }        }    }    if (material.uScale != 1.0f || material.vScale != 1.0f ||            material.uOffset != 0.0f || material.vOffset != 0.0f)    {        osg::Matrix mat;        if (material.uScale != 1.0f || material.vScale != 1.0f)        {            osg::notify(osg::DEBUG_INFO) << "Obj TexMat scale=" << material.uScale << "," << material.vScale << std::endl;            mat *= osg::Matrix::scale(material.uScale, material.vScale, 1.0);        }        if (material.uOffset != 0.0f || material.vOffset != 0.0f)        {            osg::notify(osg::DEBUG_INFO) << "Obj TexMat offset=" << material.uOffset << "," << material.uOffset << std::endl;            mat *= osg::Matrix::translate(material.uOffset, material.vOffset, 0.0);        }        osg::TexMat* texmat = new osg::TexMat;        texmat->setMatrix(mat);        stateset->setTextureAttributeAndModes( texture_unit,texmat,osg::StateAttribute::ON );    }}void ReaderWriterOBJ::buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToStateSetMap) const{    if (_fixBlackMaterials)    {        // hack to fix Maya exported models that contian all black materials.        int numBlack = 0;        int numNotBlack = 0;        obj::Model::MaterialMap::iterator itr;        for(itr = model.materialMap.begin();            itr != model.materialMap.end();            ++itr)        {            obj::Material& material = itr->second;            if (material.ambient==osg::Vec4(0.0f,0.0f,0.0f,1.0f) &&                material.diffuse==osg::Vec4(0.0f,0.0f,0.0f,1.0f))            {                ++numBlack;            }            else            {                ++numNotBlack;            }        }                if (numNotBlack==0 && numBlack!=0)        {            for(itr = model.materialMap.begin();                itr != model.materialMap.end();                ++itr)            {                obj::Material& material = itr->second;                if (material.ambient==osg::Vec4(0.0f,0.0f,0.0f,1.0f) &&                    material.diffuse==osg::Vec4(0.0f,0.0f,0.0f,1.0f))                {                    material.ambient.set(0.3f,0.3f,0.3f,1.0f);                    material.diffuse.set(1.0f,1.0f,1.0f,1.0f);                }            }        }    }        for(obj::Model::MaterialMap::iterator itr = model.materialMap.begin();        itr != model.materialMap.end();        ++itr)    {        obj::Material& material = itr->second;                osg::ref_ptr< osg::StateSet > stateset = new osg::StateSet;        bool isTransparent = false;        // handle material colors        // http://java3d.j3d.org/utilities/loaders/obj/sun.html        if (material.illum != 0)        {            osg::Material* osg_material = new osg::Material;            stateset->setAttribute(osg_material);            osg_material->setAmbient(osg::Material::FRONT_AND_BACK,material.ambient);            osg_material->setDiffuse(osg::Material::FRONT_AND_BACK,material.diffuse);            osg_material->setEmission(osg::Material::FRONT_AND_BACK,material.emissive);            if (material.illum == 2) {                osg_material->setSpecular(osg::Material::FRONT_AND_BACK,material.specular);            } else {                osg_material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,1));            }            osg_material->setShininess(osg::Material::FRONT_AND_BACK,(material.Ns/1000.0f)*128.0f ); // note OBJ shiniess is 0..1000.                        if (material.ambient[3]!=1.0 ||                material.diffuse[3]!=1.0 ||                material.specular[3]!=1.0||                material.emissive[3]!=1.0)            {                osg::notify(osg::INFO)<<"Found transparent material"<<std::endl;                isTransparent = true;            }        }                // handle textures        enum TextureUnit        {            TEXTURE_UNIT_KD = 0,            TEXTURE_UNIT_OPACITY        };        load_material_texture( model, material, stateset.get(), material.map_Kd,       TEXTURE_UNIT_KD );        load_material_texture( model, material, stateset.get(), material.map_opacity,  TEXTURE_UNIT_OPACITY );                if (isTransparent)        {            stateset->setMode(GL_BLEND, osg::StateAttribute::ON);            stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);        }        materialToStateSetMap[material.name] = stateset.get();    }}osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, bool& rotate) const{        unsigned int numVertexIndices = 0;    unsigned int numNormalIndices = 0;    unsigned int numTexCoordIndices = 0;        unsigned int numPointElements = 0;    unsigned int numPolylineElements = 0;    unsigned int numPolygonElements = 0;    obj::Model::ElementList::iterator itr;    for(itr=elementList.begin();        itr!=elementList.end();        ++itr)    {        obj::Element& element = *(*itr);        numVertexIndices += element.vertexIndices.size();        numNormalIndices += element.normalIndices.size();        numTexCoordIndices += element.texCoordIndices.size();        numPointElements += (element.dataType==obj::Element::POINTS) ? 1 : 0;        numPolylineElements += (element.dataType==obj::Element::POLYLINE) ? 1 : 0;        numPolygonElements += (element.dataType==obj::Element::POLYGON) ? 1 : 0;    }    if (numVertexIndices==0) return 0;        if (numNormalIndices!=0 && numNormalIndices!=numVertexIndices)    {        osg::notify(osg::NOTICE)<<"Incorrect number of normals, ignore them"<<std::endl;        numNormalIndices = 0;    }        if (numTexCoordIndices!=0 && numTexCoordIndices!=numVertexIndices)    {        osg::notify(osg::NOTICE)<<"Incorrect number of normals, ignore them"<<std::endl;        numTexCoordIndices = 0;    }        osg::Vec3Array* vertices = numVertexIndices ? new osg::Vec3Array : 0;    osg::Vec3Array* normals = numNormalIndices ? new osg::Vec3Array : 0;    osg::Vec2Array* texcoords = numTexCoordIndices ? new osg::Vec2Array : 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -