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 = ⊧ _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 + -
显示快捷键?