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

📄 readerwriterlwo.cpp

📁 最新osg包
💻 CPP
字号:
// -*-c++-*-/* * Lightwave Object loader for Open Scene Graph * * Copyright (C) 2001 Ulrich Hertlein <u.hertlein@web.de> * Improved LWO2 reader is (C) 2003-2004 Marco Jez <marco.jez@poste.it> * * 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 <memory>#include <sstream>#include <algorithm>#include <osg/Notify>#include <osg/Node>#include <osg/Group>#include <osg/Geode>#include <osg/Group>#include <osg/Texture2D>#include <osg/Geometry>#include <osg/StateSet>#include <osgDB/Registry>#include <osgDB/ReadFile>#include <osgDB/FileNameUtils>#include <osgDB/FileUtils>#include <osgUtil/SmoothingVisitor>#include <osgUtil/Tessellator>#include "Converter.h"#include "VertexMap.h"#include "old_lw.h"#include "old_Lwo2.h"class ReaderWriterLWO : public osgDB::ReaderWriter{public:    ReaderWriterLWO()    {        supportsExtension("lwo","Lightwave object format");        supportsExtension("lw","Lightwave object format");        supportsExtension("geo","Lightwave geometry format");    }        virtual const char* className() const { return "Lightwave Object Reader"; }    virtual ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const    {        std::string ext = osgDB::getLowerCaseFileExtension(file);                if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;        std::string fileName = osgDB::findDataFile( file, options );        if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;        // code for setting up the database path so that internally referenced file are searched for on relative paths.         osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;        local_opt->setDatabasePath(osgDB::getFilePath(fileName));        ReadResult result = readNode_LWO1(fileName,local_opt.get());        if (result.success()) return result;                if (!options || options->getOptionString() != "USE_OLD_READER") {            ReadResult result = readNode_LWO2(fileName, local_opt.get());            if (result.success()) return result;        }        return readNode_old_LWO2(fileName, local_opt.get());    }    lwosg::Converter::Options parse_options(const Options *options) const;    virtual ReadResult readNode_LWO2(const std::string& fileName, const osgDB::ReaderWriter::Options*) const;    virtual ReadResult readNode_old_LWO2(const std::string& fileName, const osgDB::ReaderWriter::Options*) const;    virtual ReadResult readNode_LWO1(const std::string& fileName, const osgDB::ReaderWriter::Options*) const;protected:    };lwosg::Converter::Options ReaderWriterLWO::parse_options(const Options *options) const{    lwosg::Converter::Options conv_options;    if (options) {        std::istringstream iss(options->getOptionString());        std::string opt;        while (iss >> opt) {            if (opt == "COMBINE_GEODES")           conv_options.combine_geodes = true;            if (opt == "FORCE_ARB_COMPRESSION")    conv_options.force_arb_compression = true;            if (opt == "USE_OSGFX")                conv_options.use_osgfx = true;            if (opt == "NO_LIGHTMODEL_ATTRIBUTE")  conv_options.apply_light_model = false;            if (opt == "BIND_TEXTURE_MAP")            {                std::string mapname;                int unit;                if (iss >> mapname >> unit)                {                    conv_options.texturemap_bindings.insert(lwosg::VertexMap_binding_map::value_type(mapname,  unit));                }            }            if (opt == "MAX_TEXTURE_UNITS") {                int n;                if (iss >> n) {                    conv_options.max_tex_units = n;                }            }        }    }    return conv_options;}// register with Registry to instantiate the above reader/writer.REGISTER_OSGPLUGIN(lwo, ReaderWriterLWO)osgDB::ReaderWriter::ReadResult ReaderWriterLWO::readNode_LWO2(const std::string &fileName, const osgDB::ReaderWriter::Options *options) const{    lwosg::Converter::Options conv_options = parse_options(options);    lwosg::Converter converter(conv_options, options);    osg::ref_ptr<osg::Node> node = converter.convert(fileName);    if (node.valid()) {        return node.release();    }    return ReadResult::FILE_NOT_HANDLED;}osgDB::ReaderWriter::ReadResult ReaderWriterLWO::readNode_old_LWO2(const std::string& fileName, const osgDB::ReaderWriter::Options*) const{    std::auto_ptr<Lwo2> lwo2(new Lwo2());    if (lwo2->ReadFile(fileName))    {        osg::ref_ptr<Group> group = new osg::Group();        if (lwo2->GenerateGroup(*group)) return group.release();    }    return ReadResult::FILE_NOT_HANDLED;}// collect all the data relavent to a particular osg::Geometry being created.struct GeometryCollection{    GeometryCollection():        _numPrimitives(0),        _numPrimitivesWithTexCoords(0),        _numPoints(0),        _texturesActive(false),        _vertices(osg::Vec3Array::iterator()),        _texcoords(osg::Vec2Array::iterator()),        _coordCount(0),        _geom(0) {}    int                         _numPrimitives;    int                         _numPrimitivesWithTexCoords;    int                         _numPoints;    bool                        _texturesActive;    osg::Vec3Array::iterator    _vertices;    osg::Vec2Array::iterator    _texcoords;    int                         _coordCount;    osg::Geometry*              _geom;};// read file and convert to OSG.osgDB::ReaderWriter::ReadResult ReaderWriterLWO::readNode_LWO1(const std::string& fileName, const osgDB::ReaderWriter::Options*) const{    lwObject* lw = lw_object_read(fileName.c_str(),osg::notify(osg::INFO));    if (!lw)        return ReadResult::FILE_NOT_HANDLED;    osg::notify(osg::INFO) << "faces " << lw->face_cnt << std::endl;    osg::notify(osg::INFO) << "materials " << lw->material_cnt << std::endl;    osg::notify(osg::INFO) << "vertices " << lw->vertex_cnt << std::endl;    typedef std::map<int,GeometryCollection> MaterialToGeometryCollectionMap;    MaterialToGeometryCollectionMap mtgcm;        // bin the indices for each material into the mtis;    int i;    for (i = 0; i < lw->face_cnt; ++i)    {        lwFace& face = lw->face[i];        if (face.index_cnt>=3)        {            GeometryCollection& gc = mtgcm[face.material];            gc._numPoints += face.index_cnt;            gc._numPrimitives += 1;            if (face.texcoord) gc._numPrimitivesWithTexCoords += 1;        }    }        MaterialToGeometryCollectionMap::iterator itr;    for(itr=mtgcm.begin(); itr!=mtgcm.end(); ++itr)    {        GeometryCollection& gc = itr->second;        if (gc._numPrimitives)        {            lwMaterial& lw_material = lw->material[itr->first];            gc._geom = new osg::Geometry;                        osg::Vec3Array* vertArray = new osg::Vec3Array(gc._numPoints);            gc._vertices = vertArray->begin();            gc._geom->setVertexArray(vertArray);            // set up color.            osg::Vec4Array* colors = new osg::Vec4Array(1);            (*colors)[0].set(lw_material.r,                             lw_material.g,                             lw_material.b,                             1.0f);                                         gc._geom->setColorArray(colors);            gc._geom->setColorBinding(osg::Geometry::BIND_OVERALL);                // set up texture if needed.            if (gc._numPrimitivesWithTexCoords==gc._numPrimitives)            {                if (lw_material.ctex.flags && strlen(lw_material.ctex.name)!=0)                {                    osg::notify(osg::INFO) << "ctex " << lw_material.ctex.name << std::endl;                    osg::Image* image = osgDB::readImageFile(lw_material.ctex.name);                    if (image)                    {                        // create state                        osg::StateSet* stateset = new osg::StateSet;                        // create texture                        osg::Texture2D* texture = new osg::Texture2D;                        texture->setImage(image);                        // texture wrap mode                        static osg::Texture::WrapMode mode[] = {                            osg::Texture::CLAMP,                            osg::Texture::CLAMP,                            osg::Texture::REPEAT,                            osg::Texture::MIRROR                        };                        texture->setWrap(osg::Texture::WRAP_S,                                         mode[lw_material.ctex.u_wrap]);                        texture->setWrap(osg::Texture::WRAP_T,                                         mode[lw_material.ctex.v_wrap]);                        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);                        gc._texturesActive=true;                                                gc._geom->setStateSet(stateset);                        osg::Vec2Array* texcoordArray = new osg::Vec2Array(gc._numPoints);                        gc._texcoords = texcoordArray->begin();                        gc._geom->setTexCoordArray(0,texcoordArray);                    }                }            }        }            }            for (i = 0; i < lw->face_cnt; ++i)    {        lwFace& face = lw->face[i];        if (face.index_cnt>=3)        {            GeometryCollection& gc = mtgcm[face.material];                        osg::PrimitiveSet::Mode mode;            switch(face.index_cnt)            {                case(0):                    mode = osg::PrimitiveSet::POINTS;                    break;                case(1):                    mode = osg::PrimitiveSet::POINTS;                    break;                case(2):                    mode = osg::PrimitiveSet::LINES;                    break;                case(3):                    mode = osg::PrimitiveSet::TRIANGLES;                    break;                case(4):                    mode = osg::PrimitiveSet::QUADS;                    break;                default:                    mode = osg::PrimitiveSet::POLYGON;                    break;            }                                    gc._geom->addPrimitiveSet(new osg::DrawArrays(mode,gc._coordCount,face.index_cnt));            gc._coordCount += face.index_cnt;            // From the spec_low.lxt :            //   "By convention, the +X direction is to the right or east, the +Y            //    direction is upward, and the +Z direction is forward or north"            // However, the osg sticks to the more conventional, y to the north,            // z upwards, x is the same - rigth/east.  To handle this difference            // simple exchange osg_z for lwo_y, and osg_y for lwo_z.            // add the corners in reverse order to reverse the windings, to keep the anticlockwise rotation of polys.            int j;            for(j=face.index_cnt-1;j>=0;--j)            {                (*gc._vertices++).set(lw->vertex[face.index[j]*3], lw->vertex[face.index[j]*3+2], lw->vertex[face.index[j]*3+1]);            }                        if (gc._texturesActive && face.texcoord)            {                for(j=face.index_cnt-1;j>=0;--j)                {                    (*gc._texcoords++).set(face.texcoord[j*2],face.texcoord[j*2+1]);                }                        }                    }    }    osg::Geode* geode = new osg::Geode;        osgUtil::Tessellator tessellator;        // add everthing into the Geode.        osgUtil::SmoothingVisitor smoother;    for(itr=mtgcm.begin();        itr!=mtgcm.end();        ++itr)    {        GeometryCollection& gc = itr->second;        if (gc._geom)        {                        tessellator.retessellatePolygons(*gc._geom);                    smoother.smooth(*gc._geom);                        geode->addDrawable(gc._geom);        }    }    // free    lw_object_free(lw);    return geode;}

⌨️ 快捷键说明

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