Submission from Perry Miller for support of OpenFlight15.7's local vertex pool

and mesh primitives.  Converted Perry's code to work with the osg::Geometry
instead of osg::GeoSet.
This commit is contained in:
Robert Osfield
2002-08-15 11:25:23 +00:00
parent 7d00b3b729
commit 61e3b34bc7
20 changed files with 1432 additions and 449 deletions

View File

@@ -1,832 +1,440 @@
# Microsoft Developer Studio Project File - Name="osgPlugin flt" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=osgPlugin flt - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "flt.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "flt.mak" CFG="osgPlugin flt - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "osgPlugin flt - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "osgPlugin flt - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "osgPlugin flt - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FLT_LIBRARY" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x414 /d "NDEBUG"
# ADD RSC /l 0x417 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 /nologo /dll /pdb:none /machine:I386 /out:"../../../bin/osgdb_flt.dll" /libpath:"../../../lib"
!ELSEIF "$(CFG)" == "osgPlugin flt - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "../../../lib"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /vmg /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FLT_LIBRARY" /D "WIN32" /D "_DEBUG" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x414 /d "_DEBUG"
# ADD RSC /l 0x417 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 /nologo /dll /pdb:"../../../bin/osgdb_fltd.pdb" /debug /machine:I386 /out:"../../../bin/osgdb_fltd.dll" /pdbtype:sept /libpath:"../../../lib"
# SUBTRACT LINK32 /pdb:none /incremental:no
!ENDIF
# Begin Target
# Name "osgPlugin flt - Win32 Release"
# Name "osgPlugin flt - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\BoundingVolumeRecords.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ColorPaletteRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\CommentRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ControlRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\DofRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ExtensionRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ExternalRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\FaceRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\flt.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\flt2osg.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\FltFile.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\GeoSetBuilder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\GroupRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\HeaderRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\Input.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\InstanceRecords.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LightPointRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LightSourcePaletteRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LightSourceRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LocalVertexPoolRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\MeshPrimitiveRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\MeshRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LodRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LongIDRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\MaterialPaletteRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ObjectRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\OldMaterialPaletteRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\OldVertexRecords.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\Pool.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ReaderWriterATTR.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ReaderWriterFLT.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\Record.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\RecordVisitor.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\RoadRecords.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\Registry.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\SwitchRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\TextureMappingPaletteRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\TexturePaletteRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\TransformationRecords.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\UnknownRecord.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\VertexPoolRecords.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;"
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\BoundingVolumeRecords.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ColorPaletteRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\CommentRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ControlRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\DofRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ExtensionRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ExternalRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\FaceRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\flt.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\flt2osg.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\FltFile.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\FltRecords.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\GeoSetBuilder.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\GroupRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\HeaderRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\Input.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\InstanceRecords.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LightPointRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LightSourcePaletteRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LightSourceRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LocalVertexPoolRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\MeshPrimitiveRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\MeshRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LodRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\LongIDRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\MaterialPaletteRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ObjectRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\OldMaterialPaletteRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\OldVertexRecords.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\opcodes.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\Pool.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\ReaderWriterFLT.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\Record.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\RecordVisitor.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\RoadRecords.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\Registry.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\SwitchRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\TextureMappingPaletteRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\TexturePaletteRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\TransformationRecords.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\UnknownRecord.h
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\VertexPoolRecords.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\flt\license.txt
# End Source File
# End Group
# End Target
# End Project

View File

@@ -213,7 +213,7 @@ void FltFile::readExternals()
}
int FltFile::getFlightVersion()
int FltFile::getFlightVersion() const
{
if (_headerRecord.get())
{

View File

@@ -44,7 +44,7 @@ class FltFile : public osg::Referenced
inline const bool useInternalTexturePalette() const { return _useInternalTexturePalette; }
inline const bool useInternalMaterialPalette() const { return _useInternalMaterialPalette; }
int getFlightVersion();
int getFlightVersion() const;
inline HeaderRecord* getHeaderRecord() { return _headerRecord.get(); }
protected:

View File

@@ -117,6 +117,17 @@ void HeaderRecord::endian()
ENDIAN( pHeader->dfLambertUpperLat );
ENDIAN( pHeader->dfLambertLowerLat );
ENDIAN( pHeader->iNextLightSource );
// New with 15.7
// Note: Don't use "getFltFile()->getFlightVersion()", it's not set yet.
if ( pHeader->diFormatRevLev >= 1570 )
{
ENDIAN( pHeader->iNextAdaptiveNodeID );
ENDIAN( pHeader->iNextCurveNodeID );
ENDIAN( pHeader->dfDatabaseDeltaZ );
ENDIAN( pHeader->dfRadius );
ENDIAN( pHeader->iNextMeshNodeID );
}
}

View File

@@ -81,6 +81,18 @@ struct SHeader
// 2 - Bessel
// 3 - Clarke 1866
// 4 - NAD 1927
// New with 15.7.0 ...
int16 iNextAdaptiveNodeID; // Next Adaptive node ID number
int16 iNextCurveNodeID; // Next Curve node ID number
int16 iReserved_5; // Reserved
float64 dfDatabaseDeltaZ; // Delta z to place database (used in
// conjunction with existing Delta x and
// Delta y values)
float64 dfRadius; // Radius (distance from database origin to
// farthest corner)
uint16 iNextMeshNodeID; // Next Mesh node ID number
uint16 iReserved_6; // Reserved
};

View File

@@ -1,3 +1,9 @@
// Input.cpp
#include <string>
// #include <malloc.h>
#include <assert.h>
#include <osg/Notify>
#include <osgDB/FileUtils>
@@ -180,14 +186,14 @@ Record* Input::readCreateRecord(FltFile* pFltFile)
pRec->_pFltFile = pFltFile;
#if 0
osg::notify(osg::ALWAYS) << "class=" << pRec->className();
osg::notify(osg::ALWAYS) << " op=" << pRec->getOpcode();
osg::notify(osg::ALWAYS) << " name=" << pRec->getName();
osg::notify(osg::ALWAYS) << " offset=" << offset() << std::endl;
osg::notify(osg::ALWAYS) << "class = " << pRec->className();
osg::notify(osg::ALWAYS) << " op = " << pRec->getOpcode();
osg::notify(osg::ALWAYS) << " name = " << pRec->getName();
osg::notify(osg::ALWAYS) << " offset = " << offset() << std::endl;
#endif
if (isLittleEndianMachine()) // From Intel with love :-(
pRec->endian();
// Perform any post-read initializations.
pRec->postReadInit();
return pRec;
}

View File

