Fixes for IRIX and Boris Bralo's TerraPage loader.
This commit is contained in:
3
AUTHORS
3
AUTHORS
@@ -83,6 +83,9 @@ Paul Fredrikson
|
||||
Phil Atkin <philatkin@philatkin.com>
|
||||
- MacOS X port.
|
||||
|
||||
Boris Bralo
|
||||
- txp TerraPage loader.
|
||||
|
||||
Sasa Bistrivic <sasa.bistrovic@zg.hinet.hr>
|
||||
- option for detailed calculation of the near clipping plane during cull traversal.
|
||||
|
||||
|
||||
6
Makefile
6
Makefile
@@ -6,7 +6,11 @@ DIRS = src
|
||||
|
||||
VERSION = osg-0.8.43
|
||||
|
||||
export OSGHOME := $(shell pwd)
|
||||
ifeq (IRIX|IRIX64,true)
|
||||
export OSGHOME = `pwd`
|
||||
else
|
||||
export OSGHOME := $(shell pwd)
|
||||
endif
|
||||
|
||||
all : $(MAKE_PREP)
|
||||
for f in $(DIRS) ; do cd $$f; $(MAKE) || exit 1; cd ..; done
|
||||
|
||||
@@ -96,6 +96,24 @@ Package=<4>
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "txp"=".\osgPlugins\txp\txp.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name osg
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name osgDB
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "gif"=".\osgPlugins\gif\gif.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
|
||||
215
VisualStudio/osgPlugins/txp/txp.dsp
Normal file
215
VisualStudio/osgPlugins/txp/txp.dsp
Normal file
@@ -0,0 +1,215 @@
|
||||
# Microsoft Developer Studio Project File - Name="txp" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=txp - Win32 Debug
|
||||
!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 "txp.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 "txp.mak" CFG="txp - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "txp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "txp - 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)" == "txp - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TXP_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TXP_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x41a /d "NDEBUG"
|
||||
# ADD RSC /l 0x41a /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 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 /out:"../../../bin/osgdb_txp.dll"
|
||||
|
||||
!ELSEIF "$(CFG)" == "txp - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "../../../lib"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TXP_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /vmg /vd0 /GR /GX /Zi /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TXP_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x41a /d "_DEBUG"
|
||||
# ADD RSC /l 0x41a /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 osgd.lib osgdbd.lib /nologo /dll /debug /machine:I386 /out:"../../../bin/osgdb_txpd.dll" /pdbtype:sept /libpath:"f:/osgcvs/openscenegraph/lib/"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "txp - Win32 Release"
|
||||
# Name "txp - 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\txp\ReaderWriterTXP.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_basic.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_geom.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_header.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_material.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_model.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_nodes.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_parse.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_rarchive.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_readbuf.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_swap.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_tile.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_warchive.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_writebuf.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\TrPageArchive.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\TrPageParser.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\ReaderWriterTXP.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trdll.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_geom.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_ident.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_io.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_read.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_scene.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_swap.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_sys.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\trpage_write.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\TrPageArchive.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\TrPageParser.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
|
||||
@@ -83,7 +83,7 @@ class SG_EXPORT Billboard : public Geode
|
||||
struct ComputeBillboardCallback : public osg::Referenced
|
||||
{
|
||||
/** Get the transformation matrix which moves from local coords to world coords.*/
|
||||
virtual void computeMatrix(const Matrix& matrix, const Billboard* billboard, const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local) const;
|
||||
virtual const bool computeMatrix(const Matrix& matrix, const Billboard* billboard, const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local) const;
|
||||
};
|
||||
|
||||
friend struct osg::Billboard::ComputeBillboardCallback;
|
||||
@@ -99,7 +99,7 @@ class SG_EXPORT Billboard : public Geode
|
||||
const ComputeBillboardCallback* getComputeBillboardCallback() const { return _computeBillboardCallback.get(); }
|
||||
|
||||
|
||||
inline void getMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local) const
|
||||
inline const bool getMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local) const
|
||||
{
|
||||
if (_computeBillboardCallback.valid())
|
||||
return _computeBillboardCallback->computeMatrix(matrix,this,eye_local,up_local,pos_local);
|
||||
@@ -113,7 +113,7 @@ class SG_EXPORT Billboard : public Geode
|
||||
|
||||
virtual const bool computeBound() const;
|
||||
|
||||
virtual void computeMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local) const;
|
||||
virtual const bool computeMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local) const;
|
||||
|
||||
enum AxisAligned
|
||||
{
|
||||
|
||||
@@ -79,6 +79,7 @@ class SG_EXPORT Statistics : public osg::Referenced, public osg::Drawable::Attri
|
||||
primverts[0] += (end-begin);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void addNumPrims(const int typ, const int nprimlen, const int numprimtype, const int primvert)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace osgGLUT
|
||||
* but shouldn't be viewed as the be all and end of osg viewer classes.
|
||||
* Someone please rewrite it :-)
|
||||
*/
|
||||
class OSGGLUT_EXPORT Viewer : public Window, osgUtil::GUIActionAdapter
|
||||
class OSGGLUT_EXPORT Viewer : public Window, public osgUtil::GUIActionAdapter
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class OSGTEXT_EXPORT Font : public osg::Object
|
||||
|
||||
Font();
|
||||
Font(const Font& font,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
|
||||
Object(font,copyop),
|
||||
osg::Object(font,copyop),
|
||||
_init(false),
|
||||
_created(false),
|
||||
_font(0L),
|
||||
|
||||
@@ -28,7 +28,7 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
|
||||
|
||||
|
||||
RenderStage();
|
||||
virtual osg::Object* cloneType(const osg::CopyOp&) const { return new RenderStage(); }
|
||||
virtual osg::Object* cloneType() const { return new RenderStage(); }
|
||||
virtual osg::Object* clone(const osg::CopyOp&) const { return new RenderStage(); } // note only implements a clone of type.
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const RenderStage*>(obj)!=0L; }
|
||||
virtual const char* className() const { return "RenderStage"; }
|
||||
|
||||
@@ -98,7 +98,7 @@ const bool Billboard::removeDrawable( Drawable *gset )
|
||||
return false;
|
||||
}
|
||||
|
||||
void Billboard::computeMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3& /*up_local*/, const Vec3& pos_local) const
|
||||
const bool Billboard::computeMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3& /*up_local*/, const Vec3& pos_local) const
|
||||
{
|
||||
|
||||
Vec3 ev(pos_local-eye_local);
|
||||
@@ -161,6 +161,8 @@ void Billboard::computeMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3&
|
||||
|
||||
matrix.setTrans(pos_local);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
const bool Billboard::computeBound() const
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
#if defined(__sgi)
|
||||
#include <cctype.h>
|
||||
#include <ctype.h>
|
||||
#elif !defined(WIN32)
|
||||
#include <cctype>
|
||||
using std::tolower;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!smake
|
||||
SHELL=/bin/sh
|
||||
|
||||
DIRS = osg rgb lib3ds flt obj lwo dw bmp pic tga osgtgz tgz zip
|
||||
DIRS = osg rgb lib3ds flt obj lwo txp dw bmp pic tga osgtgz tgz zip
|
||||
|
||||
# comment in if you have Performer installed.
|
||||
# DIRS += pfb
|
||||
|
||||
38
src/osgPlugins/txp/Makefile
Normal file
38
src/osgPlugins/txp/Makefile
Normal file
@@ -0,0 +1,38 @@
|
||||
#!smake
|
||||
include $(OSGHOME)/Make/makedefs
|
||||
|
||||
C++FILES = \
|
||||
ReaderWriterTXP.cpp\
|
||||
TrPageArchive.cpp\
|
||||
TrPageParser.cpp\
|
||||
trpage_basic.cpp\
|
||||
trpage_geom.cpp\
|
||||
trpage_header.cpp\
|
||||
trpage_tile.cpp\
|
||||
trpage_readbuf.cpp\
|
||||
trpage_rarchive.cpp\
|
||||
trpage_writebuf.cpp\
|
||||
trpage_warchive.cpp\
|
||||
trpage_parse.cpp\
|
||||
trpage_nodes.cpp\
|
||||
trpage_model.cpp\
|
||||
trpage_material.cpp\
|
||||
|
||||
|
||||
TARGET_BASENAME = osgdb_txp
|
||||
|
||||
TARGET_LIB_FILES = lib$(TARGET_BASENAME).$(DL_EXT)
|
||||
|
||||
LIB =
|
||||
LOADABLE = $(OSGHOME)/lib/osgPlugins/$(TARGET_BASENAME).$(DL_EXT)
|
||||
|
||||
TARGET_LOADER_FILES = osgPlugins/$(TARGET_BASENAME).$(DL_EXT)
|
||||
|
||||
LIBS = $(GL_LIBS) -losg -losgDB
|
||||
MACOSXLIBS = -L$(OSGHOME)/lib -losg -losgDB -lstdc++
|
||||
|
||||
C++FLAGS += -I. -I$(OSGHOME)/include
|
||||
LDFLAGS += -L$(OSGHOME)/lib
|
||||
|
||||
include $(OSGHOME)/Make/makerules
|
||||
|
||||
93
src/osgPlugins/txp/ReaderWriterTXP.cpp
Normal file
93
src/osgPlugins/txp/ReaderWriterTXP.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "ReaderWriterTXP.h"
|
||||
#include "TrPageArchive.h"
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Object>
|
||||
#include <osg/Node>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/FileUtils>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace txp;
|
||||
using namespace osg;
|
||||
//----------------------------------------------------------------------------
|
||||
// private class for txp file
|
||||
class TXPFile
|
||||
{
|
||||
public:
|
||||
TrPageArchive archive;
|
||||
|
||||
TXPFile()
|
||||
{
|
||||
};
|
||||
|
||||
~TXPFile()
|
||||
{
|
||||
};
|
||||
|
||||
Node* readNode(const string &filename)
|
||||
{
|
||||
Group* ret = 0;
|
||||
// search the SGL data path
|
||||
string foundname = osgDB::findFile(filename.c_str());
|
||||
if( !foundname.empty())
|
||||
{
|
||||
if (archive.OpenFile(foundname))
|
||||
{
|
||||
notify(INFO) << "TXPFile::loadFile(): loading archive: "
|
||||
<< foundname << std::endl;
|
||||
archive.LoadMaterials();
|
||||
archive.LoadModels();
|
||||
|
||||
notify(INFO) << "TXPFile::loadFile(): loading geometry"
|
||||
<< std::endl;
|
||||
|
||||
ret = new Group;
|
||||
ret->addChild(archive.LoadAllTiles());
|
||||
|
||||
notify(INFO) << "TXPFile::loadFile(): loaded archive: "
|
||||
<< foundname << std::endl;
|
||||
//sgluOutputTree(sceneGraph, cout, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN) << "Failed to load archive: " << foundname << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
notify(WARN) <<"sglTrPageGroup::loadFile() failed to find archive: "
|
||||
<< foundname << std::endl;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
Object* readObject(const string &filename)
|
||||
{
|
||||
return readNode(filename);
|
||||
};
|
||||
};
|
||||
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readObject(const std::string& fileName, const osgDB::ReaderWriter::Options*)
|
||||
{
|
||||
TXPFile read;
|
||||
|
||||
Object* obj = read.readObject(fileName);
|
||||
if (obj) return obj;
|
||||
else return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*)
|
||||
{
|
||||
TXPFile read;
|
||||
Node* node = read.readNode(fileName);
|
||||
if (node) return node;
|
||||
else return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
osgDB::RegisterReaderWriterProxy<ReaderWriterTXP> g_txpReaderWriterProxy;
|
||||
|
||||
50
src/osgPlugins/txp/ReaderWriterTXP.h
Normal file
50
src/osgPlugins/txp/ReaderWriterTXP.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*****************************************************************************
|
||||
* Reader for Terrex TerraPage File format for OpenSceneGraph Library
|
||||
*
|
||||
* Copyright (C) 2002 Boris Bralo All Rights Reserved.
|
||||
*
|
||||
* based on code from Scene Graph Library:
|
||||
* Copyright (C) Bryan Walsh All Rights Reserved.
|
||||
* and Terrex
|
||||
* Copyright Terrain Experts Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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 GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef READER_WRITER_TXP_H
|
||||
#define READER_WRITER_TXP_H
|
||||
|
||||
#include "trpage_sys.h"
|
||||
#include <osg/Object>
|
||||
#include <osg/Node>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
namespace txp
|
||||
{
|
||||
class ReaderWriterTXP : public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
virtual const char* className() { return "TXP Reader/Writer"; }
|
||||
virtual bool acceptsExtension(const std::string& extension)
|
||||
{
|
||||
return osgDB::equalCaseInsensitive(extension,"txp");
|
||||
}
|
||||
virtual ReadResult readObject(const std::string& fileName, const osgDB::ReaderWriter::Options*);
|
||||
virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*);
|
||||
};
|
||||
}; // namespace
|
||||
#endif
|
||||
358
src/osgPlugins/txp/TrPageArchive.cpp
Normal file
358
src/osgPlugins/txp/TrPageArchive.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
#include "TrPageArchive.h"
|
||||
#include "TrPageParser.h"
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Image>
|
||||
#include <osg/Texture>
|
||||
#include <osg/Material>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/Transparency>
|
||||
#include <osg/CullFace>
|
||||
#include <osg/Light>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/Notify>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <iostream>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
#include "trpage_geom.h"
|
||||
#include "trpage_read.h"
|
||||
#include "trpage_write.h"
|
||||
#include "trpage_scene.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace txp;
|
||||
using namespace osg;
|
||||
|
||||
TrPageArchive::TrPageArchive()
|
||||
: trpgr_Archive()
|
||||
, parse(new TrPageParser())
|
||||
{
|
||||
}
|
||||
|
||||
TrPageArchive::~TrPageArchive()
|
||||
{
|
||||
}
|
||||
|
||||
bool TrPageArchive::OpenFile(const string &file)
|
||||
{
|
||||
m_alternate_path = osgDB::getFilePath(file);
|
||||
std::string name = osgDB::getSimpleFileName(file);
|
||||
|
||||
if(m_alternate_path.empty())
|
||||
SetDirectory(".");
|
||||
else
|
||||
{
|
||||
osgDB::setFilePath(m_alternate_path.c_str());
|
||||
SetDirectory(m_alternate_path.c_str());
|
||||
}
|
||||
|
||||
if (!trpgr_Archive::OpenFile(name.c_str()))
|
||||
{
|
||||
notify(WARN) << "TrPageArchive::OpenFile() error: "
|
||||
<< "couldn't open archive: " << file << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (!ReadHeader())
|
||||
{
|
||||
notify(WARN) << "TrPageArchive::OpenFile() error: "
|
||||
<< "couldn't read header for archive: " << file
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the max group ID here because it won't change
|
||||
const trpgHeader *head = GetHeader();
|
||||
int maxID;
|
||||
head->GetMaxGroupID(maxID);
|
||||
parse->SetMaxGroupID(maxID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// load textures and materials
|
||||
// TODO : multitexturing
|
||||
void TrPageArchive::LoadMaterials()
|
||||
{
|
||||
int n_textures;
|
||||
texTable.GetNumTextures(n_textures);
|
||||
|
||||
m_textures.resize(n_textures);
|
||||
|
||||
// these extra braces are workaroud for annoying bug in MSVC
|
||||
// for( int i = ....) and i is visible outside the loop
|
||||
{
|
||||
for (int i=0; i < n_textures ; i++)
|
||||
{
|
||||
trpgTexture *tex;
|
||||
tex = texTable.GetTextureRef(i);
|
||||
char texName[1024]; texName[0] = 0;
|
||||
tex->GetName(texName,1023);
|
||||
// Create a texture by name.
|
||||
Texture *osg_texture = new Texture();
|
||||
|
||||
// Load Texture and Create Texture State
|
||||
std::string filename = osgDB::getSimpleFileName(texName);
|
||||
std::string path(getDir());
|
||||
std::string theFile = path + '/'+ filename ;
|
||||
ref_ptr<Image> image = osgDB::readImageFile(theFile);
|
||||
if (image.valid())
|
||||
{
|
||||
osg_texture->setImage(image.get());
|
||||
}
|
||||
m_textures[i] = osg_texture;
|
||||
}
|
||||
}
|
||||
|
||||
// create materials
|
||||
int n_materials;
|
||||
materialTable.GetNumMaterial(n_materials);
|
||||
|
||||
{
|
||||
for (int i = 0; i < n_materials; i++)
|
||||
{
|
||||
StateSet* osg_state_set = new StateSet;
|
||||
|
||||
trpgMaterial *mat;
|
||||
mat = materialTable.GetMaterialRef(0,i);
|
||||
// Set texture
|
||||
int numMatTex;
|
||||
mat->GetNumTexture(numMatTex);
|
||||
|
||||
// TODO : multitextuting
|
||||
// also note that multitexturing in terrapage can came from two sides
|
||||
// - multiple textures per material, and multiple materials per geometry
|
||||
if(numMatTex)
|
||||
{
|
||||
int texId;
|
||||
trpgTextureEnv texEnv;
|
||||
mat->GetTexture(0,texId,texEnv);
|
||||
|
||||
// Set up texture environment
|
||||
TexEnv *osg_texenv = new TexEnv();
|
||||
int32 te_mode;
|
||||
texEnv.GetEnvMode(te_mode);
|
||||
switch( te_mode )
|
||||
{
|
||||
case trpgTextureEnv::Alpha :
|
||||
osg_texenv->setMode(TexEnv::REPLACE);
|
||||
break;
|
||||
case trpgTextureEnv::Decal:
|
||||
osg_texenv->setMode(TexEnv::DECAL);
|
||||
break;
|
||||
case trpgTextureEnv::Blend :
|
||||
osg_texenv->setMode(TexEnv::BLEND);
|
||||
break;
|
||||
case trpgTextureEnv::Modulate :
|
||||
osg_texenv->setMode(TexEnv::MODULATE);
|
||||
break;
|
||||
}
|
||||
|
||||
osg_state_set->setAttribute(osg_texenv);
|
||||
|
||||
Material *osg_material = new Material;
|
||||
|
||||
float64 alpha;
|
||||
mat->GetAlpha(alpha);
|
||||
|
||||
trpgColor color;
|
||||
mat->GetAmbient(color);
|
||||
osg_material->setAmbient( Material::FRONT_AND_BACK ,
|
||||
Vec4(color.red, color.green, color.blue, alpha));
|
||||
mat->GetDiffuse(color);
|
||||
osg_material->setDiffuse(Material::FRONT_AND_BACK ,
|
||||
Vec4(color.red, color.green, color.blue, alpha));
|
||||
|
||||
mat->GetSpecular(color);
|
||||
osg_material->setSpecular(Material::FRONT_AND_BACK ,
|
||||
Vec4(color.red, color.green, color.blue, alpha));
|
||||
mat->GetEmission(color);
|
||||
osg_material->setEmission(Material::FRONT_AND_BACK ,
|
||||
Vec4(color.red, color.green, color.blue, alpha));
|
||||
|
||||
float64 shinines;
|
||||
mat->GetShininess(shinines);
|
||||
osg_material->setShininess(Material::FRONT_AND_BACK , (float)shinines/128.0);
|
||||
|
||||
osg_material->setAlpha(Material::FRONT_AND_BACK ,(float)alpha);
|
||||
osg_state_set->setAttributeAndModes(osg_material, StateAttribute::ON);
|
||||
|
||||
if( alpha < 1.0f )
|
||||
{
|
||||
osg_state_set->setMode(GL_BLEND,StateAttribute::ON);
|
||||
osg_state_set->setRenderingHint(StateSet::TRANSPARENT_BIN);
|
||||
}
|
||||
|
||||
/*
|
||||
int alphaFunc;
|
||||
mat->GetAlphaFunc(alphaFunc);
|
||||
*/
|
||||
|
||||
// transparency
|
||||
Transparency *osg_transparency = new Transparency;
|
||||
osg_transparency->setFunction(Transparency::SRC_ALPHA, Transparency::ONE_MINUS_SRC_ALPHA);
|
||||
osg_state_set->setAttributeAndModes(osg_transparency, StateAttribute::ON);
|
||||
|
||||
int wrap_s, wrap_t;
|
||||
texEnv.GetWrap(wrap_s, wrap_t);
|
||||
|
||||
Texture* osg_texture = m_textures[texId].get();
|
||||
osg_texture->setWrap(Texture::WRAP_S, wrap_s == trpgTextureEnv::Repeat ? Texture::REPEAT: Texture::CLAMP );
|
||||
osg_texture->setWrap(Texture::WRAP_T, wrap_t == trpgTextureEnv::Repeat ? Texture::REPEAT: Texture::CLAMP );
|
||||
osg_state_set->setAttributeAndModes(osg_texture, StateAttribute::ON);
|
||||
|
||||
if(osg_texture->getImage())
|
||||
{
|
||||
switch (osg_texture->getImage()->pixelFormat())
|
||||
{
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
case GL_RGBA:
|
||||
osg_state_set->setMode(GL_BLEND,StateAttribute::ON);
|
||||
osg_state_set->setRenderingHint(StateSet::TRANSPARENT_BIN);
|
||||
}
|
||||
}
|
||||
|
||||
int cullMode;
|
||||
mat->GetCullMode(cullMode);
|
||||
|
||||
// Culling mode in txp means opposite from osg i.e. Front-> show front face
|
||||
if( cullMode != trpgMaterial::FrontAndBack)
|
||||
{
|
||||
CullFace* cull_face = new CullFace;
|
||||
switch (cullMode)
|
||||
{
|
||||
case trpgMaterial::Front:
|
||||
cull_face->setMode(CullFace::BACK);
|
||||
break;
|
||||
case trpgMaterial::Back:
|
||||
cull_face->setMode(CullFace::FRONT);
|
||||
break;
|
||||
}
|
||||
osg_state_set->setAttributeAndModes(cull_face, StateAttribute::ON);
|
||||
}
|
||||
}
|
||||
m_gstates.push_back(osg_state_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TrPageArchive::LoadModels()
|
||||
{
|
||||
int numModel;
|
||||
modelTable.GetNumModels(numModel);
|
||||
|
||||
// Iterate over the models
|
||||
for (int i=0; i< numModel; i++)
|
||||
{
|
||||
trpgModel *mod = modelTable.GetModelRef(i);
|
||||
int type;
|
||||
mod->GetType(type);
|
||||
|
||||
// Only dealing with external models currently
|
||||
if (type == trpgModel::External)
|
||||
{
|
||||
char name[1024];
|
||||
mod->GetName(name,1023);
|
||||
|
||||
// Load the model. It's probably not TerraPage
|
||||
Node *osg_model = osgDB::readNodeFile(name);
|
||||
if (!osg_model)
|
||||
{
|
||||
notify(WARN) << "TrPageArchive::LoadModels() error: "
|
||||
<< "failed to load model: "
|
||||
<< name << std::endl;
|
||||
}
|
||||
// Do this even if it's NULL
|
||||
m_models.push_back(osg_model);
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
trpgMemReadBuffer buf(GetEndian());
|
||||
mod->Read(buf);
|
||||
Group *osg_model = parse->ParseScene(buf, m_gstates , m_models);
|
||||
m_models.push_back(osg_model);
|
||||
}
|
||||
*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Group* TrPageArchive::LoadTile(int x,int y,int lod,int &parentID)
|
||||
{
|
||||
trpgMemReadBuffer buf(GetEndian());
|
||||
|
||||
// Read the tile data in, but don't parse it
|
||||
if (!ReadTile(x,y,lod,buf))
|
||||
return NULL;
|
||||
|
||||
// Call the parser
|
||||
Group *tile = parse->ParseScene(buf, m_gstates , m_models);
|
||||
if (tile)
|
||||
{
|
||||
parentID = parse->GetParentID();
|
||||
// This is where you would page in textures and models
|
||||
}
|
||||
|
||||
// That's it
|
||||
return tile;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Group* TrPageArchive::LoadAllTiles()
|
||||
{
|
||||
// Size information comes out of the header
|
||||
const trpgHeader *head = GetHeader();
|
||||
// Create one group as the top
|
||||
Group *topGroup = new Group;
|
||||
|
||||
int32 numLod;
|
||||
head->GetNumLods(numLod);
|
||||
// Iterate over the LODs. Lower res LODs must be loaded
|
||||
// first, otherwise there's nothing to hook the higher res
|
||||
// LODs into.
|
||||
trpg2iPoint tileSize;
|
||||
|
||||
// The group list is used to map parent IDs to pfGroup nodes
|
||||
std::vector<Group *> *groupList = parse->GetGroupList();
|
||||
|
||||
for (int nl=0;nl<numLod;nl++)
|
||||
{
|
||||
// The number of tiles in X and Y changes per LOD
|
||||
head->GetLodSize(nl,tileSize);
|
||||
for (int x=0; x < tileSize.x; x++)
|
||||
{
|
||||
for (int y=0; y < tileSize.y; y++)
|
||||
{
|
||||
int parentID;
|
||||
Group *tile = LoadTile(x,y,nl,parentID);
|
||||
if (!tile)
|
||||
{
|
||||
notify(WARN)<< "TrPageArchive::LoadAllTiles error: "
|
||||
<< "failed to load tile ("
|
||||
<< x << "," << y << "," << nl << ")"
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parentID == -1)
|
||||
{
|
||||
// Get added to the top level node
|
||||
topGroup->addChild(tile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Added below some other node
|
||||
(*groupList)[parentID]->addChild(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return topGroup;
|
||||
}
|
||||
86
src/osgPlugins/txp/TrPageArchive.h
Normal file
86
src/osgPlugins/txp/TrPageArchive.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* **************************************************************************
|
||||
* OpenSceneGraph loader for Terrapage format database
|
||||
* by Boris Bralo 2002
|
||||
*
|
||||
* based on/modifed sgl (Scene Graph Library) loader by Bryan Walsh
|
||||
*
|
||||
* This loader is based on/modified from Terrain Experts Performer Loader,
|
||||
* and was ported to SGL by Bryan Walsh / bryanw at earthlink dot net
|
||||
*
|
||||
* That loader is redistributed under the terms listed on Terrain Experts
|
||||
* website (www.terrex.com/www/pages/technology/technologypage.htm)
|
||||
*
|
||||
* "TerraPage is provided as an Open Source format for use by anyone...
|
||||
* We supply the TerraPage C++ source code free of charge. Anyone
|
||||
* can use it and redistribute it as needed (including our competitors).
|
||||
* We do, however, ask that you keep the TERREX copyrights intact."
|
||||
*
|
||||
* Copyright Terrain Experts Inc. 1999.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TRPAGEARCHIVE_H_
|
||||
#define _TRPAGEARCHIVE_H_
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory> // for auto_ptr
|
||||
#include "trpage_sys.h"
|
||||
#include "trpage_read.h"
|
||||
#include <osg/GeoSet>
|
||||
|
||||
#include "TrPageParser.h"
|
||||
|
||||
namespace txp
|
||||
{
|
||||
/// main class for loading terrapage archives
|
||||
class TrPageArchive : public trpgr_Archive
|
||||
{
|
||||
public:
|
||||
TrPageArchive();
|
||||
|
||||
~TrPageArchive();
|
||||
|
||||
// open archive file
|
||||
bool OpenFile(const std::string& filename);
|
||||
|
||||
/// Load and create textures and materials
|
||||
void LoadMaterials();
|
||||
|
||||
// Load and create models, usualy OpenFlight models
|
||||
bool LoadModels();
|
||||
|
||||
/** Load a TXP tile and
|
||||
@param x Tile location input - x dimension.
|
||||
@param y Tile location input - y dimension.
|
||||
@param lod Tile LOD level input.
|
||||
@return The parent ID of this tile to let you hook it into the scene
|
||||
graph.
|
||||
|
||||
x, y dimensions are not coordinates, they are tile numbers. For example,
|
||||
for combination 10, 1 and lod number 2 terrapage opens file tile_10_1_2.tpt
|
||||
in directory of the archive. This is THE method which shoud be used once
|
||||
paging is implemented.
|
||||
|
||||
*/
|
||||
osg::Group *LoadTile(int x,int y,int lod,int &parent);
|
||||
|
||||
/** Load all the tiles . No paging.
|
||||
@return The parent of the complete scene graph.
|
||||
*/
|
||||
osg::Group *LoadAllTiles();
|
||||
|
||||
protected:
|
||||
/// This class does most of the actual parsing.
|
||||
std::auto_ptr<TrPageParser> parse;
|
||||
// Texture, material, and model lists.
|
||||
std::vector< osg::ref_ptr<osg::Texture> > m_textures;
|
||||
std::vector< osg::ref_ptr<osg::StateSet> > m_gstates;
|
||||
std::vector< osg::ref_ptr<osg::Node> > m_models;
|
||||
std::string m_alternate_path;
|
||||
};
|
||||
}; // end namespace
|
||||
|
||||
#endif
|
||||
533
src/osgPlugins/txp/TrPageParser.cpp
Normal file
533
src/osgPlugins/txp/TrPageParser.cpp
Normal file
@@ -0,0 +1,533 @@
|
||||
/* **************************************************************************
|
||||
* OpenSceneGraph loader for Terrapage format database
|
||||
* by Boris Bralo 2002
|
||||
*
|
||||
* based on/modifed sgl (Scene Graph Library) loader by Brian Walsh
|
||||
*
|
||||
* This loader is based on/modified from Terrain Experts Performer Loader,
|
||||
* and was ported to SGL by Bryan Walsh / bryanw at earthlink dot net
|
||||
*
|
||||
* That loader is redistributed under the terms listed on Terrain Experts
|
||||
* website (www.terrex.com/www/pages/technology/technologypage.htm)
|
||||
*
|
||||
* "TerraPage is provided as an Open Source format for use by anyone...
|
||||
* We supply the TerraPage C++ source code free of charge. Anyone
|
||||
* can use it and redistribute it as needed (including our competitors).
|
||||
* We do, however, ask that you keep the TERREX copyrights intact."
|
||||
*
|
||||
* Copyright Terrain Experts Inc. 1999.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "trpage_sys.h"
|
||||
#include <osg/Group>
|
||||
#include <osg/Material>
|
||||
#include <osg/Texture>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/LOD>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Transform>
|
||||
#include <osg/GeoSet>
|
||||
#include <osg/CullFace>
|
||||
#include <osg/Light>
|
||||
#include <osg/Transparency>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include "TrPageParser.h"
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
*/
|
||||
#include <algorithm>
|
||||
|
||||
using namespace txp;
|
||||
using namespace osg;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
geomRead::geomRead(TrPageParser *in_parse)
|
||||
{
|
||||
parse = in_parse;
|
||||
}
|
||||
|
||||
geomRead::~geomRead()
|
||||
{
|
||||
}
|
||||
|
||||
void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
|
||||
{
|
||||
trpgGeometry geom;
|
||||
if (!geom.Read(buf))
|
||||
return NULL;
|
||||
|
||||
// Get the necessary info out of the geom
|
||||
trpgGeometry::PrimType primType;
|
||||
int numPrims;
|
||||
int numVert;
|
||||
int numNorm;
|
||||
int matId;
|
||||
geom.GetPrimType(primType);
|
||||
geom.GetNumPrims(numPrims);
|
||||
geom.GetNumVertex(numVert);
|
||||
numVert /= 3;
|
||||
geom.GetMaterial(0,matId);
|
||||
geom.GetNumNormal(numNorm);
|
||||
numNorm /= 3;
|
||||
|
||||
Vec3* vertices = new Vec3[numVert];
|
||||
// Get vertices
|
||||
// it can be done this way because standard guaranties that vector is on
|
||||
// continuous storage and vec3 is POD
|
||||
geom.GetVertices((float32 *)vertices);
|
||||
|
||||
// Turn the trpgGeometry into something Performer can understand
|
||||
GeoSet *gset = 0L;
|
||||
|
||||
// Get texture coordinates
|
||||
Vec2* tex_coords = 0L;
|
||||
trpgTexData td;
|
||||
if (geom.GetTexCoordSet(0,&td))
|
||||
{
|
||||
tex_coords = new Vec2[numVert];
|
||||
for (int i=0 ;i < numVert; i++)
|
||||
{
|
||||
tex_coords[i][0] = td.floatData[2*i+0];
|
||||
tex_coords[i][1] = td.floatData[2*i+1];
|
||||
}
|
||||
}
|
||||
|
||||
Vec3* normals = 0L;
|
||||
if (numNorm == numVert)
|
||||
{
|
||||
normals = new Vec3[numVert];
|
||||
geom.GetNormals((float32 *)normals);
|
||||
}
|
||||
|
||||
Geode *geode = new Geode();
|
||||
// Set up the primitive type
|
||||
switch (primType)
|
||||
{
|
||||
case trpgGeometry::Triangles:
|
||||
{
|
||||
gset = new GeoSet;
|
||||
gset->setPrimType(GeoSet::TRIANGLES);
|
||||
}
|
||||
break;
|
||||
case trpgGeometry::TriStrips:
|
||||
{
|
||||
// Need primitive lengths too
|
||||
int* primitives = new int[numPrims];
|
||||
geom.GetPrimLengths(primitives);
|
||||
|
||||
// Define GeoSet
|
||||
gset = new GeoSet;
|
||||
gset->setPrimType(GeoSet::TRIANGLE_STRIP);
|
||||
gset->setPrimLengths(primitives);
|
||||
}
|
||||
break;
|
||||
case trpgGeometry::TriFans:
|
||||
{
|
||||
// Need primitive lengths too
|
||||
int* primitives = new int[numPrims];
|
||||
geom.GetPrimLengths(primitives);
|
||||
|
||||
// Need to flip the fans
|
||||
int ind = 0;
|
||||
for (int i=0;i<numPrims;i++)
|
||||
{
|
||||
int start=ind+1;
|
||||
int end=primitives[i]+ind-1;
|
||||
// Swap from start+1 to end
|
||||
int numSwap = (end-start+1)/2;
|
||||
// Swap vertices, texture coords & normals
|
||||
for (int j=0; j < numSwap; j++ )
|
||||
{
|
||||
std::swap(vertices[start], vertices[end]);
|
||||
if( tex_coords )
|
||||
std::swap(tex_coords[start], tex_coords[end]);
|
||||
if(normals)
|
||||
std::swap(normals[start], normals[end]);
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
ind += primitives[i];
|
||||
}
|
||||
// Define GeoSet
|
||||
gset = new GeoSet;
|
||||
gset->setPrimType(GeoSet::TRIANGLE_FAN);
|
||||
gset->setPrimLengths(primitives);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
// Add it to the current parent group
|
||||
Group *top = parse->GetCurrTop();
|
||||
if (gset)
|
||||
{
|
||||
gset->setCoords(vertices);
|
||||
gset->setNumPrims(numPrims);
|
||||
if (normals)
|
||||
gset->setNormals(normals);
|
||||
// Note: Should check number of materials first
|
||||
// Note: Should be combining multiple geosets
|
||||
StateSet* sset = (*parse->GetMaterials())[matId].get();
|
||||
if (tex_coords)
|
||||
{
|
||||
gset->setTextureCoords(tex_coords);
|
||||
gset->setTextureBinding(GeoSet::BIND_PERVERTEX);
|
||||
}
|
||||
gset->setStateSet(sset);
|
||||
geode->addDrawable(gset);
|
||||
top->addChild(geode);
|
||||
}
|
||||
return (void *) 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Group Reader Class
|
||||
//
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
groupRead::groupRead(TrPageParser *in_parse)
|
||||
{
|
||||
parse = in_parse;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void* groupRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
|
||||
{
|
||||
trpgGroup group;
|
||||
if (!group.Read(buf))
|
||||
return NULL;
|
||||
// Create a new Performer group
|
||||
Group *osg_Group = new Group();
|
||||
// Dump this group into the hierarchy
|
||||
Group *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->addChild(osg_Group);
|
||||
int32 id;
|
||||
group.GetID(id);
|
||||
parse->AddToGroupList(id,osg_Group);
|
||||
return (void *) osg_Group;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Attach Reader Class
|
||||
//
|
||||
attachRead::attachRead(TrPageParser *in_parse)
|
||||
{
|
||||
parse = in_parse;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
|
||||
{
|
||||
trpgAttach group;
|
||||
if (!group.Read(buf))
|
||||
return NULL;
|
||||
// Create a new Performer group
|
||||
Group *osg_Group = new Group();
|
||||
// Dump this group into the hierarchy
|
||||
Group *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->addChild(osg_Group);
|
||||
int32 id;
|
||||
group.GetID(id);
|
||||
parse->AddToGroupList(id,osg_Group);
|
||||
// This sets the parent ID for the current tile too
|
||||
int32 parentID;
|
||||
group.GetParentID(parentID);
|
||||
parse->SetParentID(parentID);
|
||||
return (void *) osg_Group;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Billboard Reader Class
|
||||
//
|
||||
billboardRead::billboardRead(TrPageParser *in_parse)
|
||||
{
|
||||
parse = in_parse;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
|
||||
{
|
||||
trpgBillboard bill;
|
||||
if (!bill.Read(buf))
|
||||
return NULL;
|
||||
|
||||
Group* osg_Group = new Group;
|
||||
int type;
|
||||
bill.GetType(type);
|
||||
if( type == trpgBillboard::Group )
|
||||
{
|
||||
// Create a new Performer group
|
||||
Billboard* bl = new Billboard();
|
||||
int m;
|
||||
bill.GetMode(m);
|
||||
if( m = trpgBillboard::Eye)
|
||||
bl->setMode(Billboard::POINT_ROT_EYE);
|
||||
else if(m == trpgBillboard::World )
|
||||
bl->setMode(Billboard::POINT_ROT_WORLD);
|
||||
else if(m == trpgBillboard::Axial )
|
||||
{
|
||||
trpg3dPoint p;
|
||||
bill.GetAxis(p);
|
||||
bl->setAxis(Vec3(p.x, p.y, p.z));
|
||||
bl->setMode(Billboard::AXIAL_ROT);
|
||||
}
|
||||
osg_Group->addChild(bl);
|
||||
}
|
||||
// Dump this group into the hierarchy
|
||||
Group *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->addChild(osg_Group);
|
||||
int32 id;
|
||||
bill.GetID(id);
|
||||
parse->AddToGroupList(id,osg_Group);
|
||||
|
||||
return (void *) osg_Group;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// LOD Reader Class
|
||||
//
|
||||
lodRead::lodRead (TrPageParser *in_parse)
|
||||
{
|
||||
parse = in_parse;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
|
||||
{
|
||||
trpgLod lod;
|
||||
if (!lod.Read(buf))
|
||||
return NULL;
|
||||
// Pull out the LOD data we'll need
|
||||
trpg3dPoint center;
|
||||
lod.GetCenter(center);
|
||||
double in,out,width;
|
||||
lod.GetLOD(in,out,width);
|
||||
double minRange = MIN(in,out);
|
||||
double maxRange = MAX(in,out);
|
||||
|
||||
// Create a new Performer LOD
|
||||
LOD *osg_Lod = new LOD();
|
||||
Vec3 osg_Center;
|
||||
osg_Center[0] = center.x; osg_Center[1] = center.y; osg_Center[2] = center.z;
|
||||
osg_Lod->setCenter(osg_Center);
|
||||
osg_Lod->setRange(0,minRange);
|
||||
osg_Lod->setRange(1,maxRange);
|
||||
|
||||
// Our LODs are binary so we need to add a group under this LOD and attach stuff
|
||||
// to that instead of the LOD
|
||||
Group *osg_LodG = new Group();
|
||||
osg_Lod->addChild(osg_LodG);
|
||||
|
||||
// Dump this group into the hierarchy
|
||||
Group *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->addChild(osg_Lod);
|
||||
int32 id;
|
||||
lod.GetID(id);
|
||||
// Add the sub-group to the group list, not the LOD
|
||||
parse->AddToGroupList(id,osg_LodG);
|
||||
return (void *) osg_LodG;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Model Reference Reader Class
|
||||
//
|
||||
modelRefRead::modelRefRead(TrPageParser *in_parse)
|
||||
{
|
||||
parse = in_parse;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void *modelRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
|
||||
{
|
||||
trpgModelRef model;
|
||||
if (!model.Read(buf))
|
||||
return NULL;
|
||||
// Get the matrix and pfNode for the model
|
||||
int modelID;
|
||||
model.GetModel(modelID);
|
||||
float64 mat[16];
|
||||
model.GetMatrix(mat);
|
||||
Matrix osg_Mat(
|
||||
(float)mat[0], (float)mat[1], (float)mat[2], (float)mat[3],
|
||||
(float)mat[4], (float)mat[5], (float)mat[6], (float)mat[7],
|
||||
(float)mat[8], (float)mat[9], (float)mat[10],(float)mat[11],
|
||||
(float)mat[12],(float)mat[13],(float)mat[14],(float)mat[15]
|
||||
);
|
||||
|
||||
// Note: Array check before you do this
|
||||
Node *osg_Model = (*parse->GetModels())[modelID].get();
|
||||
// Create the SCS and position the model
|
||||
if (osg_Model) {
|
||||
Transform *scs = new Transform();
|
||||
scs->setMatrix(osg_Mat);
|
||||
scs->addChild(osg_Model);
|
||||
// Add the SCS to the hierarchy
|
||||
Group *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->addChild(scs);
|
||||
}
|
||||
return (void *) 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Tile Header Reader Class
|
||||
//
|
||||
tileHeaderRead::tileHeaderRead(TrPageParser *in_parse)
|
||||
{
|
||||
parse = in_parse;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void* tileHeaderRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
|
||||
{
|
||||
trpgTileHeader *tileHead = parse->GetTileHeaderRef();
|
||||
if (!tileHead->Read(buf))
|
||||
return NULL;
|
||||
return (void *) 1;
|
||||
}
|
||||
|
||||
|
||||
/* ********************************** */
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Constructor for scene graph parser
|
||||
TrPageParser::TrPageParser()
|
||||
{
|
||||
currTop = NULL;
|
||||
top = NULL;
|
||||
|
||||
// Register the readers
|
||||
AddCallback(TRPG_GEOMETRY,new geomRead(this));
|
||||
AddCallback(TRPG_GROUP,new groupRead(this));
|
||||
AddCallback(TRPG_ATTACH,new attachRead(this));
|
||||
AddCallback(TRPG_BILLBOARD,new billboardRead(this));
|
||||
AddCallback(TRPG_LOD,new lodRead(this));
|
||||
AddCallback(TRPG_MODELREF,new modelRefRead(this));
|
||||
AddCallback(TRPGTILEHEADER,new tileHeaderRead(this));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Destructor for scene graph parser
|
||||
TrPageParser::~TrPageParser()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Return a reference to the Tile Header
|
||||
// Doesn't do much if you haven't just read a tile
|
||||
trpgTileHeader *TrPageParser::GetTileHeaderRef()
|
||||
{
|
||||
return &tileHead;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Parse a buffer and return a (chunk of) Performer
|
||||
// scene graph.
|
||||
Group *TrPageParser::ParseScene(trpgReadBuffer &buf,vector<ref_ptr<StateSet> > &in_mat,vector<ref_ptr<Node> > &in_model)
|
||||
{
|
||||
top = currTop = new Group();
|
||||
materials = &in_mat;
|
||||
models = &in_model;
|
||||
parentID = -1;
|
||||
|
||||
// All the setup is handled in the constructor.
|
||||
// Just parse and return the top
|
||||
if (!Parse(buf))
|
||||
{
|
||||
notify(WARN) << "trpgFPParser::ParseScene failed to parse tile.\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Group *ret = top;
|
||||
top = currTop = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Start Children
|
||||
// This is called when the parser hits a push.
|
||||
// We'll want to make the node it's handing us the "top" node
|
||||
bool TrPageParser::StartChildren(void *in_node)
|
||||
{
|
||||
Group *node = (Group *)in_node;
|
||||
|
||||
currTop = node;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// This is called when the parser hits a pop.
|
||||
// We'll want to look on the parent list (in trpgSceneParser)
|
||||
// for the parent above the current one.
|
||||
// If there isn't one, we'll just stick things in our top group.
|
||||
bool TrPageParser::EndChildren(void * /* in_node */)
|
||||
{
|
||||
// Get the parent above the current one
|
||||
int pos = parents.size()-2;
|
||||
if (pos < 0)
|
||||
{
|
||||
// Nothing above the current one. Fall back on our top group
|
||||
currTop = top;
|
||||
}
|
||||
else
|
||||
{
|
||||
currTop = (Group *)parents[pos];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Return the current top node
|
||||
Group *TrPageParser::GetCurrTop()
|
||||
{
|
||||
if (currTop)
|
||||
{
|
||||
return currTop;
|
||||
}
|
||||
else
|
||||
{
|
||||
return top;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Add the given pfGroup to the group list at position ID
|
||||
bool TrPageParser::AddToGroupList(int ID,Group *group)
|
||||
{
|
||||
// Note: check bounds
|
||||
groupList[ID] = group;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Initialize the group list
|
||||
void TrPageParser::SetMaxGroupID(int maxGroupID)
|
||||
{
|
||||
notify(WARN) << "trpgFPParser: max group ID = " << maxGroupID << std::endl;
|
||||
// Initialize the group list with -1's
|
||||
groupList.resize(0);
|
||||
// Note: Fix this
|
||||
for (int i=0;i<maxGroupID;i++)
|
||||
groupList.push_back(NULL);
|
||||
}
|
||||
162
src/osgPlugins/txp/TrPageParser.h
Normal file
162
src/osgPlugins/txp/TrPageParser.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/* **************************************************************************
|
||||
* OpenSceneGraph loader for Terrapage format database
|
||||
* by Boris Bralo 2002
|
||||
*
|
||||
* based on/modifed sgl (Scene Graph Library) loader by Bryan Walsh
|
||||
*
|
||||
* This loader is based on/modified from Terrain Experts Performer Loader,
|
||||
* and was ported to SGL by Bryan Walsh / bryanw at earthlink dot net
|
||||
*
|
||||
* That loader is redistributed under the terms listed on Terrain Experts
|
||||
* website (www.terrex.com/www/pages/technology/technologypage.htm)
|
||||
*
|
||||
* "TerraPage is provided as an Open Source format for use by anyone...
|
||||
* We supply the TerraPage C++ source code free of charge. Anyone
|
||||
* can use it and redistribute it as needed (including our competitors).
|
||||
* We do, however, ask that you keep the TERREX copyrights intact."
|
||||
*
|
||||
* Copyright Terrain Experts Inc. 1999.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TRPAGEPARSER_H_
|
||||
#define _TRPAGEPARSER_H_
|
||||
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec2>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/ref_ptr>
|
||||
#include <vector>
|
||||
#include "trpage_read.h"
|
||||
|
||||
// forward declarations
|
||||
namespace osg
|
||||
{
|
||||
class Group;
|
||||
class Node;
|
||||
class Material;
|
||||
class Texture;
|
||||
class TexEnv;
|
||||
class Light;
|
||||
class Transparency;
|
||||
class CullFace;
|
||||
};
|
||||
|
||||
namespace txp
|
||||
{
|
||||
class TrPageParser : public trpgSceneParser
|
||||
{
|
||||
public:
|
||||
TrPageParser();
|
||||
~TrPageParser();
|
||||
|
||||
osg::Group *ParseScene(trpgReadBuffer &,
|
||||
std::vector<osg::ref_ptr<osg::StateSet> > &,
|
||||
std::vector<osg::ref_ptr<osg::Node> > &);
|
||||
|
||||
// Return the parent of a recently parsed tile
|
||||
int GetParentID() { return parentID; }
|
||||
void SetParentID(int id) { parentID = id; }
|
||||
// Return a reference to the tile header (after a tile has been read)
|
||||
trpgTileHeader *GetTileHeaderRef();
|
||||
|
||||
// Return the current top node (used during parsing)
|
||||
osg::Group *GetCurrTop();
|
||||
|
||||
// Return the current material list (passed in to ParseScene())
|
||||
std::vector<osg::ref_ptr<osg::StateSet> >* GetMaterials() { return materials; }
|
||||
std::vector<osg::ref_ptr<osg::Node> >* GetModels() { return models; }
|
||||
|
||||
// Add the Group to the group list
|
||||
bool AddToGroupList(int id,osg::Group *);
|
||||
|
||||
// Return the group list
|
||||
std::vector< osg::Group* > *GetGroupList() { return &groupList; }
|
||||
|
||||
// Set the maximum number of groups (once per archive)
|
||||
void SetMaxGroupID(int);
|
||||
|
||||
protected:
|
||||
bool StartChildren(void *);
|
||||
bool EndChildren(void *);
|
||||
|
||||
protected:
|
||||
osg::Group *currTop; // Current parent group
|
||||
osg::Group *top; // Top group
|
||||
trpgTileHeader tileHead; // Dump tile header here
|
||||
// If there was an attach node, this is
|
||||
// the tile's parent ID. -1 otherwise
|
||||
int parentID;
|
||||
std::vector<osg::ref_ptr<osg::StateSet> >* materials;
|
||||
std::vector<osg::Group *> groupList;
|
||||
std::vector<osg::ref_ptr<osg::Node> >* models;
|
||||
};
|
||||
|
||||
|
||||
//! callback functions for various scene graph elements
|
||||
class geomRead : public trpgr_Callback {
|
||||
public:
|
||||
geomRead(TrPageParser *in_parse);
|
||||
~geomRead();
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf);
|
||||
protected:
|
||||
TrPageParser *parse;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class groupRead : public trpgr_Callback {
|
||||
public:
|
||||
groupRead(TrPageParser *in_parse);
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf);
|
||||
protected:
|
||||
TrPageParser *parse;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class attachRead : public trpgr_Callback {
|
||||
public:
|
||||
attachRead(TrPageParser*in_parse);
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf);
|
||||
protected:
|
||||
TrPageParser*parse;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class billboardRead : public trpgr_Callback {
|
||||
public:
|
||||
billboardRead(TrPageParser*in_parse);
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf);
|
||||
protected:
|
||||
TrPageParser*parse;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class lodRead : public trpgr_Callback {
|
||||
public:
|
||||
lodRead(TrPageParser*in_parse);
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf);
|
||||
protected:
|
||||
TrPageParser*parse;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class modelRefRead : public trpgr_Callback {
|
||||
public:
|
||||
modelRefRead(TrPageParser*in_parse);
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf);
|
||||
protected:
|
||||
TrPageParser*parse;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class tileHeaderRead : public trpgr_Callback {
|
||||
public:
|
||||
tileHeaderRead(TrPageParser*in_parse);
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf);
|
||||
protected:
|
||||
TrPageParser*parse;
|
||||
};
|
||||
|
||||
}; // namespace txp
|
||||
#endif
|
||||
27
src/osgPlugins/txp/license.txt
Normal file
27
src/osgPlugins/txp/license.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// TerraPage<67> loader for Open Scene Graph
|
||||
//
|
||||
// Copyright (C) 2002 Boris Bralo
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
// The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
|
||||
// real-time rendering of large 3D photo-realistic models.
|
||||
// The OSG homepage is http://www.openscenegraph.org/
|
||||
//
|
||||
// TerraPage is registered trademarks of Terrex.
|
||||
//
|
||||
117
src/osgPlugins/txp/trdll.h
Normal file
117
src/osgPlugins/txp/trdll.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
/* trdll.h
|
||||
Windows Only
|
||||
|
||||
This header file defines the declaration macros for DLLs.
|
||||
*/
|
||||
|
||||
// Export/import declaration for classes and functions
|
||||
// Use EXDECL class CPPDECL ... for a class
|
||||
// Use CPPDECL foo *bar(bletch) for a stand-alone C++ function
|
||||
// Use CDECL foo *bar(bletch) for a C function
|
||||
// __COMP_DLL must be defined explicitly in Build->Settings->Code Generation
|
||||
// __CURR_DLL must be defined in each header in a DLL
|
||||
#ifdef TX_CLDECL
|
||||
#undef TX_CLDECL
|
||||
#undef TX_EXDECL
|
||||
#undef TX_CDECL
|
||||
#undef TX_CPPDECL
|
||||
#undef TX_DODECL
|
||||
#endif
|
||||
// Work through cases
|
||||
// If we're not compiling a DLL, or compiling the wrong DLL do import
|
||||
// declarations (0), otherwise do export declarations (1)
|
||||
#if !defined (__COMP_DLL)
|
||||
// {secret}
|
||||
#define TX_DODECL 0
|
||||
#else
|
||||
#if __COMP_DLL == __CURR_DLL
|
||||
#define TX_DODECL 1
|
||||
#else
|
||||
#define TX_DODECL 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// #if !defined (__CURR_DLL) || __COMP_DLL != __CURR_DLL
|
||||
#if TX_DODECL == 0
|
||||
// Modified by Paul J. Metzger (pjm@rbd.com) to support static link libraries.
|
||||
// Here's the original code:
|
||||
// #define TX_CLDECL __declspec( dllimport )
|
||||
// #define TX_EXDECL
|
||||
// #ifdef __cplusplus
|
||||
// #define TX_CDECL extern "C" __declspec(dllimport)
|
||||
// #else
|
||||
// #define TX_CDECL extern __declspec(dllimport)
|
||||
// #endif
|
||||
// #define TX_CPPDECL extern __declspec(dllimport)
|
||||
|
||||
// Class declaration. Goes after "class" to handle DLL export in windows.
|
||||
#define TX_CLDECL
|
||||
// Goes before "class" to handle DLL export in windows
|
||||
#define TX_EXDECL /* no-op */
|
||||
// Exports a C++ function properly in a windows DLL
|
||||
#define TX_CPPDECL /* no-op */
|
||||
// Exports a C function properly in a windows DLL
|
||||
#define TX_CDECL /* no-op */
|
||||
// {secret}
|
||||
#define TXDUMMY_DLL_MAIN /* no-op */
|
||||
#else
|
||||
#define TX_CLDECL __declspec( dllexport )
|
||||
#define TX_EXDECL
|
||||
#define TX_CPPDECL extern __declspec(dllexport)
|
||||
#ifdef __cplusplus
|
||||
#define TX_CDECL extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define TX_CDECL extern __declspec(dllexport)
|
||||
#endif
|
||||
|
||||
// The following is a DLL Main function for DLLs that wouldn't otherwise
|
||||
// have one. It's needed to initialize the run time library.
|
||||
// This should appear once within every DLL
|
||||
#ifndef TXDUMMY_DLL_MAIN
|
||||
#define TXDUMMY_DLL_MAIN \
|
||||
extern "C" { \
|
||||
BOOL WINAPI _CRT_INIT (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved); \
|
||||
BOOL APIENTRY DllMain (HANDLE hDLL, DWORD dwReason, LPVOID lpReserved) \
|
||||
{ \
|
||||
switch (dwReason) \
|
||||
{ \
|
||||
case DLL_PROCESS_ATTACH: \
|
||||
{ \
|
||||
if (!_CRT_INIT (hDLL, dwReason, lpReserved)) \
|
||||
return FALSE; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
case DLL_PROCESS_DETACH: \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
return TRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef txdll_h_
|
||||
// {secret}
|
||||
#define txdll_h_
|
||||
|
||||
#endif
|
||||
43
src/osgPlugins/txp/trpage_basic.cpp
Normal file
43
src/osgPlugins/txp/trpage_basic.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
/* trpage_basic.cpp
|
||||
Methods for checkable base class.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "trpage_io.h"
|
||||
|
||||
/* Checkable
|
||||
This is just a class that checks validity.
|
||||
Starts out invalid.
|
||||
*/
|
||||
|
||||
trpgCheckable::trpgCheckable()
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
trpgCheckable::~trpgCheckable()
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
bool trpgCheckable::isValid() const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
|
||||
813
src/osgPlugins/txp/trpage_geom.cpp
Normal file
813
src/osgPlugins/txp/trpage_geom.cpp
Normal file
@@ -0,0 +1,813 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
/* trpage_geom.cpp
|
||||
Methods for the trpgGeometry class.
|
||||
This includes read and write methods.
|
||||
You should only need to change something in here if you want to modify
|
||||
what trpgGeometry contains.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "trpage_geom.h"
|
||||
#include "trpage_read.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define ALIGNMENT_WORKAROUND false
|
||||
#else
|
||||
#define ALIGNMENT_WORKAROUND true
|
||||
#endif
|
||||
|
||||
// Constructor
|
||||
trpgGeometry::trpgGeometry()
|
||||
{
|
||||
primType = Polygons;
|
||||
normBind = Overall;
|
||||
numPrim = 0;
|
||||
}
|
||||
trpgGeometry::~trpgGeometry()
|
||||
{
|
||||
}
|
||||
|
||||
// Reset function
|
||||
void trpgGeometry::Reset()
|
||||
{
|
||||
primType = Polygons;
|
||||
numPrim = 0;
|
||||
primLength.resize(0);
|
||||
materials.resize(0);
|
||||
vertDataFloat.resize(0);
|
||||
vertDataDouble.resize(0);
|
||||
normBind = Overall;
|
||||
normDataFloat.resize(0);
|
||||
normDataDouble.resize(0);
|
||||
colors.resize(0);
|
||||
texData.resize(0);
|
||||
edgeFlags.resize(0);
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgGeometry::SetPrimType(PrimType type)
|
||||
{
|
||||
primType = type;
|
||||
}
|
||||
void trpgGeometry::SetPrimLengths(int num,const int *len)
|
||||
{
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
numPrim = num;
|
||||
for (int i=0;i<num;i++)
|
||||
primLength.push_back(len[i]);
|
||||
}
|
||||
void trpgGeometry::AddPrimLength(int len)
|
||||
{
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
numPrim++;
|
||||
primLength.push_back(len);
|
||||
}
|
||||
void trpgGeometry::AddPrim()
|
||||
{
|
||||
numPrim++;
|
||||
}
|
||||
void trpgGeometry::SetNumPrims(int num)
|
||||
{
|
||||
numPrim = num;
|
||||
}
|
||||
void trpgGeometry::SetNumMaterial(int no)
|
||||
{
|
||||
if (no < 0)
|
||||
return;
|
||||
|
||||
materials.resize(no,-1);
|
||||
}
|
||||
void trpgGeometry::SetMaterial(int which,int mat)
|
||||
{
|
||||
if (which < 0 || which >= (int)materials.size())
|
||||
return;
|
||||
|
||||
materials[which] = mat;
|
||||
}
|
||||
void trpgGeometry::SetMaterials(int32 num,const int32 *mat)
|
||||
{
|
||||
materials.resize(num);
|
||||
for (int i=0;i<num;i++)
|
||||
materials[i] = mat[i];
|
||||
}
|
||||
int trpgGeometry::AddMaterial(int mat)
|
||||
{
|
||||
materials.push_back(mat);
|
||||
|
||||
return materials.size()-1;
|
||||
}
|
||||
|
||||
// Geometry/color/normal/etc... set functions
|
||||
void trpgGeometry::SetVertices(int num,const float32 *data)
|
||||
{
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
vertDataFloat.resize(0);
|
||||
vertDataDouble.resize(0);
|
||||
for (int i=0;i<3*num;i++)
|
||||
vertDataFloat.push_back(data[i]);
|
||||
}
|
||||
void trpgGeometry::SetVertices(int num,const float64 *data)
|
||||
{
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
vertDataFloat.resize(0);
|
||||
vertDataDouble.resize(0);
|
||||
for (int i=0;i<3*num;i++)
|
||||
vertDataDouble.push_back(data[i]);
|
||||
}
|
||||
void trpgGeometry::AddVertex(DataType type,trpg3dPoint &pt)
|
||||
{
|
||||
if (type == FloatData) {
|
||||
vertDataFloat.push_back(pt.x);
|
||||
vertDataFloat.push_back(pt.y);
|
||||
vertDataFloat.push_back(pt.z);
|
||||
} else {
|
||||
vertDataDouble.push_back(pt.x);
|
||||
vertDataDouble.push_back(pt.y);
|
||||
vertDataDouble.push_back(pt.z);
|
||||
}
|
||||
}
|
||||
void trpgGeometry::SetNormals(int num,BindType bind,const float32 *data)
|
||||
{
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
normBind = bind;
|
||||
normDataFloat.resize(0);
|
||||
normDataDouble.resize(0);
|
||||
for (int i=0;i<3*num;i++)
|
||||
normDataFloat.push_back(data[i]);
|
||||
}
|
||||
void trpgGeometry::SetNormals(int num,BindType bind,const float64 *data)
|
||||
{
|
||||
if (num <0)
|
||||
return;
|
||||
|
||||
normBind = bind;
|
||||
normDataFloat.resize(0);
|
||||
normDataDouble.resize(0);
|
||||
for (int i=0;i<3*num;i++)
|
||||
normDataDouble.push_back(data[i]);
|
||||
}
|
||||
void trpgGeometry::AddNormal(DataType type,trpg3dPoint &pt)
|
||||
{
|
||||
if (type == FloatData) {
|
||||
normDataFloat.push_back(pt.x);
|
||||
normDataFloat.push_back(pt.y);
|
||||
normDataFloat.push_back(pt.z);
|
||||
} else {
|
||||
normDataDouble.push_back(pt.x);
|
||||
normDataDouble.push_back(pt.y);
|
||||
normDataDouble.push_back(pt.z);
|
||||
}
|
||||
}
|
||||
// Constructor
|
||||
trpgColorInfo::trpgColorInfo()
|
||||
{
|
||||
}
|
||||
trpgColorInfo::~trpgColorInfo()
|
||||
{
|
||||
}
|
||||
void trpgColorInfo::Reset()
|
||||
{
|
||||
bind = 0;
|
||||
type = 0;
|
||||
data.resize(0);
|
||||
}
|
||||
void trpgGeometry::SetColors(int num,ColorType type,BindType bind,const trpgColor *data)
|
||||
{
|
||||
trpgColorInfo ci;
|
||||
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
// Set up color list
|
||||
ci.type = type;
|
||||
ci.bind = bind;
|
||||
for (int i=0;i<num;i++)
|
||||
ci.data.push_back(data[i]);
|
||||
|
||||
colors.push_back(ci);
|
||||
}
|
||||
// Constructor
|
||||
trpgTexData::trpgTexData()
|
||||
{
|
||||
}
|
||||
trpgTexData::~trpgTexData()
|
||||
{
|
||||
}
|
||||
void trpgTexData::set(int num,int in_bind,const float32 *data)
|
||||
{
|
||||
bind = in_bind;
|
||||
floatData.resize(0);
|
||||
doubleData.resize(0);
|
||||
for (int i=0;i<2*num;i++)
|
||||
floatData.push_back(data[i]);
|
||||
}
|
||||
void trpgTexData::set(int num,int in_bind,const float64 *data)
|
||||
{
|
||||
bind = in_bind;
|
||||
floatData.resize(0);
|
||||
doubleData.resize(0);
|
||||
for (int i=0;i<2*num;i++)
|
||||
doubleData.push_back(data[i]);
|
||||
}
|
||||
void trpgTexData::Reset()
|
||||
{
|
||||
bind = 0;
|
||||
floatData.resize(0);
|
||||
doubleData.resize(0);
|
||||
}
|
||||
|
||||
void trpgGeometry::SetTexCoords(int num,BindType bind,const float32 *data)
|
||||
{
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
trpgTexData td;
|
||||
td.set(num,bind,data);
|
||||
texData.push_back(td);
|
||||
}
|
||||
void trpgGeometry::SetTexCoords(int num,BindType bind,const float64 *data)
|
||||
{
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
trpgTexData td;
|
||||
td.set(num,bind,data);
|
||||
texData.push_back(td);
|
||||
}
|
||||
void trpgGeometry::AddTexCoord(DataType type,trpg2dPoint &pt)
|
||||
{
|
||||
if (texData.size() == 0)
|
||||
return;
|
||||
trpgTexData *td = &texData[0];
|
||||
|
||||
if (type == FloatData) {
|
||||
td->floatData.push_back(pt.x);
|
||||
td->floatData.push_back(pt.y);
|
||||
} else {
|
||||
td->doubleData.push_back(pt.x);
|
||||
td->doubleData.push_back(pt.y);
|
||||
}
|
||||
}
|
||||
void trpgGeometry::AddTexCoords(BindType bind)
|
||||
{
|
||||
trpgTexData td;
|
||||
td.bind = bind;
|
||||
texData.push_back(td);
|
||||
}
|
||||
void trpgGeometry::SetEdgeFlags(int num,const char *flags)
|
||||
{
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
edgeFlags.resize(0);
|
||||
for (int i=0;i<num;i++)
|
||||
edgeFlags.push_back(flags[i]);
|
||||
}
|
||||
|
||||
// Get methods
|
||||
bool trpgGeometry::GetPrimType(PrimType &t) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
t = (PrimType)primType;
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetNumPrims(int &n) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
n = numPrim;
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetPrimLengths(int *ret) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
for (int i=0;i<numPrim;i++)
|
||||
ret[i] = primLength[i];
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetNumMaterial(int &n) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
n = materials.size();
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetMaterial(int id,int32 &m) const
|
||||
{
|
||||
if (!isValid() || id < 0 || id >= (int)materials.size()) return false;
|
||||
m = materials[id];
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetNumVertex(int &v) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
int nvf = vertDataFloat.size();
|
||||
int nvd = vertDataDouble.size();
|
||||
v = MAX(nvf,nvd);
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetVertices(float32 *v) const
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!isValid()) return false;
|
||||
if (vertDataFloat.size() != 0)
|
||||
for (i=0;i<vertDataFloat.size();i++)
|
||||
v[i] = vertDataFloat[i];
|
||||
else
|
||||
for (i=0;i<vertDataDouble.size();i++)
|
||||
v[i] = vertDataDouble[i];
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetVertices(float64 *v) const
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!isValid()) return false;
|
||||
if (vertDataFloat.size() != 0)
|
||||
for (i=0;i<vertDataFloat.size();i++)
|
||||
v[i] = vertDataFloat[i];
|
||||
else
|
||||
for (i=0;i<vertDataDouble.size();i++)
|
||||
v[i] = vertDataDouble[i];
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetVertex(int n,trpg3dPoint &pt) const
|
||||
{
|
||||
int id = 3*n;
|
||||
int idMax = 3*n+2;
|
||||
if (id < 0 || (idMax >= (int)vertDataFloat.size() && idMax >= (int)vertDataDouble.size()))
|
||||
return false;
|
||||
if (vertDataFloat.size() > vertDataDouble.size()) {
|
||||
pt.x = vertDataFloat[id];
|
||||
pt.y = vertDataFloat[id+1];
|
||||
pt.z = vertDataFloat[id+2];
|
||||
} else {
|
||||
pt.x = vertDataDouble[id];
|
||||
pt.y = vertDataDouble[id+1];
|
||||
pt.z = vertDataDouble[id+2];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetNumNormal(int32 &n) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
if (normDataFloat.size() != 0)
|
||||
n = normDataFloat.size();
|
||||
if (normDataDouble.size() != 0)
|
||||
n = normDataDouble.size();
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetNormals(float32 *v) const
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!isValid()) return false;
|
||||
if (normDataFloat.size() != 0)
|
||||
for (i=0;i<normDataFloat.size();i++)
|
||||
v[i] = normDataFloat[i];
|
||||
else
|
||||
for (i=0;i<normDataDouble.size();i++)
|
||||
v[i] = normDataDouble[i];
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetNormals(float64 *v) const
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!isValid()) return false;
|
||||
if (normDataFloat.size() != 0)
|
||||
for (i=0;i<normDataFloat.size();i++)
|
||||
v[i] = normDataFloat[i];
|
||||
else
|
||||
for (i=0;i<normDataDouble.size();i++)
|
||||
v[i] = normDataDouble[i];
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetNumColorSets(int &n) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
n = (int)colors.size();
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetColorSet(int id,trpgColorInfo *ci) const
|
||||
{
|
||||
if (!isValid() || id < 0 || id >= (int)colors.size()) return false;
|
||||
*ci = colors[id];
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetNumTexCoordSets(int &n) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
n = (int)texData.size();
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetTexCoordSet(int id,trpgTexData *tx) const
|
||||
{
|
||||
if (!isValid() || id < 0 || id >= (int)texData.size()) return false;
|
||||
*tx = texData[id];
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetNumEdgeFlag(int &n) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
n = (int)edgeFlags.size();
|
||||
return true;
|
||||
}
|
||||
bool trpgGeometry::GetEdgeFlags(char *e) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
for (unsigned int i=0;i<edgeFlags.size();i++)
|
||||
e[i] = edgeFlags[i];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validity check
|
||||
// Note: maybe I should do this sometime
|
||||
bool trpgGeometry::isValid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Write geometry fields.
|
||||
// Order doesn't matter very much for this
|
||||
bool trpgGeometry::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
unsigned int i,j;
|
||||
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPG_GEOMETRY);
|
||||
/* Primitive info
|
||||
Primitive Type
|
||||
Number of primitives
|
||||
Primitive array lengths
|
||||
*/
|
||||
buf.Begin(TRPG_GEOM_PRIM);
|
||||
buf.Add(primType);
|
||||
buf.Add(numPrim);
|
||||
if (primLength.size() != 0) {
|
||||
buf.Add((uint8)1);
|
||||
for (i=0;i<(unsigned int)numPrim;i++)
|
||||
buf.Add(primLength[i]);
|
||||
} else
|
||||
buf.Add((uint8)0);
|
||||
buf.End();
|
||||
|
||||
/* Material info
|
||||
Num materials
|
||||
Material indicies
|
||||
*/
|
||||
if (materials.size() > 0) {
|
||||
buf.Begin(TRPG_GEOM_MATERIAL);
|
||||
buf.Add((int32)materials.size());
|
||||
for (i=0;i<materials.size();i++)
|
||||
buf.Add(materials[i]);
|
||||
buf.End();
|
||||
}
|
||||
|
||||
/* Vertices
|
||||
Float and Double should never both be here
|
||||
Num vertex
|
||||
Vertex data
|
||||
*/
|
||||
if (vertDataFloat.size() > 0) {
|
||||
buf.Begin(TRPG_GEOM_VERT32);
|
||||
int32 num = vertDataFloat.size()/3;
|
||||
buf.Add(num);
|
||||
for (i=0;i<(unsigned int)3*num;i++)
|
||||
buf.Add(vertDataFloat[i]);
|
||||
buf.End();
|
||||
}
|
||||
if (vertDataDouble.size() > 0) {
|
||||
buf.Begin(TRPG_GEOM_VERT64);
|
||||
int32 num = vertDataDouble.size()/3;
|
||||
buf.Add(num);
|
||||
for (i=0;i<(unsigned int)3*num;i++)
|
||||
buf.Add(vertDataDouble[i]);
|
||||
buf.End();
|
||||
}
|
||||
|
||||
/* Normals
|
||||
Normal binding
|
||||
Num normals
|
||||
Normal data
|
||||
*/
|
||||
if (normDataFloat.size() > 0) {
|
||||
buf.Begin(TRPG_GEOM_NORM32);
|
||||
buf.Add((int32)normBind);
|
||||
int32 num = normDataFloat.size()/3;
|
||||
buf.Add(num);
|
||||
for (i=0;i<(unsigned int)3*num;i++)
|
||||
buf.Add(normDataFloat[i]);
|
||||
buf.End();
|
||||
}
|
||||
if (normDataDouble.size() > 0) {
|
||||
buf.Begin(TRPG_GEOM_NORM64);
|
||||
buf.Add((int32)normBind);
|
||||
int32 num = normDataDouble.size()/3;
|
||||
buf.Add(num);
|
||||
for (i=0;i<(unsigned int)3*num;i++)
|
||||
buf.Add(normDataDouble[i]);
|
||||
buf.End();
|
||||
}
|
||||
|
||||
/* Colors
|
||||
Color binding
|
||||
Num colors
|
||||
Colors
|
||||
*/
|
||||
if (colors.size() > 0) {
|
||||
for (i=0;i<colors.size();i++) {
|
||||
trpgColorInfo &ci = colors[i];
|
||||
if (ci.data.size()) {
|
||||
buf.Begin(TRPG_GEOM_COLOR);
|
||||
buf.Add((int32)ci.type);
|
||||
buf.Add((int32)ci.bind);
|
||||
buf.Add((int32)ci.data.size());
|
||||
for (j=0;j<ci.data.size();j++)
|
||||
buf.Add(ci.data[j]);
|
||||
buf.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Texture coordinates
|
||||
Binding
|
||||
Num coords
|
||||
Texture coords
|
||||
*/
|
||||
for (i=0;i<texData.size();i++) {
|
||||
trpgTexData &td = texData[i];
|
||||
if (td.floatData.size()) {
|
||||
buf.Begin(TRPG_GEOM_TEX32);
|
||||
buf.Add((int32)td.bind);
|
||||
int32 num = td.floatData.size()/2;
|
||||
buf.Add(num);
|
||||
for (j=0;j<(unsigned int)num*2;j++)
|
||||
buf.Add(td.floatData[j]);
|
||||
buf.End();
|
||||
}
|
||||
if (td.doubleData.size()) {
|
||||
buf.Begin(TRPG_GEOM_TEX64);
|
||||
buf.Add((int32)td.bind);
|
||||
int32 num = td.doubleData.size()/2;
|
||||
buf.Add(num);
|
||||
for (j=0;j<(unsigned int)num*2;j++)
|
||||
buf.Add(td.doubleData[j]);
|
||||
buf.End();
|
||||
|
||||
// What is going on here? - mcmillan
|
||||
//float u;
|
||||
//for (j=0;j<(unsigned int)num*2;j++)
|
||||
// u = (float)td.doubleData[j];
|
||||
}
|
||||
}
|
||||
|
||||
// Edge flags (for triangle strips, etc..)
|
||||
if (edgeFlags.size() > 0) {
|
||||
buf.Begin(TRPG_GEOM_EFLAG);
|
||||
buf.Add((int32)edgeFlags.size());
|
||||
for (i=0;i<edgeFlags.size();i++)
|
||||
buf.Add(edgeFlags[i]);
|
||||
buf.End();
|
||||
}
|
||||
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Geometry class is made up of individual tokens.
|
||||
class geomCB : public trpgr_Callback {
|
||||
public:
|
||||
void *Parse(trpgToken,trpgReadBuffer &buf);
|
||||
trpgGeometry *geom;
|
||||
};
|
||||
|
||||
void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf)
|
||||
{
|
||||
int32 *iData;
|
||||
int32 num,primType,bind,type;
|
||||
float32 *fData;
|
||||
float64 *dData;
|
||||
trpgColor *cData;
|
||||
char *charData;
|
||||
uint8 hasPrimLen;
|
||||
|
||||
try {
|
||||
switch (tok) {
|
||||
case TRPG_GEOM_PRIM:
|
||||
buf.Get(primType);
|
||||
geom->SetPrimType((trpgGeometry::PrimType)primType);
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
geom->SetNumPrims(num);
|
||||
buf.Get(hasPrimLen);
|
||||
if (hasPrimLen) {
|
||||
buf.GetArray(num,&iData);
|
||||
if (ALIGNMENT_WORKAROUND)
|
||||
{
|
||||
int32 *aligned;
|
||||
aligned = (int32 *)calloc (num, sizeof(int32));
|
||||
memcpy (aligned, iData, num * sizeof(int32));
|
||||
geom->SetPrimLengths(num, aligned);
|
||||
free (aligned);
|
||||
}
|
||||
else
|
||||
geom->SetPrimLengths(num,iData);
|
||||
}
|
||||
break;
|
||||
case TRPG_GEOM_MATERIAL:
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
buf.GetArray(num,&iData);
|
||||
if (ALIGNMENT_WORKAROUND)
|
||||
{
|
||||
int32 *aligned;
|
||||
aligned = (int32 *)calloc (num, sizeof(int32));
|
||||
memcpy (aligned, iData, num * sizeof(int32));
|
||||
geom->SetMaterials(num,aligned);
|
||||
free (aligned);
|
||||
}
|
||||
else
|
||||
geom->SetMaterials(num,iData);
|
||||
break;
|
||||
case TRPG_GEOM_VERT32:
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
buf.GetArray(3*num,&fData);
|
||||
if (ALIGNMENT_WORKAROUND)
|
||||
{
|
||||
float32 *aligned;
|
||||
aligned = (float32 *)calloc (3*num, sizeof(float32));
|
||||
memcpy (aligned, fData, 3*num * sizeof(float32));
|
||||
geom->SetVertices(num,aligned);
|
||||
free (aligned);
|
||||
}
|
||||
else
|
||||
geom->SetVertices(num,fData);
|
||||
break;
|
||||
case TRPG_GEOM_VERT64:
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
buf.GetArray(3*num,&dData);
|
||||
if (ALIGNMENT_WORKAROUND)
|
||||
{
|
||||
float64 *aligned;
|
||||
aligned = (float64 *)calloc (3*num, sizeof(float64));
|
||||
memcpy (aligned, dData, 3*num * sizeof(float64));
|
||||
geom->SetVertices(num,aligned);
|
||||
free (aligned);
|
||||
}
|
||||
else
|
||||
geom->SetVertices(num,dData);
|
||||
break;
|
||||
case TRPG_GEOM_NORM32:
|
||||
buf.Get(bind);
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
buf.GetArray(3*num,&fData);
|
||||
if (ALIGNMENT_WORKAROUND)
|
||||
{
|
||||
float32 *aligned;
|
||||
aligned = (float32 *)calloc (3*num, sizeof(float32));
|
||||
memcpy (aligned, fData, 3*num * sizeof(float32));
|
||||
geom->SetNormals(num,(trpgGeometry::BindType)bind,aligned);
|
||||
free (aligned);
|
||||
}
|
||||
else
|
||||
geom->SetNormals(num,(trpgGeometry::BindType)bind,fData);
|
||||
break;
|
||||
case TRPG_GEOM_NORM64:
|
||||
buf.Get(bind);
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
buf.GetArray(3*num,&dData);
|
||||
if (ALIGNMENT_WORKAROUND)
|
||||
{
|
||||
float64 *aligned;
|
||||
aligned = (float64 *)calloc (3*num, sizeof(float64));
|
||||
memcpy (aligned, dData, 3*num * sizeof(float64));
|
||||
geom->SetNormals(num,(trpgGeometry::BindType)bind,aligned);
|
||||
free (aligned);
|
||||
}
|
||||
else
|
||||
geom->SetNormals(num,(trpgGeometry::BindType)bind,dData);
|
||||
break;
|
||||
case TRPG_GEOM_COLOR:
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
buf.Get(type);
|
||||
buf.Get(bind);
|
||||
buf.GetArray(num,&cData);
|
||||
if (ALIGNMENT_WORKAROUND)
|
||||
{
|
||||
trpgColor *aligned;
|
||||
aligned = (trpgColor *)calloc (num, sizeof(trpgColor));
|
||||
memcpy (aligned, cData, num * sizeof(trpgColor));
|
||||
geom->SetColors(num,(trpgGeometry::ColorType)type,(trpgGeometry::BindType)bind,aligned);
|
||||
free (aligned);
|
||||
}
|
||||
else
|
||||
geom->SetColors(num,(trpgGeometry::ColorType)type,(trpgGeometry::BindType)bind,cData);
|
||||
break;
|
||||
case TRPG_GEOM_TEX32:
|
||||
buf.Get(bind);
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
buf.GetArray(2*num,&fData);
|
||||
if (ALIGNMENT_WORKAROUND)
|
||||
{
|
||||
float32 *aligned;
|
||||
aligned = (float32 *)calloc (2*num, sizeof(float32));
|
||||
memcpy (aligned, fData, 2*num * sizeof(float32));
|
||||
geom->SetTexCoords(num,(trpgGeometry::BindType)bind,aligned);
|
||||
free (aligned);
|
||||
}
|
||||
else
|
||||
geom->SetTexCoords(num,(trpgGeometry::BindType)bind,fData);
|
||||
break;
|
||||
case TRPG_GEOM_TEX64:
|
||||
buf.Get(bind);
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
buf.GetArray(2*num,&dData);
|
||||
if (ALIGNMENT_WORKAROUND)
|
||||
{
|
||||
float64 *aligned;
|
||||
aligned = (float64 *)calloc (2*num, sizeof(float64));
|
||||
memcpy (aligned, dData, 2*num * sizeof(float64));
|
||||
geom->SetTexCoords(num,(trpgGeometry::BindType)bind,aligned);
|
||||
free (aligned);
|
||||
}
|
||||
else
|
||||
geom->SetTexCoords(num,(trpgGeometry::BindType)bind,dData);
|
||||
break;
|
||||
case TRPG_GEOM_EFLAG:
|
||||
buf.Get(num);
|
||||
if (num < 0) throw 1;
|
||||
buf.GetArray(num,&charData);
|
||||
geom->SetEdgeFlags(num,charData);
|
||||
break;
|
||||
default:
|
||||
// Skip
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
// Read Geometry
|
||||
bool trpgGeometry::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
trpgr_Parser parse;
|
||||
geomCB gcb;
|
||||
|
||||
gcb.geom = this;
|
||||
parse.AddCallback(TRPG_GEOM_PRIM,&gcb,false);
|
||||
parse.AddCallback(TRPG_GEOM_MATERIAL,&gcb,false);
|
||||
parse.AddCallback(TRPG_GEOM_VERT32,&gcb,false);
|
||||
parse.AddCallback(TRPG_GEOM_VERT64,&gcb,false);
|
||||
parse.AddCallback(TRPG_GEOM_NORM32,&gcb,false);
|
||||
parse.AddCallback(TRPG_GEOM_NORM64,&gcb,false);
|
||||
parse.AddCallback(TRPG_GEOM_COLOR,&gcb,false);
|
||||
parse.AddCallback(TRPG_GEOM_TEX32,&gcb,false);
|
||||
parse.AddCallback(TRPG_GEOM_TEX64,&gcb,false);
|
||||
parse.AddCallback(TRPG_GEOM_EFLAG,&gcb,false);
|
||||
parse.Parse(buf);
|
||||
|
||||
return isValid();
|
||||
}
|
||||
1618
src/osgPlugins/txp/trpage_geom.h
Normal file
1618
src/osgPlugins/txp/trpage_geom.h
Normal file
File diff suppressed because it is too large
Load Diff
315
src/osgPlugins/txp/trpage_header.cpp
Normal file
315
src/osgPlugins/txp/trpage_header.cpp
Normal file
@@ -0,0 +1,315 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* trpage_header.cpp
|
||||
Source for trpgHeader methods.
|
||||
The only reason to change this is if you want to add something
|
||||
to the header definition.
|
||||
*/
|
||||
|
||||
#include "trpage_geom.h"
|
||||
#include "trpage_read.h"
|
||||
|
||||
/* Write Header class
|
||||
Fill it in and write it out.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgHeader::trpgHeader()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
trpgHeader::~trpgHeader()
|
||||
{
|
||||
}
|
||||
|
||||
// Validity check
|
||||
bool trpgHeader::isValid() const
|
||||
{
|
||||
if (numLods <= 0)
|
||||
return false;
|
||||
if (sw.x == ne.x && sw.y == ne.y)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reset contents
|
||||
void trpgHeader::Reset()
|
||||
{
|
||||
// Initialize to a default state
|
||||
verMinor = TRPG_VERSION_MINOR;
|
||||
verMajor = TRPG_VERSION_MAJOR;
|
||||
dbVerMinor = 0;
|
||||
dbVerMajor = 0;
|
||||
origin = trpg3dPoint(0,0,0);
|
||||
sw = ne = trpg2dPoint(0,0);
|
||||
tileType = DatabaseLocal;
|
||||
|
||||
numLods = 0;
|
||||
lodSizes.resize(0);
|
||||
lodRanges.resize(0);
|
||||
tileSize.resize(0);
|
||||
maxGroupID = -1;
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgHeader::SetVersion(int32 vmaj,int32 vmin)
|
||||
{
|
||||
verMinor = vmin;
|
||||
verMajor = vmaj;
|
||||
}
|
||||
void trpgHeader::SetDbVersion(int32 vmaj,int32 vmin)
|
||||
{
|
||||
dbVerMinor = vmin;
|
||||
dbVerMajor = vmaj;
|
||||
}
|
||||
void trpgHeader::SetTileSize(int id,const trpg2dPoint &pt)
|
||||
{
|
||||
if (id < 0 || (unsigned int)id >= tileSize.size()) return;
|
||||
tileSize[id] = pt;
|
||||
}
|
||||
void trpgHeader::SetOrigin(const trpg3dPoint &pt)
|
||||
{
|
||||
origin = pt;
|
||||
}
|
||||
void trpgHeader::SetExtents(const trpg2dPoint &in_sw,const trpg2dPoint &in_ne)
|
||||
{
|
||||
sw = in_sw;
|
||||
ne = in_ne;
|
||||
}
|
||||
void trpgHeader::SetTileOriginType(trpgTileType type)
|
||||
{
|
||||
tileType = type;
|
||||
}
|
||||
void trpgHeader::SetNumLods(int no)
|
||||
{
|
||||
if (no < 0) return;
|
||||
numLods = no;
|
||||
|
||||
lodSizes.resize(no);
|
||||
lodRanges.resize(no);
|
||||
}
|
||||
void trpgHeader::SetLodSize(int no,const trpg2iPoint &pt)
|
||||
{
|
||||
if (no < 0 || no >= numLods)
|
||||
return;
|
||||
|
||||
lodSizes[no] = pt;
|
||||
}
|
||||
void trpgHeader::SetLodSize(const trpg2iPoint *pt)
|
||||
{
|
||||
for (int i=0;i<numLods;i++)
|
||||
lodSizes[i] = pt[i];
|
||||
}
|
||||
void trpgHeader::SetLodRange(int no,float64 r)
|
||||
{
|
||||
if (no < 0 || no >= numLods)
|
||||
return;
|
||||
|
||||
lodRanges[no] = r;
|
||||
}
|
||||
void trpgHeader::SetLodRange(const float64 *r)
|
||||
{
|
||||
for (int i=0;i<numLods;i++)
|
||||
lodRanges[i] = r[i];
|
||||
}
|
||||
void trpgHeader::AddLod(const trpg2iPoint &pt,const trpg2dPoint &sz,float64 r)
|
||||
{
|
||||
lodRanges.push_back(r);
|
||||
lodSizes.push_back(pt);
|
||||
tileSize.push_back(sz);
|
||||
numLods++;
|
||||
}
|
||||
void trpgHeader::SetMaxGroupID(int id)
|
||||
{
|
||||
maxGroupID = id;
|
||||
}
|
||||
int trpgHeader::AddGroupID(void)
|
||||
{
|
||||
maxGroupID++;
|
||||
return maxGroupID;
|
||||
}
|
||||
|
||||
// Write out to a buffer
|
||||
bool trpgHeader::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPGHEADER);
|
||||
buf.Add((int32)verMajor);
|
||||
buf.Add((int32)verMinor);
|
||||
buf.Add((int32)dbVerMajor);
|
||||
buf.Add((int32)dbVerMinor);
|
||||
buf.Add(origin);
|
||||
buf.Add(sw);
|
||||
buf.Add(ne);
|
||||
buf.Add((uint8)tileType);
|
||||
|
||||
buf.Add((int32)numLods);
|
||||
|
||||
buf.Begin(TRPGHEAD_LODINFO);
|
||||
for (int i=0;i<numLods;i++) {
|
||||
buf.Add(lodSizes[i]);
|
||||
buf.Add(lodRanges[i]);
|
||||
buf.Add(tileSize[i]);
|
||||
}
|
||||
buf.End();
|
||||
|
||||
buf.Add(maxGroupID);
|
||||
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********
|
||||
Read Header class.
|
||||
*/
|
||||
|
||||
// Get Functions
|
||||
bool trpgHeader::GetVersion(int32 &vmaj,int32 &vmin) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
vmin = verMinor;
|
||||
vmaj = verMajor;
|
||||
return true;
|
||||
}
|
||||
bool trpgHeader::GetDbVersion(int32 &vmaj,int32 &vmin) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
vmaj = dbVerMajor;
|
||||
vmin = dbVerMinor;
|
||||
return true;
|
||||
}
|
||||
bool trpgHeader::GetTileSize(int id,trpg2dPoint &pt) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
if (id < 0 || (unsigned int)id >= tileSize.size()) return false;
|
||||
pt = tileSize[id];
|
||||
return true;
|
||||
}
|
||||
bool trpgHeader::GetOrigin(trpg3dPoint &pt) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
pt = origin;
|
||||
return true;
|
||||
}
|
||||
bool trpgHeader::GetTileOriginType(trpgTileType &type) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
type = tileType;
|
||||
return true;
|
||||
}
|
||||
bool trpgHeader::GetNumLods(int32 &no) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
no = numLods;
|
||||
return true;
|
||||
}
|
||||
bool trpgHeader::GetLodSize(int32 id,trpg2iPoint &pt) const
|
||||
{
|
||||
if (!isValid() || (id < 0 || id >= numLods)) return false;
|
||||
pt = lodSizes[id];
|
||||
return true;
|
||||
}
|
||||
bool trpgHeader::GetLodRange(int32 id,float64 &range) const
|
||||
{
|
||||
if (!isValid() || (id < 0 || id >= numLods)) return false;
|
||||
range = lodRanges[id];
|
||||
return true;
|
||||
}
|
||||
bool trpgHeader::GetExtents(trpg2dPoint &osw,trpg2dPoint &one) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
osw = sw;
|
||||
one = ne;
|
||||
return true;
|
||||
}
|
||||
bool trpgHeader::GetMaxGroupID(int &id) const
|
||||
{
|
||||
id = maxGroupID;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read in the header
|
||||
bool trpgHeader::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
uint8 i8;
|
||||
trpgToken tok;
|
||||
bool status;
|
||||
int32 len;
|
||||
|
||||
try {
|
||||
buf.Get(verMajor);
|
||||
buf.Get(verMinor);
|
||||
buf.Get(dbVerMajor);
|
||||
buf.Get(dbVerMinor);
|
||||
buf.Get(origin);
|
||||
buf.Get(sw);
|
||||
buf.Get(ne);
|
||||
buf.Get(i8); tileType = (trpgTileType)i8;
|
||||
buf.Get(numLods);
|
||||
if (numLods < 0) throw 1;
|
||||
|
||||
// Read in the LOD range info
|
||||
buf.GetToken(tok,len);
|
||||
if (tok != TRPGHEAD_LODINFO) throw 1;
|
||||
buf.PushLimit(len);
|
||||
status = ReadLodInfo(buf);
|
||||
buf.PopLimit();
|
||||
if (!status) throw 1;
|
||||
|
||||
// Added after the first version
|
||||
buf.Get(maxGroupID);
|
||||
}
|
||||
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
// Read the LOD info (seperate token)
|
||||
bool trpgHeader::ReadLodInfo(trpgReadBuffer &buf)
|
||||
{
|
||||
float64 range;
|
||||
trpg2iPoint pt;
|
||||
trpg2dPoint sz;
|
||||
|
||||
try {
|
||||
for (int i=0;i<numLods;i++) {
|
||||
buf.Get(pt);
|
||||
buf.Get(range);
|
||||
buf.Get(sz);
|
||||
lodSizes.push_back(pt);
|
||||
lodRanges.push_back(range);
|
||||
tileSize.push_back(sz);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
21
src/osgPlugins/txp/trpage_ident.h
Normal file
21
src/osgPlugins/txp/trpage_ident.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#ifdef __CURR_DLL
|
||||
#undef __CURR_DLL
|
||||
#endif
|
||||
// {secret}
|
||||
#define __CURR_DLL 7931
|
||||
484
src/osgPlugins/txp/trpage_io.h
Normal file
484
src/osgPlugins/txp/trpage_io.h
Normal file
@@ -0,0 +1,484 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#ifndef _trpage_io_h_
|
||||
#define _trpage_io_h_
|
||||
|
||||
/* trpage_io.h
|
||||
Token definitions and basic classes.
|
||||
*/
|
||||
|
||||
#include "trpage_sys.h"
|
||||
|
||||
// Macros we may need
|
||||
#ifndef MIN
|
||||
// {secret}
|
||||
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
// {secret}
|
||||
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
// File header Magic Number
|
||||
#define TRPG_MAGIC 9480372
|
||||
|
||||
// Current TerraPage major version
|
||||
#define TRPG_VERSION_MAJOR 1
|
||||
// Current TerraPage minor version
|
||||
#define TRPG_VERSION_MINOR 0
|
||||
|
||||
// Non-existent token
|
||||
// {secret}
|
||||
#define TRPG_NOTOKEN 0
|
||||
|
||||
// 16 bit token definition value. These are values such as TRPGTEXTABLE or TRPG_ATTACH, etc...
|
||||
typedef short trpgToken;
|
||||
|
||||
// Tokens for paging data structures
|
||||
// Update the MINTOKEN and MAXTOKEN when you add tokens
|
||||
// {secret}
|
||||
#define TRPG_MINTOKEN 100
|
||||
// {secret}
|
||||
#define TRPG_PUSH 100
|
||||
// {secret}
|
||||
#define TRPG_POP 101
|
||||
|
||||
// {secret}
|
||||
#define TRPGHEADER 200
|
||||
// {secret}
|
||||
#define TRPGHEAD_LODINFO 201
|
||||
|
||||
// {secret}
|
||||
#define TRPGMATTABLE 300
|
||||
// Added 11/14/98 - New material table
|
||||
// {secret}
|
||||
#define TRPGMATTABLE2 301
|
||||
// Added 11/14/98
|
||||
// {secret}
|
||||
#define TRPGSHORTMATTABLE 302
|
||||
|
||||
// {secret}
|
||||
#define TRPGMATERIAL 400
|
||||
// {secret}
|
||||
#define TRPGMAT_BASIC 401
|
||||
// {secret}
|
||||
#define TRPGMAT_SHADE 402
|
||||
// {secret}
|
||||
// {secret}
|
||||
#define TRPGMAT_SIZES 403
|
||||
// {secret}
|
||||
#define TRPGMAT_CULL 404
|
||||
// {secret}
|
||||
#define TRPGMAT_ALPHA 405
|
||||
// {secret}
|
||||
#define TRPGMAT_NORMAL 406
|
||||
// {secret}
|
||||
#define TRPGMAT_TEXTURE 407
|
||||
|
||||
// {secret}
|
||||
#define TRPGMAT_TEXENV 500
|
||||
// {secret}
|
||||
#define TRPGMAT_TXENV_MODE 501
|
||||
// {secret}
|
||||
#define TRPGMAT_TXENV_FILTER 502
|
||||
// {secret}
|
||||
#define TRPGMAT_TXENV_WRAP 503
|
||||
// {secret}
|
||||
#define TRPGMAT_TXENV_BORDER 504
|
||||
|
||||
// {secret}
|
||||
#define TRPGTEXTABLE 600
|
||||
|
||||
// {secret}
|
||||
#define TRPGMODELREF 700
|
||||
|
||||
// {secret}
|
||||
#define TRPGMODELTABLE 800
|
||||
|
||||
// {secret}
|
||||
#define TRPGTILETABLE 900
|
||||
// {secret}
|
||||
#define TRPG_TILE_ENTRY 901
|
||||
|
||||
// {secret}
|
||||
#define TRPGTILEHEADER 1000
|
||||
// {secret}
|
||||
#define TRPG_TILE_MATLIST 1001
|
||||
// {secret}
|
||||
#define TRPG_TILE_MODELLIST 1002
|
||||
// {secret}
|
||||
#define TRPG_TILE_DATE 1003
|
||||
|
||||
// {secret}
|
||||
#define TRPG_GROUP 2001
|
||||
// {secret}
|
||||
#define TRPG_BILLBOARD 2002
|
||||
// {secret}
|
||||
#define TRPG_LOD 2003
|
||||
// {secret}
|
||||
#define TRPG_TRANSFORM 2004
|
||||
// {secret}
|
||||
#define TRPG_MODELREF 2005
|
||||
// {secret}
|
||||
#define TRPG_LAYER 2006
|
||||
|
||||
// {secret}
|
||||
#define TRPG_GEOMETRY 3000
|
||||
// {secret}
|
||||
#define TRPG_GEOM_PRIM 3001
|
||||
// {secret}
|
||||
#define TRPG_GEOM_MATERIAL 3002
|
||||
// {secret}
|
||||
#define TRPG_GEOM_VERT32 3003
|
||||
// {secret}
|
||||
#define TRPG_GEOM_VERT64 3004
|
||||
// {secret}
|
||||
#define TRPG_GEOM_NORM32 3005
|
||||
// {secret}
|
||||
#define TRPG_GEOM_NORM64 3006
|
||||
// {secret}
|
||||
#define TRPG_GEOM_COLOR 3007
|
||||
// {secret}
|
||||
#define TRPG_GEOM_TEX32 3008
|
||||
// {secret}
|
||||
#define TRPG_GEOM_TEX64 3009
|
||||
// {secret}
|
||||
#define TRPG_GEOM_EFLAG 3010
|
||||
|
||||
// {secret}
|
||||
#define TRPG_ATTACH 4000
|
||||
|
||||
// {secret}
|
||||
#define TRPG_MAXTOKEN 4000
|
||||
|
||||
// Basic data types
|
||||
|
||||
/* 64 bit disk reference value. */
|
||||
typedef trpgllong trpgDiskRef;
|
||||
// {secret}
|
||||
typedef int trpgMatRef;
|
||||
|
||||
/* Double precision 2 dimensional point. */
|
||||
TX_EXDECL class TX_CLDECL trpg2dPoint {
|
||||
public:
|
||||
double x, y;
|
||||
trpg2dPoint (void) { };
|
||||
trpg2dPoint (double in_x,double in_y) { x = in_x; y = in_y; };
|
||||
};
|
||||
/* Integer 2 dimensional point. This is used primarily as a 2D index value. */
|
||||
TX_EXDECL class TX_CLDECL trpg2iPoint {
|
||||
public:
|
||||
int x,y;
|
||||
trpg2iPoint (void) { };
|
||||
trpg2iPoint (int in_x,int in_y) {x = in_x; y = in_y;};
|
||||
};
|
||||
/* Double precision 3 dimensional point. */
|
||||
TX_EXDECL class TX_CLDECL trpg3dPoint {
|
||||
public:
|
||||
double x,y,z;
|
||||
trpg3dPoint(void) { };
|
||||
trpg3dPoint(double in_x,double in_y,double in_z) {x = in_x; y = in_y; z = in_z;}
|
||||
};
|
||||
/* Simple red, green, blue color definition */
|
||||
TX_EXDECL class TX_CLDECL trpgColor {
|
||||
public:
|
||||
trpgColor(float64 r,float64 g,float64 b) {red = r; green = g; blue = b;}
|
||||
trpgColor(void) { };
|
||||
float64 red,green,blue;
|
||||
};
|
||||
|
||||
// Used to specify machine endianess
|
||||
typedef enum {LittleEndian,BigEndian} trpgEndian;
|
||||
|
||||
/* This is a base class for an abstract buffer type.
|
||||
It contains the virtual methods for writing
|
||||
data to an abstract device. The device implementation is up
|
||||
to the subclass. trpgReadBuffer performs the similar function
|
||||
for reading.
|
||||
{group:Low Level I/O}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgWriteBuffer {
|
||||
public:
|
||||
virtual ~trpgWriteBuffer(void) { };
|
||||
/* The add functions must be filled in by the child class
|
||||
They add data of the appropriate type to the current buffer. */
|
||||
virtual void Add(int32) = 0;
|
||||
virtual void Add(int64) = 0;
|
||||
virtual void Add(const char *) = 0;
|
||||
virtual void Add(float32) = 0;
|
||||
virtual void Add(float64) = 0;
|
||||
#if (bool != int32)
|
||||
virtual void Add(bool) = 0;
|
||||
#endif
|
||||
virtual void Add(uint8) = 0;
|
||||
#if (trpgDiskRef != int64)
|
||||
virtual void Add(trpgDiskRef) = 0;
|
||||
#endif
|
||||
// Add a token (16 bit) to the buffer
|
||||
virtual void Add(trpgToken) = 0;
|
||||
|
||||
/* Child class method. Returns the buffer to an original state. */
|
||||
virtual void Reset(void) = 0;
|
||||
// See trpgMemWriteBuffer for details
|
||||
virtual void Begin(trpgToken) = 0;
|
||||
// See trpgMemWriteBuffer for details
|
||||
virtual void End(void) = 0;
|
||||
// See trpgMemWriteBuffer for details
|
||||
virtual void Push(void) = 0;
|
||||
// See trpgMemWriteBuffer for details
|
||||
virtual void Pop(void) = 0;
|
||||
|
||||
// Some add functions are helpers for composite values that call the basic add functions
|
||||
void Add(const trpg2iPoint &);
|
||||
void Add(const trpg2dPoint &);
|
||||
void Add(const trpg3dPoint &);
|
||||
void Add(const trpgColor &);
|
||||
|
||||
/* Endianness is something the child class buffer type must set and use.
|
||||
This function returns the endiannes of the current buffer. */
|
||||
virtual trpgEndian GetEndian(void) { return ness; }
|
||||
|
||||
protected:
|
||||
// Target endianness of the buffer. This should be set by the subclass on creation.
|
||||
trpgEndian ness;
|
||||
// Endianness of the machine we're running on.
|
||||
trpgEndian cpuNess;
|
||||
};
|
||||
|
||||
/* The Memory Write Buffer is an implementation of the Write Buffer that
|
||||
uses chunks of memory. It contains implementations of the all the virtual
|
||||
methods straight to memory. This is used primarily in writing archives and
|
||||
tiles.
|
||||
{group:Low Level I/O}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgMemWriteBuffer : public trpgWriteBuffer {
|
||||
public:
|
||||
/* The constructor takes an endianness for this buffer.
|
||||
Data will automatically be converted to that as it goes in. */
|
||||
trpgMemWriteBuffer(trpgEndian);
|
||||
virtual ~trpgMemWriteBuffer(void);
|
||||
// Return the current length of buffer
|
||||
virtual int length(void) const;
|
||||
// Return the raw data (if you want to write to disk, for example)
|
||||
virtual const char *getData(void) const;
|
||||
// Allocate the given amount of space for the buffer
|
||||
virtual void setLength(unsigned int);
|
||||
|
||||
// Add a 32 bit integer to the buffer
|
||||
virtual void Add(int32);
|
||||
// Add a 64 bit integer to the buffer
|
||||
virtual void Add(int64);
|
||||
/* Add an arbitrary length string to the buffer.
|
||||
This writes both the length and the string itself.
|
||||
*/
|
||||
virtual void Add(const char *);
|
||||
// Add a 32 bit float to the buffer
|
||||
virtual void Add(float32);
|
||||
// Add a 64 bit float to the buffer
|
||||
virtual void Add(float64);
|
||||
#if (bool != int32)
|
||||
// Add a boolean value to the buffer. It will become at least one byte.
|
||||
virtual void Add(bool);
|
||||
#endif
|
||||
// Add an unsigned character to the buffer
|
||||
virtual void Add(uint8);
|
||||
#if (trpgDiskRef != int64)
|
||||
// Add a 64 bit disk reference to the buffer
|
||||
virtual void Add(trpgDiskRef);
|
||||
#endif
|
||||
// Add a token (16 bit) to the buffer
|
||||
virtual void Add(trpgToken);
|
||||
// Reset this buffer. This will set the current length to zero, but will not deallocate memory
|
||||
virtual void Reset(void);
|
||||
/* Start defining an tokenized object. The token is put into the buffer stream
|
||||
and the position of a size value following it is kept. When End() is called
|
||||
the buffer will rewind to that value and save the size. This method ensures
|
||||
that token data can be skipped if necessary. */
|
||||
virtual void Begin(trpgToken);
|
||||
/* This method is called at the end of a tokenized object. See Begin for details. */
|
||||
virtual void End(void);
|
||||
/* Adds the TRPG_PUSH token to the current buffer. This is done by objects
|
||||
that have children as they're being written. See Pop as well. */
|
||||
virtual void Push(void);
|
||||
/* Adds the TRPG_POP token to the current buffer. This is done by objects
|
||||
that have defined children. See Push. */
|
||||
virtual void Pop(void);
|
||||
|
||||
protected:
|
||||
virtual void append(unsigned int,const char *);
|
||||
virtual void set(unsigned int pos,unsigned int len,const char *);
|
||||
int curLen;
|
||||
int totLen;
|
||||
char *data;
|
||||
vector<int> lengths;
|
||||
};
|
||||
|
||||
/* This is a virtual base class for reading data from a device.
|
||||
The device implementation is left as an excercise to the sub class.
|
||||
This class contains methods for getting data that must be filled in
|
||||
as well as helper methods that call those.
|
||||
{group:Low Level I/O}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgReadBuffer {
|
||||
public:
|
||||
virtual ~trpgReadBuffer(void) { };
|
||||
/* The Get methods are utility routines that all call the GetData method.
|
||||
Only that method need be filled in by a subclass. */
|
||||
virtual bool Get(int32 &);
|
||||
virtual bool Get(int64 &);
|
||||
virtual bool Get(char *,int);
|
||||
virtual bool Get(float32 &);
|
||||
virtual bool Get(float64 &);
|
||||
#if (bool != int32)
|
||||
virtual bool Get(bool &);
|
||||
#endif
|
||||
virtual bool Get(uint8 &);
|
||||
#if (trpgDiskRef != int64)
|
||||
virtual bool Get(trpgDiskRef &);
|
||||
#endif
|
||||
virtual bool Get(trpgToken &);
|
||||
|
||||
/* These methods return references to arrays of data of the given types.
|
||||
These are all utility routines and depend upon GetDataRef. */
|
||||
virtual bool GetArray(int,float32 **);
|
||||
virtual bool GetArray(int,float64 **);
|
||||
virtual bool GetArray(int,int32 **);
|
||||
virtual bool GetArray(int,trpgColor **);
|
||||
virtual bool GetArray(int,char **);
|
||||
|
||||
virtual bool Get(trpg2iPoint &);
|
||||
virtual bool Get(trpg2dPoint &);
|
||||
virtual bool Get(trpg3dPoint &);
|
||||
virtual bool Get(trpgColor &);
|
||||
virtual bool GetToken(trpgToken &,int32 &);
|
||||
|
||||
/* Force the buffer to only allow the next N bytes to be read.
|
||||
The limits are stack based. That is, this limit is the current one
|
||||
until it's popped off the stack. Then it reverts to the previous one.
|
||||
Any bytes read in the mean time count against all limits. */
|
||||
virtual void PushLimit(int);
|
||||
/* Revert to the limit before this one. Typically this would happen when
|
||||
a tokenized object has been read. */
|
||||
virtual void PopLimit(void);
|
||||
/* Skip to the end of the current limit. This is done by a parser when
|
||||
reading a tokenized object from the buffer to make sure that the next
|
||||
object can be safely read even if the current one wasn't. */
|
||||
virtual bool SkipToLimit(void);
|
||||
|
||||
// Buffer is empty
|
||||
virtual bool isEmpty(void) = 0;
|
||||
|
||||
protected:
|
||||
trpgEndian ness; // Endianness of the source we're reading
|
||||
trpgEndian cpuNess; // Endiannees of the CPU
|
||||
/* Virtual raw data retrieval function that must be implemented by a subclass.
|
||||
It must return a given number of bytes in the array passed in. */
|
||||
virtual bool GetData(char *,int)=0;
|
||||
/* Virtual raw data reference retrieval function. The difference between
|
||||
this method and GetData is that this is supposed to return a pointer
|
||||
to a given amount of bytes. This assumes some sort of memory caching
|
||||
mechanism in the subclass. */
|
||||
virtual bool GetDataRef(char **,int)=0;
|
||||
/* This virtual method must be filled in by the subclass so that SkipToLimit
|
||||
will work correctly. */
|
||||
virtual bool Skip(int) = 0;
|
||||
/* A utility function for subclasses to use to see if they would exceed an
|
||||
outside imposed limit by reading the given number of bytes. */
|
||||
virtual bool TestLimit(int);
|
||||
/* Utility function that must be called after a successfull read to update
|
||||
the outside imposed read limits. */
|
||||
virtual void UpdateLimits(int);
|
||||
vector<int> limits;
|
||||
};
|
||||
|
||||
/* This class implements a read buffer that uses a chunk of memory.
|
||||
Typically, raw data will be dumped into this class, then it will be
|
||||
passed to a parser for object based reading.
|
||||
{group:Low Level I/O}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgMemReadBuffer : public trpgReadBuffer {
|
||||
public:
|
||||
// Memory read buffers must be initialized with an endianness
|
||||
trpgMemReadBuffer(trpgEndian);
|
||||
~trpgMemReadBuffer(void);
|
||||
// Return true if we're out of data
|
||||
bool isEmpty(void);
|
||||
// Sets the size of this read buffer.
|
||||
void SetLength(int);
|
||||
/* Return a pointer to the raw data cache for this object. Data will
|
||||
be dumped straight into here (from disk, for example) and then parsed
|
||||
by something that takes a trpgReadBuffer as input. */
|
||||
char *GetDataPtr(void);
|
||||
protected:
|
||||
bool GetData(char *,int); // Retrieve the given amount of data
|
||||
bool GetDataRef(char **,int); // Retrieve a pointer to the given array
|
||||
bool Skip(int); // Skip over the given amount
|
||||
int len; // Data Length
|
||||
int totLen; // Total allocated length
|
||||
int pos; // Current position
|
||||
char *data;
|
||||
};
|
||||
|
||||
/* A Checkable is purely a base class used by other classes that
|
||||
need validity checks associated with them. By default, the
|
||||
checkable will return false for isValid unless the valid flag is set.
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgCheckable {
|
||||
public:
|
||||
trpgCheckable(void);
|
||||
virtual ~trpgCheckable(void);
|
||||
// Returns the state of the valid flag, or can be overriden by a subclass to do a more complex check.
|
||||
bool isValid(void) const;
|
||||
protected:
|
||||
/* Set this flag to true if your checkable structure doesn't have a complex
|
||||
check it needs to do. */
|
||||
bool valid;
|
||||
};
|
||||
|
||||
/* The Read/Writeable is a class that knows how to read itself from a trpgReadBuffer
|
||||
and write itself to a trpgWriteBuffer. This includes all the node and header
|
||||
data in TerraPage. These classes are intended as marshalling points for reading
|
||||
and writing data, not as data containers in and of themselves. If you find
|
||||
yourself keeping a lot of classes derived from trpgReadWriteable around, you're
|
||||
probably misusing them.
|
||||
|
||||
The classes derived from this one will have a lot of methods that begin with
|
||||
"Set", "Get", and "Add". These will almost always return a bool value. This
|
||||
is used to indicate whether the given call succeeded. In the case of "Set" and "Add" calls
|
||||
this should always work if it possibly can. An out of range index might make it
|
||||
fail, for example. "Get" calls will always fail if the object you're getting from
|
||||
is not valid. Be sure to do an isValid check as soon as you've read or filled out
|
||||
one of these objects.
|
||||
{group:Read/Write Classes}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgReadWriteable : public trpgCheckable {
|
||||
public:
|
||||
/* The Write method is a virtual that must be filled in by the subclass.
|
||||
It takes a trpgWriteBuffer and should return true on success. */
|
||||
virtual bool Write(trpgWriteBuffer &) = 0;
|
||||
/* The Read method should be overriden by a subclass. It should read
|
||||
the contents of the given trpgReadBuffer up to the current limit
|
||||
into itself. It must return true on success. */
|
||||
virtual bool Read(trpgReadBuffer &) { return false;};
|
||||
/* Every read/writeable must be able to reset itself to a pristine state
|
||||
so that, for example, multiple objects of the same type can be read into
|
||||
it, one after the other. */
|
||||
virtual void Reset(void) = 0;
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif
|
||||
31
src/osgPlugins/txp/trpage_main.cpp
Normal file
31
src/osgPlugins/txp/trpage_main.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
/* trpage_main.cpp
|
||||
This file is here to provide a DLL Main.
|
||||
Note: #ifdef this out on non-windows machines
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "trdll.h"
|
||||
|
||||
TXDUMMY_DLL_MAIN
|
||||
1184
src/osgPlugins/txp/trpage_material.cpp
Normal file
1184
src/osgPlugins/txp/trpage_material.cpp
Normal file
File diff suppressed because it is too large
Load Diff
325
src/osgPlugins/txp/trpage_model.cpp
Normal file
325
src/osgPlugins/txp/trpage_model.cpp
Normal file
@@ -0,0 +1,325 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* trpage_mode.cpp
|
||||
This source file contains the methods trpgModel and trpgModelTable.
|
||||
You should only modify this code if you want to add data to these classes.
|
||||
*/
|
||||
|
||||
#include "trpage_geom.h"
|
||||
#include "trpage_read.h"
|
||||
|
||||
/* Write Model class
|
||||
Represents a model reference.
|
||||
*/
|
||||
trpgModel::trpgModel()
|
||||
{
|
||||
name = NULL;
|
||||
type = External;
|
||||
useCount = 0;
|
||||
}
|
||||
trpgModel::trpgModel(const trpgModel &in)
|
||||
{
|
||||
name = NULL;
|
||||
type = External;
|
||||
*this = in;
|
||||
}
|
||||
|
||||
// Reset function
|
||||
void trpgModel::Reset()
|
||||
{
|
||||
if (name)
|
||||
delete name;
|
||||
name = NULL;
|
||||
useCount = 0;
|
||||
}
|
||||
|
||||
trpgModel::~trpgModel()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgModel::SetName(const char *nm)
|
||||
{
|
||||
if (name)
|
||||
delete name;
|
||||
|
||||
name = new char[(nm ? strlen(nm) : 0)+1];
|
||||
strcpy(name,nm);
|
||||
|
||||
type = External;
|
||||
}
|
||||
void trpgModel::SetReference(trpgDiskRef pos)
|
||||
{
|
||||
if (name)
|
||||
delete name;
|
||||
|
||||
diskRef = pos;
|
||||
|
||||
type = Local;
|
||||
}
|
||||
void trpgModel::SetNumTiles(int num)
|
||||
{
|
||||
useCount = num;
|
||||
}
|
||||
void trpgModel::AddTile()
|
||||
{
|
||||
useCount++;
|
||||
}
|
||||
|
||||
// Validity check
|
||||
bool trpgModel::isValid() const
|
||||
{
|
||||
if (type == External && !name)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copy from one to another
|
||||
trpgModel& trpgModel::operator = (const trpgModel &in)
|
||||
{
|
||||
if (name) {
|
||||
delete name;
|
||||
name = NULL;
|
||||
}
|
||||
|
||||
type = in.type;
|
||||
if (in.name)
|
||||
SetName(in.name);
|
||||
diskRef = in.diskRef;
|
||||
useCount = in.useCount;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compare two models
|
||||
int trpgModel::operator == (const trpgModel &in) const
|
||||
{
|
||||
if (type != in.type)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case Local:
|
||||
if (diskRef == in.diskRef)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
case External:
|
||||
if (!name && !in.name)
|
||||
return 1;
|
||||
if (!name || !in.name)
|
||||
return 0;
|
||||
if (strcmp(name,in.name))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Write a model reference out
|
||||
bool trpgModel::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPGMODELREF);
|
||||
buf.Add(type);
|
||||
if (name)
|
||||
buf.Add(name);
|
||||
else
|
||||
buf.Add(diskRef);
|
||||
buf.Add(useCount);
|
||||
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* *******************
|
||||
Model Read Methods
|
||||
*******************
|
||||
*/
|
||||
// Get methods
|
||||
bool trpgModel::GetType(int &t)
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
t = type;
|
||||
return true;
|
||||
}
|
||||
bool trpgModel::GetName(char *str,int strLen) const
|
||||
{
|
||||
if (!isValid() || type != External) return false;
|
||||
int len = (name ? strlen(name) : 0);
|
||||
strncpy(str,name,MIN(len,strLen)+1);
|
||||
return true;
|
||||
}
|
||||
bool trpgModel::GetNumTiles(int &ret) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
|
||||
ret = useCount;
|
||||
return true;
|
||||
}
|
||||
bool trpgModel::GetReference(trpgDiskRef &ref) const
|
||||
{
|
||||
if (!isValid() || type != Local) return false;
|
||||
ref = diskRef;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool trpgModel::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
char tmpName[1024];
|
||||
|
||||
try {
|
||||
buf.Get(type);
|
||||
if (type == Local)
|
||||
buf.Get(diskRef);
|
||||
else {
|
||||
buf.Get(tmpName,1023);
|
||||
SetName(tmpName);
|
||||
}
|
||||
buf.Get(useCount);
|
||||
}
|
||||
catch(...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
/* Write Model Reference table
|
||||
Groups of models for the entire file.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgModelTable::trpgModelTable()
|
||||
{
|
||||
}
|
||||
trpgModelTable::~trpgModelTable()
|
||||
{
|
||||
}
|
||||
|
||||
// Reset function
|
||||
void trpgModelTable::Reset()
|
||||
{
|
||||
models.resize(0);
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgModelTable::SetNumModels(int no)
|
||||
{
|
||||
models.resize(no);
|
||||
}
|
||||
void trpgModelTable::SetModel(int id,const trpgModel &mod)
|
||||
{
|
||||
if (id < 0 || (unsigned int)id >= models.size())
|
||||
return;
|
||||
|
||||
models[id] = mod;
|
||||
}
|
||||
int trpgModelTable::AddModel(const trpgModel &mod)
|
||||
{
|
||||
models.push_back(mod);
|
||||
|
||||
return models.size()-1;
|
||||
}
|
||||
|
||||
// Validity check
|
||||
bool trpgModelTable::isValid() const
|
||||
{
|
||||
for (unsigned int i=0;i<models.size();i++)
|
||||
if (!models[i].isValid())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write out the model table
|
||||
bool trpgModelTable::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPGMODELTABLE);
|
||||
buf.Add((int32)models.size());
|
||||
for (unsigned int i=0;i<models.size();i++)
|
||||
models[i].Write(buf);
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ***************
|
||||
Model Table Read methods
|
||||
***************
|
||||
*/
|
||||
|
||||
// Get methods
|
||||
bool trpgModelTable::GetNumModels(int &nm) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
nm = models.size();
|
||||
return true;
|
||||
}
|
||||
bool trpgModelTable::GetModel(int id,trpgModel &model) const
|
||||
{
|
||||
if (!isValid() || id < 0 || (unsigned int)id >= models.size())
|
||||
return false;
|
||||
model = models[id];
|
||||
return true;
|
||||
}
|
||||
trpgModel *trpgModelTable::GetModelRef(int id)
|
||||
{
|
||||
if (id < 0 || (unsigned int)id >= models.size())
|
||||
return NULL;
|
||||
return &models[id];
|
||||
}
|
||||
|
||||
bool trpgModelTable::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
int32 numModel;
|
||||
trpgModel model;
|
||||
trpgToken tok;
|
||||
int32 len;
|
||||
bool status;
|
||||
|
||||
try {
|
||||
buf.Get(numModel);
|
||||
for (int i=0;i<numModel;i++) {
|
||||
buf.GetToken(tok,len);
|
||||
if (tok != TRPGMODELREF) throw 1;
|
||||
buf.PushLimit(len);
|
||||
status = model.Read(buf);
|
||||
buf.PopLimit();
|
||||
if (!status) throw 1;
|
||||
models.push_back(model);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValid();
|
||||
}
|
||||
640
src/osgPlugins/txp/trpage_nodes.cpp
Normal file
640
src/osgPlugins/txp/trpage_nodes.cpp
Normal file
@@ -0,0 +1,640 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* trpage_nodes.cpp
|
||||
The methods for all the hierarchy nodes (e.g. groups, transforms, etc...)
|
||||
is here.
|
||||
You should only need to modify this if you want to add something to one
|
||||
of these classes.
|
||||
*/
|
||||
|
||||
#include "trpage_geom.h"
|
||||
#include "trpage_read.h"
|
||||
|
||||
/* Write Group
|
||||
Basic group.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgGroup::trpgGroup()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
trpgGroup::~trpgGroup()
|
||||
{
|
||||
}
|
||||
|
||||
// Reset
|
||||
void trpgGroup::Reset()
|
||||
{
|
||||
numChild = 0;
|
||||
id = -1;
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgGroup::SetNumChild(int no)
|
||||
{
|
||||
numChild = no;
|
||||
}
|
||||
int trpgGroup::AddChild()
|
||||
{
|
||||
numChild++;
|
||||
return numChild-1;
|
||||
}
|
||||
void trpgGroup::SetID(int inID)
|
||||
{
|
||||
id = inID;
|
||||
}
|
||||
|
||||
// Get methods
|
||||
bool trpgGroup::GetNumChild(int &n) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
n = numChild;
|
||||
return true;
|
||||
}
|
||||
bool trpgGroup::GetID(int &inID) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
inID = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validity check
|
||||
bool trpgGroup::isValid() const
|
||||
{
|
||||
if (numChild <= 0) return false;
|
||||
if (id < 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write group
|
||||
bool trpgGroup::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPG_GROUP);
|
||||
buf.Add(numChild);
|
||||
buf.Add(id);
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read group
|
||||
bool trpgGroup::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
try {
|
||||
buf.Get(numChild);
|
||||
if (numChild < 0) throw 1;
|
||||
buf.Get(id);
|
||||
if (id < 0) throw 1;
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
/* Write Billboard
|
||||
Represents rotational billboarded geometry.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgBillboard::trpgBillboard()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
trpgBillboard::~trpgBillboard()
|
||||
{
|
||||
}
|
||||
|
||||
// Reset function
|
||||
void trpgBillboard::Reset()
|
||||
{
|
||||
id = -1;
|
||||
mode = Axial;
|
||||
type = Group;
|
||||
axis = trpg3dPoint(0,0,1);
|
||||
center = trpg3dPoint(0,0,0);
|
||||
numChild = 0;
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgBillboard::SetCenter(const trpg3dPoint &pt)
|
||||
{
|
||||
center = pt;
|
||||
valid = true;
|
||||
}
|
||||
void trpgBillboard::SetMode(int m)
|
||||
{
|
||||
mode = m;
|
||||
}
|
||||
void trpgBillboard::SetAxis(const trpg3dPoint &pt)
|
||||
{
|
||||
axis = pt;
|
||||
}
|
||||
void trpgBillboard::SetType(int t)
|
||||
{
|
||||
type = t;
|
||||
}
|
||||
|
||||
// Get methods
|
||||
bool trpgBillboard::GetCenter(trpg3dPoint &pt) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
pt = center;
|
||||
return true;
|
||||
}
|
||||
bool trpgBillboard::GetMode(int &m) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
m = mode;
|
||||
return true;
|
||||
}
|
||||
bool trpgBillboard::GetAxis(trpg3dPoint &pt) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
pt = axis;
|
||||
return true;
|
||||
}
|
||||
bool trpgBillboard::GetType(int &t) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
t = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write billboard
|
||||
bool trpgBillboard::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPG_BILLBOARD);
|
||||
buf.Add(numChild);
|
||||
buf.Add(id);
|
||||
buf.Add((uint8)type);
|
||||
buf.Add((uint8)mode);
|
||||
buf.Add(center);
|
||||
buf.Add(axis);
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read billboard
|
||||
bool trpgBillboard::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
uint8 uChar;
|
||||
|
||||
try {
|
||||
buf.Get(numChild);
|
||||
buf.Get(id);
|
||||
buf.Get(uChar); type = uChar;
|
||||
buf.Get(uChar); mode = uChar;
|
||||
buf.Get(center);
|
||||
buf.Get(axis);
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
/* Write Level of Detail
|
||||
Represents LOD information.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgLod::trpgLod()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
trpgLod::~trpgLod()
|
||||
{
|
||||
}
|
||||
|
||||
// Reset function
|
||||
void trpgLod::Reset()
|
||||
{
|
||||
id = -1;
|
||||
numRange = 0;
|
||||
center = trpg3dPoint(0,0,0);
|
||||
switchIn = switchOut = width = 0;
|
||||
valid = true;
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgLod::SetCenter(const trpg3dPoint &pt)
|
||||
{
|
||||
center = pt;
|
||||
valid = true;
|
||||
}
|
||||
void trpgLod::SetNumChild(int no)
|
||||
{
|
||||
if (no < 0)
|
||||
return;
|
||||
|
||||
numRange = no;
|
||||
}
|
||||
void trpgLod::SetLOD(double in,double out,double wid)
|
||||
{
|
||||
switchIn = in;
|
||||
switchOut = out;
|
||||
width = wid;
|
||||
}
|
||||
void trpgLod::SetID(int inID)
|
||||
{
|
||||
id = inID;
|
||||
}
|
||||
|
||||
// Get functions
|
||||
bool trpgLod::GetCenter(trpg3dPoint &pt) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
pt = center;
|
||||
return true;
|
||||
}
|
||||
bool trpgLod::GetNumChild(int &n) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
n = numRange;
|
||||
return true;
|
||||
}
|
||||
bool trpgLod::GetLOD(double &in,double &out,double &wid) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
in = switchIn;
|
||||
out = switchOut;
|
||||
wid = width;
|
||||
return true;
|
||||
}
|
||||
bool trpgLod::GetID(int &outID) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
outID = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write out LOD
|
||||
bool trpgLod::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPG_LOD);
|
||||
buf.Add(id);
|
||||
buf.Add(numRange);
|
||||
buf.Add(center);
|
||||
buf.Add(switchIn);
|
||||
buf.Add(switchOut);
|
||||
buf.Add(width);
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read in LOD
|
||||
bool trpgLod::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
try {
|
||||
buf.Get(id);
|
||||
buf.Get(numRange);
|
||||
if (numRange < 0) throw 1;
|
||||
buf.Get(center);
|
||||
buf.Get(switchIn);
|
||||
buf.Get(switchOut);
|
||||
buf.Get(width);
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
/* Write Layer
|
||||
A layer is just a group with a different opcode.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgLayer::trpgLayer()
|
||||
{
|
||||
}
|
||||
|
||||
trpgLayer::~trpgLayer()
|
||||
{
|
||||
}
|
||||
|
||||
// Write it
|
||||
bool trpgLayer::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPG_LAYER);
|
||||
buf.Add(numChild);
|
||||
buf.Add(id);
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read layer
|
||||
bool trpgLayer::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
try {
|
||||
buf.Get(numChild);
|
||||
if (numChild < 0) throw 1;
|
||||
buf.Get(id);
|
||||
if (id < 0) throw 1;
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
// Reset function
|
||||
void trpgLayer::Reset()
|
||||
{
|
||||
numChild = 0;
|
||||
}
|
||||
|
||||
/* Write Transform
|
||||
Matrix defining the transform with children.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgTransform::trpgTransform()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
trpgTransform::~trpgTransform()
|
||||
{
|
||||
}
|
||||
|
||||
// Reset function
|
||||
void trpgTransform::Reset()
|
||||
{
|
||||
id = -1;
|
||||
// Note: Is this row major or column major?
|
||||
m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
|
||||
m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0;
|
||||
m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0;
|
||||
m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgTransform::SetMatrix(const float64 *im)
|
||||
{
|
||||
m[0][0] = im[4*0+0]; m[0][1] = im[4*0+1]; m[0][2] = im[4*0+2]; m[0][3] = im[4*0+3];
|
||||
m[1][0] = im[4*1+0]; m[1][1] = im[4*1+1]; m[1][2] = im[4*1+2]; m[1][3] = im[4*1+3];
|
||||
m[2][0] = im[4*2+0]; m[2][1] = im[4*2+1]; m[2][2] = im[4*2+2]; m[2][3] = im[4*2+3];
|
||||
m[3][0] = im[4*3+0]; m[3][1] = im[4*3+1]; m[3][2] = im[4*3+2]; m[3][3] = im[4*3+3];
|
||||
}
|
||||
|
||||
// Get methods
|
||||
bool trpgTransform::GetMatrix(float64 *rm) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
for (int i=0;i<4;i++)
|
||||
for (int j=0;j<4;j++)
|
||||
// Note: is this right?
|
||||
rm[i*4+j] = m[i][j];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write transform
|
||||
bool trpgTransform::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPG_TRANSFORM);
|
||||
buf.Add(numChild);
|
||||
buf.Add(id);
|
||||
for (int i=0;i<4;i++)
|
||||
for (int j=0;j<4;j++)
|
||||
buf.Add(m[i][j]);
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read transform
|
||||
bool trpgTransform::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
try {
|
||||
buf.Get(numChild);
|
||||
buf.Get(id);
|
||||
if (numChild < 0) throw 1;
|
||||
for (int i=0;i<4;i++)
|
||||
for (int j=0;j<4;j++)
|
||||
buf.Get(m[i][j]);
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
/* Model Reference
|
||||
This is just a matrix transform and a model ID.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgModelRef::trpgModelRef()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
trpgModelRef::~trpgModelRef()
|
||||
{
|
||||
}
|
||||
|
||||
// Reset function
|
||||
void trpgModelRef::Reset()
|
||||
{
|
||||
m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
|
||||
m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0;
|
||||
m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0;
|
||||
m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
|
||||
modelRef = -1;
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgModelRef::SetModel(int id)
|
||||
{
|
||||
modelRef = id;
|
||||
valid = true;
|
||||
}
|
||||
void trpgModelRef::SetMatrix(const float64 *im)
|
||||
{
|
||||
m[0][0] = im[4*0+0]; m[0][1] = im[4*0+1]; m[0][2] = im[4*0+2]; m[0][3] = im[4*0+3];
|
||||
m[1][0] = im[4*1+0]; m[1][1] = im[4*1+1]; m[1][2] = im[4*1+2]; m[1][3] = im[4*1+3];
|
||||
m[2][0] = im[4*2+0]; m[2][1] = im[4*2+1]; m[2][2] = im[4*2+2]; m[2][3] = im[4*2+3];
|
||||
m[3][0] = im[4*3+0]; m[3][1] = im[4*3+1]; m[3][2] = im[4*3+2]; m[3][3] = im[4*3+3];
|
||||
}
|
||||
|
||||
// Get methods
|
||||
bool trpgModelRef::GetModel(int32 &mod) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
mod = modelRef;
|
||||
return true;
|
||||
}
|
||||
bool trpgModelRef::GetMatrix(float64 *rm) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
for (int i=0;i<4;i++)
|
||||
for (int j=0;j<4;j++)
|
||||
// Note: is this right?
|
||||
rm[i*4+j] = m[i][j];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write model reference
|
||||
bool trpgModelRef::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPG_MODELREF);
|
||||
buf.Add(modelRef);
|
||||
for (int i=0;i<4;i++)
|
||||
for (int j=0;j<4;j++)
|
||||
buf.Add(m[i][j]);
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read model reference
|
||||
bool trpgModelRef::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
try {
|
||||
buf.Get(modelRef);
|
||||
if (modelRef < 0) throw 1;
|
||||
for (int i=0;i<4;i++)
|
||||
for (int j=0;j<4;j++)
|
||||
buf.Get(m[i][j]);
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
valid = true;
|
||||
return isValid();
|
||||
}
|
||||
|
||||
/* Attach Node
|
||||
You'll find one of these in each tile, except for the lowest LOD.
|
||||
It's basically a group with some extra info that tells you where to attach it.
|
||||
The ID corresponds to the one in Group and LOD.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgAttach::trpgAttach()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
trpgAttach::~trpgAttach()
|
||||
{
|
||||
}
|
||||
|
||||
// Reset
|
||||
void trpgAttach::Reset()
|
||||
{
|
||||
parentID = -1;
|
||||
childPos = -1;
|
||||
}
|
||||
|
||||
// Parent ID is the node this one gets attached to
|
||||
void trpgAttach::SetParentID(int id)
|
||||
{
|
||||
parentID = id;
|
||||
}
|
||||
bool trpgAttach::GetParentID(int &id) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
id = parentID;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Child Position is a unique number of parent
|
||||
// It could be used as an array index, for example
|
||||
void trpgAttach::SetChildPos(int id)
|
||||
{
|
||||
childPos = id;
|
||||
}
|
||||
bool trpgAttach::GetChildPos(int &id) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
id = childPos;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validity check
|
||||
bool trpgAttach::isValid() const
|
||||
{
|
||||
if (parentID < 0 || childPos < 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write Attach node
|
||||
bool trpgAttach::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
|
||||
buf.Begin(TRPG_ATTACH);
|
||||
buf.Add(numChild);
|
||||
buf.Add(id);
|
||||
buf.Add(parentID);
|
||||
buf.Add(childPos);
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read Attach node
|
||||
bool trpgAttach::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
try {
|
||||
buf.Get(numChild);
|
||||
buf.Get(id);
|
||||
if (id < 0) throw 1;
|
||||
buf.Get(parentID);
|
||||
if (parentID < 0) throw 1;
|
||||
buf.Get(childPos);
|
||||
if (childPos < 0) throw 1;
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
266
src/osgPlugins/txp/trpage_parse.cpp
Normal file
266
src/osgPlugins/txp/trpage_parse.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* trpage_parse.cpp
|
||||
This source file contains methods for the trpgr_Parser and trpgr_Token classes.
|
||||
trpgr_Parser is the main class. It parses the basic structure of paging archive
|
||||
data out of Read Buffers. You should not need to change this.
|
||||
If you want to parse data out of a different structure instead, look at
|
||||
subclassing trpgReadBuffer and replacing its virtual methods. That's what
|
||||
trpgMemReadBuffer is doing.
|
||||
|
||||
This file also contains the implementation of trpgSceneParser().
|
||||
That class implements a set of callbacks for handling the Pushes and Pops
|
||||
in an archive. You fill in the Start/EndChildren callbacks and register
|
||||
for the rest of the tokens that you want.
|
||||
*/
|
||||
|
||||
#include "trpage_read.h"
|
||||
|
||||
/* ***************************
|
||||
Paging token callback structure
|
||||
***************************
|
||||
*/
|
||||
trpgr_Token::trpgr_Token()
|
||||
{
|
||||
cb = NULL;
|
||||
destroy = true;
|
||||
}
|
||||
trpgr_Token::~trpgr_Token()
|
||||
{
|
||||
}
|
||||
trpgr_Token::trpgr_Token(int in_tok,trpgr_Callback *in_cb,bool in_dest)
|
||||
{
|
||||
init(in_tok,in_cb,in_dest);
|
||||
}
|
||||
void trpgr_Token::init(int in_tok,trpgr_Callback *in_cb,bool in_dest)
|
||||
{
|
||||
Token = in_tok;
|
||||
cb = in_cb;
|
||||
destroy = in_dest;
|
||||
}
|
||||
// Destruct
|
||||
// Destroy our callback if appropriate
|
||||
void trpgr_Token::Destruct()
|
||||
{
|
||||
if (cb && destroy)
|
||||
delete cb;
|
||||
cb = NULL;
|
||||
destroy = true;
|
||||
}
|
||||
|
||||
/* ***************************
|
||||
Paging parser implementation.
|
||||
***************************
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgr_Parser::trpgr_Parser()
|
||||
{
|
||||
lastObject = NULL;
|
||||
}
|
||||
trpgr_Parser::~trpgr_Parser()
|
||||
{
|
||||
}
|
||||
|
||||
// Validity check
|
||||
bool trpgr_Parser::isValid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add Callback
|
||||
// Make the given callback object current for the given token.
|
||||
void trpgr_Parser::AddCallback(trpgToken tok,trpgr_Callback *cb,bool in_dest)
|
||||
{
|
||||
RemoveCallback(tok);
|
||||
|
||||
tokenMap[tok] = trpgr_Token(tok,cb,in_dest);
|
||||
}
|
||||
|
||||
// Callback used as writeable wrapper
|
||||
class WriteWrapper : public trpgr_Callback {
|
||||
public:
|
||||
WriteWrapper(trpgReadWriteable *in_wr) { wr = in_wr; };
|
||||
void *Parse(trpgToken,trpgReadBuffer &buf) {
|
||||
if (wr->Read(buf))
|
||||
return wr;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
protected:
|
||||
trpgReadWriteable *wr;
|
||||
};
|
||||
|
||||
// Add Callback (writeable)
|
||||
// Build a wrapper around a trpgWriteable so it can read itself
|
||||
void trpgr_Parser::AddCallback(trpgToken tok,trpgReadWriteable *wr)
|
||||
{
|
||||
AddCallback(tok,new WriteWrapper(wr),true);
|
||||
}
|
||||
|
||||
// Remove Callback
|
||||
void trpgr_Parser::RemoveCallback(trpgToken tok)
|
||||
{
|
||||
tokenMap.erase(tok);
|
||||
}
|
||||
|
||||
// Set Default Callback
|
||||
// This gets called for all tokens we don't understand
|
||||
void trpgr_Parser::SetDefaultCallback(trpgr_Callback *cb,bool in_dest)
|
||||
{
|
||||
defCb.Destruct();
|
||||
defCb.init(-1,cb,in_dest);
|
||||
}
|
||||
|
||||
/* Token Is Valid
|
||||
Checks if something *could be* a token.
|
||||
Doesn't necessarily mean that it is.
|
||||
*/
|
||||
bool trpgr_Parser::TokenIsValid(trpgToken tok)
|
||||
{
|
||||
if (tok < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parse Buffer
|
||||
This runs through the given buffer parsing token sets until
|
||||
it (1) runs out of buffer or (2) fails.
|
||||
Note: Good place to return an exception, but keep it simple for now.
|
||||
*/
|
||||
bool trpgr_Parser::Parse(trpgReadBuffer &buf)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
try {
|
||||
while (!buf.isEmpty()) {
|
||||
/* We're expecting the following
|
||||
Token (int32)
|
||||
Length (int32)
|
||||
Data (variable)
|
||||
*/
|
||||
trpgToken tok;
|
||||
int32 len;
|
||||
if (!buf.Get(tok)) throw 1;
|
||||
// Push and Pop are special - no data
|
||||
if (tok != TRPG_PUSH && tok != TRPG_POP) {
|
||||
if (!buf.Get(len)) throw 1;
|
||||
if (!TokenIsValid(tok)) throw 1;
|
||||
if (len < 0) throw 1;
|
||||
// Limit what we're reading to the length of this
|
||||
buf.PushLimit(len);
|
||||
}
|
||||
|
||||
// Call our token handler for this one
|
||||
try {
|
||||
trpgr_Token *tcb = &tokenMap[tok];
|
||||
if (!tcb)
|
||||
// No such token, call the default
|
||||
tcb = &defCb;
|
||||
// Run the callback
|
||||
if (tcb->cb) {
|
||||
void *ret = tcb->cb->Parse(tok,buf);
|
||||
// Note: Do something with the return value
|
||||
lastObject = ret;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
// Don't want to screw up the limit stack
|
||||
}
|
||||
// No limit to worry about with push and pop
|
||||
if (tok != TRPG_PUSH && tok != TRPG_POP) {
|
||||
buf.SkipToLimit();
|
||||
buf.PopLimit();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
// Failed to parse.
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ****************
|
||||
Scene Parser
|
||||
****************
|
||||
*/
|
||||
// Helper - callback for Push
|
||||
class trpgSceneHelperPush : public trpgr_Callback {
|
||||
public:
|
||||
trpgSceneHelperPush(trpgSceneParser *in_parse) { parse = in_parse; };
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
// Call the start children callback
|
||||
parse->StartChildren(parse->lastObject);
|
||||
parse->parents.push_back(parse->lastObject);
|
||||
return (void *)1;
|
||||
}
|
||||
protected:
|
||||
trpgSceneParser *parse;
|
||||
};
|
||||
|
||||
// Helper - callback for Pop
|
||||
class trpgSceneHelperPop : public trpgr_Callback {
|
||||
public:
|
||||
trpgSceneHelperPop(trpgSceneParser *in_parse) { parse = in_parse; };
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
// Make sure we don't have an extra pop
|
||||
if (parse->parents.size() == 0)
|
||||
// Note: let someone know about the extra pop
|
||||
return NULL;
|
||||
// Call the end children callback
|
||||
int len = parse->parents.size();
|
||||
parse->EndChildren(parse->parents[len-1]);
|
||||
parse->parents.resize(len-1);
|
||||
return (void *)1;
|
||||
}
|
||||
protected:
|
||||
trpgSceneParser *parse;
|
||||
};
|
||||
|
||||
// Helper - default callback
|
||||
// Puts a 1 on the parent stack
|
||||
// Note: Need to use this fact above
|
||||
class trpgSceneHelperDefault : public trpgr_Callback {
|
||||
public:
|
||||
trpgSceneHelperDefault(trpgSceneParser *in_parse) { parse = in_parse; }
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
// Absorb it quietly
|
||||
return (void *)1;
|
||||
}
|
||||
protected:
|
||||
trpgSceneParser *parse;
|
||||
};
|
||||
|
||||
trpgSceneParser::trpgSceneParser()
|
||||
{
|
||||
// Register for Push and Pop
|
||||
AddCallback(TRPG_PUSH,new trpgSceneHelperPush(this));
|
||||
AddCallback(TRPG_POP,new trpgSceneHelperPop(this));
|
||||
|
||||
// Register for default
|
||||
SetDefaultCallback(new trpgSceneHelperDefault(this));
|
||||
};
|
||||
|
||||
trpgSceneParser::~trpgSceneParser()
|
||||
{
|
||||
};
|
||||
240
src/osgPlugins/txp/trpage_rarchive.cpp
Normal file
240
src/osgPlugins/txp/trpage_rarchive.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* trpage_rarchive.cpp
|
||||
This source file implements the methods for a trpgr_Archive.
|
||||
The Read Archive is used to read a paging archive from disk.
|
||||
*/
|
||||
|
||||
#include "trpage_read.h"
|
||||
|
||||
// Constructor
|
||||
trpgr_Archive::trpgr_Archive()
|
||||
{
|
||||
fp = NULL;
|
||||
ness = LittleEndian;
|
||||
strcpy(dir,".");
|
||||
}
|
||||
|
||||
// Destructor
|
||||
trpgr_Archive::~trpgr_Archive()
|
||||
{
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
// Set the directory where the archive is
|
||||
void trpgr_Archive::SetDirectory(const char *in_dir)
|
||||
{
|
||||
strncpy(dir,in_dir,1024);
|
||||
}
|
||||
|
||||
// Open File
|
||||
// Open the given file and look for the file specific info
|
||||
bool trpgr_Archive::OpenFile(const char *name)
|
||||
{
|
||||
char file[1024];
|
||||
sprintf(file,"%s/%s",dir,name);
|
||||
|
||||
CloseFile();
|
||||
|
||||
if (!(fp = fopen(file,"rb")))
|
||||
return false;
|
||||
|
||||
// Look for a magic # and endianness
|
||||
int32 magic;
|
||||
if (fread(&magic,sizeof(int32),1,fp) != 1)
|
||||
return false;
|
||||
|
||||
headerRead = false;
|
||||
|
||||
// Figure out the endianness from the magic number
|
||||
trpgEndian cpuNess = trpg_cpu_byte_order();
|
||||
if (magic == TRPG_MAGIC) {
|
||||
ness = cpuNess;
|
||||
return true;
|
||||
}
|
||||
if (trpg_byteswap_int(magic) == TRPG_MAGIC) {
|
||||
if (cpuNess == LittleEndian)
|
||||
ness = BigEndian;
|
||||
else
|
||||
ness = LittleEndian;
|
||||
return true;
|
||||
}
|
||||
if (magic != TRPG_MAGIC)
|
||||
return false;
|
||||
|
||||
// Not one of our files
|
||||
return false;
|
||||
}
|
||||
|
||||
// Close File
|
||||
// Close the currently open file
|
||||
void trpgr_Archive::CloseFile()
|
||||
{
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
// Read Header
|
||||
// Run through the rest of the header information
|
||||
bool trpgr_Archive::ReadHeader()
|
||||
{
|
||||
if (!fp || headerRead)
|
||||
return false;
|
||||
|
||||
headerRead = true;
|
||||
|
||||
// Eat some bytes
|
||||
// char stuff[20];
|
||||
// if (fread(stuff,1,20,fp) != 20) return false;
|
||||
|
||||
// if (fread(stuff,1,sizeof(trpgllong),fp) != sizeof(trpgllong)) return false;
|
||||
|
||||
// Next int64 should be the header size
|
||||
trpgEndian cpuNess = trpg_cpu_byte_order();
|
||||
int32 headerSize;
|
||||
if (fread(&headerSize,sizeof(int32),1,fp) != 1) return false;
|
||||
if (ness != cpuNess)
|
||||
headerSize = trpg_byteswap_int(headerSize);
|
||||
int headLen = headerSize;
|
||||
if (headLen < 0) return false;
|
||||
|
||||
// Read in the header whole
|
||||
trpgMemReadBuffer buf(ness);
|
||||
buf.SetLength(headLen);
|
||||
char *data = buf.GetDataPtr();
|
||||
if (fread(data,1,headLen,fp) != (unsigned int)headLen) return false;
|
||||
|
||||
// Set up a parser
|
||||
// Catch the tables we need for the archive
|
||||
trpgr_Parser parser;
|
||||
parser.AddCallback(TRPGHEADER,&header);
|
||||
parser.AddCallback(TRPGMATTABLE,&materialTable);
|
||||
parser.AddCallback(TRPGMATTABLE2,&materialTable); // Added 11-14-98
|
||||
parser.AddCallback(TRPGTEXTABLE,&texTable);
|
||||
parser.AddCallback(TRPGMODELTABLE,&modelTable);
|
||||
parser.AddCallback(TRPGTILETABLE,&tileTable);
|
||||
|
||||
// Parse the buffer
|
||||
if (!parser.Parse(buf))
|
||||
return false;
|
||||
|
||||
valid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read Tile
|
||||
// Read a tile into a read buffer
|
||||
bool trpgr_Archive::ReadTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf)
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
|
||||
// Reality check the address
|
||||
int32 numLods;
|
||||
header.GetNumLods(numLods);
|
||||
if (/*lod < 0 ||*/ (int)lod >= numLods) return false;
|
||||
trpg2iPoint lodSize;
|
||||
header.GetLodSize(lod,lodSize);
|
||||
if (/*x < 0 ||*/ (int)x >= lodSize.x || /*y < 0 ||*/ (int)y >= lodSize.y) return false;
|
||||
|
||||
// Figure out the file name
|
||||
// Note: This assumes External tiles
|
||||
const char *base = tileTable.GetBaseName();
|
||||
char filename[1024];
|
||||
sprintf(filename,"%s/%s/tile_%d_%d_%d.tpt",dir,base,x,y,lod);
|
||||
|
||||
// Open the file and read the contents
|
||||
FILE *fp=NULL;
|
||||
try {
|
||||
if (!(fp = fopen(filename,"rb"))) throw 1;
|
||||
// Find the file end
|
||||
if (fseek(fp,0,SEEK_END)) throw 1;
|
||||
// Note: This means tile is capped at 2 gigs
|
||||
long pos = ftell(fp);
|
||||
if (fseek(fp,0,SEEK_SET)) throw 1;
|
||||
// Now we know the size. Read the whole file
|
||||
buf.SetLength(pos);
|
||||
char *data = buf.GetDataPtr();
|
||||
if (fread(data,pos,1,fp) != 1) throw 1;
|
||||
fclose(fp); fp = NULL;
|
||||
}
|
||||
catch (...) {
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get methods
|
||||
const trpgHeader *trpgr_Archive::GetHeader() const
|
||||
{
|
||||
return &header;
|
||||
}
|
||||
const trpgMatTable *trpgr_Archive::GetMaterialTable() const
|
||||
{
|
||||
return &materialTable;
|
||||
}
|
||||
const trpgTexTable *trpgr_Archive::GetTexTable() const
|
||||
{
|
||||
return &texTable;
|
||||
}
|
||||
const trpgModelTable *trpgr_Archive::GetModelTable() const
|
||||
{
|
||||
return &modelTable;
|
||||
}
|
||||
const trpgTileTable *trpgr_Archive::GetTileTable() const
|
||||
{
|
||||
return &tileTable;
|
||||
}
|
||||
trpgEndian trpgr_Archive::GetEndian() const
|
||||
{
|
||||
return ness;
|
||||
}
|
||||
|
||||
// Utility MBR routine
|
||||
bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg2dPoint &ll,trpg2dPoint &ur) const
|
||||
{
|
||||
if (!header.isValid())
|
||||
return false;
|
||||
int32 numLod;
|
||||
header.GetNumLods(numLod);
|
||||
trpg2iPoint maxXY;
|
||||
header.GetLodSize(lod,maxXY);
|
||||
if (/*x < 0 ||*/ (int)x>= maxXY.x || /*y < 0 ||*/ (int)y>= maxXY.y)
|
||||
return false;
|
||||
|
||||
trpg3dPoint origin;
|
||||
header.GetOrigin(origin);
|
||||
trpg2dPoint size;
|
||||
header.GetTileSize(lod,size);
|
||||
|
||||
ll.x = origin.x + size.x*x;
|
||||
ll.y = origin.y + size.y*y;
|
||||
ur.x = origin.x + size.x*(x+1);
|
||||
ur.y = origin.y + size.y*(y+1);
|
||||
|
||||
return true;
|
||||
}
|
||||
155
src/osgPlugins/txp/trpage_read.h
Normal file
155
src/osgPlugins/txp/trpage_read.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#ifndef _txpage_read_h_
|
||||
// {secret}
|
||||
#define _txpage_read_h_
|
||||
|
||||
/* txpage_read.h
|
||||
Classes used to represent read objects for paging files.
|
||||
*/
|
||||
|
||||
#include "trpage_sys.h"
|
||||
|
||||
#include "trpage_geom.h"
|
||||
|
||||
/* Callback base class
|
||||
Called when a given token is found.
|
||||
{group:Archive Reading}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgr_Callback {
|
||||
public:
|
||||
virtual ~trpgr_Callback(void) { };
|
||||
virtual void *Parse(trpgToken,trpgReadBuffer &) { return (void *)1; };
|
||||
};
|
||||
|
||||
/* Paging Token
|
||||
Stores callback info associated with a given token.
|
||||
{group:Archive Reading}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgr_Token {
|
||||
public:
|
||||
trpgr_Token(void);
|
||||
trpgr_Token(int,trpgr_Callback *,bool destroy=true);
|
||||
~trpgr_Token(void);
|
||||
void init(int,trpgr_Callback *,bool destroy=true);
|
||||
int Token; // Constant token value
|
||||
trpgr_Callback *cb; // Callback when we hit this token
|
||||
bool destroy; // Should we call delete on the callback or not
|
||||
void Destruct(void); // Not quite like delete
|
||||
};
|
||||
|
||||
/* Parse class for paging data structures.
|
||||
This executes callbacks
|
||||
{group:Archive Reading}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgr_Parser {
|
||||
public:
|
||||
trpgr_Parser(void);
|
||||
virtual ~trpgr_Parser(void);
|
||||
bool isValid(void) const;
|
||||
|
||||
// Add and remove token callbacks
|
||||
virtual void AddCallback(trpgToken,trpgr_Callback *,bool destroy = true);
|
||||
virtual void AddCallback(trpgToken,trpgReadWriteable *);
|
||||
virtual void RemoveCallback(trpgToken);
|
||||
virtual void SetDefaultCallback(trpgr_Callback *,bool destroy = true);
|
||||
// Parse a read buffer
|
||||
virtual bool Parse(trpgReadBuffer &);
|
||||
virtual bool TokenIsValid(trpgToken); // Check token validity
|
||||
protected:
|
||||
void *lastObject;
|
||||
private:
|
||||
// Note: Just how slow is a map<> anyway?
|
||||
// This usage is self-contained and could be replaced with an array
|
||||
#if defined(_WIN32)
|
||||
typedef map<trpgToken,trpgr_Token> tok_map;
|
||||
#else
|
||||
typedef map<trpgToken,trpgr_Token,less<trpgToken> > tok_map;
|
||||
#endif
|
||||
tok_map tokenMap;
|
||||
trpgr_Token defCb; // Call this when no others are called
|
||||
};
|
||||
|
||||
/* Paging Archive (read version)
|
||||
This just reads the first bits of the file (and the header)
|
||||
and lets you parse from there.
|
||||
{group:Archive Reading}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgr_Archive : public trpgCheckable {
|
||||
public:
|
||||
trpgr_Archive(void);
|
||||
virtual ~trpgr_Archive(void);
|
||||
|
||||
virtual void SetDirectory(const char *);
|
||||
virtual bool OpenFile(const char *); // Open File
|
||||
virtual void CloseFile(void);
|
||||
virtual bool ReadHeader(void); // Read header (materials, tile table. etc..)
|
||||
virtual bool ReadTile(uint32 x, uint32 y, uint32 lod,trpgMemReadBuffer &);
|
||||
|
||||
// Get access to header info
|
||||
virtual const trpgHeader *GetHeader(void) const;
|
||||
virtual const trpgMatTable *GetMaterialTable(void) const;
|
||||
virtual const trpgTexTable *GetTexTable(void) const;
|
||||
virtual const trpgModelTable *GetModelTable(void) const;
|
||||
virtual const trpgTileTable *GetTileTable(void) const;
|
||||
|
||||
// Utility routine to calculate the MBR of a given point
|
||||
virtual bool trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,
|
||||
trpg2dPoint &ll,trpg2dPoint &ur) const;
|
||||
|
||||
trpgEndian GetEndian() const;
|
||||
char* getDir(){return dir;};
|
||||
protected:
|
||||
bool headerRead;
|
||||
trpgEndian ness;
|
||||
FILE *fp;
|
||||
int fid;
|
||||
// Header info
|
||||
char dir[1024];
|
||||
trpgHeader header;
|
||||
trpgMatTable materialTable;
|
||||
trpgTexTable texTable;
|
||||
trpgModelTable modelTable;
|
||||
trpgTileTable tileTable;
|
||||
};
|
||||
|
||||
class trpgSceneHelperPush;
|
||||
class trpgSceneHelperPop;
|
||||
class trpgSceneHelperDefault;
|
||||
/* Scene Parser
|
||||
This class assists in parsing a scene graph structure (tiles and models).
|
||||
To use it, do an archive ReadTile and pass the resulting Read Buffer to this
|
||||
parser.
|
||||
{group:Archive Reading}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgSceneParser : public trpgr_Parser {
|
||||
friend class trpgSceneHelperPush;
|
||||
friend class trpgSceneHelperPop;
|
||||
friend class trpgSceneHelperDefault;
|
||||
public:
|
||||
trpgSceneParser(void);
|
||||
virtual ~trpgSceneParser(void);
|
||||
protected:
|
||||
// Start defining children for the given object
|
||||
virtual bool StartChildren(void *) { return true;};
|
||||
virtual bool EndChildren(void *) { return true;};
|
||||
|
||||
// List of objects whose children we're working on
|
||||
vector<void *> parents;
|
||||
};
|
||||
|
||||
#endif
|
||||
430
src/osgPlugins/txp/trpage_readbuf.cpp
Normal file
430
src/osgPlugins/txp/trpage_readbuf.cpp
Normal file
@@ -0,0 +1,430 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* trpage_readbuf.cpp
|
||||
Methods for the trpgReadBuffer and trpgMemReadBuffer classes.
|
||||
trpgReadBuffer is a virtual base class with a few utility functions.
|
||||
It's used as generic interface for reading data out of.
|
||||
trpgMemReadBuffer is a subclass of that which implements methods for
|
||||
reading out of a chunk of memory. Data is read off of disk and then
|
||||
dumped into a read buffer for parsing.
|
||||
If you wanted to read directly from disk, for example, you could
|
||||
implement a trpgDiskReadBuffer as a subclass of trpgReadBuffer.
|
||||
*/
|
||||
|
||||
#include "trpage_io.h"
|
||||
#include "trpage_swap.h"
|
||||
|
||||
/* **********************
|
||||
Read buffer base class functions
|
||||
**********************
|
||||
*/
|
||||
|
||||
// Basic get functions
|
||||
bool trpgReadBuffer::Get(int32 &ret)
|
||||
{
|
||||
int32 val;
|
||||
|
||||
if (!GetData((char *)&val,sizeof(int32))) return false;
|
||||
if (ness != cpuNess)
|
||||
ret = trpg_byteswap_int(val);
|
||||
else
|
||||
ret = val;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::Get(int64 &ret)
|
||||
{
|
||||
int64 val;
|
||||
|
||||
if (!GetData((char *)&val,sizeof(int64))) return false;
|
||||
if (ness != cpuNess)
|
||||
ret = trpg_byteswap_llong(val);
|
||||
else
|
||||
ret = val;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::Get(char *ret,int retLen)
|
||||
{
|
||||
int32 len;
|
||||
|
||||
// Get the length first
|
||||
if (!Get(len)) return false;
|
||||
|
||||
// Read what we can
|
||||
int rlen = MIN(len,retLen-1);
|
||||
if (!GetData(ret,rlen)) return false;
|
||||
ret[rlen] = 0;
|
||||
|
||||
// Skip the rest
|
||||
if (!Skip(rlen-len)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::Get(float32 &ret)
|
||||
{
|
||||
char cval[4];
|
||||
|
||||
if (!GetData(cval,sizeof(float32))) return false;
|
||||
try {
|
||||
if (ness == cpuNess)
|
||||
memcpy(&ret,cval,4);
|
||||
else
|
||||
ret = trpg_byteswap_4bytes_to_float(cval);
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::Get(float64 &ret)
|
||||
{
|
||||
char cval[8];
|
||||
|
||||
if (!GetData(cval,sizeof(float64))) return false;
|
||||
try {
|
||||
if (ness == cpuNess)
|
||||
memcpy(&ret,cval,8);
|
||||
else
|
||||
ret = trpg_byteswap_8bytes_to_double(cval);
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::Get(uint8 &ret)
|
||||
{
|
||||
uint8 val;
|
||||
|
||||
if (!GetData((char *)&val,sizeof(uint8))) return false;
|
||||
// No byte swapping needed
|
||||
ret = val;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if (bool != int32)
|
||||
bool trpgReadBuffer::Get(bool &ret)
|
||||
{
|
||||
uint8 val;
|
||||
|
||||
if (!GetData((char *)&val,sizeof(uint8))) return false;
|
||||
// No byte swapping needed
|
||||
ret = (val == 0) ? false : true;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (trpgDiskRef != int64)
|
||||
bool trpgReadBuffer::Get(trpgDiskRef &ret)
|
||||
{
|
||||
trpgDiskRef val;
|
||||
|
||||
if (!GetData((char *)&val,sizeof(trpgDiskRef))) return false;
|
||||
if (ness == cpuNess)
|
||||
ret = val;
|
||||
else
|
||||
ret = trpg_byteswap_llong(val);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool trpgReadBuffer::Get(trpgToken &ret)
|
||||
{
|
||||
trpgToken val;
|
||||
|
||||
if (!GetData((char *)&val,sizeof(trpgToken))) return false;
|
||||
if (ness == cpuNess)
|
||||
ret = val;
|
||||
else
|
||||
ret = trpg_byteswap_short(val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Array Get functions
|
||||
bool trpgReadBuffer::GetArray(int len,float32 **arr)
|
||||
{
|
||||
if (!GetDataRef((char **)arr,sizeof(float32)*len))
|
||||
return false;
|
||||
// Byteswap in place if necessary
|
||||
if (ness != cpuNess) {
|
||||
char *ptr;
|
||||
int pos;
|
||||
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
|
||||
trpg_swap_four(ptr,ptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::GetArray(int len,float64 **arr)
|
||||
{
|
||||
if (!GetDataRef((char **)arr,sizeof(float64)*len))
|
||||
return false;
|
||||
// Byteswap in place if necessary
|
||||
if (ness != cpuNess) {
|
||||
char *ptr;
|
||||
int pos;
|
||||
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
|
||||
trpg_swap_eight(ptr,ptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::GetArray(int len,int32 **arr)
|
||||
{
|
||||
if (!GetDataRef((char **)arr,sizeof(int32)*len))
|
||||
return false;
|
||||
// Byteswap in place if necessary
|
||||
if (ness != cpuNess) {
|
||||
char *ptr;
|
||||
int pos;
|
||||
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
|
||||
trpg_swap_four(ptr,ptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::GetArray(int len,trpgColor **arr)
|
||||
{
|
||||
if (!GetDataRef((char **)arr,sizeof(trpgColor)*len))
|
||||
return false;
|
||||
// Byteswap in place if necessary
|
||||
if (ness != cpuNess) {
|
||||
char *ptr;
|
||||
int pos;
|
||||
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
|
||||
trpg_swap_four(ptr,ptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::GetArray(int len,char **arr)
|
||||
{
|
||||
return GetDataRef((char **)arr,sizeof(char)*len);
|
||||
}
|
||||
|
||||
// Utility Get functions - Just call the others
|
||||
bool trpgReadBuffer::Get(trpg2iPoint &pt)
|
||||
{
|
||||
if (!Get(pt.x) || !Get(pt.y))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::Get(trpg2dPoint &pt)
|
||||
{
|
||||
if (!Get(pt.x) || !Get(pt.y))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::Get(trpg3dPoint &pt)
|
||||
{
|
||||
if (!Get(pt.x) || !Get(pt.y) || !Get(pt.z))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool trpgReadBuffer::Get(trpgColor &color)
|
||||
{
|
||||
if (!Get(color.red) || !Get(color.green) || !Get(color.blue))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get both a token and it's length, since that's fairly common
|
||||
bool trpgReadBuffer::GetToken(trpgToken &tok,int32 &len)
|
||||
{
|
||||
if (!Get(tok) || !Get(len))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Limit Handling functions
|
||||
These impose arbitrary lenght limits on the read buffer.
|
||||
This keeps us from reading pased a token group and parsing
|
||||
random data within an archive.
|
||||
*/
|
||||
// Push Limit
|
||||
// Add another limit to the top of the stack
|
||||
void trpgReadBuffer::PushLimit(int limit)
|
||||
{
|
||||
limits.push_back(limit);
|
||||
}
|
||||
|
||||
// Pop Limit
|
||||
// Remove the current limit from the stack
|
||||
void trpgReadBuffer::PopLimit()
|
||||
{
|
||||
int len = limits.size();
|
||||
|
||||
if (len > 0)
|
||||
limits.resize(len-1);
|
||||
}
|
||||
|
||||
// Skip To Limit
|
||||
// Skip to the end of the current limit.
|
||||
// This happens when we bag the rest of the current token
|
||||
bool trpgReadBuffer::SkipToLimit()
|
||||
{
|
||||
int len=0;
|
||||
|
||||
if (limits.size() != 0)
|
||||
len = limits[limits.size()-1];
|
||||
|
||||
if (len > 0)
|
||||
return Skip(len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test Limit
|
||||
// See if the next read is going to blow the limits
|
||||
bool trpgReadBuffer::TestLimit(int len)
|
||||
{
|
||||
for (unsigned int i=0;i<limits.size();i++)
|
||||
if (len > limits[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update Limits
|
||||
// We just read a few bytes. Update the limits
|
||||
void trpgReadBuffer::UpdateLimits(int len)
|
||||
{
|
||||
for (unsigned int i=0;i<limits.size();i++)
|
||||
limits[i] -= len;
|
||||
}
|
||||
|
||||
/* *************************
|
||||
Memory Read Buffer
|
||||
*************************
|
||||
*/
|
||||
trpgMemReadBuffer::trpgMemReadBuffer(trpgEndian in_ness)
|
||||
{
|
||||
data = NULL;
|
||||
len = totLen = pos = 0;
|
||||
ness = in_ness;
|
||||
cpuNess = trpg_cpu_byte_order();
|
||||
}
|
||||
trpgMemReadBuffer::~trpgMemReadBuffer()
|
||||
{
|
||||
if (data)
|
||||
delete data;
|
||||
}
|
||||
|
||||
// Empty check
|
||||
bool trpgMemReadBuffer::isEmpty()
|
||||
{
|
||||
if (!data) return true;
|
||||
|
||||
if (pos >= len)
|
||||
return true;
|
||||
|
||||
// Also test the limits
|
||||
for (unsigned int i=0;i<limits.size();i++)
|
||||
if (limits[i] == 0) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set Length
|
||||
// Allocate the given space
|
||||
void trpgMemReadBuffer::SetLength(int newLen)
|
||||
{
|
||||
if (newLen > totLen) {
|
||||
if (data)
|
||||
delete data;
|
||||
data = new char[newLen];
|
||||
totLen = newLen;
|
||||
}
|
||||
len = newLen;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
// Get Data Ptr
|
||||
// Return a pointer to our data so it can be written to
|
||||
char *trpgMemReadBuffer::GetDataPtr()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
// Get Data
|
||||
// Protected method for actually retrieving a piece of data
|
||||
bool trpgMemReadBuffer::GetData(char *ret,int rlen)
|
||||
{
|
||||
if (rlen < 0)
|
||||
return false;
|
||||
|
||||
// Test against limits imposed from without
|
||||
if (!TestLimit(rlen)) throw 1;
|
||||
|
||||
// See if we've actually got the data
|
||||
if (pos+rlen > len) throw 1;
|
||||
|
||||
// Copy into the return buffer
|
||||
memcpy(ret,&data[pos],rlen);
|
||||
|
||||
// Update any limits we might have
|
||||
UpdateLimits(rlen);
|
||||
|
||||
pos += rlen;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get Reference to Data
|
||||
// Protected method that retrieves a reference to the given amoutn of data
|
||||
bool trpgMemReadBuffer::GetDataRef(char **ret,int rlen)
|
||||
{
|
||||
if (rlen < 0) return false;
|
||||
|
||||
// Test against limits
|
||||
if (!TestLimit(rlen)) throw 1;
|
||||
if (pos + rlen > len) throw 1;
|
||||
|
||||
// Set up reference
|
||||
*ret = &data[pos];
|
||||
|
||||
UpdateLimits(rlen);
|
||||
pos += rlen;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip
|
||||
// Same as read except we're not, uh, reading
|
||||
bool trpgMemReadBuffer::Skip(int rlen)
|
||||
{
|
||||
if (rlen < 0)
|
||||
return false;
|
||||
|
||||
// Test against limits
|
||||
if (!TestLimit(rlen)) return false;
|
||||
if (pos + rlen > len) return false;
|
||||
|
||||
UpdateLimits(rlen);
|
||||
|
||||
pos += rlen;
|
||||
|
||||
return true;
|
||||
}
|
||||
555
src/osgPlugins/txp/trpage_scene.cpp
Normal file
555
src/osgPlugins/txp/trpage_scene.cpp
Normal file
@@ -0,0 +1,555 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* trpage_scene.cpp
|
||||
This file implements a bunch of stuff, all of it optional. See trpage_scene.h
|
||||
for more information.
|
||||
Scene Graph nodes -
|
||||
All the methods for the simple scene graph are here.
|
||||
trpgSceneGraphParser -
|
||||
This is a subclass of trpgSceneParser. It uses that utility class to keep track
|
||||
of pushes and pops. It also registers an interest in all the node types it
|
||||
knows about (Geometry,Group,LOD,ModelRef). When one of those is encountered
|
||||
by the trpgr_Parser (which it's also a subclass of) it reads it into the
|
||||
appropriate trpgRead* type.
|
||||
Unless you're reading into the scene graph defined in trpage_scene.h, you won't
|
||||
use this class directly. Instead, copy it and use it as a template for how
|
||||
to read into a scene graph. You'll need to replace the helpers, primarily.
|
||||
*/
|
||||
|
||||
#include <trpage_read.h>
|
||||
#include <trpage_scene.h>
|
||||
|
||||
/* ****************
|
||||
MBR Calculation and handling
|
||||
****************
|
||||
*/
|
||||
trpgMBR::trpgMBR()
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
bool trpgMBR::isValid() const
|
||||
{
|
||||
return valid;
|
||||
}
|
||||
void trpgMBR::Reset()
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
trpg3dPoint trpgMBR::GetLL() const
|
||||
{
|
||||
return ll;
|
||||
}
|
||||
trpg3dPoint trpgMBR::GetUR() const
|
||||
{
|
||||
return ur;
|
||||
}
|
||||
void trpgMBR::AddPoint(const trpg3dPoint &pt)
|
||||
{
|
||||
if (valid) {
|
||||
ll.x = MIN(pt.x,ll.x);
|
||||
ll.y = MIN(pt.y,ll.y);
|
||||
ll.z = MIN(pt.z,ll.z);
|
||||
ur.x = MAX(pt.x,ur.x);
|
||||
ur.y = MAX(pt.y,ur.y);
|
||||
ur.z = MAX(pt.z,ur.z);
|
||||
} else {
|
||||
valid = true;
|
||||
ll = ur = pt;
|
||||
}
|
||||
}
|
||||
void trpgMBR::AddPoint(double x,double y,double z)
|
||||
{
|
||||
AddPoint(trpg3dPoint(x,y,z));
|
||||
}
|
||||
void trpgMBR::GetMBR(trpg3dPoint &oll,trpg3dPoint &our) const
|
||||
{
|
||||
oll = ll;
|
||||
our = ur;
|
||||
}
|
||||
// Add the input MBR to this one
|
||||
void trpgMBR::Union(const trpgMBR &in)
|
||||
{
|
||||
if (valid) {
|
||||
if (in.isValid()) {
|
||||
AddPoint(in.GetLL());
|
||||
AddPoint(in.GetUR());
|
||||
}
|
||||
} else {
|
||||
valid = true;
|
||||
*this = in;
|
||||
}
|
||||
}
|
||||
// See if there's any overlap between the two MBRs
|
||||
bool trpgMBR::Overlap(const trpg2dPoint &ill, const trpg2dPoint &iur) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
|
||||
trpg2dPoint ilr = trpg2dPoint(iur.x,ill.y);
|
||||
trpg2dPoint iul = trpg2dPoint(ill.x,iur.y);
|
||||
|
||||
// B MBR falls within A
|
||||
if (Within(ill) || Within(iur) || Within(ilr) || Within(iul))
|
||||
return true;
|
||||
|
||||
// A MBR falls within B
|
||||
if ((inRange(ill.x,iur.x,ll.x) && inRange(ill.y,iur.y,ll.y)) ||
|
||||
(inRange(ill.x,iur.x,ur.x) && inRange(ill.y,iur.y,ll.y)) ||
|
||||
(inRange(ill.x,iur.x,ur.x) && inRange(ill.y,iur.y,ur.y)) ||
|
||||
(inRange(ill.x,iur.x,ll.x) && inRange(ill.y,iur.y,ur.y)))
|
||||
return true;
|
||||
|
||||
if ((inRange(ll.x,ur.x,ill.x) && ill.y < ll.y && iur.y > ur.y) ||
|
||||
(inRange(ll.y,ur.y,ill.y) && ill.x < ll.x && iur.x > ur.x))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
// Check if a given 2d point is within the MBR
|
||||
bool trpgMBR::Within(const trpg2dPoint &pt) const
|
||||
{
|
||||
if (inRange(ll.x,ur.x,pt.x) && inRange(ll.y,ur.y,pt.y))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ****************
|
||||
Read Group Base
|
||||
Base class for all group structures.
|
||||
****************
|
||||
*/
|
||||
|
||||
// Destructor
|
||||
trpgReadGroupBase::~trpgReadGroupBase()
|
||||
{
|
||||
DeleteChildren();
|
||||
}
|
||||
|
||||
// Delete all children
|
||||
void trpgReadGroupBase::DeleteChildren()
|
||||
{
|
||||
for (unsigned int i=0;i<children.size();i++)
|
||||
if (children[i])
|
||||
delete children[i];
|
||||
}
|
||||
|
||||
// Add a child to the list
|
||||
void trpgReadGroupBase::AddChild(trpgReadNode *n)
|
||||
{
|
||||
children.push_back(n);
|
||||
}
|
||||
|
||||
// Unref a child (but don't delete it)
|
||||
void trpgReadGroupBase::unRefChild(int id)
|
||||
{
|
||||
if (id < 0 || id >= (int)children.size())
|
||||
return;
|
||||
children[id] = NULL;
|
||||
}
|
||||
|
||||
// Unref all the children (they've probably been moved elsewhere)
|
||||
void trpgReadGroupBase::unRefChildren()
|
||||
{
|
||||
for (unsigned int i=0;i<children.size();i++)
|
||||
unRefChild(i);
|
||||
}
|
||||
|
||||
// Calculate an MBR
|
||||
trpgMBR trpgReadGroupBase::GetMBR() const
|
||||
{
|
||||
if (mbr.isValid())
|
||||
return mbr;
|
||||
else {
|
||||
// Calculate and cache a new MBR
|
||||
trpgMBR *cmbr = const_cast<trpgMBR *>(&mbr);
|
||||
trpgMBR kmbr;
|
||||
// Ask the kids
|
||||
for (unsigned int i=0;i<children.size();i++) {
|
||||
kmbr = children[i]->GetMBR();
|
||||
cmbr->Union(kmbr);
|
||||
}
|
||||
return *cmbr;
|
||||
}
|
||||
}
|
||||
|
||||
/* ****************
|
||||
Read Geometry
|
||||
****************
|
||||
*/
|
||||
// Calculate an MBR
|
||||
trpgMBR trpgReadGeometry::GetMBR() const
|
||||
{
|
||||
if (mbr.isValid())
|
||||
return mbr;
|
||||
|
||||
trpgMBR *pmbr = const_cast<trpgMBR *>(&mbr);
|
||||
|
||||
int numVert,i;
|
||||
trpg3dPoint pt;
|
||||
data.GetNumVertex(numVert);
|
||||
numVert /= 3;
|
||||
for (i=0;i<numVert;i++) {
|
||||
data.GetVertex(i,pt);
|
||||
pmbr->AddPoint(pt);
|
||||
}
|
||||
|
||||
return mbr;
|
||||
}
|
||||
|
||||
/* ****************
|
||||
Scene Graph Parser
|
||||
****************
|
||||
*/
|
||||
|
||||
/* Scene Graph Parser Helpers
|
||||
Each of these classes reads a certain kind of data (e.g. a group)
|
||||
and creates the appropriate trpgrRead* form and returns that.
|
||||
*/
|
||||
|
||||
/* This is a helper registered by trpgSceneGraphParser that readers trpgGeometry
|
||||
nodes and adds them to the current scene graph. trpgGeometry nodes are
|
||||
always leaves so there should be no pushes after this node. The Parse method
|
||||
also adds the new node as a child to any existing (e.g. top) group.
|
||||
{group:Demonstration Scene Graph}
|
||||
*/
|
||||
class trpgReadGeometryHelper : public trpgr_Callback {
|
||||
public:
|
||||
trpgReadGeometryHelper(trpgSceneGraphParser *in_parse) { parse = in_parse;}
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
trpgReadGeometry *geom = new trpgReadGeometry();
|
||||
trpgGeometry *data = geom->GetData();
|
||||
if (!data->Read(buf)) {
|
||||
delete geom;
|
||||
return NULL;
|
||||
}
|
||||
trpgReadGroupBase *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->AddChild(geom);
|
||||
else
|
||||
delete geom;
|
||||
|
||||
return geom;
|
||||
}
|
||||
protected:
|
||||
trpgSceneGraphParser *parse;
|
||||
};
|
||||
|
||||
/* This helper is registered by trpgSceneGraphParser. It reads a trpgGroup
|
||||
from the trpgReadBuffer. It then adds it to our current scene graph.
|
||||
It also adds an index corresponding to the group's group ID in our group
|
||||
mapping in trpgSceneGraphParser. The new group becomes the top one
|
||||
after returning from the Parse call.
|
||||
{group:Demonstration Scene Graph}
|
||||
*/
|
||||
class trpgReadGroupHelper : public trpgr_Callback {
|
||||
public:
|
||||
trpgReadGroupHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
trpgReadGroup *group = new trpgReadGroup();
|
||||
trpgGroup *data = group->GetData();
|
||||
if (!data->Read(buf)) {
|
||||
delete group;
|
||||
return NULL;
|
||||
}
|
||||
trpgReadGroupBase *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->AddChild(group);
|
||||
else
|
||||
delete group;
|
||||
// Add to the group map
|
||||
int id;
|
||||
data->GetID(id);
|
||||
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
|
||||
(*gmap)[id] = group;
|
||||
return group;
|
||||
}
|
||||
protected:
|
||||
trpgSceneGraphParser *parse;
|
||||
};
|
||||
class trpgReadBillboardHelper : public trpgr_Callback {
|
||||
public:
|
||||
trpgReadBillboardHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
trpgReadBillboard *group = new trpgReadBillboard();
|
||||
trpgBillboard *data = group->GetData();
|
||||
if (!data->Read(buf)) {
|
||||
delete group;
|
||||
return NULL;
|
||||
}
|
||||
trpgReadGroupBase *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->AddChild(group);
|
||||
else
|
||||
delete group;
|
||||
// Add to the group map
|
||||
int id;
|
||||
data->GetID(id);
|
||||
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
|
||||
(*gmap)[id] = group;
|
||||
return group;
|
||||
}
|
||||
protected:
|
||||
trpgSceneGraphParser *parse;
|
||||
};
|
||||
class trpgReadAttachHelper : public trpgr_Callback {
|
||||
public:
|
||||
trpgReadAttachHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
trpgReadAttach *attach = new trpgReadAttach();
|
||||
trpgAttach *data = attach->GetData();
|
||||
if (!data->Read(buf)) {
|
||||
delete attach;
|
||||
return NULL;
|
||||
}
|
||||
trpgReadGroupBase *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->AddChild(attach);
|
||||
else
|
||||
delete attach;
|
||||
// Add to the group map
|
||||
int id;
|
||||
data->GetID(id);
|
||||
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
|
||||
(*gmap)[id] = attach;
|
||||
return attach;
|
||||
}
|
||||
protected:
|
||||
trpgSceneGraphParser *parse;
|
||||
};
|
||||
class trpgReadLodHelper : public trpgr_Callback {
|
||||
public:
|
||||
trpgReadLodHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
trpgReadLod *lod = new trpgReadLod();
|
||||
trpgLod *data = lod->GetData();
|
||||
if (!data->Read(buf)) {
|
||||
delete lod;
|
||||
return NULL;
|
||||
}
|
||||
trpgReadGroupBase *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->AddChild(lod);
|
||||
else
|
||||
delete lod;
|
||||
// Add to the group map
|
||||
int id;
|
||||
data->GetID(id);
|
||||
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
|
||||
(*gmap)[id] = lod;
|
||||
return lod;
|
||||
}
|
||||
protected:
|
||||
trpgSceneGraphParser *parse;
|
||||
};
|
||||
class trpgReadModelRefHelper : public trpgr_Callback {
|
||||
public:
|
||||
trpgReadModelRefHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
trpgReadModelRef *mod = new trpgReadModelRef();
|
||||
trpgModelRef *data = mod->GetData();
|
||||
if (!data->Read(buf)) {
|
||||
delete mod;
|
||||
return NULL;
|
||||
}
|
||||
trpgReadGroupBase *top = parse->GetCurrTop();
|
||||
if (top)
|
||||
top->AddChild(mod);
|
||||
else
|
||||
delete mod;
|
||||
return mod;
|
||||
}
|
||||
protected:
|
||||
trpgSceneGraphParser *parse;
|
||||
};
|
||||
class trpgReadTileHeaderHelper : public trpgr_Callback {
|
||||
public:
|
||||
trpgReadTileHeaderHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
|
||||
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
|
||||
trpgReadTileHeader *th = parse->GetTileHeaderRef();
|
||||
trpgTileHeader *data = th->GetData();
|
||||
if (!data->Read(buf))
|
||||
return NULL;
|
||||
return th;
|
||||
}
|
||||
protected:
|
||||
trpgSceneGraphParser *parse;
|
||||
};
|
||||
|
||||
/* The Scene Graph Parser constructor does two things. First, it sets
|
||||
up any internal variables like a normal constructor. Then it registers
|
||||
an interest in all the node types it knows how to parse. It does this
|
||||
by calling AddCallback, which is a method of its parent. It passes in
|
||||
a token representing the node type (see trpg_io.h) and an object that
|
||||
is capable of parsing the given type.
|
||||
|
||||
The objects we pass in here are called helpers. They parse specific
|
||||
objects and add them to the user defined scene graph. Examples include
|
||||
trpgReadGeometryHelper, trpgReadGroupHelper, trpgReadAttachHelper,
|
||||
trpgReadBillboardHelper, trpgReadLodHelper, trpgReadModelRefHelper,
|
||||
trpgReadTileHeaderHelper. These are all derived from trpgr_Callback.
|
||||
You should not use any of these yourself. Instead look at these classes
|
||||
as examples of how to implement your own subclass of trpgSceneParser.
|
||||
*/
|
||||
trpgSceneGraphParser::trpgSceneGraphParser()
|
||||
{
|
||||
top = currTop = NULL;
|
||||
|
||||
// Register the readers
|
||||
AddCallback(TRPG_GEOMETRY,new trpgReadGeometryHelper(this));
|
||||
AddCallback(TRPG_GROUP,new trpgReadGroupHelper(this));
|
||||
AddCallback(TRPG_ATTACH,new trpgReadAttachHelper(this));
|
||||
AddCallback(TRPG_BILLBOARD,new trpgReadBillboardHelper(this));
|
||||
AddCallback(TRPG_LOD,new trpgReadLodHelper(this));
|
||||
// AddCallback(TRPG_TRANSFORM,new trpgReadTransformHelper(this));
|
||||
AddCallback(TRPG_MODELREF,new trpgReadModelRefHelper(this));
|
||||
// AddCallback(TRPG_LAYER,new trpgReadLayerHelper(this));
|
||||
AddCallback(TRPGTILEHEADER,new trpgReadTileHeaderHelper(this));
|
||||
}
|
||||
|
||||
// Get Current Top node
|
||||
trpgReadGroupBase *trpgSceneGraphParser::GetCurrTop()
|
||||
{
|
||||
if (!currTop)
|
||||
return NULL;
|
||||
if (currTop->isGroupType())
|
||||
return (trpgReadGroupBase *)currTop;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Return a pointer to the tile header record
|
||||
trpgReadTileHeader *trpgSceneGraphParser::GetTileHeaderRef()
|
||||
{
|
||||
return &tileHead;
|
||||
}
|
||||
|
||||
// Parse Scene
|
||||
// Parse a buffer and return the resulting scene graph
|
||||
trpgReadNode *trpgSceneGraphParser::ParseScene(trpgReadBuffer &buf,GroupMap &inGmap)
|
||||
{
|
||||
gmap = &inGmap;
|
||||
trpgTileHeader *data = tileHead.GetData();
|
||||
data->Reset();
|
||||
|
||||
// Always put a group up top, since there might be more than
|
||||
// one node at the top level in the file.
|
||||
top = currTop = new trpgReadGroup();
|
||||
|
||||
// All the setup for tokens is handled in the constructor
|
||||
// Just call parse
|
||||
if (!Parse(buf)) {
|
||||
// Failed to parse correctly. Give up.
|
||||
delete top;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
// Start Children
|
||||
// This is called when the parser hits a push.
|
||||
// We'll want to make the node it's handing us the "top" node
|
||||
bool trpgSceneGraphParser::StartChildren(void *in_node)
|
||||
{
|
||||
trpgReadNode *node = (trpgReadNode *)in_node;
|
||||
|
||||
if (!node || !node->isGroupType()) {
|
||||
// Looks like there's a push in the wrong place
|
||||
// Make the current "top" NULL.
|
||||
// This will drop all node until we pop back above
|
||||
currTop = NULL;
|
||||
} else {
|
||||
// This node is our new "top"
|
||||
currTop = node;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This is called when the parser hits a pop.
|
||||
We'll want to look on the parent list (in trpgSceneParser)
|
||||
for the parent above the current one.
|
||||
If there isn't one, we'll just stick things in our top group.
|
||||
*/
|
||||
bool trpgSceneGraphParser::EndChildren(void * /*in_node*/)
|
||||
{
|
||||
// We don't need it here, but this is the node we just
|
||||
// finished putting children under. If you need to close
|
||||
// it out in some way, do that here
|
||||
//trpgReadNode *node = (trpgReadNode *)in_node;
|
||||
|
||||
// Get the parent above the current one
|
||||
int pos = parents.size()-2;
|
||||
if (pos < 0)
|
||||
// Nothing above the current one. Fall back on our top group
|
||||
currTop = top;
|
||||
else
|
||||
currTop = (trpgReadNode *)parents[pos];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return group map (for use by helpers)
|
||||
trpgSceneGraphParser::GroupMap *trpgSceneGraphParser::GetGroupMap()
|
||||
{
|
||||
return gmap;
|
||||
}
|
||||
|
||||
/* ***********
|
||||
Test functions
|
||||
***********
|
||||
*/
|
||||
|
||||
// Test all the tiles in an archive
|
||||
bool trpgTestArchive(trpgr_Archive &archive)
|
||||
{
|
||||
int numLod;
|
||||
trpg2iPoint tileSize;
|
||||
trpgSceneGraphParser parse;
|
||||
trpgReadNode *scene;
|
||||
trpgSceneGraphParser::GroupMap gmap;
|
||||
|
||||
if (!archive.isValid()) return false;
|
||||
|
||||
const trpgHeader *head = archive.GetHeader();
|
||||
head->GetNumLods(numLod);
|
||||
|
||||
// Iterate over the lods
|
||||
int nl,x,y;
|
||||
trpgMemReadBuffer buf(archive.GetEndian());
|
||||
trpg2dPoint ll,ur;
|
||||
for (nl = 0;nl < numLod;nl++) {
|
||||
head->GetLodSize(nl,tileSize);
|
||||
// Iterate over the tiles within those
|
||||
for (x = 0; x < tileSize.x; x++)
|
||||
for (y = 0; y < tileSize.y; y++) {
|
||||
archive.trpgGetTileMBR(x,y,nl,ll,ur);
|
||||
if (archive.ReadTile(x,y,nl,buf)) {
|
||||
// Parse it
|
||||
scene = parse.ParseScene(buf,gmap);
|
||||
if (scene)
|
||||
delete scene;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
239
src/osgPlugins/txp/trpage_scene.h
Normal file
239
src/osgPlugins/txp/trpage_scene.h
Normal file
@@ -0,0 +1,239 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#ifndef _txpage_scene_h_
|
||||
// {secret}
|
||||
#define _txpage_scene_h_
|
||||
|
||||
/* trpage_scene.h
|
||||
Scene Graph definition.
|
||||
This is a small scene graph we use for testing.
|
||||
It's not intended to replace the scene graph you may already be using.
|
||||
You do not need to translate from this scene graph structure to your own,
|
||||
at run-time. Instead, use this file and trpage_scene.cpp as a guideline
|
||||
for how to read TerraPage format into your own scene graph.
|
||||
*/
|
||||
|
||||
#include "trpage_geom.h"
|
||||
|
||||
/*
|
||||
{group:Demonstration Scene Graph}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgMBR {
|
||||
public:
|
||||
trpgMBR(void);
|
||||
~trpgMBR(void) { };
|
||||
bool isValid() const;
|
||||
void Reset();
|
||||
void AddPoint(const trpg3dPoint &);
|
||||
void AddPoint(double,double,double);
|
||||
void GetMBR(trpg3dPoint &ll,trpg3dPoint &ur) const;
|
||||
trpg3dPoint GetLL() const;
|
||||
trpg3dPoint GetUR() const;
|
||||
void Union(const trpgMBR &);
|
||||
// bool Overlap(const trpgMBR &) const;
|
||||
bool Overlap(const trpg2dPoint &ll, const trpg2dPoint &ur) const;
|
||||
// bool Within(const trpg3dPoint &) const
|
||||
bool Within(const trpg2dPoint &) const;
|
||||
protected:
|
||||
inline bool inRange(double minv,double maxv,double val) const { return (val >= minv && val <= maxv); }
|
||||
bool valid;
|
||||
trpg3dPoint ll,ur;
|
||||
};
|
||||
|
||||
// Read Node
|
||||
// Simple Scenegraph node used for read testing
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadNode {
|
||||
public:
|
||||
virtual ~trpgReadNode() { };
|
||||
virtual bool isGroupType() = 0;
|
||||
virtual int GetType() { return type; }
|
||||
virtual trpgMBR GetMBR() const { return trpgMBR(); }
|
||||
protected:
|
||||
int type;
|
||||
};
|
||||
|
||||
// Read Group Base
|
||||
// Base class for all group nodes
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadGroupBase : public trpgReadNode {
|
||||
public:
|
||||
virtual ~trpgReadGroupBase();
|
||||
void AddChild(trpgReadNode *);
|
||||
bool isGroupType() { return true; }
|
||||
int GetNumChildren() { return children.size(); }
|
||||
trpgReadNode *GetChild(int i) { return children[i]; }
|
||||
trpgMBR GetMBR() const;
|
||||
void unRefChild(int i);
|
||||
void unRefChildren();
|
||||
protected:
|
||||
trpgMBR mbr;
|
||||
void DeleteChildren();
|
||||
vector<trpgReadNode *> children;
|
||||
};
|
||||
|
||||
// Read Geometry
|
||||
// The leaf for this scene graph
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadGeometry : public trpgReadNode {
|
||||
public:
|
||||
trpgReadGeometry() { type = TRPG_GEOMETRY; }
|
||||
~trpgReadGeometry() { };
|
||||
bool isGroupType() { return false; }
|
||||
trpgGeometry *GetData() { return &data; }
|
||||
trpgMBR GetMBR() const;
|
||||
protected:
|
||||
trpgMBR mbr;
|
||||
trpgGeometry data;
|
||||
};
|
||||
|
||||
// Read Tile Header
|
||||
// One per tile. Info about what materials and models are used
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadTileHeader : public trpgReadNode {
|
||||
public:
|
||||
trpgReadTileHeader() { type = TRPGTILEHEADER; }
|
||||
~trpgReadTileHeader() { };
|
||||
bool isGroupType() { return false; }
|
||||
trpgTileHeader *GetData() { return &data; }
|
||||
trpgMBR GetMBR() const { trpgMBR mbr; return mbr; };
|
||||
protected:
|
||||
trpgTileHeader data;
|
||||
};
|
||||
|
||||
// Read Group
|
||||
// Simple group structure
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadGroup : public trpgReadGroupBase {
|
||||
public:
|
||||
trpgReadGroup() { type = TRPG_GROUP; }
|
||||
~trpgReadGroup() { };
|
||||
trpgGroup *GetData() { return &data; }
|
||||
protected:
|
||||
trpgGroup data;
|
||||
};
|
||||
|
||||
// Read Attach
|
||||
// Should be the top of a higher LOD tile
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadAttach : public trpgReadGroupBase {
|
||||
public:
|
||||
trpgReadAttach() { type = TRPG_ATTACH; }
|
||||
~trpgReadAttach() { };
|
||||
trpgAttach *GetData() { return &data; }
|
||||
protected:
|
||||
trpgAttach data;
|
||||
};
|
||||
|
||||
// Read billboard
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadBillboard : public trpgReadGroupBase {
|
||||
public:
|
||||
trpgReadBillboard() { type = TRPG_BILLBOARD; }
|
||||
~trpgReadBillboard() { };
|
||||
trpgBillboard *GetData() { return &data; }
|
||||
protected:
|
||||
trpgBillboard data;
|
||||
};
|
||||
|
||||
// Read LOD
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadLod : public trpgReadGroupBase {
|
||||
public:
|
||||
trpgReadLod() { type = TRPG_LOD; }
|
||||
~trpgReadLod() { };
|
||||
trpgLod *GetData() { return &data; }
|
||||
protected:
|
||||
trpgLod data;
|
||||
};
|
||||
|
||||
// Read Layer
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadLayer : public trpgReadGroupBase {
|
||||
public:
|
||||
trpgReadLayer() { type = TRPG_LAYER; }
|
||||
~trpgReadLayer() { };
|
||||
trpgLayer *GetData() { return &data; }
|
||||
protected:
|
||||
trpgLayer data;
|
||||
};
|
||||
|
||||
// Read Transform
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadTransform : public trpgReadGroupBase {
|
||||
public:
|
||||
trpgReadTransform() { type = TRPG_TRANSFORM; }
|
||||
~trpgReadTransform() { };
|
||||
trpgTransform *GetData() { return &data; }
|
||||
protected:
|
||||
trpgTransform data;
|
||||
};
|
||||
|
||||
// Read Model Reference
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgReadModelRef : public trpgReadGroupBase {
|
||||
public:
|
||||
trpgReadModelRef() { type = TRPG_MODELREF; }
|
||||
~trpgReadModelRef() { };
|
||||
trpgModelRef *GetData() { return &data; }
|
||||
protected:
|
||||
trpgModelRef data;
|
||||
};
|
||||
|
||||
/* Scene Graph Parser
|
||||
Parses a read buffer and returns a full scenegraph.
|
||||
You don't want to use this if you're reading into your own scenegraph.
|
||||
Instead, you'll want to sublcass trpgSceneParser, which is a helper
|
||||
class to keep track of pushes and pops and implement the same functionality
|
||||
that trpgSceneGraphParser has for your own scene graph.
|
||||
*/
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_EXDECL class TX_CLDECL trpgSceneGraphParser : public trpgSceneParser {
|
||||
public:
|
||||
#if defined(_WIN32)
|
||||
typedef map<int,trpgReadGroupBase *> GroupMap;
|
||||
#else
|
||||
typedef map<int,trpgReadGroupBase *,less<int> > GroupMap;
|
||||
#endif
|
||||
trpgSceneGraphParser();
|
||||
~trpgSceneGraphParser() { };
|
||||
// Call this instead of Parse()
|
||||
// Deleting it is your responsibility
|
||||
trpgReadNode *ParseScene(trpgReadBuffer &,GroupMap &);
|
||||
trpgReadGroupBase *GetCurrTop(); // Get the current parent object
|
||||
trpgReadTileHeader *GetTileHeaderRef();
|
||||
|
||||
// For use by the helpers only
|
||||
GroupMap *GetGroupMap();
|
||||
protected:
|
||||
bool StartChildren(void *);
|
||||
bool EndChildren(void *);
|
||||
trpgReadNode *currTop; // Current parent group
|
||||
trpgReadNode *top; // Top of everything
|
||||
GroupMap *gmap;
|
||||
trpgReadTileHeader tileHead; // Tile header gets read into here
|
||||
};
|
||||
|
||||
/* Test Archive
|
||||
Utility function that loads and tests all tiles.
|
||||
The only reason you'd want to call this is to test a TerraPage archive
|
||||
you'd written.
|
||||
*/
|
||||
// {group:Demonstration Scene Graph}
|
||||
TX_CPPDECL bool trpgTestArchive(trpgr_Archive &);
|
||||
|
||||
#endif
|
||||
210
src/osgPlugins/txp/trpage_swap.cpp
Normal file
210
src/osgPlugins/txp/trpage_swap.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* trpage_swap.h
|
||||
Byte swapping utility functions.
|
||||
*/
|
||||
|
||||
#include "trpage_swap.h"
|
||||
|
||||
/*
|
||||
** func: swap_two( in, out )
|
||||
**
|
||||
** desc: byte-swaps a two-byte array.
|
||||
*/
|
||||
void trpg_swap_two ( const char *in, char *out )
|
||||
{
|
||||
char tmp[2];
|
||||
|
||||
tmp[0] = in[1] ;
|
||||
tmp[1] = in[0] ;
|
||||
|
||||
memcpy(out,tmp,2);
|
||||
}
|
||||
|
||||
/*
|
||||
** func: swap_four( in, out )
|
||||
**
|
||||
** desc: byte-swaps a four-byte array.
|
||||
*/
|
||||
void trpg_swap_four ( const char *in, char *out )
|
||||
{
|
||||
char tmp[4];
|
||||
|
||||
tmp[0] = in[3] ;
|
||||
tmp[1] = in[2] ;
|
||||
tmp[2] = in[1] ;
|
||||
tmp[3] = in[0] ;
|
||||
|
||||
memcpy(out,tmp,4);
|
||||
}
|
||||
|
||||
/*
|
||||
** func: swap_eight( in, out )
|
||||
**
|
||||
** desc: byte-swaps an eight-byte array.
|
||||
*/
|
||||
void trpg_swap_eight ( const char *in, char *out )
|
||||
{
|
||||
char tmp[8];
|
||||
|
||||
tmp[0] = in[7] ;
|
||||
tmp[1] = in[6] ;
|
||||
tmp[2] = in[5] ;
|
||||
tmp[3] = in[4] ;
|
||||
tmp[4] = in[3] ;
|
||||
tmp[5] = in[2] ;
|
||||
tmp[6] = in[1] ;
|
||||
tmp[7] = in[0] ;
|
||||
|
||||
memcpy(out,tmp,8);
|
||||
}
|
||||
|
||||
/*
|
||||
** func: swap_sixteen( in, out )
|
||||
**
|
||||
** desc: byte-swaps an sixteen-byte array.
|
||||
*/
|
||||
void trpg_swap_sixteen ( const char *in, char *out )
|
||||
{
|
||||
char tmp[16];
|
||||
|
||||
tmp[0] = in[15] ;
|
||||
tmp[1] = in[14] ;
|
||||
tmp[2] = in[13] ;
|
||||
tmp[3] = in[12] ;
|
||||
tmp[4] = in[11] ;
|
||||
tmp[5] = in[10] ;
|
||||
tmp[6] = in[9] ;
|
||||
tmp[7] = in[8] ;
|
||||
tmp[8] = in[7] ;
|
||||
tmp[9] = in[6] ;
|
||||
tmp[10] = in[5] ;
|
||||
tmp[11] = in[4] ;
|
||||
tmp[12] = in[3] ;
|
||||
tmp[13] = in[2] ;
|
||||
tmp[14] = in[1] ;
|
||||
tmp[15] = in[0] ;
|
||||
|
||||
memcpy(out,tmp,16);
|
||||
}
|
||||
|
||||
/*
|
||||
** func: tx_byteswap_short( number )
|
||||
**
|
||||
** desc: byte-swaps a short int.
|
||||
*/
|
||||
short trpg_byteswap_short( short number )
|
||||
{
|
||||
short result;
|
||||
|
||||
trpg_swap_two( (const char*) &number, (char*) &result );
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
** func: tx_byteswap_int( number )
|
||||
**
|
||||
** desc: byte-swaps an int.
|
||||
*/
|
||||
int trpg_byteswap_int( int number )
|
||||
{
|
||||
int result;
|
||||
|
||||
trpg_swap_four( (const char*) &number, (char*) &result );
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
** func: tx_byteswap_long( number )
|
||||
**
|
||||
** desc: byte-swaps a long int.
|
||||
*/
|
||||
long trpg_byteswap_long( long number )
|
||||
{
|
||||
long result;
|
||||
|
||||
trpg_swap_four( (const char*) &number, (char*) &result );
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
** func: tx_byteswap_float( number )
|
||||
**
|
||||
** desc: byte-swaps a float.
|
||||
*/
|
||||
void trpg_byteswap_float_to_4bytes( float number, char result[4] )
|
||||
{
|
||||
trpg_swap_four( (const char*) &number, result );
|
||||
}
|
||||
|
||||
/*
|
||||
** func: tx_byteswap_double_to_8bytes( number )
|
||||
**
|
||||
** desc: byte-swaps a double.
|
||||
*/
|
||||
void trpg_byteswap_double_to_8bytes( double number, char result[8] )
|
||||
{
|
||||
trpg_swap_eight( (const char*) &number, result );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** func: tx_byteswap_float( number )
|
||||
**
|
||||
** desc: byte-swaps a float.
|
||||
*/
|
||||
float trpg_byteswap_4bytes_to_float( const char result[4] )
|
||||
{
|
||||
float number;
|
||||
trpg_swap_four( result, (char*) &number );
|
||||
return number;
|
||||
}
|
||||
|
||||
/*
|
||||
** func: tx_byteswap_double_to_8bytes( number )
|
||||
**
|
||||
** desc: byte-swaps a double.
|
||||
*/
|
||||
double trpg_byteswap_8bytes_to_double( const char result[8] )
|
||||
{
|
||||
double number;
|
||||
trpg_swap_eight( result, (char*) &number );
|
||||
return number;
|
||||
}
|
||||
|
||||
trpgllong trpg_byteswap_llong ( trpgllong number )
|
||||
{
|
||||
trpgllong result;
|
||||
|
||||
trpg_swap_sixteen ( (char *) &number, (char *) &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
trpgEndian trpg_cpu_byte_order(void)
|
||||
{
|
||||
static char big_endian_100[2] = { 0, 100 };
|
||||
|
||||
if ( (*((short*) big_endian_100)) == 100 )
|
||||
return BigEndian;
|
||||
else
|
||||
return LittleEndian;
|
||||
}
|
||||
|
||||
69
src/osgPlugins/txp/trpage_swap.h
Normal file
69
src/osgPlugins/txp/trpage_swap.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#ifndef trpage_swap_h_
|
||||
#define trpage_swap_h_
|
||||
|
||||
/* trpage_swap.h
|
||||
Byte swapping utility functions.
|
||||
*/
|
||||
|
||||
#include "trpage_sys.h"
|
||||
|
||||
#include "trpage_io.h"
|
||||
|
||||
// Byte swap and return a short
|
||||
// {group:Byte Ordering Utilities}
|
||||
short trpg_byteswap_short( short number );
|
||||
// Byte swap and return an integer
|
||||
// {group:Byte Ordering Utilities}
|
||||
int trpg_byteswap_int( int number );
|
||||
// Byte swap and return a long
|
||||
// {group:Byte Ordering Utilities}
|
||||
long trpg_byteswap_long( long number );
|
||||
// Byte swap and return a 64 bit long
|
||||
// {group:Byte Ordering Utilities}
|
||||
trpgllong trpg_byteswap_llong ( trpgllong number );
|
||||
// Byte swap a float value into 4 characters. We do it this way to avoid floating point exceptions.
|
||||
// {group:Byte Ordering Utilities}
|
||||
void trpg_byteswap_float_to_4bytes( float number, char result[4] );
|
||||
// Byte swap a double value into 8 characters. We do it this way to avoid floating point exceptions.
|
||||
// {group:Byte Ordering Utilities}
|
||||
void trpg_byteswap_double_to_8bytes( double number, char result[8] );
|
||||
// Swap 4 bytes into a float and return it
|
||||
// {group:Byte Ordering Utilities}
|
||||
float trpg_byteswap_4bytes_to_float( const char result[4] );
|
||||
// Swap 8 bytes into a double and return it
|
||||
// {group:Byte Ordering Utilities}
|
||||
double trpg_byteswap_8bytes_to_double( const char result[8] );
|
||||
// Determine the current CPU's byte ordering
|
||||
// {group:Byte Ordering Utilities}
|
||||
trpgEndian trpg_cpu_byte_order(void);
|
||||
|
||||
// Swap two chars
|
||||
// {group:Byte Ordering Utilities}
|
||||
void trpg_swap_two ( const char *in, char *out );
|
||||
// Swap 4 chars
|
||||
// {group:Byte Ordering Utilities}
|
||||
void trpg_swap_four ( const char *in, char *out );
|
||||
// Swap 8 chars
|
||||
// {group:Byte Ordering Utilities}
|
||||
void trpg_swap_eight ( const char *in, char *out );
|
||||
// Swap sixteen chars
|
||||
// {group:Byte Ordering Utilities}
|
||||
void trpg_swap_sixteen ( const char *in, char *out );
|
||||
|
||||
#endif
|
||||
138
src/osgPlugins/txp/trpage_sys.h
Normal file
138
src/osgPlugins/txp/trpage_sys.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
/* trpage_sys.h
|
||||
System specific declarations.
|
||||
*/
|
||||
|
||||
#ifndef trpage_sys_h_
|
||||
#define trpage_sys_h_
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* *********************
|
||||
System Specific Section.
|
||||
This is currently set up for win32.
|
||||
*********************
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// Microsoft Developer warnings that annoy me
|
||||
#pragma warning ( disable : 4251)
|
||||
#pragma warning ( disable : 4275)
|
||||
#pragma warning ( disable : 4786)
|
||||
|
||||
// Somewhat system independent file deletion macro
|
||||
#define TRPGDELETEFILE(file) DeleteFile((file))
|
||||
|
||||
#ifndef int64
|
||||
// 64 bit long value. Need this for really big files.
|
||||
typedef __int64 int64;
|
||||
#endif
|
||||
|
||||
#else // Unix
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// Delete a file
|
||||
#define TRPGDELETEFILE(file) remove((file))
|
||||
|
||||
//#ifndef int64
|
||||
//typedef long long int64;
|
||||
//#endif
|
||||
|
||||
#if defined(sgi) && defined(unix)
|
||||
# include <sgidefs.h>
|
||||
typedef __int64_t int64;
|
||||
|
||||
#elif defined(sun) && defined(unix) && (defined(SUN551) || defined(SUN56))
|
||||
// NOTE: SUN56 and SUN551 is assumed to be defined in our makefiles.
|
||||
#include <sys/types.h>
|
||||
typedef longlong_t int64;
|
||||
|
||||
#elif defined(sun) && defined(unix)
|
||||
// This should work on SunOS 5.7 and later.
|
||||
#include <sys/types.h>
|
||||
typedef int64_t int64;
|
||||
|
||||
#elif defined(linux)
|
||||
#include <sys/types.h>
|
||||
typedef int64_t int64;
|
||||
//typedef long long int int64;
|
||||
|
||||
#elif defined(__ghs__) && defined(__LL_Is_64)
|
||||
typedef long long int64;
|
||||
|
||||
#else
|
||||
typedef int int64; // DON'T KNOW WHAT TO DO
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Basic data types
|
||||
#ifndef uint8
|
||||
typedef unsigned char uint8;
|
||||
#endif
|
||||
#ifndef int32
|
||||
typedef int int32;
|
||||
#endif
|
||||
#ifndef uint32
|
||||
typedef unsigned int uint32;
|
||||
#endif
|
||||
#ifndef float32
|
||||
typedef float float32;
|
||||
#endif
|
||||
#ifndef float64
|
||||
typedef double float64;
|
||||
#endif
|
||||
|
||||
// Note: replace this with your own STL implementation
|
||||
// You can use the Microsoft provided one by deleting the first #include
|
||||
#ifdef USEROGUE
|
||||
#include <txRogueWave.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(vxw) || (defined(sgi) && defined(_STANDARD_C_PLUS_PLUS)) || (defined(__GNUC__) && (__GNUC__>=2) && (__GNUC_MINOR__>=91))
|
||||
#include <vector>
|
||||
#include <map>
|
||||
namespace std {}
|
||||
using namespace std;
|
||||
#else
|
||||
#include <vector.h>
|
||||
#include <map.h>
|
||||
#endif
|
||||
|
||||
//#if defined(_WIN32)
|
||||
//#include <vector>
|
||||
//#include <map>
|
||||
//#else
|
||||
//#include <vector.h>
|
||||
//#include <map.h>
|
||||
//#endif
|
||||
|
||||
//#if defined(_WIN32) // PJM
|
||||
//using namespace std;
|
||||
//#endif
|
||||
|
||||
// We use long longs for addresses within a paging file
|
||||
typedef int64 trpgllong;
|
||||
|
||||
// These are used to export classes from a DLL
|
||||
// Definitely Windows specific
|
||||
#include "trpage_ident.h"
|
||||
#include "trdll.h"
|
||||
|
||||
#endif
|
||||
415
src/osgPlugins/txp/trpage_tile.cpp
Normal file
415
src/osgPlugins/txp/trpage_tile.cpp
Normal file
@@ -0,0 +1,415 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* trpage_tile.cpp
|
||||
This source file contains the implementation of trpgTileTable and trpgTileHeader.
|
||||
You'll need to edit these if you want to add something to the Tile Table (at
|
||||
the front of an archive) or the Tile Header (at the beginning of each tile).
|
||||
*/
|
||||
|
||||
#include "trpage_geom.h"
|
||||
#include "trpage_read.h"
|
||||
|
||||
/* Write Tile Table
|
||||
Keeps track of tiles written to disk.
|
||||
*/
|
||||
|
||||
// Constructor
|
||||
trpgTileTable::trpgTileTable()
|
||||
{
|
||||
// numX = numY = numLod = 0;
|
||||
numLod = 0;
|
||||
baseName = NULL;
|
||||
type = External;
|
||||
}
|
||||
|
||||
// Reset function
|
||||
void trpgTileTable::Reset()
|
||||
{
|
||||
if (baseName)
|
||||
delete baseName;
|
||||
// center.resize(0);
|
||||
// tiles.resize(0);
|
||||
// numX = numY;
|
||||
numLod = 0;
|
||||
baseName = NULL;
|
||||
type = External;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
trpgTileTable::~trpgTileTable()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgTileTable::SetNumTiles(int nx,int ny)
|
||||
{
|
||||
if (nx <= 0 || ny <= 0)
|
||||
return;
|
||||
|
||||
SetNumTiles(nx,ny,1);
|
||||
}
|
||||
void trpgTileTable::SetNumTiles(int nx,int ny,int nl)
|
||||
{
|
||||
if (nx <= 0 || ny <= 0 || nl <= 0 || nl >= numLod)
|
||||
return;
|
||||
|
||||
lodSizes[nl] = trpg2iPoint(nx,ny);
|
||||
|
||||
// tiles.resize(nx*ny*nl,0);
|
||||
}
|
||||
void trpgTileTable::SetTile(int nx,int ny,int nl,trpgDiskRef ref)
|
||||
{
|
||||
if (nx < 0 || nx >= numX ||
|
||||
ny < 0 || ny >= numY ||
|
||||
nl < 0 || nl >= numLod)
|
||||
return;
|
||||
|
||||
type = Local;
|
||||
|
||||
// tiles[nl*(numX*numY)+ny*numX+nx] = ref;
|
||||
}
|
||||
void trpgTileTable::SetTile(int nx,int ny,trpgDiskRef ref)
|
||||
{
|
||||
SetTile(nx,ny,0,ref);
|
||||
}
|
||||
void trpgTileTable::SetBaseName(const char *name)
|
||||
{
|
||||
if (baseName)
|
||||
delete baseName;
|
||||
|
||||
baseName = new char[(name ? strlen(name) : 0)+1];
|
||||
strcpy(baseName,name);
|
||||
type = External;
|
||||
}
|
||||
void trpgTileTable::SetCenter(int nx,int ny,int nl,const trpg3dPoint &pt)
|
||||
{
|
||||
if (nx < 0 || nx >= numX ||
|
||||
ny < 0 || ny >= numY ||
|
||||
nl < 0 || nl >= numLod)
|
||||
return;
|
||||
|
||||
// center[nl*(numX*numY)+ny*numX+nx] = pt;
|
||||
}
|
||||
void trpgTileTable::SetCenter(int nx,int ny,const trpg3dPoint &pt)
|
||||
{
|
||||
SetCenter(nx,ny,0,pt);
|
||||
}
|
||||
|
||||
// Need the basename when writing an archive
|
||||
const char *trpgTileTable::GetBaseName() const
|
||||
{
|
||||
return baseName;
|
||||
}
|
||||
|
||||
// Validity check
|
||||
bool trpgTileTable::isValid() const
|
||||
{
|
||||
// if (numX == 0 || numY == 0 || numLod == 0)
|
||||
// return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write tile table
|
||||
bool trpgTileTable::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPGTILETABLE);
|
||||
#if 0
|
||||
numTiles = tiles.size();
|
||||
buf.Add(numX);
|
||||
buf.Add(numY);
|
||||
buf.Add(numLod);
|
||||
for (unsigned int i=0;i<tiles.size();i++) {
|
||||
buf.Add(tiles[i]);
|
||||
buf.Add(center[i]);
|
||||
}
|
||||
#endif
|
||||
buf.Add(baseName);
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* **************
|
||||
Tile Table Read methods
|
||||
**************
|
||||
*/
|
||||
|
||||
// Get methods
|
||||
bool trpgTileTable::GetNumTiles(int &x,int &y,int &l) const
|
||||
{
|
||||
// if (!isValid()) return false;
|
||||
x = numX;
|
||||
y = numY;
|
||||
l = numLod;
|
||||
return true;
|
||||
}
|
||||
bool trpgTileTable::GetType(int &t) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
t = type;
|
||||
return true;
|
||||
}
|
||||
bool trpgTileTable::GetBaseName(char *str,int strLen) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
if (type != External) return false;
|
||||
int len = (baseName ? strlen(baseName) : 0);
|
||||
strncpy(str,baseName,MIN(len,strLen)+1);
|
||||
return true;
|
||||
}
|
||||
bool trpgTileTable::GetTile(int x,int y,int lod,trpgDiskRef &ref) const
|
||||
{
|
||||
if (!isValid() || type != Local) return false;
|
||||
// Note: fill this in
|
||||
return false;
|
||||
}
|
||||
bool trpgTileTable::GetTile(int x,int y,int lod,char *str,int strLen) const
|
||||
{
|
||||
if (!isValid() || type != External) return false;
|
||||
sprintf(str,"%s\\tile_%d_%d_%d.tpt",baseName,x,y,lod);
|
||||
return true;
|
||||
}
|
||||
bool trpgTileTable::GetCenter(int x,int y,int lod,trpg3dPoint &pt) const
|
||||
{
|
||||
if (!isValid() || x < 0 || x >= numX || y < 0 || y >= numY ||
|
||||
lod < 0 || lod >= numLod)
|
||||
return false;
|
||||
// pt = center[lod*(numX*numY)+y*numX+x];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool trpgTileTable::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
// trpg3dPoint pt;
|
||||
char tmpStr[1024];
|
||||
|
||||
try {
|
||||
type = External; // Note: Read this in
|
||||
#if 0
|
||||
buf.Get(numX);
|
||||
buf.Get(numY);
|
||||
buf.Get(numLod);
|
||||
if (numTiles < 0) throw 1;
|
||||
for (int i=0;i<numTiles;i++) {
|
||||
buf.Get(diskRef);
|
||||
buf.Get(pt);
|
||||
tiles.push_back(diskRef);
|
||||
center.push_back(pt);
|
||||
}
|
||||
#endif
|
||||
buf.Get(tmpStr,1023);
|
||||
SetBaseName(tmpStr);
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
/* Tile Header
|
||||
Each distinct tile (or model) must have a header
|
||||
which tells you what models and materials are
|
||||
referenced in that tile.
|
||||
*/
|
||||
// Constructor
|
||||
trpgTileHeader::trpgTileHeader()
|
||||
{
|
||||
}
|
||||
trpgTileHeader::~trpgTileHeader()
|
||||
{
|
||||
}
|
||||
|
||||
void trpgTileHeader::Reset()
|
||||
{
|
||||
matList.resize(0);
|
||||
modelList.resize(0);
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgTileHeader::SetMaterial(int no,int id)
|
||||
{
|
||||
if (no < 0 || no >= (int)matList.size())
|
||||
return;
|
||||
matList[no] = id;
|
||||
}
|
||||
void trpgTileHeader::SetModel(int no,int id)
|
||||
{
|
||||
if (no < 0 || no >= (int)modelList.size())
|
||||
return;
|
||||
modelList[no] = id;
|
||||
}
|
||||
|
||||
// Set functions
|
||||
void trpgTileHeader::AddMaterial(int id)
|
||||
{
|
||||
// Look for it first
|
||||
for (unsigned int i=0;i<matList.size();i++)
|
||||
if (matList[i] == id)
|
||||
return;
|
||||
// Didn't find it, add it.
|
||||
matList.push_back(id);
|
||||
}
|
||||
void trpgTileHeader::AddModel(int id)
|
||||
{
|
||||
for (unsigned int i=0;i<modelList.size();i++)
|
||||
if (modelList[i] == id)
|
||||
return;
|
||||
modelList.push_back(id);
|
||||
}
|
||||
void trpgTileHeader::SetDate(int32 d)
|
||||
{
|
||||
date = d;
|
||||
}
|
||||
|
||||
// Get methods
|
||||
bool trpgTileHeader::GetNumMaterial(int32 &no) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
no = (int32)matList.size();
|
||||
return true;
|
||||
}
|
||||
bool trpgTileHeader::GetMaterial(int32 id,int32 &mat) const
|
||||
{
|
||||
if (!isValid() || id < 0 || id >= (int32)matList.size())
|
||||
return false;
|
||||
mat = matList[id];
|
||||
return true;
|
||||
}
|
||||
bool trpgTileHeader::GetNumModel(int32 &no) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
no = modelList.size();
|
||||
return true;
|
||||
}
|
||||
bool trpgTileHeader::GetModel(int32 id,int32 &m) const
|
||||
{
|
||||
if (!isValid() || id < 0 || id >= (int32)modelList.size())
|
||||
return false;
|
||||
m = modelList[id];
|
||||
return true;
|
||||
}
|
||||
bool trpgTileHeader::GetDate(int32 &d) const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
d = date;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validity check
|
||||
bool trpgTileHeader::isValid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write to a buffer
|
||||
bool trpgTileHeader::Write(trpgWriteBuffer &buf)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
buf.Begin(TRPGTILEHEADER);
|
||||
buf.Begin(TRPG_TILE_MATLIST);
|
||||
buf.Add((int32)matList.size());
|
||||
for (i=0;i<matList.size();i++)
|
||||
buf.Add(matList[i]);
|
||||
buf.End();
|
||||
buf.Begin(TRPG_TILE_MODELLIST);
|
||||
buf.Add((int32)modelList.size());
|
||||
for (i=0;i<modelList.size();i++)
|
||||
buf.Add(modelList[i]);
|
||||
buf.End();
|
||||
buf.Begin(TRPG_TILE_DATE);
|
||||
buf.Add(date);
|
||||
buf.End();
|
||||
buf.End();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Tile Header CB
|
||||
// Used to aid in parsing tile header
|
||||
// We want the tile header to be expandable, so be careful here
|
||||
class tileHeaderCB : public trpgr_Callback {
|
||||
public:
|
||||
void * Parse(trpgToken,trpgReadBuffer &);
|
||||
trpgTileHeader *head;
|
||||
};
|
||||
|
||||
void * tileHeaderCB::Parse(trpgToken tok,trpgReadBuffer &buf)
|
||||
{
|
||||
int32 no,id,date,i;
|
||||
|
||||
try {
|
||||
switch (tok) {
|
||||
case TRPG_TILE_MATLIST:
|
||||
buf.Get(no);
|
||||
if (no < 0) throw 1;
|
||||
for (i = 0;i < no; i++) {
|
||||
buf.Get(id);
|
||||
head->AddMaterial(id);
|
||||
}
|
||||
break;
|
||||
case TRPG_TILE_MODELLIST:
|
||||
buf.Get(no);
|
||||
if (no < 0) throw 1;
|
||||
for (i=0;i<no;i++) {
|
||||
buf.Get(id);
|
||||
head->AddModel(id);
|
||||
}
|
||||
break;
|
||||
case TRPG_TILE_DATE:
|
||||
buf.Get(date);
|
||||
head->SetDate(date);
|
||||
break;
|
||||
default:
|
||||
// Don't care
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
// Read tile header
|
||||
bool trpgTileHeader::Read(trpgReadBuffer &buf)
|
||||
{
|
||||
tileHeaderCB tcb;
|
||||
trpgr_Parser parse;
|
||||
|
||||
tcb.head = this;
|
||||
parse.AddCallback(TRPG_TILE_MATLIST,&tcb,false);
|
||||
parse.AddCallback(TRPG_TILE_MODELLIST,&tcb,false);
|
||||
parse.AddCallback(TRPG_TILE_DATE,&tcb,false);
|
||||
parse.Parse(buf);
|
||||
|
||||
return isValid();
|
||||
}
|
||||
651
src/osgPlugins/txp/trpage_warchive.cpp
Normal file
651
src/osgPlugins/txp/trpage_warchive.cpp
Normal file
@@ -0,0 +1,651 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* trpage_warchive.cpp
|
||||
This source file contains the implementations of trpgwArchive and trpgwGeomHelper.
|
||||
The Write Archive is used to write TerraPage archives. All its important methods
|
||||
are virtual, so you shouldn't need to modify any of this code. Simply subclass
|
||||
and override.
|
||||
The Geometry Helper is a class that's used to sort out polygons and build
|
||||
trpgGeometry objects, containing triangle strips and fans out of them. The one
|
||||
contained here is fairly simple, but all its important methods are virtual. So
|
||||
again, subclass and override if you need to change them.
|
||||
*/
|
||||
|
||||
#include "trpage_geom.h"
|
||||
#include "trpage_write.h"
|
||||
|
||||
// Constructor
|
||||
trpgwArchive::trpgwArchive(trpgEndian inNess)
|
||||
{
|
||||
fp = NULL;
|
||||
// Note: only doing external tiles
|
||||
tileTable.SetBaseName(".");
|
||||
strcpy(dir,".");
|
||||
ness = inNess;
|
||||
cpuNess = trpg_cpu_byte_order();
|
||||
}
|
||||
void trpgwArchive::init(trpgEndian inNess)
|
||||
{
|
||||
ness = inNess;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
trpgwArchive::~trpgwArchive()
|
||||
{
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
// IsValid()
|
||||
// Verifies that our file is open
|
||||
bool trpgwArchive::isValid() const
|
||||
{
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Set Functions
|
||||
These just copy tables and the header from the input.
|
||||
If these aren't set, then empty ones are written.
|
||||
*/
|
||||
bool trpgwArchive::SetHeader(const trpgHeader &head)
|
||||
{
|
||||
header = head;
|
||||
return true;
|
||||
}
|
||||
bool trpgwArchive::SetMaterialTable(const trpgMatTable &mat)
|
||||
{
|
||||
matTable = mat;
|
||||
return true;
|
||||
}
|
||||
bool trpgwArchive::SetTextureTable(const trpgTexTable &tex)
|
||||
{
|
||||
texTable = tex;
|
||||
return true;
|
||||
}
|
||||
bool trpgwArchive::SetModelTable(const trpgModelTable &models)
|
||||
{
|
||||
modelTable = models;
|
||||
return true;
|
||||
}
|
||||
|
||||
// OpenFile
|
||||
// Same as above, only gets a basename as well
|
||||
bool trpgwArchive::OpenFile(const char *in_dir,const char *name)
|
||||
{
|
||||
char filename[1024];
|
||||
|
||||
strncpy(dir,in_dir,1023);
|
||||
|
||||
sprintf(filename,"%s/%s",dir,name);
|
||||
|
||||
if (!(fp = fopen(filename,"wb")))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// CloseFile
|
||||
// Close the open file
|
||||
void trpgwArchive::CloseFile()
|
||||
{
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
/* WriteHeader
|
||||
For now everything is external, so the header is written last.
|
||||
The order is this:
|
||||
Header
|
||||
Material table
|
||||
Texture References
|
||||
Model References
|
||||
[Future:
|
||||
Tile Address Table
|
||||
Model Address Table]
|
||||
*/
|
||||
bool trpgwArchive::WriteHeader()
|
||||
{
|
||||
trpgMemWriteBuffer buf(ness);
|
||||
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
// Write all the headers into a buffer
|
||||
if (!header.Write(buf) ||
|
||||
!matTable.Write(buf) ||
|
||||
!texTable.Write(buf) ||
|
||||
!modelTable.Write(buf) ||
|
||||
!tileTable.Write(buf))
|
||||
return false;
|
||||
|
||||
// Write the disk header
|
||||
int32 magic = TRPG_MAGIC;
|
||||
if (ness != cpuNess)
|
||||
magic = trpg_byteswap_int(magic);
|
||||
if (fwrite(&magic,sizeof(int32),1,fp) != 1)
|
||||
return false;
|
||||
|
||||
// Write the header length
|
||||
int32 headerSize = buf.length();
|
||||
int headLen = headerSize;
|
||||
if (ness != cpuNess)
|
||||
headerSize = trpg_byteswap_int(headerSize);
|
||||
if (fwrite(&headerSize,1,sizeof(int32),fp) != sizeof(int32)) return false;
|
||||
|
||||
// Write the buffer
|
||||
const char *data = buf.getData();
|
||||
|
||||
if (fwrite(data,sizeof(char),headLen,fp) != (unsigned int)headLen)
|
||||
return false;
|
||||
|
||||
char space[40];
|
||||
if (fwrite(space,1,4,fp) != 4)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* WriteTile
|
||||
For now we're only doing external tiles.
|
||||
Note: Do more checking
|
||||
*/
|
||||
bool trpgwArchive::WriteTile(unsigned int x,unsigned int y,unsigned int lod,
|
||||
const trpgMemWriteBuffer *head,const trpgMemWriteBuffer *buf)
|
||||
{
|
||||
FILE *tfp=NULL;
|
||||
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
// Get the basename and make a new file
|
||||
const char *base = tileTable.GetBaseName();
|
||||
if (!base)
|
||||
return false;
|
||||
|
||||
// Make a new filename
|
||||
char filename[1024];
|
||||
// Note: Windows specific
|
||||
sprintf(filename,"%s/%s/tile_%d_%d_%d.tpt",dir,base,x,y,lod);
|
||||
if (!(tfp = fopen(filename,"wb")))
|
||||
return false;
|
||||
|
||||
// Write the header first
|
||||
int len;
|
||||
const char *data;
|
||||
if (head) {
|
||||
data = head->getData();
|
||||
len = head->length();
|
||||
if (fwrite(data,sizeof(char),len,tfp) != (unsigned int)len) {
|
||||
fclose(tfp);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the buffer out
|
||||
data = buf->getData();
|
||||
len = buf->length();
|
||||
if (fwrite(data,sizeof(char),len,tfp) != (unsigned int)len) {
|
||||
fclose(tfp);
|
||||
return false;
|
||||
}
|
||||
fclose(tfp);
|
||||
|
||||
// Note: Should be updating the center in the tile table
|
||||
// Also, last updated date
|
||||
return true;
|
||||
}
|
||||
|
||||
/* DeleteTile
|
||||
Delete the given tile.
|
||||
Note: This is system specific.
|
||||
*/
|
||||
bool trpgwArchive::DeleteTile(unsigned int x,unsigned int y,unsigned int lod)
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
|
||||
const char *base = tileTable.GetBaseName();
|
||||
if (!base) return false;
|
||||
|
||||
// Note: windows specific
|
||||
char filename[1024];
|
||||
sprintf(filename,"%s\\tile_%d_%d_%d.tpt",base,x,y,lod);
|
||||
TRPGDELETEFILE(filename);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ****************
|
||||
Geometry Stats
|
||||
Used by the Geometry Helper
|
||||
****************
|
||||
*/
|
||||
trpgwGeomStats::trpgwGeomStats()
|
||||
{
|
||||
totalTri = totalStripTri = totalFanTri = totalBagTri = 0;
|
||||
for (int i=0;i<15;i++) {
|
||||
stripStat[i] = fanStat[i] = 0;
|
||||
}
|
||||
stripGeom = fanGeom = bagGeom = 0;
|
||||
stateChanges = 0;
|
||||
numStrip = numFan = 0;
|
||||
totalQuad = 0;
|
||||
}
|
||||
trpgwGeomStats::~trpgwGeomStats()
|
||||
{
|
||||
}
|
||||
|
||||
/* ****************
|
||||
Geometry Helper
|
||||
Here, since it's used with a write archive.
|
||||
****************
|
||||
*/
|
||||
trpgwGeomHelper::trpgwGeomHelper()
|
||||
{
|
||||
buf = NULL;
|
||||
mode = trpgGeometry::Triangles;
|
||||
}
|
||||
trpgwGeomHelper::~trpgwGeomHelper()
|
||||
{
|
||||
}
|
||||
void trpgwGeomHelper::SetMode(int m)
|
||||
{
|
||||
if (m == trpgGeometry::Triangles || m == trpgGeometry::Quads)
|
||||
mode = m;
|
||||
}
|
||||
trpgwGeomHelper::trpgwGeomHelper(trpgWriteBuffer *ibuf, int dtype)
|
||||
{
|
||||
init(ibuf,dtype);
|
||||
}
|
||||
void trpgwGeomHelper::init(trpgWriteBuffer *ibuf,int dtype)
|
||||
{
|
||||
buf = ibuf;
|
||||
dataType = dtype;
|
||||
}
|
||||
// Reset back to a clean state (except for the buffer)
|
||||
void trpgwGeomHelper::Reset()
|
||||
{
|
||||
ResetTri();
|
||||
ResetPolygon();
|
||||
}
|
||||
|
||||
// Reset triangle arrays (usually after a flush)
|
||||
void trpgwGeomHelper::ResetTri()
|
||||
{
|
||||
strips.Reset();
|
||||
fans.Reset();
|
||||
bags.Reset();
|
||||
|
||||
tex.resize(0);
|
||||
norm.resize(0);
|
||||
vert.resize(0);
|
||||
}
|
||||
|
||||
// Start a polygon definition
|
||||
void trpgwGeomHelper::StartPolygon()
|
||||
{
|
||||
ResetPolygon();
|
||||
}
|
||||
|
||||
// Finish a polygon definition
|
||||
void trpgwGeomHelper::EndPolygon()
|
||||
{
|
||||
// See if we can add it to the current triangle arrays
|
||||
if (vert.size() && (matTri != matPoly)) {
|
||||
// Couldn't flush geometry and move on
|
||||
FlushGeom();
|
||||
}
|
||||
|
||||
// Turn the polygon into triangles
|
||||
// Note: Only dealing with convex here
|
||||
matTri = matPoly;
|
||||
|
||||
switch (mode) {
|
||||
case trpgGeometry::Triangles:
|
||||
{
|
||||
int num = polyVert.size() - 2;
|
||||
int id1,id2;
|
||||
for (int i=0;i<num;i++) {
|
||||
// Note: Handle color
|
||||
|
||||
/* Swap 1 and 2 positions
|
||||
This lets the Optimizer pick up on triangle fans
|
||||
If you're not using our optimizer this will do very weird things
|
||||
Probably it will screw up backface culling.
|
||||
*/
|
||||
// Note: turned this off because it was broken. Put it back
|
||||
#if 0
|
||||
id1 = i+1;
|
||||
id2 = i+2;
|
||||
if (num > 1) {
|
||||
id1 = i+2; id2 = i+1;
|
||||
}
|
||||
#else
|
||||
id1 = i+1;
|
||||
id2 = i+2;
|
||||
#endif
|
||||
|
||||
// Define the triangle
|
||||
vert.push_back(polyVert[0]);
|
||||
vert.push_back(polyVert[id1]);
|
||||
vert.push_back(polyVert[id2]);
|
||||
|
||||
norm.push_back(polyNorm[0]);
|
||||
norm.push_back(polyNorm[id1]);
|
||||
norm.push_back(polyNorm[id2]);
|
||||
|
||||
tex.push_back(polyTex[0]);
|
||||
tex.push_back(polyTex[id1]);
|
||||
tex.push_back(polyTex[id2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case trpgGeometry::Quads:
|
||||
{
|
||||
int num = polyVert.size();
|
||||
if (polyVert.size() == 4) {
|
||||
for (int i=0;i<num;i++) {
|
||||
vert.push_back(polyVert[i]);
|
||||
norm.push_back(polyNorm[i]);
|
||||
tex.push_back(polyTex[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ResetPolygon();
|
||||
}
|
||||
|
||||
// Clean out the polygon arrays
|
||||
void trpgwGeomHelper::ResetPolygon()
|
||||
{
|
||||
matPoly = -1;
|
||||
polyTex.resize(0);
|
||||
polyNorm.resize(0);
|
||||
polyVert.resize(0);
|
||||
}
|
||||
|
||||
// Set the current color
|
||||
// Note: Required
|
||||
void trpgwGeomHelper::SetColor(trpgColor &col)
|
||||
{
|
||||
// tmpColor = col;
|
||||
}
|
||||
|
||||
// Set the current texture coord
|
||||
// Note: Required
|
||||
void trpgwGeomHelper::SetTexCoord(trpg2dPoint &pt)
|
||||
{
|
||||
tmpTex = pt;
|
||||
}
|
||||
|
||||
// Set the current normal
|
||||
// Note: required
|
||||
void trpgwGeomHelper::SetNormal(trpg3dPoint &pt)
|
||||
{
|
||||
tmpNorm = pt;
|
||||
}
|
||||
|
||||
// Set the current material
|
||||
// Note: required
|
||||
void trpgwGeomHelper::SetMaterial(int32 imat)
|
||||
{
|
||||
matPoly = imat;
|
||||
}
|
||||
|
||||
// Collect the current vertex data and add a new whole vertex
|
||||
// Note: Deal with color
|
||||
void trpgwGeomHelper::AddVertex(trpg3dPoint &pt)
|
||||
{
|
||||
polyTex.push_back(tmpTex);
|
||||
polyNorm.push_back(tmpNorm);
|
||||
// Note: Turn this back on. It's not right currently, though
|
||||
#if 0
|
||||
if (buf->GetEndian() != trpg_cpu_byte_order())
|
||||
{
|
||||
trpg3dPoint tmpVert;
|
||||
tmpVert.x = trpg_byteswap_8bytes_to_double ((char *)&pt.x);
|
||||
tmpVert.y = trpg_byteswap_8bytes_to_double ((char *)&pt.y);
|
||||
tmpVert.z = trpg_byteswap_8bytes_to_double ((char *)&pt.z);
|
||||
polyVert.push_back(tmpVert);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
polyVert.push_back(pt);
|
||||
}
|
||||
|
||||
// Flush the current set of geometry and move on
|
||||
void trpgwGeomHelper::FlushGeom()
|
||||
{
|
||||
bool hadGeom = false;
|
||||
|
||||
switch (mode) {
|
||||
case trpgGeometry::Triangles:
|
||||
{
|
||||
Optimize();
|
||||
|
||||
// Write only if we've got something
|
||||
int numPrim;
|
||||
if (strips.GetNumPrims(numPrim) && numPrim) {
|
||||
strips.Write(*buf);
|
||||
stats.stripGeom++;
|
||||
hadGeom = true;
|
||||
}
|
||||
if (fans.GetNumPrims(numPrim) && numPrim) {
|
||||
fans.Write(*buf);
|
||||
stats.fanGeom++;
|
||||
hadGeom = true;
|
||||
}
|
||||
if (bags.GetNumPrims(numPrim) && numPrim) {
|
||||
bags.Write(*buf);
|
||||
stats.bagGeom++;
|
||||
hadGeom = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case trpgGeometry::Quads:
|
||||
{
|
||||
int numVert = vert.size();
|
||||
// Make sure we've got quads
|
||||
if (numVert % 4 == 0) {
|
||||
int dtype = (dataType == UseDouble ? trpgGeometry::DoubleData : trpgGeometry::FloatData);
|
||||
// Just dump the quads into single geometry node
|
||||
trpgGeometry quads;
|
||||
quads.SetPrimType(trpgGeometry::Quads);
|
||||
quads.AddTexCoords(trpgGeometry::PerVertex);
|
||||
for (int i=0;i<numVert;i++) {
|
||||
quads.AddVertex((trpgGeometry::DataType)dtype,vert[i]);
|
||||
quads.AddNormal((trpgGeometry::DataType)dtype,norm[i]);
|
||||
quads.AddTexCoord((trpgGeometry::DataType)dtype,tex[i]);
|
||||
}
|
||||
quads.SetNumPrims(numVert/4);
|
||||
quads.AddMaterial(matTri);
|
||||
|
||||
quads.Write(*buf);
|
||||
stats.totalQuad++;
|
||||
hadGeom = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (hadGeom)
|
||||
stats.stateChanges++;
|
||||
ResetTri();
|
||||
}
|
||||
|
||||
/* Optimize
|
||||
Form triangle strips and fans and dump the rest into a "bag"
|
||||
of triangles.
|
||||
This works for TERREX, but won't do a whole lot for anyone else.
|
||||
It will produce valid output, but not particularly optimized.
|
||||
*/
|
||||
#define ADDVERT(dest,vt) { \
|
||||
dest.AddVertex((trpgGeometry::DataType)dtype,vt.v); \
|
||||
dest.AddNormal((trpgGeometry::DataType)dtype,vt.n); \
|
||||
dest.AddTexCoord((trpgGeometry::DataType)dtype,vt.tex); \
|
||||
}
|
||||
class optVert {
|
||||
public:
|
||||
optVert() { valid = false; }
|
||||
optVert(trpg3dPoint iv,trpg3dPoint in,trpg2dPoint itex) { v = iv; n = in; tex = itex; valid = true;}
|
||||
trpg3dPoint v;
|
||||
trpg3dPoint n;
|
||||
trpg2dPoint tex;
|
||||
bool valid;
|
||||
int operator == (const optVert &in) const { return (v.x == in.v.x && v.y == in.v.y && v.z == in.v.z &&
|
||||
n.x == in.n.x && n.y == in.n.y && n.z == in.n.z &&
|
||||
tex.x == in.tex.x && tex.y == in.tex.y); }
|
||||
};
|
||||
void trpgwGeomHelper::Optimize()
|
||||
{
|
||||
/*bool isStrip = false;*/
|
||||
int dtype = (dataType == UseDouble ? trpgGeometry::DoubleData : trpgGeometry::FloatData);
|
||||
|
||||
// Potentially writing to all of these
|
||||
strips.SetPrimType(trpgGeometry::TriStrips);
|
||||
strips.AddMaterial(matTri);
|
||||
strips.AddTexCoords(trpgGeometry::PerVertex);
|
||||
fans.SetPrimType(trpgGeometry::TriFans);
|
||||
fans.AddMaterial(matTri);
|
||||
fans.AddTexCoords(trpgGeometry::PerVertex);
|
||||
bags.SetPrimType(trpgGeometry::Triangles);
|
||||
bags.AddMaterial(matTri);
|
||||
bags.AddTexCoords(trpgGeometry::PerVertex);
|
||||
|
||||
int numTri = vert.size()/3;
|
||||
|
||||
if (numTri == 0)
|
||||
return;
|
||||
|
||||
// Iterate through the triangles
|
||||
enum {Strip,Fan,Bag};
|
||||
int type,triId;
|
||||
optVert a[3],b[3],c[3];
|
||||
for (triId = 0; triId<numTri; ) {
|
||||
// Triangle A
|
||||
int vid = 3*triId;
|
||||
a[0] = optVert(vert[vid],norm[vid],tex[vid]);
|
||||
a[1] = optVert(vert[vid+1],norm[vid+1],tex[vid+1]);
|
||||
a[2] = optVert(vert[vid+2],norm[vid+2],tex[vid+2]);
|
||||
|
||||
// If we've got two or more triangles to go, try to form something
|
||||
if (triId + 1 <numTri) {
|
||||
// Triangle B
|
||||
b[0] = optVert(vert[vid+3],norm[vid+3],tex[vid+3]);
|
||||
b[1] = optVert(vert[vid+4],norm[vid+4],tex[vid+4]);
|
||||
b[2] = optVert(vert[vid+5],norm[vid+5],tex[vid+5]);
|
||||
|
||||
// Is it a triangle strip?
|
||||
if (a[1] == b[1] && a[2] == b[0])
|
||||
type = Strip;
|
||||
else {
|
||||
// Might be a Fan
|
||||
if (a[0] == b[0] && a[1] == b[2])
|
||||
type = Fan;
|
||||
else
|
||||
type = Bag;
|
||||
}
|
||||
} else
|
||||
type = Bag;
|
||||
|
||||
switch (type) {
|
||||
case Bag:
|
||||
ADDVERT(bags,a[0]);
|
||||
ADDVERT(bags,a[1]);
|
||||
ADDVERT(bags,a[2]);
|
||||
bags.AddPrim();
|
||||
triId++;
|
||||
stats.AddBagStat(1);
|
||||
break;
|
||||
case Strip:
|
||||
{
|
||||
bool isStrip,flip=true;
|
||||
int primLen = 0;
|
||||
// Dump A into the strip
|
||||
ADDVERT(strips,a[0]);
|
||||
ADDVERT(strips,a[1]);
|
||||
ADDVERT(strips,a[2]);
|
||||
triId++;
|
||||
primLen = 3;
|
||||
do {
|
||||
// Already checked that B was good on last go-round
|
||||
ADDVERT(strips,b[2]); primLen++;
|
||||
triId++;
|
||||
vid = 3*triId;
|
||||
|
||||
if (triId < numTri) {
|
||||
// B is the new primary, check it against the next
|
||||
c[0] = optVert(vert[vid],norm[vid],tex[vid]);
|
||||
c[1] = optVert(vert[vid+1],norm[vid+1],tex[vid+1]);
|
||||
c[2] = optVert(vert[vid+2],norm[vid+2],tex[vid+2]);
|
||||
if (flip)
|
||||
isStrip = (c[0] == b[0] && c[1] == b[2]);
|
||||
else
|
||||
isStrip = (c[0] == b[2] && c[1] == b[1]);
|
||||
b[0] = c[0]; b[1] = c[1]; b[2] = c[2];
|
||||
}
|
||||
flip = !flip;
|
||||
} while (triId < numTri && isStrip);
|
||||
|
||||
strips.AddPrimLength(primLen);
|
||||
stats.AddStripStat(primLen);
|
||||
}
|
||||
break;
|
||||
case Fan:
|
||||
{
|
||||
bool isFan;
|
||||
int primLen = 0;
|
||||
|
||||
// Dump A into the Fan
|
||||
ADDVERT(fans,a[0]);
|
||||
ADDVERT(fans,a[2]);
|
||||
ADDVERT(fans,a[1]);
|
||||
triId++;
|
||||
primLen = 3;
|
||||
do {
|
||||
// Already know that B is good, add that
|
||||
ADDVERT(fans,b[1]); primLen++;
|
||||
triId++;
|
||||
vid = 3*triId;
|
||||
|
||||
if (triId < numTri) {
|
||||
// B is the new primary, check it agains the next
|
||||
c[0] = optVert(vert[vid],norm[vid],tex[vid]);
|
||||
c[1] = optVert(vert[vid+1],norm[vid+1],tex[vid+1]);
|
||||
c[2] = optVert(vert[vid+2],norm[vid+2],tex[vid+2]);
|
||||
isFan = (c[0] == b[0] && c[2] == b[1]);
|
||||
b[0] = c[0]; b[1] = c[1]; b[2] = c[2];
|
||||
}
|
||||
} while (triId < numTri && isFan);
|
||||
|
||||
fans.AddPrimLength(primLen);
|
||||
stats.AddFanStat(primLen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
191
src/osgPlugins/txp/trpage_write.h
Normal file
191
src/osgPlugins/txp/trpage_write.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#ifndef _txpage_write_h_
|
||||
// {secret}
|
||||
#define _txpage_write_h_
|
||||
|
||||
/* trpage_write.h
|
||||
Classes that are used to write paging archives.
|
||||
*/
|
||||
|
||||
#include "trpage_sys.h"
|
||||
#include "trpage_io.h"
|
||||
#include "trpage_swap.h"
|
||||
|
||||
/* Geometry Stats
|
||||
Used with a Geometry Helper to keep track of what go built.
|
||||
{group:Archive Writing}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgwGeomStats {
|
||||
public:
|
||||
trpgwGeomStats(void);
|
||||
~trpgwGeomStats(void);
|
||||
|
||||
int totalTri; // Total # of triangles
|
||||
|
||||
int totalQuad; // Total # of quads
|
||||
|
||||
// Add up to totalTri
|
||||
int totalStripTri; // triangles in strips
|
||||
int totalFanTri; // triangles in fans
|
||||
int totalBagTri; // loose triangles
|
||||
|
||||
int numStrip; // Number of distinct strips
|
||||
int numFan; // Number of distinct fans
|
||||
|
||||
int stripStat[15]; // Strip length stats
|
||||
int fanStat[15]; // Fan length stats
|
||||
|
||||
int stripGeom; // Number of seperate trpgGeometry nodes for strips
|
||||
int fanGeom; // Same for fans
|
||||
int bagGeom; // Same for bags
|
||||
|
||||
int stateChanges; // Number of distinct material switches
|
||||
|
||||
// Helper functions
|
||||
inline void AddStripStat(int val) { stripStat[MIN(14,val)]++; totalStripTri += val; totalTri += val; numStrip++;}
|
||||
inline void AddFanStat(int val) { fanStat[MIN(14,val)]++; totalFanTri += val; totalTri += val; numFan++;}
|
||||
inline void AddBagStat(int val) { totalBagTri += val; totalTri += val;}
|
||||
inline void AddQuadStat(int val) { totalQuad++; }
|
||||
};
|
||||
|
||||
/* Geometry Helper
|
||||
Collects up geometry and tries to form triangle strips, fans,
|
||||
and groups of triangles.
|
||||
Right now this looks for a very careful ordering. If that ordering
|
||||
isn't there you won't get useful tristrips or fans. You can, however
|
||||
use this class as a starting point and build something more akin
|
||||
to the geometry builder in Performer.
|
||||
{group:Archive Writing}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgwGeomHelper {
|
||||
public:
|
||||
trpgwGeomHelper(void);
|
||||
virtual ~trpgwGeomHelper(void);
|
||||
enum {UseDouble,UseFloat};
|
||||
trpgwGeomHelper(trpgWriteBuffer *,int dataType=UseDouble);
|
||||
void init(trpgWriteBuffer *,int dataType=UseDouble);
|
||||
virtual void SetMode(int); // Takes a trpgGeometry primitive type (triangle by default)
|
||||
virtual void Reset();
|
||||
// Start/End polygon definition
|
||||
virtual void StartPolygon();
|
||||
virtual void EndPolygon();
|
||||
virtual void ResetPolygon(); // If you change your mind about the current poly
|
||||
// Set the current state
|
||||
// Note: Currently you *must* set all of these
|
||||
virtual void SetColor(trpgColor &);
|
||||
virtual void SetTexCoord(trpg2dPoint &);
|
||||
virtual void SetNormal(trpg3dPoint &);
|
||||
virtual void SetMaterial(int32);
|
||||
// Pull the state info together and add a vertex
|
||||
virtual void AddVertex(trpg3dPoint &);
|
||||
|
||||
// Dump whatever we're doing and move on
|
||||
virtual void FlushGeom();
|
||||
|
||||
// Get statistics for whatever we built
|
||||
trpgwGeomStats *GetStats() { return &stats; }
|
||||
protected:
|
||||
int mode;
|
||||
int dataType;
|
||||
trpgWriteBuffer *buf;
|
||||
|
||||
/* Builds strips and fans from the triangle array.
|
||||
We (TERREX) are assuming a certain ordering in our vertex array
|
||||
because we do this optimization elsewhere. This won't work well
|
||||
for anyone else. What you will need to do if you want good
|
||||
performance is to implement a more generic form of this method.
|
||||
All you should have to do is override Optimize(). You've
|
||||
got the triangle arrays and a guarantee that the triangles
|
||||
have the same material. All you really need is a decent fan/strip
|
||||
algorithm.
|
||||
*/
|
||||
virtual void Optimize();
|
||||
|
||||
// Reset Triangle arrays
|
||||
virtual void ResetTri();
|
||||
|
||||
// Collections of geometry
|
||||
trpgGeometry strips,fans,bags;
|
||||
|
||||
// Temporary data arrays for triangles/quads
|
||||
int32 matTri;
|
||||
vector<trpg2dPoint> tex;
|
||||
vector<trpg3dPoint> norm,vert;
|
||||
// Data arrays for a polygon
|
||||
int32 matPoly;
|
||||
vector<trpg2dPoint> polyTex;
|
||||
vector<trpg3dPoint> polyNorm,polyVert;
|
||||
// Single points
|
||||
trpg2dPoint tmpTex;
|
||||
trpg3dPoint tmpNorm;
|
||||
trpgColor tmpCol;
|
||||
|
||||
// Geometry status built up as we go
|
||||
trpgwGeomStats stats;
|
||||
};
|
||||
|
||||
/* Paging Archive
|
||||
This is a writeable paging archive.
|
||||
It organizes where things get written and how.
|
||||
{group:Archive Writing}
|
||||
*/
|
||||
TX_EXDECL class TX_CLDECL trpgwArchive : public trpgCheckable {
|
||||
public:
|
||||
trpgwArchive(trpgEndian ness=LittleEndian);
|
||||
void init(trpgEndian);
|
||||
virtual ~trpgwArchive(void);
|
||||
|
||||
// Set functions. Have to fill all these out before writing
|
||||
virtual bool SetHeader(const trpgHeader &);
|
||||
virtual bool SetMaterialTable(const trpgMatTable &);
|
||||
virtual bool SetTextureTable(const trpgTexTable &);
|
||||
virtual bool SetModelTable(const trpgModelTable &);
|
||||
|
||||
// Note: For now, everything is external
|
||||
// enum {Local,External};
|
||||
// virtual bool SetModelMode(int);
|
||||
// virtual bool SetTileMode(int);
|
||||
|
||||
// Write functions.
|
||||
// For now, the header is written last.
|
||||
virtual bool OpenFile(const char *,const char *);
|
||||
virtual void CloseFile(void);
|
||||
// virtual bool OpenFile(const char *);
|
||||
virtual bool WriteHeader(void);
|
||||
virtual bool WriteTile(unsigned int,unsigned int,unsigned int,const trpgMemWriteBuffer *,const trpgMemWriteBuffer *);
|
||||
virtual bool DeleteTile(unsigned int,unsigned int,unsigned int);
|
||||
// virtual bool WriteModel(unsigned int,trpgMemWriteBuffer &);
|
||||
|
||||
bool isValid(void) const;
|
||||
char* getDir(){return dir;};
|
||||
protected:
|
||||
trpgEndian ness,cpuNess;
|
||||
// Fed in from the outside
|
||||
char dir[1024]; // Directory where we're doing all this
|
||||
trpgHeader header;
|
||||
trpgMatTable matTable;
|
||||
trpgTexTable texTable;
|
||||
trpgModelTable modelTable;
|
||||
|
||||
// Used by this class only
|
||||
trpgTileTable tileTable;
|
||||
// int modelMode,tileMode;
|
||||
FILE *fp;
|
||||
};
|
||||
|
||||
#endif
|
||||
286
src/osgPlugins/txp/trpage_writebuf.cpp
Normal file
286
src/osgPlugins/txp/trpage_writebuf.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
/* ************************
|
||||
Copyright Terrain Experts Inc.
|
||||
Terrain Experts Inc (TERREX) reserves all rights to this source code
|
||||
unless otherwise specified in writing by the Chief Operating Officer
|
||||
of TERREX.
|
||||
This copyright may be updated in the future, in which case that version
|
||||
supercedes this one.
|
||||
-------------------
|
||||
Terrex Experts Inc.
|
||||
84 West Santa Clara St., Suite 380
|
||||
San Jose, CA 95113
|
||||
info@terrex.com
|
||||
Tel: (408) 293-9977
|
||||
************************
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* trpage_writebuf.cpp
|
||||
This source file contains the implementation of trpgMemWriteBuffer.
|
||||
That is a subclass of trpgWriteBuffer, which implements an interface
|
||||
definition for an object which can accept data to be written.
|
||||
The Mem version is used to write (for example) a tile's worth of data.
|
||||
That data can then be written to a file (or sent over the network).
|
||||
You should not need to change this implementation. Simply sublcass
|
||||
trpgWriteBuffer and implement all of the required methods. The
|
||||
resulting class can then be used in all the places a trpgWriteBuffer
|
||||
is required.
|
||||
*/
|
||||
|
||||
#include "trpage_io.h"
|
||||
#include "trpage_swap.h"
|
||||
|
||||
/* **********************
|
||||
Memory Write Buffer functions
|
||||
**********************
|
||||
*/
|
||||
// Constructor
|
||||
trpgMemWriteBuffer::trpgMemWriteBuffer(trpgEndian in_ness)
|
||||
{
|
||||
ness = in_ness;
|
||||
cpuNess = trpg_cpu_byte_order();
|
||||
data = NULL;
|
||||
curLen = totLen = 0;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
trpgMemWriteBuffer::~trpgMemWriteBuffer()
|
||||
{
|
||||
if (data)
|
||||
delete data;
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
/* Length()
|
||||
Return the length of the given buffer.
|
||||
*/
|
||||
int trpgMemWriteBuffer::length() const
|
||||
{
|
||||
return curLen;
|
||||
}
|
||||
|
||||
/* getData()
|
||||
Return a pointer to the memory buffer.
|
||||
*/
|
||||
const char *trpgMemWriteBuffer::getData() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Length()
|
||||
Set the maximum buffer length.
|
||||
*/
|
||||
void trpgMemWriteBuffer::setLength(unsigned int len)
|
||||
{
|
||||
if ((int)len > totLen) {
|
||||
char *old_data = data;
|
||||
int oldLen = totLen;
|
||||
totLen = 2*len;
|
||||
data = new char[totLen];
|
||||
|
||||
if (old_data) {
|
||||
memcpy(data,old_data,oldLen);
|
||||
delete old_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* append()
|
||||
Append the given data to our buffer.
|
||||
*/
|
||||
void trpgMemWriteBuffer::append(unsigned int len,const char *val)
|
||||
{
|
||||
if (len == 0) return;
|
||||
setLength(curLen+len);
|
||||
memcpy(&data[curLen],val,len);
|
||||
curLen += len;
|
||||
}
|
||||
|
||||
/* set()
|
||||
Set a specific portion of the buffer to a given value.
|
||||
*/
|
||||
void trpgMemWriteBuffer::set(unsigned int pos,unsigned int len,const char *val)
|
||||
{
|
||||
if (len == 0) return;
|
||||
if (pos+len > (unsigned int)curLen) return;
|
||||
|
||||
memcpy(&data[pos],val,len);
|
||||
}
|
||||
|
||||
/* --- replacement virtual functions --- */
|
||||
|
||||
/* Reset()
|
||||
Drop whatever's being stored.
|
||||
*/
|
||||
void trpgMemWriteBuffer::Reset()
|
||||
{
|
||||
curLen = 0;
|
||||
}
|
||||
|
||||
// Add(Int32)
|
||||
void trpgMemWriteBuffer::Add(int32 val)
|
||||
{
|
||||
if (ness != cpuNess)
|
||||
val = trpg_byteswap_int(val);
|
||||
append(sizeof(int32),(const char *)&val);
|
||||
}
|
||||
|
||||
// Add(int64)
|
||||
void trpgMemWriteBuffer::Add(int64 val)
|
||||
{
|
||||
if (ness != cpuNess)
|
||||
val = trpg_byteswap_llong(val);
|
||||
append(sizeof(int64),(const char *)&val);
|
||||
}
|
||||
|
||||
// Add(string)
|
||||
// [len] [value...]
|
||||
void trpgMemWriteBuffer::Add(const char *val)
|
||||
{
|
||||
int32 len = (val ? strlen(val) : 0),vlen = len;
|
||||
if (ness != cpuNess)
|
||||
vlen = trpg_byteswap_int(vlen);
|
||||
append(sizeof(int32),(const char *)&len);
|
||||
append(len,val);
|
||||
}
|
||||
|
||||
// Add(float32)
|
||||
void trpgMemWriteBuffer::Add(float32 val)
|
||||
{
|
||||
char cval[4];
|
||||
if (ness != cpuNess)
|
||||
trpg_byteswap_float_to_4bytes(val,cval);
|
||||
else
|
||||
memcpy(cval,&val,4);
|
||||
|
||||
append(sizeof(float32),cval);
|
||||
}
|
||||
|
||||
// Add(float64)
|
||||
void trpgMemWriteBuffer::Add(float64 val)
|
||||
{
|
||||
char cval[8];
|
||||
if (ness != cpuNess)
|
||||
trpg_byteswap_double_to_8bytes(val,cval);
|
||||
else
|
||||
memcpy(cval,&val,8);
|
||||
|
||||
append(sizeof(float64),cval);
|
||||
}
|
||||
|
||||
// Add(int8)
|
||||
void trpgMemWriteBuffer::Add(uint8 val)
|
||||
{
|
||||
// No byte swapping needed
|
||||
append(sizeof(uint8),(const char *)&val);
|
||||
}
|
||||
|
||||
#if (bool != int32)
|
||||
// Add(bool)
|
||||
void trpgMemWriteBuffer::Add(bool val)
|
||||
{
|
||||
uint8 ival;
|
||||
|
||||
ival = (val ? 1 : 0);
|
||||
Add(ival);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (trpgDiskRef != int64)
|
||||
// Add(trpgDiskRef)
|
||||
void trpgMemWriteBuffer::Add(trpgDiskRef val)
|
||||
{
|
||||
if (ness != cpuNess)
|
||||
val = trpg_byteswap_llong(val);
|
||||
|
||||
append(sizeof(trpgDiskRef),(const char *)&val);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Add(trpgToken)
|
||||
void trpgMemWriteBuffer::Add(trpgToken val)
|
||||
{
|
||||
if (ness != cpuNess)
|
||||
val = trpg_byteswap_short(val);
|
||||
|
||||
append(sizeof(trpgToken),(const char *)&val);
|
||||
}
|
||||
|
||||
// Add(tx2iPoint)
|
||||
void trpgWriteBuffer::Add(const trpg2iPoint &val)
|
||||
{
|
||||
Add((int32)val.x);
|
||||
Add((int32)val.y);
|
||||
}
|
||||
|
||||
// Add(tx2dPoint)
|
||||
void trpgWriteBuffer::Add(const trpg2dPoint &val)
|
||||
{
|
||||
Add((float64)val.x);
|
||||
Add((float64)val.y);
|
||||
}
|
||||
|
||||
// Add(trpg3dPoint)
|
||||
void trpgWriteBuffer::Add(const trpg3dPoint &val)
|
||||
{
|
||||
Add((float64)val.x);
|
||||
Add((float64)val.y);
|
||||
Add((float64)val.z);
|
||||
}
|
||||
|
||||
// Add(trpgColor)
|
||||
void trpgWriteBuffer::Add(const trpgColor &val)
|
||||
{
|
||||
Add(val.red);
|
||||
Add(val.green);
|
||||
Add(val.blue);
|
||||
}
|
||||
|
||||
/* Push()
|
||||
Starts defining a new object.
|
||||
Need to keep track of where length goes.
|
||||
*/
|
||||
void trpgMemWriteBuffer::Begin(trpgToken tok)
|
||||
{
|
||||
Add(tok);
|
||||
lengths.push_back(curLen);
|
||||
Add((int32)0);
|
||||
}
|
||||
|
||||
/* Push()
|
||||
Pushes a level on the stack. For defining children.
|
||||
*/
|
||||
void trpgMemWriteBuffer::Push()
|
||||
{
|
||||
Add((trpgToken)TRPG_PUSH);
|
||||
}
|
||||
|
||||
/* Pop()
|
||||
Pops a level off the "stack".
|
||||
*/
|
||||
void trpgMemWriteBuffer::Pop()
|
||||
{
|
||||
Add((trpgToken)TRPG_POP);
|
||||
}
|
||||
|
||||
/* End()
|
||||
Finished defining an object.
|
||||
Write the length out where appropriate.
|
||||
*/
|
||||
void trpgMemWriteBuffer::End()
|
||||
{
|
||||
if (lengths.size() == 0)
|
||||
// Note: say something clever here
|
||||
return;
|
||||
|
||||
int id = lengths.size()-1;
|
||||
int32 len = curLen - lengths[id];
|
||||
int32 rlen = len-sizeof(int32);
|
||||
if (ness != cpuNess)
|
||||
rlen = trpg_byteswap_int(rlen);
|
||||
set(curLen - len,sizeof(int32),(const char *)&rlen);
|
||||
lengths.resize(id);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ Paragraph::Paragraph()
|
||||
}
|
||||
|
||||
Paragraph::Paragraph(const Paragraph& paragraph,const osg::CopyOp& copyop):
|
||||
Geode(paragraph,copyop),
|
||||
osg::Geode(paragraph,copyop),
|
||||
_position(paragraph._position),
|
||||
_text(paragraph._text),
|
||||
_font(dynamic_cast<Font*>(copyop(paragraph._font.get()))),
|
||||
|
||||
Reference in New Issue
Block a user