From 61e3b34bc7bb1f16afc173395caed1e5bd1cc381 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 15 Aug 2002 11:25:23 +0000 Subject: [PATCH] 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. --- VisualStudio/osgPlugins/flt/flt.dsp | 432 +-------------- src/osgPlugins/flt/FltFile.cpp | 2 +- src/osgPlugins/flt/FltFile.h | 2 +- src/osgPlugins/flt/HeaderRecord.cpp | 11 + src/osgPlugins/flt/HeaderRecord.h | 12 + src/osgPlugins/flt/Input.cpp | 18 +- src/osgPlugins/flt/LocalVertexPoolRecord.cpp | 523 +++++++++++++++++++ src/osgPlugins/flt/LocalVertexPoolRecord.h | 119 +++++ src/osgPlugins/flt/Makefile | 3 + src/osgPlugins/flt/MeshPrimitiveRecord.cpp | 145 +++++ src/osgPlugins/flt/MeshPrimitiveRecord.h | 72 +++ src/osgPlugins/flt/MeshRecord.cpp | 58 ++ src/osgPlugins/flt/MeshRecord.h | 62 +++ src/osgPlugins/flt/Record.cpp | 12 +- src/osgPlugins/flt/Record.h | 3 +- src/osgPlugins/flt/RecordVisitor.h | 6 + src/osgPlugins/flt/flt.h | 56 +- src/osgPlugins/flt/flt2osg.cpp | 322 +++++++++++- src/osgPlugins/flt/flt2osg.h | 20 +- src/osgPlugins/flt/opcodes.h | 3 + 20 files changed, 1432 insertions(+), 449 deletions(-) create mode 100644 src/osgPlugins/flt/LocalVertexPoolRecord.cpp create mode 100644 src/osgPlugins/flt/LocalVertexPoolRecord.h create mode 100644 src/osgPlugins/flt/MeshPrimitiveRecord.cpp create mode 100644 src/osgPlugins/flt/MeshPrimitiveRecord.h create mode 100644 src/osgPlugins/flt/MeshRecord.cpp create mode 100644 src/osgPlugins/flt/MeshRecord.h diff --git a/VisualStudio/osgPlugins/flt/flt.dsp b/VisualStudio/osgPlugins/flt/flt.dsp index f0dbca717..e08a1096e 100644 --- a/VisualStudio/osgPlugins/flt/flt.dsp +++ b/VisualStudio/osgPlugins/flt/flt.dsp @@ -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 - diff --git a/src/osgPlugins/flt/FltFile.cpp b/src/osgPlugins/flt/FltFile.cpp index 5f7e9cc14..627cbb6e9 100644 --- a/src/osgPlugins/flt/FltFile.cpp +++ b/src/osgPlugins/flt/FltFile.cpp @@ -213,7 +213,7 @@ void FltFile::readExternals() } -int FltFile::getFlightVersion() +int FltFile::getFlightVersion() const { if (_headerRecord.get()) { diff --git a/src/osgPlugins/flt/FltFile.h b/src/osgPlugins/flt/FltFile.h index 4d70d0d59..29b85f021 100644 --- a/src/osgPlugins/flt/FltFile.h +++ b/src/osgPlugins/flt/FltFile.h @@ -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: diff --git a/src/osgPlugins/flt/HeaderRecord.cpp b/src/osgPlugins/flt/HeaderRecord.cpp index fbdd17870..c23dfbf3d 100644 --- a/src/osgPlugins/flt/HeaderRecord.cpp +++ b/src/osgPlugins/flt/HeaderRecord.cpp @@ -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 ); + } } diff --git a/src/osgPlugins/flt/HeaderRecord.h b/src/osgPlugins/flt/HeaderRecord.h index a5de99853..befd1585e 100644 --- a/src/osgPlugins/flt/HeaderRecord.h +++ b/src/osgPlugins/flt/HeaderRecord.h @@ -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 }; diff --git a/src/osgPlugins/flt/Input.cpp b/src/osgPlugins/flt/Input.cpp index 754f9bccb..3e281c797 100644 --- a/src/osgPlugins/flt/Input.cpp +++ b/src/osgPlugins/flt/Input.cpp @@ -1,3 +1,9 @@ +// Input.cpp + +#include +// #include +#include + #include #include @@ -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; } diff --git a/src/osgPlugins/flt/LocalVertexPoolRecord.cpp b/src/osgPlugins/flt/LocalVertexPoolRecord.cpp new file mode 100644 index 000000000..1a594eeeb --- /dev/null +++ b/src/osgPlugins/flt/LocalVertexPoolRecord.cpp @@ -0,0 +1,523 @@ +// LocalVertexPoolRecords.cpp + +#ifdef _WIN32 +#pragma warning(disable:4786) // Truncated debug names. +#endif + +#include "LocalVertexPoolRecord.h" +#include "Registry.h" +#include + +// 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 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; +} diff --git a/src/osgPlugins/flt/LocalVertexPoolRecord.h b/src/osgPlugins/flt/LocalVertexPoolRecord.h new file mode 100644 index 000000000..687eeba77 --- /dev/null +++ b/src/osgPlugins/flt/LocalVertexPoolRecord.h @@ -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 diff --git a/src/osgPlugins/flt/Makefile b/src/osgPlugins/flt/Makefile index 6189bdcab..f554c9a94 100644 --- a/src/osgPlugins/flt/Makefile +++ b/src/osgPlugins/flt/Makefile @@ -16,6 +16,9 @@ CXXFILES =\ ExternalRecord.cpp\ Record.cpp\ FaceRecord.cpp\ + LocalVertexPoolRecord.cpp\ + MeshPrimitiveRecord.cpp\ + MeshRecord.cpp\ RecordVisitor.cpp\ RoadRecords.cpp\ GeoSetBuilder.cpp\ diff --git a/src/osgPlugins/flt/MeshPrimitiveRecord.cpp b/src/osgPlugins/flt/MeshPrimitiveRecord.cpp new file mode 100644 index 000000000..a7ca889de --- /dev/null +++ b/src/osgPlugins/flt/MeshPrimitiveRecord.cpp @@ -0,0 +1,145 @@ +// MeshPrimitiveRecords.cpp + +#ifdef _WIN32 +#pragma warning(disable:4786) // Truncated debug names. +#endif + +#include "MeshPrimitiveRecord.h" +#include "Registry.h" +#include + +using namespace flt; + + +//////////////////////////////////////////////////////////////////// +// +// MeshPrimitiveRecord +// +//////////////////////////////////////////////////////////////////// + +RegisterRecordProxy 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 +} diff --git a/src/osgPlugins/flt/MeshPrimitiveRecord.h b/src/osgPlugins/flt/MeshPrimitiveRecord.h new file mode 100644 index 000000000..343a925b6 --- /dev/null +++ b/src/osgPlugins/flt/MeshPrimitiveRecord.h @@ -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 diff --git a/src/osgPlugins/flt/MeshRecord.cpp b/src/osgPlugins/flt/MeshRecord.cpp new file mode 100644 index 000000000..1d38d1409 --- /dev/null +++ b/src/osgPlugins/flt/MeshRecord.cpp @@ -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 + +using namespace flt; + +//////////////////////////////////////////////////////////////////// +// +// MeshRecord +// +//////////////////////////////////////////////////////////////////// + +RegisterRecordProxy 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 ); +} diff --git a/src/osgPlugins/flt/MeshRecord.h b/src/osgPlugins/flt/MeshRecord.h new file mode 100644 index 000000000..2116ab763 --- /dev/null +++ b/src/osgPlugins/flt/MeshRecord.h @@ -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 diff --git a/src/osgPlugins/flt/Record.cpp b/src/osgPlugins/flt/Record.cpp index de7085844..f25345d69 100644 --- a/src/osgPlugins/flt/Record.cpp +++ b/src/osgPlugins/flt/Record.cpp @@ -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) { diff --git a/src/osgPlugins/flt/Record.h b/src/osgPlugins/flt/Record.h index 416c936b7..954625f9f 100644 --- a/src/osgPlugins/flt/Record.h +++ b/src/osgPlugins/flt/Record.h @@ -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); diff --git a/src/osgPlugins/flt/RecordVisitor.h b/src/osgPlugins/flt/RecordVisitor.h index 27975cff2..957ec48e6 100644 --- a/src/osgPlugins/flt/RecordVisitor.h +++ b/src/osgPlugins/flt/RecordVisitor.h @@ -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); } diff --git a/src/osgPlugins/flt/flt.h b/src/osgPlugins/flt/flt.h index 36a4084ea..0166bfc34 100644 --- a/src/osgPlugins/flt/flt.h +++ b/src/osgPlugins/flt/flt.h @@ -9,6 +9,7 @@ #include #include +#include #if defined(__CYGWIN__) || defined(__MINGW32__) #include @@ -202,8 +203,59 @@ struct SRecHeader }; +////////////////////////////////////////////////////////////////////////// +// +// Perform a byte swap. +// +////////////////////////////////////////////////////////////////////////// + +template 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 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 inline bool hasBits + ( const DataTypeNumber &number, const DataTypeBits &bits ) +{ + return ( ( number & bits ) == bits ); +} + + }; // end namespace flt + #endif - - diff --git a/src/osgPlugins/flt/flt2osg.cpp b/src/osgPlugins/flt/flt2osg.cpp index 08fe50925..e89a4ab61 100644 --- a/src/osgPlugins/flt/flt2osg.cpp +++ b/src/osgPlugins/flt/flt2osg.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -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; +} diff --git a/src/osgPlugins/flt/flt2osg.h b/src/osgPlugins/flt/flt2osg.h index c5eb9c8a7..9781ec6a9 100644 --- a/src/osgPlugins/flt/flt2osg.h +++ b/src/osgPlugins/flt/flt2osg.h @@ -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 VertexPaletteOffsetMap; VertexPaletteOffsetMap _VertexPaletteOffsetMap; diff --git a/src/osgPlugins/flt/opcodes.h b/src/osgPlugins/flt/opcodes.h index 76d2a5c1e..451c1ed03 100644 --- a/src/osgPlugins/flt/opcodes.h +++ b/src/osgPlugins/flt/opcodes.h @@ -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