@@ -0,0 +1,523 @@
// LocalVertexPoolRecords.cpp
#ifdef _WIN32
#pragma warning(disable:4786) // Truncated debug names.
#endif
#include "LocalVertexPoolRecord.h"
#include "Registry.h"
#include <assert.h>
// The sizes (in bytes) of the various attribute sections of the vertex data.
#define SIZE_POSITION 24 // 3 * float64 = 3 * 8
#define SIZE_COLOR 4 // 1 uint32
#define SIZE_NORMAL 12 // 3 * float32 = 3 * 4
#define SIZE_BASE_UV 8 // 2 * float32 = 2 * 4
#define SIZE_UV_1 SIZE_BASE_UV
#define SIZE_UV_2 SIZE_BASE_UV
#define SIZE_UV_3 SIZE_BASE_UV
#define SIZE_UV_4 SIZE_BASE_UV
#define SIZE_UV_5 SIZE_BASE_UV
#define SIZE_UV_6 SIZE_BASE_UV
#define SIZE_UV_7 SIZE_BASE_UV
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// LocalVertexPoolRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<LocalVertexPoolRecord> g_LocalVertexPoolProxy;
LocalVertexPoolRecord *_current = NULL;
LocalVertexPoolRecord::LocalVertexPoolRecord() : AncillaryRecord()
{
}
// virtual
LocalVertexPoolRecord::~LocalVertexPoolRecord()
{
}
///////////////////////////////////////////////////////////////////////////////
//
// Return the address of the beginning of the vertices.
//
///////////////////////////////////////////////////////////////////////////////
char *LocalVertexPoolRecord::_getStartOfVertices() const
{
SLocalVertexPool *pool = (SLocalVertexPool *) this->getData();
char *vertex = (char *) (&(pool[1]));
return vertex;
}
///////////////////////////////////////////////////////////////////////////////
//
// Return the address of the beginning of the specified vertex attribute.
//
///////////////////////////////////////////////////////////////////////////////
char *LocalVertexPoolRecord::_getStartOfAttribute ( const uint32 &whichVertex, const uint32 &offset ) const
{
assert ( whichVertex < this->getNumVertices() );
// Get pointer to start of vertex data.
char *startOfVertices = (char *) this->_getStartOfVertices();
// The size of all the vertex information is the size of the entire record
// minus the size of the record's header.
size_t sizeOfAllVertices = _pData->_wLength - sizeof ( SLocalVertexPool );
// The number of vertices.
uint32 numVertices = this->getNumVertices();
// The size of each individual vertex is the size of all of them divided by
// how many there are.
size_t sizeOfVertex = sizeOfAllVertices / numVertices;
// If we're doing the math right (and the record data is good) then there
// should not be a remainder when doing the integer division above.
assert ( 0 == ( sizeOfAllVertices % numVertices ) );
assert ( 0 == ( sizeOfAllVertices % sizeOfVertex ) );
assert ( sizeOfAllVertices == sizeOfVertex * numVertices );
// Set the start of the desired vertex's data.
char *startOfAttribute = &startOfVertices[whichVertex * sizeOfVertex];
// Now adjust for the offset within this vertex.
startOfAttribute += offset;
// Should be true. It means that the address we are returning should not be
// greater than the start of the last vertex's attribute.
assert ( ( ( (uint32) startOfAttribute ) - ( (uint32) startOfVertices ) ) <= ( sizeOfAllVertices - sizeOfVertex + offset ) );
// Double check, make sure we are not off the end of this record.
assert ( ( ( (uint32) startOfAttribute ) - ( (uint32) startOfVertices ) ) < sizeOfAllVertices );
// Return the pointer.
return startOfAttribute;
}
///////////////////////////////////////////////////////////////////////////////
//
// Return the specified vertex attribute.
//
///////////////////////////////////////////////////////////////////////////////
bool LocalVertexPoolRecord::getColorIndex ( const uint32 &whichVertex, uint32 &colorIndex ) const
{
ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, COLOR_INDEX );
// Offset to the start of the color.
uint32 *color = (uint32 *) this->_getStartOfAttribute ( whichVertex, _offset.color );
if ( NULL == color )
return false;
// Set the color index and return.
colorIndex = *color;
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// Return the specified vertex attribute.
//
///////////////////////////////////////////////////////////////////////////////
bool LocalVertexPoolRecord::getColorRGBA ( const uint32 &whichVertex, float32 &r, float32 &g, float32 &b, float32 &a ) const
{
ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, RGB_COLOR );
// Offset to the start of the color.
uint32 *color = (uint32 *) this->_getStartOfAttribute ( whichVertex, _offset.color );
if ( NULL == color )
return false;
// Since we already byte-swapped, we have to check the endian of this
// machine so that we know how to grab the channels.
uint32 red, green, blue, alpha;
// If this machine is little-endian...
if ( flt::isLittleEndianMachine() )
{
red = ( ( (*color) & 0xFF000000 ) >> 0 );
green = ( ( (*color) & 0x00FF0000 ) >> 8 );
blue = ( ( (*color) & 0x0000FF00 ) >> 16 );
alpha = ( ( (*color) & 0x000000FF ) >> 24 );
}
// Otherwise, big-endian...
else
{
red = ( ( (*color) & 0x000000FF ) >> 0 );
green = ( ( (*color) & 0x0000FF00 ) >> 8 );
blue = ( ( (*color) & 0x00FF0000 ) >> 16 );
alpha = ( ( (*color) & 0xFF000000 ) >> 24 );
}
// Normalize.
float32 scale = 1.0f / 255.0f;
r = scale * red;
g = scale * green;
b = scale * blue;
a = scale * alpha;
// It worked.
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// Return the specified vertex attribute.
//
///////////////////////////////////////////////////////////////////////////////
bool LocalVertexPoolRecord::getNormal ( const uint32 &whichVertex, float32 &nx, float32 &ny, float32 &nz ) const
{
ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, NORMAL );
// Offset to the start of the normals.
float32 *vec = (float32 *) this->_getStartOfAttribute ( whichVertex, _offset.normal );
if ( NULL == vec )
return false;
// Set the normal vector and return.
nx = vec[0];
ny = vec[1];
nz = vec[2];
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// Return the specified vertex attribute.
//
///////////////////////////////////////////////////////////////////////////////
bool LocalVertexPoolRecord::getPosition ( const uint32 &whichVertex, float64 &px, float64 &py, float64 &pz ) const
{
ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, POSITION );
// Offset to the start of the normals.
float64 *point = (float64 *) this->_getStartOfAttribute ( whichVertex, _offset.position );
if ( NULL == point )
return false;
// Set the normal vector and return.
px = point[0];
py = point[1];
pz = point[2];
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// Return the specified vertex attribute.
//
///////////////////////////////////////////////////////////////////////////////
bool LocalVertexPoolRecord::getUV ( const uint32 &whichVertex, const AttributeMask &whichUV, float32 &u, float32 &v ) const
{
ARGUMENT_CHECK_FOR_GET_FUNCTION ( whichVertex, (uint32) whichUV );
// Offset to the start of the normals.
float32 *uv = (float32 *) this->_getStartOfAttribute ( whichVertex, this->_getOffset ( whichUV ) );
if ( NULL == uv )
return false;
// Set the normal vector and return.
u = uv[0];
v = uv[1];
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// Getthe offset that corresponds to the given attribute.
//
///////////////////////////////////////////////////////////////////////////////
uint32 LocalVertexPoolRecord::_getOffset ( const AttributeMask &attribute ) const
{
switch ( attribute )
{
case POSITION: return _offset.position;
case COLOR_INDEX: return _offset.color;
case RGB_COLOR: return _offset.color;
case NORMAL: return _offset.normal;
case BASE_UV: return _offset.baseUV;
case UV_1: return _offset.uv1;
case UV_2: return _offset.uv2;
case UV_3: return _offset.uv3;
case UV_4: return _offset.uv4;
case UV_5: return _offset.uv5;
case UV_6: return _offset.uv6;
case UV_7: return _offset.uv7;
default:
assert ( 0 );
return 0;
}
}
///////////////////////////////////////////////////////////////////////////////
//
// Convert the data from big-endian to little-endian.
//
///////////////////////////////////////////////////////////////////////////////
void LocalVertexPoolRecord::endian()
{
// Should only be in here for little-endian machines.
assert ( flt::isLittleEndianMachine() );
// Get a pointer to the vertex pool structure. Note: The members of
// SLocalVertexPool have already been endian-corrected in
// _initAttributeOffsets().
SLocalVertexPool *pool = (SLocalVertexPool *) this->getData();
// Get pointer to start of vertex data.
char *vertex = this->_getStartOfVertices();
// Loop through the vertices and byte-swap the data.
for ( uint32 i = 0; i < pool->numVerts; ++i )
{
if ( this->hasAttribute ( POSITION ) )
{
// Get the size of the coordinates.
size_t size = sizeof ( float64 );
// Get the values.
float64 *x = (float64 *) vertex;
float64 *y = &(x[1]);
float64 *z = &(y[1]);
// Swap the data.
flt::swapBytes ( size, x );
flt::swapBytes ( size, y );
flt::swapBytes ( size, z );
// Move pointer to the end of this chunk of data.
vertex = (char *) ( &(z[1]) );
}
if ( this->hasAttribute ( COLOR_INDEX ) ||
this->hasAttribute ( RGB_COLOR ) )
{
// Get the size of the coordinates.
size_t size = sizeof ( uint32 );
// Get the value.
uint32 *color = (uint32 *) vertex;
// Swap the data.
flt::swapBytes ( size, color );
// Move pointer to the end of this chunk of data.
vertex = (char *) ( &(color[1]) );
}
if ( this->hasAttribute ( NORMAL ) )
{
// Get the size of the elements.
size_t size = sizeof ( float32 );
// Get the values.
float32 *x = (float32 *) vertex;
float32 *y = &(x[1]);
float32 *z = &(y[1]);
// Swap the data.
flt::swapBytes ( size, x );
flt::swapBytes ( size, y );
flt::swapBytes ( size, z );
// Move pointer to the end of this chunk of data.
vertex = (char *) ( &(z[1]) );
}
if ( this->hasAttribute ( BASE_UV ) ||
this->hasAttribute ( UV_1 ) ||
this->hasAttribute ( UV_2 ) ||
this->hasAttribute ( UV_3 ) ||
this->hasAttribute ( UV_4 ) ||
this->hasAttribute ( UV_5 ) ||
this->hasAttribute ( UV_6 ) ||
this->hasAttribute ( UV_7 ) )
{
// Get the size of the elements.
size_t size = sizeof ( float32 );
// Get the values.
float32 *u = (float32 *) vertex;
float32 *v = &(u[1]);
// Swap the data.
flt::swapBytes ( size, u );
flt::swapBytes ( size, v );
// Move pointer to the end of this chunk of data.
vertex = (char *) ( &(v[1]) );
}
}
// Should be true. It means that we walked the pointer "vertex" to the
// end of the record, but not past it.
assert ( pool->RecHeader._wLength == ( (uint16) ( ( ( (uint32) vertex ) - ( (uint32) pool ) ) ) ) );
}
///////////////////////////////////////////////////////////////////////////////
//
// The offsets to the start of each attribute depends on the what attributes
// are in the vertices. Here we initialize those integer data members.
//
///////////////////////////////////////////////////////////////////////////////
void LocalVertexPoolRecord::_initAttributeOffsets()
{
// When we get to here we just got done reading the data (i.e., it is still
// big-endian). Correct the endian of the members of SLocalVertexPool
// because we need the SLocalVertexPool::attributeMask to determine the
// offsets (but do not endian-correct the vertex data that follows). The
// rest of the data (the vertices) will be endian-corrected in endian().
// If we are on a little-endian machine...
if ( flt::isLittleEndianMachine() )
{
// Fix these data members.
SLocalVertexPool *pool = (SLocalVertexPool *) this->getData();
ENDIAN ( pool->numVerts );
ENDIAN ( pool->attributeMask );
}
// Initialize.
uint32 current = 0;
// The order is important because the data will be in this order. We drop
// down through here and set the offsets. Each time we update the current
// position so that we can set the next one.
if ( this->hasAttribute ( POSITION ) )
{
_offset.position = current;
current += SIZE_POSITION;
}
if ( this->hasAttribute ( COLOR_INDEX ) || this->hasAttribute ( RGB_COLOR ) )
{
// According to 15.7 manual, we should not have both flags.
assert ( false == ( this->hasAttribute ( COLOR_INDEX ) && this->hasAttribute ( RGB_COLOR ) ) );
_offset.color = current;
current += SIZE_COLOR;
}
if ( this->hasAttribute ( NORMAL ) )
{
_offset.normal = current;
current += SIZE_NORMAL;
}
if ( this->hasAttribute ( BASE_UV ) )
{
_offset.baseUV = current;
current += SIZE_BASE_UV;
}
if ( this->hasAttribute ( UV_1 ) )
{
_offset.uv1 = current;
current += SIZE_UV_1;
}
if ( this->hasAttribute ( UV_2 ) )
{
_offset.uv2 = current;
current += SIZE_UV_2;
}
if ( this->hasAttribute ( UV_3 ) )
{
_offset.uv3 = current;
current += SIZE_UV_3;
}
if ( this->hasAttribute ( UV_4 ) )
{
_offset.uv4 = current;
current += SIZE_UV_4;
}
if ( this->hasAttribute ( UV_5 ) )
{
_offset.uv5 = current;
current += SIZE_UV_5;
}
if ( this->hasAttribute ( UV_6 ) )
{
_offset.uv6 = current;
current += SIZE_UV_6;
}
if ( this->hasAttribute ( UV_7 ) )
{
_offset.uv7 = current;
current += SIZE_UV_7;
}
}
///////////////////////////////////////////////////////////////////////////////
//
// This is called after the record is read.
//
///////////////////////////////////////////////////////////////////////////////
void LocalVertexPoolRecord::postReadInit()
{
// Initialize the attribute offsets.
this->_initAttributeOffsets();
// Call the base class's function.
AncillaryRecord::postReadInit();
}
///////////////////////////////////////////////////////////////////////////////
//
// Make this instance the current one.
//
///////////////////////////////////////////////////////////////////////////////
void LocalVertexPoolRecord::makeCurrent()
{
_current = this;
}
///////////////////////////////////////////////////////////////////////////////
//
// Return the current instance.
//
///////////////////////////////////////////////////////////////////////////////
LocalVertexPoolRecord *LocalVertexPoolRecord::getCurrent()
{
return _current;
}

View File

@@ -0,0 +1,119 @@
// LocalVertexPoolRecord.h
#ifndef __FLT_LOCAL_VERTEX_POOL_RECORDS_H
#define __FLT_LOCAL_VERTEX_POOL_RECORDS_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
////////////////////////////////////////////////////////////////////
//
// LocalVertexPoolRecord
//
////////////////////////////////////////////////////////////////////
struct SLocalVertexPool // Local vertex info, new with 15.7
{
SRecHeader RecHeader; // Header (opcode and size)
uint32 numVerts; // Number of vertices contained in this record
uint32 attributeMask; // 32 bit mask indicating what kind of vertex information is contained in this vertex list. Bits are ordered from left to right (bit 1 is leftmost).
};
class LocalVertexPoolRecord : public AncillaryRecord
{
public:
enum AttributeMask
{
POSITION = 0x80000000, // Has Position - indicates that each vertex in the list includes x, y, and z coordinates (three double-precision floating point values)
COLOR_INDEX = 0x40000000, // Has Color Index- indicates that each vertex in the list includes a color value that is a color table index (one integer value)
RGB_COLOR = 0x20000000, // Has RGB Color - indicates that each vertex in the list includes a color value that is a packed RGB color value (one integer value) NOTE: Bits 2 and 3 are mutually exclusive - a vertex can have either a color index or an RGB color value or neither, but cannot have both a color index and an RGB value.
NORMAL = 0x10000000, // Has Normal - indicates that each vertex in the list includes a normal (three single-precision floating point values)
BASE_UV = 0x08000000, // Has Base UV - indicates that each vertex in the list includes uv texture coordinates for the base texture (two single-precision floating point values)
UV_1 = 0x04000000, // Has UV 1 - indicates that each vertex in the list includes uv texture coordinates for layer 1 (two single-precision floating point values)
UV_2 = 0x02000000, // Has UV 2 - indicates that each vertex in the list includes uv texture coordinates for layer 2 (two single-precision floating point values)
UV_3 = 0x01000000, // Has UV 3 - indicates that each vertex in the list includes uv texture coordinates for layer 3 (two single-precision floating point values)
UV_4 = 0x00800000, // Has UV 4 - indicates that each vertex in the list includes uv texture coordinates for layer 4 (two single-precision floating point values)
UV_5 = 0x00400000, // Has UV 5 - indicates that each vertex in the list includes uv texture coordinates for layer 5 (two single-precision floating point values)
UV_6 = 0x00200000, // Has UV 6 - indicates that each vertex in the list includes uv texture coordinates for layer 6 (two single-precision floating point values)
UV_7 = 0x00100000 // Has UV 7 - indicates that each vertex in the list includes uv texture coordinates for layer 7 (two single-precision floating point values)
};
LocalVertexPoolRecord();
virtual void accept ( RecordVisitor &rv ) { rv.apply ( *this ); }
virtual const char * className() const { return "LocalVertexPoolRecord"; }
virtual int classOpcode() const { return LOCAL_VERTEX_POOL_OP; }
virtual Record * clone() const { return new LocalVertexPoolRecord(); }
SLocalVertexPool * getData() const { return (SLocalVertexPool *) _pData; }
uint32 getNumVertices() const { return this->getData()->numVerts; }
// Vertex attributes.
bool getColorIndex ( const uint32 &whichVertex, uint32 &colorIndex ) const;
bool getColorRGBA ( const uint32 &whichVertex, float32 &r, float32 &g, float32 &b, float32 &a ) const;
bool getNormal ( const uint32 &whichVertex, float32 &nx, float32 &ny, float32 &nz ) const;
bool getPosition ( const uint32 &whichVertex, float64 &px, float64 &py, float64 &pz ) const;
bool getUV ( const uint32 &whichVertex, const AttributeMask &whichUV, float32 &u, float32 &v ) const;
bool hasAttribute ( const uint32 &bits ) const { return flt::hasBits ( this->getData()->attributeMask, bits ); }
bool isInRange ( const uint32 &i ) const { return i < this->getNumVertices(); }
virtual void postReadInit();
virtual size_t sizeofData() const { return sizeof ( SLocalVertexPool ); }
void makeCurrent();
static LocalVertexPoolRecord * getCurrent();
protected:
class Offset
{
public:
uint32 position, color, normal, baseUV, uv1, uv2, uv3, uv4, uv5, uv6, uv7;
Offset() : position ( 0 ), color ( 0 ), normal ( 0 ), baseUV ( 0 ), uv1 ( 0 ), uv2 ( 0 ), uv3 ( 0 ), uv4 ( 0 ), uv5 ( 0 ), uv6 ( 0 ), uv7 ( 0 ){}
} _offset;
virtual ~LocalVertexPoolRecord();
virtual void endian();
uint32 _getOffset ( const AttributeMask &attribute ) const;
char * _getStartOfVertices() const;
char * _getStartOfAttribute ( const uint32 &whichVertex, const uint32 &attributeOffset ) const;
void _initAttributeOffsets();
};
}; // end namespace flt
///////////////////////////////////////////////////////////////////////////////
//
// Used in cpp file. Put it here because (if memory serves) gcc doesn't like
// macros in cpp files, only headers. If this is wrong then move to cpp file.
//
// Note: Asking for an attribute the vertex does not have will just return
// false. However, asking for a vertex that is out of range should assert
// and then return false. This was an arbitrary decision.
//
///////////////////////////////////////////////////////////////////////////////
#define ARGUMENT_CHECK_FOR_GET_FUNCTION(which,attribute) \
if ( false == this->hasAttribute ( attribute ) ) \
return false; \
if ( false == this->isInRange ( which ) ) \
{ \
assert ( 0 ); \
return false; \
}
#endif // __FLT_LOCAL_VERTEX_POOL_RECORDS_H

