txpparser.cpp

来自「最新osg包」· C++ 代码 · 共 1,859 行 · 第 1/4 页

CPP
1,859
字号
#include <stdlib.h>#include <osg/AlphaFunc>#include <osg/Group>#include <osg/Material>#include <osg/TexEnv>#include <osg/LOD>#include <osg/Geode>#include <osg/Billboard>#include <osg/Matrix>#include <osg/MatrixTransform>#include <osg/Geometry>#include <osg/CullFace>#include <osg/Light>#include <osg/Notify>#include <osg/PolygonOffset>#include <osg/MatrixTransform>#include <osg/PagedLOD>#include <osgSim/LightPointNode>#include <osg/Point>#include <osg/ShapeDrawable>#include <osg/ApplicationUsage>#include <osgText/Text>#include <osgUtil/Optimizer>#include "TXPParser.h"#include "TXPArchive.h"using namespace txp;#include <sstream>static osg::ApplicationUsageProxy TXP_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_TXP_DEFAULT_MAX_ANISOTROPY \"<value> [<value>]\"","1.0 | 2.0 | 4.0 | 8.0 | 16.0");class LayerGroup : public osg::Group{public:    LayerGroup() : osg::Group() {}        LayerGroup(const LayerGroup& gg,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):        osg::Group(gg, copyop)    {};        META_Node(txp, LayerGroup);protected:    virtual ~LayerGroup() {}};class LayerVisitor : public osg::NodeVisitor{public:    LayerVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}    virtual void apply(osg::Group& node)    {        LayerGroup *lg = dynamic_cast<LayerGroup*>(&node);        if (lg)        {            for (unsigned int i=1; i < lg->getNumChildren(); ++i)            {                osg::Node *child = lg->getChild(i);                osg::StateSet *sset = child->getOrCreateStateSet();                osg::PolygonOffset* polyoffset = new osg::PolygonOffset;                polyoffset->setFactor(-1.0f);                polyoffset->setUnits(-200.0f*i);                sset->setAttributeAndModes(polyoffset,osg::StateAttribute::ON);            }        }        traverse(node);    }};TXPParser::TXPParser():    _archive(0),    _currentTop(0),    _root(0),    _underBillboardSubgraph(false),    _numBillboardLevels(0),    _underLayerSubgraph(false),    _numLayerLevels(0),    _layerGeode(0),    _defaultMaxAnisotropy(1.0f),    _realMinRange(0.0),    _realMaxRange(0.0),    _usedMaxRange(0.0),    _childRefCB(0){    AddCallback(TRPG_ATTACH,    new attachRead(this));    AddCallback(TRPG_CHILDREF,  new childRefRead(this));    AddCallback(TRPG_GEOMETRY,  new geomRead(this));    AddCallback(TRPG_GROUP,     new groupRead(this));    AddCallback(TRPG_LOD,       new lodRead(this));    AddCallback(TRPG_MODELREF,  new modelRefRead(this));    AddCallback(TRPG_BILLBOARD, new billboardRead(this));    AddCallback(TRPG_LIGHT,     new lightRead(this));    AddCallback(TRPG_LAYER,     new layerRead(this));    AddCallback(TRPG_LABEL,     new labelRead(this));    AddCallback(TRPGTILEHEADER, new tileHeaderRead(this));    _childRefCB = dynamic_cast<childRefRead *>(GetCallback(TRPG_CHILDREF));        if (getenv("OSG_TXP_DEFAULT_MAX_ANISOTROPY"))    {        _defaultMaxAnisotropy = atof(getenv("OSG_TXP_DEFAULT_MAX_ANISOTROPY"));    }    }TXPParser::~TXPParser(){}osg::Group *TXPParser::parseScene(    trpgReadBuffer &buf,     std::map<int,osg::ref_ptr<osg::StateSet> > &materials,    std::map<int,osg::ref_ptr<osg::Node> > &models,    double realMinRange, double realMaxRange, double usedMaxRange){    if (_archive == 0) return NULL;    if(_childRefCB)       _childRefCB->Reset();    _root = new osg::Group();    _currentTop = _root.get();    _materialMap = &materials;    _localMaterials.clear();    _models = &models;    _underBillboardSubgraph = false;    _numBillboardLevels = 0;    _underLayerSubgraph = false;    _numLayerLevels = 0;    _realMinRange = realMinRange;    _realMaxRange = realMaxRange;    _usedMaxRange = usedMaxRange;    _tileCenter = osg::Vec3(0.f,0.f,0.f);    if (!Parse(buf))    {        osg::notify(osg::NOTICE) << "txp::TXPParser::parseScene(): failed to parse the given tile" << std::endl;        return NULL;    }    for (std::map<osg::Group*,int>::iterator i = _tileGroups.begin(); i != _tileGroups.end(); i++)    {        replaceTileLod((*i).first);    }    _tileGroups.clear();    try    {       LayerVisitor lv;       _root->accept(lv);       //modified by Brad Anderegg May-27-08       //running the optimizer on the terrain fixes some major preformance issues, unfortunately the texture atlas builder seems to get messed up        //on some of the textures (usually around buildings) and the tri stripper seems to occasionally crash and also mess up the indices on certain buildings.       osgUtil::Optimizer opt;       opt.optimize(_root.get(), (osgUtil::Optimizer::ALL_OPTIMIZATIONS ^ osgUtil::Optimizer::TEXTURE_ATLAS_BUILDER) ^ osgUtil::Optimizer::TRISTRIP_GEOMETRY);    }    catch (...)    {       osg::notify(osg::NOTICE) << "txp::TXPParser::parseScene(): exception thrown in the osg::Optimizer" << std::endl;    }    return _root.get();}void TXPParser::replaceTileLod(osg::Group* group){    if (group->getNumChildren() == 2)    {        osg::LOD* loLOD = dynamic_cast<osg::LOD*>(group->getChild(0));        osg::LOD* hiLOD = dynamic_cast<osg::LOD*>(group->getChild(1));        if (loLOD && hiLOD)        {            osg::Group *g = dynamic_cast<osg::Group*>(hiLOD->getChild(0));            if (!g) return;            if (g->getNumChildren()) return;            _tileCenter = loLOD->getCenter();            group->addChild(loLOD->getChild(0));            group->removeChild(loLOD);            group->removeChild(hiLOD);        }    }}unsigned int TXPParser::GetNbChildrenRef() const{   if(_childRefCB)         return _childRefCB->GetNbChildrenRef();      else         return 0;}const trpgChildRef* TXPParser::GetChildRef(unsigned int idx) const{   if(_childRefCB)      return _childRefCB->GetChildRef(idx);   else      return 0;}bool TXPParser::StartChildren(void * /*in*/){    bool pushParent = true;    if (_underBillboardSubgraph )    {        if (_numBillboardLevels > 0) pushParent = false;        _numBillboardLevels++;    }    else    if (_underLayerSubgraph)    {        if (_numLayerLevels > 0) pushParent = false;        _numLayerLevels++;    }    if (pushParent)    {        _parents.push(_currentTop);        _currentTop = _currentNode->asGroup();    }        return true;}bool TXPParser::EndChildren(void *){    bool popParent = true;    if (_underLayerSubgraph)    {        _numLayerLevels--;        if (_numLayerLevels == 0)        {            _underLayerSubgraph = false;        }        else            popParent = false;    }    else    if (_underBillboardSubgraph)    {        _numBillboardLevels--;        if (_numBillboardLevels == 0)        {            _underBillboardSubgraph = false;        }        else            popParent = false;    }    if (popParent)    {        if (_parents.size())        {            _currentTop = _parents.top();            _parents.pop();        }        else            _currentTop = _root.get();    }    return true;}DeferredLightAttribute& TXPParser::getLightAttribute(int ix){     return _archive->getLightAttribute(ix); }class FindEmptyGroupsVisitor : public osg::NodeVisitor{public:    FindEmptyGroupsVisitor(osg::NodeList& nl):      osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _nl(nl) {};    virtual void apply(osg::Group& group)    {        if (group.getNumChildren()==0)        {            _nl.push_back(&group);        }        traverse(group);    }protected:    osg::NodeList& _nl;};void TXPParser::removeEmptyGroups(){    if (_root.get() && _root->getNumChildren())    {        osg::NodeList nl;        FindEmptyGroupsVisitor fegv(nl);        _root->accept(fegv);        for (unsigned int i = 0; i < nl.size(); i++)        {            osg::Node* node = nl[i].get();            if (node == NULL) continue;            osg::Node::ParentList parents = node->getParents();            for (unsigned int j = 0; j < parents.size(); j++)            {                osg::Group* parent = parents[j];                if (parent) parent->removeChild(node);            }        }    }}osg::Geode* TXPParser::createBoundingBox(int x,int y, int lod){    TXPArchive::TileInfo info;    _archive->getTileInfo(x,y,lod,info);    osg::Geode* geode = new osg::Geode();    osg::TessellationHints* hints = new osg::TessellationHints;    hints->setDetailRatio(0.5f);    osg::ShapeDrawable* sd = new osg::ShapeDrawable(            new osg::Box(                info.center,                info.bbox.xMax()-info.bbox.xMin(),                info.bbox.yMax()-info.bbox.yMin(),                1            ),            hints        );        if (lod==0)    {        sd->setColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));    }    else    if (lod==1)    {        sd->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f));    }    else    if (lod==2)    {        sd->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f));    }    else    if (lod==3)    {        sd->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f));    }    else    if (lod==4)    {        sd->setColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f));    }    geode->addDrawable( sd );    return geode;}void TXPParser::loadLocalMaterials(){    bool separateGeo = false;    int majorVer,minorVer;    this->getArchive()->GetVersion(majorVer,minorVer);    if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) {    separateGeo = true;    }    // new to 2.0 LOCAL materials    trpgrImageHelper image_helper(        _archive->GetEndian(),        _archive->getDir(),        *_archive->GetMaterialTable(),        *_archive->GetTexTable(),        separateGeo    );    trpgTileHeader* tile_head = getTileHeaderRef();    int n_materials;    tile_head->GetNumLocalMaterial(n_materials);    int n_mat;    tile_head->GetNumMaterial(n_mat);    _localMaterials.clear();    _localMaterials.resize(n_materials);    {        for (int i = 0; i < n_materials; i++)        {            osg::StateSet* osg_state_set = new osg::StateSet;                        trpgLocalMaterial locmat;            tile_head->GetLocalMaterial(i,locmat);                        const trpgMaterial* mat = 0;            const trpgTexture *tex = 0;            int32 size;            image_helper.GetImageInfoForLocalMat(&locmat, &mat,&tex,size);            int num_tex;            mat->GetNumTexture(num_tex);            for (int texNo = 0 ; texNo < num_tex; ++texNo)            {                int texId;                trpgTextureEnv texEnv;                mat->GetTexture(texNo,texId,texEnv);                // Set up texture environment                osg::TexEnv       *osg_texenv       = new osg::TexEnv();                int32 te_mode;                texEnv.GetEnvMode(te_mode);                switch( te_mode )                {                case trpgTextureEnv::Alpha :                    osg_texenv->setMode(osg::TexEnv::REPLACE);            break;                case trpgTextureEnv::Decal:                    osg_texenv->setMode(osg::TexEnv::DECAL);                    break;                case trpgTextureEnv::Blend :                    osg_texenv->setMode(osg::TexEnv::BLEND);                    break;                case trpgTextureEnv::Modulate :                    osg_texenv->setMode(osg::TexEnv::MODULATE);                    break;                }                            osg_state_set->setTextureAttribute(texNo,osg_texenv);                image_helper.GetNthImageInfoForLocalMat(&locmat, texNo, &mat,&tex,size);                            trpgTexture::ImageMode mode;                tex->GetImageMode(mode);                osg::Texture2D* osg_texture = 0L;                if(mode == trpgTexture::Template)                     osg_texture = getTemplateTexture(image_helper,&locmat, tex, texNo);                else if(mode == trpgTexture::Local)                     osg_texture = getLocalTexture(image_helper,tex);                else if(mode == trpgTexture::Global)                    osg_texture = _archive->getGlobalTexture(texId);                if(osg_texture)                {                    if(osg_texture->getImage())                    {                        GLenum gltype = osg_texture->getImage()->getPixelFormat();                        if( gltype == GL_RGBA || gltype == GL_LUMINANCE_ALPHA )                        {                            osg_state_set->setMode(GL_BLEND,osg::StateAttribute::ON);                            osg_state_set->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);                        }                    }                    else

⌨️ 快捷键说明

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