From 3246dde716d9a7e94344912d8535356488faf3d1 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 8 Mar 2006 21:38:37 +0000 Subject: [PATCH] From Brede Johansen, new OpenFlight plugin!!!!! By default the original flt plugin is still used, to select at runtime the new plugin set the env OSG_OPEN_FLIGHT_PLUGIN=new --- Make/makedirdefs | 5 +- VisualStudio/OpenSceneGraph.dsw | 24 + .../osgPlugins/OpenFlight/OpenFlight.dsp | 222 ++++++ VisualStudio/osgSim/osgSim.dsp | 8 + .../osgWrappers/osgSim/wrapper_osgSim.dsp | 4 + include/osgSim/OpenFlightOptimizer | 114 +++ src/osgDB/Registry.cpp | 9 + .../OpenFlight/AncillaryRecords.cpp | 269 +++++++ src/osgPlugins/OpenFlight/AttrData.cpp | 76 ++ src/osgPlugins/OpenFlight/AttrData.h | 310 ++++++++ src/osgPlugins/OpenFlight/ControlRecords.cpp | 210 +++++ src/osgPlugins/OpenFlight/DataInputStream.cpp | 210 +++++ src/osgPlugins/OpenFlight/DataInputStream.h | 61 ++ src/osgPlugins/OpenFlight/Document.cpp | 114 +++ src/osgPlugins/OpenFlight/Document.h | 221 ++++++ src/osgPlugins/OpenFlight/GNUmakefile | 34 + src/osgPlugins/OpenFlight/GeometryRecords.cpp | 625 +++++++++++++++ .../OpenFlight/LightPointRecords.cpp | 314 ++++++++ src/osgPlugins/OpenFlight/PaletteRecords.cpp | 635 +++++++++++++++ src/osgPlugins/OpenFlight/Pools.cpp | 121 +++ src/osgPlugins/OpenFlight/Pools.h | 214 +++++ src/osgPlugins/OpenFlight/PrimaryRecords.cpp | 747 ++++++++++++++++++ .../OpenFlight/ReaderWriterATTR.cpp | 177 +++++ src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp | 187 +++++ src/osgPlugins/OpenFlight/Record.cpp | 138 ++++ src/osgPlugins/OpenFlight/Record.h | 114 +++ .../OpenFlight/RecordInputStream.cpp | 126 +++ src/osgPlugins/OpenFlight/RecordInputStream.h | 49 ++ src/osgPlugins/OpenFlight/Registry.cpp | 47 ++ src/osgPlugins/OpenFlight/Registry.h | 66 ++ src/osgPlugins/OpenFlight/ReservedRecords.cpp | 23 + src/osgPlugins/OpenFlight/RoadRecords.cpp | 121 +++ src/osgPlugins/OpenFlight/Vertex.cpp | 55 ++ src/osgPlugins/OpenFlight/Vertex.h | 44 ++ src/osgPlugins/OpenFlight/VertexRecords.cpp | 324 ++++++++ src/osgPlugins/OpenFlight/opcodes.h | 123 +++ src/osgPlugins/OpenFlight/types.h | 38 + src/osgSim/GNUmakefile | 1 + src/osgSim/OpenFlightOptimizer.cpp | 239 ++++++ src/osgWrappers/osgSim/GNUmakefile | 1 + .../osgSim/OpenFlightOptimizer.cpp | 57 ++ 41 files changed, 6475 insertions(+), 2 deletions(-) create mode 100644 VisualStudio/osgPlugins/OpenFlight/OpenFlight.dsp create mode 100644 include/osgSim/OpenFlightOptimizer create mode 100644 src/osgPlugins/OpenFlight/AncillaryRecords.cpp create mode 100644 src/osgPlugins/OpenFlight/AttrData.cpp create mode 100644 src/osgPlugins/OpenFlight/AttrData.h create mode 100644 src/osgPlugins/OpenFlight/ControlRecords.cpp create mode 100644 src/osgPlugins/OpenFlight/DataInputStream.cpp create mode 100644 src/osgPlugins/OpenFlight/DataInputStream.h create mode 100644 src/osgPlugins/OpenFlight/Document.cpp create mode 100644 src/osgPlugins/OpenFlight/Document.h create mode 100644 src/osgPlugins/OpenFlight/GNUmakefile create mode 100644 src/osgPlugins/OpenFlight/GeometryRecords.cpp create mode 100644 src/osgPlugins/OpenFlight/LightPointRecords.cpp create mode 100644 src/osgPlugins/OpenFlight/PaletteRecords.cpp create mode 100644 src/osgPlugins/OpenFlight/Pools.cpp create mode 100644 src/osgPlugins/OpenFlight/Pools.h create mode 100644 src/osgPlugins/OpenFlight/PrimaryRecords.cpp create mode 100644 src/osgPlugins/OpenFlight/ReaderWriterATTR.cpp create mode 100644 src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp create mode 100644 src/osgPlugins/OpenFlight/Record.cpp create mode 100644 src/osgPlugins/OpenFlight/Record.h create mode 100644 src/osgPlugins/OpenFlight/RecordInputStream.cpp create mode 100644 src/osgPlugins/OpenFlight/RecordInputStream.h create mode 100644 src/osgPlugins/OpenFlight/Registry.cpp create mode 100644 src/osgPlugins/OpenFlight/Registry.h create mode 100644 src/osgPlugins/OpenFlight/ReservedRecords.cpp create mode 100644 src/osgPlugins/OpenFlight/RoadRecords.cpp create mode 100644 src/osgPlugins/OpenFlight/Vertex.cpp create mode 100644 src/osgPlugins/OpenFlight/Vertex.h create mode 100644 src/osgPlugins/OpenFlight/VertexRecords.cpp create mode 100644 src/osgPlugins/OpenFlight/opcodes.h create mode 100644 src/osgPlugins/OpenFlight/types.h create mode 100644 src/osgSim/OpenFlightOptimizer.cpp create mode 100644 src/osgWrappers/osgSim/OpenFlightOptimizer.cpp diff --git a/Make/makedirdefs b/Make/makedirdefs index 10311f83c..61060bf33 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -70,8 +70,9 @@ PLUGIN_DIRS = \ directx \ dw \ dxf \ - ESRIShape \ + ESRIShape \ flt \ + OpenFlight \ hdr \ ive \ lib3ds \ @@ -80,7 +81,7 @@ PLUGIN_DIRS = \ lws \ md2 \ net \ - normals \ + normals \ obj \ osg \ osga \ diff --git a/VisualStudio/OpenSceneGraph.dsw b/VisualStudio/OpenSceneGraph.dsw index cd40f2fed..c6cb17e87 100644 --- a/VisualStudio/OpenSceneGraph.dsw +++ b/VisualStudio/OpenSceneGraph.dsw @@ -2763,6 +2763,30 @@ Package=<4> ############################################################################### +Project: "osgPlugin OpenFlight"=.\osgPlugins\OpenFlight\OpenFlight.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name Core osg + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgDB + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgUtil + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgSim + End Project Dependency +}}} + +############################################################################### + Project: "osgPlugin freetype"=.\osgPlugins\freetype\freetype.dsp - Package Owner=<4> Package=<5> diff --git a/VisualStudio/osgPlugins/OpenFlight/OpenFlight.dsp b/VisualStudio/osgPlugins/OpenFlight/OpenFlight.dsp new file mode 100644 index 000000000..9df4c47d2 --- /dev/null +++ b/VisualStudio/osgPlugins/OpenFlight/OpenFlight.dsp @@ -0,0 +1,222 @@ +# Microsoft Developer Studio Project File - Name="osgPlugin OpenFlight" - 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 OpenFlight - 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 "OpenFlight.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 "OpenFlight.mak" CFG="osgPlugin OpenFlight - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "osgPlugin OpenFlight - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "osgPlugin OpenFlight - 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 OpenFlight - 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 "" +F90=df.exe +# 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" /I "../../../../OpenThreads/include" /I "../../../../Producer/include" /I "../../../../3rdParty/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FLT_LIBRARY" /YX /FD /Zm200 /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 OpenThreadsWin32.lib /nologo /dll /pdb:none /machine:I386 /out:"../../../bin/osgdb_OpenFlight.dll" /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib" + +!ELSEIF "$(CFG)" == "osgPlugin OpenFlight - 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 "" +F90=df.exe +# 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 /GR /GX /Zi /Od /I "../../../include" /I "../../../../OpenThreads/include" /I "../../../../Producer/include" /I "../../../../3rdParty/include" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FLT_LIBRARY" /D "WIN32" /D "_DEBUG" /YX /FD /GZ /Zm200 /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 OpenThreadsWin32d.lib /nologo /dll /pdb:"../../../bin/osgdb_OpenFlightd.pdb" /debug /machine:I386 /out:"../../../bin/osgdb_OpenFlightd.dll" /pdbtype:sept /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib" +# SUBTRACT LINK32 /pdb:none /incremental:no + +!ENDIF + +# Begin Target + +# Name "osgPlugin OpenFlight - Win32 Release" +# Name "osgPlugin OpenFlight - 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\OpenFlight\AncillaryRecords.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\AttrData.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\ControlRecords.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\DataInputStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Document.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\GeometryRecords.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\LightPointRecords.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\PaletteRecords.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Pools.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\PrimaryRecords.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\ReaderWriterATTR.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\ReaderWriterFLT.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Record.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\RecordInputStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\ReservedRecords.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\RoadRecords.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Vertex.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\VertexRecords.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;" +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\AttrData.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\DataInputStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Document.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\opcodes.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Pools.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Record.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\RecordInputStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Registry.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\types.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\OpenFlight\Vertex.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" +# End Group +# End Target +# End Project diff --git a/VisualStudio/osgSim/osgSim.dsp b/VisualStudio/osgSim/osgSim.dsp index 0bb34e8d7..fa5acefdd 100644 --- a/VisualStudio/osgSim/osgSim.dsp +++ b/VisualStudio/osgSim/osgSim.dsp @@ -139,6 +139,10 @@ SOURCE=..\..\src\osgSim\OverlayNode.cpp # End Source File # Begin Source File +SOURCE=..\..\src\osgSim\OpenFlightOptimizer.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\osgSim\ScalarBar.cpp # End Source File # Begin Source File @@ -219,6 +223,10 @@ SOURCE=..\..\include\osgSim\OverlayNode # End Source File # Begin Source File +SOURCE=..\..\include\osgSim\OpenFlightOptimizer +# End Source File +# Begin Source File + SOURCE=..\..\include\osgSim\ScalarBar # End Source File # Begin Source File diff --git a/VisualStudio/osgWrappers/osgSim/wrapper_osgSim.dsp b/VisualStudio/osgWrappers/osgSim/wrapper_osgSim.dsp index 1d59403c0..dacc0690e 100644 --- a/VisualStudio/osgWrappers/osgSim/wrapper_osgSim.dsp +++ b/VisualStudio/osgWrappers/osgSim/wrapper_osgSim.dsp @@ -139,6 +139,10 @@ SOURCE=..\..\..\src\osgWrappers\osgSim\LightPointSystem.cpp SOURCE=..\..\..\src\osgWrappers\osgSim\MultiSwitch.cpp # End Source File +# Begin Source File +SOURCE=..\..\..\src\osgWrappers\osgSim\OpenFlightOptimizer.cpp +# End Source File + # Begin Source File SOURCE=..\..\..\src\osgWrappers\osgSim\OverlayNode.cpp # End Source File diff --git a/include/osgSim/OpenFlightOptimizer b/include/osgSim/OpenFlightOptimizer new file mode 100644 index 000000000..dce138f27 --- /dev/null +++ b/include/osgSim/OpenFlightOptimizer @@ -0,0 +1,114 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef OSGSIM_OPENFLIGHTOPTIMIZER +#define OSGSIM_OPENFLIGHTOPTIMIZER + +#include +#include +#include + +#include + +namespace osgFlightUtil { + +/** Flight optimizer + */ +class OSGSIM_EXPORT Optimizer +{ + public: + + Optimizer() {} + virtual ~Optimizer() {} + + enum OptimizationOptions + { + TESSELATE_POLYGON = 0x001, + MERGE_GEODES = 0x002, + MAKE_LIT = 0x004, + DEFAULT_OPTIMIZATIONS = TESSELATE_POLYGON | MERGE_GEODES, + ALL_OPTIMIZATIONS = TESSELATE_POLYGON | MERGE_GEODES + }; + + + /** Traverse the node and its subgraph with a series of optimization + * visitors, specified by the OptimizationOptions.*/ + void optimize(osg::Node* node); + + /** Traverse the node and its subgraph with a series of optimization + * visitors, specified by the OptimizationOptions.*/ + virtual void optimize(osg::Node* node, unsigned int options); + + protected: + + + public: + + class TesselateVisitor : public osg::NodeVisitor + { + public: + + /// default to traversing all children. + TesselateVisitor() : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + virtual void apply(osg::Geode& geode); + + protected: + + bool hasPolygons(osg::Geometry& geometry); + + }; + + class MakeLitVisitor : public osg::NodeVisitor + { + public: + + /// default to traversing all children. + MakeLitVisitor() : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + virtual void apply(osg::Geode& geode); + }; + + + /** Combine geodes + */ + class MergeGeodesVisitor : public osg::NodeVisitor + { + public: + + /// default to traversing all children. + MergeGeodesVisitor() : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + virtual void apply(osg::Group& group); + + void mergeGeodes(osg::Group& group); + + protected: + + bool mergeGeode(osg::Geode& lhs, osg::Geode& rhs); + + }; + +}; + +} // end namespace + +#endif diff --git a/src/osgDB/Registry.cpp b/src/osgDB/Registry.cpp index 8f07dd3ef..0f401e49e 100644 --- a/src/osgDB/Registry.cpp +++ b/src/osgDB/Registry.cpp @@ -140,6 +140,15 @@ Registry::Registry() initFilePathLists(); // register file extension alias. + const char* flt_str = getenv("OSG_OPEN_FLIGHT_PLUGIN"); + if (flt_str) + { + if (strcmp(flt_str, "new")==0) + { + addFileExtensionAlias("flt", "OpenFlight"); + } + } + addFileExtensionAlias("sgi", "rgb"); addFileExtensionAlias("rgba", "rgb"); addFileExtensionAlias("int", "rgb"); diff --git a/src/osgPlugins/OpenFlight/AncillaryRecords.cpp b/src/osgPlugins/OpenFlight/AncillaryRecords.cpp new file mode 100644 index 000000000..210ae31c1 --- /dev/null +++ b/src/osgPlugins/OpenFlight/AncillaryRecords.cpp @@ -0,0 +1,269 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include + +#include "Registry.h" +#include "Document.h" +#include "RecordInputStream.h" + +namespace flt { + +/** Comment - + */ +class Comment : public Record +{ + public: + + Comment() {} + + META_Record(Comment) + + protected: + + virtual ~Comment() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::streamsize size = in.getRecordSize(); + std::string comment = in.readString(size-4); + + if (_parent.valid()) + _parent->setComment(comment); + } +}; + +RegisterRecordProxy g_Comment(COMMENT_OP); + + +/** LongID - + */ +class LongID : public Record +{ + public: + + LongID() {} + + META_Record(LongID) + + protected: + + virtual ~LongID() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::streamsize size = in.getRecordSize(); + std::string id = in.readString(size-4); + + if (_parent.valid()) + _parent->setID(id); + } +}; + +RegisterRecordProxy g_LongID(LONG_ID_OP); + + +/** Matrix - + */ +class Matrix : public Record +{ + public: + + Matrix() {} + + META_Record(Matrix) + + protected: + + virtual ~Matrix() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + osg::Matrix matrix; + for (int i=0; i<4; ++i) + { + for (int j=0; j<4; ++j) + { + matrix(i,j) = in.readFloat32(); + } + } + + // scale position. + osg::Vec3 pos = matrix.getTrans(); + matrix *= osg::Matrix::translate(-pos); + pos *= (float)document.unitScale(); + matrix *= osg::Matrix::translate(pos); + + if (_parent.valid()) + _parent->setMatrix(matrix); + } +}; + +RegisterRecordProxy g_Matrix(MATRIX_OP); + + +/** Multitexture - + */ +class Multitexture : public Record +{ + public: + + Multitexture() {} + + META_Record(Multitexture) + + protected: + + virtual ~Multitexture() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + osg::ref_ptr stateset = new osg::StateSet; + + uint32 mask = in.readUInt32(); + for (int layer=1; layer<8; layer++) + { + uint32 layerBit = 0x80000000u >> (layer-1); + if (mask & layerBit) + { + int16 textureIndex = in.readInt16(); + int16 effectIndex = in.readInt16(); + int16 mappingIndex = in.readInt16(); + uint16 data= in.readUInt16(); + + osg::ref_ptr texturePoolStateset = document.getOrCreateTexturePool()->get(textureIndex); + if (stateset.valid() && texturePoolStateset.valid()) + { + osg::Texture2D* texture = dynamic_cast(texturePoolStateset->getTextureAttribute(0,osg::StateAttribute::TEXTURE)); + if (texture) + stateset->setTextureAttributeAndModes(layer,texture,osg::StateAttribute::ON); + } + } + } + + if (_parent.valid()) + _parent->setMultitexture(*stateset); + } +}; + +RegisterRecordProxy g_Multitexture(MULTITEXTURE_OP); + + +/** UVList - Texture coordinates used with multitexture. + UVList is an ancillary to VertexList. + */ +class UVList : public Record +{ + public: + + UVList() {} + + META_Record(UVList) + + protected: + + virtual ~UVList() {} + + // count number of 1's in mask. + int bitCount(uint32 mask) + { + int count = 0; + while (mask) + { + if (mask & 0x0001) + ++count; + mask >>= 1; + } + return count; + } + + virtual void readRecord(RecordInputStream& in, Document& document) + { + uint32 mask = in.readUInt32(0); + + int numLayers = bitCount(mask); + int numVertices = (in.getRecordSize()-8) / (8 * numLayers); + for (int n=0; n < numVertices; ++n) + { + for (unsigned int layer=1; layer<8; layer++) + { + uint32 layerBit = 0x80000000u >> (layer-1); + if (mask & layerBit) + { + float32 u = in.readFloat32(); + float32 v = in.readFloat32(); + + // Add texture coodinates to geometry. + if (_parent.valid()) + _parent->addVertexUV(layer,osg::Vec2(u,v)); + } + } + } + } +}; + +RegisterRecordProxy g_UVList(UV_LIST_OP); + + +/** Replicate - + */ +class Replicate : public Record +{ + public: + + Replicate() {} + + META_Record(Replicate) + + protected: + + virtual ~Replicate() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int16 replicate = in.readInt16(); + + if (_parent.valid()) + _parent->setNumberOfReplications((int)replicate); + } +}; + +RegisterRecordProxy g_Replicate(REPLICATE_OP); + + +// Prevent "unknown record" message for the following ancillary records: +RegisterRecordProxy g_OldTranslate(OLD_TRANSLATE2_OP); +RegisterRecordProxy g_OldRotateAboutPoint(OLD_ROTATE_ABOUT_POINT_OP); +RegisterRecordProxy g_OldRotateAboutEdge(OLD_ROTATE_ABOUT_EDGE_OP); +RegisterRecordProxy g_OldScale(OLD_SCALE_OP); +RegisterRecordProxy g_OldTranslate2(OLD_TRANSLATE_OP); +RegisterRecordProxy g_OldNonuniformScale(OLD_NONUNIFORM_SCALE_OP); +RegisterRecordProxy g_OldRotateAboutPoint2(OLD_ROTATE_ABOUT_POINT2_OP); +RegisterRecordProxy g_OldRotateScaleToPoint(OLD_ROTATE_SCALE_TO_POINT_OP); +RegisterRecordProxy g_OldPutTransform(OLD_PUT_TRANSFORM_OP); +RegisterRecordProxy g_OldBoundingBox(OLD_BOUNDING_BOX_OP); +RegisterRecordProxy g_IndexedString(INDEXED_STRING_OP); +RegisterRecordProxy g_RoadZone(ROAD_ZONE_OP); +RegisterRecordProxy g_RotateAboutEdge(ROTATE_ABOUT_EDGE_OP); +RegisterRecordProxy g_Translate(TRANSLATE_OP); +RegisterRecordProxy g_Scale(NONUNIFORM_SCALE_OP); +RegisterRecordProxy g_RotateAboutPoint(ROTATE_ABOUT_POINT_OP); +RegisterRecordProxy g_RotateScaleToPoint(ROTATE_SCALE_TO_POINT_OP); +RegisterRecordProxy g_PutTransform(PUT_TRANSFORM_OP); +RegisterRecordProxy g_GeneralMatrix(GENERAL_MATRIX_OP); +RegisterRecordProxy g_Vector(VECTOR_OP); +RegisterRecordProxy g_BoundingBox(BOUNDING_BOX_OP); +RegisterRecordProxy g_BoundingSphere(BOUNDING_SPHERE_OP); +RegisterRecordProxy g_BoundingCylinder(BOUNDING_CYLINDER_OP); +RegisterRecordProxy g_BoundingConvexHull(BOUNDING_CONVEX_HULL_OP); +RegisterRecordProxy g_BoundingHistogram(BOUNDING_HISTOGRAM); +RegisterRecordProxy g_BoundingVolumeCenter(BOUNDING_VOLUME_CENTER_OP); +RegisterRecordProxy g_BoundingVolumeOrientation(BOUNDING_VOLUME_ORIENTATION_OP); +RegisterRecordProxy g_HistogramBoundingVolume(HISTOGRAM_BOUNDING_VOLUME_OP); + +} // end namespace + diff --git a/src/osgPlugins/OpenFlight/AttrData.cpp b/src/osgPlugins/OpenFlight/AttrData.cpp new file mode 100644 index 000000000..a064a57af --- /dev/null +++ b/src/osgPlugins/OpenFlight/AttrData.cpp @@ -0,0 +1,76 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include "AttrData.h" + +using namespace flt; + + +AttrData::AttrData() : + texels_u(0), + textel_v(0), + direction_u(0), + direction_v(0), + x_up(0), + y_up(0), + fileFormat(-1), // -1 Not used + minFilterMode(MIN_FILTER_NONE), + magFilterMode(MAG_FILTER_POINT), + wrapMode(WRAP_REPEAT), + wrapMode_u(WRAP_REPEAT), + wrapMode_v(WRAP_REPEAT), + modifyFlag(0), + pivot_x(0), + pivot_y(0), + texEnvMode(TEXENV_MODULATE), + intensityAsAlpha(0), + size_u(0), + size_v(0), + originCode(0), + kernelVersion(0), + intFormat(0), // 0 - Default + extFormat(0), // 0 - Default + useMips(0), + // float32 _mips[8]), + useLodScale(0), + // float32 lod0), + // float32 scale0), + // ... + // float32 lod7), + // float32 scale7), + clamp(0), + magFilterAlpha(2), // 2 = None + magFilterColor(2), // 2 = None + lambertMeridian(0), + lambertUpperLat(0), + lambertlowerLat(0), + useDetail(0), + txDetail_j(0), + txDetail_k(0), + txDetail_m(0), + txDetail_n(0), + txDetail_s(0), + useTile(0), + txTile_ll_u(0), + txTile_ll_v(0), + txTile_ur_u(0), + txTile_ur_v(0), + projection(PROJECTION_UNDEFINED), + earthModel(DATUM_WGS84), + utmZone(0), + imageOrigin(0), + geoUnits(0), + hemisphere(1), + comments(""), + attrVersion(0), + controlPoints(0) + // TODO: +{} + +AttrData::AttrData(const AttrData& attr, const osg::CopyOp& copyop) : + osg::Object(attr,copyop) +{} + diff --git a/src/osgPlugins/OpenFlight/AttrData.h b/src/osgPlugins/OpenFlight/AttrData.h new file mode 100644 index 000000000..a1362c6a3 --- /dev/null +++ b/src/osgPlugins/OpenFlight/AttrData.h @@ -0,0 +1,310 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_ATTRDATA_H +#define FLT_ATTRDATA_H + +#include +#include +#include "types.h" + +namespace flt { + + +class AttrData : public osg::Object +{ + public : + + AttrData(); + + AttrData(const AttrData& attr, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(flt,AttrData); + + + enum MinFilterMode { + MIN_FILTER_POINT = 0, + MIN_FILTER_BILINEAR = 1, + MIN_FILTER_MIPMAP = 2, // (Obsolete) + MIN_FILTER_MIPMAP_POINT = 3, + MIN_FILTER_MIPMAP_LINEAR = 4, + MIN_FILTER_MIPMAP_BILINEAR = 5, + MIN_FILTER_MIPMAP_TRILINEAR = 6, + MIN_FILTER_NONE = 7, + MIN_FILTER_BICUBIC = 8, + MIN_FILTER_BILINEAR_GEQUAL = 9, + MIN_FILTER_BILINEAR_LEQUAL = 10, + MIN_FILTER_BICUBIC_GEQUAL = 11, + MIN_FILTER_BICUBIC_LEQUAL = 12 + }; + + enum MagFilterMode { + MAG_FILTER_POINT = 0, + MAG_FILTER_BILINEAR = 1, + MAG_FILTER_NONE = 2, + MAG_FILTER_BICUBIC = 3, + MAG_FILTER_SHARPEN = 4, + MAG_FILTER_ADD_DETAIL = 5, + MAG_FILTER_MODULATE_DETAIL = 6, + MAG_FILTER_BILINEAR_GEQUAL = 7, + MAG_FILTER_BILINEAR_LEQUAL = 8, + MAG_FILTER_BICUBIC_GEQUAL = 9, + MAG_FILTER_BICUBIC_LEQUAL = 10 + }; + + enum WrapMode { + WRAP_REPEAT = 0, + WRAP_CLAMP = 1 + }; + + enum TexEnvMode { + TEXENV_MODULATE = 0, + TEXENV_BLEND = 1, + TEXENV_DECAL = 2, + TEXENV_COLOR = 3 + }; + + enum Projection { + PROJECTION_FLAT = 0, + PROJECTION_LAMBERT_CONIC = 3, + PROJECTION_UTM = 4, + PROJECTION_UNDEFINED = 7 + }; + + enum Datum { + DATUM_WGS84 = 0, + DATUM_WGS72 = 1, + DATUM_BESSEL = 2, + DATUM_CLARK_1866 = 3, + DATUM_NAD27 = 4 + }; + + + int32 texels_u; // Number of texels in u direction + int32 textel_v; // Number of texels in v direction + int32 direction_u; // Real world size u direction + int32 direction_v; // Real world size v direction + int32 x_up; // x component of up vector + int32 y_up; // y component of up vector + int32 fileFormat; // File format type + // -1 Not used + // 0 AT&T image 8 pattern + // 1 AT&T image 8 template + // 2 SGI intensity modulation + // 3 SGI intensity w/ alpha + // 4 SGI RGB + // 5 SGI RGB w/ alpha + int32 minFilterMode; // Minification filter type + // 0 - TX_POINT + // 1 - TX_BILINEAR + // 2 - TX_MIPMAP (Obsolete) + // 3 - TX_MIPMAP_POINT + // 4 - TX_MIPMAP_LINEAR + // 5 - TX_MIPMAP_BILINEAR + // 6 - TX_MIPMAP_TRILINEAR + // 7 - None + // 8 - TX_BICUBIC + // 9 - TX_BILINEAR_GEQUAL + // 10 - TX_BILINEAR_LEQUAL + // 11 - TX_BICUBIC_GEQUAL + // 12 - TX_BICUBIC_LEQUAL + int32 magFilterMode; // Magnification filter type + // 0 - TX_POINT + // 1 - TX_BILINEAR + // 2 - None + // 3 - TX_BICUBIC + // 4 - TX_SHARPEN + // 5 - TX_ADD_DETAIL + // 6 - TX_MODULATE_DETAIL + // 7 - TX_BILINEAR_GEQUAL + // 8 - TX_BILINEAR_LEQUAL + // 9 - TX_BICUBIC_GEQUAL + // 10 - TX_BICUBIC_LEQUAL + int32 wrapMode; // Repetition type + // 0 - TX_REPEAT + // 1 - TX_CLAMP + // 2 - (Obsolete) + int32 wrapMode_u; // Repetition type in u direction (see above) + int32 wrapMode_v; // Repetition type in v direction (see above) + int32 modifyFlag; // Modify flag (for internal use) + int32 pivot_x; // x pivot point for rotating textures + int32 pivot_y; // y pivot point for rotating textures + + // -------------- + // v11 ends here + // -------------- + + int32 texEnvMode; // Environment type + // 0 - TV_MODULATE + // 1 - TV_BLEND + // 2 - TV_DECAL + // 3 - TV_COLOR + int32 intensityAsAlpha; // TRUE if intensity pattern to be loaded in alpha with white in color +// int32 spare1[8]; // 8 words of spare + float64 size_u; // Real world size u for floating point databases + float64 size_v; // Real world size v for floating point databases + int32 originCode; // Code for origin of imported texture + int32 kernelVersion; // Kernel version number + int32 intFormat; // Internal format type + // 0 - Default + // 1 - TX_I_12A_4 + // 2 - TX_IA_8 + // 3 - TX_RGB_5 + // 4 - TX_RGBA_4 + // 5 - TX_IA_12 + // 6 - TX_RGBA_8 + // 7 - TX_RGBA_12 + // 8 - TX_I_16 (shadow mode only) + // 9 - TX_RGB_12 + int32 extFormat; // External format type + // 0 - Default + // 1 - TX_PACK_8 + // 2 - TX_PACK_16 + int32 useMips; // TRUE if using following 8 floats for MIPMAP kernel + float32 _mips[8]; // 8 floats for kernel of separable symmetric filter + int32 useLodScale; // Boolean if TRUE send: + float32 lod0; // LOD0 for TX_CONTROL_POINT + float32 scale0; // SCALE0 for TX_CONTROL_POINT + float32 lod1; // LOD1 for TX_CONTROL_POINT + float32 scale1; // SCALE1 for TX_CONTROL_POINT + float32 lod2; // LOD2 for TX_CONTROL_POINT + float32 scale2; // SCALE2 for TX_CONTROL_POINT + float32 lod3; // LOD3 for TX_CONTROL_POINT + float32 scale3; // SCALE3 for TX_CONTROL_POINT + float32 lod4; // LOD4 for TX_CONTROL_POINT + float32 scale4; // SCALE4 for TX_CONTROL_POINT + float32 lod5; // LOD5 for TX_CONTROL_POINT + float32 scale5; // SCALE5 for TX_CONTROL_POINT + float32 lod6; // LOD6 for TX_CONTROL_POINT + float32 scale6; // SCALE6 for TX_CONTROL_POINT + float32 lod7; // LOD7 for TX_CONTROL_POINT + float32 scale7; // SCALE7 for TX_CONTROL_POINT + + float32 clamp; // Clamp + int32 magFilterAlpha; // magfilteralpha: + // 0 = TX_POINT + // 1 = TX_BILINEAR + // 2 = None + // 3 = TX_BICUBIC + // 4 = TX_SHARPEN + // 5 = TX_ADD_DETAIL + // 6 = TX_MODULATE_DETAIL + // 7 = TX_BILINEAR_GEQUAL + // 8 = TX_BILINEAR_LEQUAL + // 9 = TX_BICUBIC_GEQUAL + // 10 = TX_BIBICUBIC_LEQUAL + int32 magFilterColor; // magfiltercolor: + // 0 = TX_POINT + // 1 = TX_BILINEAR + // 2 = None + // 3 = TX_BICUBIC + // 4 = TX_SHARPEN + // 5 = TX_ADD_DETAIL + // 6 = TX_MODULATE_DETAIL + // 7 = TX_BILINEAR_GEQUAL + // 8 = TX_BILINEAR_LEQUAL + // 9 = TX_BICUBIC_GEQUAL + // 10 = TX_BIBICUBIC_LEQUAL +// float32 reserved1; // Reserved +// float32 reserved2[8]; // Reserved + float64 lambertMeridian; // Lambert conic projection central meridian + float64 lambertUpperLat; // Lambert conic projection upper latitude + float64 lambertlowerLat; // Lambert conic projection lower latitude +// float64 reserved3; // Reserved +// float32 spare2[5]; // Spare + int32 useDetail; // TRUE if using next 5 integers for detail texture + int32 txDetail_j; // J argument for TX_DETAIL + int32 txDetail_k; // K argument for TX_DETAIL + int32 txDetail_m; // M argument for TX_DETAIL + int32 txDetail_n; // N argument for TX_DETAIL + int32 txDetail_s; // Scramble argument for TX_DETAIL + int32 useTile; // TRUE if using next for floats for TX_TILE + float32 txTile_ll_u; // Lower-left u value for TX_TILE + float32 txTile_ll_v; // Lower-left v value for TX_TILE + float32 txTile_ur_u; // Upper-right u value for TX_TILE + float32 txTile_ur_v; // Upper-right v value for TX_TILE + int32 projection; // Projection + // 0 = Flat earth + // 3 = Lambert conic + // 4 = UTM + // 7 = Undefined projection + int32 earthModel; // Earth model + // 0 = WGS84 + // 1 = WGS72 + // 2 = Bessel + // 3 = Clark 1866 + // 4 = NAD27 +// int32 reserved4; // Reserved + int32 utmZone; // UTM zone + int32 imageOrigin; // Image origin + // 0 = Lower-left + // 1 = Upper-left + int32 geoUnits; // Geospecific points units + // 0 = Degrees + // 1 = Meters + // 2 = Pixels +// int32 reserved5; // Reserved +// int32 reserved6; // Reserved + int32 hemisphere; // Hemisphere for geospecific points units + // 0 = Southern + // 1 = Northern +// int32 reserved7; // Reserved +// int32 reserved8; // Reserved +// int32 spare3[149]; // Spare +// char comments[512]; // Comments + std::string comments; + // -------------- + // v12 ends here + // -------------- + +// int32 reserved9[13]; // Reserved + int32 attrVersion; // Attribute file version number + + int32 controlPoints; // Number of geospecific control points + // If the number of geospecific control points is > 0, + // the following fields are also in the attribute file: + int32 reserved10; // Reserved + #if 0 + // For each geospecific control point: + { + float64 texel_u; // Texel u of geospecific control point + float64 texel_v; // Texel v of geospecific control point + float64 geoPoint[2]; // Real earth coordinate of geospecific control point + // (this value depends on the projection, earth model, + // and geospecific points units) + } + + // ---------------- + // v15.6 ends here + // ---------------- + + // After all geospecific control points are listed, the following subtexture + // information appears: + int32 subtextures; // Number of subtexture definitions contained in the + // texture attribute file + // If the number of subtexture definitions is >0, + // the following fields are repeated for each subtexture definition: + { + char name[32]; // name of subtexture definition + int32 left; // Coordinate of left edge of subtexture + // definition measured in texels. + int32 bottom; // Coordinate of bottom edge of subtexture + // definition measured in texels. + int32 right; // Coordinate of right edge of subtexture + // definition measured in texels. + int32 top; // Coordinate of top edge of subtexture + // definition measured in texels. + } + #endif + +}; + + +} // end namespace + +#endif + + diff --git a/src/osgPlugins/OpenFlight/ControlRecords.cpp b/src/osgPlugins/OpenFlight/ControlRecords.cpp new file mode 100644 index 000000000..9de893d86 --- /dev/null +++ b/src/osgPlugins/OpenFlight/ControlRecords.cpp @@ -0,0 +1,210 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include +#include +#include "Registry.h" +#include "Document.h" +#include "RecordInputStream.h" + +namespace flt { + + + +/** PushLevel +*/ +class PushLevel : public Record +{ + public: + + PushLevel() {} + + META_Record(PushLevel) + + virtual void read(RecordInputStream& in, Document& document) + { + document.pushLevel(); + } + + protected: + + virtual ~PushLevel() {} +}; + +RegisterRecordProxy g_PushLevel(PUSH_LEVEL_OP); + + +/** PophLevel +*/ +class PopLevel : public Record +{ + public: + + PopLevel() {} + + META_Record(PopLevel) + + virtual void read(RecordInputStream& in, Document& document) + { + document.popLevel(); + } + + protected: + + virtual ~PopLevel() {} +}; + +RegisterRecordProxy g_PopLevel(POP_LEVEL_OP); + + +/** PushSubface +*/ +class PushSubface : public Record +{ + public: + + PushSubface() {} + + META_Record(PushSubface) + + virtual void read(RecordInputStream& in, Document& document) + { + document.pushSubface(); + } + + protected: + + virtual ~PushSubface() {} +}; + +RegisterRecordProxy g_PushSubface(PUSH_SUBFACE_OP); + + +/** PopSubface +*/ +class PopSubface : public Record +{ + public: + + PopSubface() {} + + META_Record(PopSubface) + + virtual void read(RecordInputStream& in, Document& document) + { + document.popSubface(); + } + + protected: + + virtual ~PopSubface() {} +}; + +RegisterRecordProxy g_PopSubface(POP_SUBFACE_OP); + + +/** PushExtension +*/ +class PushExtension : public Record +{ + public: + + PushExtension() {} + + META_Record(PushExtension) + + virtual void read(RecordInputStream& in, Document& document) + { + readRecord(in,document); + document.pushExtension(); + } + + protected: + + virtual ~PushExtension() {} +}; + +RegisterRecordProxy g_PushExtension(PUSH_EXTENSION_OP); + + +/** PopExtension +*/ +class PopExtension : public Record +{ + public: + + PopExtension() {} + + META_Record(PopExtension) + + virtual void read(RecordInputStream& in, Document& document) + { + readRecord(in,document); + document.popExtension(); + } + + protected: + + virtual ~PopExtension() {} +}; + +RegisterRecordProxy g_PopExtension(POP_EXTENSION_OP); + + +/** PushAttribute - Reserved subtree +*/ +class PushAttribute : public Record +{ + public: + + PushAttribute() {} + + META_Record(PushAttribute) + + virtual void read(RecordInputStream& in, Document& document) + { + readRecord(in,document); + // in().seekg(in.getEndOfRecord(), std::ios_base::beg); + // loop until PopAttribute + + } + + protected: + + virtual ~PushAttribute() {} +}; + +RegisterRecordProxy g_PushAttribute(PUSH_ATTRIBUTE_OP); + + +/** PopAttribute +*/ +class PopAttribute : public Record +{ + public: + + PopAttribute() {} + + META_Record(PopAttribute) + + virtual void read(RecordInputStream& in, Document& document) + { + readRecord(in,document); + } + + protected: + + virtual ~PopAttribute() {} +}; + +RegisterRecordProxy g_PopAttribute(POP_ATTRIBUTE_OP); + + +} // end namespace + + + diff --git a/src/osgPlugins/OpenFlight/DataInputStream.cpp b/src/osgPlugins/OpenFlight/DataInputStream.cpp new file mode 100644 index 000000000..d2f347a5f --- /dev/null +++ b/src/osgPlugins/OpenFlight/DataInputStream.cpp @@ -0,0 +1,210 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include "DataInputStream.h" + +#include +#include +#include + +using namespace flt; + + +DataInputStream::DataInputStream(std::istream* istream): + _istream(istream) +{ + _byteswap = osg::getCpuByteOrder() == osg::LittleEndian; + + if (!istream) + throw std::string("DataInputStream::DataInputStream(): null pointer exception in argument."); +} + + +DataInputStream::~DataInputStream() +{ +} + + +int8 DataInputStream::readInt8(int8 def) const +{ + int8 d=def; + read((char*)&d, sizeof(int8)); + return d; +} + + +uint8 DataInputStream::readUInt8(uint8 def) const +{ + uint8 d=def; + read((char*)&d, sizeof(uint8)); + return d; +} + + +int16 DataInputStream::readInt16(int16 def) const +{ + int16 d=def; + read((char*)&d, sizeof(int16)); + if (_byteswap && !_istream->fail()) + osg::swapBytes2((char *)&d); + return d; +} + + +uint16 DataInputStream::readUInt16(uint16 def) const +{ + uint16 d=def; + read((char*)&d, sizeof(uint16)); + if (_byteswap && !_istream->fail()) + osg::swapBytes2((char *)&d); + return d; +} + + +int32 DataInputStream::readInt32(int32 def) const +{ + int32 d=def; + read((char*)&d, sizeof(int32)); + if (_byteswap && !_istream->fail()) + osg::swapBytes4((char *)&d); + return d; +} + + +uint32 DataInputStream::readUInt32(uint32 def) const +{ + uint32 d=def; + read((char*)&d, sizeof(uint32)); + if (_byteswap && !_istream->fail()) + osg::swapBytes4((char *)&d); + return d; +} + + +float32 DataInputStream::readFloat32(float32 def) const +{ + float32 d=def; + char buf[sizeof(float32)]; + read(buf, sizeof(float32)); + if (_byteswap && !_istream->fail()) + { + osg::swapBytes4(buf); + memcpy(&d,buf,sizeof(float32)); + } + return d; +} + + +float64 DataInputStream::readFloat64(float64 def) const +{ + float64 d=def; + char buf[sizeof(float64)]; + read(buf, sizeof(float64)); + if (_byteswap && !_istream->fail()) + { + osg::swapBytes8(buf); + memcpy(&d,buf,sizeof(float64)); + } + return d; +} + + +void DataInputStream::readCharArray(char* data, int size) const +{ + read(data, size); +} + + +std::string DataInputStream::readString(int size) const +{ + char* buf = new char[size+1]; + read(buf,size); + buf[size] = '\0'; + std::string str = buf; + delete [] buf; + return str; +} + + +osg::Vec4f DataInputStream::readColor32() const +{ + uint8 alpha = readUInt8(); + uint8 blue = readUInt8(); + uint8 green = readUInt8(); + uint8 red = readUInt8(); + + osg::Vec4f color((float)red/255,(float)green/255,(float)blue/255,1); + + return color; +} + + +osg::Vec2f DataInputStream::readVec2f() const +{ + float32 x = readFloat32(); + float32 y = readFloat32(); + + osg::Vec2f vec(x,y); + + return vec; +} + + +osg::Vec3f DataInputStream::readVec3f() const +{ + float32 x = readFloat32(); + float32 y = readFloat32(); + float32 z = readFloat32(); + + osg::Vec3f vec(x,y,z); + + return vec; +} + + +osg::Vec3d DataInputStream::readVec3d() const +{ + float64 x = readFloat64(); + float64 y = readFloat64(); + float64 z = readFloat64(); + + osg::Vec3d vec(x,y,z); + + return vec; +} + + +int16 DataInputStream::peekInt16() const +{ + // Get current read position in stream. + std::istream::pos_type pos = _istream->tellg(); + + int16 value = readInt16(); + + // Restore position + _istream->seekg(pos, std::ios_base::beg); + + return value; +} + + +void DataInputStream::forward(std::istream::off_type _Off) const +{ + seekg(_Off, std::ios_base::cur); +} + + +std::istream& DataInputStream::read(std::istream::char_type *_Str, std::streamsize _Count) const +{ + return _istream->read(_Str, _Count); +} + + +std::istream& DataInputStream::seekg(std::istream::off_type _Off, std::ios_base::seekdir _Way) const +{ + return _istream->seekg(_Off, _Way); +} + diff --git a/src/osgPlugins/OpenFlight/DataInputStream.h b/src/osgPlugins/OpenFlight/DataInputStream.h new file mode 100644 index 000000000..9016717b9 --- /dev/null +++ b/src/osgPlugins/OpenFlight/DataInputStream.h @@ -0,0 +1,61 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_DATAINPUTSTREAM +#define FLT_DATAINPUTSTREAM 1 + +#include // for ifstream +#include +#include +#include +#include +#include "types.h" + +namespace flt { + +class Record; + +class DataInputStream +{ +public: + + DataInputStream(std::istream* istream); + virtual ~DataInputStream(); + + int8 readInt8(int8 def=0) const; + uint8 readUInt8(uint8 def=0) const; + int16 readInt16(int16 def=0) const; + uint16 readUInt16(uint16 def=0) const; + int32 readInt32(int32 def=0) const; + uint32 readUInt32(uint32 def=0) const; + float32 readFloat32(float32 def=0) const; + float64 readFloat64(float64 def=0) const; + void readCharArray(char* data, int size) const; + std::string readString(int size) const; + osg::Vec4f readColor32() const; + osg::Vec2f readVec2f() const; + osg::Vec3f readVec3f() const; + osg::Vec3d readVec3d() const; + + void forward(std::istream::off_type _Off) const; + + int16 peekInt16() const; + + inline std::istream& operator() () { return *_istream; } + +protected: + + virtual std::istream& read(std::istream::char_type *_Str, std::streamsize _Count) const; + virtual std::istream& seekg(std::istream::off_type _Off, std::ios_base::seekdir _Way) const; + + bool _byteswap; + std::istream* _istream; +}; + +} // end namespace + +#endif + diff --git a/src/osgPlugins/OpenFlight/Document.cpp b/src/osgPlugins/OpenFlight/Document.cpp new file mode 100644 index 000000000..5e73e4efe --- /dev/null +++ b/src/osgPlugins/OpenFlight/Document.cpp @@ -0,0 +1,114 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include "Document.h" + +using namespace flt; + + +Document::Document() : + _done(false), + _level(0), + _subfaceLevel(0), + _version(0), + _unitScale(1.0), + _defaultDOFAnimationState(false), + _useTextureAlphaForTransparancyBinning(true), + _doUnitsConversion(true), + _desiredUnits(METERS) +{ +} + + +Document::~Document() +{ +} + + +void Document::pushLevel() +{ + _levelStack.push_back(_currentPrimaryRecord.get()); + _level++; +} + + +void Document::popLevel() +{ + _levelStack.pop_back(); + + if (!_levelStack.empty()) + _currentPrimaryRecord = _levelStack.back().get(); + + if (--_level<=0) + _done = true; +} + + +void Document::pushSubface() +{ + _subfaceLevel++; +} + + +void Document::popSubface() +{ + _subfaceLevel--; +} + + +void Document::pushExtension() +{ + if (!_currentPrimaryRecord.valid()) + { + osg::notify(osg::WARN) << "No current primary in Document::pushExtension()." << std::endl; + return; + } + + _extensionStack.push_back(_currentPrimaryRecord.get()); +} + + +void Document::popExtension() +{ + _currentPrimaryRecord=_extensionStack.back().get(); + if (!_currentPrimaryRecord.valid()) + { + osg::notify(osg::WARN) << "Can't descide primary in Document::popExtension()." << std::endl; + return; + } + + _extensionStack.pop_back(); +} + + +osg::Node* Document::getInstanceDefinition(int no) +{ + InstanceDefinitionMap::iterator itr = _instanceDefinitionMap.find(no); + if (itr != _instanceDefinitionMap.end()) + return (*itr).second.get(); + + return NULL; +} + + +double flt::unitsToMeters(CoordUnits unit) +{ + switch (unit) + { + case METERS: + return 1.0; + case KILOMETERS: + return 1000.0; + case FEET: + return 0.3048; + case INCHES: + return 0.02540; + case NAUTICAL_MILES: + return 1852.0; + } + + return 1.0; +} diff --git a/src/osgPlugins/OpenFlight/Document.h b/src/osgPlugins/OpenFlight/Document.h new file mode 100644 index 000000000..386d1cdd4 --- /dev/null +++ b/src/osgPlugins/OpenFlight/Document.h @@ -0,0 +1,221 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_FLIGHTDATA_H +#define FLT_FLIGHTDATA_H 1 + +#include +#include +#include +#include +#include + +#include "types.h" +#include "Record.h" +#include "Pools.h" + + +namespace flt { + +class Header; +class PushLevel; +class PopLevel; + +enum Version +{ + VERSION_11 = 11, + VERSION_12 = 12, + VERSION_13 = 13, + VERSION_14 = 14, + VERSION_14_1 = 14, + VERSION_14_2 = 1420, + VERSION_15_1 = 1510, + VERSION_15_4 = 1540, + VERSION_15_5 = 1550, + VERSION_15_6 = 1560, + VERSION_15_7 = 1570, + VERSION_15_8 = 1580, + VERSION_16_0 = 1600 +}; + +enum CoordUnits { + METERS = 0, + KILOMETERS = 1, + FEET = 4, + INCHES = 5, + NAUTICAL_MILES = 8 +}; + +double unitsToMeters(CoordUnits unit); + + +enum Projection { + FLAT_EARTH = 0, + TRAPEZOIDAL = 1, + ROUND_EARTH = 2, + LAMBERT = 3, + UTM = 4, + GEODETIC = 5, + GEOCENTRIC = 6 +}; + +enum Ellipsoid { + WGS_1984 = 0, + WGS_1972 = 1, + BESSEL = 2, + CLARKE_1866 = 3, + NAD_1927 = 4 +}; + + +class Document +{ + public: + + Document(); + virtual ~Document(); + + void setOptions(const osgDB::ReaderWriter::Options* options) { _options = options; } + const osgDB::ReaderWriter::Options* getOptions() const { return _options.get(); } + + // Current primar record + void setCurrentPrimaryRecord(PrimaryRecord* record) {_currentPrimaryRecord=record; } + PrimaryRecord* getCurrentPrimaryRecord() { return _currentPrimaryRecord.get(); } + const PrimaryRecord* getCurrentPrimaryRecord() const { return _currentPrimaryRecord.get(); } + + // Level stack + PrimaryRecord* getTopOfLevelStack(); + void pushLevel(); + void popLevel(); + + // Subface stack + void pushSubface(); + void popSubface(); + + // Extension stack + void pushExtension(); + void popExtension(); + + + void setHeaderNode(osg::Node* node) { _osgHeader = node; } + osg::Node* getHeaderNode() { return _osgHeader.get(); } + + // Instance definitions + void setInstanceDefinition(int no, osg::Node* node) { _instanceDefinitionMap[no] = node; } + osg::Node* getInstanceDefinition(int no); + + uint32 version() const { return _version; } + bool done() const { return _done; } + int level() const { return _level; } + int subfaceLevel() const { return _subfaceLevel; } + double unitScale() const { return _unitScale; } + + // Pools + void setVertexPool(VertexPool* vp) { _vertexPool = vp; } + VertexPool* getVertexPool() { return _vertexPool.get(); } + const VertexPool* getVertexPool() const { return _vertexPool.get(); } + + void setColorPool(ColorPool* cp) { _colorPool = cp; } + ColorPool* getColorPool() { return _colorPool.get(); } + const ColorPool* getColorPool() const { return _colorPool.get(); } + + TexturePool* getOrCreateTexturePool(); + MaterialPool* getOrCreateMaterialPool(); + LightPointAppearancePool* getOrCreateLightPointAppearancePool(); + ShaderPool* getOrCreateShaderPool(); + + // Options + void setDefaultDOFAnimationState(bool state) { _defaultDOFAnimationState = state; } + bool getDefaultDOFAnimationState() const { return _defaultDOFAnimationState; } + void setUseTextureAlphaForTransparancyBinning(bool flag) { _useTextureAlphaForTransparancyBinning=flag; } + bool getUseTextureAlphaForTransparancyBinning() const { return _useTextureAlphaForTransparancyBinning; } + void setDoUnitsConversion(bool flag) { _doUnitsConversion=flag; } + bool getDoUnitsConversion() const { return _doUnitsConversion; } + void setDesiredUnits(CoordUnits units ) { _desiredUnits=units; } + CoordUnits getDesiredUnits() const { return _desiredUnits; } + + protected: + + // Options + osg::ref_ptr _options; + bool _defaultDOFAnimationState; + bool _useTextureAlphaForTransparancyBinning; + bool _doUnitsConversion; + CoordUnits _desiredUnits; + + friend class Header; + bool _done; + int _level; + int _subfaceLevel; + double _unitScale; + uint32 _version; + + // Header data + osg::ref_ptr _osgHeader; + + osg::ref_ptr _vertexPool; + osg::ref_ptr _colorPool; + osg::ref_ptr _texturePool; + osg::ref_ptr _materialPool; + osg::ref_ptr _lightPointAppearancePool; + osg::ref_ptr _shaderPool; + + osg::ref_ptr _currentPrimaryRecord; + + typedef std::vector > LevelStack; + LevelStack _levelStack; + LevelStack _extensionStack; + + typedef std::map > InstanceDefinitionMap; + InstanceDefinitionMap _instanceDefinitionMap; +}; + + +inline TexturePool* Document::getOrCreateTexturePool() +{ + if (!_texturePool.valid()) + _texturePool = new TexturePool; + return _texturePool.get(); +} + + +inline MaterialPool* Document::getOrCreateMaterialPool() +{ + if (!_materialPool.valid()) + _materialPool = new MaterialPool; + return _materialPool.get(); +} + + +inline LightPointAppearancePool* Document::getOrCreateLightPointAppearancePool() +{ + if (!_lightPointAppearancePool.valid()) + _lightPointAppearancePool = new LightPointAppearancePool; + return _lightPointAppearancePool.get(); +} + + +inline ShaderPool* Document::getOrCreateShaderPool() +{ + if (!_shaderPool.valid()) + _shaderPool = new ShaderPool; + return _shaderPool.get(); +} + + +inline PrimaryRecord* Document::getTopOfLevelStack() +{ + // Anything on the level stack? + if (_levelStack.empty()) + return NULL; + + return _levelStack.back().get(); +} + + +} // end namespace + +#endif diff --git a/src/osgPlugins/OpenFlight/GNUmakefile b/src/osgPlugins/OpenFlight/GNUmakefile new file mode 100644 index 000000000..6f4c3c2cf --- /dev/null +++ b/src/osgPlugins/OpenFlight/GNUmakefile @@ -0,0 +1,34 @@ +TOPDIR = ../../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + AncillaryRecords.cpp \ + AttrData.cpp \ + ControlRecords.cpp \ + DataInputStream.cpp \ + Document.cpp \ + GeometryRecords.cpp \ + LightPointRecords.cpp \ + PaletteRecords.cpp \ + Pools.cpp \ + PrimaryRecords.cpp \ + ReaderWriterATTR.cpp \ + ReaderWriterFLT.cpp \ + Record.cpp \ + RecordInputStream.cpp \ + Registry.cpp \ + ReservedRecords.cpp \ + RoadRecords.cpp \ + Vertex.cpp \ + VertexRecords.cpp \ + + +INC += -I$(THISDIR) + +LIBS += -losgSim -losgText $(OSG_LIBS) $(OTHER_LIBS) + +TARGET_BASENAME = OpenFlight +include $(TOPDIR)/Make/cygwin_plugin_def +PLUGIN = $(PLUGIN_PREFIX)$(TARGET_BASENAME).$(PLUGIN_EXT) + +include $(TOPDIR)/Make/makerules diff --git a/src/osgPlugins/OpenFlight/GeometryRecords.cpp b/src/osgPlugins/OpenFlight/GeometryRecords.cpp new file mode 100644 index 000000000..ce0a0b173 --- /dev/null +++ b/src/osgPlugins/OpenFlight/GeometryRecords.cpp @@ -0,0 +1,625 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Registry.h" +#include "Document.h" +#include "RecordInputStream.h" + +namespace flt { + +class Face : public PrimaryRecord +{ + // flags + static const unsigned int TERRAIN_BIT = 0x80000000u >> 0; + static const unsigned int NO_COLOR_BIT = 0x80000000u >> 1; + static const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2; + static const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3; + static const unsigned int FOOTPRINT_BIT = 0x80000000u >> 4; // Terrain culture cutout + static const unsigned int HIDDEN_BIT = 0x80000000u >> 5; + static const unsigned int ROOFLINE_BIT = 0x80000000u >> 6; + + osg::Vec4 _primaryColor; + + int32 _IRColor; + int16 _relativePriority; + uint8 _drawFlag; + uint8 _texturedWhite; + int16 _primaryNameIndex; + int16 _secondaryNameIndex; + uint8 _template; + int _detailTexture; + int _textureIndex; + int _materialIndex; + int16 _surface; + int16 _feature; + int32 _IRMaterial; + uint16 _transparency; + uint8 _influenceLOD; + uint8 _linestyle; + uint32 _flags; + uint8 _lightMode; + osg::Vec4 _primaryPackedColor; + osg::Vec4 _secondaryPackedColor; + int _textureMappingIndex; + int _primaryColorIndex; + int _alternateColorIndex; + int _shaderIndex; + + osg::ref_ptr _geode; + osg::ref_ptr _geometry; + +public: + + Face() : + _primaryColor(1,1,1,1) + { + } + + META_Record(Face) + + META_setID(_geode) + META_setComment(_geode) + META_setMatrix(_geode) + META_setMultitexture(_geode) + + // draw mode + enum DrawMode + { + SOLID_BACKFACED = 0, + SOLID_NO_BACKFACE = 1, + WIREFRAME_CLOSED = 2, + WIREFRAME_NOT_CLOSED = 3, + SURROUND_ALTERNATE_COLOR = 4, + OMNIDIRECTIONAL_LIGHT = 8, + UNIDIRECTIONAL_LIGHT = 9, + BIDIRECTIONAL_LIGHT = 10 + }; + + inline DrawMode getDrawMode() const { return (DrawMode)_drawFlag; } + + // lighting + enum LightMode + { + FACE_COLOR = 0, + VERTEX_COLOR = 1, + FACE_COLOR_LIGHTING = 2, + VERTEX_COLOR_LIGHTING = 3 + }; + + inline LightMode getLightMode() const { return (LightMode)_lightMode; } + inline bool isLit() const { return (_lightMode==FACE_COLOR_LIGHTING) || (_lightMode==VERTEX_COLOR_LIGHTING); } + inline bool isGouraud() const { return (_lightMode==VERTEX_COLOR) || (_lightMode==VERTEX_COLOR_LIGHTING); } + + // flags + inline bool noColor() const { return (_flags & NO_COLOR_BIT)!=0; } + inline bool isHidden() const { return (_flags & HIDDEN_BIT)!=0; } + inline bool isTerrain() const { return (_flags & TERRAIN_BIT)!=0; } + inline bool isFootprint() const { return (_flags & FOOTPRINT_BIT)!=0; } + inline bool isRoofline() const { return (_flags & ROOFLINE_BIT)!=0; } + inline bool packedColorMode() const { return (_flags & PACKED_COLOR_BIT)!=0; } + + // billboard + enum TemplateMode + { + FIXED_NO_ALPHA_BLENDING = 0, + FIXED_ALPHA_BLENDING = 1, + AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2, + POINT_ROTATE_WITH_ALPHA_BLENDING = 4 + }; + + inline TemplateMode getTemplateMode() const { return (TemplateMode)_template; } + + // transparency & alpha + inline bool isAlphaBlend() const + { + return (_template==FIXED_ALPHA_BLENDING) || + (_template==AXIAL_ROTATE_WITH_ALPHA_BLENDING) || + (_template==POINT_ROTATE_WITH_ALPHA_BLENDING); + } + + virtual osg::Vec4 getPrimaryColor() const { return _primaryColor; } + inline int getMaterialIndex() const { return _materialIndex; } + inline int getTextureIndex() const { return _textureIndex; } + inline int getTextureMappingIndex() const { return _textureMappingIndex; } + inline float getTransparency() const { return (float)_transparency / 65535.0f; } + inline bool isTransparent() const { return _transparency > 0; } + + virtual void addChild(osg::Node& child) + { + // Add subface to parent. + if (_parent.valid()) + _parent->addChild(child); + } + + virtual void addVertex(Vertex& vertex) + { + osg::Vec3Array* vertices = getOrCreateVertexArray(*_geometry); + vertices->push_back(vertex._coord); + + if (isGouraud()) + { + osg::Vec4Array* colors = getOrCreateColorArray(*_geometry); + if (vertex.validColor()) + { + colors->push_back(vertex._color); + } + else + { + // Use face color if vertex color is -1 in a gouraud polygon. + // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000967.html + colors->push_back(_primaryColor); + } + } + + if (vertex.validNormal()) + { + osg::Vec3Array* normals = getOrCreateNormalArray(*_geometry); + normals->push_back(vertex._normal); + } + + if (vertex.validUV()) + { + osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,0); + UVs->push_back(vertex._uv); + } + } + + virtual void addVertexUV(int unit, const osg::Vec2& uv) + { + osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,unit); + UVs->push_back(uv); + } + + virtual void addMorphVertex(Vertex& vertex0, Vertex& vertex100) + { + osg::Vec3Array* vertices = getOrCreateVertexArray(*_geometry); + vertices->push_back(vertex0._coord); + + if (isGouraud()) + { + osg::Vec4Array* colors = getOrCreateColorArray(*_geometry); + if (vertex0.validColor()) + { + colors->push_back(vertex0._color); + } + else + { + // Use face color if vertex color is -1 in a gouraud polygon. + // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000967.html + colors->push_back(_primaryColor); + } + } + + if (vertex0.validNormal()) + { + osg::Vec3Array* normals = getOrCreateNormalArray(*_geometry); + normals->push_back(vertex0._normal); + } + + if (vertex0.validUV()) + { + osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,0); + UVs->push_back(vertex0._uv); + } + } + +protected: + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + _IRColor = in.readInt32(); + _relativePriority = in.readInt16(); + _drawFlag = in.readUInt8(); + _texturedWhite = in.readUInt8(); + _primaryNameIndex = in.readInt16(-1); + _secondaryNameIndex = in.readInt16(-1); + in.forward(1); + _template = in.readUInt8(FIXED_NO_ALPHA_BLENDING); + _detailTexture = in.readInt16(-1); + _textureIndex = in.readInt16(-1); + _materialIndex = in.readInt16(-1); + _surface = in.readInt16(); + _feature = in.readInt16(); + _IRMaterial = in.readInt32(-1); + _transparency = in.readUInt16(0); + // version > 13 + _influenceLOD = in.readUInt8(); + _linestyle = in.readUInt8(); + _flags = in.readUInt32(0); + _lightMode = in.readUInt8(FACE_COLOR); + in.forward(7); + _primaryPackedColor = in.readColor32(); + _secondaryPackedColor = in.readColor32(); + // version >= VERSION_15_1 + _textureMappingIndex = in.readInt16(-1); + in.forward(2); + _primaryColorIndex = in.readInt32(-1); + _alternateColorIndex = in.readInt32(-1); + // version >= 16 + in.forward(2); + _shaderIndex = in.readInt16(-1); + + // Create Geode or Billboard. + switch (_template) + { + case AXIAL_ROTATE_WITH_ALPHA_BLENDING: + { + osg::Billboard* billboard = new osg::Billboard; + billboard->setMode(osg::Billboard::AXIAL_ROT); + _geode = billboard; + } + break; + case POINT_ROTATE_WITH_ALPHA_BLENDING: + { + osg::Billboard* billboard = new osg::Billboard; + billboard->setMode(osg::Billboard::POINT_ROT_WORLD); + _geode = billboard; + } + break; + default: + _geode = new osg::Geode; + } + + _geode->setDataVariance(osg::Object::STATIC); + _geode->setName(id); + + _geometry = new osg::Geometry; + _geometry->setDataVariance(osg::Object::STATIC); + _geode->addDrawable(_geometry.get()); + + // StateSet + osg::StateSet* stateset = _geode->getOrCreateStateSet(); + + // Hidden + if (isHidden()) + _geode->setNodeMask(0); + + // Face color + if (_texturedWhite!=0 && _textureIndex>=0) + { + _primaryColor = osg::Vec4(1,1,1,1); + } + else + { + if (packedColorMode()) + { + _primaryColor = _primaryPackedColor; + } + else + { + if (document.version() < VERSION_15_1) + _primaryColor = document.getColorPool()->getColor(_primaryNameIndex); + + else // >= VERSION_15_1 + _primaryColor = document.getColorPool()->getColor(_primaryColorIndex); + } + } + + // Lighting + stateset->setMode(GL_LIGHTING, isLit() ? osg::StateAttribute::ON : osg::StateAttribute::OFF); + + // Material + bool isTransparentMaterial = false; + if (isLit()) + { + osg::Vec4 col = _primaryColor; + col.a() = 1.0f - getTransparency(); + osg::Material* material = document.getOrCreateMaterialPool()->getOrCreateMaterial(_materialIndex,col); + stateset->setAttribute(material); + isTransparentMaterial = material->getDiffuse(osg::Material::FRONT).a() < 0.99f; + } + + // Shaders + if (_shaderIndex >= 0) + { + ShaderPool* sp = document.getOrCreateShaderPool(); + osg::Program* program = sp->get(_shaderIndex); + if (program) + stateset->setAttributeAndModes(program, osg::StateAttribute::ON); + } + + // Texture + TexturePool* tp = document.getOrCreateTexturePool(); + osg::StateSet* textureStateSet = tp->get(_textureIndex); + if (textureStateSet) + { + // Merge face stateset with texture stateset + stateset->merge(*textureStateSet); + } + + // Translucent image? + bool isImageTranslucent = false; + if (textureStateSet) + { + if (document.getUseTextureAlphaForTransparancyBinning()) + { + osg::Texture2D* texture = dynamic_cast(textureStateSet->getTextureAttribute(0,osg::StateAttribute::TEXTURE)); + if (texture) + { + osg::Image* image = texture->getImage(); + if (image && image->isImageTranslucent()) + isImageTranslucent = true; + } + } + } + + // Enable alpha blend? + if (isAlphaBlend() || isTransparent() || isTransparentMaterial || isImageTranslucent) + { + stateset->setAttributeAndModes(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA), osg::StateAttribute::ON); + stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + } + + // Cull face + switch(_drawFlag) + { + case SOLID_BACKFACED: // Enable backface culling + stateset->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK), osg::StateAttribute::ON); + break; + case SOLID_NO_BACKFACE: // Disable backface culling + stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); + break; + } + + // Subface + if (document.subfaceLevel() > 0) + { + osg::PolygonOffset* polyoffset = new osg::PolygonOffset; + polyoffset->setFactor(-10.0f); + polyoffset->setUnits(-40.0f); + stateset->setAttributeAndModes(polyoffset, osg::StateAttribute::ON); + + osg::Depth* depth = new osg::Depth; + depth->setWriteMask(false); + stateset->setAttribute(depth); + + stateset->setRenderBinDetails(document.subfaceLevel(),"RenderBin"); + } + + // Add to parent. + if (_parent.valid()) + _parent->addChild(*_geode); + } + + osg::PrimitiveSet::Mode getPrimitiveSetMode(int numVertices) + { + switch(getDrawMode()) + { + case WIREFRAME_NOT_CLOSED: + return osg::PrimitiveSet::LINE_STRIP; + case WIREFRAME_CLOSED: + return osg::PrimitiveSet::LINE_LOOP; + case OMNIDIRECTIONAL_LIGHT: + case UNIDIRECTIONAL_LIGHT: + case BIDIRECTIONAL_LIGHT: + return osg::PrimitiveSet::POINTS; + default: break; + } + + switch (numVertices) + { + case 1: return osg::PrimitiveSet::POINTS; + case 2: return osg::PrimitiveSet::LINES; + case 3: return osg::PrimitiveSet::TRIANGLES; + case 4: return osg::PrimitiveSet::QUADS; + default: break; + } + + return osg::PrimitiveSet::POLYGON; + } + + virtual ~Face() + { + if (_geode.valid()) + { + for (unsigned int i=0; i<_geode->getNumDrawables(); ++i) + { + osg::Geometry* geometry = dynamic_cast(_geode->getDrawable(i)); + if (geometry) + { + osg::Array* vertices = geometry->getVertexArray(); + if (vertices) + { + GLint first = 0; + GLsizei count = vertices->getNumElements(); + osg::PrimitiveSet::Mode mode = getPrimitiveSetMode(count); + geometry->addPrimitiveSet(new osg::DrawArrays(mode,first,count)); + } + + // Color binding + if (isGouraud()) + { + // Color per vertex + geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); + } + else + { + // Color per face + osg::Vec4 col = getPrimaryColor(); + col[3] = 1.0f - getTransparency(); + + geometry->setColorBinding(osg::Geometry::BIND_OVERALL); + osg::Vec4Array* colors = new osg::Vec4Array(1); + (*colors)[0] = col; + geometry->setColorArray(colors); + } + + // Normal binding + if (isLit()) + { + geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX ); + } + else + { + geometry->setNormalBinding(osg::Geometry::BIND_OFF); + geometry->setNormalArray(NULL); + } + } + } + } + } +}; + +RegisterRecordProxy g_Face(FACE_OP); +RegisterRecordProxy g_Mesh(MESH_OP); + + +/** VertexList - + * The VertexList is a leaf record. + * Possible parents: Face, Mesh & LightPoint + */ +class VertexList : public PrimaryRecord +{ +public: + + VertexList() {} + + META_Record(VertexList) + + virtual void addVertex(Vertex& vertex) + { + // forward vertex to parent. + if (_parent.valid()) + _parent->addVertex(vertex); + } + + virtual void addVertexUV(int layer,const osg::Vec2& uv) + { + // forward uv to parent. + if (_parent.valid()) + _parent->addVertexUV(layer,uv); + } + +protected: + + virtual ~VertexList() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + VertexPool* vp = document.getVertexPool(); + if (vp) + { + int vertices = (in.getRecordSize()-4) / 4; + + // Use the Vertex pool as a record stream. + RecordInputStream inVP(vp); + for (int n=0; n g_VertexList(VERTEX_LIST_OP); + + +/** MorphVertexList - + * The MorphVertexList is a leaf record. + */ +class MorphVertexList : public PrimaryRecord +{ + enum Mode + { + UNDEFINED, + MORPH_0, + MORPH_100 + }; + + Mode _mode; + Vertex _vertex0; + Vertex _vertex100; + +public: + + MorphVertexList(): + _mode(UNDEFINED) + { + } + + META_Record(MorphVertexList) + + virtual void addVertex(Vertex& vertex) + { + switch (_mode) + { + case MORPH_0: + _vertex0 = vertex; + break; + case MORPH_100: + _vertex100 = vertex; + + // forward vertex to parent. + if (_parent.valid()) + _parent->addMorphVertex(_vertex0, _vertex100); + break; + } + } + + //virtual void addVertexUV(int layer,const osg::Vec2& uv) + //{ + // // forward uv to parent. + // if (_parent.valid()) + // _parent->addVertexUV(layer,uv); + //} + +protected: + + virtual ~MorphVertexList() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + VertexPool* vp = document.getVertexPool(); + if (vp) + { + int vertices = (in.getRecordSize()-4) / 8; + + // Use the Vertex pool as a record stream. + RecordInputStream inVP(vp); + for (int n=0; n g_MorphVertexList(MORPH_VERTEX_LIST_OP); + +} // end namespace diff --git a/src/osgPlugins/OpenFlight/LightPointRecords.cpp b/src/osgPlugins/OpenFlight/LightPointRecords.cpp new file mode 100644 index 000000000..3916173f3 --- /dev/null +++ b/src/osgPlugins/OpenFlight/LightPointRecords.cpp @@ -0,0 +1,314 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include "Registry.h" +#include "Document.h" +#include "RecordInputStream.h" + +using namespace flt; + +/** LightPoint +*/ +class LightPoint : public PrimaryRecord +{ + enum Directionality + { + OMNIDIRECTIONAL = 0, + UNIDIRECTIONAL = 1, + BIDIRECTIONAL = 2 + }; + + // flags + static const unsigned int NO_BACK_COLOR_BIT = 0x80000000u >> 1; + + int16 _material; + int16 _feature; + osg::Vec4f _backColor; + int32 _displayMode; + float32 _intensityFront; + float32 _intensityBack; + float32 _minDefocus; + float32 _maxDefocus; + int32 _fadeMode; + int32 _fogPunchMode; + int32 _directionalMode; + int32 _rangeMode; + float32 _minPixelSize; + float32 _maxPixelSize; + float32 _actualPixelSize; + float32 _transparentFalloff; + float32 _transparentFalloffExponent; + float32 _transparentFalloffScalar; + float32 _transparentFalloffClamp; + float32 _fog; + float32 _sizeDifferenceThreshold; + int32 _directionality; + float32 _lobeHorizontal; + float32 _lobeVertical; + float32 _lobeRoll; + float32 _falloff; + float32 _ambientIntensity; + float32 _animationPeriod; + float32 _animationPhaseDelay; + float32 _animationPeriodEnable; + float32 _significance; + int32 _drawOrder; + uint32 _flags; + osg::Vec3f _animationAxis; + + osg::ref_ptr _lpn; + +public: + + LightPoint() {} + + META_Record(LightPoint) + + META_setID(_lpn) + META_setComment(_lpn) + META_setMatrix(_lpn) + + // Add lightpoint, add two if bidirectional. + virtual void addVertex(Vertex& vertex) + { + osgSim::LightPoint lp; + lp._position = vertex._coord; + lp._radius = 0.5f * _actualPixelSize; + lp._intensity = _intensityFront; + + // color + lp._color = (vertex.validColor()) ? vertex._color : osg::Vec4(1,1,1,1); + + // sector + bool directional = (_directionality==UNIDIRECTIONAL) || (_directionality==BIDIRECTIONAL); + if (directional && vertex.validNormal()) + { + lp._sector = new osgSim::DirectionalSector( + vertex._normal, + osg::DegreesToRadians(_lobeHorizontal), + osg::DegreesToRadians(_lobeVertical), + osg::DegreesToRadians(_lobeRoll)); + } + + _lpn->addLightPoint(lp); + + // Create a new lightpoint if bi-directional. + if ((_directionality==BIDIRECTIONAL) && vertex.validNormal()) + { + // back intensity + lp._intensity = _intensityBack; + + // back color + if (!(_flags & NO_BACK_COLOR_BIT)) + lp._color = _backColor; + + // back sector + lp._sector = new osgSim::DirectionalSector( + -vertex._normal, + osg::DegreesToRadians(_lobeHorizontal), + osg::DegreesToRadians(_lobeVertical), + osg::DegreesToRadians(_lobeRoll)); + + _lpn->addLightPoint(lp); + } + } + +protected: + + virtual ~LightPoint() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + _material = in.readInt16(); + _feature = in.readInt16(); + _backColor = in.readColor32(); + _displayMode = in.readInt32(); + _intensityFront = in.readFloat32(); + _intensityBack = in.readFloat32(); + _minDefocus = in.readFloat32(); + _maxDefocus = in.readFloat32(); + _fadeMode = in.readInt32(); + _fogPunchMode = in.readInt32(); + _directionalMode = in.readInt32(); + _rangeMode = in.readInt32(); + _minPixelSize = in.readFloat32(); // * document.unitScale(); + _maxPixelSize = in.readFloat32(); // * document.unitScale(); + _actualPixelSize = in.readFloat32(); // * document.unitScale(); + _transparentFalloff = in.readFloat32(); + _transparentFalloffExponent = in.readFloat32(); + _transparentFalloffScalar = in.readFloat32(); + _transparentFalloffClamp = in.readFloat32(); + _fog = in.readFloat32(); + in.forward(4); + _sizeDifferenceThreshold = in.readFloat32(); + _directionality = in.readInt32(); + _lobeHorizontal = in.readFloat32(); + _lobeVertical = in.readFloat32(); + _lobeRoll = in.readFloat32(); + _falloff = in.readFloat32(); + _ambientIntensity = in.readFloat32(); + _animationPeriod = in.readFloat32(); + _animationPhaseDelay = in.readFloat32(); + _animationPeriodEnable = in.readFloat32(); + _significance = in.readFloat32(); + _drawOrder = in.readInt32(); + _flags = in.readUInt32(0); + _animationAxis = in.readVec3f(); + + _lpn = new osgSim::LightPointNode; + _lpn->setName(id); + _lpn->setMinPixelSize(_minPixelSize); + _lpn->setMaxPixelSize(_maxPixelSize); + + // Add to parent + if (_parent.valid()) + _parent->addChild(*_lpn); + } +}; + +RegisterRecordProxy g_LightPoint(LIGHT_POINT_OP); + + +/** IndexedLightPoint +*/ +class IndexedLightPoint : public PrimaryRecord +{ + enum Directionality + { + OMNIDIRECTIONAL = 0, + UNIDIRECTIONAL = 1, + BIDIRECTIONAL = 2 + }; + + // flags + static const unsigned int NO_BACK_COLOR_BIT = 0x80000000u >> 1; + + osg::ref_ptr _lpn; + osg::ref_ptr _appearance; + +public: + + IndexedLightPoint() {} + + META_Record(IndexedLightPoint) + + META_setID(_lpn) + META_setComment(_lpn) + META_setMatrix(_lpn) + + // Add lightpoint, add two if bidirectional. + virtual void addVertex(Vertex& vertex) + { + if (_appearance.valid()) + { + osgSim::LightPoint lp; + lp._position = vertex._coord; + lp._radius = 0.5f * _appearance->actualPixelSize; + lp._intensity = _appearance->intensityFront; + + // color + lp._color = (vertex.validColor()) ? vertex._color : osg::Vec4(1,1,1,1); + + // sector + bool directional = (_appearance->directionality==UNIDIRECTIONAL) || (_appearance->directionality==BIDIRECTIONAL); + if (directional && vertex.validNormal()) + { + lp._sector = new osgSim::DirectionalSector( + vertex._normal, + osg::DegreesToRadians(_appearance->horizontalLobeAngle), + osg::DegreesToRadians(_appearance->verticalLobeAngle), + osg::DegreesToRadians(_appearance->lobeRollAngle)); + } + + _lpn->addLightPoint(lp); + + // Create a new lightpoint if bi-directional. + if ((_appearance->directionality==BIDIRECTIONAL) && vertex.validNormal()) + { + // back intensity + lp._intensity = _appearance->intensityBack; + + // back color + if (!(_appearance->flags & NO_BACK_COLOR_BIT)) + lp._color = _appearance->backColor; + + // back sector + lp._sector = new osgSim::DirectionalSector( + -vertex._normal, + osg::DegreesToRadians(_appearance->horizontalLobeAngle), + osg::DegreesToRadians(_appearance->verticalLobeAngle), + osg::DegreesToRadians(_appearance->lobeRollAngle)); + + _lpn->addLightPoint(lp); + } + } + } + + +protected: + + virtual ~IndexedLightPoint() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + int32 appearanceIndex = in.readInt32(); + int32 animationIndex = in.readInt32(); + int32 drawOrder = in.readInt32(); // for calligraphic lights + + LightPointAppearancePool* lpaPool = document.getOrCreateLightPointAppearancePool(); + _appearance = lpaPool->get(appearanceIndex); + + _lpn = new osgSim::LightPointNode; + _lpn->setName(id); + + if (_appearance.valid()) + { + _lpn->setMinPixelSize(_appearance->minPixelSize); + _lpn->setMaxPixelSize(_appearance->maxPixelSize); + } + + // Add to parent + if (_parent.valid()) + _parent->addChild(*_lpn); + + } +}; + +RegisterRecordProxy g_IndexedLightPoint(INDEXED_LIGHT_POINT_OP); + + +/** LightPointSystem +*/ +class LightPointSystem : public PrimaryRecord +{ +public: + + LightPointSystem() {} + + META_Record(LightPointSystem) + +protected: + + virtual ~LightPointSystem() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + osg::notify(osg::INFO) << "ID: " << id << std::endl; + + osg::Group* group = new osg::Group; + group->setName(id); + + if (_parent.valid()) + _parent->addChild(*group); + } +}; + +RegisterRecordProxy g_LightPointSystem(LIGHT_POINT_SYSTEM_OP); + diff --git a/src/osgPlugins/OpenFlight/PaletteRecords.cpp b/src/osgPlugins/OpenFlight/PaletteRecords.cpp new file mode 100644 index 000000000..11813daed --- /dev/null +++ b/src/osgPlugins/OpenFlight/PaletteRecords.cpp @@ -0,0 +1,635 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include +#include +#include +#include +#include +#include +#include "Registry.h" +#include "Document.h" +#include "AttrData.h" +#include "RecordInputStream.h" + +namespace flt { + +class VertexPalette : public Record +{ +public: + + VertexPalette() {} + + META_Record(VertexPalette) + +protected: + + virtual ~VertexPalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + uint32 paletteSize = in.readUInt32(); + VertexPool* vp = new VertexPool(paletteSize); + in.moveToStartOfRecord(); + in().read(vp->str(),paletteSize); // read beyond record end so use isream::read(). + document.setVertexPool(vp); + in.setEndOfRecord(in.getStartOfRecord()+(std::istream::pos_type)paletteSize); + } +}; + +RegisterRecordProxy g_VertexPalette(VERTEX_PALETTE_OP); + + +class ColorPalette : public Record +{ +public: + + ColorPalette() {} + + META_Record(ColorPalette) + +protected: + + virtual ~ColorPalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + if (document.version() > VERSION_13) + { + bool oldVersion = false; + bool colorNameSection = in.getRecordSize() > 4228; + int maxColors = (document.version()>=VERSION_15_1) ? 1024 : 512; + + // It might be less. + if (!colorNameSection) + { + // Max colors calculated by record size. + int maxColorsByRecordSize = (in.getRecordBodySize()-128) / 4; + if (maxColorsByRecordSize < maxColors) + maxColors = maxColorsByRecordSize; + } + + ColorPool* cp = new ColorPool(oldVersion,maxColors); + document.setColorPool(cp); + + in.forward(128); + for (int i=0; i g_ColorPalette(COLOR_PALETTE_OP); + + +class NameTable : public Record +{ +public: + + NameTable() {} + + META_Record(NameTable) + +protected: + + virtual ~NameTable() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + } +}; + +RegisterRecordProxy g_NameTable(NAME_TABLE_OP); + + +class MaterialPalette : public Record +{ +public: + + MaterialPalette() {} + + META_Record(MaterialPalette) + +protected: + + virtual ~MaterialPalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int32 index = in.readInt32(); + std::string name = in.readString(12); + uint32 flags = in.readUInt32(); + osg::Vec3f ambient = in.readVec3f(); + osg::Vec3f diffuse = in.readVec3f(); + osg::Vec3f specular = in.readVec3f(); + osg::Vec3f emissive = in.readVec3f(); + float32 shininess = in.readFloat32(); + float32 alpha = in.readFloat32(); + + osg::Material* material = new osg::Material; + material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(ambient,alpha)); + material->setDiffuse (osg::Material::FRONT_AND_BACK,osg::Vec4(diffuse,alpha)); + material->setSpecular(osg::Material::FRONT_AND_BACK,osg::Vec4(specular,alpha)); + material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(emissive,alpha)); + material->setShininess(osg::Material::FRONT_AND_BACK,shininess); + + MaterialPool* mp = document.getOrCreateMaterialPool(); + (*mp)[index] = material; + } +}; + +RegisterRecordProxy g_MaterialPalette(MATERIAL_PALETTE_OP); + + +class OldMaterialPalette : public Record +{ +public: + + OldMaterialPalette() {} + + META_Record(OldMaterialPalette) + +protected: + + virtual ~OldMaterialPalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + for (int i=0; i < 64; i++) + { + osg::Vec3f ambient = in.readVec3f(); + osg::Vec3f diffuse = in.readVec3f(); + osg::Vec3f specular = in.readVec3f(); + osg::Vec3f emissive = in.readVec3f(); + float32 shininess = in.readFloat32(); + float32 alpha = in.readFloat32(); + uint32 flags = in.readUInt32(); + std::string name = in.readString(12); + in.forward(4*28); + + osg::Material* material = new osg::Material; + material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(ambient,alpha)); + material->setDiffuse (osg::Material::FRONT_AND_BACK,osg::Vec4(diffuse,alpha)); + material->setSpecular(osg::Material::FRONT_AND_BACK,osg::Vec4(specular,alpha)); + material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(emissive,alpha)); + material->setShininess(osg::Material::FRONT_AND_BACK,shininess); + + MaterialPool* mp = document.getOrCreateMaterialPool(); + (*mp)[i] = material; + } + } + +}; + +RegisterRecordProxy g_OldMaterialPalette(OLD_MATERIAL_PALETTE_OP); + + +class TexturePalette : public Record +{ +public: + + TexturePalette() {} + + META_Record(TexturePalette) + +protected: + + virtual ~TexturePalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int maxLength = (document.version() < VERSION_14) ? 80 : 200; + std::string filename = in.readString(maxLength); + int32 index = in.readInt32(-1); + int32 x = in.readInt32(); + int32 y = in.readInt32(); + + osg::ref_ptr image = osgDB::readImageFile(filename,document.getOptions()); + if (!image.valid()) + { + osg::notify(osg::WARN) << "Can't find texture (" << index << ") " << filename << std::endl; + return; + } + + // Create stateset + osg::ref_ptr stateset = new osg::StateSet; + + osg::Texture2D* texture = new osg::Texture2D; + texture->setResizeNonPowerOfTwoHint(true); + texture->setImage(image.get()); + stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); + + // Blend mode moved to Face. + //if (image->isImageTranslucent()) + //{ + // stateset->setAttributeAndModes(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA),osg::StateAttribute::ON); + // stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + //} + + // Read attribute file + std::string attrname = filename + ".attr"; + osg::ref_ptr attr = dynamic_cast(osgDB::readObjectFile(attrname,document.getOptions())); + if (attr.valid()) + { + // Wrap mode + osg::Texture2D::WrapMode wrap_s = (attr->wrapMode_u==AttrData::WRAP_CLAMP) ? osg::Texture2D::CLAMP : osg::Texture2D::REPEAT; + texture->setWrap(osg::Texture2D::WRAP_S,wrap_s); + + osg::Texture2D::WrapMode wrap_t = (attr->wrapMode_v==AttrData::WRAP_CLAMP) ? osg::Texture2D::CLAMP : osg::Texture2D::REPEAT; + texture->setWrap(osg::Texture2D::WRAP_T,wrap_t); + + // Min filter + switch (attr->minFilterMode) + { + case AttrData::MIN_FILTER_POINT: + texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST); + break; + case AttrData::MIN_FILTER_BILINEAR: + texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR); + break; + case AttrData::MIN_FILTER_MIPMAP_POINT: + texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST_MIPMAP_NEAREST); + break; + case AttrData::MIN_FILTER_MIPMAP_LINEAR: + texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST_MIPMAP_LINEAR); + break; + case AttrData::MIN_FILTER_MIPMAP_BILINEAR: + texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST); + break; + case AttrData::MIN_FILTER_MIPMAP_TRILINEAR: + texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR); + break; + case AttrData::MIN_FILTER_BICUBIC: + case AttrData::MIN_FILTER_BILINEAR_GEQUAL: + case AttrData::MIN_FILTER_BILINEAR_LEQUAL: + case AttrData::MIN_FILTER_BICUBIC_GEQUAL: + case AttrData::MIN_FILTER_BICUBIC_LEQUAL: + texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST); + break; + default: + texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR); + break; + } + + // Mag filter + switch (attr->magFilterMode) + { + case AttrData::MAG_FILTER_POINT: + texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST); + break; + case AttrData::MAG_FILTER_BILINEAR: + case AttrData::MAG_FILTER_BILINEAR_GEQUAL: + case AttrData::MAG_FILTER_BILINEAR_LEQUAL: + case AttrData::MAG_FILTER_SHARPEN: + case AttrData::MAG_FILTER_BICUBIC: + case AttrData::MAG_FILTER_BICUBIC_GEQUAL: + case AttrData::MAG_FILTER_BICUBIC_LEQUAL: + case AttrData::MAG_FILTER_ADD_DETAIL: + case AttrData::MAG_FILTER_MODULATE_DETAIL: + texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR); + break; + } + + osg::TexEnv* texenv = new osg::TexEnv; + switch (attr->texEnvMode) + { + case AttrData::TEXENV_MODULATE: + texenv->setMode(osg::TexEnv::MODULATE); + break; + case AttrData::TEXENV_BLEND: + texenv->setMode(osg::TexEnv::BLEND); + break; + case AttrData::TEXENV_DECAL: + texenv->setMode(osg::TexEnv::DECAL); + break; + case AttrData::TEXENV_COLOR: + texenv->setMode(osg::TexEnv::REPLACE); + break; + } + stateset->setTextureAttribute(0, texenv); + } + + TexturePool* tp = document.getOrCreateTexturePool(); + (*tp)[index] = stateset.get(); + } +}; + +RegisterRecordProxy g_TexturePalette(TEXTURE_PALETTE_OP); + + +class EyepointAndTrackplanePalette : public Record +{ +public: + + EyepointAndTrackplanePalette() {} + + META_Record(EyepointAndTrackplanePalette) + +protected: + + virtual ~EyepointAndTrackplanePalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) {} +}; + +RegisterRecordProxy g_EyepointAndTrackplanePalette(EYEPOINT_AND_TRACKPLANE_PALETTE_OP); + + +class LinkagePalette : public Record +{ +public: + + LinkagePalette() {} + + META_Record(LinkagePalette) + +protected: + + virtual ~LinkagePalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) {} +}; + +RegisterRecordProxy g_LinkagePalette(LINKAGE_PALETTE_OP); + + +class SoundPalette : public Record +{ +public: + + SoundPalette() {} + + META_Record(SoundPalette) + +protected: + + virtual ~SoundPalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) {} +}; + +RegisterRecordProxy g_SoundPalette(SOUND_PALETTE_OP); + + +class LightSourcePalette : public Record +{ +public: + + LightSourcePalette() {} + + META_Record(LightSourcePalette) + +protected: + + virtual ~LightSourcePalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) {} +}; + +RegisterRecordProxy g_LightSourcePalette(LIGHT_SOURCE_PALETTE_OP); + + +class LightPointAppearancePalette : public Record +{ +public: + + LightPointAppearancePalette() {} + + META_Record(LightPointAppearancePalette) + +protected: + + virtual ~LightPointAppearancePalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + osg::ref_ptr appearance = new LPAppearance; + + in.forward(4); + appearance->name = in.readString(256); + appearance->index = in.readInt32(-1); + appearance->materialCode = in.readInt16(); + appearance->featureID = in.readInt16(); + appearance->backColor = in.readColor32(); + appearance->displayMode = in.readInt32(); + appearance->intensityFront = in.readFloat32(); + appearance->intensityBack = in.readFloat32(); + appearance->minDefocus = in.readFloat32(); + appearance->maxDefocus = in.readFloat32(); + appearance->fadingMode = in.readInt32(); + appearance->fogPunchMode = in.readInt32(); + appearance->directionalMode = in.readInt32(); + appearance->rangeMode = in.readInt32(); + appearance->minPixelSize = in.readFloat32(); + appearance->maxPixelSize = in.readFloat32(); + appearance->actualPixelSize = in.readFloat32(); + appearance->transparentFalloffPixelSize = in.readFloat32(); + appearance->transparentFalloffExponent = in.readFloat32(); + appearance->transparentFalloffScalar = in.readFloat32(); + appearance->transparentFalloffClamp = in.readFloat32(); + appearance->fogScalar = in.readFloat32(); + appearance->fogIntensity = in.readFloat32(); + appearance->sizeDifferenceThreshold = in.readFloat32(); + appearance->directionality = in.readInt32(); + appearance->horizontalLobeAngle = in.readFloat32(); + appearance->verticalLobeAngle = in.readFloat32(); + appearance->lobeRollAngle = in.readFloat32(); + appearance->directionalFalloffExponent = in.readFloat32(); + appearance->directionalAmbientIntensity = in.readFloat32(); + appearance->significance = in.readFloat32(); + appearance->flags = in.readUInt32(); + appearance->visibilityRange = in.readFloat32(); + appearance->fadeRangeRatio = in.readFloat32(); + appearance->fadeInDuration = in.readFloat32(); + appearance->fadeOutDuration = in.readFloat32(); + appearance->LODRangeRatio = in.readFloat32(); + appearance->LODScale = in.readFloat32(); + appearance->texturePatternIndex = in.readInt32(-1); + + // Add to pool + LightPointAppearancePool* lpaPool = document.getOrCreateLightPointAppearancePool(); + (*lpaPool)[appearance->index] = appearance.get(); + } + +}; + +RegisterRecordProxy g_LightPointAppearancePalette(LIGHT_POINT_APPEARANCE_PALETTE_OP); + + +class LightPointAnimationPalette : public Record +{ +public: + + LightPointAnimationPalette() {} + + META_Record(LightPointAnimationPalette) + +protected: + + virtual ~LightPointAnimationPalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + in.forward(4); + std::string name = in.readString(256); + int32 index = in.readInt32(-1); + float32 animationPeriod = in.readFloat32(); + float32 animationPhaseDelay = in.readFloat32(); + float32 animationEnabledPeriod = in.readFloat32(); + osg::Vec3f axisOfRotation = in.readVec3f(); + uint32 flags = in.readUInt32(); + int32 animationType = in.readInt32(); + int32 morseCodeTiming = in.readInt32(); + int32 wordRate = in.readInt32(); + int32 characterRate = in.readInt32(); + std::string morseCodeString = in.readString(1024); + int32 numberOfSequences = in.readInt32(); + for (int n=0; n g_LightPointAnimationPalette(LIGHT_POINT_ANIMATION_PALETTE_OP); + + +class LineStylePalette : public Record +{ +public: + + LineStylePalette() {} + + META_Record(LineStylePalette) + +protected: + + virtual ~LineStylePalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + } +}; + +RegisterRecordProxy g_LineStylePalette(LINE_STYLE_PALETTE_OP); + + +class TextureMappingPalette : public Record +{ +public: + + TextureMappingPalette() {} + + META_Record(TextureMappingPalette) + +protected: + + virtual ~TextureMappingPalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + } +}; + +RegisterRecordProxy g_TextureMappingPalette(TEXTURE_MAPPING_PALETTE_OP); + + +class ShaderPalette : public Record +{ +public: + + ShaderPalette() {} + + META_Record(ShaderPalette) + + enum ShaderType + { + CG=0, + CGFX=1, + GLSL=2 + }; + +protected: + + virtual ~ShaderPalette() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int32 index = in.readInt32(); + int32 type = in.readInt32(); + std::string name = in.readString(1024); + std::string vertexProgramFilename = in.readString(1024); + std::string fragmentProgramFilename = in.readString(1024); + + if (type == GLSL) + { + osg::Program* program = new osg::Program; + program->setName(name); + + std::string vertexProgramFilePath = osgDB::findDataFile(vertexProgramFilename); + if (!vertexProgramFilePath.empty()) + { + osg::Shader* vertexShader = osg::Shader::readShaderFile(osg::Shader::VERTEX, vertexProgramFilePath); + if (vertexShader) + program->addShader( vertexShader ); + } + + std::string fragmentProgramFilePath = osgDB::findDataFile(fragmentProgramFilename); + if (!fragmentProgramFilePath.empty()) + { + osg::Shader* fragmentShader = osg::Shader::readShaderFile(osg::Shader::FRAGMENT, fragmentProgramFilePath); + if (fragmentShader) + program->addShader( fragmentShader ); + } + + ShaderPool* shaderPool = document.getOrCreateShaderPool(); + (*shaderPool)[index] = program; + } + } +}; + +RegisterRecordProxy g_ShaderPalette(SHADER_PALETTE_OP); + +} // end namespace + + diff --git a/src/osgPlugins/OpenFlight/Pools.cpp b/src/osgPlugins/OpenFlight/Pools.cpp new file mode 100644 index 000000000..f44184234 --- /dev/null +++ b/src/osgPlugins/OpenFlight/Pools.cpp @@ -0,0 +1,121 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include "Pools.h" +#include "Document.h" + +using namespace flt; + + +osg::Vec4 ColorPool::getColor(int indexIntensity) const +{ + if (_old) // version <= 13 + { + // bit 0-6: intensity + // bit 7-11 color index + // bit 12 fixed intensity bit + bool fixedIntensity = (indexIntensity & 0x1000) ? true : false; + unsigned int index = (fixedIntensity) ? (indexIntensity & 0x0fff)+(4096>>7) : indexIntensity >> 7; + assert(index>=0 && index 13 + { + // bit 0-6: intensity + // bit 7-15 color index + int index = indexIntensity >> 7; + + if (index<0 || index>=(int)size()) + { + // color index not available. + return osg::Vec4(1,1,1,1); + } + + osg::Vec4 col = at(index); + float intensity = (float)(indexIntensity & 0x7f)/127.f; + col[0] *= intensity; + col[1] *= intensity; + col[2] *= intensity; + return col; + } +} + + +MaterialPool::MaterialPool() +{ + // Default material. + // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000228.html + _defaultMaterial = new osg::Material; + _defaultMaterial->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(1,1,1,1)); + _defaultMaterial->setDiffuse (osg::Material::FRONT_AND_BACK,osg::Vec4(1,1,1,1)); + _defaultMaterial->setSpecular(osg::Material::FRONT_AND_BACK,osg::Vec4(0,0,0,1)); + _defaultMaterial->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0,0,0,1)); + _defaultMaterial->setShininess(osg::Material::FRONT_AND_BACK,0); +} + + + +osg::Material* MaterialPool::get(int index) +{ + iterator itr = find(index); + if (itr != end()) + return (*itr).second.get(); + + // Use default material if not found in material palette. + return _defaultMaterial.get(); +} + + +namespace { + + osg::Vec4 finalColor(const osg::Vec4& materialColor, const osg::Vec4& faceColor) + { + return osg::Vec4( + materialColor.r() * faceColor.r(), + materialColor.g() * faceColor.g(), + materialColor.b() * faceColor.b(), + materialColor.a() * faceColor.a()); + } + +} // end namespace + +osg::Material* MaterialPool::getOrCreateMaterial(int index, const osg::Vec4& faceColor) +{ + MaterialParameters materialParam(index,faceColor); + + // Look for final material. + FinalMaterialMap::iterator itr = _finalMaterialMap.find(materialParam); + if (itr != _finalMaterialMap.end()) + { + // Final material found. + return (*itr).second.get(); + } + + osg::Material* poolMaterial = get(index); + + // Create final material. + osg::Material* material = dynamic_cast(poolMaterial->clone(osg::CopyOp::SHALLOW_COPY)); + osg::Vec4 materialPaletteAmbient = poolMaterial->getAmbient(osg::Material::FRONT); + osg::Vec4 materialPaletteDiffuse = poolMaterial->getDiffuse(osg::Material::FRONT); + + material->setAmbient(osg::Material::FRONT_AND_BACK, finalColor(materialPaletteAmbient, faceColor)); + material->setDiffuse(osg::Material::FRONT_AND_BACK, finalColor(materialPaletteDiffuse, faceColor)); + material->setAlpha(osg::Material::FRONT_AND_BACK, materialPaletteAmbient.a()*faceColor.a()); + + // Set final material so it can be reused. + _finalMaterialMap[materialParam] = material; + + return material; +} diff --git a/src/osgPlugins/OpenFlight/Pools.h b/src/osgPlugins/OpenFlight/Pools.h new file mode 100644 index 000000000..3a24fed3b --- /dev/null +++ b/src/osgPlugins/OpenFlight/Pools.h @@ -0,0 +1,214 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_POOLS_H +#define FLT_POOLS_H 1 + +#include +#include + +// need to replace this... and associated istrstream as its deprecated +#include + +#include +#include +#include +#include +#include "types.h" + + +namespace flt { + +class VertexPool : public osg::Referenced, public std::istrstream +{ + const char* _buffer; + +public: + + explicit VertexPool(std::streamsize count) : + std::istrstream(_buffer=new char[count],count) {} + +protected: + + virtual ~VertexPool() + { + if (_buffer) delete [] _buffer; + } +}; + + +class ColorPool : public osg::Referenced , public std::vector +{ +public: + + explicit ColorPool(bool old,int size) : + std::vector(size), + _old(old) {} + + osg::Vec4 getColor(int indexIntensity) const; + +protected: + + virtual ~ColorPool() {} + + bool _old; // true if version <= 13 +}; + + +class TexturePool : public osg::Referenced , public std::map > +{ +public: + + TexturePool() {} + + osg::StateSet* get(int index) + { + iterator itr = find(index); + if (itr != end()) + return (*itr).second.get(); + return NULL; + } + +protected: + + virtual ~TexturePool() {} + +}; + + +class MaterialPool : public osg::Referenced , public std::map > +{ +public: + + MaterialPool(); + + // Get material, return default material if not found in palette. + osg::Material* get(int index); + + // Get or create material based on + // index: face material index + // color: face color with alpha set to 1-face transparency. + osg::Material* getOrCreateMaterial(int index, const osg::Vec4& faceColor); + +protected: + + virtual ~MaterialPool() {} + + osg::ref_ptr _defaultMaterial; + + struct MaterialParameters + { + int index; // face index to material pool + osg::Vec4 color; // face color with alpha set to 1-face transparency. + + MaterialParameters(): + index(-1) {} + + MaterialParameters(int i, const osg::Vec4& c): + index(i), + color(c) {} + + bool operator < (const MaterialParameters& rhs) const + { + if (index < rhs.index) return true; + else if (index > rhs.index) return false; + else return (color < rhs.color); + } + }; + + // Material from palette combined with face color stored here for reuse. + typedef std::map > FinalMaterialMap; + FinalMaterialMap _finalMaterialMap; +}; + + +struct LPAppearance : public osg::Referenced +{ + std::string name; + int32 index; + int16 materialCode; + int16 featureID; + osg::Vec4f backColor; + int32 displayMode; + float32 intensityFront; + float32 intensityBack; + float32 minDefocus; + float32 maxDefocus; + int32 fadingMode; + int32 fogPunchMode; + int32 directionalMode; + int32 rangeMode; + float32 minPixelSize; + float32 maxPixelSize; + float32 actualPixelSize; + float32 transparentFalloffPixelSize; + float32 transparentFalloffExponent; + float32 transparentFalloffScalar; + float32 transparentFalloffClamp; + float32 fogScalar; + float32 fogIntensity; + float32 sizeDifferenceThreshold; + int32 directionality; + float32 horizontalLobeAngle; + float32 verticalLobeAngle; + float32 lobeRollAngle; + float32 directionalFalloffExponent; + float32 directionalAmbientIntensity; + float32 significance; + uint32 flags; + float32 visibilityRange; + float32 fadeRangeRatio; + float32 fadeInDuration; + float32 fadeOutDuration; + float32 LODRangeRatio; + float32 LODScale; + int32 texturePatternIndex; +}; + + +class LightPointAppearancePool : public osg::Referenced , public std::map > +{ +public: + + LightPointAppearancePool() {} + + LPAppearance* get(int index) + { + iterator itr = find(index); + if (itr != end()) + return (*itr).second.get(); + return NULL; + } + +protected: + + virtual ~LightPointAppearancePool() {} + +}; + + +class ShaderPool : public osg::Referenced , public std::map > +{ +public: + + ShaderPool() {} + + osg::Program* get(int index) + { + iterator itr = find(index); + if (itr != end()) + return (*itr).second.get(); + return NULL; + } + +protected: + + virtual ~ShaderPool() {} +}; + +} // end namespace + +#endif diff --git a/src/osgPlugins/OpenFlight/PrimaryRecords.cpp b/src/osgPlugins/OpenFlight/PrimaryRecords.cpp new file mode 100644 index 000000000..a1dc76eff --- /dev/null +++ b/src/osgPlugins/OpenFlight/PrimaryRecords.cpp @@ -0,0 +1,747 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Registry.h" +#include "Document.h" +#include "RecordInputStream.h" + +namespace flt { + +/** Header +*/ +class Header : public PrimaryRecord +{ + static const unsigned int SAVE_VERTEX_NORMALS_BIT = 0x80000000u >> 0; + static const unsigned int PACKED_COLOR_MODE_BIT = 0x80000000u >> 1; + static const unsigned int CAD_VIEW_MODE_BIT = 0x80000000u >> 2; + + osg::ref_ptr _header; + +public: + + Header() {} + + META_Record(Header) + + META_setID(_header) + META_setComment(_header) +// META_setMatrix(_header) + META_setMultitexture(_header) + META_addChild(_header) + +protected: + + virtual ~Header() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + osg::notify(osg::DEBUG_INFO) << "ID: " << id << std::endl; + + uint32 format = in.readUInt32(); + osg::notify(osg::DEBUG_INFO) << "Format: " << format << std::endl; + document._version = format; + + uint32 revision = in.readUInt32(); + + std::string revisionTime = in.readString(32); + osg::notify(osg::INFO) << "Last revision: " << revisionTime << std::endl; + + in.forward(4*2); + + // Flight v.11 & 12 use integer coordinates + int16 multDivUnits = in.readInt16(); // Units multiplier/divisor + uint8 units = in.readUInt8(); // 0=Meters 1=Kilometers 4=Feet 5=Inches 8=Nautical miles + uint8 textureWhite = in.readUInt8(); + uint32 flags = in.readUInt32(); + + if (document.getDoUnitsConversion()) + document._unitScale = unitsToMeters((CoordUnits)units) / unitsToMeters(document.getDesiredUnits()); + + if (document._version < VERSION_13) + { + if (multDivUnits >= 0) + document._unitScale *= (double)multDivUnits; + else + document._unitScale /= (double)(-multDivUnits); + } + + _header = new osg::Group; + _header->setName(id); + + document.setHeaderNode(_header.get()); + } + +}; + +RegisterRecordProxy
g_Header(HEADER_OP); + + +/** Object +*/ +class Object : public PrimaryRecord +{ + static const unsigned int HIDE_IN_DAYLIGHT = 0x80000000u >> 0; + static const unsigned int HIDE_AT_DUSK = 0x80000000u >> 1; + static const unsigned int HIDE_AT_NIGHT = 0x80000000u >> 2; + static const unsigned int NO_ILLUMINATION = 0x80000000u >> 3; + static const unsigned int FLAT_SHADED = 0x80000000u >> 4; + static const unsigned int SHADOW_OBJECT = 0x80000000u >> 5; + + osg::ref_ptr _object; + +public: + + Object() {} + + META_Record(Object) + + META_setID(_object) + META_setComment(_object) + META_setMatrix(_object) + META_setMultitexture(_object) + META_addChild(_object) + +protected: + + virtual ~Object() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + uint32 flags = in.readUInt32(); + + _object = new osg::Group; + _object->setName(id); + + // Flat shaded? + if (flags & FLAT_SHADED) + { + osg::ShadeModel* shademodel = new osg::ShadeModel; + shademodel->setMode(osg::ShadeModel::FLAT); + _object->getOrCreateStateSet()->setAttribute(shademodel); + } + + if (_parent.valid()) + _parent->addChild(*_object); + } +}; + +RegisterRecordProxy g_Object(OBJECT_OP); + + +/** Group +*/ +class Group : public PrimaryRecord +{ + static const unsigned int FORWARD_ANIM = 0x80000000u >> 1; + static const unsigned int SWING_ANIM = 0x80000000u >> 2; + static const unsigned int BOUND_BOX_FOLLOW = 0x80000000u >> 3; + static const unsigned int FREEZE_BOUND_BOX = 0x80000000u >> 4; + static const unsigned int DEFAULT_PARENT = 0x80000000u >> 5; + static const unsigned int BACKWARD_ANIM = 0x80000000u >> 6; + + osg::ref_ptr _group; + +public: + + Group() {} + + META_Record(Group) + + META_setID(_group) + META_setComment(_group) + META_setMatrix(_group) + META_setMultitexture(_group) + META_addChild(_group) + +protected: + + virtual ~Group() {} + + void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + osg::notify(osg::DEBUG_INFO) << "ID: " << id << std::endl; + + int16 relativePriority = in.readInt16(); + in.forward(2); + uint32 flags = in.readUInt32(); + uint16 specialId0 = in.readUInt16(); + uint16 specialId1 = in.readUInt16(); + uint16 significance = in.readUInt16(); + int8 layer = in.readInt8(); + in.forward(5); + uint32 loopCount = in.readUInt32(); + float32 loopDuration = in.readFloat32(); + float32 lastFrameDuration = in.readFloat32(); + + // Check for forward animation (sequence) + bool forwardAnim = (flags & FORWARD_ANIM) != 0; + + // For versions prior to 15.8, the swing bit can be set independently + // of the animation bit. This implies forward animation (with swing) + if ((document.version() < VERSION_15_8) && (flags & SWING_ANIM)) + forwardAnim = true; + + // OpenFlight 15.8 adds backwards animations + const bool backwardAnim = ( (document.version() >= VERSION_15_8) && + ((flags & BACKWARD_ANIM) != 0) ); + + if (forwardAnim || backwardAnim) + { + osg::ref_ptr sequence = new osg::Sequence; + + // Regardless of forwards or backwards, animation could have swing bit set + const osg::Sequence::LoopMode loopMode = ((flags & SWING_ANIM) == 0) ? + osg::Sequence::LOOP : osg::Sequence::SWING; + + if (forwardAnim) + sequence->setInterval(loopMode, 0, -1); + else + sequence->setInterval(loopMode, -1, 0); + + float speed=0.1f; + sequence->setDuration(speed); + sequence->setMode(osg::Sequence::START); + + _group = sequence.get(); + } + else + { + _group = new osg::Group; + } + + _group->setName(id); + + // Add this implementation to parent implementation. + if (_parent.valid()) + _parent->addChild(*_group); + } + +}; + +RegisterRecordProxy g_Group(GROUP_OP); + + +/** DegreeOfFreedom +*/ +class DegreeOfFreedom : public PrimaryRecord +{ + // Flags + static const unsigned long LIMIT_TRANSLATION_X = 0x80000000u >> 0; + static const unsigned long LIMIT_TRANSLATION_Y = 0x80000000u >> 1; + static const unsigned long LIMIT_TRANSLATION_Z = 0x80000000u >> 2; + static const unsigned long LIMIT_PITCH = 0x80000000u >> 3; + static const unsigned long LIMIT_ROLL = 0x80000000u >> 4; + static const unsigned long LIMIT_YAW = 0x80000000u >> 5; + static const unsigned long LIMIT_SCALE_X = 0x80000000u >> 6; + static const unsigned long LIMIT_SCALE_Y = 0x80000000u >> 7; + static const unsigned long LIMIT_SCALE_Z = 0x80000000u >> 8; + + struct Range + { + float64 min; // Minimum value with respect to the local coord system + float64 max; // Maximum value with respect to the local coordsystem + float64 current; // Current value with respect to the local coord system + float64 increment; // Increment + }; + + osg::ref_ptr _dof; + +public: + + DegreeOfFreedom(): + _dof(new osgSim::DOFTransform) {} + + META_Record(DegreeOfFreedom) + + META_setID(_dof) + META_setComment(_dof) + META_setMatrix(_dof) + META_setMultitexture(_dof) + META_addChild(_dof) + +protected: + + virtual ~DegreeOfFreedom() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + in.forward(4); // Reserved + osg::Vec3d localOrigin = in.readVec3d(); + osg::Vec3d pointOnXAxis = in.readVec3d(); + osg::Vec3d pointInXYPlane = in.readVec3d(); + Range rangeZ = readRange(in); // Legal z values with respect to the local coord system + Range rangeY = readRange(in); // Legal y values with respect to the local coord system + Range rangeX = readRange(in); // Legal x values with respect to the local coord system + Range rangePitch = readRange(in); // Legal pitch values (rotation about the x-axis) + Range rangeRoll = readRange(in); // Legal roll values( rotation about the y-axis) + Range rangeYaw = readRange(in); // Legal yaw values (rotation about the z-axis) + Range rangeScaleZ = readRange(in); // Legal z scale values (about local origin) + Range rangeScaleY = readRange(in); // Legal y scale values about local origin) + Range rangeScaleX = readRange(in); // Legal x scale values (about local origin) + uint32 flags = in.readUInt32(); // Flags, bits from left to right (see OF doc) + + // out of range check, required for racecar.flt (Creator Gallery) + if (!valid(localOrigin)) + localOrigin = osg::Vec3d(0,0,0); + if (!valid(pointOnXAxis)) + pointOnXAxis = osg::X_AXIS; + if (!valid(pointInXYPlane)) + pointInXYPlane = osg::Y_AXIS; + + _dof->setName(id); + + //tranlsations: + _dof->setMinTranslate(osg::Vec3(rangeX.min,rangeY.min,rangeZ.min)*document.unitScale()); + _dof->setMaxTranslate(osg::Vec3(rangeX.max,rangeY.max,rangeZ.max)*document.unitScale()); + _dof->setCurrentTranslate(osg::Vec3(rangeX.current,rangeY.current,rangeZ.current)*document.unitScale()); + _dof->setIncrementTranslate(osg::Vec3(rangeX.increment,rangeY.increment,rangeZ.increment)*document.unitScale()); + + //rotations: + _dof->setMinHPR(osg::Vec3(osg::inDegrees(rangeYaw.min),osg::inDegrees(rangePitch.min),osg::inDegrees(rangeRoll.min))); + _dof->setMaxHPR(osg::Vec3(osg::inDegrees(rangeYaw.max),osg::inDegrees(rangePitch.max),osg::inDegrees(rangeRoll.max))); + _dof->setCurrentHPR(osg::Vec3(osg::inDegrees(rangeYaw.current),osg::inDegrees(rangePitch.current),osg::inDegrees(rangeRoll.current))); + _dof->setIncrementHPR(osg::Vec3(osg::inDegrees(rangeYaw.increment),osg::inDegrees(rangePitch.increment),osg::inDegrees(rangeRoll.increment))); + + //scales: + _dof->setMinScale(osg::Vec3(rangeScaleX.min,rangeScaleY.min,rangeScaleZ.min)); + _dof->setMaxScale(osg::Vec3(rangeScaleX.max,rangeScaleY.max,rangeScaleZ.max)); + _dof->setCurrentScale(osg::Vec3(rangeScaleX.current,rangeScaleY.current,rangeScaleZ.current)); + _dof->setIncrementScale(osg::Vec3(rangeScaleX.increment,rangeScaleY.increment,rangeScaleZ.increment)); + + // compute axis. + osg::Vec3 xAxis = pointOnXAxis - localOrigin; + osg::Vec3 xyPlaneVector = pointInXYPlane - localOrigin; + osg::Vec3 zAxis = xAxis ^ xyPlaneVector; + osg::Vec3 yAxis = zAxis ^ xAxis; + + // normalize + xAxis.normalize(); + yAxis.normalize(); + zAxis.normalize(); + + // scale origin + osg::Vec3 origin = localOrigin * document.unitScale(); + + // create putmatrix + osg::Matrix inv_putmat(xAxis.x(), xAxis.y(), xAxis.z(), 0.0, + yAxis.x(), yAxis.y(), yAxis.z(), 0.0, + zAxis.x(), zAxis.y(), zAxis.z(), 0.0, + origin.x(), origin.y(), origin.z(), 1.0); + + _dof->setInversePutMatrix(inv_putmat); + _dof->setPutMatrix(osg::Matrix::inverse(inv_putmat)); + + _dof->setLimitationFlags(flags); + _dof->setAnimationOn(document.getDefaultDOFAnimationState()); +// _dof->setHPRMultOrder(osgSim::DOFTransform::HPR); + + // Add this implementation to parent implementation. + if (_parent.valid()) + _parent->addChild(*_dof); + } + + Range readRange(RecordInputStream& in) const + { + Range range; + range.min = in.readFloat64(); + range.max = in.readFloat64(); + range.current = in.readFloat64(); + range.increment = in.readFloat64(); + + // Extend valid range (See Creator help on DOF). + if (range.current < range.min) range.min = range.current; + if (range.current > range.max) range.max = range.current; + + const float64 epsilon = 1.0e-7; + if (fabs(range.max-range.min) < epsilon) + range.increment = 0; + + return range; + } + + bool valid(const osg::Vec3d& v) const + { + const osg::Vec3d bad(-1.0e8,-1.0e8,-1.0e8); + const float64 epsilon = 1.0e-7; + + return (fabs(v.x()-bad.x()) > epsilon) || + (fabs(v.y()-bad.y()) > epsilon) || + (fabs(v.z()-bad.z()) > epsilon); + } +}; + +RegisterRecordProxy g_DegreeOfFreedom(DOF_OP); + + +/** LevelOfDetail - To recreate the LevelOfDetail record in OSG we have to create a LOD node with one Group node under it. + * OSG representation Children of the LevelOfDetail record will be added to +*/ +class LevelOfDetail : public PrimaryRecord +{ + osg::ref_ptr _lod; + osg::ref_ptr _impChild0; + +public: + + LevelOfDetail() {} + + META_Record(LevelOfDetail) + + META_setID(_lod) + META_setComment(_lod) + META_setMatrix(_lod) + META_setMultitexture(_lod) + META_addChild(_impChild0) + +protected: + + virtual ~LevelOfDetail() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + in.forward(4); + float64 switchInDistance = in.readFloat64(); + float64 switchOutDistance = in.readFloat64(); + int16 specialEffectID1 = in.readInt16(); + int16 specialEffectID2 = in.readInt16(); + uint32 flags = in.readUInt32(); + osg::Vec3d center = in.readVec3d(); + + _lod = new osg::LOD; + _lod->setName(id); + _lod->setCenter(center*document.unitScale()); + + _impChild0 = new osg::Group; + _impChild0->setName("LOD child0"); + + // Add child to lod. + _lod->addChild(_impChild0.get(), + (float)switchOutDistance * document.unitScale(), + (float)switchInDistance * document.unitScale()); + + // Add this implementation to parent implementation. + if (_parent.valid()) + _parent->addChild(*_lod); + } + +}; + +RegisterRecordProxy g_LevelOfDetail(LOD_OP); + + +/** OldLevelOfDetail + */ +class OldLevelOfDetail : public PrimaryRecord +{ + osg::ref_ptr _lod; + osg::ref_ptr _impChild0; + +public: + + OldLevelOfDetail() {} + + META_Record(OldLevelOfDetail) + + META_setID(_lod) + META_setComment(_lod) + META_setMatrix(_lod) + META_setMultitexture(_lod) + META_addChild(_impChild0) + +protected: + + virtual ~OldLevelOfDetail() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + uint32 switchInDistance = in.readUInt32(); + uint32 switchOutDistance = in.readUInt32(); + int16 specialEffectID1 = in.readInt16(); + int16 specialEffectID2 = in.readInt16(); + uint32 flags = in.readUInt32(); + + osg::Vec3 center; + center.x() = (float)in.readInt32(); + center.y() = (float)in.readInt32(); + center.z() = (float)in.readInt32(); + + _lod = new osg::LOD; + _lod->setName(id); + _lod->setCenter(center*document.unitScale()); + _lod->setRange(0, (float)switchOutDistance * document.unitScale(), + (float)switchInDistance * document.unitScale()); + + // Add child to lod. + _impChild0 = new osg::Group; + _lod->addChild(_impChild0.get()); + + // Add this implementation to parent implementation. + if (_parent.valid()) + _parent->addChild(*_lod); + } + +}; + +RegisterRecordProxy g_OldLevelOfDetail(OLD_LOD_OP); + + +/** Switch +*/ +class Switch : public PrimaryRecord +{ + uint32 _currentMask; + uint32 _numberOfMasks; + uint32 _wordsInMask; + std::vector _masks; + + osg::ref_ptr _multiSwitch; + +public: + + Switch() {} + + META_Record(Switch) + + META_setID(_multiSwitch) + META_setComment(_multiSwitch) + META_setMatrix(_multiSwitch) + META_setMultitexture(_multiSwitch) + + virtual void addChild(osg::Node& child) + { + if (_multiSwitch.valid()) + { + unsigned int nChild = _multiSwitch->getNumChildren(); + for (unsigned int nMask=0; nMask<_numberOfMasks; ++nMask) + { + // test if this child is active in the current mask (itMask) + unsigned int nMaskBit = nChild % 32; + unsigned int nMaskWord = nMask * _wordsInMask + nChild / 32; + _multiSwitch->setValue(nMask, nChild, (_masks[nMaskWord] & (uint32(1) << nMaskBit))!=0 ); + } + + _multiSwitch->addChild(&child); + } + } + +protected: + + virtual ~Switch() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + in.forward(4); + _currentMask = in.readUInt32(); + _numberOfMasks = in.readUInt32(); + _wordsInMask = in.readUInt32(); + + _multiSwitch = new osgSim::MultiSwitch; + _multiSwitch->setName(id); + + /* Example: + | word #0 || word #1 || word #2 | <- Mask #0 + | word #0 || word #1 || word #2 | <- Mask #1 + In this example numberOfMasks=2 and wordsInMask=3, currentMask can be 0 or 1. + */ + + for (unsigned int n=0; n<_numberOfMasks*_wordsInMask; n++) + { + uint32 maskWord = in.readUInt32(); + _masks.push_back(maskWord); + } + + _multiSwitch->setActiveSwitchSet(_currentMask); + + // Add this implementation to parent implementation. + if (_parent.valid()) + _parent->addChild(*_multiSwitch); + } +}; + +RegisterRecordProxy g_Switch(SWITCH_OP); + + +/** ExternalReference +*/ +class ExternalReference : public PrimaryRecord +{ + osg::ref_ptr _external; + +public: + + ExternalReference() {} + + META_Record(ExternalReference) + + META_setID(_external) + META_setComment(_external) + META_setMatrix(_external) + META_setMultitexture(_external) + META_addChild(_external) + +protected: + + virtual ~ExternalReference() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string strFile = in.readString(200); + + //Path for Nested external references + const osgDB::ReaderWriter::Options *options = document.getOptions(); + std::string filename = osgDB::findDataFile(strFile, options); + if (filename.empty()) + { + osg::notify(osg::WARN) << "Can't find external " << strFile << std::endl; + return; + } + + _external = new osg::Group; + _external->setName(strFile); + Registry::instance()->addExternal(filename, _external.get()); + + // Add this implementation to parent implementation. + if (_parent.valid()) + _parent->addChild(*_external); + } + +}; + +RegisterRecordProxy g_ExternalReference(EXTERNAL_REFERENCE_OP); + + +/** InstanceDefinition +*/ +class InstanceDefinition : public PrimaryRecord +{ + osg::ref_ptr _instanceDefinition; + +public: + + InstanceDefinition() {} + + META_Record(InstanceDefinition) + + META_setID(_instanceDefinition) + META_setComment(_instanceDefinition) + META_setMultitexture(_instanceDefinition) + META_addChild(_instanceDefinition) + + virtual void setMatrix(osg::Matrix& matrix) + { + osg::ref_ptr transform = new osg::MatrixTransform(matrix); + transform->setDataVariance(osg::Object::STATIC); + transform->addChild(_instanceDefinition.get()); + _instanceDefinition = transform.get(); + } + +protected: + + virtual ~InstanceDefinition() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + in.forward(2); + uint16 number = in.readUInt16(); + + _instanceDefinition = new osg::Group; + + // Add to instance definition table. + document.setInstanceDefinition(number,_instanceDefinition.get()); + } +}; + +RegisterRecordProxy g_InstanceDefinition(INSTANCE_DEFINITION_OP); + + +/** InstanceReference + * The InstanceReference is a leaf record. + */ +class InstanceReference : public PrimaryRecord +{ +public: + + InstanceReference() {} + + META_Record(InstanceReference) + +protected: + + virtual ~InstanceReference() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + in.forward(2); + uint16 number = in.readUInt16(); + + // Get definition. + osg::Node* instance = document.getInstanceDefinition(number); + + // Add this implementation to parent implementation. + if (_parent.valid()) + _parent->addChild(*instance); + } +}; + +RegisterRecordProxy g_InstanceReference(INSTANCE_REFERENCE_OP); + + +/** Extension +*/ +class Extension : public PrimaryRecord +{ + osg::ref_ptr _extension; + +public: + + Extension() {} + + META_Record(Extension) + + META_setID(_extension) + META_setComment(_extension) + META_setMatrix(_extension) + META_setMultitexture(_extension) + META_addChild(_extension) + +protected: + + virtual ~Extension() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + std::string id = in.readString(8); + std::string siteId = in.readString(8); + in.forward(1); + + _extension = new osg::Group; + _extension->setName(id); + + // Add this implementation to parent implementation. + if (_parent.valid()) + _parent->addChild(*_extension); + } +}; + +RegisterRecordProxy g_Extension(EXTENSION_OP); + + +} // end namespace diff --git a/src/osgPlugins/OpenFlight/ReaderWriterATTR.cpp b/src/osgPlugins/OpenFlight/ReaderWriterATTR.cpp new file mode 100644 index 000000000..e64318c74 --- /dev/null +++ b/src/osgPlugins/OpenFlight/ReaderWriterATTR.cpp @@ -0,0 +1,177 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "AttrData.h" +#include "DataInputStream.h" + +using namespace osg; +using namespace osgDB; +using namespace flt; + + +class ReaderWriterATTR : public osgDB::ReaderWriter +{ + public: + + virtual const char* className() const { return "ATTR Image Attribute Reader/Writer"; } + + virtual bool acceptsExtension(const std::string& extension) const + { + return equalCaseInsensitive(extension,"attr"); + } + + virtual ReadResult readObject(const std::string& fileName, const ReaderWriter::Options*) const; +}; + + +ReaderWriter::ReadResult ReaderWriterATTR::readObject(const std::string& file, const ReaderWriter::Options* options) const +{ + using std::ios; + + std::string ext = osgDB::getLowerCaseFileExtension(file); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + + std::string fileName = osgDB::findDataFile( file, options ); + if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; + + std::ifstream fin(fileName.c_str(), ios::in | ios::binary); + + if ( fin.fail()) + return ReadResult::ERROR_IN_READING_FILE; + + flt::DataInputStream in(&fin); + + AttrData* attr = new AttrData; + + try + { + attr->texels_u = in.readInt32(); + attr->textel_v = in.readInt32(); + attr->direction_u = in.readInt32(); + attr->direction_v = in.readInt32(); + attr->x_up = in.readInt32(); + attr->y_up = in.readInt32(); + attr->fileFormat = in.readInt32(); + attr->minFilterMode = in.readInt32(); + attr->magFilterMode = in.readInt32(); + attr->wrapMode = in.readInt32(); + + attr->wrapMode_u = in.readInt32(); + if ((attr->wrapMode_u != AttrData::WRAP_CLAMP) && ((attr->wrapMode_u != AttrData::WRAP_REPEAT))) + attr->wrapMode_u = attr->wrapMode; + + attr->wrapMode_v = in.readInt32(); + if ((attr->wrapMode_v != AttrData::WRAP_CLAMP) && ((attr->wrapMode_v != AttrData::WRAP_REPEAT))) + attr->wrapMode_v = attr->wrapMode; + + attr->modifyFlag = in.readInt32(); + attr->pivot_x = in.readInt32(); + attr->pivot_y = in.readInt32(); + + // v11 ends here +// if (in.eof() || (_flt_version <= 11)) return true; +#if 1 + attr->texEnvMode = in.readInt32(); + attr->intensityAsAlpha = in.readInt32(); + in.forward(4*8); + attr->size_u = in.readFloat64(); + attr->size_v = in.readFloat64(); + attr->originCode = in.readInt32(); + attr->kernelVersion = in.readInt32(); + attr->intFormat = in.readInt32(); + attr->extFormat = in.readInt32(); + attr->useMips = in.readInt32(); + for (int n=0; n<8; n++) + attr->_mips[n] = in.readFloat32(); + attr->useLodScale = in.readInt32(); + attr->lod0 = in.readFloat32(); + attr->scale0 = in.readFloat32(); + attr->lod1 = in.readFloat32(); + attr->scale1 = in.readFloat32(); + attr->lod2 = in.readFloat32(); + attr->scale2 = in.readFloat32(); + attr->lod3 = in.readFloat32(); + attr->scale3 = in.readFloat32(); + attr->lod4 = in.readFloat32(); + attr->scale4 = in.readFloat32(); + attr->lod5 = in.readFloat32(); + attr->scale5 = in.readFloat32(); + attr->lod6 = in.readFloat32(); + attr->scale6 = in.readFloat32(); + attr->lod7 = in.readFloat32(); + attr->scale7 = in.readFloat32(); + attr->clamp = in.readFloat32(); + attr->magFilterAlpha = in.readInt32(); + attr->magFilterColor = in.readInt32(); + in.forward(4); + in.forward(4*8); + attr->lambertMeridian = in.readFloat64(); + attr->lambertUpperLat = in.readFloat64(); + attr->lambertlowerLat = in.readFloat64(); + in.forward(8); + in.forward(4*5); + attr->useDetail = in.readInt32( ); + attr->txDetail_j = in.readInt32(); + attr->txDetail_k = in.readInt32(); + attr->txDetail_m = in.readInt32(); + attr->txDetail_n = in.readInt32(); + attr->txDetail_s = in.readInt32( ); + attr->useTile = in.readInt32(); + attr->txTile_ll_u= in.readFloat32(); + attr->txTile_ll_v = in.readFloat32(); + attr->txTile_ur_u = in.readFloat32(); + attr->txTile_ur_v = in.readFloat32(); + attr->projection = in.readInt32(); + attr->earthModel = in.readInt32(); + in.forward(4); + attr->utmZone = in.readInt32(); + attr->imageOrigin = in.readInt32(); + attr->geoUnits = in.readInt32(); + in.forward(4); + in.forward(4); + attr->hemisphere = in.readInt32(); + in.forward(4); + in.forward(4); + in.forward(149); + attr->comments = in.readString(512); + + // v12 ends here +// if (in.eof() || (_flt_version <= 12)) return true; + + in.forward(13*4); + attr->attrVersion = in.readInt32(); + attr->controlPoints = in.readInt32(); + in.forward(4); +#endif + } + catch(...) + { + if (!fin.eof()) + { + throw; + } + } + + fin.close(); + + return attr; +} + + + +// now register with Registry to instantiate the above +// reader/writer. +osgDB::RegisterReaderWriterProxy g_readerWriter_ATTR_Proxy; diff --git a/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp b/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp new file mode 100644 index 000000000..f410862d5 --- /dev/null +++ b/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp @@ -0,0 +1,187 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Registry.h" +#include "Document.h" +#include "RecordInputStream.h" + +#define SERIALIZER() OpenThreads::ScopedLock lock(_serializerMutex) + +using namespace flt; +using namespace osg; +using namespace osgDB; + + +class FLTReaderWriter : public ReaderWriter +{ + public: + virtual const char* className() const { return "FLT Reader/Writer"; } + + virtual bool acceptsExtension(const std::string& extension) const + { + return equalCaseInsensitive(extension,"flt"); + } + + virtual ReadResult readObject(const std::string& file, const Options* options) const + { + return readNode(file, options); + } + + virtual ReadResult readNode(const std::string& file, const Options* options) const + { + SERIALIZER(); + + std::string ext = osgDB::getLowerCaseFileExtension(file); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + + std::string fileName = osgDB::findDataFile( file, options ); + if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; + + // code for setting up the database path so that internally referenced file are searched for on relative paths. + osg::ref_ptr local_opt = options ? static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; + local_opt->setDatabasePath(osgDB::getFilePath(fileName)); +// local_opt->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL); + + std::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary); + return readNode(istream,local_opt.get()); + } + + virtual ReadResult readObject(std::istream& fin, const Options* options) const + { + return readNode(fin, options); + } + + virtual ReadResult readNode(std::istream& fin, const Options* options) const + { + try + { + Document document; + document.setOptions(options); + + // option string + if (options) + { + document.setUseTextureAlphaForTransparancyBinning(options->getOptionString().find("noTextureAlphaForTransparancyBinning")==std::string::npos); + osg::notify(osg::DEBUG_INFO) << "FltFile.getUseTextureAlphaForTransparancyBinning()=" << document.getUseTextureAlphaForTransparancyBinning() << std::endl; + document.setDoUnitsConversion((options->getOptionString().find("noUnitsConversion")==std::string::npos)); // default to true, unless noUnitsConversion is specified.o + osg::notify(osg::DEBUG_INFO) << "FltFile.getDoUnitsConversion()=" << document.getDoUnitsConversion() << std::endl; + + if (document.getDoUnitsConversion()) + { + if (options->getOptionString().find("convertToFeet")!=std::string::npos) + document.setDesiredUnits(FEET); + else if (options->getOptionString().find("convertToInches")!=std::string::npos) + document.setDesiredUnits(INCHES); + else if (options->getOptionString().find("convertToMeters")!=std::string::npos) + document.setDesiredUnits(METERS); + else if (options->getOptionString().find("convertToKilometers")!=std::string::npos) + document.setDesiredUnits(KILOMETERS); + else if (options->getOptionString().find("convertToNauticalMiles")!=std::string::npos) + document.setDesiredUnits(NAUTICAL_MILES); + } + } + + { + // read records + flt::RecordInputStream recordStream(&fin); + while (recordStream().good() && !document.done()) + { + recordStream.readRecord(document); + } + } + + { + // optimize + osgFlightUtil::Optimizer optimizer; + optimizer.optimize(document.getHeaderNode()); + } + + readExternals(options); + + return document.getHeaderNode(); + } + catch (std::exception &e) + { + osg::notify(osg::NOTICE) << "Error reading file: " << e.what() << std::endl; + return ReadResult::FILE_NOT_HANDLED; + } + catch (...) + { + return ReadResult::FILE_NOT_HANDLED; + } + } + + virtual WriteResult writeObject(const Object& object,const std::string& fileName, const osgDB::ReaderWriter::Options* options) const + { + const Node* node = dynamic_cast(&object); + if (node) return writeNode( *node, fileName, options ); + return WriteResult::FILE_NOT_HANDLED; + } + + virtual WriteResult writeNode(const Node& node,const std::string& fileName, const osgDB::ReaderWriter::Options* options) const + { + std::string ext = getFileExtension(fileName); + if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; + + // code for setting up the database path so that internally referenced file are searched for on relative paths. + osg::ref_ptr local_opt = options ? static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; + if(local_opt->getDatabasePathList().empty()) + local_opt->setDatabasePath(osgDB::getFilePath(fileName)); + + std::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary); + WriteResult result = writeNode(node, fout, local_opt.get()); + fout.close(); + return result; + } + + virtual WriteResult writeObject(const Object& object,std::ostream& fout, const osgDB::ReaderWriter::Options* options) const + { + const Node* node = dynamic_cast(&object); + if (node) return writeNode( *node, fout, options ); + return WriteResult::FILE_NOT_HANDLED; + } + + virtual WriteResult writeNode(const Node& node,std::ostream& fout, const osgDB::ReaderWriter::Options* options) const + { + return WriteResult::FILE_NOT_HANDLED; + + } + + protected: + + void readExternals(const Options* options) const + { + flt::Registry::ExternalQueue& eq = flt::Registry::instance()->getExternalQueue(); + while (!eq.empty()) + { + std::string extfilename = eq.front().first; + osg::ref_ptr external = eq.front().second; + eq.pop(); + + if (external.valid()) + { + osg::Node* extmodel = osgDB::readNodeFile(extfilename,options); + external->addChild(extmodel); + } + } + } + + mutable osgDB::ReentrantMutex _serializerMutex; +}; + +// now register with Registry to instantiate the above +// reader/writer. +RegisterReaderWriterProxy g_FLTReaderWriterProxy; diff --git a/src/osgPlugins/OpenFlight/Record.cpp b/src/osgPlugins/OpenFlight/Record.cpp new file mode 100644 index 000000000..991521254 --- /dev/null +++ b/src/osgPlugins/OpenFlight/Record.cpp @@ -0,0 +1,138 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include +#include +#include "Record.h" +#include "Document.h" + +using namespace flt; + + +Record::Record() +{ +} + +void Record::setParent(PrimaryRecord* parent) +{ + _parent = parent; +} + +//PrimaryRecord& Record::parent() +//{ +// if (!_parent) +// throw std::runtime_error("Record::parent(): invalid pointer to parent exception."); +// +// return *_parent; +//} + + +void Record::read(RecordInputStream& in, Document& document) +{ + setParent(document.getCurrentPrimaryRecord()); + + // Read record body. + readRecord(in,document); +} + + +void Record::readRecord(RecordInputStream& in, Document& document) +{ +} + + +PrimaryRecord::PrimaryRecord() : + _numberOfReplications(0) +{ +} + + +void PrimaryRecord::read(RecordInputStream& in, Document& document) +{ + setParent(document.getTopOfLevelStack()); + + // Update primary record. + document.setCurrentPrimaryRecord(this); + + // Read record body. + readRecord(in,document); +} + +/////////////////////////////////////////////////////////////////////////////////// +// Helper methods + +// Insert matrix-tranform above node. +// Return transform. +osg::ref_ptr flt::insertMatrixTransform(osg::Node& node, const osg::Matrix& matrix) +{ + osg::ref_ptr ref = &node; + osg::ref_ptr transform = new osg::MatrixTransform(matrix); + transform->setDataVariance(osg::Object::STATIC); + + // Replace parent + osg::Node::ParentList parents = node.getParents(); + for (osg::Node::ParentList::iterator itr=parents.begin(); + itr!=parents.end(); + ++itr) + { + (*itr)->replaceChild(&node,transform.get()); + } + + // Make primary a child of matrix transform. + transform->addChild(&node); + + return transform; +} + + +/////////////////////////////////////////////////////////////////////////////////// + + +osg::Vec3Array* flt::getOrCreateVertexArray(osg::Geometry& geometry) +{ + osg::Vec3Array* vertices = dynamic_cast(geometry.getVertexArray()); + if (!vertices) + { + vertices = new osg::Vec3Array; + geometry.setVertexArray(vertices); + } + return vertices; +} + +osg::Vec3Array* flt::getOrCreateNormalArray(osg::Geometry& geometry) +{ + osg::Vec3Array* normals = dynamic_cast(geometry.getNormalArray()); + if (!normals) + { + normals = new osg::Vec3Array; + geometry.setNormalArray(normals); + } + return normals; +} + +osg::Vec4Array* flt::getOrCreateColorArray(osg::Geometry& geometry) +{ + osg::Vec4Array* colors = dynamic_cast(geometry.getColorArray()); + if (!colors) + { + colors = new osg::Vec4Array; + geometry.setColorArray(colors); + } + return colors; +} + + +osg::Vec2Array* flt::getOrCreateTextureArray(osg::Geometry& geometry, int unit) +{ + osg::Vec2Array* UVs = dynamic_cast(geometry.getTexCoordArray(unit)); + if (!UVs) + { + UVs = new osg::Vec2Array; + geometry.setTexCoordArray(unit,UVs); + } + return UVs; +} diff --git a/src/osgPlugins/OpenFlight/Record.h b/src/osgPlugins/OpenFlight/Record.h new file mode 100644 index 000000000..b68fe4fc5 --- /dev/null +++ b/src/osgPlugins/OpenFlight/Record.h @@ -0,0 +1,114 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_RECORD_H +#define FLT_RECORD_H 1 + +#include +#include +#include +#include +#include +#include +#include +#include "Vertex.h" + +namespace flt +{ + +class RecordInputStream; +class Document; +class PrimaryRecord; +class Matrix; + +#define META_Record(name) \ + virtual flt::Record* cloneType() const { return new name (); } \ + virtual bool isSameKindAs(const flt::Record* rec) const { return dynamic_cast(rec)!=NULL; } +#define META_setID(imp) virtual void setID(const std::string& id) { if (imp.valid()) imp->setName(id); } +#define META_setComment(imp) virtual void setComment(const std::string& id) { if (imp.valid()) imp->addDescription(id); } +#define META_setMatrix(imp) virtual void setMatrix(osg::Matrix& matrix) { if (imp.valid()) insertMatrixTransform(*imp,matrix); } +#define META_setMultitexture(imp) virtual void setMultitexture(osg::StateSet& multitexture) { if (imp.valid()) imp->getOrCreateStateSet()->merge(multitexture); } +#define META_addChild(imp) virtual void addChild(osg::Node& child) { if (imp.valid()) imp->addChild(&child); } + + +// pure virtual base class +class Record : public osg::Referenced +{ +public: + + Record(); + + virtual Record* cloneType() const = 0; + virtual bool isSameKindAs(const Record* rec) const = 0; + virtual void read(RecordInputStream& in, Document& document); + + void setParent(PrimaryRecord* parent); + +protected: + + virtual ~Record() {} + + virtual void readRecord(RecordInputStream& in, Document& document); + + osg::ref_ptr _parent; +}; + + +class PrimaryRecord : public Record +{ +public: + + PrimaryRecord(); + + virtual void read(RecordInputStream& in, Document& document); + + // Ancillary operations + virtual void setID(const std::string& id) {} + virtual void setComment(const std::string& comment) {} + virtual void setMatrix(osg::Matrix& matrix) {} + virtual void setMultitexture(osg::StateSet& multitexture) {} + virtual void addChild(osg::Node& child) {} + virtual void addVertex(Vertex& vertex) {} + virtual void addVertexUV(int layer,const osg::Vec2& uv) {} + virtual void addMorphVertex(Vertex& vertex0, Vertex& vertex100) {} + + void setNumberOfReplications(int num) { _numberOfReplications = num; } + +protected: + + virtual ~PrimaryRecord() {} + + int _numberOfReplications; +}; + + +/** DummyRecord - + */ +class DummyRecord : public Record +{ + public: + + DummyRecord() {} + + META_Record(DummyRecord) + + protected: + + virtual ~DummyRecord() {} +}; + + +osg::ref_ptr insertMatrixTransform(osg::Node& node, const osg::Matrix& matrix); + +osg::Vec3Array* getOrCreateVertexArray(osg::Geometry& geometry); +osg::Vec3Array* getOrCreateNormalArray(osg::Geometry& geometry); +osg::Vec4Array* getOrCreateColorArray(osg::Geometry& geometry); +osg::Vec2Array* getOrCreateTextureArray(osg::Geometry& geometry, int unit); + + +} // end namespace + +#endif diff --git a/src/osgPlugins/OpenFlight/RecordInputStream.cpp b/src/osgPlugins/OpenFlight/RecordInputStream.cpp new file mode 100644 index 000000000..292f8e70c --- /dev/null +++ b/src/osgPlugins/OpenFlight/RecordInputStream.cpp @@ -0,0 +1,126 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include "opcodes.h" +#include "Registry.h" +#include "Document.h" +#include "RecordInputStream.h" + +using namespace flt; +using namespace std; + + +RecordInputStream::RecordInputStream(std::istream* istream): + DataInputStream(istream) +{ + +#if 0 //def _DEBUG + ios::iostate mask = istream->exceptions(); + cout << "ios::badbit=" << ( mask & ios::badbit ) << std::endl; + cout << "ios::failbit=" << ( mask & ios::failbit ) << std::endl; + cout << "ios::eofbit=" << ( mask & ios::eofbit ) << std::endl; +#endif + + // dont't throw an exception on failbit + istream->exceptions(istream->exceptions() & ~ios::failbit); +} + + +RecordInputStream::~RecordInputStream() +{ +} + + +std::istream& RecordInputStream::read(std::istream::char_type *_Str, std::streamsize _Count) const +{ + // Bounds check + istream::pos_type pos = _istream->tellg(); + if (pos+(istream::pos_type)_Count > _end) + { + _istream->setstate(ios::failbit); // end-of-record (EOR) + return *_istream; + } + + return _istream->read(_Str,_Count); +} + + +bool RecordInputStream::readRecord(Document& document) +{ + // Get current read position in stream. + _start = _istream->tellg(); + + // Get record header without bounds check. + DataInputStream distream(_istream); + uint16 opcode = distream.readUInt16(); + uint16 size = distream.readUInt16(); + + // Correct endian error in Creator v2.5 gallery models. + // Last pop level record in little-endian. + const uint16 LITTLE_ENDIAN_POP_LEVEL_OP = 0x0B00; + if (opcode==LITTLE_ENDIAN_POP_LEVEL_OP) + { + osg::notify(osg::INFO) << "Little endian pop-level record" << std::endl; + opcode=POP_LEVEL_OP; + size=4; + } + + // Update end-of-record + _end = _start + (std::istream::pos_type)size; + +#if 0 + // TODO: Peek at next opcode looking for continuation record. + _istream->seekg(_end, std::ios_base::beg); + if (_istream->fail()) + return false; + + int16 nextOpcode = readUInt16(); + _istream->seekg(_start+(std::istream::pos_type)4, std::ios_base::beg); + if (nextOpcode == CONTINUATION_OP) + { + + } +#endif + + // Get prototype record + Record* prototype = Registry::instance()->getPrototype((int)opcode); + + if (prototype) + { +#if 0 //def _DEBUG + { + for (int i=0; i record = prototype->cloneType(); + + // Read record + record->read(*this,document); + } + + // Clear failbit, it's used for end-of-record testing. + _istream->clear(_istream->rdstate() & ~std::ios::failbit); + } + else // prototype not found + { + osg::notify(osg::WARN) << "Unknown record, opcode=" << opcode << " size=" << size << std::endl; + + // Add to registry so we only have to see this error message once. + Registry::instance()->addPrototype(opcode,new DummyRecord); + } + + // Move to beginning of next record + _istream->seekg(_end, std::ios_base::beg); + + return _istream->good(); +} diff --git a/src/osgPlugins/OpenFlight/RecordInputStream.h b/src/osgPlugins/OpenFlight/RecordInputStream.h new file mode 100644 index 000000000..0d6848088 --- /dev/null +++ b/src/osgPlugins/OpenFlight/RecordInputStream.h @@ -0,0 +1,49 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_RECORDINPUTSTREAM_H +#define FLT_RECORDINPUTSTREAM_H 1 + +#include "Record.h" +#include "DataInputStream.h" + +namespace flt { + +class Document; + +class RecordInputStream : public DataInputStream +{ + public: + + RecordInputStream(std::istream* istream); + virtual ~RecordInputStream(); + + // end of record +// bool eor() const; + + bool readRecord(Document& data); + + inline std::istream::pos_type getStartOfRecord() const { return _start; } + inline std::istream::pos_type getEndOfRecord() const { return _end; } + inline std::streamsize getRecordSize() const { return _end-_start; } + inline std::streamsize getRecordBodySize() const { return getRecordSize()-(std::streamsize)4; } + + inline void moveToStartOfRecord() const { _istream->seekg(_start,std::ios_base::beg); } + inline void setEndOfRecord(std::istream::pos_type pos) { _end=pos; } + + + protected: + + virtual std::istream& read(std::istream::char_type *_Str, std::streamsize _Count) const; + +// std::istream* _istream; + std::istream::pos_type _start; // start of record + std::istream::pos_type _end; // end of record +}; + +} // end namespace + +#endif diff --git a/src/osgPlugins/OpenFlight/Registry.cpp b/src/osgPlugins/OpenFlight/Registry.cpp new file mode 100644 index 000000000..7bb255eb7 --- /dev/null +++ b/src/osgPlugins/OpenFlight/Registry.cpp @@ -0,0 +1,47 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include "Registry.h" + +using namespace flt; + +Registry::Registry() +{ +} + +Registry::~Registry() +{ +} + +Registry* Registry::instance() +{ + static Registry s_registry; + return &s_registry; +} + +void Registry::addPrototype(int opcode, Record* prototype) +{ + if (prototype==0L) + { + osg::notify(osg::WARN) << "Not a record." << std::endl; + return; + } + + if (_recordProtoMap.find(opcode) != _recordProtoMap.end()) + osg::notify(osg::WARN) << "Registry already contains prototype for opcode " << opcode << "." << std::endl; + + _recordProtoMap[opcode] = prototype; +} + +Record* Registry::getPrototype(int opcode) +{ + RecordProtoMap::iterator itr = _recordProtoMap.find(opcode); + if (itr != _recordProtoMap.end()) + return (*itr).second.get(); + + return NULL; +} diff --git a/src/osgPlugins/OpenFlight/Registry.h b/src/osgPlugins/OpenFlight/Registry.h new file mode 100644 index 000000000..32f79067b --- /dev/null +++ b/src/osgPlugins/OpenFlight/Registry.h @@ -0,0 +1,66 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_REGISTRY_H +#define FLT_REGISTRY_H 1 + +#include +#include +#include "opcodes.h" +#include "Record.h" + +namespace flt { + +class Registry : public osg::Referenced +{ + public: + + ~Registry(); + static Registry* instance(); + + // Prototypes + void addPrototype(int opcode, Record* prototype); + Record* getPrototype(int opcode); + + // Externals + typedef std::pair ExtNameNodePair; + typedef std::queue ExternalQueue; + + inline ExternalQueue& getExternalQueue() { return _externalQueue; } + + inline void addExternal(const std::string& name, osg::Group* node) + { + _externalQueue.push( ExtNameNodePair(name,node) ); + } + + protected: + + Registry(); + + typedef std::map > RecordProtoMap; + RecordProtoMap _recordProtoMap; + + ExternalQueue _externalQueue; +}; + + +/** Proxy class for automatic registration of reader/writers with the Registry.*/ +template +class RegisterRecordProxy +{ + public: + + explicit RegisterRecordProxy(int opcode) + { + Registry::instance()->addPrototype(opcode,new T); + } + + ~RegisterRecordProxy() {} +}; + +} // end namespace + +#endif diff --git a/src/osgPlugins/OpenFlight/ReservedRecords.cpp b/src/osgPlugins/OpenFlight/ReservedRecords.cpp new file mode 100644 index 000000000..e0e7ebdc1 --- /dev/null +++ b/src/osgPlugins/OpenFlight/ReservedRecords.cpp @@ -0,0 +1,23 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include "Registry.h" + +using namespace flt; + +// Prevent "unknown record" message for the following reserved records: +RegisterRecordProxy g_Reserved_103(103); +RegisterRecordProxy g_Reserved_104(104); +RegisterRecordProxy g_Reserved_117(117); +RegisterRecordProxy g_Reserved_118(118); +RegisterRecordProxy g_Reserved_120(120); +RegisterRecordProxy g_Reserved_121(121); +RegisterRecordProxy g_Reserved_124(124); +RegisterRecordProxy g_Reserved_125(125); + + + + diff --git a/src/osgPlugins/OpenFlight/RoadRecords.cpp b/src/osgPlugins/OpenFlight/RoadRecords.cpp new file mode 100644 index 000000000..e6ca61e23 --- /dev/null +++ b/src/osgPlugins/OpenFlight/RoadRecords.cpp @@ -0,0 +1,121 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include +#include +#include "Registry.h" +#include "Document.h" +#include "RecordInputStream.h" + + +namespace flt { + +/** RoadSegment +*/ +class RoadSegment : public PrimaryRecord +{ + osg::ref_ptr _roadSegment; + + public: + + RoadSegment() {} + + META_Record(RoadSegment) + + META_setID(_roadSegment) + META_setComment(_roadSegment) + META_setMatrix(_roadSegment) + META_setMultitexture(_roadSegment) + META_addChild(_roadSegment) + + protected: + + virtual ~RoadSegment() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + _roadSegment = new osg::Group; + + // Add to parent. + if (_parent.valid()) + _parent->addChild(*_roadSegment); + } +}; + +RegisterRecordProxy g_RoadSegment(ROAD_SEGMENT_OP); + + +/** RoadConstruction +*/ +class RoadConstruction : public PrimaryRecord +{ + osg::ref_ptr _roadConstruction; + + public: + + RoadConstruction() {} + + META_Record(RoadConstruction) + + META_setID(_roadConstruction) + META_setComment(_roadConstruction) + META_setMatrix(_roadConstruction) + META_setMultitexture(_roadConstruction) + META_addChild(_roadConstruction) + + protected: + + virtual ~RoadConstruction() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + _roadConstruction = new osg::Group; + + // Add to parent. + if (_parent.valid()) + _parent->addChild(*_roadConstruction); + } +}; + +RegisterRecordProxy g_RoadConstruction(ROAD_CONSTRUCTION_OP); + + +/** RoadPath +*/ +class RoadPath : public PrimaryRecord +{ + osg::ref_ptr _roadPath; + + public: + + RoadPath() {} + + META_Record(RoadPath) + + META_setID(_roadPath) + META_setComment(_roadPath) + META_setMatrix(_roadPath) + META_setMultitexture(_roadPath) + META_addChild(_roadPath) + + protected: + + virtual ~RoadPath() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + _roadPath = new osg::Group; + + // Add to parent. + if (_parent.valid()) + _parent->addChild(*_roadPath); + } +}; + +RegisterRecordProxy g_RoadPath(ROAD_PATH_OP); + + +} // end namespace diff --git a/src/osgPlugins/OpenFlight/Vertex.cpp b/src/osgPlugins/OpenFlight/Vertex.cpp new file mode 100644 index 000000000..6678680c5 --- /dev/null +++ b/src/osgPlugins/OpenFlight/Vertex.cpp @@ -0,0 +1,55 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include "Vertex.h" + +using namespace flt; + +Vertex::Vertex(): + _coord(0,0,0), + _color(1,1,1,1), + _normal(0,0,1), + _validColor(false), + _validNormal(false), + _validUV(false) +{ +} + +Vertex::Vertex(const Vertex& vertex): + _coord(vertex._coord), + _color(vertex._color), + _normal(vertex._normal), + _uv(vertex._uv), + _validColor(vertex._validColor), + _validNormal(vertex._validNormal), + _validUV(vertex._validUV) +{ +} + +void Vertex::setCoord(osg::Vec3 coord) +{ + _coord = coord; +} + +void Vertex::setColor(osg::Vec4 color) +{ + _color = color; + _validColor = true; +} + +void Vertex::setNormal(osg::Vec3 normal) +{ + _normal = normal; + _validNormal = true; +} + +void Vertex::setUV(osg::Vec2 uv) +{ + _uv = uv; + _validUV = true; +} + + diff --git a/src/osgPlugins/OpenFlight/Vertex.h b/src/osgPlugins/OpenFlight/Vertex.h new file mode 100644 index 000000000..a84298272 --- /dev/null +++ b/src/osgPlugins/OpenFlight/Vertex.h @@ -0,0 +1,44 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_VERTEX_H +#define FLT_VERTEX_H 1 + +#include +#include +#include + +namespace flt { + +class Vertex +{ +public: + + Vertex(); + Vertex(const Vertex& vertex); + + void setCoord(osg::Vec3 coord); + void setColor(osg::Vec4 color); + void setNormal(osg::Vec3 normal); + void setUV(osg::Vec2 uv); + + bool validColor() const { return _validColor; } + bool validNormal() const { return _validNormal; } + bool validUV() const { return _validUV; } + + osg::Vec3 _coord; + osg::Vec4 _color; + osg::Vec3 _normal; + osg::Vec2 _uv; + + bool _validColor; + bool _validNormal; + bool _validUV; +}; + +} // end namespace + +#endif diff --git a/src/osgPlugins/OpenFlight/VertexRecords.cpp b/src/osgPlugins/OpenFlight/VertexRecords.cpp new file mode 100644 index 000000000..8f13eb275 --- /dev/null +++ b/src/osgPlugins/OpenFlight/VertexRecords.cpp @@ -0,0 +1,324 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include "Record.h" +#include "Registry.h" +#include "Document.h" +#include "RecordInputStream.h" + +namespace flt { + +// Color from ColorPool. +osg::Vec4 getColorFromPool(int index, const ColorPool* colorPool) +{ + osg::Vec4 color(1,1,1,1); + if (colorPool) + color = colorPool->getColor(index); + return color; +} + + +// Vertex flags +enum Flags +{ + START_HARD_EDGE = (0x8000 >> 0), + NORMAL_FROZEN = (0x8000 >> 1), + NO_COLOR = (0x8000 >> 2), + PACKED_COLOR = (0x8000 >> 3) +}; + + +class VertexC : public Record +{ + public: + + VertexC() {} + + META_Record(VertexC) + + virtual ~VertexC() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int colorNameIndex = in.readInt16(); + uint16 flags = in.readUInt16(); + osg::Vec3d coord = in.readVec3d(); + osg::Vec4f packedColor = in.readColor32(); + int colorIndex = in.readInt32(-1); + + Vertex vertex; + vertex.setCoord(coord*document.unitScale()); + + // color + if (flags & PACKED_COLOR) + vertex.setColor(packedColor); // Packed color + else if (colorIndex >= 0) + vertex.setColor(getColorFromPool(colorIndex, document.getColorPool())); // Color from pool + + if (_parent.valid()) + _parent->addVertex(vertex); + } +}; + +RegisterRecordProxy g_VertexC(VERTEX_C_OP); + + +class VertexCN : public Record +{ + public: + + VertexCN() {} + + META_Record(VertexCN) + + protected: + + virtual ~VertexCN() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int colorNameIndex = in.readInt16(); + uint16 flags = in.readUInt16(); + osg::Vec3d coord = in.readVec3d(); + osg::Vec3f normal = in.readVec3f(); + osg::Vec4f packedColor = in.readColor32(); + int colorIndex = in.readInt32(-1); + + Vertex vertex; + vertex.setCoord(coord*document.unitScale()); + vertex.setNormal(normal); + + // color + if (flags & PACKED_COLOR) + vertex.setColor(packedColor); // Packed color + else if (colorIndex >= 0) + vertex.setColor(getColorFromPool(colorIndex, document.getColorPool())); // Color from pool + + if (_parent.valid()) + _parent->addVertex(vertex); + } +}; + +RegisterRecordProxy g_VertexCN(VERTEX_CN_OP); + + +class VertexCT : public Record +{ + public: + + VertexCT() {} + + META_Record(VertexCT) + + protected: + + virtual ~VertexCT() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int colorNameIndex = in.readInt16(); + uint16 flags = in.readUInt16(); + osg::Vec3d coord = in.readVec3d(); + osg::Vec2f uv = in.readVec2f(); + osg::Vec4f packedColor = in.readColor32(); + int colorIndex = in.readInt32(-1); + + Vertex vertex; + vertex.setCoord(coord*document.unitScale()); + vertex.setUV(uv); + + // color + if (flags & PACKED_COLOR) + vertex.setColor(packedColor); // Packed color + else if (colorIndex >= 0) + vertex.setColor(getColorFromPool(colorIndex, document.getColorPool())); // Color from pool + + if (_parent.valid()) + _parent->addVertex(vertex); + } +}; + +RegisterRecordProxy g_VertexCT(VERTEX_CT_OP); + + +class VertexCNT : public Record +{ + public: + + VertexCNT() {} + + META_Record(VertexCNT) + + protected: + + virtual ~VertexCNT() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int colorNameIndex = in.readInt16(); + uint16 flags = in.readUInt16(); + osg::Vec3d coord = in.readVec3d(); + osg::Vec3f normal = in.readVec3f(); + osg::Vec2f uv = in.readVec2f(); + osg::Vec4f packedColor = in.readColor32(); + int colorIndex = in.readInt32(-1); + + Vertex vertex; + vertex.setCoord(coord*document.unitScale()); + vertex.setNormal(normal); + vertex.setUV(uv); + + // color + if (flags & PACKED_COLOR) + vertex.setColor(packedColor); // Packed color + else if (colorIndex >= 0) + vertex.setColor(getColorFromPool(colorIndex, document.getColorPool())); // Color from pool + + if (_parent.valid()) + _parent->addVertex(vertex); + } +}; + +RegisterRecordProxy g_VertexCNT(VERTEX_CNT_OP); + + +/** Absolut Vertex - + * version < 13 + */ +class AbsoluteVertex : public Record +{ + public: + + AbsoluteVertex() {} + + META_Record(AbsoluteVertex) + + protected: + + virtual ~AbsoluteVertex() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int32 x = in.readInt32(); + int32 y = in.readInt32(); + int32 z = in.readInt32(); + + Vertex vertex; + + // coord + vertex.setCoord(osg::Vec3(x,y,z) * document.unitScale()); + + // optional texture coordinates + if (in().tellg() < in.getEndOfRecord()) + { + osg::Vec2f uv = in.readVec2f(); + vertex.setUV(uv); + } + + if (_parent.valid()) + _parent->addVertex(vertex); + } +}; + +RegisterRecordProxy g_AbsoluteVertex(OLD_ABSOLUTE_VERTEX_OP); + + +/** Shaded Vertex + * version < 13 + */ +class ShadedVertex : public Record +{ + public: + + ShadedVertex() {} + + META_Record(ShadedVertex) + + protected: + + virtual ~ShadedVertex() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int32 x = in.readInt32(); + int32 y = in.readInt32(); + int32 z = in.readInt32(); + uint8 edgeFlag = in.readUInt8(); + uint8 shadingFlag = in.readUInt8(); + int colorIndex = (int)in.readInt16(); + + Vertex vertex; + + // coord + vertex.setCoord(osg::Vec3(x,y,z) * document.unitScale()); + + // color + if (colorIndex >= 0) + vertex.setColor(getColorFromPool(colorIndex, document.getColorPool())); // Color from pool + + // optional texture coordinates + if (in().tellg() < in.getEndOfRecord()) + { + osg::Vec2f uv = in.readVec2f(); + vertex.setUV(uv); + } + + if (_parent.valid()) + _parent->addVertex(vertex); + } +}; + +RegisterRecordProxy g_ShadedVertex(OLD_SHADED_VERTEX_OP); + + +/** Normal Vertex + * version < 13 + */ +class NormalVertex : public Record +{ + public: + + NormalVertex() {} + + META_Record(NormalVertex) + + protected: + + virtual ~NormalVertex() {} + + virtual void readRecord(RecordInputStream& in, Document& document) + { + int32 x = in.readInt32(); + int32 y = in.readInt32(); + int32 z = in.readInt32(); + uint8 edgeFlag = in.readUInt8(); + uint8 shadingFlag = in.readUInt8(); + int colorIndex = (int)in.readInt16(); + osg::Vec3f normal = in.readVec3d(); + + Vertex vertex; + vertex.setCoord(osg::Vec3(x,y,z) * document.unitScale()); + vertex.setNormal(normal / (float)(1L<<30)); + + // color + if (colorIndex >= 0) + vertex.setColor(getColorFromPool(colorIndex, document.getColorPool())); // Color from pool + + // optional texture coordinates + if (in().tellg() < in.getEndOfRecord()) + { + osg::Vec2f uv = in.readVec2f(); + vertex.setUV(uv); + } + + if (_parent.valid()) + _parent->addVertex(vertex); + } +}; + +RegisterRecordProxy g_NormalVertex(OLD_NORMAL_VERTEX_OP); + +} // end namespace diff --git a/src/osgPlugins/OpenFlight/opcodes.h b/src/osgPlugins/OpenFlight/opcodes.h new file mode 100644 index 000000000..d5315cbe3 --- /dev/null +++ b/src/osgPlugins/OpenFlight/opcodes.h @@ -0,0 +1,123 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_OPCODES_H +#define FLT_OPCODES_H + +namespace flt { + +enum Opcodes +{ + UNKNOWN_OP = 0, + HEADER_OP = 1, + GROUP_OP = 2, + OLD_LOD_OP = 3, + OBJECT_OP = 4, + FACE_OP = 5, + OLD_ABSOLUTE_VERTEX_OP = 7, + OLD_SHADED_VERTEX_OP = 8, + OLD_NORMAL_VERTEX_OP = 9, + PUSH_LEVEL_OP = 10, + POP_LEVEL_OP = 11, + DOF_OP = 14, + PUSH_SUBFACE_OP = 19, + POP_SUBFACE_OP = 20, + PUSH_EXTENSION_OP = 21, + POP_EXTENSION_OP = 22, + CONTINUATION_OP = 23, + COMMENT_OP = 31, + COLOR_PALETTE_OP = 32, + LONG_ID_OP = 33, + OLD_TRANSLATE_OP = 40, + OLD_ROTATE_ABOUT_POINT_OP = 41, + OLD_ROTATE_ABOUT_EDGE_OP = 42, + OLD_SCALE_OP = 43, + OLD_TRANSLATE2_OP = 44, + OLD_NONUNIFORM_SCALE_OP = 45, + OLD_ROTATE_ABOUT_POINT2_OP = 46, + OLD_ROTATE_SCALE_TO_POINT_OP = 47, + OLD_PUT_TRANSFORM_OP = 48, + MATRIX_OP = 49, + VECTOR_OP = 50, + OLD_BOUNDING_BOX_OP = 51, + MULTITEXTURE_OP = 52, + UV_LIST_OP = 53, + BINARY_SEPARATING_PLANE_OP = 55, + REPLICATE_OP = 60, + INSTANCE_REFERENCE_OP = 61, + INSTANCE_DEFINITION_OP = 62, + EXTERNAL_REFERENCE_OP = 63, + TEXTURE_PALETTE_OP = 64, + OLD_EYEPOINT_PALETTE_OP = 65, + OLD_MATERIAL_PALETTE_OP = 66, + VERTEX_PALETTE_OP = 67, + VERTEX_C_OP = 68, + VERTEX_CN_OP = 69, + VERTEX_CNT_OP = 70, + VERTEX_CT_OP = 71, + VERTEX_LIST_OP = 72, + LOD_OP = 73, + BOUNDING_BOX_OP = 74, + ROTATE_ABOUT_EDGE_OP = 76, + SCALE_OP = 77, + TRANSLATE_OP = 78, + NONUNIFORM_SCALE_OP = 79, + ROTATE_ABOUT_POINT_OP = 80, + ROTATE_SCALE_TO_POINT_OP = 81, + PUT_TRANSFORM_OP = 82, + EYEPOINT_AND_TRACKPLANE_PALETTE_OP = 83, + MESH_OP = 84, + LOCAL_VERTEX_POOL_OP = 85, + MESH_PRIMITIVE_OP = 86, + ROAD_SEGMENT_OP = 87, + ROAD_ZONE_OP = 88, + MORPH_VERTEX_LIST_OP = 89, + LINKAGE_PALETTE_OP = 90, + SOUND_OP = 91, + ROAD_PATH_OP = 92, + SOUND_PALETTE_OP = 93, + GENERAL_MATRIX_OP = 94, + TEXT_OP = 95, + SWITCH_OP = 96, + LINE_STYLE_PALETTE_OP = 97, + CLIP_REGION_OP = 98, + EXTENSION_OP = 100, + LIGHT_SOURCE_OP = 101, + LIGHT_SOURCE_PALETTE_OP = 102, + BOUNDING_SPHERE_OP = 105, + BOUNDING_CYLINDER_OP = 106, + BOUNDING_CONVEX_HULL_OP = 107, + BOUNDING_VOLUME_CENTER_OP = 108, + BOUNDING_VOLUME_ORIENTATION_OP = 109, + HISTOGRAM_BOUNDING_VOLUME_OP = 110, + LIGHT_POINT_OP = 111, + TEXTURE_MAPPING_PALETTE_OP = 112, + MATERIAL_PALETTE_OP = 113, + NAME_TABLE_OP = 114, + CAT_OP = 115, + CAT_DATA_OP = 116, + BOUNDING_HISTOGRAM = 119, + PUSH_ATTRIBUTE_OP = 122, + POP_ATTRIBUTE_OP = 123, + ADAPTIVE_ATTRIBUTE_OP = 125, + CURVE_NODE_OP = 126, + ROAD_CONSTRUCTION_OP = 127, + LIGHT_POINT_APPEARANCE_PALETTE_OP = 128, + LIGHT_POINT_ANIMATION_PALETTE_OP = 129, + INDEXED_LIGHT_POINT_OP = 130, + LIGHT_POINT_SYSTEM_OP = 131, + INDEXED_STRING_OP = 132, + SHADER_PALETTE_OP = 133 +}; + + +} // end namespace + +#endif + + + + diff --git a/src/osgPlugins/OpenFlight/types.h b/src/osgPlugins/OpenFlight/types.h new file mode 100644 index 000000000..711371ed9 --- /dev/null +++ b/src/osgPlugins/OpenFlight/types.h @@ -0,0 +1,38 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#ifndef FLT_TYPES_H +#define FLT_TYPES_H 1 + +namespace flt { + +#if defined(_MSC_VER) + +typedef __int8 int8; +typedef unsigned __int8 uint8; +typedef __int16 int16; +typedef unsigned __int16 uint16; +typedef __int32 int32; +typedef unsigned __int32 uint32; +typedef float float32; +typedef double float64; + +#else + +typedef signed char int8; +typedef unsigned char uint8; +typedef signed short int16; +typedef unsigned short uint16; +typedef signed int int32; +typedef unsigned int uint32; +typedef float float32; +typedef double float64; + +#endif + +} // end namespace + +#endif diff --git a/src/osgSim/GNUmakefile b/src/osgSim/GNUmakefile index 542c53353..155f74a0b 100644 --- a/src/osgSim/GNUmakefile +++ b/src/osgSim/GNUmakefile @@ -14,6 +14,7 @@ CXXFILES = \ LightPointNode.cpp\ MultiSwitch.cpp\ OverlayNode.cpp\ + OpenFlightOptimizer.cpp\ ScalarBar.cpp\ ScalarsToColors.cpp\ Sector.cpp\ diff --git a/src/osgSim/OpenFlightOptimizer.cpp b/src/osgSim/OpenFlightOptimizer.cpp new file mode 100644 index 000000000..ad714edd7 --- /dev/null +++ b/src/osgSim/OpenFlightOptimizer.cpp @@ -0,0 +1,239 @@ +// +// OpenFlightŪ loader for OpenSceneGraph +// +// Copyright (C) 2005-2006 Brede Johansen +// + +#include + +#include +#include + +#include +#include + +#include +#include + +using namespace osgFlightUtil; + + +void Optimizer::optimize(osg::Node* node) +{ + unsigned int options = 0; + + const char* env = getenv("OSG_FLIGHTUTIL_OPTIMIZER"); + if (env) + { + std::string str(env); + + if(str.find("OFF")!=std::string::npos) options = 0; + + if(str.find("~DEFAULT")!=std::string::npos) options ^= DEFAULT_OPTIMIZATIONS; + else if(str.find("DEFAULT")!=std::string::npos) options |= DEFAULT_OPTIMIZATIONS; + + if(str.find("~TESSELATE_POLYGON")!=std::string::npos) options ^= TESSELATE_POLYGON; + else if(str.find("TESSELATE_POLYGON")!=std::string::npos) options |= TESSELATE_POLYGON; + + if(str.find("~MAKE_LIT")!=std::string::npos) options ^= MAKE_LIT; + else if(str.find("MAKE_LIT")!=std::string::npos) options |= MAKE_LIT; + + if(str.find("~MERGE_GEODES")!=std::string::npos) options ^= MERGE_GEODES; + else if(str.find("MERGE_GEODES")!=std::string::npos) options |= MERGE_GEODES; + } + else + { + options = DEFAULT_OPTIMIZATIONS; + } + + optimize(node,options); +} + +void Optimizer::optimize(osg::Node* node, unsigned int options) +{ + if (options & TESSELATE_POLYGON) + { + osg::notify(osg::INFO)<<"osgFlightUtil::Optimizer::optimize() doing TESSELATE_POLYGON"<accept(visitor); + } + + if (options & MAKE_LIT) + { + osg::notify(osg::INFO)<<"osgFlightUtil::Optimizer::optimize() doing MAKE_LIT"<accept(visitor); + } + + if (options & MERGE_GEODES) + { + osg::notify(osg::INFO)<<"osgFlightUtil::Optimizer::optimize() doing MERGE_GEODES"<accept(visitor); + } +} + + +void Optimizer::TesselateVisitor::apply(osg::Geode& geode) +{ + for (unsigned int i=0; i(geode.getDrawable(i)); + if (geometry) + { + if (hasPolygons(*geometry)) + { + // Tesselate + osgUtil::Tesselator tesselator; + tesselator.retesselatePolygons(*geometry); + } + } + } +} + +bool Optimizer::TesselateVisitor::hasPolygons(osg::Geometry& geometry) +{ + for (unsigned int i=0; igetMode() == osg::PrimitiveSet::POLYGON) + return true; + } + + return false; +} + + +void Optimizer::MakeLitVisitor::apply(osg::Geode& /*geode*/) +{ +#if 0 // TODO + osg::StateSet* stateset = geode.getStateSet(); + if (stateset) + { + // Not lit? + if (!(stateset->getMode(GL_LIGHTING)&osg::StateAttribute::ON)) + { + stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON); + for (unsigned int i=0; i(geode.getDrawable(i)); + if (geometry) + { + if () TODO Compare vertex array length and normal array length + normal binding. + { + // generate normals + osgUtil::SmoothingVisitor smoother; + smoother.smooth(*geometry); + } + } + } + } + } +#endif +} + +/** Need to share stateset before merging geodes. + */ +class GeodeStateOptimizer : public osgUtil::Optimizer::StateVisitor +{ + public: + + GeodeStateOptimizer(): + osgUtil::Optimizer::StateVisitor() {} + + void optimize(osg::Group& group) + { + for (unsigned int i=0; igetStateSet(),geode); + } + } + + osgUtil::Optimizer::StateVisitor::optimize(); + } + + +}; + + +void Optimizer::MergeGeodesVisitor::apply(osg::Group& group) +{ + mergeGeodes(group); + traverse(group); +} + + +// Requires shared stateset to work. Run GeodeStateOptimizer before MergeGeodesVisitor. +struct LessGeode +{ + bool operator() (const osg::Geode* lhs,const osg::Geode* rhs) const + { + if (lhs->getStateSet()getStateSet()) return true; +// if (rhs->getStateSet()getStateSet()) return false; + return false; + } +}; + +void Optimizer::MergeGeodesVisitor::mergeGeodes(osg::Group& group) +{ + { + GeodeStateOptimizer gsopt; + gsopt.optimize(group); + } + + typedef std::vector DuplicateList; + typedef std::map GeodeDuplicateMap; + + GeodeDuplicateMap geodeDuplicateMap; + + for (unsigned int i=0; isecond.size()>1) + { + osg::Geode* lhs = itr->second[0]; + for(DuplicateList::iterator dupItr=itr->second.begin()+1; + dupItr!=itr->second.end(); + ++dupItr) + { + osg::Geode* rhs = *dupItr; + + if (mergeGeode(*lhs,*rhs)) + { + group.removeChild(rhs); + + static int co = 0; + osg::notify(osg::INFO)<<"merged and removed Geode "<<++co< +#include +#include + +#include +#include +#include +#include + +// Must undefine IN and OUT macros defined in Windows headers +#ifdef IN +#undef IN +#endif +#ifdef OUT +#undef OUT +#endif + +BEGIN_ENUM_REFLECTOR(osgFlightUtil::Optimizer::OptimizationOptions) + I_EnumLabel(osgFlightUtil::Optimizer::TESSELATE_POLYGON); + I_EnumLabel(osgFlightUtil::Optimizer::MERGE_GEODES); + I_EnumLabel(osgFlightUtil::Optimizer::MAKE_LIT); + I_EnumLabel(osgFlightUtil::Optimizer::DEFAULT_OPTIMIZATIONS); + I_EnumLabel(osgFlightUtil::Optimizer::ALL_OPTIMIZATIONS); +END_REFLECTOR + +BEGIN_VALUE_REFLECTOR(osgFlightUtil::Optimizer) + I_Constructor0(); + I_Method1(void, optimize, IN, osg::Node *, node); + I_Method2(void, optimize, IN, osg::Node *, node, IN, unsigned int, options); +END_REFLECTOR + +BEGIN_OBJECT_REFLECTOR(osgFlightUtil::Optimizer::MakeLitVisitor) + I_BaseType(osg::NodeVisitor); + I_Constructor0(); + I_Method1(void, apply, IN, osg::Geode &, geode); +END_REFLECTOR + +BEGIN_OBJECT_REFLECTOR(osgFlightUtil::Optimizer::MergeGeodesVisitor) + I_BaseType(osg::NodeVisitor); + I_Constructor0(); + I_Method1(void, apply, IN, osg::Group &, group); + I_Method1(void, mergeGeodes, IN, osg::Group &, group); +END_REFLECTOR + +BEGIN_OBJECT_REFLECTOR(osgFlightUtil::Optimizer::TesselateVisitor) + I_BaseType(osg::NodeVisitor); + I_Constructor0(); + I_Method1(void, apply, IN, osg::Geode &, geode); +END_REFLECTOR +