View File

@@ -16,6 +16,9 @@ CXXFILES =\
ExternalRecord.cpp\
Record.cpp\
FaceRecord.cpp\
LocalVertexPoolRecord.cpp\
MeshPrimitiveRecord.cpp\
MeshRecord.cpp\
RecordVisitor.cpp\
RoadRecords.cpp\
GeoSetBuilder.cpp\

View File

@@ -0,0 +1,145 @@
// MeshPrimitiveRecords.cpp
#ifdef _WIN32
#pragma warning(disable:4786) // Truncated debug names.
#endif
#include "MeshPrimitiveRecord.h"
#include "Registry.h"
#include <assert.h>
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// MeshPrimitiveRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<MeshPrimitiveRecord> g_MeshPrimitiveProxy;
MeshPrimitiveRecord::MeshPrimitiveRecord() : PrimNodeRecord()
{
}
// virtual
MeshPrimitiveRecord::~MeshPrimitiveRecord()
{
}
///////////////////////////////////////////////////////////////////////////////
//
// Return the address of the beginning of the vertex indices.
//
///////////////////////////////////////////////////////////////////////////////
char *MeshPrimitiveRecord::_getStartOfVertexIndices() const
{
SMeshPrimitive *mesh = this->getData();
char *index = (char *) (&(mesh[1]));
return index;
}
///////////////////////////////////////////////////////////////////////////////
//
// Get the index into the local vertex pool for the given i'th vertex of
// this mesh primitive.
//
///////////////////////////////////////////////////////////////////////////////
bool MeshPrimitiveRecord::getVertexIndex ( const uint32 &whichVertex, uint32 &index ) const
{
assert ( whichVertex < this->getNumVertices() );
// Get pointer to start of vertex indices.
char *start = (char *) this->_getStartOfVertexIndices();
// Need a pointer to the mesh structure.
SMeshPrimitive *mesh = this->getData();
// Move the pointer to the beginning of the requested vertex index. We are
// treating the array of indices as an array of chars (8 bits) so we have to
// multiply times the correct elements size (mesh->indexSize) to get the
// correct index.
uint32 adjust = whichVertex * ((uint32) mesh->indexSize);
start = &start[adjust];
// The index "adjust" that we just calculated should not walk off the end.
assert ( adjust <= mesh->indexSize * mesh->numVerts );
// Interpret the address "start" correctly...
switch ( mesh->indexSize )
{
case sizeof ( uint32 ): index = *((uint32 *) start); break; // No cast required.
case sizeof ( uint16 ): index = (uint32) (*((uint16 *) start)); break;
case sizeof ( uint8 ): index = (uint32) (*((uint8 *) start)); break;
default:
assert ( 0 ); // Invalid index size (according to 15.7.0 specs).
return false;
}
// It worked.
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// Convert the data from big-endian to little-endian.
//
///////////////////////////////////////////////////////////////////////////////
void MeshPrimitiveRecord::endian()
{
// Should only be in here for little-endian machines.
assert ( flt::isLittleEndianMachine() );
SMeshPrimitive *mesh = this->getData();
ENDIAN ( mesh->primitiveType );
ENDIAN ( mesh->indexSize );
ENDIAN ( mesh->numVerts );
// Get pointer to start of vertex indices.
char *index = this->_getStartOfVertexIndices();
// Determine the size of the elements in the array of vertex indices.
switch ( mesh->indexSize )
{
case sizeof ( uint32 ): // 32 bits.
// Perform byte-swap on all the elements in the array.
flt::swapBytesArray ( sizeof ( uint32 ), mesh->numVerts, (uint32 *) index );
break;
case sizeof ( uint16 ): // 16 bits.
// Perform byte-swap on all the elements in the array.
flt::swapBytesArray ( sizeof ( uint16 ), mesh->numVerts, (uint16 *) index );
break;
case sizeof ( uint8 ): // 8 bits.
// We don't have to swap bytes because there is only one byte.
break;
default:
assert ( 0 ); // Invalid index size (according to 15.7.0 specs).
}
#ifdef _DEBUG
// Sanity check. The address immediately following the last element,
// minus the start of this record, should be the size of this record.
char *offEndC = &(index[mesh->numVerts * mesh->indexSize]);
uint32 offEndI = (uint32) offEndC;
uint32 indexI = (uint32) mesh;
uint32 diff32 = ( offEndI ) - ( indexI );
uint16 diff16 = (uint16) ( diff32 );
assert ( mesh->RecHeader._wLength == diff16 );
#endif
}

View File

@@ -0,0 +1,72 @@
// MeshPrimitiveRecord.h
#ifndef __FLT_MESH_PRIMITIVE_RECORDS_H
#define __FLT_MESH_PRIMITIVE_RECORDS_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
////////////////////////////////////////////////////////////////////
//
// MeshPrimitiveRecord
//
////////////////////////////////////////////////////////////////////
struct SMeshPrimitive
{
SRecHeader RecHeader; // Header (opcode and size)
uint16 primitiveType; // Primitive Type - can be one of the following values:
// 1 - Triangle Strip
// 2 - Triangle Fan
// 3 - Quadrilateral Strip
// 4 - Indexed Polygon
// Note: This field specifies how the vertices of the primitive are interpreted.
uint16 indexSize; // Specifies the length (in bytes) of each of the vertex indices that follow - will be 1, 2, or 4
uint32 numVerts; // Number of vertices contained in this primitive
};
class MeshPrimitiveRecord : public PrimNodeRecord
{
public:
enum PrimitiveType
{
TRIANGLE_STRIP = 1,
TRIANGLE_FAN = 2,
QUADRILATERAL_STRIP = 3,
INDEXED_POLYGON = 4
};
MeshPrimitiveRecord();
virtual void accept ( RecordVisitor &rv ) { rv.apply ( *this ); }
virtual const char * className() const { return "MeshPrimitiveRecord"; }
virtual int classOpcode() const { return MESH_PRIMITIVE_OP; }
virtual Record * clone() const { return new MeshPrimitiveRecord(); }
SMeshPrimitive * getData() const { return (SMeshPrimitive *) _pData; }
uint32 getNumVertices() const { return this->getData()->numVerts; }
bool getVertexIndex ( const uint32 &whichVertex, uint32 &index ) const;
virtual size_t sizeofData() const { return sizeof ( SMeshPrimitive ); }
protected:
virtual ~MeshPrimitiveRecord();
virtual void endian();
char * _getStartOfVertexIndices() const;
};
}; // end namespace flt
#endif // __FLT_MESH_PRIMITIVE_RECORDS_H

View File

@@ -0,0 +1,58 @@
// MeshRecord.cpp
#ifdef _WIN32
#pragma warning(disable:4786) // Truncated debug names.
#endif
#include "flt.h"
#include "Registry.h"
#include "MeshRecord.h"
#include "Input.h"
#include <assert.h>
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// MeshRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<MeshRecord> g_MeshProxy;
MeshRecord::MeshRecord() : FaceRecord()
{
}
// virtual
MeshRecord::~MeshRecord()
{
}
void MeshRecord::endian()
{
// Should only be in here for little-endian machines.
assert ( flt::isLittleEndianMachine() );
// Call the base class's function.
// Note 1: We can do this because all the data members are the same.
// Note 2: FaceRecord::endian() checks for file version. This is
// unnecessary for a MeshRecord because it is new with 15.7. Therefore it
// could be optimized here, but doing this shouldn't slow us down too much.
FaceRecord::endian();
}
// virtual
bool MeshRecord::readLocalData ( Input &fr )
{
// Bypass FaceRecord's readLocalData() because it doesn't look for the
// correct kind of records. Instead, we call PrimNodeRecord's readLocalData()
// which looks for Ancillary Record's (we should at least find a
// LocalVertexPoolRecord), and then reads from a PushLevelRecord to a
// PopLevelRecord. Inside the push-pop pair we should have at least one
// MeshPrimitiveRecord.
return PrimNodeRecord::readLocalData ( fr );
}

View File

@@ -0,0 +1,62 @@
// MeshRecord.h
#ifndef __FLT_MESH_RECORD_H
#define __FLT_MESH_RECORD_H
#include "FaceRecord.h"
namespace flt {
////////////////////////////////////////////////////////////////////
//
// MeshRecord
//
////////////////////////////////////////////////////////////////////
struct SMesh : public SFace
{
// Members are identical to SFace (version 15.7).
};
// Note: the enums for FaceRecord are the same for MeshRecord, so we inherit
// and overload where necessary. I was sort of on the fence with this decision,
// because a MeshRecord isn't really a more specific case of a FaceRecord s
// (which single inheritance typically implies). However, there is too much in
// FaceRecord that is identical to not take advantage of. This can be changed
// later if the two records diverge, or if it proved to be a bad idea.
class MeshRecord : public FaceRecord
{
public:
MeshRecord();
virtual void accept ( RecordVisitor &rv ) { rv.apply ( *this ); }
virtual const char * className() const { return "MeshRecord"; }
virtual int classOpcode() const { return MESH_OP; }
virtual Record * clone() const { return new MeshRecord(); }
SMesh * getData() const { return (SMesh *) _pData; }
virtual size_t sizeofData() const { return sizeof ( SMesh ); }
protected:
virtual ~MeshRecord();
virtual void endian();
virtual bool readLocalData ( Input &fr );
};
}; // end namespace flt
#endif // __FLT_MESH_RECORD_H

View File

@@ -37,7 +37,7 @@ Record::~Record()
}
int Record::getFlightVersion()
int Record::getFlightVersion() const
{
if (_pFltFile)
return _pFltFile->getFlightVersion();
@@ -65,6 +65,16 @@ void Record::accept(RecordVisitor& rv)
}
void Record::postReadInit()
{
// These two lines used to be the last thing in Input::readCreateRecord().
// Some records need a "post read" function called regardless of
// the endian of the machine, so I moved it to here.
if ( flt::isLittleEndianMachine() ) // From Intel with love :-(
this->endian();
}
/*
void Record::ascend(RecordVisitor& rv)
{

View File

@@ -62,8 +62,9 @@ class Record : public osg::Referenced
bool isOfType(int op) const;
Record* getParent() const { return _pParent; }
FltFile* getFltFile() { return _pFltFile; }
int getFlightVersion();
int getFlightVersion() const;
virtual void postReadInit();
friend std::ostream& operator << (std::ostream& output, const Record& rec);

View File

@@ -26,6 +26,8 @@ class OldLodRecord;
class DofRecord;
class ObjectRecord;
class FaceRecord;
class MeshRecord;
class MeshPrimitiveRecord;
class VertexListRecord;
class MorphVertexListRecord;
class LightSourceRecord;
@@ -38,6 +40,7 @@ class ExternalRecord;
class CommentRecord;
class LongIDRecord;
class VectorRecord;
class LocalVertexPoolRecord;
class OldVertexRecord;
class OldVertexColorRecord;
class OldVertexColorNormalRecord;
@@ -120,6 +123,8 @@ class RecordVisitor
virtual void apply(DofRecord& rec) { apply((PrimNodeRecord&)rec); }
virtual void apply(ObjectRecord& rec) { apply((PrimNodeRecord&)rec); }
virtual void apply(FaceRecord& rec) { apply((PrimNodeRecord&)rec); }
virtual void apply(MeshRecord& rec) { apply((PrimNodeRecord&)rec); }
virtual void apply(MeshPrimitiveRecord& rec) { apply((PrimNodeRecord&)rec); }
virtual void apply(VertexListRecord& rec) { apply((PrimNodeRecord&)rec); }
virtual void apply(MorphVertexListRecord& rec) { apply((PrimNodeRecord&)rec); }
virtual void apply(LightSourceRecord& rec) { apply((PrimNodeRecord&)rec); }
@@ -132,6 +137,7 @@ class RecordVisitor
virtual void apply(CommentRecord& rec) { apply((Record&)rec); }
virtual void apply(LongIDRecord& rec) { apply((Record&)rec); }
virtual void apply(VectorRecord& rec) { apply((Record&)rec); }
virtual void apply(LocalVertexPoolRecord& rec) { apply((Record&)rec); }
virtual void apply(OldVertexRecord& rec) { apply((Record&)rec); }
virtual void apply(OldVertexColorRecord& rec) { apply((Record&)rec); }
virtual void apply(OldVertexColorNormalRecord& rec) { apply((Record&)rec); }

View File

@@ -9,6 +9,7 @@
#include <osg/Vec4>
#include <iostream>
#include <assert.h>
#if defined(__CYGWIN__) || defined(__MINGW32__)
#include <sys/types.h>
@@ -202,8 +203,59 @@ struct SRecHeader
};
//////////////////////////////////////////////////////////////////////////
//
// Perform a byte swap.
//
//////////////////////////////////////////////////////////////////////////
template<class PointerType> inline void swapBytes ( const size_t &numBytes, PointerType *pointer )
{
assert ( numBytes >= 2 );
assert ( pointer );
flt::endian2 ( (void *) pointer, numBytes, (void *) pointer, numBytes );
}
//////////////////////////////////////////////////////////////////////////
//
// Perform a byte swap on all elements in the array.
//
//////////////////////////////////////////////////////////////////////////
template<class PointerType, class IndexType> inline void swapBytesArray ( const size_t &numBytes, const IndexType &numElements, PointerType *pointer )
{
// For the way this function is being used, this should be true. If it
// becomes necessary to pass in a "numBytes" that is not actually the number
// of bytes at this pointer type, then remove this assertion.
// I pass in the "numBytes" instead of calculating it here for the purposes
// of speeding it up. I didn't test the performance benefits, there may not
// be any.
assert ( numBytes == sizeof ( PointerType ) );
// Loop through the array and byte-swap the elements.
for ( IndexType i = 0; i < numElements; ++i )
{
// Swap the byte order at the address of i'th element.
flt::swapBytes ( numBytes, &(pointer[i]) );
}
}
//////////////////////////////////////////////////////////////////////////
//
// See if the "bits" are in "number".
//
//////////////////////////////////////////////////////////////////////////
template<class DataTypeNumber, class DataTypeBits> inline bool hasBits
( const DataTypeNumber &number, const DataTypeBits &bits )
{
return ( ( number & bits ) == bits );
}
}; // end namespace flt
#endif

View File

@@ -22,6 +22,7 @@
#include <osg/Texture>
#include <osg/Image>
#include <osg/Notify>
#include <osg/GeoSet>
#include <osg/DOFTransform>
#include <osg/Sequence>
@@ -50,6 +51,8 @@
#include "SwitchRecord.h"
#include "ObjectRecord.h"
#include "FaceRecord.h"
#include "MeshRecord.h"
#include "MeshPrimitiveRecord.h"
#include "TransformationRecords.h"
#include "ExternalRecord.h"
#include "LightPointRecord.h"
@@ -57,6 +60,7 @@
#include "GeoSetBuilder.h"
#include "LongIDRecord.h"
#include "InstanceRecords.h"
#include "LocalVertexPoolRecord.h"
@@ -217,6 +221,14 @@ osg::Group* ConvertFromFLT::visitPrimaryNode(osg::Group& osgParent, PrimNodeReco
{
switch (child->getOpcode())
{
case MESH_OP:
if( ((MeshRecord*)child)->getData()->swTemplateTrans == 2) //Axis type rotate
visitMesh(osgParent, &billboardBuilder, (MeshRecord*)child);
else
visitMesh(osgParent, &geoSetBuilder, (MeshRecord*)child);
break;
case FACE_OP:
{
FaceRecord* fr = (FaceRecord*)child;
@@ -256,6 +268,14 @@ osg::Group* ConvertFromFLT::visitPrimaryNode(osg::Group& osgParent, PrimNodeReco
case EXTERNAL_REFERENCE_OP:
osgPrim = visitExternal(osgParent, (ExternalRecord*)child);
break;
#ifdef _DEBUG
default:
osg::notify(osg::INFO) << "In ConvertFromFLT::visitPrimaryNode(), unknown opcode: " << child->getOpcode() << std::endl;
break;
#endif
}
}
}
@@ -901,18 +921,8 @@ osg::Group* ConvertFromFLT::visitObject(osg::Group& osgParent, ObjectRecord* rec
}
void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
void ConvertFromFLT::setCullFaceAndWireframe ( const SFace *pSFace, osg::StateSet *osgStateSet, DynGeoSet *dgset )
{
DynGeoSet* dgset = pBuilder->getDynGeoSet();
osg::StateSet* osgStateSet = dgset->getStateSet();
SFace *pSFace = (SFace*)rec->getData();
bool bBlend = false;
if (rec->getFlightVersion() > 13)
{
if (pSFace->dwFlags & FaceRecord::HIDDEN_BIT)
return;
}
//
// Cull face & wireframe
@@ -948,7 +958,11 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
dgset->setPrimType(osg::Primitive::POINTS);
break;
}
}
void ConvertFromFLT::setDirectionalLight()
{
/*
TODO:
@@ -963,7 +977,11 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
break;
}
*/
}
void ConvertFromFLT::setLightingAndColorBinding ( const FaceRecord *rec, const SFace *pSFace, osg::StateSet *osgStateSet, DynGeoSet *dgset )
{
//
// Lighting and color binding
//
@@ -1009,8 +1027,11 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
dgset->setColorBinding( osg::Geometry::BIND_OVERALL /*BIND_PERPRIM*/ );
}
}
void ConvertFromFLT::setColor ( FaceRecord *rec, SFace *pSFace, DynGeoSet *dgset, bool &bBlend )
{
//
// Face Color
//
@@ -1059,7 +1080,11 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
if ((dgset->getColorBinding() == osg::Geometry::BIND_OVERALL)
|| (dgset->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE))
dgset->addColor(_faceColor);
}
void ConvertFromFLT::setMaterial ( FaceRecord *rec, SFace *pSFace, osg::StateSet *osgStateSet, bool &bBlend )
{
//
// Material
//
@@ -1114,7 +1139,6 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
if (alpha < 1.0f) bBlend = true;
}
}
//
// Subface
//
@@ -1132,7 +1156,11 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
}
}
}
}
void ConvertFromFLT::setTexture ( FaceRecord *rec, SFace *pSFace, osg::StateSet *osgStateSet, DynGeoSet *dgset, bool &bBlend )
{
//
// Texture
//
@@ -1177,8 +1205,11 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
}
}
}
}
void ConvertFromFLT::setTransparency ( osg::StateSet *osgStateSet, bool &bBlend )
{
//
// Transparency
//
@@ -1191,23 +1222,57 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
osgStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
osgStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
}
void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec)
{
DynGeoSet* dgset = pBuilder->getDynGeoSet();
osg::StateSet* osgStateSet = dgset->getStateSet();
SFace *pSFace = (SFace*)rec->getData();
bool bBlend = false;
if (rec->getFlightVersion() > 13)
{
if (pSFace->dwFlags & FaceRecord::HIDDEN_BIT)
return;
}
// Various properties.
setCullFaceAndWireframe ( pSFace, osgStateSet, dgset );
setDirectionalLight();
setLightingAndColorBinding ( rec, pSFace, osgStateSet, dgset );
setColor ( rec, pSFace, dgset, bBlend );
setMaterial ( rec, pSFace, osgStateSet, bBlend );
// Subface
if (rec->getParent()->isOfType(FACE_OP))
{
if (_nSubfaceLevel > 0)
{
osg::PolygonOffset* polyoffset = new osg::PolygonOffset;
if (polyoffset)
{
polyoffset->setFactor(-1.0f*_nSubfaceLevel);
polyoffset->setUnits(-20.0f*_nSubfaceLevel);
osgStateSet->setAttributeAndModes(polyoffset,osg::StateAttribute::ON);
}
}
}
// Texture.
setTexture ( rec, pSFace, osgStateSet, dgset, bBlend );
// Transparency
setTransparency ( osgStateSet, bBlend );
//
// Vertices
//
addVertices(pBuilder, rec);
//
// Add face to builder GeoSet pool
//
pBuilder->addPrimitive();
//
// Look for subfaces
//
{
_nSubfaceLevel++;
int n;
@@ -1241,6 +1306,10 @@ int ConvertFromFLT::addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec
vertices += visitVertexList(pBuilder, (VertexListRecord*)child);
break;
case LOCAL_VERTEX_POOL_OP:
vertices += visitLocalVertexPool(pBuilder, (LocalVertexPoolRecord *)child);
break;
default :
vertices += addVertex(pBuilder, child);
break;
@@ -1263,6 +1332,7 @@ int ConvertFromFLT::addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec
return vertices;
}
int ConvertFromFLT::visitVertexList(GeoSetBuilder* pBuilder, VertexListRecord* rec)
{
//DynGeoSet* dgset = pBuilder->getDynGeoSet();
@@ -1280,9 +1350,6 @@ int ConvertFromFLT::visitVertexList(GeoSetBuilder* pBuilder, VertexListRecord* r
}
// Return 1 if record is a known vertex record else return 0.
int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec)
{
@@ -1468,3 +1535,210 @@ void ConvertFromFLT::visitLightPoint(GeoSetBuilder* pBuilder, LightPointRecord*
addVertices(pBuilder, rec);
pBuilder->addPrimitive();
}
void ConvertFromFLT::visitMesh ( osg::Group &parent, GeoSetBuilder *pBuilder, MeshRecord *rec )
{
DynGeoSet* dgset = pBuilder->getDynGeoSet();
osg::StateSet *osgStateSet = dgset->getStateSet();
SFace *pSFace = (SFace *) rec->getData();
bool bBlend = false;
// See if it's hidden.
if ( rec->getFlightVersion() > 13 && flt::hasBits ( pSFace->dwFlags, (uint32) MeshRecord::HIDDEN_BIT ) )
return;
// Set the various properties.
setCullFaceAndWireframe ( pSFace, osgStateSet, dgset );
setDirectionalLight();
setLightingAndColorBinding ( rec, pSFace, osgStateSet, dgset );
setColor ( rec, pSFace, dgset, bBlend );
setMaterial ( rec, pSFace, osgStateSet, bBlend );
setTexture ( rec, pSFace, osgStateSet, dgset, bBlend );
setTransparency ( osgStateSet, bBlend );
// Add the vertices.
addVertices ( pBuilder, rec );
// Add the mesh primitives.
addMeshPrimitives ( parent, pBuilder, rec );
}
int ConvertFromFLT::addMeshPrimitives ( osg::Group &parent, GeoSetBuilder *, MeshRecord *rec )
{
// The count of the mesh primitives added.
int count = 0;
// Loop through all the children.
for ( int i = 0; i < rec->getNumChildren(); ++i )
{
// Get the i'th child.
Record *child = rec->getChild ( i );
// If it is a mesh primitive...
if ( MESH_PRIMITIVE_OP == child->getOpcode() )
{
// Visit this mesh primitive.
visitMeshPrimitive ( parent, (MeshPrimitiveRecord *) child );
++count;
}
}
// Return the number of mesh primitives added.
return count;
}
int ConvertFromFLT::visitLocalVertexPool ( GeoSetBuilder *, LocalVertexPoolRecord *rec )
{
// Make the given instance the current one.
rec->makeCurrent();
// We didn't add any vertices.
return 0;
}
void ConvertFromFLT::visitMeshPrimitive ( osg::Group &parent, MeshPrimitiveRecord *mesh )
{
assert ( mesh );
osg::Geode *geode = new osg::Geode();
osg::Geometry *geometry = new osg::Geometry();
LocalVertexPoolRecord *pool = LocalVertexPoolRecord::getCurrent();
assert ( pool );
// Set the correct primitive type.
switch ( mesh->getData()->primitiveType )
{
case MeshPrimitiveRecord::TRIANGLE_STRIP:
geometry->addPrimitive ( new osg::DrawArrays(osg::Primitive::TRIANGLE_STRIP,0,mesh->getNumVertices()) );
break;
case MeshPrimitiveRecord::TRIANGLE_FAN:
geometry->addPrimitive ( new osg::DrawArrays(osg::Primitive::TRIANGLE_FAN,0,mesh->getNumVertices()) );
break;
case MeshPrimitiveRecord::QUADRILATERAL_STRIP:
geometry->addPrimitive ( new osg::DrawArrays(osg::Primitive::QUAD_STRIP,0,mesh->getNumVertices()) );
break;
case MeshPrimitiveRecord::INDEXED_POLYGON:
geometry->addPrimitive ( new osg::DrawArrays(osg::Primitive::POLYGON,0,mesh->getNumVertices()) );
break;
default:
assert ( 0 ); // What type is this?
return;
}
// Add the vertex properties.
setMeshCoordinates ( mesh->getNumVertices(), pool, mesh, geometry );
setMeshNormals ( mesh->getNumVertices(), pool, mesh, geometry );
// Add the geoset to the geode.
geode->addDrawable ( geometry );
// Add the geode to the parent.
parent.addChild ( geode );
}
uint32 ConvertFromFLT::setMeshCoordinates ( const uint32 &numVerts, const LocalVertexPoolRecord *pool, MeshPrimitiveRecord *mesh, osg::Geometry *geometry )
{
assert ( pool );
assert ( mesh );
assert ( geometry );
// If there aren't any coordinates...
if ( false == pool->hasAttribute ( LocalVertexPoolRecord::POSITION ) )
return 0;
// Allocate the vertices.
osg::Vec3Array *coords = new osg::Vec3Array(numVerts);
if ( NULL == coords )
{
assert ( 0 );
return false;
}
// Declare outside of loop.
uint32 i ( 0 ), index ( 0 );
float64 px, py, pz;
// Loop through all the coordinates.
for ( i = 0; i < numVerts; ++i )
{
// Get the i'th index into the vertex pool.
if ( !mesh->getVertexIndex ( i, index ) )
{
assert ( 0 ); // We stepped out of bounds.
break;
}
// Get the coordinate (using "index").
if ( !pool->getPosition ( index, px, py, pz ) )
{
assert ( 0 ); // We stepped out of bounds.
break;
}
// Add the coordinate.
(*coords)[i].set ( (float) px, (float) py, (float) pz );
}
// Set the mesh coordinates.
geometry->setVertexArray ( coords );
// Return the number of coordinates added.
return i;
}
uint32 ConvertFromFLT::setMeshNormals ( const uint32 &numVerts, const LocalVertexPoolRecord *pool, MeshPrimitiveRecord *mesh, osg::Geometry *geometry )
{
assert ( pool );
assert ( mesh );
assert ( geometry );
// If there aren't any coordinates...
if ( false == pool->hasAttribute ( LocalVertexPoolRecord::NORMAL ) )
return 0;
// Allocate the normals.
osg::Vec3Array *normals = new osg::Vec3Array(numVerts);
if ( NULL == normals )
{
assert ( 0 );
return 0;
}
// Declare outside of loop.
uint32 i ( 0 ), index ( 0 );
float32 x, y, z;
// Loop through all the coordinates.
for ( i = 0; i < numVerts; ++i )
{
// Get the i'th index into the vertex pool.
if ( !mesh->getVertexIndex ( i, index ) )
{
assert ( 0 ); // We stepped out of bounds.
break;
}
// Get the coordinate (using "index").
if ( !pool->getNormal ( index, x, y, z ) )
{
assert ( 0 ); // We stepped out of bounds.
break;
}
// Add the coordinate.
(*normals)[i].set ( x, y, z );
}
// Set the mesh coordinates.
geometry->setNormalArray( normals );
geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
// Return the number of coordinates added.
return i;
}

View File

@@ -16,7 +16,6 @@ class Object;
class Group;
class LOD;
class Geode;
class GeoSet;
class Material;
class Texture;
class Vec4;
@@ -43,13 +42,17 @@ class DofRecord;
class SwitchRecord;
class ObjectRecord;
class FaceRecord;
class MeshRecord;
class MeshPrimitiveRecord;
class MatrixRecord;
class ExternalRecord;
class LightPointRecord;
class VertexListRecord;
class LocalVertexPoolRecord;
class LongIDRecord;
class InstanceDefinitionRecord;
class InstanceReferenceRecord;
struct SFace;
//class GeoSetBuilder;
@@ -140,16 +143,31 @@ class ConvertFromFLT
osg::Group* visitInstanceReference(osg::Group& osgParent,InstanceReferenceRecord* rec);
void visitFace(GeoSetBuilder* pParent, FaceRecord* rec);
void visitMesh(osg::Group& osgParent,GeoSetBuilder* pParent, MeshRecord* rec);
void visitMeshPrimitive(osg::Group& osgParent, MeshPrimitiveRecord* rec);
void visitLightPoint(GeoSetBuilder* pBuilder, LightPointRecord* rec);
int visitVertexList(GeoSetBuilder* pParent, VertexListRecord* rec);
int visitLocalVertexPool(GeoSetBuilder* pBuilder, LocalVertexPoolRecord* rec);
private:
int addMeshPrimitives ( osg::Group &osgParent, GeoSetBuilder *pBuilder, MeshRecord *rec );
int addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec);
int addVertex(DynGeoSet* dgset, Record* rec);
int addVertex(GeoSetBuilder* pBuilder, Record* rec) {return addVertex( pBuilder->getDynGeoSet(), rec);} ;
Record* getVertexFromPool(int nOffset);
void regisiterVertex(int nOffset, Record* pRec);
void visitFaceOrMeshCommonCode(GeoSetBuilder* pBuilder, FaceRecord* rec);
uint32 setMeshCoordinates ( const uint32 &numVerts, const LocalVertexPoolRecord *pool, MeshPrimitiveRecord *mesh, osg::Geometry *geometry );
uint32 setMeshNormals ( const uint32 &numVerts, const LocalVertexPoolRecord *pool, MeshPrimitiveRecord *mesh, osg::Geometry *geometry );
void setCullFaceAndWireframe ( const SFace *pSFace, osg::StateSet *osgStateSet, DynGeoSet *dgset );
void setDirectionalLight();
void setLightingAndColorBinding ( const FaceRecord *rec, const SFace *pSFace, osg::StateSet *osgStateSet, DynGeoSet *dgset );
void setColor ( FaceRecord *rec, SFace *pSFace, DynGeoSet *dgset, bool &bBlend );
void setMaterial ( FaceRecord *rec, SFace *pSFace, osg::StateSet *osgStateSet, bool &bBlend );
void setTexture ( FaceRecord *rec, SFace *pSFace, osg::StateSet *osgStateSet, DynGeoSet *dgset, bool &bBlend );
void setTransparency ( osg::StateSet *osgStateSet, bool &bBlend );
typedef std::map<int,Record*> VertexPaletteOffsetMap;
VertexPaletteOffsetMap _VertexPaletteOffsetMap;

View File

@@ -56,6 +56,9 @@ Ignore 76-82
#define PUT_TRANSFORM_OP 82
*/
#define EYEPOINT_TRACKPLANE_OP 83
#define MESH_OP 84
#define LOCAL_VERTEX_POOL_OP 85
#define MESH_PRIMITIVE_OP 86
#define ROAD_SEGMENT_OP 87
#define ROAD_ZONE_OP 88
#define MORPH_VERTEX_LIST_OP 89