From Paul Martz, "Here's the mods to the OpenFlight plugin to support FLT export. The ZIP file contains the new .cpp/h files as well as existing files that I modified.
Changes to existing files: ReaderWriter.cpp -- to support writeNode() of course. ReaderWriterATTR.cpp -- to support writeObject -- we write .attr files for textures, if they don't already exist. AttrData.cpp/.h -- Minor fixes. CMakeLists.txt -- to include the new files in the build." From Robert Osfield, port to non Windows platforms just required fixing of header capitilization errors that windows lets through the net due to having a case insensitive file system.
This commit is contained in:
@@ -24,7 +24,7 @@ using namespace flt;
|
||||
|
||||
AttrData::AttrData() :
|
||||
texels_u(0),
|
||||
textel_v(0),
|
||||
texels_v(0),
|
||||
direction_u(0),
|
||||
direction_v(0),
|
||||
x_up(0),
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <osg/Object>
|
||||
#include "types.h"
|
||||
#include "Types.h"
|
||||
|
||||
namespace flt {
|
||||
|
||||
@@ -112,7 +112,7 @@ class AttrData : public osg::Object
|
||||
};
|
||||
|
||||
int32 texels_u; // Number of texels in u direction
|
||||
int32 textel_v; // Number of texels in v direction
|
||||
int32 texels_v; // Number of texels in v direction
|
||||
int32 direction_u; // Real world size u direction
|
||||
int32 direction_v; // Real world size v direction
|
||||
int32 x_up; // x component of up vector
|
||||
@@ -328,6 +328,7 @@ class AttrData : public osg::Object
|
||||
// definition measured in texels.
|
||||
}
|
||||
#endif
|
||||
int32 numSubtextures; // # of subtextures
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -6,9 +6,18 @@ SET(TARGET_SRC
|
||||
AttrData.cpp
|
||||
ControlRecords.cpp
|
||||
DataInputStream.cpp
|
||||
DataOutputStream.cpp
|
||||
Document.cpp
|
||||
expAncillaryRecords.cpp
|
||||
expControlRecords.cpp
|
||||
expGeometryRecords.cpp
|
||||
expPrimaryRecords.cpp
|
||||
ExportOptions.cpp
|
||||
FltExportVisitor.cpp
|
||||
GeometryRecords.cpp
|
||||
LightPointRecords.cpp
|
||||
LightSourcePaletteManager.cpp
|
||||
MaterialPaletteManager.cpp
|
||||
PaletteRecords.cpp
|
||||
Pools.cpp
|
||||
PrimaryRecords.cpp
|
||||
@@ -19,21 +28,32 @@ SET(TARGET_SRC
|
||||
Registry.cpp
|
||||
ReservedRecords.cpp
|
||||
RoadRecords.cpp
|
||||
TexturePaletteManager.cpp
|
||||
Vertex.cpp
|
||||
VertexPaletteManager.cpp
|
||||
VertexRecords.cpp
|
||||
)
|
||||
|
||||
SET(TARGET_H
|
||||
AttrData.h
|
||||
DataInputStream.h
|
||||
DataOutputStream.h
|
||||
ExportOptions.h
|
||||
FltExportVisitor.h
|
||||
FltWriteResult.h
|
||||
Document.h
|
||||
LightSourcePaletteManager.h
|
||||
MaterialPaletteManager.h
|
||||
Pools.h
|
||||
Record.h
|
||||
RecordInputStream.h
|
||||
Registry.h
|
||||
TexturePaletteManager.h
|
||||
Vertex.h
|
||||
opcodes.h
|
||||
types.h
|
||||
VertexPaletteManager.h
|
||||
Opcodes.h
|
||||
Types.h
|
||||
Utils.h
|
||||
)
|
||||
|
||||
SET(TARGET_ADDED_LIBRARIES osgSim )
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/Vec3d>
|
||||
#include <osg/Vec4f>
|
||||
#include "types.h"
|
||||
#include "Types.h"
|
||||
|
||||
namespace flt {
|
||||
|
||||
|
||||
202
src/osgPlugins/OpenFlight/DataOutputStream.cpp
Normal file
202
src/osgPlugins/OpenFlight/DataOutputStream.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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 "DataOutputStream.h"
|
||||
|
||||
#include <osg/Endian>
|
||||
#include <osg/Notify>
|
||||
|
||||
|
||||
using namespace flt;
|
||||
|
||||
|
||||
char DataOutputStream::_null( 0 );
|
||||
|
||||
|
||||
DataOutputStream::DataOutputStream( std::streambuf* sb, bool validate )
|
||||
: std::ostream( sb ),
|
||||
_validate( validate )
|
||||
{
|
||||
_byteswap = osg::getCpuByteOrder() == osg::LittleEndian;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataOutputStream::writeInt8( const int8 val )
|
||||
{
|
||||
vwrite( (char*)&val, sizeof( int8 ) );
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeUInt8( const uint8 val )
|
||||
{
|
||||
vwrite( (char*)&val, sizeof( uint8 ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataOutputStream::writeInt16( const int16 val )
|
||||
{
|
||||
int16 data=val;
|
||||
if (_byteswap && good())
|
||||
osg::swapBytes2( (char*)&data );
|
||||
vwrite( (char*)&data, sizeof( int16 ) );
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeUInt16( const uint16 val )
|
||||
{
|
||||
uint16 data=val;
|
||||
if (_byteswap && good())
|
||||
osg::swapBytes2( (char*)&data );
|
||||
vwrite( (char*)&data, sizeof( uint16 ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataOutputStream::writeInt32( const int32 val )
|
||||
{
|
||||
int32 data=val;
|
||||
if (_byteswap && good())
|
||||
osg::swapBytes4( (char*)&data );
|
||||
vwrite( (char*)&data, sizeof( int32 ) );
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeUInt32( const uint32 val )
|
||||
{
|
||||
uint32 data=val;
|
||||
if (_byteswap && good())
|
||||
osg::swapBytes4( (char*)&data );
|
||||
vwrite( (char*)&data, sizeof( uint32 ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataOutputStream::writeFloat32( const float32 val )
|
||||
{
|
||||
float32 data=val;
|
||||
if (_byteswap && good())
|
||||
osg::swapBytes4( (char*)&data );
|
||||
vwrite( (char*)&data, sizeof( float32 ) );
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeFloat64( const float64 val )
|
||||
{
|
||||
float64 data=val;
|
||||
if (_byteswap && good())
|
||||
osg::swapBytes8( (char*)&data );
|
||||
vwrite( (char*)&data, sizeof( float64 ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataOutputStream::writeString( const std::string& val, bool nullTerminate )
|
||||
{
|
||||
vwrite( const_cast<char*>( val.c_str() ), val.size() );
|
||||
if (nullTerminate)
|
||||
vwrite( &_null, 1 );
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeString( const std::string& val, int size, char fill )
|
||||
{
|
||||
if (val.size() > ((unsigned int)size)-1)
|
||||
{
|
||||
vwrite( const_cast<char*>( val.c_str() ), size-1 );
|
||||
vwrite( &fill, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
vwrite( const_cast<char*>( val.c_str() ), val.size() );
|
||||
writeFill( size - val.size(), fill );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeID( const std::string& val )
|
||||
{
|
||||
unsigned int len = val.size();
|
||||
|
||||
vwrite( const_cast<char*>( val.c_str() ), len );
|
||||
|
||||
while (len++ < 8)
|
||||
vwrite( &_null, 1 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataOutputStream::writeColor32( const osg::Vec4f& val )
|
||||
{
|
||||
writeUInt8( val.a() );
|
||||
writeUInt8( val.b() );
|
||||
writeUInt8( val.g() );
|
||||
writeUInt8( val.r() );
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeVec2f( const osg::Vec2f& val )
|
||||
{
|
||||
writeFloat32( val.x() );
|
||||
writeFloat32( val.y() );
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeVec3f( const osg::Vec3f& val )
|
||||
{
|
||||
writeFloat32( val.x() );
|
||||
writeFloat32( val.y() );
|
||||
writeFloat32( val.z() );
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeVec4f( const osg::Vec4f& val )
|
||||
{
|
||||
writeFloat32( val.x() );
|
||||
writeFloat32( val.y() );
|
||||
writeFloat32( val.z() );
|
||||
writeFloat32( val.w() );
|
||||
}
|
||||
|
||||
void
|
||||
DataOutputStream::writeVec3d( const osg::Vec3d& val )
|
||||
{
|
||||
writeFloat64( val.x() );
|
||||
writeFloat64( val.y() );
|
||||
writeFloat64( val.z() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataOutputStream::writeFill( int sizeBytes, const char val )
|
||||
{
|
||||
for (int i = 0; i < sizeBytes; ++i)
|
||||
{
|
||||
put(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::ostream&
|
||||
DataOutputStream::vwrite( char_type* str, std::streamsize count )
|
||||
{
|
||||
if (_validate)
|
||||
return *this;
|
||||
else
|
||||
return write( str, count );
|
||||
}
|
||||
|
||||
78
src/osgPlugins/OpenFlight/DataOutputStream.h
Normal file
78
src/osgPlugins/OpenFlight/DataOutputStream.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.
|
||||
//
|
||||
|
||||
#ifndef __FLTEXP_DATA_OUTPUT_STREAM_H__
|
||||
#define __FLTEXP_DATA_OUTPUT_STREAM_H__ 1
|
||||
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/Vec3d>
|
||||
#include <osg/Vec4f>
|
||||
#include "Types.h"
|
||||
//#include "Export.h"
|
||||
|
||||
|
||||
namespace flt {
|
||||
|
||||
|
||||
class Record;
|
||||
|
||||
class DataOutputStream : public std::ostream
|
||||
{
|
||||
public:
|
||||
explicit DataOutputStream( std::streambuf* sb, bool validate=false );
|
||||
|
||||
void writeInt8( const int8 val );
|
||||
void writeUInt8( const uint8 val );
|
||||
void writeInt16( const int16 val );
|
||||
void writeUInt16( const uint16 val );
|
||||
void writeInt32( const int32 val );
|
||||
void writeUInt32( const uint32 val );
|
||||
void writeFloat32( const float32 val );
|
||||
void writeFloat64( const float64 val );
|
||||
|
||||
// Write the entire string. If nullTerminate is true, write an additional NULL.
|
||||
// Always writes either 'val.size()' bytes or 'val.size()+1' bytes.
|
||||
void writeString( const std::string& val, bool nullTerminate=true );
|
||||
|
||||
// Never write more than 'size-1' bytes from 'val', and write 'fill' so that 'size' bytes total are written.
|
||||
// Always writes 'size' bytes..
|
||||
void writeString( const std::string& val, int size, char fill='\0' );
|
||||
|
||||
void writeID( const std::string& val );
|
||||
void writeColor32( const osg::Vec4f& val );
|
||||
void writeVec2f( const osg::Vec2f& val );
|
||||
void writeVec3f( const osg::Vec3f& val );
|
||||
void writeVec4f( const osg::Vec4f& val );
|
||||
void writeVec3d( const osg::Vec3d& val );
|
||||
|
||||
void writeFill( int sizeBytes, const char val='\0' );
|
||||
|
||||
protected:
|
||||
virtual std::ostream& vwrite( char_type* str, std::streamsize count );
|
||||
|
||||
bool _byteswap;
|
||||
bool _validate;
|
||||
|
||||
static char _null;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <osg/Geometry>
|
||||
#include <osgDB/ReaderWriter>
|
||||
|
||||
#include "types.h"
|
||||
#include "Types.h"
|
||||
#include "Record.h"
|
||||
#include "Pools.h"
|
||||
|
||||
|
||||
231
src/osgPlugins/OpenFlight/ExportOptions.cpp
Normal file
231
src/osgPlugins/OpenFlight/ExportOptions.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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 <osg/Notify>
|
||||
#include <osg/ProxyNode>
|
||||
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include "ExportOptions.h"
|
||||
//#include "DataOutputStream.h"
|
||||
//#include "FltNodeVisitor.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
|
||||
/** @name Valid Option Strings
|
||||
* This plugin supports the following \c Option string values.
|
||||
*/
|
||||
//@{
|
||||
/** Value: "version".
|
||||
* Specifies the version of the output OpenFlight file. Supported values
|
||||
* include 15.7, 15.8, and 16.1. Default is 16.1. Example:
|
||||
* "version=15.8".
|
||||
*/
|
||||
std::string ExportOptions::_versionOption( "version" );
|
||||
/** Value: "units".
|
||||
* Specifies the contents of the \c Units field of the OpenFliht header record.
|
||||
* Valid values include INCHES, FEET, METERS, KILOMETERS, and NATICAL_MILES.
|
||||
* Default is METERS. Example: "units=METERS".
|
||||
*/
|
||||
std::string ExportOptions::_unitsOption( "units" );
|
||||
/** Value: "validate".
|
||||
* If present in the Options string, the plugin does not write an OpenFlight file.
|
||||
* Instead, it returns an indication of the scene graph's suitability for
|
||||
* OpenFlight export.
|
||||
*/
|
||||
std::string ExportOptions::_validateOption( "validate" );
|
||||
/** Value: "tempDir".
|
||||
* Specifies the directory to use for creation of temporary files. If not
|
||||
* specified, the directory is taken from the file name. If the file doesn't
|
||||
* contain a path, the current working directory is used. Applications should
|
||||
* set this to the name of their app-specific temp directory. If the path
|
||||
* contains spaces, use double quotes to ensure correct parsing. Examples:
|
||||
* "tempDir=/tmp".
|
||||
* "tempDir=\"C:\\My Temp Dir\"".
|
||||
*/
|
||||
std::string ExportOptions::_tempDirOption( "tempDir" );
|
||||
/** Value: "lighting".
|
||||
* Specifies a default enable/disable state for lighting, for Nodes in the
|
||||
* exported scene graph that don't set it explicitly. By default, the
|
||||
* exporter assumes lighting is enabled (GL_LIGHTING ON). Set this to
|
||||
* either ON or OFF. Example:
|
||||
* "lighting=OFF".
|
||||
*/
|
||||
std::string ExportOptions::_lightingOption( "lighting" );
|
||||
/** Value: "stripTextureFilePath".
|
||||
* If present in the Options string, the exporter strips the path from
|
||||
* texture file names, and writes only the texure file name to the FLT
|
||||
* Texture Palette. By default, the exporter doesn't strip the path,
|
||||
* and the name written to the Texture Palette is taken directly from
|
||||
* the osg::Image object referenced by the osg::Texture2D StateAttribute.
|
||||
*/
|
||||
std::string ExportOptions::_stripTextureFilePathOption( "stripTextureFilePath" );
|
||||
//@}
|
||||
|
||||
|
||||
using namespace osgDB;
|
||||
|
||||
|
||||
const int ExportOptions::VERSION_15_7( 1570 );
|
||||
const int ExportOptions::VERSION_15_8( 1580 );
|
||||
const int ExportOptions::VERSION_16_1( 1610 );
|
||||
|
||||
|
||||
|
||||
ExportOptions::ExportOptions()
|
||||
: _version( VERSION_16_1 ),
|
||||
_units( METERS ),
|
||||
_validate( false ),
|
||||
_lightingDefault( true ),
|
||||
_stripTextureFilePath( false )
|
||||
{
|
||||
}
|
||||
|
||||
ExportOptions::ExportOptions( const osgDB::ReaderWriter::Options* opt )
|
||||
: _version( VERSION_16_1 ),
|
||||
_units( METERS ),
|
||||
_validate( false ),
|
||||
_lightingDefault( true )
|
||||
{
|
||||
if (opt)
|
||||
{
|
||||
const ExportOptions* fltOpt = dynamic_cast<const ExportOptions*>( opt );
|
||||
if (fltOpt)
|
||||
{
|
||||
_version = fltOpt->_version;
|
||||
_units = fltOpt->_units;
|
||||
_validate = fltOpt->_validate;
|
||||
_tempDir = fltOpt->_tempDir;
|
||||
_lightingDefault = fltOpt->_lightingDefault;
|
||||
}
|
||||
setOptionString( opt->getOptionString() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ExportOptions::parseOptionsString()
|
||||
{
|
||||
// Parse out the option string and store values directly in
|
||||
// ExportOptions member variables.
|
||||
|
||||
const std::string& str = getOptionString();
|
||||
if (str.empty())
|
||||
return;
|
||||
|
||||
std::string::size_type pos( 0 );
|
||||
while (pos != str.npos)
|
||||
{
|
||||
// Skip leading spaces.
|
||||
while ( (pos < str.length()) &&
|
||||
(str[pos] == ' ') )
|
||||
pos++;
|
||||
|
||||
// Get the next token
|
||||
std::string::size_type count = str.substr( pos ).find_first_of( " =" );
|
||||
std::string token = str.substr( pos, count );
|
||||
if (count == str.npos)
|
||||
pos = str.npos;
|
||||
else
|
||||
pos += (count+1);
|
||||
|
||||
// See if it's a Boolen/toggle
|
||||
if ( token == _validateOption )
|
||||
{
|
||||
osg::notify( osg::INFO ) << "fltexp: Found: " << token << std::endl;
|
||||
setValidateOnly( true );
|
||||
continue;
|
||||
}
|
||||
if ( token == _stripTextureFilePathOption )
|
||||
{
|
||||
osg::notify( osg::INFO ) << "fltexp: Found: " << token << std::endl;
|
||||
setStripTextureFilePath( true );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Not a Boolean/toggle. Must have a value.
|
||||
// Get the value of the token, which could be double-quoted.
|
||||
if( str[pos] == '"' )
|
||||
{
|
||||
++pos;
|
||||
count = str.substr( pos ).find_first_of( '"' );
|
||||
}
|
||||
else
|
||||
count = str.substr( pos ).find_first_of( ' ' );
|
||||
std::string value = str.substr( pos, count );
|
||||
if (count == str.npos)
|
||||
pos = str.npos;
|
||||
else
|
||||
pos += (count+1);
|
||||
|
||||
if (token == _versionOption)
|
||||
{
|
||||
osg::notify( osg::INFO ) << "fltexp: Token: " << token << ", Value: " << value << std::endl;
|
||||
int version( VERSION_16_1 );
|
||||
if( value == std::string( "15.7" ) )
|
||||
version = VERSION_15_7;
|
||||
else if( value == std::string( "15.8" ) )
|
||||
version = VERSION_15_8;
|
||||
else if( value != std::string( "16.1" ) )
|
||||
osg::notify( osg::WARN ) << "fltexp: Unsupported version: " << value << ". Defaulting to 16.1." << std::endl;
|
||||
setFlightFileVersionNumber( version );
|
||||
}
|
||||
else if (token == _unitsOption)
|
||||
{
|
||||
osg::notify( osg::INFO ) << "fltexp: Token: " << token << ", Value: " << value << std::endl;
|
||||
FlightUnits units( METERS );
|
||||
if( value == std::string( "KILOMETERS" ) )
|
||||
units = KILOMETERS;
|
||||
else if( value == std::string( "FEET" ) )
|
||||
units = FEET;
|
||||
else if( value == std::string( "INCHES" ) )
|
||||
units = INCHES;
|
||||
else if( value == std::string( "NAUTICAL_MILES" ) )
|
||||
units = NAUTICAL_MILES;
|
||||
else if( value != std::string( "METERS" ) )
|
||||
osg::notify( osg::WARN ) << "fltexp: Unsupported units: " << value << ". Defaulting to METERS." << std::endl;
|
||||
setFlightUnits( units );
|
||||
}
|
||||
else if (token == _tempDirOption)
|
||||
{
|
||||
osg::notify( osg::INFO ) << "fltexp: Token: " << token << ", Value: " << value << std::endl;
|
||||
setTempDir( value );
|
||||
}
|
||||
else if (token == _lightingOption)
|
||||
{
|
||||
osg::notify( osg::INFO ) << "fltexp: Token: " << token << ", Value: " << value << std::endl;
|
||||
bool lighting( true );
|
||||
if (value == std::string( "OFF" ) )
|
||||
lighting = false;
|
||||
else if (value != std::string( "ON" ) )
|
||||
osg::notify( osg::WARN ) << "fltexp: Unsupported lighting value: " << value << ". Defaulting to ON." << std::endl;
|
||||
setLightingDefault( lighting );
|
||||
}
|
||||
else
|
||||
osg::notify( osg::WARN ) << "fltexp: Bogus OptionString: " << token << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
104
src/osgPlugins/OpenFlight/ExportOptions.h
Normal file
104
src/osgPlugins/OpenFlight/ExportOptions.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.
|
||||
//
|
||||
|
||||
#ifndef __FLT_EXPORT_OPTIONS_H__
|
||||
#define __FLT_EXPORT_OPTIONS_H__ 1
|
||||
|
||||
#include "FltWriteResult.h"
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/Notify>
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
Options class for controlling export behavior.
|
||||
Features a parser for the Option string as well as getter
|
||||
methods for supported options.
|
||||
*/
|
||||
class ExportOptions : public osgDB::ReaderWriter::Options
|
||||
{
|
||||
public:
|
||||
ExportOptions( const Options* opt );
|
||||
ExportOptions();
|
||||
|
||||
static const int VERSION_15_7;
|
||||
static const int VERSION_15_8;
|
||||
static const int VERSION_16_1;
|
||||
|
||||
enum FlightUnits
|
||||
{
|
||||
METERS,
|
||||
KILOMETERS,
|
||||
FEET,
|
||||
INCHES,
|
||||
NAUTICAL_MILES
|
||||
};
|
||||
|
||||
void setFlightFileVersionNumber( int num ) { _version = num; }
|
||||
int getFlightFileVersionNumber() const { return _version; }
|
||||
|
||||
void setFlightUnits( FlightUnits units ) { _units = units; }
|
||||
FlightUnits getFlightUnits() const { return _units; }
|
||||
|
||||
void setValidateOnly( bool validate ) { _validate = validate; }
|
||||
bool getValidateOnly() const { return _validate; }
|
||||
|
||||
void setTempDir( const std::string& dir ) { _tempDir = dir; }
|
||||
std::string getTempDir() const { return _tempDir; }
|
||||
|
||||
void setLightingDefault( bool lighting ) { _lightingDefault = lighting; }
|
||||
bool getLightingDefault() const { return _lightingDefault; }
|
||||
|
||||
void setStripTextureFilePath( bool strip ) { _stripTextureFilePath = strip; }
|
||||
bool getStripTextureFilePath() const { return _stripTextureFilePath; }
|
||||
|
||||
FltWriteResult & getWriteResult() const { return( wr_ ); }
|
||||
|
||||
// Parse the OptionString and override values based on
|
||||
// what was set in the OptionString.
|
||||
void parseOptionsString();
|
||||
|
||||
protected:
|
||||
int _version;
|
||||
FlightUnits _units;
|
||||
bool _validate;
|
||||
std::string _tempDir;
|
||||
bool _lightingDefault;
|
||||
bool _stripTextureFilePath;
|
||||
|
||||
mutable FltWriteResult wr_;
|
||||
|
||||
static std::string _versionOption;
|
||||
static std::string _unitsOption;
|
||||
static std::string _validateOption;
|
||||
static std::string _tempDirOption;
|
||||
static std::string _lightingOption;
|
||||
static std::string _stripTextureFilePathOption;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* __OPEN_FLIGHT_WRITER_H__ */
|
||||
632
src/osgPlugins/OpenFlight/FltExportVisitor.cpp
Normal file
632
src/osgPlugins/OpenFlight/FltExportVisitor.cpp
Normal file
@@ -0,0 +1,632 @@
|
||||
/*
|
||||
* 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/Billboard>
|
||||
#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 )
|
||||
#endif
|
||||
|
||||
namespace 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 candon'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() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::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 Curently 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 );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::Sequence& node )
|
||||
{
|
||||
_firstNode = false;
|
||||
ScopedStatePushPop guard( this, node.getStateSet() );
|
||||
|
||||
writeSequence( node );
|
||||
writeMatrix( node.getUserData() );
|
||||
writeComment( node );
|
||||
writePushTraverseWritePop( node );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::Switch& node )
|
||||
{
|
||||
_firstNode = false;
|
||||
ScopedStatePushPop guard( this, node.getStateSet() );
|
||||
|
||||
writeSwitch( &node );
|
||||
|
||||
writeMatrix( node.getUserData() );
|
||||
writeComment( node );
|
||||
writePushTraverseWritePop( node );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::LOD& lodNode )
|
||||
{
|
||||
_firstNode = false;
|
||||
ScopedStatePushPop guard( this, lodNode.getStateSet() );
|
||||
|
||||
// LOD center - same for all chilrden
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::MatrixTransform& node )
|
||||
{
|
||||
// Importer reads a Matrix record and inserts a MatrixTransform above
|
||||
// the corrent 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;
|
||||
}
|
||||
|
||||
std::vector< osg::Referenced* > saveUserDataList;
|
||||
unsigned int idx;
|
||||
for( idx=0; idx<node.getNumChildren(); idx++ )
|
||||
{
|
||||
saveUserDataList.push_back( node.getChild( idx )->getUserData() );
|
||||
node.getChild( idx )->setUserData( m.get() );
|
||||
}
|
||||
|
||||
traverse( (osg::Node&)node );
|
||||
|
||||
// Restore saved UserData.
|
||||
unsigned int nd = node.getNumChildren();
|
||||
while (nd--)
|
||||
node.getChild( nd )->setUserData(
|
||||
saveUserDataList[ nd ] );
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::PositionAttitudeTransform& node )
|
||||
{
|
||||
_firstNode = false;
|
||||
ScopedStatePushPop guard( this, node.getStateSet() );
|
||||
|
||||
osg::ref_ptr<osg::RefMatrix> m = new osg::RefMatrix;
|
||||
|
||||
const osg::Vec3d& trans = node.getPosition();
|
||||
const osg::Quat& rot = node.getAttitude();
|
||||
m->set(osg::Matrix::translate(trans) * osg::Matrix::rotate(rot) );
|
||||
|
||||
std::vector< osg::Referenced* > saveUserDataList;
|
||||
unsigned int idx;
|
||||
for( idx=0; idx<node.getNumChildren(); idx++ )
|
||||
{
|
||||
saveUserDataList.push_back( node.getChild( idx )->getUserData() );
|
||||
node.getChild( idx )->setUserData( m.get() );
|
||||
}
|
||||
|
||||
traverse( (osg::Node&)node );
|
||||
|
||||
// Restore saved UserData.
|
||||
unsigned int nd = node.getNumChildren();
|
||||
while (nd--)
|
||||
node.getChild( nd )->setUserData(
|
||||
saveUserDataList[ nd ] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::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 );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::LightSource& node )
|
||||
{
|
||||
_firstNode = false;
|
||||
ScopedStatePushPop guard( this, node.getStateSet() );
|
||||
|
||||
writeLightSource( node );
|
||||
writeMatrix( node.getUserData() );
|
||||
writeComment( node );
|
||||
writePushTraverseWritePop( node );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::Geode& node )
|
||||
{
|
||||
_firstNode = false;
|
||||
ScopedStatePushPop guard( this, node.getStateSet() );
|
||||
|
||||
unsigned int idx;
|
||||
for (idx=0; idx<node.getNumDrawables(); idx++)
|
||||
{
|
||||
osg::Geometry* geom = node.getDrawable( idx )->asGeometry();
|
||||
if (!geom)
|
||||
continue;
|
||||
|
||||
ScopedStatePushPop drawableGuard( this, geom->getStateSet() );
|
||||
|
||||
// Write vertex array data out to vertex palette manager
|
||||
if (!isAllMesh( *geom ))
|
||||
// If at least one record will be a Face record, then we
|
||||
// need to write to the vertex pool.
|
||||
_vertexPalette->add( *geom );
|
||||
|
||||
unsigned int jdx;
|
||||
for (jdx=0; jdx < geom->getNumPrimitiveSets(); jdx++)
|
||||
{
|
||||
osg::PrimitiveSet* prim = geom->getPrimitiveSet( jdx );
|
||||
if (prim->getType() == osg::PrimitiveSet::DrawArraysPrimitiveType)
|
||||
handleDrawArrays( dynamic_cast<osg::DrawArrays*>( prim ), *geom, node );
|
||||
else if (prim->getType() == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType)
|
||||
handleDrawArrayLengths( dynamic_cast<osg::DrawArrayLengths*>( prim ), *geom, node );
|
||||
else if ( (prim->getType() == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) ||
|
||||
(prim->getType() == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) ||
|
||||
(prim->getType() == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) )
|
||||
handleDrawElements( dynamic_cast<osg::DrawElements*>( prim ), *geom, node );
|
||||
else
|
||||
{
|
||||
std::string warning( "fltexp: Unknown PrimitiveSet type." );
|
||||
osg::notify( osg::WARN ) << warning << std::endl;
|
||||
_fltOpt->getWriteResult().warn( warning );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Would traverse here if this node could have children.
|
||||
// traverse( (osg::Node&)node );
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::Billboard& node )
|
||||
{
|
||||
_firstNode = false;
|
||||
ScopedStatePushPop guard( this, node.getStateSet() );
|
||||
|
||||
// TBD -- Not yet implemented, but HIGH priority.
|
||||
// Face record -- HIGH
|
||||
// Mesh record -- HIGH
|
||||
|
||||
writeMatrix( node.getUserData() );
|
||||
writeComment( node );
|
||||
writePushTraverseWritePop( node );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::Node& node )
|
||||
{
|
||||
_firstNode = false;
|
||||
ScopedStatePushPop guard( this, node.getStateSet() );
|
||||
|
||||
osgSim::LightPointNode* lpn = dynamic_cast< osgSim::LightPointNode* >( &node );
|
||||
if (lpn)
|
||||
{
|
||||
writeLightPoint( lpn );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown Node. Warn and return.
|
||||
// (Note, if the base class of this Node was a Grouo, then apply(Group&)
|
||||
// would export a Group record then continue traversal. Because we are
|
||||
// a Node, there's no way to continue traversal, so just return.)
|
||||
std::string warning( "fltexp: Unknown Node in OpenFlight export." );
|
||||
osg::notify( osg::WARN ) << warning << std::endl;
|
||||
_fltOpt->getWriteResult().warn( warning );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::apply( osg::ProxyNode& node )
|
||||
{
|
||||
_firstNode = false;
|
||||
ScopedStatePushPop guard( this, node.getStateSet() );
|
||||
|
||||
writeExternalReference( node );
|
||||
writeMatrix( node.getUserData() );
|
||||
writeComment( node );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool
|
||||
FltExportVisitor::complete( const osg::Node& node )
|
||||
{
|
||||
// Always write final pop level
|
||||
writePop();
|
||||
// Done writing records, close the record data temp file.
|
||||
_recordsStr.close();
|
||||
|
||||
// Write OpenFlight file front matter: heqader, vertex palette, etc.
|
||||
writeHeader( node.getName() );
|
||||
|
||||
writeColorPalette();
|
||||
_materialPalette->write( _dos );
|
||||
_texturePalette->write( _dos );
|
||||
_lightSourcePalette->write( _dos );
|
||||
_vertexPalette->write( _dos );
|
||||
|
||||
// Write Comment ancillary record and specify the _dos DataOutputStream.
|
||||
writeComment( node, &_dos );
|
||||
|
||||
// Copy record data temp file into final OpenFlight file.
|
||||
// Yee-uck. TBD need better stream copy routine.
|
||||
char buf;
|
||||
std::ifstream recIn;
|
||||
recIn.open( _recordsTempName.c_str(), std::ios::in | std::ios::binary );
|
||||
while (!recIn.eof() )
|
||||
{
|
||||
recIn.read( &buf, 1 );
|
||||
if (recIn.good())
|
||||
_dos << buf;
|
||||
}
|
||||
recIn.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// StateSet stack support
|
||||
|
||||
void
|
||||
FltExportVisitor::pushStateSet( const osg::StateSet* rhs )
|
||||
{
|
||||
osg::StateSet* ss = new osg::StateSet( *( _stateSetStack.back().get() ) );
|
||||
|
||||
if (rhs)
|
||||
ss->merge( *rhs );
|
||||
|
||||
_stateSetStack.push_back( ss );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::popStateSet()
|
||||
{
|
||||
_stateSetStack.pop_back();
|
||||
}
|
||||
|
||||
const osg::StateSet*
|
||||
FltExportVisitor::getCurrentStateSet() const
|
||||
{
|
||||
return _stateSetStack.back().get();
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::clearStateSetStack()
|
||||
{
|
||||
_stateSetStack.clear();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::writeATTRFile( int unit, const osg::Texture2D* texture ) const
|
||||
{
|
||||
std::string name;
|
||||
if (_fltOpt->getStripTextureFilePath())
|
||||
name = osgDB::getSimpleFileName( texture->getImage()->getFileName() );
|
||||
else
|
||||
name = texture->getImage()->getFileName();
|
||||
name += std::string( ".attr" );
|
||||
|
||||
if ( osgDB::findDataFile( name ).empty() )
|
||||
{
|
||||
// No .attr file found. We should write one out.
|
||||
// Fill AttrData fields from current state.
|
||||
AttrData ad;
|
||||
|
||||
ad.texels_u = texture->getImage()->s();
|
||||
ad.texels_v = texture->getImage()->t();
|
||||
|
||||
switch( texture->getFilter( osg::Texture::MIN_FILTER ) )
|
||||
{
|
||||
case osg::Texture::LINEAR:
|
||||
ad.minFilterMode = AttrData::MIN_FILTER_BILINEAR;
|
||||
break;
|
||||
case osg::Texture::LINEAR_MIPMAP_LINEAR:
|
||||
ad.minFilterMode = AttrData::MIN_FILTER_MIPMAP_TRILINEAR;
|
||||
break;
|
||||
case osg::Texture::LINEAR_MIPMAP_NEAREST:
|
||||
ad.minFilterMode = AttrData::MIN_FILTER_MIPMAP_BILINEAR;
|
||||
break;
|
||||
case osg::Texture::NEAREST:
|
||||
ad.minFilterMode = AttrData::MIN_FILTER_POINT;
|
||||
break;
|
||||
case osg::Texture::NEAREST_MIPMAP_LINEAR:
|
||||
ad.minFilterMode = AttrData::MIN_FILTER_MIPMAP_LINEAR;
|
||||
break;
|
||||
case osg::Texture::NEAREST_MIPMAP_NEAREST:
|
||||
ad.minFilterMode = AttrData::MIN_FILTER_MIPMAP_POINT;
|
||||
break;
|
||||
default:
|
||||
ad.minFilterMode = AttrData::MIN_FILTER_MIPMAP_TRILINEAR;
|
||||
break;
|
||||
}
|
||||
switch( texture->getFilter( osg::Texture::MAG_FILTER ) )
|
||||
{
|
||||
case osg::Texture::NEAREST:
|
||||
ad.magFilterMode = AttrData::MAG_FILTER_POINT;
|
||||
break;
|
||||
default:
|
||||
ad.magFilterMode = AttrData::MAG_FILTER_BILINEAR;
|
||||
break;
|
||||
}
|
||||
|
||||
// Repeat and Clamp
|
||||
switch( texture->getWrap( osg::Texture::WRAP_S ) )
|
||||
{
|
||||
case osg::Texture::CLAMP:
|
||||
case osg::Texture::CLAMP_TO_EDGE:
|
||||
case osg::Texture::CLAMP_TO_BORDER:
|
||||
ad.wrapMode_u = AttrData::WRAP_CLAMP;
|
||||
break;
|
||||
case osg::Texture::REPEAT:
|
||||
default:
|
||||
ad.wrapMode_u = AttrData::WRAP_REPEAT;
|
||||
break;
|
||||
case osg::Texture::MIRROR:
|
||||
if (_fltOpt->getFlightFileVersionNumber() >= 1610)
|
||||
ad.wrapMode_u = AttrData::WRAP_MIRRORED_REPEAT;
|
||||
else
|
||||
ad.wrapMode_u = AttrData::WRAP_REPEAT;
|
||||
break;
|
||||
}
|
||||
switch( texture->getWrap( osg::Texture::WRAP_T ) )
|
||||
{
|
||||
case osg::Texture::CLAMP:
|
||||
case osg::Texture::CLAMP_TO_EDGE:
|
||||
case osg::Texture::CLAMP_TO_BORDER:
|
||||
ad.wrapMode_v = AttrData::WRAP_CLAMP;
|
||||
break;
|
||||
case osg::Texture::REPEAT:
|
||||
default:
|
||||
ad.wrapMode_v = AttrData::WRAP_REPEAT;
|
||||
break;
|
||||
case osg::Texture::MIRROR:
|
||||
if (_fltOpt->getFlightFileVersionNumber() >= 1610)
|
||||
ad.wrapMode_v = AttrData::WRAP_MIRRORED_REPEAT;
|
||||
else
|
||||
ad.wrapMode_v = AttrData::WRAP_REPEAT;
|
||||
break;
|
||||
}
|
||||
|
||||
const osg::StateSet* ss = getCurrentStateSet();
|
||||
const osg::TexEnv* texenv = dynamic_cast<const osg::TexEnv*>(
|
||||
ss->getTextureAttribute( unit, osg::StateAttribute::TEXENV ) );
|
||||
switch( texenv->getMode())
|
||||
{
|
||||
case osg::TexEnv::DECAL:
|
||||
ad.texEnvMode = AttrData::TEXENV_DECAL;
|
||||
break;
|
||||
case osg::TexEnv::MODULATE:
|
||||
default:
|
||||
ad.texEnvMode = AttrData::TEXENV_MODULATE;
|
||||
break;
|
||||
case osg::TexEnv::BLEND:
|
||||
ad.texEnvMode = AttrData::TEXENV_BLEND;
|
||||
break;
|
||||
case osg::TexEnv::REPLACE:
|
||||
ad.texEnvMode = AttrData::TEXENV_COLOR;
|
||||
break;
|
||||
case osg::TexEnv::ADD:
|
||||
ad.texEnvMode = AttrData::TEXENV_ADD;
|
||||
break;
|
||||
}
|
||||
|
||||
osgDB::writeObjectFile( ad, name, _fltOpt.get() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
261
src/osgPlugins/OpenFlight/FltExportVisitor.h
Normal file
261
src/osgPlugins/OpenFlight/FltExportVisitor.h
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* 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.
|
||||
//
|
||||
|
||||
#ifndef __FLTEXP_FLT_EXPORT_VISITOR_H__
|
||||
#define __FLTEXP_FLT_EXPORT_VISITOR_H__ 1
|
||||
|
||||
#include <osg/NodeVisitor>
|
||||
#include "ExportOptions.h"
|
||||
#include "Types.h"
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
namespace osg {
|
||||
class DrawArrays;
|
||||
class DrawArrayLengths;
|
||||
class DrawElements;
|
||||
class Geometry;
|
||||
class StateSet;
|
||||
class Switch;
|
||||
class Material;
|
||||
class Texture2D;
|
||||
}
|
||||
namespace osgSim {
|
||||
class DOFTransform;
|
||||
class MultiSwitch;
|
||||
class LightPointNode;
|
||||
class ObjectRecordData;
|
||||
}
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
class ExportOptions;
|
||||
class DataOutputStream;
|
||||
class MaterialPaletteManager;
|
||||
class TexturePaletteManager;
|
||||
class VertexPaletteManager;
|
||||
class LightSourcePaletteManager;
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
The main NodeVisitor for walking the scene graph during export.
|
||||
A collection of apply() methods is in FltExportVisitor.cpp.
|
||||
The apply() methods call several other methods for writing
|
||||
specific FLT record types, most of which are in exp*.cpp.
|
||||
*/
|
||||
class FltExportVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
FltExportVisitor( DataOutputStream* dos, ExportOptions* fltOpt );
|
||||
~FltExportVisitor( );
|
||||
|
||||
bool complete( const osg::Node& node );
|
||||
|
||||
virtual void apply( osg::Group& node );
|
||||
virtual void apply( osg::Sequence& node );
|
||||
virtual void apply( osg::Switch& node );
|
||||
virtual void apply( osg::LOD& node );
|
||||
virtual void apply( osg::MatrixTransform& node );
|
||||
virtual void apply( osg::PositionAttitudeTransform& node );
|
||||
virtual void apply( osg::Transform& node );
|
||||
virtual void apply( osg::LightSource& node );
|
||||
virtual void apply( osg::Geode& node );
|
||||
virtual void apply( osg::Billboard& node );
|
||||
virtual void apply( osg::Node& node );
|
||||
virtual void apply( osg::ProxyNode& node );
|
||||
|
||||
|
||||
|
||||
// Primary records
|
||||
void writeHeader( const std::string& headerName );
|
||||
void writeGroup( const osg::Group& node );
|
||||
void writeGroup( const osg::Group& group,
|
||||
int32 flags,
|
||||
int32 loopCount,
|
||||
float32 loopDuration,
|
||||
float32 lastFrameDuration);
|
||||
void writeSequence( const osg::Sequence& node );
|
||||
void writeObject( const osg::Group& node, osgSim::ObjectRecordData* ord );
|
||||
void writeDegreeOfFreedom( const osgSim::DOFTransform* dof );
|
||||
void writeExternalReference( const osg::ProxyNode& node );
|
||||
void writeLevelOfDetail( const osg::LOD& lod, const osg::Vec3d& center,
|
||||
double switchInDist, double switchOutDist);
|
||||
void writeLightSource( const osg::LightSource& ls );
|
||||
void writeSwitch( const osgSim::MultiSwitch* ms );
|
||||
void writeSwitch( const osg::Switch* ms );
|
||||
void writeLightPoint( const osgSim::LightPointNode* lpn );
|
||||
|
||||
// Ancillary records
|
||||
void writeComment( const osg::Node& node, DataOutputStream* dos=NULL );
|
||||
void writeLongID( const std::string& id, DataOutputStream* dos=NULL );
|
||||
void writeMatrix( const osg::Referenced* ref );
|
||||
void writeContinuationRecord( const unsigned short length );
|
||||
|
||||
// Control records
|
||||
void writePush();
|
||||
void writePop();
|
||||
void writePushSubface();
|
||||
void writePopSubface();
|
||||
|
||||
// Helper routine for traversing a pushed subtree
|
||||
void writePushTraverseWritePop(osg::Node& node)
|
||||
{
|
||||
writePush();
|
||||
traverse(node);
|
||||
writePop();
|
||||
}
|
||||
|
||||
// Geometry records
|
||||
void writeFace( const osg::Geode& geode, const osg::Geometry& geom, GLenum mode );
|
||||
void writeMesh( const osg::Geode& geode, const osg::Geometry& geom, GLenum mode );
|
||||
int writeVertexList( int first, unsigned int count );
|
||||
int writeVertexList( const std::vector<unsigned int>& indices, unsigned int count );
|
||||
void writeMeshPrimitive( const std::vector<unsigned int>& indices, GLenum mode );
|
||||
void writeLocalVertexPool( const osg::Geometry& geom, GLenum mode );
|
||||
void writeMultitexture( const osg::Geometry& geom );
|
||||
void writeUVList( int numVerts, const osg::Geometry& geom );
|
||||
|
||||
// Light Point records
|
||||
void writeLightPoint();
|
||||
|
||||
// Exporter doesn't currently support color palette; write a dummy in its place to
|
||||
// support loaders that require it.
|
||||
void writeColorPalette();
|
||||
|
||||
// StateSet stack support
|
||||
void pushStateSet( const osg::StateSet* rhs );
|
||||
void popStateSet();
|
||||
const osg::StateSet* getCurrentStateSet() const;
|
||||
void clearStateSetStack();
|
||||
|
||||
// Write a .attr file if none exists in the data file path.
|
||||
void writeATTRFile( int unit, const osg::Texture2D* texture ) const;
|
||||
|
||||
|
||||
private:
|
||||
// Methods for handling different primitive set types.
|
||||
// These are defined in expGeometryRecords.cpp.
|
||||
void handleDrawArrays( const osg::DrawArrays* da, const osg::Geometry& geom, const osg::Geode& geode );
|
||||
void handleDrawArrayLengths( const osg::DrawArrayLengths* dal, const osg::Geometry& geom, const osg::Geode& geode );
|
||||
void handleDrawElements( const osg::DrawElements* de, const osg::Geometry& geom, const osg::Geode& geode );
|
||||
|
||||
bool isLit( const osg::Geometry& geom ) const;
|
||||
bool isTextured( int unit, const osg::Geometry& geom ) const;
|
||||
bool isAllMesh( const osg::Geometry& geom ) const;
|
||||
|
||||
osg::ref_ptr< ExportOptions > _fltOpt;
|
||||
|
||||
// _dos is the primary output stream, produces the actual .flt file.
|
||||
DataOutputStream& _dos;
|
||||
|
||||
// _records is a temp file for most records. After the Header and palette
|
||||
// records are written to _dos, _records is copied onto _dos.
|
||||
std::ofstream _recordsStr;
|
||||
DataOutputStream* _records;
|
||||
std::string _recordsTempName;
|
||||
|
||||
// Track state changes during a scene graph walk.
|
||||
typedef std::vector< osg::ref_ptr<osg::StateSet> > StateSetStack;
|
||||
StateSetStack _stateSetStack;
|
||||
|
||||
std::auto_ptr<MaterialPaletteManager> _materialPalette;
|
||||
std::auto_ptr<TexturePaletteManager> _texturePalette;
|
||||
std::auto_ptr<LightSourcePaletteManager> _lightSourcePalette;
|
||||
std::auto_ptr<VertexPaletteManager> _vertexPalette;
|
||||
|
||||
// Used to avoid duplicate Header/Group records at top of output FLT file.
|
||||
bool _firstNode;
|
||||
};
|
||||
|
||||
/*!
|
||||
Helper class to ensure symmetrical state push/pop behavior.
|
||||
*/
|
||||
class ScopedStatePushPop
|
||||
{
|
||||
public:
|
||||
ScopedStatePushPop ( FltExportVisitor * fnv, const osg::StateSet *ss ) :
|
||||
fnv_( fnv )
|
||||
{
|
||||
fnv_->pushStateSet( ss );
|
||||
}
|
||||
virtual ~ScopedStatePushPop ()
|
||||
{
|
||||
fnv_->popStateSet();
|
||||
}
|
||||
|
||||
private:
|
||||
FltExportVisitor * fnv_;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
Automatically handles writing the LongID ancillary record.
|
||||
*/
|
||||
struct IdHelper
|
||||
{
|
||||
IdHelper(flt::FltExportVisitor& v, const std::string& id)
|
||||
: v_(v), id_(id), dos_(NULL)
|
||||
{ }
|
||||
|
||||
// Write an ancillary ID record upon destruction if name is too long
|
||||
~IdHelper()
|
||||
{
|
||||
if (id_.length() > 8)
|
||||
v_.writeLongID(id_,dos_);
|
||||
}
|
||||
|
||||
// Allow implicit conversion to the abbreviated name string
|
||||
operator const std::string() const
|
||||
{
|
||||
return( (id_.length() > 8) ? id_.substr(0, 8) : id_ );
|
||||
}
|
||||
|
||||
flt::FltExportVisitor& v_;
|
||||
const std::string id_;
|
||||
DataOutputStream* dos_;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
Supports wrapping subfaces with push/pop records.
|
||||
*/
|
||||
struct SubfaceHelper
|
||||
{
|
||||
SubfaceHelper(flt::FltExportVisitor& v, const osg::StateSet* ss )
|
||||
: v_(v)
|
||||
{
|
||||
_polygonOffsetOn = ( ss->getMode( GL_POLYGON_OFFSET_FILL ) == osg::StateAttribute::ON );
|
||||
if (_polygonOffsetOn)
|
||||
v_.writePushSubface();
|
||||
}
|
||||
|
||||
~SubfaceHelper()
|
||||
{
|
||||
if (_polygonOffsetOn)
|
||||
v_.writePopSubface();
|
||||
}
|
||||
|
||||
flt::FltExportVisitor& v_;
|
||||
bool _polygonOffsetOn;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
73
src/osgPlugins/OpenFlight/FltWriteResult.h
Normal file
73
src/osgPlugins/OpenFlight/FltWriteResult.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
//
|
||||
|
||||
#ifndef __FLT_WRITE_RESULT_H__
|
||||
#define __FLT_WRITE_RESULT_H__ 1
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/Notify>
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
Custom WriteResult to support proxy/validation ("validate" Option).
|
||||
If the application is able to #include this header and obtain the Writeresult
|
||||
from osgDB, then the app can query this class for warning or error
|
||||
conditions due to scene graph incompatibility with FLT.
|
||||
*/
|
||||
class FltWriteResult : public osgDB::ReaderWriter::WriteResult
|
||||
{
|
||||
public:
|
||||
FltWriteResult( WriteResult::WriteStatus status=WriteResult::FILE_NOT_HANDLED )
|
||||
: WriteResult( status )
|
||||
{}
|
||||
|
||||
void setNumErrors( int n );
|
||||
int getNumErrors() const;
|
||||
|
||||
void setNumWarnings( int n );
|
||||
int getNumWarnings() const;
|
||||
|
||||
typedef std::pair< int, std::string > MessagePair;
|
||||
typedef std::vector< MessagePair > MessageVector;
|
||||
|
||||
void warn( const std::string &ss )
|
||||
{
|
||||
messages_.push_back( std::make_pair( osg::WARN, ss ) );
|
||||
}
|
||||
|
||||
void error( const std::string &ss )
|
||||
{
|
||||
messages_.push_back( std::make_pair( osg::FATAL, ss ) );
|
||||
}
|
||||
|
||||
protected:
|
||||
MessageVector messages_;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif /* __OPEN_FLIGHT_WRITER_H__ */
|
||||
116
src/osgPlugins/OpenFlight/LightSourcePaletteManager.cpp
Normal file
116
src/osgPlugins/OpenFlight/LightSourcePaletteManager.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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 "LightSourcePaletteManager.h"
|
||||
#include "DataOutputStream.h"
|
||||
#include "Opcodes.h"
|
||||
#include <osg/Notify>
|
||||
#include <osg/Light>
|
||||
#include <osg/Vec4f>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
LightSourcePaletteManager::LightSourcePaletteManager( ExportOptions& fltOpt )
|
||||
: _fltOpt( fltOpt ),
|
||||
_currIndex( -1 )
|
||||
{
|
||||
// TODO: Pay attention to the version here(?)
|
||||
}
|
||||
|
||||
|
||||
int LightSourcePaletteManager::add(osg::Light const* light)
|
||||
{
|
||||
int index = -1;
|
||||
if (light == NULL) return -1;
|
||||
|
||||
|
||||
// If this light has already been cached, set 'index' to the cached value
|
||||
LightPalette::const_iterator it = _lightPalette.find(light);
|
||||
if ( it != _lightPalette.end() )
|
||||
{
|
||||
index = it->second.Index;
|
||||
}
|
||||
|
||||
// New light? Add it to the cache...
|
||||
else
|
||||
{
|
||||
index = ++_currIndex;
|
||||
_lightPalette.insert(std::make_pair(light,
|
||||
LightRecord(light, index) ) );
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
LightSourcePaletteManager::write( DataOutputStream& dos ) const
|
||||
{
|
||||
using osg::Vec4f;
|
||||
|
||||
static int const INFINITE_LIGHT = 0;
|
||||
static int const LOCAL_LIGHT = 1;
|
||||
static int const SPOT_LIGHT = 2;
|
||||
|
||||
LightPalette::const_iterator it = _lightPalette.begin();
|
||||
for ( ; it != _lightPalette.end(); ++it)
|
||||
{
|
||||
LightRecord m = it->second;
|
||||
|
||||
static char lightName[64];
|
||||
sprintf(lightName, "Light%02d", m.Light->getLightNum() );
|
||||
|
||||
int lightType = INFINITE_LIGHT;
|
||||
Vec4f const& lightPos = m.Light->getPosition();
|
||||
if (lightPos.w() != 0)
|
||||
{
|
||||
if (m.Light->getSpotCutoff() < 180)
|
||||
lightType = SPOT_LIGHT;
|
||||
else
|
||||
lightType = LOCAL_LIGHT;
|
||||
}
|
||||
|
||||
dos.writeInt16( (int16) LIGHT_SOURCE_PALETTE_OP );
|
||||
dos.writeInt16( 240 );
|
||||
dos.writeInt32( m.Index );
|
||||
dos.writeFill(2*4, '\0'); // Reserved
|
||||
dos.writeString( lightName, 20 );
|
||||
dos.writeFill(4, '\0'); // Reserved
|
||||
|
||||
dos.writeVec4f(m.Light->getAmbient() );
|
||||
dos.writeVec4f(m.Light->getDiffuse() );
|
||||
dos.writeVec4f(m.Light->getSpecular() );
|
||||
dos.writeInt32(lightType);
|
||||
dos.writeFill(4*10, '\0'); // Reserved
|
||||
dos.writeFloat32(m.Light->getSpotExponent() );
|
||||
dos.writeFloat32(m.Light->getSpotCutoff() );
|
||||
dos.writeFloat32(0); // Yaw (N/A)
|
||||
dos.writeFloat32(0); // Pitch (N/A)
|
||||
dos.writeFloat32(m.Light->getConstantAttenuation() );
|
||||
dos.writeFloat32(m.Light->getLinearAttenuation() );
|
||||
dos.writeFloat32(m.Light->getQuadraticAttenuation() );
|
||||
dos.writeInt32(0); // Modeling flag (N/A)
|
||||
dos.writeFill(4*19, '\0'); // Reserved
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // End namespace fltexp
|
||||
74
src/osgPlugins/OpenFlight/LightSourcePaletteManager.h
Normal file
74
src/osgPlugins/OpenFlight/LightSourcePaletteManager.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.
|
||||
//
|
||||
|
||||
#ifndef __FLTEXP_LIGHT_SOURCE_PALETTE_MANAGER_H__
|
||||
#define __FLTEXP_LIGHT_SOURCE_PALETTE_MANAGER_H__ 1
|
||||
|
||||
#include "ExportOptions.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace osg {
|
||||
class Light;
|
||||
}
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
class DataOutputStream;
|
||||
|
||||
|
||||
class LightSourcePaletteManager
|
||||
{
|
||||
public:
|
||||
LightSourcePaletteManager( ExportOptions& fltOpt );
|
||||
|
||||
// Add a light to the palette and auto-assign it the next available index
|
||||
int add(osg::Light const* light);
|
||||
|
||||
// Write the light palette records out to a DataOutputStream
|
||||
void write( DataOutputStream& dos ) const;
|
||||
|
||||
|
||||
private:
|
||||
int _currIndex;
|
||||
|
||||
// Helper struct to hold light palette records
|
||||
struct LightRecord
|
||||
{
|
||||
LightRecord(osg::Light const* light, int i)
|
||||
: Light(light)
|
||||
, Index(i) { }
|
||||
|
||||
osg::Light const* Light;
|
||||
int Index;
|
||||
|
||||
};
|
||||
|
||||
// Map to allow lookups by Light pointer
|
||||
typedef std::map<osg::Light const*, LightRecord> LightPalette;
|
||||
LightPalette _lightPalette;
|
||||
|
||||
|
||||
ExportOptions& _fltOpt;
|
||||
};
|
||||
|
||||
|
||||
} // End namespace fltexp
|
||||
|
||||
#endif // !__FLTEXP_LIGHT_SOURCE_PALETTE_MANAGER_H__
|
||||
120
src/osgPlugins/OpenFlight/MaterialPaletteManager.cpp
Normal file
120
src/osgPlugins/OpenFlight/MaterialPaletteManager.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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 "MaterialPaletteManager.h"
|
||||
#include "DataOutputStream.h"
|
||||
#include "Opcodes.h"
|
||||
#include <osg/Notify>
|
||||
#include <osg/Material>
|
||||
#include <osg/Vec4f>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
MaterialPaletteManager::MaterialPaletteManager( ExportOptions& fltOpt )
|
||||
: _fltOpt( fltOpt ),
|
||||
_currIndex( -1 )
|
||||
{
|
||||
// TODO: Pay attention to the version here(?)
|
||||
}
|
||||
|
||||
|
||||
int MaterialPaletteManager::add(osg::Material const* material)
|
||||
{
|
||||
int index = -1;
|
||||
if (material == NULL) return -1;
|
||||
|
||||
|
||||
// If this material has already been cached, set 'index' to the cached value
|
||||
MaterialPalette::const_iterator it = _materialPalette.find(material);
|
||||
if ( it != _materialPalette.end() )
|
||||
{
|
||||
index = it->second.Index;
|
||||
}
|
||||
|
||||
// New material? Add it to the cache...
|
||||
else
|
||||
{
|
||||
index = ++_currIndex;
|
||||
_materialPalette.insert(std::make_pair(material,
|
||||
MaterialRecord(material, index) ) );
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
MaterialPaletteManager::write( DataOutputStream& dos ) const
|
||||
{
|
||||
using osg::Vec4f;
|
||||
|
||||
MaterialPalette::const_iterator it = _materialPalette.begin();
|
||||
for ( ; it != _materialPalette.end(); ++it)
|
||||
{
|
||||
MaterialRecord m = it->second;
|
||||
Vec4f const& ambient = m.Material->getAmbient(osg::Material::FRONT);
|
||||
Vec4f const& diffuse = m.Material->getDiffuse(osg::Material::FRONT);
|
||||
Vec4f const& specular = m.Material->getSpecular(osg::Material::FRONT);
|
||||
Vec4f const& emissive = m.Material->getEmission(osg::Material::FRONT);
|
||||
float shininess = m.Material->getShininess(osg::Material::FRONT);
|
||||
|
||||
dos.writeInt16( (int16) MATERIAL_PALETTE_OP );
|
||||
dos.writeInt16( 84 ); // Length - FIXME: hard-code/FLT version?
|
||||
dos.writeInt32( m.Index );
|
||||
std::string fakename = "SOMEFAKENAME";
|
||||
dos.writeString( fakename, 12 ); // Name - FIXME: put a 'real' name here?
|
||||
dos.writeInt32( 0 ); // Flags
|
||||
dos.writeFloat32(ambient.r() );
|
||||
dos.writeFloat32(ambient.g() );
|
||||
dos.writeFloat32(ambient.b() );
|
||||
dos.writeFloat32(diffuse.r() );
|
||||
dos.writeFloat32(diffuse.g() );
|
||||
dos.writeFloat32(diffuse.b() );
|
||||
dos.writeFloat32(specular.r() );
|
||||
dos.writeFloat32(specular.g() );
|
||||
dos.writeFloat32(specular.b() );
|
||||
dos.writeFloat32(emissive.r() );
|
||||
dos.writeFloat32(emissive.g() );
|
||||
dos.writeFloat32(emissive.b() );
|
||||
dos.writeFloat32(shininess);
|
||||
dos.writeFloat32(1.0f); // Alpha - unused
|
||||
dos.writeFloat32(1.0f); // 'Reserved' - unused
|
||||
|
||||
if (m.Material->getAmbientFrontAndBack() == false ||
|
||||
m.Material->getDiffuseFrontAndBack() == false ||
|
||||
m.Material->getSpecularFrontAndBack() == false ||
|
||||
m.Material->getEmissionFrontAndBack() == false ||
|
||||
m.Material->getShininessFrontAndBack() == false )
|
||||
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Front and back faces of material \'"
|
||||
<< fakename
|
||||
<< "\' have different material"
|
||||
<< "properties - OpenFlt does not support this..."
|
||||
<< std::endl;
|
||||
_fltOpt.getWriteResult().warn( ss.str() );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // End namespace fltexp
|
||||
72
src/osgPlugins/OpenFlight/MaterialPaletteManager.h
Normal file
72
src/osgPlugins/OpenFlight/MaterialPaletteManager.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.
|
||||
//
|
||||
|
||||
#ifndef __FLTEXP_MATERIAL_PALETTE_MANAGER_H__
|
||||
#define __FLTEXP_MATERIAL_PALETTE_MANAGER_H__ 1
|
||||
|
||||
#include "ExportOptions.h"
|
||||
#include <set>
|
||||
|
||||
namespace osg {
|
||||
class Material;
|
||||
}
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
class DataOutputStream;
|
||||
|
||||
|
||||
class MaterialPaletteManager
|
||||
{
|
||||
public:
|
||||
MaterialPaletteManager( ExportOptions& fltOpt );
|
||||
|
||||
// Add a material to the palette and auto-assign it the next available index
|
||||
int add(osg::Material const* material);
|
||||
|
||||
// Write the material palette records out to a DataOutputStream
|
||||
void write( DataOutputStream& dos ) const;
|
||||
|
||||
|
||||
private:
|
||||
int _currIndex;
|
||||
|
||||
// Helper struct to hold material palette records
|
||||
struct MaterialRecord
|
||||
{
|
||||
MaterialRecord(osg::Material const* m, int i)
|
||||
: Material(m)
|
||||
, Index(i) { }
|
||||
|
||||
osg::Material const* Material;
|
||||
int Index;
|
||||
|
||||
};
|
||||
|
||||
// Map to allow lookups by Material pointer, and permit sorting by index
|
||||
typedef std::map<osg::Material const*, MaterialRecord> MaterialPalette;
|
||||
MaterialPalette _materialPalette;
|
||||
|
||||
ExportOptions& _fltOpt;
|
||||
};
|
||||
|
||||
|
||||
} // End namespace fltexp
|
||||
|
||||
#endif // !FLTEXP_MATERIAL_PALETTE_MANAGER_H
|
||||
136
src/osgPlugins/OpenFlight/Opcodes.h
Normal file
136
src/osgPlugins/OpenFlight/Opcodes.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// OpenFlight<68> loader for OpenSceneGraph
|
||||
//
|
||||
// Copyright (C) 2005-2007 Brede Johansen
|
||||
//
|
||||
|
||||
#ifndef FLT_OPCODES_H
|
||||
#define FLT_OPCODES_H
|
||||
|
||||
namespace flt {
|
||||
|
||||
enum Opcodes
|
||||
{
|
||||
UNKNOWN_OP = 0,
|
||||
HEADER_OP = 1,
|
||||
GROUP_OP = 2,
|
||||
OLD_LOD_OP = 3,
|
||||
OBJECT_OP = 4,
|
||||
FACE_OP = 5,
|
||||
OLD_ABSOLUTE_VERTEX_OP = 7,
|
||||
OLD_SHADED_VERTEX_OP = 8,
|
||||
OLD_NORMAL_VERTEX_OP = 9,
|
||||
PUSH_LEVEL_OP = 10,
|
||||
POP_LEVEL_OP = 11,
|
||||
DOF_OP = 14,
|
||||
PUSH_SUBFACE_OP = 19,
|
||||
POP_SUBFACE_OP = 20,
|
||||
PUSH_EXTENSION_OP = 21,
|
||||
POP_EXTENSION_OP = 22,
|
||||
CONTINUATION_OP = 23,
|
||||
COMMENT_OP = 31,
|
||||
COLOR_PALETTE_OP = 32,
|
||||
LONG_ID_OP = 33,
|
||||
OLD_TRANSLATE_OP = 40,
|
||||
OLD_ROTATE_ABOUT_POINT_OP = 41,
|
||||
OLD_ROTATE_ABOUT_EDGE_OP = 42,
|
||||
OLD_SCALE_OP = 43,
|
||||
OLD_TRANSLATE2_OP = 44,
|
||||
OLD_NONUNIFORM_SCALE_OP = 45,
|
||||
OLD_ROTATE_ABOUT_POINT2_OP = 46,
|
||||
OLD_ROTATE_SCALE_TO_POINT_OP = 47,
|
||||
OLD_PUT_TRANSFORM_OP = 48,
|
||||
MATRIX_OP = 49,
|
||||
VECTOR_OP = 50,
|
||||
OLD_BOUNDING_BOX_OP = 51,
|
||||
MULTITEXTURE_OP = 52,
|
||||
UV_LIST_OP = 53,
|
||||
BINARY_SEPARATING_PLANE_OP = 55,
|
||||
REPLICATE_OP = 60,
|
||||
INSTANCE_REFERENCE_OP = 61,
|
||||
INSTANCE_DEFINITION_OP = 62,
|
||||
EXTERNAL_REFERENCE_OP = 63,
|
||||
TEXTURE_PALETTE_OP = 64,
|
||||
OLD_EYEPOINT_PALETTE_OP = 65,
|
||||
OLD_MATERIAL_PALETTE_OP = 66,
|
||||
VERTEX_PALETTE_OP = 67,
|
||||
VERTEX_C_OP = 68,
|
||||
VERTEX_CN_OP = 69,
|
||||
VERTEX_CNT_OP = 70,
|
||||
VERTEX_CT_OP = 71,
|
||||
VERTEX_LIST_OP = 72,
|
||||
LOD_OP = 73,
|
||||
BOUNDING_BOX_OP = 74,
|
||||
ROTATE_ABOUT_EDGE_OP = 76,
|
||||
SCALE_OP = 77,
|
||||
TRANSLATE_OP = 78,
|
||||
NONUNIFORM_SCALE_OP = 79,
|
||||
ROTATE_ABOUT_POINT_OP = 80,
|
||||
ROTATE_SCALE_TO_POINT_OP = 81,
|
||||
PUT_TRANSFORM_OP = 82,
|
||||
EYEPOINT_AND_TRACKPLANE_PALETTE_OP = 83,
|
||||
MESH_OP = 84,
|
||||
LOCAL_VERTEX_POOL_OP = 85,
|
||||
MESH_PRIMITIVE_OP = 86,
|
||||
ROAD_SEGMENT_OP = 87,
|
||||
ROAD_ZONE_OP = 88,
|
||||
MORPH_VERTEX_LIST_OP = 89,
|
||||
LINKAGE_PALETTE_OP = 90,
|
||||
SOUND_OP = 91,
|
||||
ROAD_PATH_OP = 92,
|
||||
SOUND_PALETTE_OP = 93,
|
||||
GENERAL_MATRIX_OP = 94,
|
||||
TEXT_OP = 95,
|
||||
SWITCH_OP = 96,
|
||||
LINE_STYLE_PALETTE_OP = 97,
|
||||
CLIP_REGION_OP = 98,
|
||||
EXTENSION_OP = 100,
|
||||
LIGHT_SOURCE_OP = 101,
|
||||
LIGHT_SOURCE_PALETTE_OP = 102,
|
||||
BOUNDING_SPHERE_OP = 105,
|
||||
BOUNDING_CYLINDER_OP = 106,
|
||||
BOUNDING_CONVEX_HULL_OP = 107,
|
||||
BOUNDING_VOLUME_CENTER_OP = 108,
|
||||
BOUNDING_VOLUME_ORIENTATION_OP = 109,
|
||||
HISTOGRAM_BOUNDING_VOLUME_OP = 110,
|
||||
LIGHT_POINT_OP = 111,
|
||||
TEXTURE_MAPPING_PALETTE_OP = 112,
|
||||
MATERIAL_PALETTE_OP = 113,
|
||||
NAME_TABLE_OP = 114,
|
||||
CAT_OP = 115,
|
||||
CAT_DATA_OP = 116,
|
||||
BOUNDING_HISTOGRAM = 119,
|
||||
PUSH_ATTRIBUTE_OP = 122,
|
||||
POP_ATTRIBUTE_OP = 123,
|
||||
ADAPTIVE_ATTRIBUTE_OP = 125,
|
||||
CURVE_NODE_OP = 126,
|
||||
ROAD_CONSTRUCTION_OP = 127,
|
||||
LIGHT_POINT_APPEARANCE_PALETTE_OP = 128,
|
||||
LIGHT_POINT_ANIMATION_PALETTE_OP = 129,
|
||||
INDEXED_LIGHT_POINT_OP = 130,
|
||||
LIGHT_POINT_SYSTEM_OP = 131,
|
||||
INDEXED_STRING_OP = 132,
|
||||
SHADER_PALETTE_OP = 133
|
||||
};
|
||||
|
||||
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <osg/Material>
|
||||
#include <osg/Light>
|
||||
#include <osg/Program>
|
||||
#include "types.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
namespace flt {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "AttrData.h"
|
||||
#include "DataInputStream.h"
|
||||
#include "DataOutputStream.h"
|
||||
|
||||
using namespace osg;
|
||||
using namespace osgDB;
|
||||
@@ -47,6 +48,7 @@ class ReaderWriterATTR : public osgDB::ReaderWriter
|
||||
}
|
||||
|
||||
virtual ReadResult readObject(const std::string& fileName, const ReaderWriter::Options*) const;
|
||||
virtual ReaderWriter::WriteResult writeObject(const osg::Object& object, const std::string& fileName, const Options* options) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -74,7 +76,7 @@ ReaderWriter::ReadResult ReaderWriterATTR::readObject(const std::string& file, c
|
||||
try
|
||||
{
|
||||
attr->texels_u = in.readInt32();
|
||||
attr->textel_v = in.readInt32();
|
||||
attr->texels_v = in.readInt32();
|
||||
attr->direction_u = in.readInt32();
|
||||
attr->direction_v = in.readInt32();
|
||||
attr->x_up = in.readInt32();
|
||||
@@ -170,7 +172,7 @@ ReaderWriter::ReadResult ReaderWriterATTR::readObject(const std::string& file, c
|
||||
in.forward(14*4);
|
||||
attr->attrVersion = in.readInt32();
|
||||
attr->controlPoints = in.readInt32();
|
||||
in.forward(4);
|
||||
attr->numSubtextures = in.readInt32();
|
||||
#endif
|
||||
}
|
||||
catch(...)
|
||||
@@ -187,19 +189,125 @@ ReaderWriter::ReadResult ReaderWriterATTR::readObject(const std::string& file, c
|
||||
}
|
||||
|
||||
|
||||
ReaderWriter::WriteResult
|
||||
ReaderWriterATTR::writeObject(const osg::Object& object, const std::string& fileName, const Options* options) const
|
||||
{
|
||||
using std::ios;
|
||||
|
||||
std::string ext = osgDB::getLowerCaseFileExtension( fileName );
|
||||
if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
|
||||
|
||||
const AttrData* attr = dynamic_cast< const AttrData* >( &object );
|
||||
if (attr == NULL)
|
||||
{
|
||||
osg::notify( osg::FATAL ) << "AttrWriter: Invalid Object." << std::endl;
|
||||
return WriteResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
std::ofstream fOut;
|
||||
fOut.open( fileName.c_str(), std::ios::out | std::ios::binary );
|
||||
|
||||
if ( fOut.fail())
|
||||
return WriteResult::ERROR_IN_WRITING_FILE;
|
||||
|
||||
flt::DataOutputStream out( fOut.rdbuf() );
|
||||
|
||||
|
||||
out.writeInt32( attr->texels_u );
|
||||
out.writeInt32( attr->texels_v );
|
||||
out.writeInt32( attr->direction_u );
|
||||
out.writeInt32( attr->direction_v );
|
||||
out.writeInt32( attr->x_up );
|
||||
out.writeInt32( attr->y_up );
|
||||
out.writeInt32( attr->fileFormat );
|
||||
out.writeInt32( attr->minFilterMode );
|
||||
out.writeInt32( attr->magFilterMode );
|
||||
out.writeInt32( attr->wrapMode );
|
||||
|
||||
out.writeInt32( attr->wrapMode_u );
|
||||
out.writeInt32( attr->wrapMode_v );
|
||||
|
||||
out.writeInt32( attr->modifyFlag );
|
||||
out.writeInt32( attr->pivot_x );
|
||||
out.writeInt32( attr->pivot_y );
|
||||
|
||||
out.writeInt32( attr->texEnvMode );
|
||||
out.writeInt32( attr->intensityAsAlpha );
|
||||
out.writeFill( 4*8 );
|
||||
out.writeFloat64( attr->size_u );
|
||||
out.writeFloat64( attr->size_v );
|
||||
out.writeInt32( attr->originCode );
|
||||
out.writeInt32( attr->kernelVersion );
|
||||
out.writeInt32( attr->intFormat );
|
||||
out.writeInt32( attr->extFormat );
|
||||
out.writeInt32( attr->useMips );
|
||||
for (int n=0; n<8; n++)
|
||||
out.writeFloat32( attr->of_mips[n] );
|
||||
out.writeInt32( attr->useLodScale );
|
||||
out.writeFloat32( attr->lod0 );
|
||||
out.writeFloat32( attr->scale0 );
|
||||
out.writeFloat32( attr->lod1 );
|
||||
out.writeFloat32( attr->scale1 );
|
||||
out.writeFloat32( attr->lod2 );
|
||||
out.writeFloat32( attr->scale2 );
|
||||
out.writeFloat32( attr->lod3 );
|
||||
out.writeFloat32( attr->scale3 );
|
||||
out.writeFloat32( attr->lod4 );
|
||||
out.writeFloat32( attr->scale4 );
|
||||
out.writeFloat32( attr->lod5 );
|
||||
out.writeFloat32( attr->scale5 );
|
||||
out.writeFloat32( attr->lod6 );
|
||||
out.writeFloat32( attr->scale6 );
|
||||
out.writeFloat32( attr->lod7 );
|
||||
out.writeFloat32( attr->scale7 );
|
||||
out.writeFloat32( attr->clamp );
|
||||
out.writeInt32( attr->magFilterAlpha );
|
||||
out.writeInt32( attr->magFilterColor );
|
||||
out.writeFill( 4 );
|
||||
out.writeFill( 4*8 );
|
||||
out.writeFloat64( attr->lambertMeridian );
|
||||
out.writeFloat64( attr->lambertUpperLat );
|
||||
out.writeFloat64( attr->lambertlowerLat );
|
||||
out.writeFill( 8 );
|
||||
out.writeFill( 4*5 );
|
||||
out.writeInt32( attr->useDetail );
|
||||
out.writeInt32( attr->txDetail_j );
|
||||
out.writeInt32( attr->txDetail_k );
|
||||
out.writeInt32( attr->txDetail_m );
|
||||
out.writeInt32( attr->txDetail_n );
|
||||
out.writeInt32( attr->txDetail_s );
|
||||
out.writeInt32( attr->useTile );
|
||||
out.writeFloat32( attr->txTile_ll_u );
|
||||
out.writeFloat32( attr->txTile_ll_v );
|
||||
out.writeFloat32( attr->txTile_ur_u );
|
||||
out.writeFloat32( attr->txTile_ur_v );
|
||||
out.writeInt32( attr->projection );
|
||||
out.writeInt32( attr->earthModel );
|
||||
out.writeFill( 4 );
|
||||
out.writeInt32( attr->utmZone );
|
||||
out.writeInt32( attr->imageOrigin );
|
||||
out.writeInt32( attr->geoUnits );
|
||||
out.writeFill( 4 );
|
||||
out.writeFill( 4 );
|
||||
out.writeInt32( attr->hemisphere );
|
||||
out.writeFill( 4 );
|
||||
out.writeFill( 4 );
|
||||
out.writeFill( 149*4 );
|
||||
out.writeString( attr->comments, 512 );
|
||||
|
||||
out.writeFill( 13*4 );
|
||||
out.writeInt32( attr->attrVersion );
|
||||
out.writeInt32( attr->controlPoints );
|
||||
out.writeInt32( attr->numSubtextures );
|
||||
|
||||
|
||||
fOut.close();
|
||||
|
||||
return WriteResult::FILE_SAVED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// now register with Registry to instantiate the above
|
||||
// reader/writer.
|
||||
REGISTER_OSGPLUGIN(attr, ReaderWriterATTR)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
#include "Registry.h"
|
||||
#include "Document.h"
|
||||
#include "RecordInputStream.h"
|
||||
#include "DataOutputStream.h"
|
||||
#include "FltExportVisitor.h"
|
||||
#include "ExportOptions.h"
|
||||
|
||||
#define SERIALIZER() OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_serializerMutex)
|
||||
|
||||
@@ -81,9 +84,44 @@ public:
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
|
||||
FLTReaderWriter supports importing and exporting OSG scene grqphs
|
||||
from/to OpenFlight files.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th align="center">Node</th>
|
||||
<th align="center">Object</th>
|
||||
<th align="center">Image</th>
|
||||
<th align="center">HeightField</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Read</td>
|
||||
<td align="center"><strong>X</strong></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Write</td>
|
||||
<td align="center"><strong>X</strong></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
*/
|
||||
|
||||
class FLTReaderWriter : public ReaderWriter
|
||||
{
|
||||
public:
|
||||
FLTReaderWriter()
|
||||
: _implicitPath( "." )
|
||||
{}
|
||||
|
||||
virtual const char* className() const { return "FLT Reader/Writer"; }
|
||||
|
||||
virtual bool acceptsExtension(const std::string& extension) const
|
||||
@@ -347,11 +385,38 @@ class FLTReaderWriter : public ReaderWriter
|
||||
return WriteResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
virtual WriteResult writeNode(const Node& /*node*/,const std::string& /*fileName*/, const osgDB::ReaderWriter::Options* /*options*/) const
|
||||
virtual WriteResult writeNode( const osg::Node& node, const std::string& fileName, const Options* options ) const
|
||||
{
|
||||
return WriteResult::FILE_NOT_HANDLED;
|
||||
if ( fileName.empty() )
|
||||
{
|
||||
osg::notify( osg::FATAL ) << "fltexp: writeNode: empty file name" << std::endl;
|
||||
return WriteResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
std::string ext = osgDB::getLowerCaseFileExtension( fileName );
|
||||
if ( !acceptsExtension(ext) )
|
||||
return WriteResult::FILE_NOT_HANDLED;
|
||||
|
||||
// Get and save the implicit path name (in case a path wasn't specified in Options).
|
||||
std::string filePath = osgDB::getFilePath( fileName );
|
||||
if (!filePath.empty())
|
||||
_implicitPath = filePath;
|
||||
|
||||
std::ofstream fOut;
|
||||
fOut.open( fileName.c_str(), std::ios::out | std::ios::binary );
|
||||
if ( fOut.fail())
|
||||
{
|
||||
osg::notify( osg::FATAL ) << "fltexp: Failed to open output stream." << std::endl;
|
||||
return WriteResult::ERROR_IN_WRITING_FILE;
|
||||
}
|
||||
|
||||
WriteResult wr = WriteResult::FILE_NOT_HANDLED;
|
||||
wr = writeNode( node, fOut, options );
|
||||
fOut.close();
|
||||
|
||||
return wr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual WriteResult writeObject(const Object& object,std::ostream& fout, const osgDB::ReaderWriter::Options* options) const
|
||||
{
|
||||
const Node* node = dynamic_cast<const Node*>(&object);
|
||||
@@ -359,12 +424,42 @@ class FLTReaderWriter : public ReaderWriter
|
||||
return WriteResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
virtual WriteResult writeNode(const Node& /*node*/,std::ostream& /*fout*/, const osgDB::ReaderWriter::Options* /*options*/) const
|
||||
virtual WriteResult writeNode( const osg::Node& node, std::ostream& fOut, const Options* options ) const
|
||||
{
|
||||
return WriteResult::FILE_NOT_HANDLED;
|
||||
// Convert Options to FltOptions.
|
||||
ExportOptions* fltOpt = new ExportOptions( options );
|
||||
fltOpt->parseOptionsString();
|
||||
|
||||
// If user didn't specify a temp dir, use the output directory
|
||||
// that was implicit in the output file name.
|
||||
if (fltOpt->getTempDir().empty())
|
||||
fltOpt->setTempDir( _implicitPath );
|
||||
if (!fltOpt->getTempDir().empty())
|
||||
{
|
||||
// If the temp directory doesn't already exist, make it.
|
||||
if ( !osgDB::makeDirectory( fltOpt->getTempDir() ) )
|
||||
{
|
||||
osg::notify( osg::FATAL ) << "fltexp: Error creating temp dir: " << fltOpt->getTempDir() << std::endl;
|
||||
return WriteResult::ERROR_IN_WRITING_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
flt::DataOutputStream dos( fOut.rdbuf(), fltOpt->getValidateOnly() );
|
||||
flt::FltExportVisitor fnv( &dos, fltOpt );
|
||||
|
||||
// Hm. 'node' is const, but in order to write out this scene graph,
|
||||
// must use Node::accept() which requires 'node' to be non-const.
|
||||
// Pretty much requires casting away const.
|
||||
osg::Node* nodeNonConst = const_cast<osg::Node*>( &node );
|
||||
nodeNonConst->accept( fnv );
|
||||
fnv.complete( node );
|
||||
|
||||
// FIXME: Error-handling?
|
||||
return WriteResult::FILE_SAVED;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable std::string _implicitPath;
|
||||
|
||||
mutable OpenThreads::ReentrantMutex _serializerMutex;
|
||||
};
|
||||
@@ -372,16 +467,3 @@ class FLTReaderWriter : public ReaderWriter
|
||||
// now register with Registry to instantiate the above
|
||||
// reader/writer.
|
||||
REGISTER_OSGPLUGIN(OpenFlight, FLTReaderWriter)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "opcodes.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Registry.h"
|
||||
#include "Document.h"
|
||||
#include "RecordInputStream.h"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <osg/ref_ptr>
|
||||
#include "opcodes.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Record.h"
|
||||
|
||||
namespace flt {
|
||||
|
||||
99
src/osgPlugins/OpenFlight/TexturePaletteManager.cpp
Normal file
99
src/osgPlugins/OpenFlight/TexturePaletteManager.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 "TexturePaletteManager.h"
|
||||
#include "FltExportVisitor.h"
|
||||
#include "ExportOptions.h"
|
||||
#include "DataOutputStream.h"
|
||||
#include "Opcodes.h"
|
||||
#include <osg/Notify>
|
||||
#include <osg/Texture2D>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
TexturePaletteManager::TexturePaletteManager( const FltExportVisitor& nv, const ExportOptions& fltOpt )
|
||||
: _fltOpt( fltOpt ),
|
||||
_nv( nv ),
|
||||
_currIndex( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
TexturePaletteManager::add( int unit, const osg::Texture2D* texture )
|
||||
{
|
||||
if( (!texture) ||
|
||||
(!texture->getImage()) )
|
||||
return -1;
|
||||
|
||||
int index( -1 );
|
||||
TextureIndexMap::const_iterator it = _indexMap.find( texture );
|
||||
if (it != _indexMap.end())
|
||||
index = it->second;
|
||||
else
|
||||
{
|
||||
index = _currIndex++;
|
||||
_indexMap[ texture ] = index;
|
||||
|
||||
// If there is no .attr file, write one
|
||||
_nv.writeATTRFile( unit, texture );
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
TexturePaletteManager::write( DataOutputStream& dos ) const
|
||||
{
|
||||
int x( 0 ), y( 0 ), height( 0 );
|
||||
TextureIndexMap::const_iterator it = _indexMap.begin();
|
||||
while (it != _indexMap.end())
|
||||
{
|
||||
const osg::Texture2D* texture = it->first;
|
||||
int index = it->second;
|
||||
|
||||
std::string fileName;
|
||||
if ( _fltOpt.getStripTextureFilePath() )
|
||||
fileName = osgDB::getSimpleFileName( texture->getImage()->getFileName() );
|
||||
else
|
||||
fileName = texture->getImage()->getFileName();
|
||||
|
||||
dos.writeInt16( (int16) TEXTURE_PALETTE_OP );
|
||||
dos.writeUInt16( 216 );
|
||||
dos.writeString( fileName, 200 );
|
||||
dos.writeInt32( index );
|
||||
dos.writeInt32( x );
|
||||
dos.writeInt32( y );
|
||||
it++;
|
||||
|
||||
x += texture->getImage()->s();
|
||||
if (texture->getImage()->t() > height)
|
||||
height = texture->getImage()->t();
|
||||
if (x > 1024)
|
||||
{
|
||||
x = 0;
|
||||
y += height;
|
||||
height = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
62
src/osgPlugins/OpenFlight/TexturePaletteManager.h
Normal file
62
src/osgPlugins/OpenFlight/TexturePaletteManager.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.
|
||||
//
|
||||
|
||||
#ifndef __FLTEXP_TEXTURE_PALETTE_MANAGER_H__
|
||||
#define __FLTEXP_TEXTURE_PALETTE_MANAGER_H__ 1
|
||||
|
||||
|
||||
#include "ExportOptions.h"
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
|
||||
namespace osg {
|
||||
class Texture2D;
|
||||
}
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
class DataOutputStream;
|
||||
class FltExportVisitor;
|
||||
|
||||
|
||||
class TexturePaletteManager
|
||||
{
|
||||
public:
|
||||
TexturePaletteManager( const FltExportVisitor& nv, const ExportOptions& fltOpt );
|
||||
|
||||
int add( int unit, const osg::Texture2D* texture );
|
||||
|
||||
void write( DataOutputStream& dos ) const;
|
||||
|
||||
protected:
|
||||
int _currIndex;
|
||||
|
||||
typedef std::map< const osg::Texture2D*, int > TextureIndexMap;
|
||||
TextureIndexMap _indexMap;
|
||||
|
||||
const FltExportVisitor& _nv;
|
||||
|
||||
const ExportOptions& _fltOpt;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
51
src/osgPlugins/OpenFlight/Types.h
Normal file
51
src/osgPlugins/OpenFlight/Types.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// OpenFlight<68> loader for OpenSceneGraph
|
||||
//
|
||||
// Copyright (C) 2005-2007 Brede Johansen
|
||||
//
|
||||
|
||||
#ifndef FLT_TYPES_H
|
||||
#define FLT_TYPES_H 1
|
||||
|
||||
namespace flt {
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
typedef __int8 int8;
|
||||
typedef unsigned __int8 uint8;
|
||||
typedef __int16 int16;
|
||||
typedef unsigned __int16 uint16;
|
||||
typedef __int32 int32;
|
||||
typedef unsigned __int32 uint32;
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
|
||||
#else
|
||||
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
36
src/osgPlugins/OpenFlight/Utils.h
Normal file
36
src/osgPlugins/OpenFlight/Utils.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.
|
||||
//
|
||||
|
||||
#ifndef __FLTEXP_UTILS_H__
|
||||
#define __FLTEXP_UTILS_H__ 1
|
||||
|
||||
|
||||
// FLTEXP_DELETEFILE macro is used to delete temp files created during file export.
|
||||
// (Too bad OSG doesn't use Boost.)
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
#define FLTEXP_DELETEFILE(file) DeleteFile((file))
|
||||
|
||||
#else // Unix
|
||||
|
||||
#include <stdio.h>
|
||||
#define FLTEXP_DELETEFILE(file) remove((file))
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
342
src/osgPlugins/OpenFlight/VertexPaletteManager.cpp
Normal file
342
src/osgPlugins/OpenFlight/VertexPaletteManager.cpp
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* 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 "VertexPaletteManager.h"
|
||||
#include "DataOutputStream.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Utils.h"
|
||||
#include <osg/Notify>
|
||||
#include <osg/Geometry>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
VertexPaletteManager::VertexPaletteManager( const ExportOptions& fltOpt )
|
||||
: _fltOpt( fltOpt ),
|
||||
_currentSizeBytes( 8 ),
|
||||
_current( NULL ),
|
||||
_vertices( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
VertexPaletteManager::~VertexPaletteManager()
|
||||
{
|
||||
if (!_verticesTempName.empty())
|
||||
{
|
||||
// Delete our temp file.
|
||||
if (_verticesStr.is_open())
|
||||
{
|
||||
osg::notify( osg::WARN ) << "fltexp: VertexPaletteManager destructor has an open temp file." << std::endl;
|
||||
// This should not happen. FltNodeVisitor::complete should close
|
||||
// this file before we get to this destructor.
|
||||
return;
|
||||
}
|
||||
osg::notify( osg::INFO ) << "fltexp: Deleting temp file " << _verticesTempName << std::endl;
|
||||
FLTEXP_DELETEFILE( _verticesTempName.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VertexPaletteManager::add( const osg::Geometry& geom )
|
||||
{
|
||||
const osg::Array* v = geom.getVertexArray();
|
||||
const osg::Array* c = geom.getColorArray();
|
||||
const osg::Array* n = geom.getNormalArray();
|
||||
const osg::Array* t = geom.getTexCoordArray( 0 );
|
||||
// TBD eventually need to be able to support other array types.
|
||||
const osg::Vec3Array* v3 = dynamic_cast<const osg::Vec3Array*>( v );
|
||||
const osg::Vec4Array* c4 = dynamic_cast<const osg::Vec4Array*>( c );
|
||||
const osg::Vec3Array* n3 = dynamic_cast<const osg::Vec3Array*>( n );
|
||||
const osg::Vec2Array* t2 = dynamic_cast<const osg::Vec2Array*>( t );
|
||||
if (v && !v3)
|
||||
{
|
||||
std::string warning( "fltexp: VertexPalette: VertexArray is not Vec3Array." );
|
||||
osg::notify( osg::WARN ) << warning << std::endl;
|
||||
_fltOpt.getWriteResult().warn( warning );
|
||||
return;
|
||||
}
|
||||
if (c && !c4)
|
||||
{
|
||||
std::string warning( "fltexp: VertexPalette: ColorArray is not Vec4Array." );
|
||||
osg::notify( osg::WARN ) << warning << std::endl;
|
||||
_fltOpt.getWriteResult().warn( warning );
|
||||
return;
|
||||
}
|
||||
if (n && !n3)
|
||||
{
|
||||
std::string warning( "fltexp: VertexPalette: NormalArray is not Vec3Array." );
|
||||
osg::notify( osg::WARN ) << warning << std::endl;
|
||||
_fltOpt.getWriteResult().warn( warning );
|
||||
return;
|
||||
}
|
||||
if (t && !t2)
|
||||
{
|
||||
std::string warning( "fltexp: VertexPalette: TexCoordArray is not Vec2Array." );
|
||||
osg::notify( osg::WARN ) << warning << std::endl;
|
||||
_fltOpt.getWriteResult().warn( warning );
|
||||
return;
|
||||
}
|
||||
|
||||
const bool cpv =( geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX );
|
||||
const bool npv =( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX );
|
||||
add( v3, c4, n3, t2, cpv, npv );
|
||||
}
|
||||
void
|
||||
VertexPaletteManager::add( const osg::Vec3Array* v, const osg::Vec4Array* c,
|
||||
const osg::Vec3Array* n, const osg::Vec2Array* t,
|
||||
bool colorPerVertex, bool normalPerVertex, bool allowSharing )
|
||||
{
|
||||
bool needsInit( true );
|
||||
|
||||
if (allowSharing)
|
||||
{
|
||||
ArrayMap::iterator it = _arrayMap.find( v );
|
||||
if (it != _arrayMap.end())
|
||||
needsInit = false;
|
||||
_current = &( _arrayMap[ v ] );
|
||||
}
|
||||
else
|
||||
_current = &( _nonShared );
|
||||
|
||||
if (needsInit)
|
||||
{
|
||||
_current->_byteStart = _currentSizeBytes;
|
||||
|
||||
_current->_idxCount = v->size();
|
||||
|
||||
_current->_idxSizeBytes = recordSize( recordType( v, c, n, t ) );
|
||||
_currentSizeBytes += ( _current->_idxSizeBytes * _current->_idxCount );
|
||||
|
||||
// Next we'll write the vertex palette record data. But,
|
||||
// if we don't have a DataOutputStream yet, open the temp file.
|
||||
if (!_vertices)
|
||||
{
|
||||
_verticesTempName = _fltOpt.getTempDir() + "/ofw_temp_vertices";
|
||||
_verticesStr.open( _verticesTempName.c_str(), std::ios::out | std::ios::binary );
|
||||
_vertices = new DataOutputStream( _verticesStr.rdbuf(), _fltOpt.getValidateOnly() );
|
||||
}
|
||||
writeRecords( v, c, n, t, colorPerVertex, normalPerVertex );
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
VertexPaletteManager::byteOffset( unsigned int idx ) const
|
||||
{
|
||||
if (!_current)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "fltexp: No current vertex array in VertexPaletteManager." << std::endl;
|
||||
return 4;
|
||||
}
|
||||
if (idx >= _current->_idxCount)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "fltexp: Index out of range in VertexPaletteManager." << std::endl;
|
||||
return 4;
|
||||
}
|
||||
|
||||
return( _current->_byteStart + (_current->_idxSizeBytes * idx) );
|
||||
}
|
||||
|
||||
void
|
||||
VertexPaletteManager::write( DataOutputStream& dos ) const
|
||||
{
|
||||
if (_currentSizeBytes == 8)
|
||||
// Empty palette. Don't write anything.
|
||||
return;
|
||||
|
||||
dos.writeInt16( (int16) VERTEX_PALETTE_OP );
|
||||
dos.writeUInt16( 8 );
|
||||
dos.writeInt32( _currentSizeBytes );
|
||||
|
||||
// Close the temp file. We're done writing new data to it.
|
||||
_verticesStr.close();
|
||||
|
||||
// Open that temp file again, this time for reading.
|
||||
// Then copy to dos.
|
||||
char buf;
|
||||
std::ifstream vertIn;
|
||||
vertIn.open( _verticesTempName.c_str(), std::ios::in | std::ios::binary );
|
||||
while (!vertIn.eof() )
|
||||
{
|
||||
vertIn.read( &buf, 1 );
|
||||
if (vertIn.good())
|
||||
dos << buf;
|
||||
}
|
||||
vertIn.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
VertexPaletteManager::PaletteRecordType
|
||||
VertexPaletteManager::recordType( const osg::Array* v, const osg::Array* c,
|
||||
const osg::Array* n, const osg::Array* t )
|
||||
{
|
||||
if (t)
|
||||
{
|
||||
// Texture coordinstes
|
||||
if (n)
|
||||
return VERTEX_CNT;
|
||||
else
|
||||
return VERTEX_CT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No textue coordinates
|
||||
if (n)
|
||||
return VERTEX_CN;
|
||||
else
|
||||
return VERTEX_C;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
VertexPaletteManager::recordSize( PaletteRecordType recType )
|
||||
{
|
||||
switch (recType)
|
||||
{
|
||||
case VERTEX_C:
|
||||
return 40;
|
||||
break;
|
||||
case VERTEX_CN:
|
||||
return (_fltOpt.getFlightFileVersionNumber() > ExportOptions::VERSION_15_7) ? 56 : 52;
|
||||
break;
|
||||
case VERTEX_CT:
|
||||
return 48;
|
||||
break;
|
||||
case VERTEX_CNT:
|
||||
return 64;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VertexPaletteManager::writeRecords( const osg::Vec3Array* v, const osg::Vec4Array* c,
|
||||
const osg::Vec3Array* n, const osg::Vec2Array* t,
|
||||
bool colorPerVertex, bool normalPerVertex )
|
||||
{
|
||||
const PaletteRecordType recType = recordType( v, c, n, t );
|
||||
const int16 sizeBytes = recordSize( recType );
|
||||
|
||||
int16 opcode;
|
||||
switch( recType )
|
||||
{
|
||||
case VERTEX_C:
|
||||
opcode = VERTEX_C_OP;
|
||||
break;
|
||||
case VERTEX_CN:
|
||||
opcode = VERTEX_CN_OP;
|
||||
if (!n)
|
||||
osg::notify( osg::WARN ) << "fltexp: VPM::writeRecords: no normal array." << std::endl;
|
||||
break;
|
||||
case VERTEX_CNT:
|
||||
opcode = VERTEX_CNT_OP;
|
||||
if (!n)
|
||||
osg::notify( osg::WARN ) << "fltexp: VPM::writeRecords: no normal array." << std::endl;
|
||||
if (!t)
|
||||
osg::notify( osg::WARN ) << "fltexp: VPM::writeRecords: no tex coord array." << std::endl;
|
||||
break;
|
||||
case VERTEX_CT:
|
||||
opcode = VERTEX_CT_OP;
|
||||
if (!t)
|
||||
osg::notify( osg::WARN ) << "fltexp: VPM::writeRecords: no tex coord array." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
enum FlagBits
|
||||
{
|
||||
START_HARD_EDGE = (0x8000 >> 0),
|
||||
NORMAL_FROZEN = (0x8000 >> 1),
|
||||
NO_COLOR = (0x8000 >> 2),
|
||||
PACKED_COLOR = (0x8000 >> 3)
|
||||
};
|
||||
uint32 flags( NO_COLOR );
|
||||
if (colorPerVertex)
|
||||
flags = PACKED_COLOR;
|
||||
|
||||
|
||||
int cIdx( 0 );
|
||||
int nIdx( 0 );
|
||||
size_t idx;
|
||||
for( idx=0; idx<v->size(); idx++)
|
||||
{
|
||||
uint32 packedColor( 0 );
|
||||
if (c)
|
||||
{
|
||||
osg::Vec4 color = (*c)[ cIdx ];
|
||||
packedColor = (int)(color[3]*255) << 24 |
|
||||
(int)(color[2]*255) << 16 | (int)(color[1]*255) << 8 |
|
||||
(int)(color[0]*255);
|
||||
}
|
||||
else
|
||||
osg::notify( osg::DEBUG_INFO ) << "fltexp: VPM::writeRecords: no color array." << std::endl;
|
||||
|
||||
// Write fields common to all record types.
|
||||
_vertices->writeInt16( opcode );
|
||||
_vertices->writeUInt16( sizeBytes );
|
||||
_vertices->writeUInt16( 0 ); // Color name
|
||||
_vertices->writeInt16( flags ); // Flags
|
||||
_vertices->writeVec3d( osg::Vec3d( (*v)[ idx ] ) ); // Vertex
|
||||
|
||||
// Now write record-specific field.
|
||||
switch( recType )
|
||||
{
|
||||
case VERTEX_C:
|
||||
_vertices->writeInt32( packedColor ); // Packed color
|
||||
_vertices->writeUInt32( 0 ); // Vertex color index
|
||||
break;
|
||||
case VERTEX_CN:
|
||||
_vertices->writeVec3f( (*n)[ nIdx ] ); // Normal
|
||||
_vertices->writeInt32( packedColor ); // Packed color
|
||||
_vertices->writeUInt32( 0 ); // Vertex color index
|
||||
if (_fltOpt.getFlightFileVersionNumber() > ExportOptions::VERSION_15_7)
|
||||
_vertices->writeUInt32( 0 ); // Reserved
|
||||
break;
|
||||
case VERTEX_CNT:
|
||||
_vertices->writeVec3f( (*n)[ nIdx ] ); // Normal
|
||||
_vertices->writeVec2f( (*t)[ idx ] ); // Tex coord
|
||||
_vertices->writeInt32( packedColor ); // Packed color
|
||||
_vertices->writeUInt32( 0 ); // Vertex color index
|
||||
_vertices->writeUInt32( 0 ); // Reserved
|
||||
break;
|
||||
case VERTEX_CT:
|
||||
_vertices->writeVec2f( (*t)[ idx ] ); // Tex coord
|
||||
_vertices->writeInt32( packedColor ); // Packed color
|
||||
_vertices->writeUInt32( 0 ); // Vertex color index
|
||||
break;
|
||||
}
|
||||
|
||||
if (colorPerVertex)
|
||||
cIdx++;
|
||||
if (normalPerVertex)
|
||||
nIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
VertexPaletteManager::ArrayInfo::ArrayInfo()
|
||||
: _byteStart( 0 ),
|
||||
_idxSizeBytes( 0 ),
|
||||
_idxCount( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
99
src/osgPlugins/OpenFlight/VertexPaletteManager.h
Normal file
99
src/osgPlugins/OpenFlight/VertexPaletteManager.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.
|
||||
//
|
||||
|
||||
#ifndef __FLTEXP_VERTEX_PALETTE_MANAGER_H__
|
||||
#define __FLTEXP_VERTEX_PALETTE_MANAGER_H__ 1
|
||||
|
||||
|
||||
#include "DataOutputStream.h"
|
||||
#include "ExportOptions.h"
|
||||
#include <osg/Array>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
|
||||
namespace osg {
|
||||
class Geometry;
|
||||
}
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
Manages writing the Vertex Palette record during export.
|
||||
Maintains a map to ensure that instanced VertexArray data is only
|
||||
written once to the palette. Writes the palette record to a temp
|
||||
file and copies it to FltExportVisitor::_dos after the scene graph
|
||||
has been completely walked.
|
||||
*/
|
||||
class VertexPaletteManager
|
||||
{
|
||||
public:
|
||||
VertexPaletteManager( const ExportOptions& fltOpt );
|
||||
~VertexPaletteManager();
|
||||
|
||||
void add( const osg::Geometry& geom );
|
||||
void add( const osg::Vec3Array* v, const osg::Vec4Array* c,
|
||||
const osg::Vec3Array* n, const osg::Vec2Array* t,
|
||||
bool colorPerVertex, bool normalPerVertex, bool allowSharing=true );
|
||||
|
||||
unsigned int byteOffset( unsigned int idx ) const;
|
||||
|
||||
void write( DataOutputStream& dos ) const;
|
||||
|
||||
protected:
|
||||
typedef enum {
|
||||
VERTEX_C,
|
||||
VERTEX_CN,
|
||||
VERTEX_CNT,
|
||||
VERTEX_CT
|
||||
} PaletteRecordType;
|
||||
|
||||
static PaletteRecordType recordType( const osg::Array* v, const osg::Array* c,
|
||||
const osg::Array* n, const osg::Array* t );
|
||||
unsigned int recordSize( PaletteRecordType recType );
|
||||
|
||||
void writeRecords( const osg::Vec3Array* v, const osg::Vec4Array* c,
|
||||
const osg::Vec3Array* n, const osg::Vec2Array* t,
|
||||
bool colorPerVertex, bool normalPerVertex );
|
||||
|
||||
unsigned int _currentSizeBytes;
|
||||
|
||||
struct ArrayInfo {
|
||||
ArrayInfo();
|
||||
|
||||
unsigned int _byteStart;
|
||||
unsigned int _idxSizeBytes;
|
||||
unsigned int _idxCount;
|
||||
};
|
||||
ArrayInfo* _current;
|
||||
ArrayInfo _nonShared;
|
||||
|
||||
typedef std::map< const osg::Array*, ArrayInfo > ArrayMap;
|
||||
ArrayMap _arrayMap;
|
||||
|
||||
mutable std::ofstream _verticesStr;
|
||||
DataOutputStream* _vertices;
|
||||
std::string _verticesTempName;
|
||||
|
||||
const ExportOptions& _fltOpt;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
109
src/osgPlugins/OpenFlight/expAncillaryRecords.cpp
Normal file
109
src/osgPlugins/OpenFlight/expAncillaryRecords.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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 "DataOutputStream.h"
|
||||
#include "Opcodes.h"
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/Notify>
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
/** If the DataOutputStream paraqmeter is NULL, write to the _records
|
||||
member variable. Otherwise, write to the specified DataOutputStream.
|
||||
*/
|
||||
void
|
||||
FltExportVisitor::writeComment( const osg::Node& node, DataOutputStream* dos )
|
||||
{
|
||||
if (dos==NULL)
|
||||
dos = _records;
|
||||
|
||||
// Write all descriptions as Comment records.
|
||||
unsigned int nd = node.getNumDescriptions();
|
||||
unsigned int idx=0;
|
||||
while( idx < nd )
|
||||
{
|
||||
const std::string& com = node.getDescription( idx );
|
||||
unsigned int iLen = com.length() + 5;
|
||||
if (iLen > 0xffff)
|
||||
{
|
||||
// short overrun
|
||||
std::string warning( "fltexp: writeComment: Descriptions too long, resorts in short overrun. Skipping." );
|
||||
_fltOpt->getWriteResult().warn( warning );
|
||||
osg::notify( osg::WARN ) << warning << std::endl;
|
||||
continue;
|
||||
}
|
||||
uint16 length( (uint16)iLen );
|
||||
|
||||
dos->writeInt16( (int16) COMMENT_OP );
|
||||
dos->writeInt16( length );
|
||||
dos->writeString( com );
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/** If the DataOutputStream paraqmeter is NULL, write to the _records
|
||||
member variable. Otherwise, write to the specified DataOutputStream.
|
||||
*/
|
||||
void
|
||||
FltExportVisitor::writeLongID( const std::string& id, DataOutputStream* dos )
|
||||
{
|
||||
if (dos==NULL)
|
||||
dos = _records;
|
||||
|
||||
uint16 length( 2 + 2 + id.length() + 1 ); // +1 for terminating '\0'
|
||||
|
||||
dos->writeInt16( (int16) LONG_ID_OP );
|
||||
dos->writeUInt16( length );
|
||||
dos->writeString( id );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::writeMatrix( const osg::Referenced* ref )
|
||||
{
|
||||
const osg::RefMatrix* rm = dynamic_cast<const osg::RefMatrix*>( ref );
|
||||
if (!rm)
|
||||
return;
|
||||
|
||||
uint16 length( 4 + (16 * sizeof(float32)) );
|
||||
|
||||
_records->writeInt16( (int16) MATRIX_OP );
|
||||
_records->writeUInt16( length );
|
||||
|
||||
int idx, jdx;
|
||||
for (idx=0; idx<4; idx++)
|
||||
{
|
||||
for (jdx=0; jdx<4; jdx++)
|
||||
{
|
||||
_records->writeFloat32( (*rm)( idx, jdx ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::writeContinuationRecord( const unsigned short length )
|
||||
{
|
||||
osg::notify( osg::DEBUG_INFO ) << "fltexp: Continuation record length: " << length+4 << std::endl;
|
||||
_records->writeInt16( (int16) CONTINUATION_OP );
|
||||
_records->writeUInt16( length+4 );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
55
src/osgPlugins/OpenFlight/expControlRecords.cpp
Normal file
55
src/osgPlugins/OpenFlight/expControlRecords.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 "DataOutputStream.h"
|
||||
#include "Opcodes.h"
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::writePush()
|
||||
{
|
||||
_records->writeInt16( (int16) PUSH_LEVEL_OP );
|
||||
_records->writeInt16( 4 );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::writePop()
|
||||
{
|
||||
_records->writeInt16( (int16) POP_LEVEL_OP );
|
||||
_records->writeInt16( 4 );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::writePushSubface()
|
||||
{
|
||||
_records->writeInt16( (int16) PUSH_SUBFACE_OP );
|
||||
_records->writeInt16( 4 );
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::writePopSubface()
|
||||
{
|
||||
_records->writeInt16( (int16) POP_SUBFACE_OP );
|
||||
_records->writeInt16( 4 );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
1106
src/osgPlugins/OpenFlight/expGeometryRecords.cpp
Normal file
1106
src/osgPlugins/OpenFlight/expGeometryRecords.cpp
Normal file
File diff suppressed because it is too large
Load Diff
792
src/osgPlugins/OpenFlight/expPrimaryRecords.cpp
Normal file
792
src/osgPlugins/OpenFlight/expPrimaryRecords.cpp
Normal file
@@ -0,0 +1,792 @@
|
||||
/*
|
||||
* 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 "VertexPaletteManager.h"
|
||||
#include "LightSourcePaletteManager.h"
|
||||
#include "DataOutputStream.h"
|
||||
#include "Opcodes.h"
|
||||
#include <osg/Group>
|
||||
#include <osg/Sequence>
|
||||
#include <osg/LightSource>
|
||||
#include <osg/LOD>
|
||||
#include <osg/ProxyNode>
|
||||
#include <osg/Switch>
|
||||
#include <osgSim/MultiSwitch>
|
||||
#include <osgSim/DOFTransform>
|
||||
#include <osgSim/LightPointNode>
|
||||
#include <osgSim/ObjectRecordData>
|
||||
|
||||
|
||||
// FIXME: This header was copied verbatim from the importer, with the only change
|
||||
// being that the symbols it defines are placed in namespace 'fltexp' instead
|
||||
// of 'flt'. Thus, this one-off copy has to be kept in sync with the
|
||||
// importer until the reader/writer are unified...
|
||||
#include "Pools.h"
|
||||
|
||||
|
||||
namespace flt
|
||||
{
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::writeHeader( const std::string& headerName )
|
||||
{
|
||||
int16 length;
|
||||
int32 version;
|
||||
const int ver = _fltOpt->getFlightFileVersionNumber();
|
||||
if (ver == ExportOptions::VERSION_15_7)
|
||||
{
|
||||
length = 304;
|
||||
version = 1570;
|
||||
}
|
||||
else if (ver == ExportOptions::VERSION_15_8)
|
||||
{
|
||||
length = 324;
|
||||
version = 1580;
|
||||
}
|
||||
else // ExportOptions::VERSION_16_1:
|
||||
{
|
||||
length = 324;
|
||||
version = 1610;
|
||||
}
|
||||
|
||||
int8 units;
|
||||
switch( _fltOpt->getFlightUnits() )
|
||||
{
|
||||
case ExportOptions::KILOMETERS:
|
||||
units = 1;
|
||||
break;
|
||||
case ExportOptions::FEET:
|
||||
units = 4;
|
||||
break;
|
||||
case ExportOptions::INCHES:
|
||||
units = 5;
|
||||
break;
|
||||
case ExportOptions::NAUTICAL_MILES:
|
||||
units = 8;
|
||||
break;
|
||||
default:
|
||||
case ExportOptions::METERS:
|
||||
units = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
static const unsigned int SAVE_VERTEX_NORMALS_BIT = 0x80000000u >> 0;
|
||||
static const unsigned int PACKED_COLOR_MODE_BIT = 0x80000000u >> 1;
|
||||
static const unsigned int CAD_VIEW_MODE_BIT = 0x80000000u >> 2;
|
||||
uint32 flags( SAVE_VERTEX_NORMALS_BIT );
|
||||
|
||||
IdHelper id(*this, headerName);
|
||||
id.dos_ = &_dos;
|
||||
|
||||
_dos.writeInt16( (int16) HEADER_OP );
|
||||
_dos.writeInt16( length );
|
||||
_dos.writeID( id );
|
||||
_dos.writeInt32( version );
|
||||
_dos.writeInt32( 0 ); // edit revision
|
||||
// TBD need platform-independent method to generate date/time string
|
||||
_dos.writeString( std::string(" "), 32 ); // date and time string for last rev
|
||||
_dos.writeInt16( 0 ); // next group id
|
||||
_dos.writeInt16( 0 ); // next LOD id
|
||||
_dos.writeInt16( 0 ); // next object id
|
||||
_dos.writeInt16( 0 ); // next face id
|
||||
_dos.writeInt16( 1 ); // unit multiplier
|
||||
_dos.writeInt8( units ); // coordinate units
|
||||
_dos.writeInt8( 0 ); // if TRUE, texwhite on new faces
|
||||
_dos.writeUInt32( flags ); // flags
|
||||
_dos.writeFill( sizeof( int32 ) * 6 ); // reserved
|
||||
_dos.writeInt32( 0 ); // projection
|
||||
_dos.writeFill( sizeof( int32 ) * 7 ); // reserved
|
||||
_dos.writeInt16( 0 ); // next DOF id
|
||||
_dos.writeInt16( 1 ); // vertex storage type, should always be 1
|
||||
_dos.writeInt32( 100 ); // DB origin, 100=OpenFlight
|
||||
_dos.writeFloat64( 0. ); // SW corner X
|
||||
_dos.writeFloat64( 0. ); // SW corner Y
|
||||
_dos.writeFloat64( 0. ); // delta X
|
||||
_dos.writeFloat64( 0. ); // delta Y
|
||||
_dos.writeInt16( 0 ); // next sound id
|
||||
_dos.writeInt16( 0 ); // next path id
|
||||
_dos.writeFill( sizeof( int32 ) * 2 ); // reserved
|
||||
_dos.writeInt16( 0 ); // next clip id
|
||||
_dos.writeInt16( 0 ); // next text id
|
||||
_dos.writeInt16( 0 ); // next BSP id
|
||||
_dos.writeInt16( 0 ); // next switch id
|
||||
_dos.writeInt32( 0 ); // reserved
|
||||
_dos.writeFloat64( 0. ); // SW corner lat
|
||||
_dos.writeFloat64( 0. ); // SW corner lon
|
||||
_dos.writeFloat64( 0. ); // NE corner lat
|
||||
_dos.writeFloat64( 0. ); // NE corner lon
|
||||
_dos.writeFloat64( 0. ); // origin lat
|
||||
_dos.writeFloat64( 0. ); // origin lon
|
||||
_dos.writeFloat64( 0. ); // lambert upper lat
|
||||
_dos.writeFloat64( 0. ); // lambert upper lon
|
||||
_dos.writeInt16( 0 ); // next light source id
|
||||
_dos.writeInt16( 0 ); // next light point id
|
||||
_dos.writeInt16( 0 ); // next road id
|
||||
_dos.writeInt16( 0 ); // next CAT id
|
||||
_dos.writeFill( sizeof( int16 ) * 4 ); // reserved
|
||||
_dos.writeInt32( 0 ); // ellipsoid model, 0=WGS84
|
||||
_dos.writeInt16( 0 ); // next adaptive id
|
||||
_dos.writeInt16( 0 ); // next curve id
|
||||
_dos.writeInt16( 0 ); // utm zone
|
||||
_dos.writeFill( 6 ); // reserved
|
||||
_dos.writeFloat64( 0. ); // delta z
|
||||
_dos.writeFloat64( 0. ); // radius
|
||||
_dos.writeInt16( 0 ); // next mesh id
|
||||
_dos.writeInt16( 0 ); // next light system id
|
||||
|
||||
if (version >= 1580)
|
||||
{
|
||||
_dos.writeInt32( 0 ); // reserved
|
||||
_dos.writeFloat64( 0. ); // earth major axis for user defined ellipsoid
|
||||
_dos.writeFloat64( 0. ); // earth minor axis for user defined ellipsoid
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Group flags
|
||||
static const unsigned int FORWARD_ANIM = 0x80000000u >> 1;
|
||||
static const unsigned int SWING_ANIM = 0x80000000u >> 2;
|
||||
static const unsigned int BOUND_BOX_FOLLOW = 0x80000000u >> 3;
|
||||
static const unsigned int FREEZE_BOUND_BOX = 0x80000000u >> 4;
|
||||
static const unsigned int DEFAULT_PARENT = 0x80000000u >> 5;
|
||||
static const unsigned int BACKWARD_ANIM = 0x80000000u >> 6;
|
||||
|
||||
|
||||
//
|
||||
// Convenience routine for writing Group nodes that aren't animated
|
||||
//
|
||||
void
|
||||
FltExportVisitor::writeGroup( const osg::Group& group )
|
||||
{
|
||||
int32 flags = 0, loopCount = 0;
|
||||
float32 loopDuration = 0.0f, lastFrameDuration = 0.0f;
|
||||
|
||||
writeGroup(group, flags, loopCount, loopDuration, lastFrameDuration);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::writeGroup( const osg::Group& group,
|
||||
int32 flags,
|
||||
int32 loopCount,
|
||||
float32 loopDuration,
|
||||
float32 lastFrameDuration) // <-- placeholder: ignored
|
||||
{
|
||||
int16 length( 44 );
|
||||
IdHelper id(*this, group.getName() );
|
||||
|
||||
_records->writeInt16( (int16) GROUP_OP );
|
||||
_records->writeInt16( length );
|
||||
_records->writeID( id );
|
||||
_records->writeInt16( 0 ); // Relative priority
|
||||
_records->writeInt16( 0 ); // Reserved
|
||||
_records->writeUInt32( flags );
|
||||
_records->writeInt16( 0 ); // Special effect ID1
|
||||
_records->writeInt16( 0 ); // Special effect ID2
|
||||
_records->writeInt16( 0 ); // Significance
|
||||
_records->writeInt8( 0 ); // Layer code
|
||||
_records->writeInt8( 0 ); // Reserved
|
||||
_records->writeInt32( 0 ); // Reserved
|
||||
_records->writeInt32( loopCount );
|
||||
_records->writeFloat32( loopDuration );
|
||||
_records->writeFloat32( lastFrameDuration );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Since OpenFlight doesn't have 'Sequence' records---just Group records that
|
||||
// may, optionally, be animated---this routine sets the animation-related
|
||||
// parameters for a Group record and simply forwards to writeGroup()
|
||||
//
|
||||
void
|
||||
FltExportVisitor::writeSequence( const osg::Sequence& sequence )
|
||||
{
|
||||
|
||||
int32 flags = 0, loopCount = 0;
|
||||
float32 loopDuration = 0.0f, lastFrameDuration = 0.0f;
|
||||
|
||||
osg::Sequence::LoopMode mode;
|
||||
int firstChildDisplayed, lastChildDisplayed;
|
||||
sequence.getInterval(mode, firstChildDisplayed, lastChildDisplayed);
|
||||
|
||||
if (firstChildDisplayed == 0)
|
||||
{
|
||||
flags |= FORWARD_ANIM;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
flags &= ~FORWARD_ANIM;
|
||||
}
|
||||
|
||||
if (mode == osg::Sequence::SWING)
|
||||
{
|
||||
flags |= SWING_ANIM;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
flags &= ~SWING_ANIM;
|
||||
}
|
||||
|
||||
// Do we loop infinitely, or only a certain number of times?
|
||||
float speedUp;
|
||||
int numReps;
|
||||
sequence.getDuration(speedUp, numReps);
|
||||
|
||||
if (numReps != -1)
|
||||
{
|
||||
loopCount = numReps;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
loopCount = 0; // == loop continuously
|
||||
}
|
||||
|
||||
// Sum individual frame durations to get the total loopDuration
|
||||
for (unsigned int i = 0; i < sequence.getNumChildren(); ++i)
|
||||
{
|
||||
loopDuration += sequence.getTime(i);
|
||||
}
|
||||
|
||||
lastFrameDuration = sequence.getLastFrameTime();
|
||||
|
||||
writeGroup(sequence, flags, loopCount, loopDuration, lastFrameDuration);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::writeObject( const osg::Group& group, osgSim::ObjectRecordData* ord )
|
||||
{
|
||||
uint16 length( 28 );
|
||||
IdHelper id(*this, group.getName() );
|
||||
|
||||
if (!ord)
|
||||
{
|
||||
std::string warning( "fltexp: writeObject has invalid ObjectRecordData." );
|
||||
osg::notify( osg::WARN ) << warning << std::endl;
|
||||
_fltOpt->getWriteResult().warn( warning );
|
||||
return;
|
||||
}
|
||||
|
||||
_records->writeInt16( (int16) OBJECT_OP );
|
||||
_records->writeInt16( length );
|
||||
_records->writeID( id );
|
||||
_records->writeInt32( ord->_flags );
|
||||
_records->writeInt16( ord->_relativePriority );
|
||||
_records->writeUInt16( ord->_transparency );
|
||||
_records->writeUInt16( ord->_effectID1 );
|
||||
_records->writeUInt16( ord->_effectID2 );
|
||||
_records->writeUInt16( ord->_significance );
|
||||
_records->writeUInt16( 0 ); // reserved
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::writeDegreeOfFreedom( const osgSim::DOFTransform* dof )
|
||||
{
|
||||
const osg::Matrix& invPut = dof->getInversePutMatrix();
|
||||
|
||||
// Origin of DOF coord sys
|
||||
osg::Vec3d origin( invPut.getTrans() );
|
||||
|
||||
osg::Vec3 xAxis( invPut(0,0), invPut(0,1), invPut(0,2) );
|
||||
osg::Vec3 yAxis( invPut(1,0), invPut(1,1), invPut(1,2) );
|
||||
// Reference point along DOF coord sys's X axis
|
||||
osg::Vec3d pointOnXAxis = origin + xAxis;
|
||||
// Reference point in DOF coord sys's X-Y plane
|
||||
osg::Vec3d pointInXYPlane = origin + yAxis;
|
||||
|
||||
// Translations
|
||||
osg::Vec3d minTranslate( dof->getMinTranslate() );
|
||||
osg::Vec3d maxTranslate( dof->getMaxTranslate() );
|
||||
osg::Vec3d currTranslate( dof->getCurrentTranslate() );
|
||||
osg::Vec3d incrTranslate( dof->getIncrementTranslate() );
|
||||
|
||||
// Rotations
|
||||
osg::Vec3d minHPR( dof->getMinHPR() );
|
||||
osg::Vec3d maxHPR( dof->getMaxHPR() );
|
||||
osg::Vec3d currHPR( dof->getCurrentHPR() );
|
||||
osg::Vec3d incrHPR( dof->getIncrementHPR() );
|
||||
|
||||
// Scaling
|
||||
osg::Vec3d minScale( dof->getMinScale() );
|
||||
osg::Vec3d maxScale( dof->getMaxScale() );
|
||||
osg::Vec3d currScale( dof->getCurrentScale() );
|
||||
osg::Vec3d incrScale( dof->getIncrementScale() );
|
||||
|
||||
|
||||
uint16 length( 384 );
|
||||
IdHelper id(*this, dof->getName() );
|
||||
|
||||
_records->writeInt16( (int16) DOF_OP );
|
||||
_records->writeInt16( length );
|
||||
_records->writeID( id );
|
||||
_records->writeInt32( 0 ); // 'Reserved' (unused)
|
||||
_records->writeVec3d( origin );
|
||||
_records->writeVec3d( pointOnXAxis );
|
||||
_records->writeVec3d( pointInXYPlane );
|
||||
|
||||
// Translations
|
||||
_records->writeFloat64( minTranslate.z() );
|
||||
_records->writeFloat64( maxTranslate.z() );
|
||||
_records->writeFloat64( currTranslate.z() );
|
||||
_records->writeFloat64( incrTranslate.z() );
|
||||
|
||||
_records->writeFloat64( minTranslate.y() );
|
||||
_records->writeFloat64( maxTranslate.y() );
|
||||
_records->writeFloat64( currTranslate.y() );
|
||||
_records->writeFloat64( incrTranslate.y() );
|
||||
|
||||
_records->writeFloat64( minTranslate.x() );
|
||||
_records->writeFloat64( maxTranslate.x() );
|
||||
_records->writeFloat64( currTranslate.x() );
|
||||
_records->writeFloat64( incrTranslate.x() );
|
||||
|
||||
// Rotations: 0 = Yaw, 1 = Pitch, 2 = Roll
|
||||
_records->writeFloat64( osg::RadiansToDegrees(minHPR[1]) );
|
||||
_records->writeFloat64( osg::RadiansToDegrees(maxHPR[1]) );
|
||||
_records->writeFloat64( osg::RadiansToDegrees(currHPR[1]) );
|
||||
_records->writeFloat64( osg::RadiansToDegrees(incrHPR[1]) );
|
||||
|
||||
_records->writeFloat64( osg::RadiansToDegrees(minHPR[2]) );
|
||||
_records->writeFloat64( osg::RadiansToDegrees(maxHPR[2]) );
|
||||
_records->writeFloat64( osg::RadiansToDegrees(currHPR[2]) );
|
||||
_records->writeFloat64( osg::RadiansToDegrees(incrHPR[2]) );
|
||||
|
||||
_records->writeFloat64( osg::RadiansToDegrees(minHPR[0]) );
|
||||
_records->writeFloat64( osg::RadiansToDegrees(maxHPR[0]) );
|
||||
_records->writeFloat64( osg::RadiansToDegrees(currHPR[0]) );
|
||||
_records->writeFloat64( osg::RadiansToDegrees(incrHPR[0]) );
|
||||
|
||||
// Scaling
|
||||
_records->writeFloat64( minScale.z() );
|
||||
_records->writeFloat64( maxScale.z() );
|
||||
_records->writeFloat64( currScale.z() );
|
||||
_records->writeFloat64( incrScale.z() );
|
||||
|
||||
_records->writeFloat64( minScale.y() );
|
||||
_records->writeFloat64( maxScale.y() );
|
||||
_records->writeFloat64( currScale.y() );
|
||||
_records->writeFloat64( incrScale.y() );
|
||||
|
||||
_records->writeFloat64( minScale.x() );
|
||||
_records->writeFloat64( maxScale.x() );
|
||||
_records->writeFloat64( currScale.x() );
|
||||
_records->writeFloat64( incrScale.y() );
|
||||
|
||||
_records->writeInt32( dof->getLimitationFlags() ); // Constraint flags
|
||||
_records->writeInt32( 0 ); // 'Reserved' (unused)
|
||||
|
||||
}
|
||||
|
||||
// Parent pool override flags
|
||||
static const unsigned long COLOR_PALETTE_OVERRIDE = 0x80000000u >> 0;
|
||||
static const unsigned long MATERIAL_PALETTE_OVERRIDE = 0x80000000u >> 1;
|
||||
static const unsigned long TEXTURE_PALETTE_OVERRIDE = 0x80000000u >> 2;
|
||||
static const unsigned long LINE_STYLE_PALETTE_OVERRIDE = 0x80000000u >> 3;
|
||||
static const unsigned long SOUND_PALETTE_OVERRIDE = 0x80000000u >> 4;
|
||||
static const unsigned long LIGHT_SOURCE_PALETTE_OVERRIDE = 0x80000000u >> 5;
|
||||
static const unsigned long LIGHT_POINT_PALETTE_OVERRIDE = 0x80000000u >> 6;
|
||||
static const unsigned long SHADER_PALETTE_OVERRIDE = 0x80000000u >> 7;
|
||||
|
||||
void
|
||||
FltExportVisitor::writeExternalReference( const osg::ProxyNode& proxy )
|
||||
{
|
||||
uint16 length( 216 );
|
||||
|
||||
// Set sane defaults for the override flags
|
||||
unsigned long flags = COLOR_PALETTE_OVERRIDE |
|
||||
MATERIAL_PALETTE_OVERRIDE |
|
||||
TEXTURE_PALETTE_OVERRIDE |
|
||||
LIGHT_POINT_PALETTE_OVERRIDE |
|
||||
SHADER_PALETTE_OVERRIDE ;
|
||||
|
||||
// Selectively turn off overrides for resources we don't need
|
||||
const ParentPools* pp = static_cast<const ParentPools*>(proxy.getUserData() );
|
||||
if (pp && pp->getColorPool() )
|
||||
flags &= ~COLOR_PALETTE_OVERRIDE;
|
||||
|
||||
if (pp && pp->getMaterialPool() )
|
||||
flags &= ~MATERIAL_PALETTE_OVERRIDE;
|
||||
|
||||
if (pp && pp->getTexturePool() )
|
||||
flags &= ~TEXTURE_PALETTE_OVERRIDE;
|
||||
|
||||
if (pp && pp->getLightSourcePool() )
|
||||
flags &= ~LIGHT_SOURCE_PALETTE_OVERRIDE;
|
||||
|
||||
if (pp && pp->getLPAppearancePool() )
|
||||
flags &= ~LIGHT_POINT_PALETTE_OVERRIDE;
|
||||
|
||||
if (pp && pp->getShaderPool() )
|
||||
flags &= ~SHADER_PALETTE_OVERRIDE;
|
||||
|
||||
_records->writeInt16( (int16) EXTERNAL_REFERENCE_OP );
|
||||
_records->writeInt16( length );
|
||||
_records->writeString(proxy.getFileName(0), 200);
|
||||
_records->writeInt32(0); // Reserved
|
||||
_records->writeInt32(flags);
|
||||
_records->writeInt16(0); // ViewAsBoundingBox flag
|
||||
_records->writeInt16(0); // Reserved
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::writeLevelOfDetail( const osg::LOD& lod,
|
||||
osg::Vec3d const& center,
|
||||
double switchInDist,
|
||||
double switchOutDist)
|
||||
{
|
||||
uint16 length( 80 );
|
||||
IdHelper id(*this, lod.getName() );
|
||||
|
||||
_records->writeInt16( (int16) LOD_OP );
|
||||
_records->writeInt16( length );
|
||||
_records->writeID( id );
|
||||
_records->writeInt32( 0 ); // 'Reserved' field
|
||||
_records->writeFloat64( switchInDist );
|
||||
_records->writeFloat64( switchOutDist ); // Switch-out distance
|
||||
_records->writeInt16( 0 ); // Special Effect ID1
|
||||
_records->writeInt16( 0 ); // Special Effect ID2
|
||||
_records->writeInt32( 0 ); // Flags
|
||||
_records->writeFloat64( center.x() );
|
||||
_records->writeFloat64( center.y() );
|
||||
_records->writeFloat64( center.z() );
|
||||
_records->writeFloat64( 0 ); // Transition range
|
||||
_records->writeFloat64( 0 ); // Significant size
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::writeLightSource( const osg::LightSource& node )
|
||||
{
|
||||
|
||||
static const unsigned int ENABLED = 0x80000000u >> 0;
|
||||
static const unsigned int GLOBAL = 0x80000000u >> 1;
|
||||
|
||||
osg::Light const* light = node.getLight();
|
||||
int index = _lightSourcePalette->add(light);
|
||||
|
||||
osg::Vec4d const& lightPos = light->getPosition();
|
||||
osg::Vec3f const& lightDir = light->getDirection();
|
||||
|
||||
uint32 flags = 0;
|
||||
osg::StateSet const* ss = getCurrentStateSet();
|
||||
if (ss->getMode(GL_LIGHT0 + light->getLightNum() ) & osg::StateAttribute::ON)
|
||||
{
|
||||
flags |= ENABLED;
|
||||
}
|
||||
|
||||
// If this light is enabled for the node at the top of our StateSet stack,
|
||||
// assume it is 'global' for OpenFlight's purposes
|
||||
ss = _stateSetStack.front().get();
|
||||
if (ss->getMode(GL_LIGHT0 + light->getLightNum() ) & osg::StateAttribute::ON)
|
||||
{
|
||||
flags |= GLOBAL;
|
||||
}
|
||||
|
||||
uint16 length( 64 );
|
||||
IdHelper id(*this, node.getName() );
|
||||
|
||||
_records->writeInt16( (int16) LIGHT_SOURCE_OP );
|
||||
_records->writeInt16( length );
|
||||
_records->writeID( id );
|
||||
_records->writeInt32( 0 ); // Reserved
|
||||
_records->writeInt32( index ); // Index into light source palette
|
||||
_records->writeInt32( 0 ); // Reserved
|
||||
_records->writeUInt32( flags ); // Flags
|
||||
_records->writeInt32( 0 ); // Reserved
|
||||
_records->writeVec3d( osg::Vec3d(
|
||||
lightPos.x() , lightPos.y() , lightPos.z() ) );
|
||||
|
||||
// TODO: Verify that indices 0 and 1 correspond to yaw and pitch
|
||||
_records->writeFloat32( lightDir[0] ); // Yaw
|
||||
_records->writeFloat32( lightDir[1] ); // Pitch
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::writeSwitch( const osgSim::MultiSwitch* ms )
|
||||
{
|
||||
int32 currMask = ms->getActiveSwitchSet();
|
||||
int32 numMasks = ms->getSwitchSetList().size();
|
||||
int32 numWordsPerMask = ms->getNumChildren() / 32;
|
||||
if (ms->getNumChildren() % 32 != 0) ++numWordsPerMask;
|
||||
|
||||
uint16 length( 28 + numMasks * numWordsPerMask * sizeof(int32) );
|
||||
IdHelper id(*this, ms->getName() );
|
||||
|
||||
_records->writeInt16( (int16) SWITCH_OP );
|
||||
_records->writeInt16( length );
|
||||
_records->writeID( id );
|
||||
_records->writeInt32( 0 ); // <-- 'Reserved' (unused)
|
||||
_records->writeInt32( currMask );
|
||||
_records->writeInt32( numMasks );
|
||||
_records->writeInt32( numWordsPerMask );
|
||||
|
||||
// For each mask...
|
||||
for (int i = 0; i < numMasks; ++i)
|
||||
{
|
||||
// ... write out the set of 32-bit words comprising the mask
|
||||
uint32 maskWord = 0;
|
||||
const osgSim::MultiSwitch::ValueList& maskBits = ms->getValueList(i);
|
||||
|
||||
for (size_t j = 0; j < maskBits.size(); ++j)
|
||||
{
|
||||
// If this bit is set, set the corresponding mask word
|
||||
if (maskBits[j]) maskWord |= 1 << (j % 32);
|
||||
|
||||
// If we just set the 31st (last) bit of the current word, need
|
||||
// to write it out and reset prior to continuing the loop
|
||||
if ( (j + 1) % 32 == 0 )
|
||||
{
|
||||
_records->writeUInt32(maskWord);
|
||||
maskWord = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If the mask size wasn't a multiple of 32, need to write out
|
||||
// the final word containing the 'remainder' bits
|
||||
if (maskBits.size() % 32 != 0)
|
||||
{
|
||||
_records->writeUInt32(maskWord);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::writeSwitch( const osg::Switch* sw )
|
||||
{
|
||||
// An osg::Switch is just a special case of an osgSim::MultiSwitch
|
||||
// that only has a single mask
|
||||
int32 currMask = 0;
|
||||
int32 numMasks = 1;
|
||||
int32 numWordsPerMask = sw->getNumChildren() / 32;
|
||||
if (sw->getNumChildren() % 32 != 0) ++numWordsPerMask;
|
||||
|
||||
uint16 length( 28 + numMasks * numWordsPerMask * sizeof(int32) );
|
||||
IdHelper id(*this, sw->getName() );
|
||||
|
||||
_records->writeInt16( (int16) SWITCH_OP );
|
||||
_records->writeInt16( length );
|
||||
_records->writeID( id );
|
||||
_records->writeInt32( 0 ); // <-- 'Reserved' (unused)
|
||||
_records->writeInt32( currMask );
|
||||
_records->writeInt32( numMasks );
|
||||
_records->writeInt32( numWordsPerMask );
|
||||
|
||||
// Bust the mask up into as many 32-bit words as are necessary to hold it
|
||||
uint32 maskWord = 0;
|
||||
const osg::Switch::ValueList& maskBits = sw->getValueList();
|
||||
|
||||
for (size_t i = 0; i < maskBits.size(); ++i)
|
||||
{
|
||||
// If this bit is set, set the corresponding mask word
|
||||
if (maskBits[i]) maskWord |= 1 << (i % 32);
|
||||
|
||||
// If we just set the 31st (last) bit of the current word, need
|
||||
// to write it out and reset prior to continuing the loop
|
||||
if ( (i + 1) % 32 == 0 )
|
||||
{
|
||||
_records->writeUInt32(maskWord);
|
||||
maskWord = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If the mask size wasn't a multiple of 32, need to write out
|
||||
// the final word containing the 'remainder' bits
|
||||
if (maskBits.size() % 32 != 0)
|
||||
{
|
||||
_records->writeUInt32(maskWord);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
FltExportVisitor::writeLightPoint( const osgSim::LightPointNode* lpn )
|
||||
{
|
||||
enum Directionality
|
||||
{
|
||||
OMNIDIRECTIONAL = 0,
|
||||
UNIDIRECTIONAL = 1,
|
||||
BIDIRECTIONAL = 2
|
||||
};
|
||||
enum DisplayMode
|
||||
{
|
||||
RASTER = 0,
|
||||
CALLIG = 1,
|
||||
EITHER = 2
|
||||
};
|
||||
enum Modes
|
||||
{
|
||||
ENABLE = 0,
|
||||
DISABLE = 1
|
||||
};
|
||||
enum Flags
|
||||
{
|
||||
NO_BACK_COLOR = 0x80000000u >> 1,
|
||||
CALLIGRAPHIC = 0x80000000u >> 3,
|
||||
REFLECTIVE = 0x80000000u >> 4,
|
||||
PERSPECTIVE = 0x80000000u >> 8,
|
||||
FLASHING = 0x80000000u >> 9,
|
||||
ROTATING = 0x80000000u >> 10,
|
||||
ROTATE_CC = 0x80000000u >> 11,
|
||||
VISIBLE_DAY = 0x80000000u >> 15,
|
||||
VISIBLE_DUSK = 0x80000000u >> 16,
|
||||
VISIBLE_NIGHT = 0x80000000u >> 17
|
||||
};
|
||||
int32 flags( NO_BACK_COLOR );
|
||||
|
||||
if (lpn->getNumLightPoints() == 0)
|
||||
return;
|
||||
|
||||
// In OSG, each LightPoint within a LightPointNode can have different appearance
|
||||
// parameters, but in OpenFlight, a Light Point Record contains a list of homogenous
|
||||
// vertices. To be correct, we'd have to look at all LightPoints in the LightPointNode
|
||||
// and spew out multiple FLT records for each group that shared common appearance
|
||||
// parameters. Instead, we cheat: We take the first LightPoint and use its appearance
|
||||
// parameters for all LightPoints in the LightPointNode.
|
||||
const osgSim::LightPoint& lp0 = lpn->getLightPoint( 0 );
|
||||
|
||||
// No really good mapping between OSG and FLT light point animations.
|
||||
float32 animPeriod( 0.f );
|
||||
float32 animEnabled( 0.f );
|
||||
float32 animPhaseDelay( 0.f );
|
||||
if (lp0._blinkSequence != NULL)
|
||||
{
|
||||
flags |= FLASHING;
|
||||
animPeriod = 4.f;
|
||||
animEnabled = 2.f;
|
||||
animPhaseDelay = lp0._blinkSequence->getPhaseShift();
|
||||
}
|
||||
|
||||
// Note that true bidirectional light points are currently unsupported (they are inavailable
|
||||
// in OSG, so we never write them out to FLT as BIDIRECTIONAL.
|
||||
int32 directionality( OMNIDIRECTIONAL );
|
||||
float32 horizLobe( 360.f );
|
||||
float32 vertLobe( 360.f );
|
||||
float32 lobeRoll( 0.f );
|
||||
const osgSim::DirectionalSector* ds = dynamic_cast< osgSim::DirectionalSector* >( lp0._sector.get() );
|
||||
if (ds)
|
||||
{
|
||||
directionality = UNIDIRECTIONAL;
|
||||
horizLobe = osg::RadiansToDegrees( ds->getHorizLobeAngle() );
|
||||
vertLobe = osg::RadiansToDegrees( ds->getVertLobeAngle() );
|
||||
lobeRoll = osg::RadiansToDegrees( ds->getLobeRollAngle() );
|
||||
}
|
||||
|
||||
{
|
||||
// Braces req'd to invoke idHelper destructor (and potentially
|
||||
// write LongID record) before Push Record.
|
||||
|
||||
const uint16 length( 156 );
|
||||
IdHelper id( *this, lpn->getName() );
|
||||
|
||||
_records->writeInt16( (int16) LIGHT_POINT_OP );
|
||||
_records->writeInt16( length );
|
||||
_records->writeID( id );
|
||||
_records->writeInt16( 0 ); // Surface material code
|
||||
_records->writeInt16( 0 ); // Feature ID
|
||||
_records->writeUInt32( -1 ); // Back color for bidirectional
|
||||
_records->writeInt32( EITHER ); // Display mode
|
||||
_records->writeFloat32( lp0._intensity ); // Intensity
|
||||
_records->writeFloat32( 0.f ); // Back intensity TBD
|
||||
_records->writeFloat32( 0.f ); // min defocus
|
||||
_records->writeFloat32( 0.f ); // max defocus
|
||||
_records->writeInt32( DISABLE ); // Fading mode
|
||||
_records->writeInt32( DISABLE ); // Fog punch mode
|
||||
_records->writeInt32( DISABLE ); // Directional mode
|
||||
_records->writeInt32( 0 ); // Range mode
|
||||
_records->writeFloat32( lpn->getMinPixelSize() ); // min pixel size
|
||||
_records->writeFloat32( lpn->getMaxPixelSize() ); // max pixel size
|
||||
_records->writeFloat32( lp0._radius * 2.f ); // Actual size
|
||||
_records->writeFloat32( 1.f ); // transparent falloff pixel size
|
||||
_records->writeFloat32( 1.f ); // Transparent falloff exponent
|
||||
_records->writeFloat32( 1.f ); // Transparent falloff scalar
|
||||
_records->writeFloat32( 0.f ); // Transparent falloff clamp
|
||||
_records->writeFloat32( 1.f ); // Fog scalar
|
||||
_records->writeFloat32( 0.f ); // Reserved
|
||||
_records->writeFloat32( 0.f ); // Size difference threshold
|
||||
_records->writeInt32( directionality ); // Directionality
|
||||
_records->writeFloat32( horizLobe ); // Horizontal lobe angle
|
||||
_records->writeFloat32( vertLobe ); // Vertical lobe angle
|
||||
_records->writeFloat32( lobeRoll ); // Lobe roll angle
|
||||
_records->writeFloat32( 0.f ); // Directional falloff exponent
|
||||
_records->writeFloat32( 0.f ); // Directional ambient intensity
|
||||
_records->writeFloat32( animPeriod ); // Animation period in seconds
|
||||
_records->writeFloat32( animPhaseDelay ); // Animation phase delay in secnds
|
||||
_records->writeFloat32( animEnabled ); // Animation enabled period in seconds
|
||||
_records->writeFloat32( 1.f ); // Significance
|
||||
_records->writeInt32( 0 ); // Calligraphic draw order
|
||||
_records->writeInt32( flags ); // Flags
|
||||
_records->writeVec3f( osg::Vec3f( 0.f, 0.f, 0.f ) ); // Axis of rotation
|
||||
}
|
||||
|
||||
{
|
||||
osg::ref_ptr< osg::Vec3Array > v = new osg::Vec3Array( lpn->getNumLightPoints() );
|
||||
osg::ref_ptr< osg::Vec4Array > c = new osg::Vec4Array( lpn->getNumLightPoints() );
|
||||
osg::ref_ptr< osg::Vec3Array > n = new osg::Vec3Array( lpn->getNumLightPoints() );
|
||||
osg::Vec3f normal( 0.f, 0.f, 1.f );
|
||||
|
||||
unsigned int idx;
|
||||
for( idx=0; idx<lpn->getNumLightPoints(); idx++)
|
||||
{
|
||||
const osgSim::LightPoint& lp = lpn->getLightPoint( idx );
|
||||
(*v)[ idx ] = lp._position;
|
||||
(*c)[ idx ] = lp._color;
|
||||
|
||||
const osgSim::DirectionalSector* ds = dynamic_cast< osgSim::DirectionalSector* >( lp._sector.get() );
|
||||
if (ds)
|
||||
normal = ds->getDirection();
|
||||
(*n)[ idx ] = normal;
|
||||
}
|
||||
_vertexPalette->add( v.get(), c.get(), n.get(), NULL, true, true, false );
|
||||
}
|
||||
|
||||
writeMatrix( lpn->getUserData() );
|
||||
writeComment( *lpn );
|
||||
writePush();
|
||||
writeVertexList( 0, lpn->getNumLightPoints() );
|
||||
writePop();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FltExportVisitor::writeColorPalette()
|
||||
{
|
||||
// FLT exporter doesn't use a color palette but writes
|
||||
// a bogus one to satisfy loaders that require it.
|
||||
uint16 length( 4228 );
|
||||
|
||||
_dos.writeInt16( (int16) COLOR_PALETTE_OP );
|
||||
_dos.writeInt16( length );
|
||||
_dos.writeFill( 128 ); // Reserved
|
||||
int idx;
|
||||
for( idx=0; idx<1024; idx++)
|
||||
_dos.writeUInt32( 0xffffffff ); // Color n
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user