📄 fltexportvisitor.cpp
字号:
/* * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or (at * your option) any later version. The full license is in the LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details.*///// Copyright(c) 2008 Skew Matrix Software LLC.//#include "FltExportVisitor.h"#include "ExportOptions.h"#include "FltWriteResult.h"#include "DataOutputStream.h"#include "Opcodes.h"#include "LightSourcePaletteManager.h"#include "MaterialPaletteManager.h"#include "TexturePaletteManager.h"#include "VertexPaletteManager.h"#include "AttrData.h"#include "Utils.h"#include <osgDB/FileUtils>#include <osgDB/WriteFile>#include <osg/Geode>#include <osg/Geometry>#include <osg/LightSource>#include <osg/LOD>#include <osg/MatrixTransform>#include <osg/PositionAttitudeTransform>#include <osg/PrimitiveSet>#include <osg/ProxyNode>#include <osg/Quat>#include <osg/Sequence>#include <osg/Texture2D>#include <osg/TexEnv>#include <osg/Switch>#include <osg/Material>#include <osg/CullFace>#include <osg/BlendFunc>#include <osg/PolygonOffset>#include <osgSim/DOFTransform>#include <osgSim/MultiSwitch>#include <osgSim/LightPointNode>#include <osgSim/ObjectRecordData>#ifdef _WIN32// Disable this warning. It's OK for us to use 'this' in initializer list,// as the texturePaletteManager merely stores a ref to it.#pragma warning( disable : 4355 )#endifnamespace flt{FltExportVisitor::FltExportVisitor( DataOutputStream* dos, ExportOptions* fltOpt ) : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ), _dos( *dos ), _fltOpt( fltOpt ), _materialPalette( new MaterialPaletteManager( *fltOpt ) ), _texturePalette( new TexturePaletteManager( *this, *fltOpt ) ), _lightSourcePalette( new LightSourcePaletteManager( *fltOpt ) ), _vertexPalette( new VertexPaletteManager( *fltOpt ) ), _firstNode( true ){ // Init the StateSet stack. osg::StateSet* ss = new osg::StateSet; int unit; for(unit=0; unit<8; unit++) { osg::TexEnv* texenv = new osg::TexEnv; ss->setTextureAttributeAndModes( unit, texenv, osg::StateAttribute::OFF ); // TBD other texture state? } osg::Material* material = new osg::Material; ss->setAttribute( material, osg::StateAttribute::OFF ); if (fltOpt->getLightingDefault()) ss->setMode( GL_LIGHTING, osg::StateAttribute::ON ); else ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); osg::CullFace* cf = new osg::CullFace; ss->setAttributeAndModes( cf, osg::StateAttribute::OFF ); osg::BlendFunc* bf = new osg::BlendFunc; ss->setAttributeAndModes( bf, osg::StateAttribute::OFF ); osg::PolygonOffset* po = new osg::PolygonOffset; ss->setAttributeAndModes( po, osg::StateAttribute::OFF ); _stateSetStack.push_back( ss ); // Temp file for storing records. Need a temp file because we don't // write header and palette until FltExportVisitor completes traversal. _recordsTempName = fltOpt->getTempDir() + "/ofw_temp_records"; _recordsStr.open( _recordsTempName.c_str(), std::ios::out | std::ios::binary ); _records = new DataOutputStream( _recordsStr.rdbuf(), fltOpt->getValidateOnly() ); // Always write initial push level writePush();}FltExportVisitor::~FltExportVisitor(){ // Delete our temp file. if (_recordsStr.is_open()) { osg::notify( osg::WARN ) << "fltexp: FltExportVisitor destructor has an open temp file." << std::endl; // This should not happen. FltExportVisitor::complete should close // this file before we get to this destructor. return; } osg::notify( osg::INFO ) << "fltexp: Deleting temp file " << _recordsTempName << std::endl; FLTEXP_DELETEFILE( _recordsTempName.c_str() );}voidFltExportVisitor::apply( osg::Group& node ){ ScopedStatePushPop guard( this, node.getStateSet() ); if (_firstNode) { // On input, a FLT header creates a Group node. // On export, we always write a Header record, but then the first Node // we export is the Group that was created from the original input Header. // On successive roundtrips, this results in increased redundant top-level Group nodes/records. // Avoid this by NOT outputting anything for a top-level Group node. _firstNode = false; traverse( node ); return; } // A Group node could indicate one of many possible records. // Header record -- Don't need to support this here. We always output a header. // Group record -- HIGH // Child of an LOD node -- HIGH Currently write out a Group record regardless. // InstanceDefinition/InstanceReference -- MED -- multiparented Group is an instance // Extension record -- MED // Object record -- MED // LightPointSystem record (if psgSim::MultiSwitch) -- LOW osgSim::MultiSwitch* multiSwitch = dynamic_cast<osgSim::MultiSwitch*>( &node ); if (multiSwitch) { writeSwitch( multiSwitch ); } else { osgSim::ObjectRecordData* ord = dynamic_cast< osgSim::ObjectRecordData* >( node.getUserData() ); if (ord) { // This Group should write an Object Record. writeObject( node, ord ); } else { // Handle other cases here. // For now, just output a Group record. writeGroup( node ); } } writeMatrix( node.getUserData() ); writeComment( node ); writePushTraverseWritePop( node );}voidFltExportVisitor::apply( osg::Sequence& node ){ _firstNode = false; ScopedStatePushPop guard( this, node.getStateSet() ); writeSequence( node ); writeMatrix( node.getUserData() ); writeComment( node ); writePushTraverseWritePop( node );}voidFltExportVisitor::apply( osg::Switch& node ){ _firstNode = false; ScopedStatePushPop guard( this, node.getStateSet() ); writeSwitch( &node ); writeMatrix( node.getUserData() ); writeComment( node ); writePushTraverseWritePop( node );}voidFltExportVisitor::apply( osg::LOD& lodNode ){ _firstNode = false; ScopedStatePushPop guard( this, lodNode.getStateSet() ); // LOD center - same for all children osg::Vec3d center = lodNode.getCenter(); // Iterate children of the LOD and write a separate LOD record for each, // with that child's individual switchIn and switchOut properties for ( size_t i = 0; i < lodNode.getNumChildren(); ++i ) { osg::Node* lodChild = lodNode.getChild(i); // Switch-in/switch-out distances may vary per child double switchInDist = lodNode.getMaxRange(i); double switchOutDist = lodNode.getMinRange(i); writeLevelOfDetail( lodNode, center, switchInDist, switchOutDist); writeMatrix( lodNode.getUserData() ); writeComment( lodNode ); // Traverse each child of the LOD writePushTraverseWritePop( *lodChild ); }}voidFltExportVisitor::apply( osg::MatrixTransform& node ){ // Importer reads a Matrix record and inserts a MatrixTransform above // the current node. We need to do the opposite: Write a Matrix record // as an ancillary record for each child. We do that by storing the // MatrixTransform in each child's UserData. Each child then checks // UserData and writes a Matrix record if UserData is a MatrixTransform. _firstNode = false; ScopedStatePushPop guard( this, node.getStateSet() ); osg::ref_ptr< osg::RefMatrix > m = new osg::RefMatrix; m->set( node.getMatrix() ); if (node.getUserData()) { const osg::RefMatrix* rm = dynamic_cast<const osg::RefMatrix*>( node.getUserData() ); if (rm) (*m) *= *rm; } typedef std::vector< osg::ref_ptr< osg::Referenced > > UserDataList; UserDataList saveUserDataList( node.getNumChildren() ); unsigned int idx; for( idx=0; idx<node.getNumChildren(); ++idx ) { saveUserDataList[ idx ] = node.getChild( idx )->getUserData(); node.getChild( idx )->setUserData( m.get() ); } traverse( (osg::Node&)node ); // Restore saved UserData. for( idx=0; idx< node.getNumChildren(); ++idx ) { node.getChild( idx )->setUserData( saveUserDataList[ idx ].get() ); }}voidFltExportVisitor::apply( osg::PositionAttitudeTransform& node ){ _firstNode = false; ScopedStatePushPop guard( this, node.getStateSet() ); osg::ref_ptr<osg::RefMatrix> m = new osg::RefMatrix( osg::Matrix::translate( -node.getPivotPoint() ) * osg::Matrix::scale( node.getScale() ) * osg::Matrix::rotate( node.getAttitude() ) * osg::Matrix::translate( node.getPosition() ) ); typedef std::vector< osg::ref_ptr< osg::Referenced > > UserDataList; UserDataList saveUserDataList( node.getNumChildren() ); unsigned int idx; for( idx=0; idx<node.getNumChildren(); ++idx ) { saveUserDataList[ idx ] = node.getChild( idx )->getUserData(); node.getChild( idx )->setUserData( m.get() ); } traverse( (osg::Node&)node ); // Restore saved UserData. for( idx=0; idx<node.getNumChildren(); ++idx ) { node.getChild( idx )->setUserData( saveUserDataList[ idx ].get() ); }}voidFltExportVisitor::apply( osg::Transform& node ){ _firstNode = false; ScopedStatePushPop guard( this, node.getStateSet() ); osgSim::DOFTransform* dof = dynamic_cast<osgSim::DOFTransform*>( &node ); if (dof) { writeDegreeOfFreedom( dof); } writeMatrix( node.getUserData() ); writeComment( node ); writePushTraverseWritePop( node );}voidFltExportVisitor::apply( osg::LightSource& node ){ _firstNode = false; ScopedStatePushPop guard( this, node.getStateSet() ); writeLightSource( node ); writeMatrix( node.getUserData() ); writeComment( node ); writePushTraverseWritePop( node );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -