Initial revision

This commit is contained in:
Don BURNS
2001-01-10 16:32:10 +00:00
parent 7c12eb9361
commit 70208ebc06
461 changed files with 70936 additions and 0 deletions

29
src/Demos/Makefile Normal file
View File

@@ -0,0 +1,29 @@
#!smake
SHELL=/bin/sh
DIRS = sgv cube
all :
for f in $(DIRS) ; do cd $$f; make ; cd ..; done
clean :
for f in $(DIRS) ; do cd $$f; make clean; cd ..; done
clobber :
for f in $(DIRS) ; do cd $$f; make clobber; cd ..; done
depend :
for f in $(DIRS) ; do cd $$f; make depend; cd ..; done
to_unix :
for f in $(DIRS) ; do cd $$f; to_unix Makefile Makefile; cd ..; done
for f in $(DIRS) ; do cd $$f; make to_unix; cd ..; done
install :
for f in $(DIRS) ; do cd $$f; make install; cd ..; done
instlinks :
for f in $(DIRS) ; do cd $$f; make instlinks; cd ..; done
instclean :
for f in $(DIRS) ; do cd $$f; make instclean; cd ..; done

View File

15
src/Demos/cube/Makefile Normal file
View File

@@ -0,0 +1,15 @@
#!smake
include ../../../Make/makedefs
C++FILES = \
cube.cpp
TARGET = ../../../bin/cube
TARGET_BIN_FILES = cube
LIBS = -losgGLUT -losgUtil -losg -lglut -lGLU -lGL -lm -lXmu -lX11 -lXi
C++FLAGS += -I../../../include
LDFLAGS += -L../../../lib -L/usr/X11R6/lib
include ../../../Make/makerules

135
src/Demos/cube/cube.cpp Normal file
View File

@@ -0,0 +1,135 @@
#include "osgGLUT/Viewer"
#include "osg/Geode"
#include "osg/GeoSet"
#include "osg/GeoState"
#include "osg/Material"
#include "osg/Vec3"
#include "osg/DCS"
#include <GL/glut.h>
#include <math.h>
// ----------------------------------------------------------------------
// Global variables - this is basically the stuff which will be animated
// ----------------------------------------------------------------------
osg::DCS* myDCS;
osg::GeoSet* cube;
int mytime=0; // in milliseconds
unsigned int dt=50; // in milliseconds
double omega=0.002; // in inverse milliseconds
// ----------------------------------------------------------------
// This is the callback function registered with GLUT to be called
// at a future time in the GLUT loop
// ----------------------------------------------------------------
void timedCB( int delta_t )
{
static float lastdx = 0;
static float lastdy = 0;
static float lastdz = 0;
mytime+=dt;
// ---------------------------------------------------------
// Update the DCS so that the cube will appear to oscillate
// ---------------------------------------------------------
double dx = 0.5 * cos( (double) omega * (double) mytime );
double dy = 0.5 * sin( (double) omega * (double) mytime );
double dz = 0.0;
myDCS->preTranslate( -lastdx, -lastdy, -lastdz );
myDCS->preTranslate( (float) dx, (float) dy, dz );
lastdx=dx; lastdy=dy; lastdz=dz;
// Graeme, commeted out this call as the cube itself remains static.
// cube->dirtyDisplayList();
// -------------------------------------------
// If required, reschedule the timed callback
// -------------------------------------------
if ( delta_t != 0 ) {
glutTimerFunc( (unsigned int) delta_t, timedCB, delta_t );
}
}
int main( int argc, char **argv )
{
osg::Geode* geode = new osg::Geode();
// -------------------------------------------
// Set up a new GeoSet which will be our cube
// -------------------------------------------
cube = new osg::GeoSet();
cube->setPrimType( osg::GeoSet::POLYGON );
cube->setNumPrims( 6 ); // the six square faces
int cubeLengthList[6] = { 4, 4, 4, 4, 4, 4 }; // each has 4 vertices
cube->setPrimLengths( cubeLengthList );
osg::Vec3 cubeCoords[24];
cubeCoords[0].set( -1.0000f, 1.0000f, -1.000f );
cubeCoords[1].set( 1.0000f, 1.0000f, -1.0000f );
cubeCoords[2].set( 1.0000f, -1.0000f, -1.0000f );
cubeCoords[3].set( -1.0000f, -1.0000f, -1.000 );
cubeCoords[4].set( 1.0000f, 1.0000f, -1.0000f );
cubeCoords[5].set( 1.0000f, 1.0000f, 1.0000f );
cubeCoords[6].set( 1.0000f, -1.0000f, 1.0000f );
cubeCoords[7].set( 1.0000f, -1.0000f, -1.0000f );
cubeCoords[8].set( 1.0000f, 1.0000f, 1.0000f );
cubeCoords[9].set( -1.0000f, 1.0000f, 1.000f );
cubeCoords[10].set( -1.0000f, -1.0000f, 1.000f );
cubeCoords[11].set( 1.0000f, -1.0000f, 1.0000f );
cubeCoords[12].set( -1.0000f, 1.0000f, 1.000 );
cubeCoords[13].set( -1.0000f, 1.0000f, -1.000 );
cubeCoords[14].set( -1.0000f, -1.0000f, -1.000 );
cubeCoords[15].set( -1.0000f, -1.0000f, 1.000 );
cubeCoords[16].set( -1.0000f, 1.0000f, 1.000 );
cubeCoords[17].set( 1.0000f, 1.0000f, 1.0000f );
cubeCoords[18].set( 1.0000f, 1.0000f, -1.0000f );
cubeCoords[19].set( -1.0000f, 1.0000f, -1.000f );
cubeCoords[20].set( -1.0000f, -1.0000f, 1.000f );
cubeCoords[21].set( -1.0000f, -1.0000f, -1.000f );
cubeCoords[22].set( 1.0000f, -1.0000f, -1.0000f );
cubeCoords[23].set( 1.0000f, -1.0000f, 1.0000f );
cube->setCoords( cubeCoords );
// ---------------------------------------
// Set up a GeoState to make the cube red
// ---------------------------------------
osg::GeoState* cubeState = new osg::GeoState();
osg::Material* redMaterial = new osg::Material();
osg::Vec4 red( 1.0f, 0.0f, 0.0f, 0.0f );
redMaterial->setEmission( osg::Material::FACE_FRONT_AND_BACK, red );
redMaterial->setAmbient( osg::Material::FACE_FRONT_AND_BACK, red );
redMaterial->setDiffuse( osg::Material::FACE_FRONT_AND_BACK, red );
redMaterial->setSpecular( osg::Material::FACE_FRONT_AND_BACK, red );
cubeState->setAttribute( osg::GeoState::MATERIAL, redMaterial );
cube->setGeoState( cubeState );
geode->addGeoSet( cube );
myDCS = new osg::DCS();
myDCS->addChild( geode );
glutInit( &argc, argv );
// ---------------------------------------------------------------------
// Register a timer callback with GLUT, in the first instance as a test
// This will call the function "timedCB(value)" after dt ms
// I have decided to use value as the time for the next scheduling
// If the last parameter=0 then don't reschedule the timer.
// ---------------------------------------------------------------------
glutTimerFunc( dt, timedCB, dt );
osgGLUT::Viewer viewer;
viewer.init( myDCS );
viewer.run();
return 0;
}

0
src/Demos/sgv/Makedepend Normal file
View File

19
src/Demos/sgv/Makefile Normal file
View File

@@ -0,0 +1,19 @@
#!smake
include ../../../Make/makedefs
C++FILES = \
sgv.cpp
TARGET = ../../../bin/sgv
TARGET_BIN_FILES = sgv
# LIBS = -losg -lglut -lGLU -lGL -lm -lXmu -lX11 -lXi
# C++FLAGS += -I../../include
# LDFLAGS += -L../../lib -L/usr/X11R6/lib
LIBS = -losgGLUT -losgUtil -losg -lglut -lGLU -lGL -lm -lXmu -lX11 -lXi
C++FLAGS += -I../../../include
LDFLAGS += -L../../../lib -L/usr/X11R6/lib
include ../../../Make/makerules

118
src/Demos/sgv/sgv.cpp Normal file
View File

@@ -0,0 +1,118 @@
#include "osg/OSG"
#include "osg/Node"
#include "osg/Registry"
#include "osg/Notify"
#include <GL/glut.h>
#include "osgGLUT/Viewer"
/*
* Function to read several files (typically one) as specified on the command
* line, and return them in an osg::Node
*/
osg::Node* getNodeFromFiles(int argc,char **argv)
{
osg::Node *rootnode = new osg::Node;
int i;
typedef std::vector<osg::Node*> NodeList;
NodeList nodeList;
for( i = 1; i < argc; i++ )
{
if (argv[i][0]=='-')
{
switch(argv[i][1])
{
case('l'):
++i;
if (i<argc)
{
osg::Registry::instance()->loadLibrary(argv[i]);
}
break;
case('e'):
++i;
if (i<argc)
{
std::string libName = osg::Registry::instance()->createLibraryNameForExt(argv[i]);
osg::Registry::instance()->loadLibrary(libName);
}
break;
}
} else
{
osg::Node *node = osg::loadNodeFile( argv[i] );
if( node != (osg::Node *)0L )
{
if (node->getName().empty()) node->setName( argv[i] );
nodeList.push_back(node);
}
}
}
if (nodeList.size()==0)
{
osg::notify(osg::WARN) << "No data loaded."<<endl;
exit(0);
}
if (nodeList.size()==1)
{
rootnode = nodeList.front();
}
else // size >1
{
osg::Group* group = new osg::Group();
for(NodeList::iterator itr=nodeList.begin();
itr!=nodeList.end();
++itr)
{
group->addChild(*itr);
}
rootnode = group;
}
return rootnode;
}
int main( int argc, char **argv )
{
if (argc<2)
{
osg::notify(osg::NOTICE)<<"usage:"<<endl;
osg::notify(osg::NOTICE)<<" sgv [options] infile1 [infile2 ...]"<<endl;
osg::notify(osg::NOTICE)<<endl;
osg::notify(osg::NOTICE)<<"options:"<<endl;
osg::notify(osg::NOTICE)<<" -l libraryName - load plugin of name libraryName"<<endl;
osg::notify(osg::NOTICE)<<" i.e. -l osgdb_pfb"<<endl;
osg::notify(osg::NOTICE)<<" Useful for loading reader/writers which can load"<<endl;
osg::notify(osg::NOTICE)<<" other file formats in addition to its extension."<<endl;
osg::notify(osg::NOTICE)<<" -e extensionName - load reader/wrter plugin for file extension"<<endl;
osg::notify(osg::NOTICE)<<" i.e. -e pfb"<<endl;
osg::notify(osg::NOTICE)<<" Useful short hand for specifying full library name as"<<endl;
osg::notify(osg::NOTICE)<<" done with -l above, as it automatically expands to the"<<endl;
osg::notify(osg::NOTICE)<<" full library name appropriate for each platform."<<endl;
osg::notify(osg::NOTICE)<<endl;
return 0;
}
osg::Node* rootnode = getNodeFromFiles( argc, argv);
osgGLUT::Viewer viewer;
glutInit( &argc, argv );
viewer.init( rootnode );
viewer.run();
return 0;
}

36
src/Makefile Normal file
View File

@@ -0,0 +1,36 @@
#!smake
SHELL=/bin/sh
DIRS = osg osgUtil osgGLUT Demos osgPlugins
all :
for f in $(DIRS) ; do cd $$f; make ; cd ..; done
clean :
for f in $(DIRS) ; do cd $$f; make clean; cd ..; done
clobber :
for f in $(DIRS) ; do cd $$f; make clobber; cd ..; done
depend :
for f in $(DIRS) ; do cd $$f; make depend; cd ..; done
docs :
(cd osg; make docs;)
(cd osgUtil; make docs; )
(cd osgGLUT; make docs; )
to_unix :
for f in $(DIRS) ; do cd $$f; to_unix Makefile Makefile; cd ..; done
for f in $(DIRS) ; do cd $$f; make to_unix; cd ..; done
install :
for f in $(DIRS) ; do cd $$f; make install; cd ..; done
instlinks :
for f in $(DIRS) ; do cd $$f; make instlinks; cd ..; done
instclean :
for f in $(DIRS) ; do cd $$f; make instclean; cd ..; done

101
src/osg/AlphaFunc.cpp Normal file
View File

@@ -0,0 +1,101 @@
#include "osg/GL"
#include "osg/AlphaFunc"
#include "osg/Output"
#include "osg/Input"
using namespace osg;
AlphaFunc::AlphaFunc()
{
_comparisonFunc = ALWAYS;
_referenceValue = 1.0f;
}
AlphaFunc::~AlphaFunc()
{
}
AlphaFunc* AlphaFunc::instance()
{
static ref_ptr<AlphaFunc> s_AlphaFunc(new AlphaFunc);
return s_AlphaFunc.get();
}
void AlphaFunc::enable()
{
glEnable(GL_ALPHA_TEST);
}
void AlphaFunc::disable()
{
glDisable(GL_ALPHA_TEST);
}
void AlphaFunc::apply()
{
glAlphaFunc((GLenum)_comparisonFunc,_referenceValue);
}
bool AlphaFunc::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
ComparisonFunction func;
if (fr[0].matchWord("comparisonFunc") && matchFuncStr(fr[1].getStr(),func))
{
_comparisonFunc = func;
fr+=2;
iteratorAdvanced = true;
}
float ref;
if (fr[0].matchWord("referenceValue") && fr[1].getFloat(ref))
{
_referenceValue = ref;
fr+=2;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool AlphaFunc::writeLocalData(Output& fw)
{
fw.indent() << "comparisonFunc " << getFuncStr(_comparisonFunc) << endl;
fw.indent() << "referenceValue " << _referenceValue << endl;
return true;
}
bool AlphaFunc::matchFuncStr(const char* str,ComparisonFunction& func)
{
if (strcmp(str,"NEVER")==0) func = NEVER;
else if (strcmp(str,"LESS")==0) func = LESS;
else if (strcmp(str,"EQUAL")==0) func = EQUAL;
else if (strcmp(str,"LEQUAL")==0) func = LEQUAL;
else if (strcmp(str,"GREATER")==0) func = GREATER;
else if (strcmp(str,"NOTEQUAL")==0) func = NOTEQUAL;
else if (strcmp(str,"GEQUAL")==0) func = GEQUAL;
else if (strcmp(str,"ALWAYS")==0) func = ALWAYS;
else return false;
return true;
}
const char* AlphaFunc::getFuncStr(ComparisonFunction func)
{
switch(func)
{
case(NEVER): return "NEVER";
case(LESS): return "LESS";
case(EQUAL): return "EQUAL";
case(LEQUAL): return "LEQUAL";
case(GREATER): return "GREATER";
case(NOTEQUAL): return "NOTEQUAL";
case(GEQUAL): return "GEQUAL";
case(ALWAYS): return "ALWAYS";
}
return "";
}

272
src/osg/Billboard.cpp Normal file
View File

@@ -0,0 +1,272 @@
#include <stdio.h>
#include <math.h>
#include "osg/Billboard"
#include "osg/Input"
#include "osg/Output"
#include "osg/Registry"
using namespace osg;
RegisterObjectProxy<Billboard> g_BillboardProxy;
#define square(x) ((x)*(x))
Billboard::Billboard()
{
_mode = AXIAL_ROT;
// _mode = POINT_ROT_WORLD;
_axis.set(0.0f,0.0f,1.0f);
}
Billboard::~Billboard()
{
}
bool Billboard::addGeoSet(GeoSet *gset)
{
if (Geode::addGeoSet(gset))
{
Vec3 pos(0.0f,0.0f,0.0f);
while (_positionList.size()<_geosets.size())
{
_positionList.push_back(pos);
}
return true;
}
return false;
}
bool Billboard::addGeoSet(GeoSet *gset,const Vec3& pos)
{
if (Geode::addGeoSet(gset))
{
while (_positionList.size()<_geosets.size())
{
_positionList.push_back(pos);
}
return true;
}
return false;
}
bool Billboard::removeGeoSet( GeoSet *gset )
{
PositionList::iterator pitr = _positionList.begin();
for (GeoSetList::iterator itr=_geosets.begin();
itr!=_geosets.end();
++itr,++pitr)
{
if (itr->get()==gset)
{
// note ref_ptr<> automatically handles decrementing gset's reference count.
_geosets.erase(itr);
_positionList.erase(pitr);
_bsphere_computed = false;
return true;
}
}
return false;
}
void Billboard::calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix& mat)
{
switch(_mode)
{
case(AXIAL_ROT):
{
Vec3 ev = pos_local-eye_local;
ev.z() = 0.0f;
float ev_length = ev.length();
if (ev_length>0.0f) {
//float rotation_zrotation_z = atan2f(ev.x(),ev.y());
//mat.makeRot(rotation_z*180.0f/M_PI,0.0f,0.0f,1.0f);
float inv = 1.0f/ev_length;
float c = ev.y()*inv;
float s = ev.x()*inv;
mat._mat[0][0] = c;
mat._mat[0][1] = -s;
mat._mat[1][0] = s;
mat._mat[1][1] = c;
}
break;
}
case(POINT_ROT_WORLD):
case(POINT_ROT_EYE):
{
Vec3 ev = pos_local-eye_local;
ev.normalize();
float ev_len = ev.length();
if (ev_len != 0.0f)
{
ev /= ev_len;
Vec3 cp = ev^Vec3(0.0f,1.0f,0.0f);
float dot = ev*Vec3(0.0f,1.0f,0.0f);
float cp_len = cp.length();
if (cp_len != 0.0f)
{
cp /= cp_len;
float rotation_cp = acosf(dot);
mat.makeRot(rotation_cp*180.0f/M_PI,cp[0],cp[1],cp[2]);
}
}
break;
}
}
}
void Billboard::calcTransform(const Vec3& eye_local, const Vec3& pos_local,Matrix& mat)
{
// mat.makeTrans(pos_local[0],pos_local[1],pos_local[2]);
// mat.makeIdent();
calcRotation(eye_local,pos_local,mat);
// mat.postTrans(pos_local[0],pos_local[1],pos_local[2]);
mat._mat[3][0] += pos_local[0];
mat._mat[3][1] += pos_local[1];
mat._mat[3][2] += pos_local[2];
}
bool Billboard::readLocalData(Input& fr)
{
// note, free done by Node::read(Input& fr)
bool iteratorAdvanced = false;
if (fr[0].matchWord("Mode"))
{
if (fr[1].matchWord("AXIAL_ROT"))
{
_mode = AXIAL_ROT;
fr+=2;
iteratorAdvanced = true;
}
else if (fr[1].matchWord("POINT_ROT_EYE"))
{
_mode = POINT_ROT_EYE;
fr+=2;
iteratorAdvanced = true;
}
else if (fr[1].matchWord("POINT_ROT_WORLD"))
{
_mode = POINT_ROT_WORLD;
fr+=2;
iteratorAdvanced = true;
}
}
// read the position data.
bool matchFirst = false;
if ((matchFirst=fr.matchSequence("Positions {")) || fr.matchSequence("Positions %i {"))
{
// set up coordinates.
int entry = fr[0].getNoNestedBrackets();
if (matchFirst)
{
fr += 2;
}
else
{
//_positionList.(capacity);
fr += 3;
}
Vec3 pos;
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
{
if (fr[0].getFloat(pos[0]) && fr[1].getFloat(pos[1]) && fr[2].getFloat(pos[2]))
{
fr += 3;
_positionList.push_back(pos);
}
else
{
++fr;
}
}
iteratorAdvanced = true;
++fr;
}
if (Geode::readLocalData(fr)) iteratorAdvanced = true;
return iteratorAdvanced;
}
bool Billboard::writeLocalData(Output& fw)
{
switch(_mode)
{
case(AXIAL_ROT): fw.indent() << "Mode AXIAL_ROT"<<endl; break;
case(POINT_ROT_EYE): fw.indent() << "Mode POINT_ROT_EYE"<<endl; break;
case(POINT_ROT_WORLD): fw.indent() << "Mode POINT_ROT_WORLD"<<endl; break;
}
fw.indent() << "Axis " << _axis[0] << " "<<_axis[1]<<" "<<_axis[2]<<endl;
fw.indent() << "Positions {"<<endl;
fw.moveIn();
for(PositionList::iterator piter = _positionList.begin();
piter != _positionList.end();
++piter)
{
fw.indent() << (*piter)[0] << " "<<(*piter)[1]<<" "<<(*piter)[2]<<endl;
}
fw.moveOut();
fw.indent() << "}"<<endl;
Geode::writeLocalData(fw);
return true;
}
bool Billboard::computeBound( void )
{
int i;
int ngsets = _geosets.size();
if( ngsets == 0 ) return false;
_bsphere._center.set(0.0f,0.0f,0.0f);
for( i = 0; i < ngsets; i++ )
{
GeoSet *gset = _geosets[i].get();
const BoundingBox& bbox = gset->getBound();
_bsphere._center += bbox.center();
_bsphere._center += _positionList[i];
}
_bsphere._center /= (float)(ngsets);
float maxd = 0.0;
for( i = 0; i < ngsets; ++i )
{
GeoSet *gset = _geosets[i].get();
const BoundingBox& bbox = gset->getBound();
Vec3 local_center = _bsphere._center-_positionList[i];
for(unsigned int c=0;c<8;++c)
{
float d = (bbox.corner(c)-local_center).length2();
if( d > maxd ) maxd = d;
}
}
_bsphere._radius = sqrtf(maxd);
_bsphere_computed=true;
return true;
}

44
src/osg/BoundingBox.cpp Normal file
View File

@@ -0,0 +1,44 @@
#include "osg/BoundingBox"
#include "osg/BoundingSphere"
using namespace osg;
void BoundingBox::expandBy(const Vec3& v)
{
if(v.x()<_min.x()) _min.x() = v.x();
if(v.x()>_max.x()) _max.x() = v.x();
if(v.y()<_min.y()) _min.y() = v.y();
if(v.y()>_max.y()) _max.y() = v.y();
if(v.z()<_min.z()) _min.z() = v.z();
if(v.z()>_max.z()) _max.z() = v.z();
}
void BoundingBox::expandBy(const BoundingBox& bb)
{
if (!bb.isValid()) return;
if(bb._min.x()<_min.x()) _min.x() = bb._min.x();
if(bb._max.x()>_max.x()) _max.x() = bb._max.x();
if(bb._min.y()<_min.y()) _min.y() = bb._min.y();
if(bb._max.y()>_max.y()) _max.y() = bb._max.y();
if(bb._min.z()<_min.z()) _min.z() = bb._min.z();
if(bb._max.z()>_max.z()) _max.z() = bb._max.z();
}
void BoundingBox::expandBy(const BoundingSphere& sh)
{
if (!sh.isValid()) return;
if(sh._center.x()-sh._radius<_min.x()) _min.x() = sh._center.x()-sh._radius;
if(sh._center.x()+sh._radius>_max.x()) _max.x() = sh._center.x()+sh._radius;
if(sh._center.y()-sh._radius<_min.y()) _min.y() = sh._center.y()-sh._radius;
if(sh._center.y()+sh._radius>_max.y()) _max.y() = sh._center.y()+sh._radius;
if(sh._center.z()-sh._radius<_min.z()) _min.z() = sh._center.z()-sh._radius;
if(sh._center.z()+sh._radius>_max.z()) _max.z() = sh._center.z()+sh._radius;
}

View File

@@ -0,0 +1,81 @@
#include "osg/BoundingSphere"
using namespace osg;
void BoundingSphere::expandBy(const Vec3& v)
{
if (isValid())
{
Vec3 dv = v-_center;
float r = dv.length();
if (r>_radius)
{
float dr = (r-_radius)*0.5f;
_center += dv*(dr/r);
_radius += dr;
} // else do nothing as vertex is within sphere.
}
else
{
_center = v;
_radius = 0.0f;
}
}
void BoundingSphere::expandRadiusBy(const Vec3& v)
{
if (isValid())
{
float r = (v-_center).length();
if (r>_radius) _radius = r;
// else do nothing as vertex is within sphere.
}
else
{
_center = v;
_radius = 0.0f;
}
}
void BoundingSphere::expandBy(const BoundingSphere& sh)
{
if (sh.isValid())
{
if (isValid())
{
Vec3 dv = sh._center-_center;
float dv_len = dv.length();
if (dv_len+sh._radius>_radius)
{
Vec3 e1 = _center-(dv*(_radius/dv_len));
Vec3 e2 = sh._center+(dv*(sh._radius/dv_len));
_center = (e1+e2)*0.5f;
_radius = (e2-_center).length();
} // else do nothing as vertex is within sphere.
}
else
{
_center = sh._center;
_radius = sh._radius;
}
}
}
void BoundingSphere::expandRadiusBy(const BoundingSphere& sh)
{
if (sh.isValid())
{
if (isValid())
{
float r = (sh._center-_center).length()+sh._radius;
if (r>_radius) _radius = r;
// else do nothing as vertex is within sphere.
}
else
{
_center = sh._center;
_radius = sh._radius;
}
}
}

85
src/osg/Camera.cpp Normal file
View File

@@ -0,0 +1,85 @@
#include "osg/GL"
#include <osg/Camera>
using namespace osg;
Camera::Camera()
{
_fovy = 60.0;
_aspectRatio = 1.0;
home();
}
Camera::~Camera()
{
}
void Camera::home()
{
_eyePoint.set(0.0f,0.0f,0.0f);
_lookPoint.set(0.0f,0.0f,-1.0f);
_upVector.set(0.0f,1.0f,0.0f);
_nearPlane = 1.0;
_farPlane = 1000.0;
}
void Camera::setView(osg::Vec3 eyePoint, osg::Vec3 lookPoint, osg::Vec3 upVector)
{
// Should do some checking here!
_eyePoint = eyePoint;
_lookPoint = lookPoint;
_upVector = upVector;
}
void Camera::draw_PROJECTION() const
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective(_fovy, _aspectRatio, static_cast<GLdouble>(_nearPlane), static_cast<GLdouble>(_farPlane));
glMatrixMode( GL_MODELVIEW );
}
void Camera::draw_MODELVIEW() const
{
glMatrixMode( GL_MODELVIEW );
gluLookAt( _eyePoint.x(), _eyePoint.y(), _eyePoint.z(),
_lookPoint.x(), _lookPoint.y(), _lookPoint.z(),
_upVector.x(), _upVector.y(), _upVector.z());
}
void Camera::ensureOrthogonalUpVector()
{
Vec3 lv = _lookPoint-_eyePoint;
Vec3 sv = lv^_upVector;
_upVector = sv^lv;
_upVector.normalize();
}
void Camera::mult(const Camera& camera,const Matrix& m)
{
// transform camera.
_upVector = (camera._lookPoint+camera._upVector)*m;
_eyePoint = camera._eyePoint*m;
_lookPoint = camera._lookPoint*m;
_upVector -= _lookPoint;
// now reset up vector so it remains at 90 degrees to look vector,
// as it may drift during transformation.
ensureOrthogonalUpVector();
}
void Camera::mult(const Matrix& m,const Camera& camera)
{
// transform camera.
_upVector = m*(camera._lookPoint+camera._upVector);
_eyePoint = m*camera._eyePoint;
_lookPoint = m*camera._lookPoint;
_upVector -= _lookPoint;
// now reset up vector so it remains at 90 degrees to look vector,
// as it may drift during transformation.
ensureOrthogonalUpVector();
}

80
src/osg/CullFace.cpp Normal file
View File

@@ -0,0 +1,80 @@
#include "osg/GL"
#include "osg/CullFace"
#include "osg/Output"
#include "osg/Input"
using namespace osg;
CullFace::CullFace()
{
_mode = BACK;
}
CullFace::~CullFace()
{
}
CullFace* CullFace::instance()
{
static ref_ptr<CullFace> s_CullFace(new CullFace);
return s_CullFace.get();
}
void CullFace::enable( void )
{
glEnable( GL_CULL_FACE );
}
void CullFace::disable( void )
{
glDisable( GL_CULL_FACE );
}
void CullFace::apply()
{
glCullFace((GLenum)_mode);
}
bool CullFace::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (fr[0].matchWord("mode"))
{
if (fr[1].matchWord("FRONT"))
{
_mode = FRONT;
fr+=2;
iteratorAdvanced = true;
}
else if (fr[1].matchWord("BACK"))
{
_mode = BACK;
fr+=2;
iteratorAdvanced = true;
}
else if (fr[1].matchWord("FRONT_AND_BACK"))
{
_mode = FRONT_AND_BACK;
fr+=2;
iteratorAdvanced = true;
}
}
return iteratorAdvanced;
}
bool CullFace::writeLocalData(Output& fw)
{
switch(_mode)
{
case(FRONT): fw.indent() << "mode FRONT" << endl; break;
case(BACK): fw.indent() << "mode BACK" << endl; break;
case(FRONT_AND_BACK): fw.indent() << "mode FRONT_AND_BACK" << endl; break;
}
return true;
}

112
src/osg/DCS.cpp Normal file
View File

@@ -0,0 +1,112 @@
#include "osg/DCS"
#include "osg/Registry"
#include "osg/Input"
#include "osg/Output"
using namespace osg;
RegisterObjectProxy<DCS> g_DCSProxy;
DCS::DCS()
{
_mat = new Matrix(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
_mat->ref();
}
DCS::DCS(const Matrix& mat )
{
_mat = new Matrix(mat);
_mat->ref();
}
DCS::~DCS()
{
_mat->unref();
}
void DCS::setMatrix(const Matrix& mat )
{
*_mat = mat;
dirtyBound();
}
void DCS::preTranslate( float tx, float ty, float tz )
{
_mat->preTrans( tx, ty, tz );
dirtyBound();
}
void DCS::preRotate( float deg, float x, float y, float z )
{
_mat->preRot( deg, x, y, z );
dirtyBound();
}
bool DCS::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (Matrix* tmpMatrix = static_cast<Matrix*>(Matrix::instance()->readClone(fr)))
{
if (_mat) _mat->unref();
_mat = tmpMatrix;
_mat->ref();
iteratorAdvanced = true;
}
if (Group::readLocalData(fr)) iteratorAdvanced = true;
return iteratorAdvanced;
}
bool DCS::writeLocalData(Output& fw)
{
if (_mat) _mat->write(fw);
return Group::writeLocalData(fw);
}
bool DCS::computeBound( void )
{
if (!Group::computeBound()) return false;
Vec3 xdash = _bsphere._center;
xdash.x() += _bsphere._radius;
xdash = xdash*(*_mat);
Vec3 ydash = _bsphere._center;
ydash.y() += _bsphere._radius;
ydash = ydash*(*_mat);
Vec3 zdash = _bsphere._center;
zdash.y() += _bsphere._radius;
zdash = zdash*(*_mat);
_bsphere._center = _bsphere._center*(*_mat);
xdash -= _bsphere._center;
float len_xdash = xdash.length();
ydash -= _bsphere._center;
float len_ydash = ydash.length();
zdash -= _bsphere._center;
float len_zdash = zdash.length();
_bsphere._radius = len_xdash;
if (_bsphere._radius<len_ydash) _bsphere._radius = len_ydash;
if (_bsphere._radius<len_zdash) _bsphere._radius = len_zdash;
return true;
}

View File

@@ -0,0 +1,66 @@
#ifdef WIN32
#include <Io.h>
#include <Windows.h>
#include <Winbase.h>
#else
#include <unistd.h>
#include <dlfcn.h>
#endif
#ifndef OSG_USE_IO_DOT_H
#include <iostream>
using namespace std;
#endif
#include "osg/DynamicLibrary"
#include "osg/OSG"
#include "osg/Notify"
using namespace osg;
DynamicLibrary::DynamicLibrary(const std::string& name,HANDLE handle)
{
_name = name;
_handle = handle;
}
DynamicLibrary::~DynamicLibrary()
{
if (_handle)
{
#ifdef WIN32
FreeLibrary((HMODULE)_handle);
#else
dlclose(_handle);
#endif
}
}
DynamicLibrary* DynamicLibrary::loadLibrary(const std::string& libraryName)
{
char* fullLibraryName = osg::findDSO( libraryName.c_str() );
if (fullLibraryName==NULL) return NULL;
#ifdef WIN32
HANDLE handle = LoadLibrary( fullLibraryName );
if (handle) return new DynamicLibrary(libraryName,handle);
notify(WARN) << "DynamicLibrary::failed loading "<<fullLibraryName<<endl;
#else
HANDLE handle = dlopen( fullLibraryName, RTLD_LAZY );
if (handle) return new DynamicLibrary(libraryName,handle);
notify(WARN) << "DynamicLibrary::failed loading "<<fullLibraryName<<endl;
notify(WARN) << "DynamicLibrary::error "<<dlerror()<<endl;
#endif
return NULL;
}
DynamicLibrary::PROC_ADDRESS DynamicLibrary::getProcAddress(const std::string& procName)
{
if (_handle==NULL) return NULL;
#ifdef WIN32
return GetProcAddress( (HMODULE)_handle, procName.c_str() );
#else
return dlsym( _handle, procName.c_str() );
#endif
}

View File

@@ -0,0 +1,45 @@
#include "osg/GL"
#include "osg/ExtensionSupported"
#include <stdlib.h>
#include <string.h>
// copied form glut_ext.c
// to be rewritten... Robert Osfield, November 2000.
bool osg::ExtensionSupported(const char *extension)
{
static const GLubyte *extensions = NULL;
const GLubyte *start;
GLubyte *where, *terminator;
/* Extension names should not have spaces. */
where = (GLubyte *) strchr(extension, ' ');
if (where || *extension == '\0')
return 0;
if (!extensions) {
extensions = glGetString(GL_EXTENSIONS);
}
/* It takes a bit of care to be fool-proof about parsing the
OpenGL extensions string. Don't be fooled by sub-strings,
etc. */
start = extensions;
for (;;) {
/* If your application crashes in the strstr routine below,
you are probably calling glutExtensionSupported without
having a current window. Calling glGetString without
a current OpenGL context has unpredictable results.
Please fix your program. */
where = (GLubyte *) strstr((const char *) start, extension);
if (!where)
break;
terminator = where + strlen(extension);
if (where == start || *(where - 1) == ' ') {
if (*terminator == ' ' || *terminator == '\0') {
return true;
}
}
start = terminator;
}
return false;
}

422
src/osg/Field.cpp Normal file
View File

@@ -0,0 +1,422 @@
#include "osg/Field"
using namespace osg;
Field::Field()
{
_init();
}
Field::Field(const Field& ic)
{
_copy(ic);
}
Field::~Field()
{
_free();
}
Field& Field::operator = (const Field& ic)
{
if (this==&ic) return *this;
_free();
_copy(ic);
return *this;
}
void Field::_free()
{
// free all data
if (_fieldCache) delete [] _fieldCache;
_init();
}
void Field::_init()
{
_fieldCacheCapacity = 256;
_fieldCacheSize = 0;
_fieldCache = NULL;
_fieldType = UNINTIALISED;
_withinQuotes = false;
_noNestedBrackets = 0;
}
void Field::_copy(const Field& ic)
{
// copy string cache.
if (ic._fieldCache)
{
_fieldCacheCapacity = ic._fieldCacheCapacity;
_fieldCacheSize = ic._fieldCacheSize;
_fieldCache = new char [_fieldCacheCapacity];
strncpy(_fieldCache,ic._fieldCache,_fieldCacheCapacity);
}
else
{
_fieldCacheCapacity = 0;
_fieldCacheSize = 0;
_fieldCache = NULL;
}
_fieldType = ic._fieldType;
_withinQuotes = ic._withinQuotes;
_noNestedBrackets = ic._noNestedBrackets;
}
void Field::setWithinQuotes(bool withinQuotes)
{
_withinQuotes=withinQuotes;
_fieldType = UNINTIALISED;
}
bool Field::getWithinQuotes()
{
return _withinQuotes;
}
void Field::setNoNestedBrackets(int no)
{
_noNestedBrackets=no;
}
int Field::getNoNestedBrackets()
{
return _noNestedBrackets;
}
const char* Field::getStr() const
{
if (_fieldCacheSize!=0) return _fieldCache;
else return NULL;
}
char* Field::takeStr()
{
char* field = _fieldCache;
_fieldCache = NULL;
_fieldCacheSize = 0;
_fieldType = UNINTIALISED;
_withinQuotes = false;
return field;
}
void Field::reset()
{
_fieldCacheSize = 0;
if (_fieldCache)
{
_fieldCache[_fieldCacheSize] = 0;
}
_withinQuotes = false;
_noNestedBrackets = 0;
}
void Field::addChar(char c)
{
if (_fieldCache==NULL)
{
if (_fieldCacheCapacity<MIN_CACHE_SIZE) _fieldCacheCapacity=MIN_CACHE_SIZE;
_fieldCache = new char[_fieldCacheCapacity];
_fieldCacheSize = 0;
}
else if (_fieldCacheSize>=_fieldCacheCapacity-1)
{
if (_fieldCacheCapacity<MIN_CACHE_SIZE) _fieldCacheCapacity=MIN_CACHE_SIZE;
while (_fieldCacheSize>=_fieldCacheCapacity-1) _fieldCacheCapacity *= 2;
char* tmp_str = _fieldCache;
_fieldCache = new char[_fieldCacheCapacity];
strncpy(_fieldCache,tmp_str,_fieldCacheSize);
delete [] tmp_str;
}
_fieldCache[_fieldCacheSize++] = c;
_fieldCache[_fieldCacheSize] = 0;
_fieldType = UNINTIALISED;
}
Field::FieldType Field::getFieldType() const
{
if (_fieldType==UNINTIALISED && _fieldCache)
{
_fieldType = calculateFieldType(_fieldCache,_withinQuotes);
}
return _fieldType;
}
bool Field::isValid() const
{
if (_fieldCacheSize>0 && !_withinQuotes) return true;
else return false;
}
bool Field::isOpenBracket() const
{
if (_fieldCacheSize==1) return _fieldCache[0]=='{';
else return false;
}
bool Field::isCloseBracket() const
{
if (_fieldCacheSize==1) return _fieldCache[0]=='}';
else return false;
}
bool Field::isWord() const
{
getFieldType();
return (_fieldType==WORD);
}
bool Field::matchWord(const char* str) const
{
getFieldType();
return _fieldType==WORD && strcmp(_fieldCache,str)==0;
}
bool Field::matchWord(const char* str,int noCharacters) const
{
getFieldType();
return _fieldType==WORD && strncmp(_fieldCache,str,noCharacters)==0;
}
bool Field::isString() const
{
return getNoCharacters()!=0;
}
bool Field::matchString(const char* str) const
{
return strcmp(_fieldCache,str)==0;
}
bool Field::matchString(const char* str,int noCharacters) const
{
return strncmp(_fieldCache,str,noCharacters)==0;
}
bool Field::isQuotedString() const
{
return _withinQuotes;
}
bool Field::isInt() const
{
getFieldType();
return _fieldType==INTEGER;
}
bool Field::matchInt(int i) const
{
getFieldType();
if (_fieldType==INTEGER)
{
return atoi(_fieldCache)==i;
}
else
{
return false;
}
}
bool Field::getInt(int& i) const
{
getFieldType();
if (_fieldType==INTEGER)
{
i = atoi(_fieldCache);
return true;
}
else
{
return false;
}
}
bool Field::isFloat() const
{
getFieldType();
return _fieldType==REAL || _fieldType==INTEGER;
}
bool Field::matchFloat(float f) const
{
getFieldType();
if (_fieldType==REAL || _fieldType==INTEGER)
{
return (float)atof(_fieldCache)==f;
}
else
{
return false;
}
}
bool Field::getFloat(float& f) const
{
getFieldType();
if (_fieldType==REAL || _fieldType==INTEGER)
{
f = (float)atof(_fieldCache);
return true;
}
else
{
return false;
}
}
bool Field::isDouble() const
{
getFieldType();
return _fieldType==REAL || _fieldType==INTEGER;
}
bool Field::matchDouble(double d) const
{
getFieldType();
if (_fieldType==REAL || _fieldType==INTEGER)
{
return atof(_fieldCache)==d;
}
else
{
return false;
}
}
bool Field::getDouble(double& d) const
{
getFieldType();
if (_fieldType==REAL || _fieldType==INTEGER)
{
d = atof(_fieldCache);
return true;
}
else
{
return false;
}
}
Field::FieldType Field::calculateFieldType(const char* str,bool withinQuotes)
{
if (str==NULL) return BLANK;
if (*str==0) return BLANK;
if (withinQuotes) return STRING;
bool hadPlusMinus = false;
bool hadDecimalPlace = false;
bool hadExponent = false;
bool couldBeInt = true;
bool couldBeFloat = true;
int noZeroToNine = 0;
const char* ptr = str;
while (*ptr!=0 && couldBeFloat)
{
if (*ptr=='+' || *ptr=='-')
{
if (hadPlusMinus)
{
couldBeInt = false;
couldBeFloat = false;
} else hadPlusMinus = true;
}
else if (*ptr>='0' && *ptr<='9')
{
noZeroToNine++;
}
else if (*ptr=='.')
{
if (hadDecimalPlace)
{
couldBeInt = false;
couldBeFloat = false;
}
else
{
hadDecimalPlace = true;
couldBeInt = false;
}
}
else if (*ptr=='e' || *ptr=='E')
{
if (hadExponent || noZeroToNine==0)
{
couldBeInt = false;
couldBeFloat = false;
}
else
{
hadExponent = true;
couldBeInt = false;
hadDecimalPlace = false;
hadPlusMinus = false;
noZeroToNine=0;
}
}
else
{
couldBeInt = false;
couldBeFloat = false;
}
++ptr;
}
if (couldBeInt && noZeroToNine>0) return INTEGER;
if (couldBeFloat && noZeroToNine>0) return REAL;
if (str[0]=='{') return OPEN_BRACKET;
if (str[0]=='}') return CLOSE_BRACKET;
return WORD;
}

269
src/osg/FieldReader.cpp Normal file
View File

@@ -0,0 +1,269 @@
#include "osg/FieldReader"
#include "osg/Field"
using namespace osg;
FieldReader::FieldReader()
{
_init();
}
FieldReader::FieldReader(const FieldReader& ic)
{
_copy(ic);
}
FieldReader::~FieldReader()
{
_free();
}
FieldReader& FieldReader::operator = (const FieldReader& ic)
{
if (this==&ic) return *this;
_free();
_copy(ic);
return *this;
}
void FieldReader::_free()
{
// free all data
_init();
}
void FieldReader::_init()
{
_fin = NULL;
_eof = true;
_noNestedBrackets = 0;
int i;
for(i=0;i<256;++i) _delimatorEatLookUp[i]=false;
_delimatorEatLookUp[' '] = true;
_delimatorEatLookUp['\t'] = true;
_delimatorEatLookUp['\n'] = true;
_delimatorEatLookUp['\r'] = true;
for(i=0;i<256;++i) _delimatorKeepLookUp[i]=false;
_delimatorKeepLookUp['{'] = true;
_delimatorKeepLookUp['}'] = true;
_delimatorKeepLookUp['"'] = true;
_delimatorKeepLookUp['\''] = true;
}
void FieldReader::_copy(const FieldReader& ic)
{
_fin = ic._fin;
_eof = ic._eof;
_noNestedBrackets = ic._noNestedBrackets;
int i;
for(i=0;i<256;++i) _delimatorEatLookUp[i]=ic._delimatorEatLookUp[i];
for(i=0;i<256;++i) _delimatorKeepLookUp[i]=ic._delimatorKeepLookUp[i];
}
void FieldReader::attach(istream* input)
{
_fin = input;
if (_fin)
{
_eof = _fin->eof()!=0;
}
else
{
_eof = true;
}
}
void FieldReader::detach()
{
_fin = NULL;
_eof = true;
}
bool FieldReader::eof() const
{
return _eof;
}
bool FieldReader::findStartOfNextField()
{
int ch = 0;
while (true)
{
ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
return false;
}
else if (_delimatorEatLookUp[ch])
{
_fin->ignore(1);
}
else
{
return true;
}
}
}
bool FieldReader::readField(Field& fieldPtr)
{
return _readField(&fieldPtr);
}
void FieldReader::ignoreField()
{
_readField(NULL);
}
bool FieldReader::_readField(Field* fieldPtr)
{
if (fieldPtr) fieldPtr->reset();
if (!eof() && findStartOfNextField())
{
int ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
if (fieldPtr) fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
else if (ch=='"')
{
if (fieldPtr)
{
fieldPtr->setWithinQuotes(true);
fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
}
_fin->ignore(1);
char c;
while (true)
{
ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
c = ch;
if (ch=='"')
{
_fin->ignore(1);
//return fieldPtr && fieldPtr->getNoCharacters()!=0;
return fieldPtr!=NULL;
}
else
{
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
}
}
else if (ch=='\'')
{
if (fieldPtr)
{
fieldPtr->setWithinQuotes(true);
fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
}
_fin->ignore(1);
char c;
while (true)
{
ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
c = ch;
if (ch=='\'')
{
_fin->ignore(1);
//return fieldPtr && fieldPtr->getNoCharacters()!=0;
return fieldPtr!=NULL;
}
else
{
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
}
}
else if (_delimatorKeepLookUp[ch])
{
char c;
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
if (c=='{') ++_noNestedBrackets;
else if (c=='}') --_noNestedBrackets;
if (fieldPtr) fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
else
{
if (fieldPtr) fieldPtr->setNoNestedBrackets(getNoNestedBrackets());
char c;
while (true)
{
ch = _fin->peek();
if (ch==EOF)
{
_eof = true;
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
c = ch;
if (_delimatorEatLookUp[c])
{
_fin->ignore(1);
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
if (_delimatorKeepLookUp[c])
{
return fieldPtr && fieldPtr->getNoCharacters()!=0;
}
else
{
_fin->get(c);
if (fieldPtr) fieldPtr->addChar(c);
}
}
}
}
else
{
return false;
}
}
int FieldReader::getNoNestedBrackets() const
{
return _noNestedBrackets;
}

View File

@@ -0,0 +1,361 @@
#include "osg/FieldReaderIterator"
using namespace osg;
FieldReaderIterator::FieldReaderIterator()
{
_init();
}
FieldReaderIterator::FieldReaderIterator(const FieldReaderIterator& ic)
{
_copy(ic);
}
FieldReaderIterator::~FieldReaderIterator()
{
_free();
}
FieldReaderIterator& FieldReaderIterator::operator = (const FieldReaderIterator& ic)
{
if (this==&ic) return *this;
_free();
_copy(ic);
return *this;
}
void FieldReaderIterator::_free()
{
// free all data
if (_previousField)
{
delete _previousField;
}
if (_fieldQueue)
{
for(int i=0;i<_fieldQueueCapacity;++i)
{
if (_fieldQueue[i]) delete _fieldQueue[i];
_fieldQueue[i] = NULL;
}
delete [] _fieldQueue;
}
_init();
}
void FieldReaderIterator::_init()
{
_previousField = NULL;
_fieldQueue = NULL;
_fieldQueueSize = 0;
_fieldQueueCapacity = 0;
}
void FieldReaderIterator::_copy(const FieldReaderIterator& ic)
{
_reader = ic._reader;
if (ic._previousField)
{
_previousField = new Field(*ic._previousField);
}
if (ic._fieldQueue && ic._fieldQueueCapacity>0)
{
_fieldQueue = new Field* [ic._fieldQueueCapacity];
for(int i=0;i<ic._fieldQueueCapacity;++i)
{
if (ic._fieldQueue[i])
{
_fieldQueue[i] = new Field(*ic._fieldQueue[i]);
}
else
{
_fieldQueue[i] = NULL;
}
}
_fieldQueueSize = ic._fieldQueueSize;
_fieldQueueCapacity = ic._fieldQueueCapacity;
}
else
{
_fieldQueue = NULL;
_fieldQueueSize = 0;
_fieldQueueCapacity = 0;
}
}
void FieldReaderIterator::attach(istream* input)
{
_reader.attach(input);
}
void FieldReaderIterator::detach()
{
_reader.detach();
}
bool FieldReaderIterator::eof() const
{
return _fieldQueueSize==0 && _reader.eof();
}
void FieldReaderIterator::insert(int pos,Field* field)
{
if (field==NULL) return;
if (pos<0) pos=0;
if (pos>_fieldQueueSize) pos=_fieldQueueSize;
int i;
if (_fieldQueueSize>=_fieldQueueCapacity) // need to reallocate the stack
{
int newCapacity = _fieldQueueCapacity*2;
if (newCapacity<MINIMUM_FIELD_READER_QUEUE_SIZE) newCapacity = MINIMUM_FIELD_READER_QUEUE_SIZE;
while(_fieldQueueSize>=newCapacity) newCapacity*=2;
Field** newFieldStack = new Field* [newCapacity];
for(i=0;i<_fieldQueueCapacity;++i)
{
newFieldStack[i] = _fieldQueue[i];
}
for(;i<newCapacity;++i)
{
newFieldStack[i] = NULL;
}
_fieldQueue = newFieldStack;
_fieldQueueCapacity = newCapacity;
}
for(i=_fieldQueueSize-1;i>=pos;++i)
{
_fieldQueue[i+1]=_fieldQueue[i];
}
_fieldQueue[pos] = field;
++_fieldQueueSize;
}
void FieldReaderIterator::insert(int pos,const char* str)
{
if (str)
{
Field* field = new Field;
while(*str!=0)
{
field->addChar(*str);
++str;
}
insert(pos,field);
}
}
Field& FieldReaderIterator::operator [] (int pos)
{
return field(pos);
}
Field& FieldReaderIterator::field (int pos)
{
if (pos<0)
{
_blank.setNoNestedBrackets(_reader.getNoNestedBrackets());
return _blank;
} // can directly access field
else if (pos<_fieldQueueSize)
{
return *_fieldQueue[pos];
} // need to read the new fields.
else
{
if (pos>=_fieldQueueCapacity) // need to reallocate the stack
{
int newCapacity = _fieldQueueCapacity*2;
if (newCapacity<MINIMUM_FIELD_READER_QUEUE_SIZE) newCapacity = MINIMUM_FIELD_READER_QUEUE_SIZE;
while(_fieldQueueSize>=newCapacity) newCapacity*=2;
Field** newFieldStack = new Field* [newCapacity];
int i;
for(i=0;i<_fieldQueueCapacity;++i)
{
newFieldStack[i] = _fieldQueue[i];
}
for(;i<newCapacity;++i)
{
newFieldStack[i] = NULL;
}
_fieldQueue = newFieldStack;
_fieldQueueCapacity = newCapacity;
}
while(!_reader.eof() && pos>=_fieldQueueSize)
{
if (_fieldQueue[_fieldQueueSize]==NULL) _fieldQueue[_fieldQueueSize] = new Field;
if (_reader.readField(*_fieldQueue[_fieldQueueSize]))
{
++_fieldQueueSize;
}
}
if (pos<_fieldQueueSize)
{
return *_fieldQueue[pos];
}
else
{
_blank.setNoNestedBrackets(_reader.getNoNestedBrackets());
return _blank;
}
}
}
FieldReaderIterator& FieldReaderIterator::operator ++ ()
{
return (*this)+=1;
}
FieldReaderIterator& FieldReaderIterator::operator += (int no)
{
if (no>_fieldQueueSize)
{
while (!_reader.eof() && no>_fieldQueueSize)
{
_reader.ignoreField();
--no;
}
_fieldQueueSize=0;
}
else if (no>0)
{
Field** tmpFields = new Field* [no];
int i;
for(i=0;i<no;++i)
{
tmpFields[i] = _fieldQueue[i];
}
for(i=no;i<_fieldQueueSize;++i)
{
_fieldQueue[i-no] = _fieldQueue[i];
}
_fieldQueueSize -= no;
for(i=0;i<no;++i)
{
_fieldQueue[_fieldQueueSize+i] = tmpFields[i];
}
delete [] tmpFields;
}
return *this;
}
// increments the itetor of the next simple field or
// whole block if the current field[0] is an open bracket
void FieldReaderIterator::advanceOverCurrentFieldOrBlock()
{
if (field(0).isOpenBracket()) advanceToEndOfCurrentBlock();
else ++(*this);
}
void FieldReaderIterator::advanceToEndOfCurrentBlock()
{
int entry = field(0).getNoNestedBrackets();
while(!eof() && field(0).getNoNestedBrackets()>=entry)
{
++(*this);
}
}
void FieldReaderIterator::advanceToEndOfBlock(int noNestedBrackets)
{
while(!eof() && field(0).getNoNestedBrackets()>=noNestedBrackets)
{
++(*this);
}
}
bool FieldReaderIterator::matchSequence(const char* str)
{
if (str==NULL) return false;
if (*str==0) return false;
int fieldCount = 0;
const char* end = str;
while((*end)!=0 && (*end)==' ') ++end;
const char* start = end;
while((*start)!=0)
{
if (*end!=' ' && *end!=0)
{
++end;
}
else
{
if (start!=end)
{
if (end-start>1 && *start=='%')
{
const char type = *(start+1);
switch(type)
{
case('i') : // expecting an integer
{
if (!field(fieldCount).isInt()) return false;
break;
}
case('f') : // expecting an floating point number
{
if (!field(fieldCount).isFloat()) return false;
break;
}
case('s') : // expecting an quoted string
{
if (!field(fieldCount).isQuotedString()) return false;
break;
}
default : // expecting an word
{
if (!field(fieldCount).isWord()) return false;
break;
}
}
}
else
{
if (*start=='{')
{
if (!field(fieldCount).isOpenBracket()) return false;
}
else if (*start=='}')
{
if (!field(fieldCount).isCloseBracket()) return false;
}
else
{
if (!field(fieldCount).matchWord(start,end-start)) return false;
}
}
fieldCount++;
}
while((*end)==' ') ++end;
start = end;
}
}
return true;
}

50
src/osg/FileNameUtils.cpp Normal file
View File

@@ -0,0 +1,50 @@
#include "osg/FileNameUtils"
std::string osg::getFilePath(const std::string& fileName)
{
std::string::size_type slash = fileName.find_last_of('/');
if (slash==std::string::npos) return std::string("");
return std::string(fileName.begin(),fileName.begin()+slash+1);
}
std::string osg::getSimpleFileName(const std::string& fileName)
{
std::string::size_type slash = fileName.find_last_of('/');
if (slash==std::string::npos) return fileName;
return std::string(fileName.begin()+slash+1,fileName.end());
}
std::string osg::getFileExtension(const std::string& fileName)
{
std::string::size_type dot = fileName.find_last_of('.');
if (dot==std::string::npos) return std::string("");
return std::string(fileName.begin()+dot+1,fileName.end());
}
std::string osg::getLowerCaseFileExtension(const std::string& filename)
{
std::string ext = osg::getFileExtension(filename);
for(std::string::iterator itr=ext.begin();
itr!=ext.end();
++itr)
{
*itr = (char)tolower(*itr);
}
return ext;
}
std::string osg::getStrippedName(const std::string& fileName)
{
std::string::size_type slash = fileName.find_last_of('/');
std::string::size_type dot = fileName.find_last_of('.');
if (slash==std::string::npos) {
if (dot==std::string::npos) return fileName;
else return std::string(fileName.begin(),fileName.begin()+dot);
}
else
{
if (dot==std::string::npos) return std::string(fileName.begin()+slash+1,fileName.end());
else return std::string(fileName.begin()+slash+1,fileName.begin()+dot);
}
}

47
src/osg/Fog.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include "osg/GL"
#include "osg/Fog"
using namespace osg;
Fog::Fog( void )
{
_mode = EXP;
_density = 1.0f;
_start = 0.0f;
_end = 1.0f;
_color.set( 0.0f, 0.0f, 0.0f, 0.0f);
}
Fog::~Fog( void )
{
}
Fog* Fog::instance()
{
static ref_ptr<Fog> s_fog(new Fog);
return s_fog.get();
}
void Fog::enable( void )
{
glEnable( GL_FOG );
}
void Fog::disable( void )
{
glDisable( GL_FOG );
}
void Fog::apply( void )
{
glFogi( GL_FOG_MODE, _mode );
glFogf( GL_FOG_DENSITY, _density );
glFogf( GL_FOG_START, _start );
glFogf( GL_FOG_END, _end );
glFogfv( GL_FOG_COLOR, (GLfloat*)_color.ptr() );
}

1778
src/osg/GeoSet.cpp Normal file

File diff suppressed because it is too large Load Diff

427
src/osg/GeoSet_ogl.cpp Normal file
View File

@@ -0,0 +1,427 @@
#include <stdio.h>
#include "osg/GL"
#include "osg/GeoSet"
#include "osg/Notify"
using namespace osg;
#define DO_SHADING 1
#define I_ON (1<<4)
#define C_ON (1<<3)
#define N_ON (1<<2)
#define T_ON (1<<1)
#define V_ON (1<<0)
void GeoSet::set_fast_path( void )
{
if( _iaformat != IA_OFF )
{
_fast_path = I_ON;
}
else
{
if( ( _normal_binding != BIND_PERPRIM) &&
( _nindex == 0L ) &&
( _color_binding != BIND_PERPRIM) &&
( _colindex == 0L ) &&
( _primtype != FLAT_LINE_STRIP ) &&
( _primtype != FLAT_TRIANGLE_STRIP ) &&
( _primtype != FLAT_TRIANGLE_FAN )
)
_fast_path = V_ON;
else
{
_fast_path = 0;
#ifdef DEBUG
if( _normal_binding == BIND_PERPRIM )
notify( DEBUG ) << "Geoset - Failed fast path because NORMALS are bound PER_PRIM\n";
if( _nindex != 0L )
notify( DEBUG ) << "Geoset - Failed fast path because NORMAL indeces are specified\n";
if( _color_binding == BIND_PERPRIM )
notify( DEBUG ) << "Geoset - Failed fast path because COLORS are bound PER_PRIM\n";
if( _cindex != 0L )
notify( DEBUG ) << "Geoset - Failed fast path because COLOR indeces are specified\n";
if( _primtype == FLAT_LINE_STRIP )
notify( DEBUG ) << "Geoset - Failed fast path because primitive is FLAT_LINE_STRIP\n";
if ( _primtype == FLAT_TRIANGLE_STRIP )
notify( DEBUG ) << "Geoset - Failed fast path because primitive is FLAT_TRIANGLE_STRIP\n";
if ( _primtype == FLAT_TRIANGLE_FAN )
notify( DEBUG ) << "Geoset - Failed fast path because primitive is FLAT_TRIANGLE_FAN\n";
#endif
}
if( _fast_path )
{
if( _color_binding == BIND_PERVERTEX )
_fast_path |= C_ON;
if( _normal_binding == BIND_PERVERTEX )
_fast_path |= N_ON;
if( _texture_binding == BIND_PERVERTEX )
_fast_path |= T_ON;
}
}
#ifdef DEBUG
notify(INFO) << "GeoSet - fast path = " << _fast_path << "\n";
#endif
}
void GeoSet::draw_fast_path( void )
{
ushort *ocindex = _cindex;
switch( _fast_path )
{
case (I_ON) :
_cindex = _iaindex;
glInterleavedArrays( (GLenum)_ogliaformat, 0, _iarray );
break;
case (V_ON) :
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords );
break;
case (T_ON|V_ON) :
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FLOAT, 0, (GLfloat *)_tcoords );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords );
break;
case (N_ON|V_ON) :
glDisableClientState( GL_COLOR_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords );
break;
case (N_ON|T_ON|V_ON) :
glDisableClientState( GL_COLOR_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FLOAT, 0, (GLfloat *)_tcoords );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords );
break;
case (C_ON|V_ON) :
glEnableClientState( GL_COLOR_ARRAY );
glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors );
glDisableClientState( GL_NORMAL_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords );
break;
case (C_ON|T_ON|V_ON) :
glEnableClientState( GL_COLOR_ARRAY );
glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors );
glDisableClientState( GL_NORMAL_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FLOAT, 0, (GLfloat *)_tcoords );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords );
break;
case (C_ON|N_ON|V_ON) :
glEnableClientState( GL_COLOR_ARRAY );
glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors );
glEnableClientState( GL_NORMAL_ARRAY );
glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords );
break;
case (C_ON|N_ON|T_ON|V_ON) :
glEnableClientState( GL_COLOR_ARRAY );
glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors );
glEnableClientState( GL_NORMAL_ARRAY );
glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FLOAT, 0, (GLfloat *)_tcoords );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords );
break;
}
if( _color_binding == BIND_OVERALL )
{
if( _colindex != 0L )
glColor4fv( (GLfloat * )&_colors[_colindex[0]] );
else
glColor4fv( (GLfloat * )&_colors[0] );
}
if( _normal_binding == BIND_OVERALL )
{
if( _nindex != 0L )
glNormal3fv( (GLfloat * )&_normals[_nindex[0]] );
else
glNormal3fv( (GLfloat * )&_normals[0] );
}
if( _needprimlen ) // LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP,
// TRIANGLE_FAN, QUAD_STRIP, POLYGONS
{
int index = 0;
if( _primLengths == (int *)0 )
{
notify(WARN) << "GeoSet->draw() : " "Primitive lengths required\n";
return;
}
for( int i = 0; i < _numprims; i++ )
{
if( _cindex != (ushort *)0L )
glDrawElements( (GLenum)_oglprimtype, _primLengths[i], GL_UNSIGNED_SHORT, &_cindex[index] );
else
glDrawArrays( (GLenum)_oglprimtype, index, _primLengths[i] );
index += _primLengths[i];
}
}
else // POINTS, LINES, TRIANGLES, QUADS
{
if( _cindex != (ushort *)0L )
glDrawElements( (GLenum)_oglprimtype, _numindices, GL_UNSIGNED_SHORT, _cindex );
else
glDrawArrays( (GLenum)_oglprimtype, 0, _numcoords );
}
_cindex = ocindex;
}
void GeoSet::draw_alternate_path( void )
{
if( (_color_binding == BIND_PERVERTEX) && (_cindex == 0L) && (_flat_shaded_skip == 0) )
{
glEnableClientState( GL_COLOR_ARRAY );
glColorPointer( 4, GL_FLOAT, 0, (GLfloat *)_colors );
}
else
{
glDisableClientState( GL_COLOR_ARRAY );
if( _color_binding == BIND_OVERALL )
{
if( _colindex )
glColor4fv( (GLfloat *)&_colors[_colindex[0]] );
else
glColor4fv( (GLfloat *)&_colors[0] );
}
}
if( (_normal_binding == BIND_PERVERTEX) && (_nindex == 0L) && (_flat_shaded_skip == 0) )
{
glEnableClientState( GL_NORMAL_ARRAY );
glNormalPointer( GL_FLOAT, 0, (GLfloat *)_normals );
}
else
{
glDisableClientState( GL_NORMAL_ARRAY );
if( _normal_binding == BIND_OVERALL )
{
if( _nindex )
glNormal3fv( (GLfloat *)&_normals[_nindex[0]] );
else
glNormal3fv( (GLfloat *)&_normals[0] );
}
}
if( (_texture_binding == BIND_PERVERTEX) && (_tindex == 0L) )
{
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FLOAT, 0, _tcoords );
}
else
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, (GLfloat *)_coords );
if( _needprimlen ) // LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP,
// TRIANGLE_FAN, QUAD_STRIP, POLYGONS
// FLAT_LINE_STRIP, FLAT_TRIANGLE_STRIP, FLAT_TRIANGLE_FAN
{
int i, j;
int index = 0;
int ai = 0;
int ci = 0;
int ni = 0;
int ti = 0;
if( _primLengths == (int *)0 )
{
notify(WARN) << "GeoSet->draw() : " "Primitive lengths required\n";
return;
}
for( i = 0; i < _numprims; i++ )
{
if( _color_binding == BIND_PERPRIM )
{
if( _colindex )
glColor4fv( (GLfloat *)&_colors[_colindex[ci++]] );
else
glColor4fv( (GLfloat *)&_colors[ci++] );
}
if( _normal_binding == BIND_PERPRIM )
{
if( _nindex )
glNormal3fv( (GLfloat *)&_normals[_nindex[ni++]] );
else
glNormal3fv( (GLfloat *)&_normals[ni++] );
}
if( _flat_shaded_skip )
{
#ifdef DO_SHADING
glShadeModel( GL_FLAT );
#endif
glBegin( (GLenum)_oglprimtype );
for( j = 0; j < _primLengths[i]; j++ )
{
if( j >= _flat_shaded_skip )
{
if( _color_binding == BIND_PERVERTEX )
{
if( (_colindex != 0L) )
glColor4fv( (GLfloat *)&_colors[_colindex[ci++]] );
else
glColor4fv( (GLfloat *)&_colors[ci++] );
}
if( _normal_binding == BIND_PERVERTEX )
{
if(_nindex != 0L)
glNormal3fv( (GLfloat *)&_normals[_nindex[ni++]] );
else
glNormal3fv( (GLfloat *)&_normals[ni++] );
}
}
if( _texture_binding == BIND_PERVERTEX )
{
if( _tindex != 0L )
glTexCoord2fv( (GLfloat *)&_tcoords[_tindex[ti++]] );
else
glTexCoord2fv( (GLfloat *)&_tcoords[ti++] );
}
if( _cindex )
glArrayElement( _cindex[ai++] );
else
glArrayElement( ai++ );
}
glEnd();
#ifdef DO_SHADING
glShadeModel( GL_SMOOTH );
#endif
}
else
if( ((_color_binding == BIND_PERVERTEX ) && (_colindex != 0L) ) ||
((_normal_binding == BIND_PERVERTEX ) && (_nindex != 0L) ) ||
((_texture_binding == BIND_PERVERTEX ) && (_tindex != 0L) ) )
{
glBegin( (GLenum)_oglprimtype );
for( j = 0; j < _primLengths[i]; j++ )
{
if( (_color_binding == BIND_PERVERTEX) && (_colindex != 0L) )
glColor4fv( (GLfloat *)&_colors[_colindex[ci++]] );
if( (_normal_binding == BIND_PERVERTEX) && (_nindex != 0L) )
glNormal3fv( (GLfloat *)&_normals[_nindex[ci++]] );
if( (_texture_binding == BIND_PERVERTEX) && (_tindex != 0L) )
glTexCoord2fv( (GLfloat *)&_tcoords[_tindex[ti++]] );
if( _cindex )
glArrayElement( _cindex[ai++] );
else
glArrayElement( ai++ );
}
glEnd();
}
else
{
if( _cindex != (ushort *)0L )
glDrawElements( (GLenum)_oglprimtype, _primLengths[i], GL_UNSIGNED_SHORT, &_cindex[index] );
else
glDrawArrays( (GLenum)_oglprimtype, index, _primLengths[i] );
}
index += _primLengths[i];
}
}
else // POINTS, LINES, TRIANGLES, QUADS
{
int i, j;
if( _normal_binding == BIND_PERPRIM || _color_binding == BIND_PERPRIM ||
((_color_binding == BIND_PERVERTEX ) && (_colindex != 0L) ) ||
((_normal_binding == BIND_PERVERTEX ) && (_nindex != 0L) ) ||
((_texture_binding == BIND_PERVERTEX ) && (_tindex != 0L) ) )
{
glBegin( (GLenum)_oglprimtype );
for( i = 0; i < _numprims; i++ )
{
if( _color_binding == BIND_PERPRIM )
{
if( _colindex )
glColor4fv( (GLfloat *)&_colors[_colindex[i]] );
else
glColor4fv( (GLfloat *)&_colors[i] );
}
if( _normal_binding == BIND_PERPRIM )
{
if( _nindex )
glNormal3fv( (GLfloat *)&_normals[_nindex[i]] );
else
glNormal3fv( (GLfloat *)&_normals[i] );
}
for( j = 0; j < _primlength; j++ )
{
if( (_color_binding == BIND_PERVERTEX) && (_colindex != 0L ) )
glColor4fv( (GLfloat *)&_colors[_colindex[i*_primlength+j]] );
if( (_normal_binding == BIND_PERVERTEX) && (_nindex != 0L ) )
glNormal3fv( (GLfloat *)&_normals[_nindex[i*_primlength+j]] );
if( (_texture_binding == BIND_PERVERTEX) && (_tindex != 0L ) )
glTexCoord2fv( (GLfloat *)&_tcoords[_tindex[i*_primlength+j]] );
glArrayElement( i*_primlength+j );
}
}
glEnd();
}
else
{
if( _cindex != (ushort *)0L )
glDrawElements( (GLenum)_oglprimtype, _numindices, GL_UNSIGNED_SHORT, _cindex );
else
glDrawArrays( (GLenum)_oglprimtype, 0, _numcoords );
}
}
}

850
src/osg/GeoState.cpp Normal file
View File

@@ -0,0 +1,850 @@
#include <stdio.h>
#include "osg/GeoState"
#include "osg/Input"
#include "osg/Output"
#include "osg/Notify"
using namespace osg;
GeoState::GeoState()
{
_transparencing = INHERIT;
_face_culling = INHERIT;
_lighting = INHERIT;
_texturing = INHERIT;
_fogging = INHERIT;
_texgening = INHERIT;
_antialiasing = INHERIT;
_colortable = INHERIT;
_pointSmoothing = INHERIT;
_polygonOffsetting = INHERIT;
_alphaTesting = INHERIT;
_transparency = 0L;
_cullFace = 0L;
_texture = 0L;
_fog = 0L;
_texgen = 0L;
_material = 0L;
_texenv = 0L;
_texmat = 0L;
_point = 0L;
_polygonOffset = 0L;
_alphaFunc = 0L;
}
GeoState::~GeoState()
{
// note, all attached state attributes will be automatically
// unreferenced by ref_ptr<> and therefore there is now need to
// delete the memory manually.
}
GeoState* GeoState::instance()
{
static ref_ptr<GeoState> s_geostate(new GeoState);
return s_geostate.get();
}
void GeoState::setGlobalDefaults()
{
_transparencing = OFF;
_face_culling = ON;
_lighting = OFF;
_texturing = OFF;
_fogging = OFF;
_texgening = OFF;
_antialiasing = OFF;
_colortable = OFF;
_pointSmoothing = OFF;
_polygonOffsetting = OFF;
_alphaTesting = OFF;
_transparency = new Transparency;
_cullFace = new CullFace;
_texture = 0L;
_fog = 0L;
_texgen = 0L;
_material = new Material;
_material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
_texenv = 0L;
_texmat = 0L;
_point = 0L;
_polygonOffset = 0L;
_alphaFunc = new AlphaFunc;
}
void GeoState::setAllToInherit()
{
_transparencing = INHERIT;
_face_culling = INHERIT;
_lighting = INHERIT;
_texturing = INHERIT;
_fogging = INHERIT;
_texgening = INHERIT;
_antialiasing = INHERIT;
_colortable = INHERIT;
_pointSmoothing = INHERIT;
_polygonOffsetting = INHERIT;
_alphaTesting = INHERIT;
_transparency = 0L;
_cullFace = 0L;
_texture = 0L;
_fog = 0L;
_texgen = 0L;
_material = 0L;
_texenv = 0L;
_texmat = 0L;
_point = 0L;
_polygonOffset = 0L;
_alphaFunc = 0L;
}
bool GeoState::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
AttributeMode mode;
if (fr[0].matchWord("transparency") && matchModeStr(fr[1].getStr(),mode))
{
_transparencing = mode;
fr+=2;
iteratorAdvanced = true;
}
if (Transparency* transTmp = static_cast<Transparency*>(Transparency::instance()->readClone(fr)))
{
_transparency = transTmp;
iteratorAdvanced = true;
}
if (fr[0].matchWord("antialiasing") && matchModeStr(fr[1].getStr(),mode))
{
_antialiasing = mode;
fr+=2;
iteratorAdvanced = true;
}
if (fr[0].matchWord("face_culling") && matchModeStr(fr[1].getStr(),mode))
{
_face_culling = mode;
fr+=2;
iteratorAdvanced = true;
}
if (CullFace* cullTmp = static_cast<CullFace*>(CullFace::instance()->readClone(fr)))
{
_cullFace = cullTmp;
iteratorAdvanced = true;
}
if (fr[0].matchWord("lighting") && matchModeStr(fr[1].getStr(),mode))
{
_lighting = mode;
fr+=2;
iteratorAdvanced = true;
}
if (fr[0].matchWord("texturing") && matchModeStr(fr[1].getStr(),mode))
{
_texturing = mode;
fr+=2;
iteratorAdvanced = true;
}
if (Texture* textTmp = static_cast<Texture*>(Texture::instance()->readClone(fr)))
{
_texture = textTmp;
iteratorAdvanced = true;
}
if (fr[0].matchWord("fogging") && matchModeStr(fr[1].getStr(),mode))
{
_fogging = mode;
fr+=2;
iteratorAdvanced = true;
}
if (Fog* fogTmp = static_cast<Fog*>(Fog::instance()->readClone(fr)))
{
_fog = fogTmp;
iteratorAdvanced = true;
}
if (fr[0].matchWord("colortable") && matchModeStr(fr[1].getStr(),mode))
{
_colortable = mode;
fr+=2;
iteratorAdvanced = true;
}
if (fr[0].matchWord("texgening") && matchModeStr(fr[1].getStr(),mode))
{
_texgening = mode;
fr+=2;
iteratorAdvanced = true;
}
if (TexGen* tmpTexgen = static_cast<TexGen*>(TexGen::instance()->readClone(fr)))
{
_texgen = tmpTexgen;
iteratorAdvanced = true;
}
if (fr[0].matchWord("point_smoothing") && matchModeStr(fr[1].getStr(),mode))
{
_pointSmoothing = mode;
fr+=2;
iteratorAdvanced = true;
}
if (Point* tmpPoint = static_cast<Point*>(Point::instance()->readClone(fr)))
{
_point = tmpPoint;
iteratorAdvanced = true;
}
if (fr[0].matchWord("polygon_offset") && matchModeStr(fr[1].getStr(),mode))
{
_polygonOffsetting = mode;
fr+=2;
iteratorAdvanced = true;
}
if (PolygonOffset* tmpPolygonOffset = static_cast<PolygonOffset*>(PolygonOffset::instance()->readClone(fr)))
{
_polygonOffset = tmpPolygonOffset;
iteratorAdvanced = true;
}
if (fr[0].matchWord("alpha_test") && matchModeStr(fr[1].getStr(),mode))
{
_alphaTesting = mode;
fr+=2;
iteratorAdvanced = true;
}
if (AlphaFunc* tmpAlphaFunc = static_cast<AlphaFunc*>(AlphaFunc::instance()->readClone(fr)))
{
_alphaFunc = tmpAlphaFunc;
iteratorAdvanced = true;
}
if (Material* tmpMaterial = static_cast<Material*>(Material::instance()->readClone(fr)))
{
_material = tmpMaterial;
iteratorAdvanced = true;
}
/*
* Decided that texmatting does not make sense. If a Texture matrix
* is present, just apply it. No need for a mode. Don.
*
if (fr[0].matchWord("texmating") && matchModeStr(fr[1].getStr(),mode)) {
_texmating = mode;
fr+=2;
iteratorAdvanced = true;
}
*/
return iteratorAdvanced;
}
bool GeoState::writeLocalData(Output& fw)
{
fw.indent() << "transparency " << getModeStr(_transparencing) << endl;
if (_transparency.valid()) _transparency->write(fw);
fw.indent() << "antialiasing " << getModeStr(_antialiasing) << endl;
fw.indent() << "face_culling " << getModeStr(_face_culling) << endl;
if (_cullFace.valid()) _cullFace->write(fw);
fw.indent() << "lighting " << getModeStr(_lighting) << endl;
fw.indent() << "texturing " << getModeStr(_texturing) << endl;
if (_texture.valid()) _texture->write(fw);
fw.indent() << "fogging " << getModeStr(_fogging) << endl;
if (_fog.valid()) _fog->write(fw);
fw.indent() << "colortable " << getModeStr(_colortable) << endl;
fw.indent() << "texgening " << getModeStr(_texgening) << endl;
if (_texgen.valid()) _texgen->write(fw);
if (_texenv.valid()) _texenv->write(fw);
fw.indent() << "point_smoothing " << getModeStr(_pointSmoothing) << endl;
if (_point.valid()) _point->write(fw);
fw.indent() << "polygon_offset " << getModeStr(_polygonOffsetting) << endl;
if (_polygonOffset.valid()) _polygonOffset->write(fw);
fw.indent() << "alpha_test " << getModeStr(_alphaTesting) << endl;
if (_alphaFunc.valid()) _alphaFunc->write(fw);
if (_material.valid()) _material->write(fw);
/*
fw.indent() << "texmating " << getModeStr(_texmating) << endl;
*/
return true;
}
bool GeoState::matchModeStr(const char* str,AttributeMode& mode)
{
if (strcmp(str,"INHERIT")==0) mode = INHERIT;
else if (strcmp(str,"ON")==0) mode = ON;
else if (strcmp(str,"OFF")==0) mode = OFF;
else if (strcmp(str,"OVERRIDE_ON")==0) mode = OVERRIDE_ON;
else if (strcmp(str,"OVERRIDE_OFF")==0) mode = OVERRIDE_OFF;
else return false;
return true;
}
const char* GeoState::getModeStr(AttributeMode mode)
{
switch(mode)
{
case(INHERIT): return "INHERIT";
case(ON): return "ON";
case(OFF): return "OFF";
case(OVERRIDE_ON): return "OVERRIDE_ON";
case(OVERRIDE_OFF): return "OVERRIDE_OFF";
}
return "";
}
void GeoState::setMode( AttributeType type, AttributeMode mode )
{
switch( type )
{
case ANTIALIAS : _antialiasing = mode; break;
case FACE_CULL: _face_culling = mode; break;
case FOG : _fogging = mode; break;
case LIGHTING: _lighting = mode; break;
case POINT : _pointSmoothing = mode; break;
case POLYGON_OFFSET : _polygonOffsetting = mode; break;
case TEXGEN : _texgening = mode; break;
case TEXTURE : _texturing = mode; break;
case TRANSPARENCY: _transparencing = mode; break;
case ALPHAFUNC: _alphaTesting = mode; break;
default : notify(WARN) << "GeoState::setMode("<<(int)type<<","<<(int)mode<<") not handled."<<endl;
}
}
GeoState::AttributeMode GeoState::getMode( AttributeType type) const
{
switch( type )
{
case ANTIALIAS : return _antialiasing;
case FACE_CULL: return _face_culling;
case FOG : return _fogging;
case LIGHTING: return _lighting;
case POINT : return _pointSmoothing;
case POLYGON_OFFSET : return _polygonOffsetting;
case TEXTURE : return _texturing;
case TEXGEN : return _texgening;
case TRANSPARENCY: return _transparencing;
case ALPHAFUNC: return _alphaTesting;
default : notify(WARN) << "GeoState::getMode("<<(int)type<<") not handled."<<endl;
}
return INHERIT;
}
void GeoState::setAttribute( AttributeType type, Object *attribute )
{
switch( type )
{
case FACE_CULL : _cullFace = dynamic_cast<CullFace*>(attribute); break;
case FOG : _fog = dynamic_cast<Fog*>(attribute); break;
case LIGHTING: break; /*_light = (Light *)attribute;*/
case MATERIAL: _material = dynamic_cast<Material*>(attribute); break;
case POINT : _point = dynamic_cast<Point*>(attribute); break;
case POLYGON_OFFSET: _polygonOffset = dynamic_cast<PolygonOffset*>(attribute); break;
case TEXENV : _texenv = dynamic_cast<TexEnv*>(attribute); break;
case TEXGEN : _texgen = dynamic_cast<TexGen*>(attribute); break;
case TEXMAT : _texmat = dynamic_cast<TexMat*>(attribute); break;
case TEXTURE : _texture = dynamic_cast<Texture*>(attribute); break;
case TRANSPARENCY: _transparency = dynamic_cast<Transparency*>(attribute); break;
case ALPHAFUNC: _alphaFunc = dynamic_cast<AlphaFunc*>(attribute); break;
default : notify(WARN) << "GeoState::setAttribute("<<(int)type<<","<<attribute<<") not handled."<<endl;
}
}
Object* GeoState::getAttribute( AttributeType type) const
{
switch( type )
{
case FOG : return _fog.get();
case LIGHTING: return NULL; /*_light*/
case MATERIAL: return _material.get();
case POINT : return _point.get();
case POLYGON_OFFSET: return _polygonOffset.get();
case TEXENV : return _texenv.get();
case TEXGEN : return _texgen.get();
case TEXMAT : return _texmat.get();
case TEXTURE : return _texture.get();
case TRANSPARENCY: return _transparency.get();
case ALPHAFUNC: return _alphaFunc.get();
default : notify(WARN) << "GeoState::getAttribute("<<(int)type<<") not handled."<<endl;
}
return NULL;
}
void GeoState::apply()
{
switch(_transparencing)
{
case(ON):
case(OVERRIDE_ON):
Transparency::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
Transparency::disable();
break;
case(INHERIT):
break;
}
switch(_face_culling)
{
case(ON):
case(OVERRIDE_ON):
CullFace::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
CullFace::disable();
break;
case(INHERIT):
break;
}
switch(_lighting)
{
case(ON):
case(OVERRIDE_ON):
Lighting::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
Lighting::disable();
break;
case(INHERIT):
break;
}
switch(_texturing)
{
case(ON):
case(OVERRIDE_ON):
Texture::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
Texture::disable();
break;
case(INHERIT):
break;
}
switch(_texgening)
{
case(ON):
case(OVERRIDE_ON):
TexGen::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
TexGen::disable();
break;
case(INHERIT):
break;
}
switch(_fogging)
{
case(ON):
case(OVERRIDE_ON):
Fog::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
Fog::disable();
break;
case(INHERIT):
break;
}
switch(_pointSmoothing)
{
case(ON):
case(OVERRIDE_ON):
Point::enableSmooth();
break;
case(OFF):
case(OVERRIDE_OFF):
Point::disableSmooth();
break;
case(INHERIT):
break;
}
switch(_polygonOffsetting)
{
case(ON):
case(OVERRIDE_ON):
PolygonOffset::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
PolygonOffset::disable();
break;
case(INHERIT):
break;
}
switch(_alphaTesting)
{
case(ON):
case(OVERRIDE_ON):
AlphaFunc::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
AlphaFunc::disable();
break;
case(INHERIT):
break;
}
if( _transparency.valid())
_transparency->apply();
if( _cullFace.valid())
_cullFace->apply();
if( _texenv.valid())
_texenv->apply();
if( _texgen.valid())
_texgen->apply();
if( _texture.valid())
_texture->apply();
if( _material.valid())
_material->apply();
if( _fog.valid())
_fog->apply();
if( _texmat.valid())
_texmat->apply();
if( _point.valid())
_point->apply();
if( _polygonOffset.valid())
_polygonOffset->apply();
if( _alphaFunc.valid())
_alphaFunc->apply();
}
void GeoState::apply(GeoState* global,GeoState* prev)
{
if (global==NULL || prev==NULL)
{
apply();
return;
}
switch(GeoState::combineMode(global->_transparencing,prev->_transparencing,_transparencing))
{
case(ON):
case(OVERRIDE_ON):
Transparency::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
Transparency::disable();
break;
case(INHERIT):
break;
}
switch(GeoState::combineMode(global->_face_culling,prev->_face_culling,_face_culling))
{
case(ON):
case(OVERRIDE_ON):
CullFace::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
CullFace::disable();
break;
case(INHERIT):
break;
}
switch(GeoState::combineMode(global->_lighting,prev->_lighting,_lighting))
{
case(ON):
case(OVERRIDE_ON):
Lighting::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
Lighting::disable();
break;
case(INHERIT):
break;
}
switch(GeoState::combineMode(global->_texturing,prev->_texturing,_texturing))
{
case(ON):
case(OVERRIDE_ON):
Texture::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
Texture::disable();
break;
case(INHERIT):
break;
}
switch(GeoState::combineMode(global->_texgening,prev->_texgening,_texgening))
{
case(ON):
case(OVERRIDE_ON):
TexGen::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
TexGen::disable();
break;
case(INHERIT):
break;
}
switch(GeoState::combineMode(global->_fogging,prev->_fogging,_fogging))
{
case(ON):
case(OVERRIDE_ON):
Fog::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
Fog::disable();
break;
case(INHERIT):
break;
}
switch(GeoState::combineMode(global->_pointSmoothing,prev->_pointSmoothing,_pointSmoothing))
{
case(ON):
case(OVERRIDE_ON):
Point::enableSmooth();
break;
case(OFF):
case(OVERRIDE_OFF):
Point::disableSmooth();
break;
case(INHERIT):
break;
}
switch(GeoState::combineMode(global->_polygonOffsetting,prev->_polygonOffsetting,_polygonOffsetting))
{
case(ON):
case(OVERRIDE_ON):
PolygonOffset::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
PolygonOffset::disable();
break;
case(INHERIT):
break;
}
switch(GeoState::combineMode(global->_alphaTesting,prev->_alphaTesting,_alphaTesting))
{
case(ON):
case(OVERRIDE_ON):
AlphaFunc::enable();
break;
case(OFF):
case(OVERRIDE_OFF):
AlphaFunc::disable();
break;
case(INHERIT):
break;
}
if (prev->_transparency!=_transparency)
{
osg::Transparency* new_transparency;
if (_transparency.valid()) new_transparency = _transparency.get();
else new_transparency = global->_transparency.get();
if (new_transparency) new_transparency->apply();
}
if (prev->_cullFace!=_cullFace)
{
osg::CullFace* new_cullFace;
if (_cullFace.valid()) new_cullFace = _cullFace.get();
else new_cullFace = global->_cullFace.get();
if (new_cullFace) new_cullFace->apply();
}
if (prev->_texenv!=_texenv)
{
osg::TexEnv* new_texenv;
if (_texenv.valid()) new_texenv = _texenv.get();
else new_texenv = global->_texenv.get();
if (new_texenv) new_texenv->apply();
}
if (prev->_texgen!=_texgen)
{
osg::TexGen* new_texgen;
if (_texgen.valid()) new_texgen = _texgen.get();
else new_texgen = global->_texgen.get();
if (new_texgen) new_texgen->apply();
}
if (prev->_texture!=_texture)
{
osg::Texture* new_texture;
if (_texture.valid()) new_texture = _texture.get();
else new_texture = global->_texture.get();
if (new_texture) new_texture->apply();
}
if (prev->_material!=_material)
{
osg::Material* new_material;
if (_material.valid()) new_material = _material.get();
else new_material = global->_material.get();
if (new_material) new_material->apply();
}
if (prev->_fog!=_fog)
{
osg::Fog* new_fog;
if (_fog.valid()) new_fog = _fog.get();
else new_fog = global->_fog.get();
if (new_fog) new_fog->apply();
}
if (prev->_texmat!=_texmat)
{
osg::TexMat* new_texmat;
if (_texmat.valid()) new_texmat = _texmat.get();
else new_texmat = global->_texmat.get();
if (new_texmat) new_texmat->apply();
}
if (prev->_point!=_point)
{
osg::Point* new_point;
if (_point.valid()) new_point = _point.get();
else new_point = global->_point.get();
if (new_point) new_point->apply();
}
if (prev->_polygonOffset!=_polygonOffset)
{
osg::PolygonOffset* new_polygonOffset;
if (_polygonOffset.valid()) new_polygonOffset = _polygonOffset.get();
else new_polygonOffset = global->_polygonOffset.get();
if (new_polygonOffset) new_polygonOffset->apply();
}
if (prev->_alphaFunc!=_alphaFunc)
{
osg::AlphaFunc* new_AlphaFunc;
if (_alphaFunc.valid()) new_AlphaFunc = _alphaFunc.get();
else new_AlphaFunc = global->_alphaFunc.get();
if (new_AlphaFunc) new_AlphaFunc->apply();
}
}
bool GeoState::check()
{
return true;
}
/*
#if 0 // [ NOTES on how apply should work
Each Scene must have a global initial GeoState, current GeoState, and current request state. The current definition of GeoState
should really become an GeoState. The global initial State can have modes set to
SG_ON,
SG_OFF,
and may be or'ed with
SG_OVERRIDE.
All attributes are set to the default. Defaults can be set at start up by querying hardware
and determining best parameters (for example, do we have hardware texture mapping?, if so enable texture and create a texture environment).
The current GeoState and the request GeoState begin as a copy of the initial state. The request state is subsequently changed by each GeoState,
during traversal. It is the current state that will actually issue the GL commands at apply time.
Attributes for the GeoStates may be
SG_ON -explicitely
SG_OFF -explicitely
SG_INHERIT
and may be or'ed with
SG_PERSIST
During traversal, each GeoState's attribute set to INHERIT does nothing. Each attribute set to ON or OFF sets the subsequent request state
to the same before drawing and unsets it after. If the attribute is or'ed with SG_PERSIST, then the mode is not unset after drawing.
Just before drawing the request state is compared to the current state. If an attribute or mode has changed, it is changed in the current
state then applied. Only at this application will the actual GL calls be issued.
For exammple, if two subsequent geosets have lighting on the sequence will be as follows
geostate 1 sets lighting on in request state
at draw:
if current state has lighting off it is changed to on and applied.
geostate1 unsets lighting in request state.
geosate2 resets lighting to on in request state
at draw:
current state has lighting set to on from previous draw therefore nothing changes
geostate2
Addendum 10/22 - Use this method for traversal. Currently we shall do dumb apply().
Upon implementation of a CULL traversal, which creates a DRAW display list, then we
shall implement the "smart" state change described above.
#endif // ]
*/

161
src/osg/Geode.cpp Normal file
View File

@@ -0,0 +1,161 @@
#include <stdio.h>
#include <math.h>
#include "osg/Geode"
#include "osg/Input"
#include "osg/Output"
#include <algorithm>
#ifdef __sgi
using std::find;
using std::for_each;
#endif
#define square(x) ((x)*(x))
#include "osg/Registry"
using namespace osg;
RegisterObjectProxy<Geode> g_GeodeProxy;
Geode::Geode()
{
_bsphere_computed = false;
}
Geode::~Geode()
{
// ref_ptr<> automactially decrements the reference count of all geosets.
}
bool Geode::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (Node::readLocalData(fr)) iteratorAdvanced = true;
int num_geosets;
if (fr[0].matchWord("num_geosets") &&
fr[1].getInt(num_geosets))
{
// could allocate space for children here...
fr+=2;
iteratorAdvanced = true;
}
GeoSet* gset_read = NULL;
do
{
if ((gset_read=static_cast<GeoSet*>(GeoSet::instance()->readClone(fr))))
{
addGeoSet(gset_read);
iteratorAdvanced = true;
}
} while(gset_read != NULL);
return iteratorAdvanced;
}
bool Geode::writeLocalData(Output& fw)
{
Node::writeLocalData(fw);
fw.indent() << "num_geosets " << getNumGeosets() << endl;
for(GeoSetList::iterator itr = _geosets.begin();
itr!=_geosets.end();
++itr)
{
(*itr)->write(fw);
}
return true;
}
bool Geode::addGeoSet( GeoSet *gset )
{
if (gset && !containsGeoSet(gset))
{
// note ref_ptr<> automatically handles incrementing gset's reference count.
_geosets.push_back(gset);
dirtyBound();
return true;
}
else return false;
}
bool Geode::removeGeoSet( GeoSet *gset )
{
GeoSetList::iterator itr = findGeoSet(gset);
if (itr!=_geosets.end())
{
// note ref_ptr<> automatically handles decrementing gset's reference count.
_geosets.erase(itr);
dirtyBound();
return true;
}
else return false;
}
bool Geode::replaceGeoSet( GeoSet *origGset, GeoSet *newGset )
{
if (newGset==NULL || origGset==newGset) return false;
GeoSetList::iterator itr = findGeoSet(origGset);
if (itr!=_geosets.end())
{
// note ref_ptr<> automatically handles decrementing origGset's reference count,
// and inccrementing newGset's reference count.
*itr = newGset;
dirtyBound();
return true;
}
else return false;
}
bool Geode::computeBound( void )
{
BoundingBox bb;
GeoSetList::iterator itr;
for(itr=_geosets.begin();
itr!=_geosets.end();
++itr)
{
bb.expandBy((*itr)->getBound());
}
_bsphere._center = bb.center();
_bsphere._radius = 0.0f;
for(itr=_geosets.begin();
itr!=_geosets.end();
++itr)
{
const BoundingBox& bbox = (*itr)->getBound();
for(unsigned int c=0;c<8;++c)
{
_bsphere.expandRadiusBy(bbox.corner(c));
}
}
_bsphere_computed=true;
return true;
}
void Geode::compileGeoSets( void )
{
for(GeoSetList::iterator itr = _geosets.begin();
itr!=_geosets.end();
++itr)
{
(*itr)->compile();
}
}

180
src/osg/Group.cpp Normal file
View File

@@ -0,0 +1,180 @@
#include <stdio.h>
#include <math.h>
#include "osg/Group"
#include "osg/Input"
#include "osg/Output"
#include "osg/Registry"
#include "osg/BoundingBox"
#include <algorithm>
// #ifdef __sgi
// using std::find;
// using std::for_each;
// using std::string;
// #endif
#define square(x) ((x)*(x))
using namespace osg;
RegisterObjectProxy<Group> g_GroupProxy;
Group::Group()
{
}
Group::~Group()
{
for(ChildList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
Node* child = itr->get();
ParentList::iterator pitr = std::find(child->_parents.begin(),child->_parents.end(),this);
if (pitr!=child->_parents.end()) child->_parents.erase(pitr);
}
}
void Group::traverse(NodeVisitor& nv)
{
for(ChildList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
(*itr)->accept(nv);
}
}
bool Group::addChild( Node *child )
{
if (child && !containsNode(child))
{
// note ref_ptr<> automatically handles incrementing child's reference count.
_children.push_back(child);
// register as parent of child.
child->_parents.push_back(this);
dirtyBound();
return true;
}
else return false;
}
bool Group::removeChild( Node *child )
{
ChildList::iterator itr = findNode(child);
if (itr!=_children.end())
{
// note ref_ptr<> automatically handles decrementing child's reference count.
_children.erase(itr);
dirtyBound();
ParentList::iterator pitr = std::find(child->_parents.begin(),child->_parents.end(),child);
if (pitr!=child->_parents.end()) child->_parents.erase(pitr);
return true;
}
else return false;
}
bool Group::replaceChild( Node *origNode, Node *newNode )
{
if (newNode==NULL || origNode==newNode) return false;
ChildList::iterator itr = findNode(origNode);
if (itr!=_children.end())
{
ParentList::iterator pitr = std::find(origNode->_parents.begin(),origNode->_parents.end(),origNode);
if (pitr!=origNode->_parents.end()) origNode->_parents.erase(pitr);
// note ref_ptr<> automatically handles decrementing origNode's reference count,
// and inccrementing newNode's reference count.
*itr = newNode;
// register as parent of child.
newNode->_parents.push_back(this);
dirtyBound();
return true;
}
else return false;
}
bool Group::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (Node::readLocalData(fr)) iteratorAdvanced = true;
int num_children;
if (fr[0].matchWord("num_children") &&
fr[1].getInt(num_children))
{
// could allocate space for children here...
fr+=2;
iteratorAdvanced = true;
}
Node* node = NULL;
while((node=fr.readNode())!=NULL)
{
addChild(node);
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool Group::writeLocalData(Output& fw)
{
Node::writeLocalData(fw);
fw.indent() << "num_children " << getNumChildren() << endl;
for(int i=0;i<getNumChildren();++i)
{
getChild(i)->write(fw);
}
return true;
}
bool Group::computeBound()
{
_bsphere_computed = true;
_bsphere.init();
if (_children.empty()) return false;
BoundingBox bb;
bb.init();
ChildList::iterator itr;
for(itr=_children.begin();
itr!=_children.end();
++itr)
{
bb.expandBy((*itr)->getBound());
}
if (!bb.isValid()) return false;
_bsphere._center = bb.center();
_bsphere._radius = 0.0f;
for(itr=_children.begin();
itr!=_children.end();
++itr)
{
_bsphere.expandRadiusBy((*itr)->getBound());
}
return true;
}

224
src/osg/Image.cpp Normal file
View File

@@ -0,0 +1,224 @@
#include "osg/Image"
#include "osg/Input"
#include "osg/Output"
#include "osg/GL"
#include "osg/Notify"
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/GeoState>
#include <osg/Texture>
using namespace osg;
Image::Image()
{
_fileName = NULL;
_s = _t = _r = 0;
_internalFormat = 0;
_pixelFormat = (unsigned int)0;
_dataType = (unsigned int)0;
_packing = 4;
_data = (unsigned char *)0L;
}
Image::~Image()
{
if (_fileName) ::free(_fileName);
if (_data) ::free(_data);
}
void Image::setFileName(const char* fileName)
{
if (_fileName) ::free(_fileName);
if (fileName) _fileName = strdup(fileName);
else _fileName = NULL;
}
void Image::setImage(int s,int t,int r,
int internalFormat,
unsigned int pixelFormat,
unsigned int dataType,
unsigned char *data,
int packing)
{
if (_data) ::free(_data);
_s = s;
_t = t;
_r = r;
_internalFormat = internalFormat;
_pixelFormat = pixelFormat;
_dataType = dataType;
_data = data;
if (packing<0)
{
if (_s%4==0)
_packing = 4;
else
_packing = 1;
}
else
_packing = packing;
// scaleImageTo(16,16,_r);
}
bool Image::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (fr[0].matchWord("file") && fr[1].isString())
{
//loadFile(fr[1].getStr());
fr += 2;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool Image::writeLocalData(Output& fw)
{
if (_fileName)
{
fw.indent() << "file \""<<_fileName<<"\""<<endl;
}
return true;
}
void Image::scaleImage(int s,int t,int /*r*/)
{
if (_data==NULL) return;
unsigned char* newData = (unsigned char *)malloc(2 * (s+1)*(t+1)*4);
glPixelStorei(GL_PACK_ALIGNMENT,_packing);
glPixelStorei(GL_UNPACK_ALIGNMENT,_packing);
GLint status = gluScaleImage((GLenum)_pixelFormat,
_s,
_t,
(GLenum)_dataType,
_data,
s,
t,
(GLenum)_dataType,
newData);
if (status==0) {
// free old image.
::free(_data);
_s = s;
_t = t;
_data = newData;
}
else
{
::free(newData);
notify(WARN) << "Error Image::scaleImage() do not succeed : errorString = "<<gluErrorString((GLenum)status)<<endl;
}
}
void Image::ensureDimensionsArePowerOfTwo()
{
float sp2 = logf((float)_s)/logf(2.0f);
float rounded_sp2 = floorf(sp2+0.5f);
int new_s = (int)(powf(2.0f,rounded_sp2));
float tp2 = logf((float)_t)/logf(2.0f);
float rounded_tp2 = floorf(tp2+0.5f);
int new_t = (int)(powf(2.0f,rounded_tp2));
if (new_s!=_s && new_t!=_t)
{
notify(NOTICE) << "Scaling image '"<<_fileName<<"' from ("<<_s<<","<<_t<<") to ("<<new_s<<","<<new_t<<")"<<endl;
scaleImage(new_s,new_t,_r);
}
}
Geode* osg::createGeodeForImage(osg::Image* image)
{
return createGeodeForImage(image,image->s(),image->t());
}
Geode* osg::createGeodeForImage(osg::Image* image,float s,float t)
{
if (image)
{
if (s>0 && t>0)
{
float y = 1.0;
float x = y*(s/t);
// set up the texture.
osg::Texture* texture = new osg::Texture;
texture->setImage(image);
// set up the geostate.
osg::GeoState* gstate = new osg::GeoState;
gstate->setMode(osg::GeoState::FACE_CULL,osg::GeoState::OFF);
gstate->setMode(osg::GeoState::LIGHTING,osg::GeoState::OFF);
gstate->setMode(osg::GeoState::TEXTURE,osg::GeoState::ON);
gstate->setAttribute(osg::GeoState::TEXTURE,texture);
// set up the geoset.
osg::GeoSet* gset = new osg::GeoSet;
gset->setGeoState(gstate);
osg::Vec3* coords = new Vec3 [4];
coords[0].set(-x,0.0f,y);
coords[1].set(-x,0.0f,-y);
coords[2].set(x,0.0f,-y);
coords[3].set(x,0.0f,y);
gset->setCoords(coords);
osg::Vec2* tcoords = new Vec2 [4];
tcoords[0].set(0.0f,1.0f);
tcoords[1].set(0.0f,0.0f);
tcoords[2].set(1.0f,0.0f);
tcoords[3].set(1.0f,1.0f);
gset->setTextureCoords(tcoords);
gset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
osg::Vec4* colours = new Vec4;
colours->set(1.0f,1.0f,1.0,0.0f);
gset->setColors(colours);
gset->setColorBinding(osg::GeoSet::BIND_OVERALL);
gset->setNumPrims(1);
gset->setPrimType(osg::GeoSet::QUADS);
// set up the geode.
osg::Geode* geode = new osg::Geode;
geode->addGeoSet(gset);
return geode;
}
else
{
return NULL;
}
}
else
{
return NULL;
}
}

69
src/osg/Input.cpp Normal file
View File

@@ -0,0 +1,69 @@
#include "osg/Input"
#include "osg/Registry"
#include "osg/Object"
#ifdef __sgi
using std::string;
#endif
using namespace osg;
// Will extend to handle #DEF and use
// functionality similar to Inventor,
// and add the ability to handle #include
// from within the OSG file format.
Input::Input()
{
}
Input::~Input()
{
}
Object* Input::getObjectForUniqueID(const std::string& uniqueID)
{
UniqueIDToObjectMapping::iterator fitr = _uniqueIDToObjectMap.find(uniqueID);
if (fitr != _uniqueIDToObjectMap.end()) return (*fitr).second;
else return NULL;
}
void Input::regisiterUniqueIDForObject(const std::string& uniqueID,Object* obj)
{
_uniqueIDToObjectMap[uniqueID] = obj;
}
Object* Input::readObject()
{
return Registry::instance()->readObject(*this);
}
Object* Input::readObject(const string& fileName)
{
return Registry::instance()->readObject(fileName);
}
Image* Input::readImage()
{
return Registry::instance()->readImage(*this);
}
Image* Input::readImage(const string& fileName)
{
return Registry::instance()->readImage(fileName);
}
Node* Input::readNode()
{
return Registry::instance()->readNode(*this);
}
Node* Input::readNode(const string& fileName)
{
return Registry::instance()->readNode(fileName);
}

130
src/osg/LOD.cpp Normal file
View File

@@ -0,0 +1,130 @@
#include "osg/LOD"
#include "osg/Input"
#include "osg/Output"
#include "osg/Registry"
#include <algorithm>
using namespace osg;
RegisterObjectProxy<LOD> g_LODProxy;
void LOD::traverse(NodeVisitor& nv)
{
switch(nv.getTraverseMode())
{
case(NodeVisitor::TRAVERSE_ALL_CHILDREN):
std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
break;
case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
if (_children.size()!=0) _children.front()->accept(nv);
break;
default:
break;
}
}
void LOD::setRange(unsigned int index, float range)
{
if (index<_rangeList.size()) _rangeList[index] = range;
else while (index>=_rangeList.size()) _rangeList.push_back(range);
if (index<_rangeList2.size()) _rangeList2[index] = range*range;
else while (index>=_rangeList2.size()) _rangeList2.push_back(range*range);
}
int LOD::evaluate(const Vec3& eye_local, float bias)
{
// For cache coherency, use _rangeList2 exclusively
if (_rangeList2.size()==0) return -1;
// Test distance-squared against the stored array of squared ranges
float LODRange = (eye_local-_center).length2()*bias;
if (LODRange<_rangeList2[0]) return -1;
for(unsigned int i=0;i<_rangeList2.size()-1;++i)
{
if (_rangeList2[i]<=LODRange && LODRange<_rangeList2[i+1]) {
return i;
}
}
return -1;
}
bool LOD::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (fr.matchSequence("Center %f %f %f"))
{
fr[1].getFloat(_center[0]);
fr[2].getFloat(_center[1]);
fr[3].getFloat(_center[2]);
iteratorAdvanced = true;
fr+=3;
}
bool matchFirst = false;
if ((matchFirst=fr.matchSequence("Ranges {")) || fr.matchSequence("Ranges %i {"))
{
// set up coordinates.
int entry = fr[0].getNoNestedBrackets();
if (matchFirst)
{
fr += 2;
}
else
{
//_rangeList.(capacity);
fr += 3;
}
float range;
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
{
if (fr[0].getFloat(range))
{
++fr;
_rangeList.push_back(range);
_rangeList2.push_back(range*range);
}
else
{
++fr;
}
}
iteratorAdvanced = true;
++fr;
}
if (Group::readLocalData(fr)) iteratorAdvanced = true;
return iteratorAdvanced;
}
bool LOD::writeLocalData(Output& fw)
{
fw.indent() << "Center "<<_center[0] << " "<<_center[1] << " "<<_center[2] <<endl;
fw.indent() << "Ranges {"<<endl;
fw.moveIn();
for(RangeList::iterator riter = _rangeList.begin();
riter != _rangeList.end();
++riter)
{
fw.indent() << (*riter) <<endl;
}
fw.moveOut();
fw.indent() << "}"<<endl;
Group::writeLocalData(fw);
return true;
}

97
src/osg/Light.cpp Normal file
View File

@@ -0,0 +1,97 @@
#include "osg/Light"
#include "osg/Notify"
using namespace osg;
int Light::_currentLightNum = -1;
Light::Light( void )
{
_lightnum = ++_currentLightNum;
_on = 1;
init();
// notify(DEBUG) << "_ambient "<<_ambient<<endl;
// notify(DEBUG) << "_diffuse "<<_diffuse<<endl;
// notify(DEBUG) << "_specular "<<_specular<<endl;
// notify(DEBUG) << "_position "<<_position<<endl;
// notify(DEBUG) << "_direction "<<_direction<<endl;
// notify(DEBUG) << "_spot_exponent "<<_spot_exponent<<endl;
// notify(DEBUG) << "_spot_cutoff "<<_spot_cutoff<<endl;
// notify(DEBUG) << "_constant_attenuation "<<_constant_attenuation<<endl;
// notify(DEBUG) << "_linear_attenuation "<<_linear_attenuation<<endl;
// notify(DEBUG) << "_quadratic_attenuation "<<_quadratic_attenuation<<endl;
}
Light::~Light( void )
{
}
Light* Light::instance()
{
static ref_ptr<Light> s_Light(new Light);
return s_Light.get();
}
void Light::init( void )
{
_ambient.set(0.05f,0.05f,0.05f,1.0f);
_diffuse.set(0.8f,0.8f,0.8f,1.0f);
_specular.set(0.05f,0.05f,0.05f,1.0f);
_position.set(0.0f,0.0f,1.0f,0.0f);
_direction.set(0.0f,0.0f,-1.0f);
_spot_exponent = 0.0f;
_spot_cutoff = 180.0f;
_constant_attenuation = 1.0f;
_linear_attenuation = 0.0f;
_quadratic_attenuation = 0.0f;
}
void Light::captureLightState()
{
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_AMBIENT, _ambient.ptr() );
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_DIFFUSE, _diffuse.ptr() );
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_SPECULAR, _specular.ptr() );
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_POSITION, _position.ptr() );
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_SPOT_DIRECTION, _direction.ptr() );
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_SPOT_EXPONENT, &_spot_exponent );
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_SPOT_CUTOFF, &_spot_cutoff );
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_CONSTANT_ATTENUATION, &_constant_attenuation );
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_LINEAR_ATTENUATION, &_linear_attenuation );
glGetLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_QUADRATIC_ATTENUATION, &_quadratic_attenuation );
}
void Light::enable( void )
{
glEnable( GL_LIGHTING );
}
void Light::disable( void )
{
glDisable( GL_LIGHTING );
}
void Light::apply( void )
{
if( _on )
{
glEnable ( (GLenum)((int)GL_LIGHT0 + _lightnum) );
glLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_AMBIENT, _ambient.ptr() );
glLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_DIFFUSE, _diffuse.ptr() );
glLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_SPECULAR, _specular.ptr() );
glLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_POSITION, _position.ptr() );
glLightfv( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_SPOT_DIRECTION, _direction.ptr() );
glLightf ( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_SPOT_EXPONENT, _spot_exponent );
glLightf ( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_SPOT_CUTOFF, _spot_cutoff );
glLightf ( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_CONSTANT_ATTENUATION, _constant_attenuation );
glLightf ( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_LINEAR_ATTENUATION, _linear_attenuation );
glLightf ( (GLenum)((int)GL_LIGHT0 + _lightnum), GL_QUADRATIC_ATTENUATION, _quadratic_attenuation );
}
else
glDisable( (GLenum)((int)GL_LIGHT0 + _lightnum) );
}

59
src/osg/LightSource.cpp Normal file
View File

@@ -0,0 +1,59 @@
#include "osg/LightSource"
#include "osg/Input"
#include "osg/Output"
#include "osg/Registry"
using namespace osg;
RegisterObjectProxy<LightSource> g_LightSourceProxy;
LightSource::LightSource()
{
_bsphere_computed = false;
}
LightSource::~LightSource()
{
// ref_ptr<> automactially decrements the reference count of attached lights.
}
bool LightSource::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (Node::readLocalData(fr)) iteratorAdvanced = true;
Light* light = static_cast<Light*>(Light::instance()->readClone(fr));
if (light)
{
_light = light;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool LightSource::writeLocalData(Output& fw)
{
Node::writeLocalData(fw);
if (_light.valid()) _light->write(fw);
return true;
}
bool LightSource::computeBound( void )
{
// note, don't do anything right now as the light itself is not
// visualised, just having an effect on the lighting of geodes.
_bsphere.init();
_bsphere_computed = true;
return true;
}

15
src/osg/Lighting.cpp Normal file
View File

@@ -0,0 +1,15 @@
#include "osg/GL"
#include "osg/Lighting"
using namespace osg;
void Lighting::enable( void )
{
glEnable( GL_LIGHTING );
}
void Lighting::disable( void )
{
glDisable( GL_LIGHTING );
}

0
src/osg/Makedepend Normal file
View File

148
src/osg/Makefile Normal file
View File

@@ -0,0 +1,148 @@
#!smake
include ../../Make/makedefs
C++FILES = \
Registry.cpp\
OSG.cpp\
AlphaFunc.cpp\
Group.cpp\
Field.cpp\
FieldReader.cpp\
FieldReaderIterator.cpp\
GeoSet.cpp\
GeoSet_ogl.cpp\
GeoState.cpp\
Geode.cpp\
Input.cpp\
FileNameUtils.cpp\
Light.cpp\
LightSource.cpp\
Lighting.cpp\
Material.cpp\
Matrix.cpp\
Quat.cpp\
Seg.cpp\
Node.cpp\
NodeVisitor.cpp\
Object.cpp\
Output.cpp\
DynamicLibrary.cpp\
TexEnv.cpp\
TexGen.cpp\
Image.cpp\
Texture.cpp\
DCS.cpp\
Scene.cpp\
Switch.cpp\
Sequence.cpp\
LOD.cpp\
Billboard.cpp\
BoundingSphere.cpp\
BoundingBox.cpp\
Transparency.cpp\
CullFace.cpp\
TexMat.cpp\
Timer.cpp\
Fog.cpp\
ReaderWriterOSG.cpp\
ReaderWriterRGB.cpp\
Camera.cpp\
Notify.cpp\
ExtensionSupported.cpp\
Point.cpp\
PolygonOffset.cpp\
Version.cpp\
TARGET_BASENAME = osg
TARGET_LIB_FILES = lib$(TARGET_BASENAME).so
TARGET_INCLUDE_FILES = \
osg/AlphaFunc\
osg/Billboard\
osg/BoundingBox\
osg/BoundingSphere\
osg/Camera\
osg/CullFace\
osg/DCS\
osg/DynamicLibrary\
osg/Export\
osg/Field\
osg/FieldReader\
osg/FieldReaderIterator\
osg/FileNameUtils\
osg/Fog\
osg/GeoSet\
osg/GeoState\
osg/Geode\
osg/Group\
osg/GL\
osg/Image\
osg/Input\
osg/LOD\
osg/Light\
osg/LightSource\
osg/Lighting\
osg/Material\
osg/Matrix\
osg/Node\
osg/Notify\
osg/NodeVisitor\
osg/OSG\
osg/Object\
osg/Output\
osg/Point\
osg/PolygonOffset\
osg/Quat\
osg/Referenced\
osg/Registry\
osg/Scene\
osg/Seg\
osg/Sequence\
osg/State\
osg/Switch\
osg/TexEnv\
osg/TexGen\
osg/TexMat\
osg/Texture\
osg/Transparency\
osg/Timer\
osg/Types\
osg/Vec2\
osg/Vec3\
osg/Vec4\
osg/Version\
TARGET_DATA_FILES = \
cessna.osg\
cow.osg\
dumptruck.osg\
e-s-bike.osg\
flight_park.fly\
glider.osg\
ncc1701d.osg\
paraglider.osg\
torus.osg\
turtle.osg\
Test/CullFace.osg\
Test/Point.osg\
Test/PolygonOffset.osg\
Images/lz.rgb\
Images/reflect.rgb\
Images/tank.rgb\
Images/tree0.rgba\
Images/water.rgb\
Images/white.rgb\
LIBS = -ldl
LIB = ../../lib/lib$(TARGET_BASENAME).so
#LIB = ../../lib/lib$(TARGET_BASENAME).a
C++FLAGS += -I ../../include
include ../../Make/makerules

560
src/osg/Material.cpp Normal file
View File

@@ -0,0 +1,560 @@
#include "osg/Material"
#include "osg/Input"
#include "osg/Output"
#include "osg/Notify"
using namespace osg;
Material::Material( void )
{
_colorMode = OFF;
_ambientFrontAndBack = true;
_ambientFront.set(0.2f, 0.2f, 0.2f, 1.0f);
_ambientBack.set(0.2f, 0.2f, 0.2f, 1.0f);
_diffuseFrontAndBack = true;
_diffuseFront.set(0.8f, 0.8f, 0.8f, 1.0f);
_diffuseBack.set(0.8f, 0.8f, 0.8f, 1.0f);
_specularFrontAndBack = true;
_specularFront.set(0.0f, 0.0f, 0.0f, 1.0f);
_specularBack.set(0.0f, 0.0f, 0.0f, 1.0f);
_emissionFrontAndBack = true;
_emissionFront.set(0.0f, 0.0f, 0.0f, 1.0f);
_emissionBack.set(0.0f, 0.0f, 0.0f, 1.0f);
_shininessFrontAndBack = true;
_shininessFront = 0.0f;
_shininessBack = 0.0f;
}
Material::~Material( void )
{
}
Material* Material::instance()
{
static ref_ptr<Material> s_Material(new Material);
return s_Material.get();
}
void Material::setAmbient( MaterialFace face, const Vec4& ambient )
{
switch(face) {
case(FACE_FRONT):
_ambientFrontAndBack = false;
_ambientFront = ambient;
break;
case(FACE_BACK):
_ambientFrontAndBack = false;
_ambientBack = ambient;
break;
case(FACE_FRONT_AND_BACK):
_ambientFrontAndBack = true;
_ambientFront = ambient;
_ambientBack = ambient;
break;
default:
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::setAmbient()."<<endl;
}
}
const Vec4& Material::getAmbient(MaterialFace face) const
{
switch(face) {
case(FACE_FRONT):
return _ambientFront;
case(FACE_BACK):
return _ambientBack;
case(FACE_FRONT_AND_BACK):
if (!_ambientFrontAndBack)
{
notify(NOTICE)<<"Notice: Material::getAmbient(FRONT_AND_BACK) called on material "<<endl;
notify(NOTICE)<<" with seperate FRONT and BACK ambient colors."<<endl;
}
return _ambientFront;
}
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::getAmbient()."<<endl;
return _ambientFront;
}
void Material::setDiffuse( MaterialFace face, const Vec4& diffuse )
{
switch(face) {
case(FACE_FRONT):
_diffuseFrontAndBack = false;
_diffuseFront = diffuse;
break;
case(FACE_BACK):
_diffuseFrontAndBack = false;
_diffuseBack = diffuse;
break;
case(FACE_FRONT_AND_BACK):
_diffuseFrontAndBack = true;
_diffuseFront = diffuse;
_diffuseBack = diffuse;
break;
default:
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::setDiffuse()."<<endl;
break;
}
}
const Vec4& Material::getDiffuse(MaterialFace face) const
{
switch(face) {
case(FACE_FRONT):
return _diffuseFront;
case(FACE_BACK):
return _diffuseBack;
case(FACE_FRONT_AND_BACK):
if (!_diffuseFrontAndBack)
{
notify(NOTICE)<<"Notice: Material::getDiffuse(FRONT_AND_BACK) called on material "<<endl;
notify(NOTICE)<<" with seperate FRONT and BACK diffuse colors."<<endl;
}
return _diffuseFront;
}
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::getDiffuse()."<<endl;
return _diffuseFront;
}
void Material::setSpecular( MaterialFace face, const Vec4& specular )
{
switch(face) {
case(FACE_FRONT):
_specularFrontAndBack = false;
_specularFront = specular;
break;
case(FACE_BACK):
_specularFrontAndBack = false;
_specularBack = specular;
break;
case(FACE_FRONT_AND_BACK):
_specularFrontAndBack = true;
_specularFront = specular;
_specularBack = specular;
break;
default:
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::setSpecular()."<<endl;
break;
}
}
const Vec4& Material::getSpecular(MaterialFace face) const
{
switch(face) {
case(FACE_FRONT):
return _specularFront;
case(FACE_BACK):
return _specularBack;
case(FACE_FRONT_AND_BACK):
if (!_specularFrontAndBack)
{
notify(NOTICE)<<"Notice: Material::getSpecular(FRONT_AND_BACK) called on material "<<endl;
notify(NOTICE)<<" with seperate FRONT and BACK specular colors."<<endl;
}
return _specularFront;
}
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::getSpecular()."<<endl;
return _specularFront;
}
void Material::setEmission( MaterialFace face, const Vec4& emission )
{
switch(face) {
case(FACE_FRONT):
_emissionFrontAndBack = false;
_emissionFront = emission;
break;
case(FACE_BACK):
_emissionFrontAndBack = false;
_emissionBack = emission;
break;
case(FACE_FRONT_AND_BACK):
_emissionFrontAndBack = true;
_emissionFront = emission;
_emissionBack = emission;
break;
default:
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::setEmission()."<<endl;
break;
}
}
const Vec4& Material::getEmission(MaterialFace face) const
{
switch(face) {
case(FACE_FRONT):
return _emissionFront;
case(FACE_BACK):
return _emissionBack;
case(FACE_FRONT_AND_BACK):
if (!_emissionFrontAndBack)
{
notify(NOTICE)<<"Notice: Material::getEmission(FRONT_AND_BACK) called on material "<<endl;
notify(NOTICE)<<" with seperate FRONT and BACK emission colors."<<endl;
}
return _emissionFront;
}
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::getEmission()."<<endl;
return _emissionFront;
}
void Material::setShininess( MaterialFace face, float shininess )
{
switch(face) {
case(FACE_FRONT):
_shininessFrontAndBack = false;
_shininessFront = shininess;
break;
case(FACE_BACK):
_shininessFrontAndBack = false;
_shininessBack = shininess;
break;
case(FACE_FRONT_AND_BACK):
_shininessFrontAndBack = true;
_shininessFront = shininess;
_shininessBack = shininess;
break;
default:
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::setShininess()."<<endl;
break;
}
}
float Material::getShininess(MaterialFace face) const
{
switch(face) {
case(FACE_FRONT):
return _shininessFront;
case(FACE_BACK):
return _shininessBack;
case(FACE_FRONT_AND_BACK):
if (!_shininessFrontAndBack)
{
notify(NOTICE)<<"Notice: Material::getShininess(FRONT_AND_BACK) called on material "<<endl;
notify(NOTICE)<<" with seperate FRONT and BACK shininess colors."<<endl;
}
return _shininessFront;
}
notify(NOTICE)<<"Notice: invalid MaterialFace passed to Material::getShininess()."<<endl;
return _shininessFront;
}
bool Material::matchFaceAndColor(Input& fr,const char* name,MaterialFace& mf,Vec4& color)
{
bool iteratorAdvanced = false;
if (fr[0].matchWord(name))
{
int fr_inc = 1;
if (fr[1].matchWord("FRONT"))
{
mf = FACE_FRONT;
++fr_inc;
}
else if (fr[1].matchWord("BACK"))
{
mf = FACE_BACK;
++fr_inc;
}
if (fr[fr_inc].getFloat(color[0]) && fr[fr_inc+1].getFloat(color[1]) && fr[fr_inc+2].getFloat(color[2]))
{
fr_inc += 3;
if (fr[fr_inc].getFloat(color[3])) ++fr_inc;
else color[3] = 1.0f;
fr+=fr_inc;
iteratorAdvanced = true;
}
}
return iteratorAdvanced;
}
bool Material::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
Vec4 data(0.0f, 0.0f, 0.0f, 1.0f);
MaterialFace mf = FACE_FRONT_AND_BACK;
if (fr[0].matchWord("ColorMode"))
{
if (fr[1].matchWord("AMBIENT"))
{
setColorMode(AMBIENT);
fr+=2;
iteratorAdvanced = true;
}
else if (fr[1].matchWord("DIFFUSE"))
{
setColorMode(DIFFUSE);
fr+=2;
iteratorAdvanced = true;
}
else if (fr[1].matchWord("SPECULAR"))
{
setColorMode(SPECULAR);
fr+=2;
iteratorAdvanced = true;
}
else if (fr[1].matchWord("EMISSION"))
{
setColorMode(EMISSION);
fr+=2;
iteratorAdvanced = true;
}
else if (fr[1].matchWord("AMBIENT_AND_DIFFUSE"))
{
setColorMode(AMBIENT_AND_DIFFUSE);
fr+=2;
iteratorAdvanced = true;
}
else if (fr[1].matchWord("OFF"))
{
setColorMode(OFF);
fr+=2;
iteratorAdvanced = true;
}
}
if (matchFaceAndColor(fr,"ambientColor",mf,data))
{
setAmbient(mf,data);
iteratorAdvanced = true;
}
if (matchFaceAndColor(fr,"diffuseColor",mf,data))
{
setDiffuse(mf,data);
iteratorAdvanced = true;
}
if (matchFaceAndColor(fr,"specularColor",mf,data))
{
setSpecular(mf,data);
iteratorAdvanced = true;
}
if (matchFaceAndColor(fr,"emissionColor",mf,data))
{
setEmission(mf,data);
iteratorAdvanced = true;
}
if (matchFaceAndColor(fr,"ambientColor",mf,data))
{
setAmbient(mf,data);
iteratorAdvanced = true;
}
float shininess = 0.0f;
if (fr[0].matchWord("shininess"))
{
mf = FACE_FRONT_AND_BACK;
int fr_inc = 1;
if (fr[1].matchWord("FRONT"))
{
mf = FACE_FRONT;
++fr_inc;
}
else if (fr[1].matchWord("BACK"))
{
mf = FACE_BACK;
++fr_inc;
}
if (fr[fr_inc].getFloat(shininess))
{
fr+=(fr_inc+1);
setShininess(mf,shininess);
iteratorAdvanced = true;
}
}
float transparency = 0.0f;
if (fr[0].matchWord("transparency") && fr[1].getFloat(transparency))
{
_ambientFront[3] = 1.0f-transparency;
_diffuseFront[3] = 1.0f-transparency;
_specularFront[3] = 1.0f-transparency;
_emissionFront[3] = 1.0f-transparency;
_ambientBack[3] = 1.0f-transparency;
_diffuseBack[3] = 1.0f-transparency;
_specularBack[3] = 1.0f-transparency;
_emissionBack[3] = 1.0f-transparency;
fr+=2;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool Material::writeLocalData(Output& fw)
{
switch(_colorMode)
{
case(AMBIENT): fw.indent() << "ColorMode AMBIENT" << endl; break;
case(DIFFUSE): fw.indent() << "ColorMode DIFFUSE" << endl; break;
case(SPECULAR): fw.indent() << "ColorMode SPECULAR" << endl; break;
case(EMISSION): fw.indent() << "ColorMode EMISSION" << endl; break;
case(AMBIENT_AND_DIFFUSE): fw.indent() << "ColorMode AMBIENT_AND_DIFFUSE" << endl; break;
case(OFF): fw.indent() << "ColorMode OFF" << endl; break;
}
if (_ambientFrontAndBack)
{
fw.indent() << "ambientColor " << _ambientFront << endl;
}
else
{
fw.indent() << "ambientColor FRONT " << _ambientFront << endl;
fw.indent() << "ambientColor BACK " << _ambientBack << endl;
}
if (_diffuseFrontAndBack)
{
fw.indent() << "diffuseColor " << _diffuseFront << endl;
}
else
{
fw.indent() << "diffuseColor FRONT " << _diffuseFront << endl;
fw.indent() << "diffuseColor BACK " << _diffuseBack << endl;
}
if (_specularFrontAndBack)
{
fw.indent() << "specularColor " << _specularFront << endl;
}
else
{
fw.indent() << "specularColor FRONT " << _specularFront << endl;
fw.indent() << "specularColor BACK " << _specularBack << endl;
}
if (_emissionFrontAndBack)
{
fw.indent() << "emissionColor " << _emissionFront << endl;
}
else
{
fw.indent() << "emissionColor FRONT " << _emissionFront << endl;
fw.indent() << "emissionColor BACK " << _emissionBack << endl;
}
if (_shininessFrontAndBack)
{
fw.indent() << "shininess " << _shininessFront << endl;
}
else
{
fw.indent() << "shininess FRONT " << _shininessFront << endl;
fw.indent() << "shininess BACK " << _shininessBack << endl;
}
return true;
}
void Material::apply( void )
{
if (_colorMode==OFF)
{
glDisable(GL_COLOR_MATERIAL);
}
else
{
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK,(GLenum)_colorMode);
switch(_colorMode) {
case(AMBIENT): glColor4fv(_ambientFront.ptr()); break;
case(DIFFUSE): glColor4fv(_diffuseFront.ptr()); break;
case(SPECULAR): glColor4fv(_specularFront.ptr()); break;
case(EMISSION): glColor4fv(_emissionFront.ptr()); break;
case(AMBIENT_AND_DIFFUSE): glColor4fv(_diffuseFront.ptr()); break;
case(OFF): break;
}
}
if (_colorMode!=AMBIENT && _colorMode!=AMBIENT_AND_DIFFUSE)
{
if (_ambientFrontAndBack)
{
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, _ambientFront.ptr() );
}
else
{
glMaterialfv( GL_FRONT, GL_AMBIENT, _ambientFront.ptr() );
glMaterialfv( GL_BACK, GL_AMBIENT, _ambientBack.ptr() );
}
}
if (_colorMode!=DIFFUSE && _colorMode!=AMBIENT_AND_DIFFUSE)
{
if (_diffuseFrontAndBack)
{
glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, _diffuseFront.ptr() );
}
else
{
glMaterialfv( GL_FRONT, GL_DIFFUSE, _diffuseFront.ptr() );
glMaterialfv( GL_BACK, GL_DIFFUSE, _diffuseBack.ptr() );
}
}
if (_colorMode!=SPECULAR)
{
if (_specularFrontAndBack)
{
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, _specularFront.ptr() );
}
else
{
glMaterialfv( GL_FRONT, GL_SPECULAR, _specularFront.ptr() );
glMaterialfv( GL_BACK, GL_SPECULAR, _specularBack.ptr() );
}
}
if (_colorMode!=EMISSION)
{
if (_emissionFrontAndBack)
{
glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, _emissionFront.ptr() );
}
else
{
glMaterialfv( GL_FRONT, GL_EMISSION, _emissionFront.ptr() );
glMaterialfv( GL_BACK, GL_EMISSION, _emissionBack.ptr() );
}
}
if (_shininessFrontAndBack)
{
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, _shininessFront* 128.0f );
}
else
{
glMaterialf( GL_FRONT, GL_SHININESS, _shininessFront* 128.0f );
glMaterialf( GL_BACK, GL_SHININESS, _shininessBack* 128.0f );
}
}

512
src/osg/Matrix.cpp Normal file
View File

@@ -0,0 +1,512 @@
#include <math.h>
#include "osg/Matrix"
#include "osg/Input"
#include "osg/Output"
#include "osg/Notify"
#define square(x) ((x)*(x))
#define DEG2RAD(x) ((x)*M_PI/180.0)
using namespace osg;
typedef struct quaternion_
{
double x ;
double y ;
double z ;
double w ;
} quaternion ;
/* C = a(row).b(row) */
#define matrix_inner_product( a, b, row, col, C ) \
{ \
(C)[row][col] = (a)[row][0] * (b)[0][col] + \
(a)[row][1] * (b)[1][col] + \
(a)[row][2] * (b)[2][col] + \
(a)[row][3] * (b)[3][col]; \
}
/* C = a.b */
#define matrix_mult( a, b, C ) \
{ \
matrix_inner_product( a, b, 0, 0, C ); \
matrix_inner_product( a, b, 0, 1, C ); \
matrix_inner_product( a, b, 0, 2, C ); \
matrix_inner_product( a, b, 0, 3, C ); \
matrix_inner_product( a, b, 1, 0, C ); \
matrix_inner_product( a, b, 1, 1, C ); \
matrix_inner_product( a, b, 1, 2, C ); \
matrix_inner_product( a, b, 1, 3, C ); \
matrix_inner_product( a, b, 2, 0, C ); \
matrix_inner_product( a, b, 2, 1, C ); \
matrix_inner_product( a, b, 2, 2, C ); \
matrix_inner_product( a, b, 2, 3, C ); \
matrix_inner_product( a, b, 3, 0, C ); \
matrix_inner_product( a, b, 3, 1, C ); \
matrix_inner_product( a, b, 3, 2, C ); \
matrix_inner_product( a, b, 3, 3, C ); \
}
static void quaternion_matrix( quaternion *q, double mat[4][4] )
{
/* copied from Shoemake/ACM SIGGRAPH 89 */
double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz ;
xs = q->x + q->x;
ys = q->y + q->y;
zs = q->z + q->z;
wx = q->w * xs ; wy = q->w * ys ; wz = q->w * zs ;
xx = q->x * xs ; xy = q->x * ys ; xz = q->x * zs ;
yy = q->y * ys ; yz = q->y * zs ; zz = q->z * zs ;
mat[0][0] = 1.0 - ( yy + zz ) ;
mat[0][1] = xy - wz ;
mat[0][2] = xz + wy ;
mat[1][0] = xy + wz ;
mat[1][1] = 1.0 - ( xx + zz ) ;
mat[1][2] = yz - wx ;
mat[2][0] = xz - wy ;
mat[2][1] = yz + wx ;
mat[2][2] = 1.0 - ( xx + yy ) ;
mat[0][3] = 0.0;
mat[1][3] = 0.0;
mat[2][3] = 0.0;
mat[3][0] = 0.0;
mat[3][1] = 0.0;
mat[3][2] = 0.0;
mat[3][3] = 1.0;
}
Matrix::Matrix()
{
makeIdent();
}
Matrix::Matrix(const Matrix& matrix) : Object()
{
memcpy(_mat,matrix._mat,sizeof(_mat));
}
Matrix& Matrix::operator = (const Matrix& matrix)
{
if (&matrix==this) return *this;
memcpy(_mat,matrix._mat,sizeof(_mat));
return *this;
}
Matrix::Matrix(
float a00, float a01, float a02, float a03,
float a10, float a11, float a12, float a13,
float a20, float a21, float a22, float a23,
float a30, float a31, float a32, float a33)
{
_mat[0][0] = a00;
_mat[0][1] = a01;
_mat[0][2] = a02;
_mat[0][3] = a03;
_mat[1][0] = a10;
_mat[1][1] = a11;
_mat[1][2] = a12;
_mat[1][3] = a13;
_mat[2][0] = a20;
_mat[2][1] = a21;
_mat[2][2] = a22;
_mat[2][3] = a23;
_mat[3][0] = a30;
_mat[3][1] = a31;
_mat[3][2] = a32;
_mat[3][3] = a33;
}
Matrix::~Matrix()
{
}
Matrix* Matrix::instance()
{
static ref_ptr<Matrix> s_matrix(new Matrix());
return s_matrix.get();
}
bool Matrix::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
bool matched = true;
for(int k=0;k<16 && matched;++k)
{
matched = fr[k].isFloat();
}
if (matched)
{
int k=0;
for(int i=0;i<4;++i)
{
for(int j=0;j<4;++j)
{
fr[k].getFloat(_mat[i][j]);
k++;
}
}
fr += 16;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool Matrix::writeLocalData(Output& fw)
{
fw.indent() << _mat[0][0] << " " << _mat[0][1] << " " << _mat[0][2] << " " << _mat[0][3] << endl;
fw.indent() << _mat[1][0] << " " << _mat[1][1] << " " << _mat[1][2] << " " << _mat[1][3] << endl;
fw.indent() << _mat[2][0] << " " << _mat[2][1] << " " << _mat[2][2] << " " << _mat[2][3] << endl;
fw.indent() << _mat[3][0] << " " << _mat[3][1] << " " << _mat[3][2] << " " << _mat[3][3] << endl;
return true;
}
void Matrix::makeIdent()
{
_mat[0][0] = 1.0f;
_mat[0][1] = 0.0f;
_mat[0][2] = 0.0f;
_mat[0][3] = 0.0f;
_mat[1][0] = 0.0f;
_mat[1][1] = 1.0f;
_mat[1][2] = 0.0f;
_mat[1][3] = 0.0f;
_mat[2][0] = 0.0f;
_mat[2][1] = 0.0f;
_mat[2][2] = 1.0f;
_mat[2][3] = 0.0f;
_mat[3][0] = 0.0f;
_mat[3][1] = 0.0f;
_mat[3][2] = 0.0f;
_mat[3][3] = 1.0f;
}
void Matrix::copy(const Matrix& matrix)
{
memcpy(_mat,matrix._mat,sizeof(_mat));
}
void Matrix::makeScale(float sx, float sy, float sz)
{
makeIdent();
_mat[0][0] = sx;
_mat[1][1] = sy;
_mat[2][2] = sz;
}
void Matrix::preScale( float sx, float sy, float sz, const Matrix& m )
{
Matrix transMat;
transMat.makeScale(sx, sy, sz);
mult(transMat,m);
}
void Matrix::postScale( const Matrix& m, float sx, float sy, float sz )
{
Matrix transMat;
transMat.makeScale(sx, sy, sz);
mult(m,transMat);
}
void Matrix::preScale( float sx, float sy, float sz )
{
Matrix transMat;
transMat.makeScale(sx, sy, sz);
preMult(transMat);
}
void Matrix::postScale( float sx, float sy, float sz )
{
Matrix transMat;
transMat.makeScale(sx, sy, sz);
postMult(transMat);
}
void Matrix::makeTrans( float tx, float ty, float tz )
{
makeIdent();
_mat[3][0] = tx;
_mat[3][1] = ty;
_mat[3][2] = tz;
}
void Matrix::preTrans( float tx, float ty, float tz, const Matrix& m )
{
Matrix transMat;
transMat.makeTrans(tx, ty, tz);
mult(transMat,m);
}
void Matrix::postTrans( const Matrix& m, float tx, float ty, float tz )
{
Matrix transMat;
transMat.makeTrans(tx, ty, tz);
mult(m,transMat);
}
void Matrix::preTrans( float tx, float ty, float tz )
{
_mat[3][0] = (tx * _mat[0][0]) + (ty * _mat[1][0]) + (tz * _mat[2][0]) + _mat[3][0];
_mat[3][1] = (tx * _mat[0][1]) + (ty * _mat[1][1]) + (tz * _mat[2][1]) + _mat[3][1];
_mat[3][2] = (tx * _mat[0][2]) + (ty * _mat[1][2]) + (tz * _mat[2][2]) + _mat[3][2];
_mat[3][3] = (tx * _mat[0][3]) + (ty * _mat[1][3]) + (tz * _mat[2][3]) + _mat[3][3];
}
void Matrix::postTrans( float tx, float ty, float tz )
{
Matrix transMat;
transMat.makeTrans(tx, ty, tz);
postMult(transMat);
}
void Matrix::makeRot( float deg, float x, float y, float z )
{
double __mat[4][4];
quaternion q;
float d = sqrtf( square(x) + square(y) + square(z) );
if( d == 0 )
return;
float sin_HalfAngle = sinf( DEG2RAD(deg/2) );
float cos_HalfAngle = cosf( DEG2RAD(deg/2) );
q.x = sin_HalfAngle * (x/d);
q.y = sin_HalfAngle * (y/d);
q.z = sin_HalfAngle * (z/d);
q.w = cos_HalfAngle;
quaternion_matrix( &q, __mat );
for(int i=0;i<4;++i)
{
for(int j=0;j<4;++j)
{
_mat[i][j]=__mat[i][j];
}
}
}
void Matrix::preRot( float deg, float x, float y, float z, const Matrix& m )
{
Matrix rotMat;
rotMat.makeRot( deg, x, y, z );
mult(rotMat,m);
}
void Matrix::postRot( const Matrix& m, float deg, float x, float y, float z )
{
Matrix rotMat;
rotMat.makeRot( deg, x, y, z );
mult(m,rotMat);
}
void Matrix::preRot( float deg, float x, float y, float z )
{
quaternion q;
double __mat[4][4];
float res_mat[4][4];
float d = sqrtf( square(x) + square(y) + square(z) );
if( d == 0 )
return;
float sin_HalfAngle = sinf( DEG2RAD(deg/2) );
float cos_HalfAngle = cosf( DEG2RAD(deg/2) );
q.x = sin_HalfAngle * (x/d);
q.y = sin_HalfAngle * (y/d);
q.z = sin_HalfAngle * (z/d);
q.w = cos_HalfAngle;
quaternion_matrix( &q, __mat );
matrix_mult( __mat, _mat, res_mat );
memcpy( _mat, res_mat, sizeof( _mat ) );
}
void Matrix::postRot( float deg, float x, float y, float z )
{
quaternion q;
double __mat[4][4];
float res_mat[4][4];
float d = sqrtf( square(x) + square(y) + square(z) );
if( d == 0 )
return;
float sin_HalfAngle = sinf( DEG2RAD(deg/2) );
float cos_HalfAngle = cosf( DEG2RAD(deg/2) );
q.x = sin_HalfAngle * (x/d);
q.y = sin_HalfAngle * (y/d);
q.z = sin_HalfAngle * (z/d);
q.w = cos_HalfAngle;
quaternion_matrix( &q, __mat );
matrix_mult( _mat, __mat , res_mat );
memcpy( _mat, res_mat, sizeof( _mat ) );
}
void Matrix::setTrans( float tx, float ty, float tz )
{
_mat[3][0] = tx;
_mat[3][1] = ty;
_mat[3][2] = tz;
}
void Matrix::setTrans( const Vec3& v )
{
_mat[3][0] = v[0];
_mat[3][1] = v[1];
_mat[3][2] = v[2];
}
void Matrix::preMult(const Matrix& m)
{
Matrix tm;
matrix_mult( m._mat, _mat, tm._mat );
*this = tm;
}
void Matrix::postMult(const Matrix& m)
{
Matrix tm;
matrix_mult( _mat, m._mat, tm._mat );
*this = tm;
}
void Matrix::mult(const Matrix& lhs,const Matrix& rhs)
{
matrix_mult( lhs._mat, rhs._mat, _mat );
}
Matrix Matrix::operator * (const Matrix& m) const
{
Matrix nm;
matrix_mult( _mat,m._mat, nm._mat );
return nm;
}
bool Matrix::invert(const Matrix& _m)
{
// code lifted from VR Juggler.
// not cleanly added, but seems to work. RO.
const float* a = reinterpret_cast<const float*>(_m._mat);
float* b = reinterpret_cast<float*>(_mat);
int n = 4;
int i, j, k;
int r[ 4], c[ 4], row[ 4], col[ 4];
float m[ 4][ 4*2], pivot, max_m, tmp_m, fac;
/* Initialization */
for ( i = 0; i < n; i ++ )
{
r[ i] = c[ i] = 0;
row[ i] = col[ i] = 0;
}
/* Set working matrix */
for ( i = 0; i < n; i++ )
{
for ( j = 0; j < n; j++ )
{
m[ i][ j] = a[ i * n + j];
m[ i][ j + n] = ( i == j ) ? 1.0 : 0.0 ;
}
}
/* Begin of loop */
for ( k = 0; k < n; k++ )
{
/* Choosing the pivot */
for ( i = 0, max_m = 0; i < n; i++ )
{
if ( row[ i] ) continue;
for ( j = 0; j < n; j++ )
{
if ( col[ j] ) continue;
tmp_m = fabs( m[ i][j]);
if ( tmp_m > max_m)
{
max_m = tmp_m;
r[ k] = i;
c[ k] = j;
}
}
}
row[ r[k] ] = col[ c[k] ] = 1;
pivot = m[ r[ k] ][ c[ k] ];
if ( fabs( pivot) <= 1e-20)
{
notify(WARN) << "*** pivot = %f in mat_inv. ***\n";
//exit( 0);
return false;
}
/* Normalization */
for ( j = 0; j < 2*n; j++ )
{
if ( j == c[ k] )
m[ r[ k]][ j] = 1.0;
else
m[ r[ k]][ j] /=pivot;
}
/* Reduction */
for ( i = 0; i < n; i++ )
{
if ( i == r[ k] )
continue;
for ( j=0, fac = m[ i][ c[k]];j < 2*n; j++ )
{
if ( j == c[ k] )
m[ i][ j] =0.0;
else
m[ i][ j] -=fac * m[ r[k]][ j];
}
}
}
/* Assign invers to a matrix */
for ( i = 0; i < n; i++ )
for ( j = 0; j < n; j++ )
row[ i] = ( c[ j] == i ) ? r[j] : row[ i];
for ( i = 0; i < n; i++ )
for ( j = 0; j < n; j++ )
b[ i * n + j] = m[ row[ i]][j + n];
return true; // It worked
}

168
src/osg/Node.cpp Normal file
View File

@@ -0,0 +1,168 @@
#include "osg/Node"
#include "osg/Group"
#include "osg/NodeVisitor"
#include "osg/Input"
#include "osg/Output"
#include "osg/Registry"
#include "osg/Notify"
#include <algorithm>
using namespace osg;
RegisterObjectProxy<Node> g_NodeProxy;
Node::Node()
{
_bsphere_computed = false;
_userData = NULL;
_nodeMask = 0xffffffff;
}
Node::~Node()
{
if (_userData && _memoryAdapter.valid()) _memoryAdapter->decrementReference(_userData);
}
void Node::accept(NodeVisitor& nv)
{
nv.apply(*this);
}
void Node::ascend(NodeVisitor& nv)
{
std::for_each(_parents.begin(),_parents.end(),NodeAcceptOp(nv));
}
bool Node::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (Object::readLocalData(fr)) iteratorAdvanced = true;
if (fr.matchSequence("name %s"))
{
_name = fr[1].takeStr();
fr+=2;
iteratorAdvanced = true;
}
// if (fr.matchSequence("user_data {"))
// {
// notify(DEBUG) << "Matched user_data {"<<endl;
// int entry = fr[0].getNoNestedBrackets();
// fr += 2;
//
// while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
// {
// Object* object = fr.readObject();
// if (object) setUserData(object);
// notify(DEBUG) << "read "<<object<<endl;
// ++fr;
// }
// iteratorAdvanced = true;
// }
while (fr.matchSequence("description {"))
{
notify(DEBUG) << "Matched description {"<<endl;
int entry = fr[0].getNoNestedBrackets();
fr += 2;
while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
{
_descriptions.push_back(fr[0].getStr());
notify(DEBUG) << "read "<<_descriptions.back()<<endl;
++fr;
}
iteratorAdvanced = true;
}
while (fr.matchSequence("description %s"))
{
notify(DEBUG) << "Matched description %s"<<endl;
_descriptions.push_back(fr[1].getStr());
notify(DEBUG) << "read "<<_descriptions.back()<<endl;
fr+=2;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool Node::writeLocalData(Output& fw)
{
Object::writeLocalData(fw);
if (!_name.empty()) fw.indent() << "name "<<'"'<<_name<<'"'<<endl;
// if (_userData)
// {
// Object* object = dynamic_cast<Object*>(_userData);
// if (object)
// {
// fw.indent() << "user_data {"<<endl;
// fw.moveIn();
// object->write(fw);
// fw.moveOut();
// fw.indent() << "}"<<endl;
// }
// }
if (!_descriptions.empty())
{
if (_descriptions.size()==1)
{
fw.indent() << "description "<<'"'<<_descriptions.front()<<'"'<<endl;
}
else
{
fw.indent() << "description {"<<endl;
fw.moveIn();
for(DescriptionList::iterator ditr=_descriptions.begin();
ditr!=_descriptions.end();
++ditr)
{
fw.indent() << '"'<<*ditr<<'"'<<endl;
}
fw.moveOut();
fw.indent() << "}"<<endl;
}
}
return true;
}
bool Node::computeBound()
{
_bsphere.init();
return false;
}
const BoundingSphere& Node::getBound()
{
if(!_bsphere_computed) computeBound();
return _bsphere;
}
void Node::dirtyBound()
{
if (_bsphere_computed)
{
_bsphere_computed = false;
// dirty parent bounding sphere's to ensure that all are valid.
for(ParentList::iterator itr=_parents.begin();
itr!=_parents.end();
++itr)
{
(*itr)->dirtyBound();
}
}
}

40
src/osg/NodeVisitor.cpp Normal file
View File

@@ -0,0 +1,40 @@
#include "osg/NodeVisitor"
#include <stdlib.h>
using namespace osg;
NodeVisitor::NodeVisitor(TraversalMode tm)
{
_traverseVisitor = NULL;
_traverseMode = tm;
}
NodeVisitor::~NodeVisitor()
{
// if (_traverseVisitor) detach from _traverseVisitor;
}
void NodeVisitor::setTraverseMode(TraversalMode mode)
{
if (_traverseMode==mode) return;
if (mode==TRAVERSE_VISITOR)
{
if (_traverseVisitor==NULL) _traverseMode = TRAVERSE_NONE;
else _traverseMode = TRAVERSE_VISITOR;
}
else
{
if (_traverseVisitor) _traverseVisitor=NULL;
_traverseMode = mode;
}
}
void NodeVisitor::setTraverseVisitor(NodeVisitor* nv)
{
if (_traverseVisitor==nv) return;
// if (_traverseVisitor) detach from _traverseVisitor;
_traverseVisitor = nv;
if (_traverseVisitor) _traverseMode = TRAVERSE_VISITOR;
else _traverseMode = TRAVERSE_NONE;
// attach to _traverseVisitor;
}

87
src/osg/Notify.cpp Normal file
View File

@@ -0,0 +1,87 @@
#include "osg/Notify"
#include <string>
using namespace osg;
int osg::NotifyInit::count_ = 0;
NotifySeverity osg::g_NotifyLevel = osg::NOTICE;
ofstream *osg::g_absorbStreamPtr = NULL;
void osg::setNotifyLevel(NotifySeverity severity)
{
g_NotifyLevel = severity;
}
int osg::getNotifyLevel()
{
return g_NotifyLevel;
}
#ifndef WIN32
ostream& osg::notify(NotifySeverity severity)
{
if (severity<=g_NotifyLevel || g_absorbStreamPtr==NULL)
{
if (severity<=osg::WARN) return cerr;
else return cout;
}
return *g_absorbStreamPtr;
}
#endif
NotifyInit::NotifyInit()
{
if (count_++ == 0) {
// g_NotifyLevel
// =============
g_NotifyLevel = osg::NOTICE; // Default value
char *OSGNOTIFYLEVEL=getenv("OSGNOTIFYLEVEL");
if(OSGNOTIFYLEVEL){
std::string stringOSGNOTIFYLEVEL(OSGNOTIFYLEVEL);
// Convert to upper case
for(std::string::iterator i=stringOSGNOTIFYLEVEL.begin();
i!=stringOSGNOTIFYLEVEL.end();
++i) *i=toupper(*i);
if(stringOSGNOTIFYLEVEL.find("ALWAYS")!=std::string::npos) g_NotifyLevel=osg::ALWAYS;
else if(stringOSGNOTIFYLEVEL.find("FATAL")!=std::string::npos) g_NotifyLevel=osg::FATAL;
else if(stringOSGNOTIFYLEVEL.find("WARN")!=std::string::npos) g_NotifyLevel=osg::WARN;
else if(stringOSGNOTIFYLEVEL.find("NOTICE")!=std::string::npos) g_NotifyLevel=osg::NOTICE;
else if(stringOSGNOTIFYLEVEL.find("INFO")!=std::string::npos) g_NotifyLevel=osg::INFO;
else if(stringOSGNOTIFYLEVEL.find("DEBUG")!=std::string::npos) g_NotifyLevel=osg::DEBUG;
else if(stringOSGNOTIFYLEVEL.find("FP_DEBUG")!=std::string::npos) g_NotifyLevel=osg::FP_DEBUG;
}
// g_absorbStreamPtr
// =================
char *OSGNOTIFYABSORBFILE=getenv("OSGNOTIFYABSORBFILE");
if (OSGNOTIFYABSORBFILE)
{
g_absorbStreamPtr=new ofstream(OSGNOTIFYABSORBFILE);
}
else
{
#ifdef WIN32
// What's the Windows equivalent of /dev/null?
g_absorbStreamPtr=new ofstream("C:/Windows/Tmp/osg.log");
#else
g_absorbStreamPtr=new ofstream("/dev/null");
#endif
}
}
}
NotifyInit::~NotifyInit()
{
if(--count_ == 0) {
delete g_absorbStreamPtr;
g_absorbStreamPtr=NULL;
}
}

254
src/osg/OSG.cpp Normal file
View File

@@ -0,0 +1,254 @@
#ifndef WIN32
#include <unistd.h>
#include <dlfcn.h>
#else
#include <Io.h>
#include <Windows.h>
#include <Winbase.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "osg/Notify"
#include "osg/OSG"
#include "osg/Node"
#include "osg/Geode"
#include "osg/Group"
#include "osg/Input"
#include "osg/Output"
#include "osg/Registry"
using namespace osg;
#ifdef WIN32
char *PathDelimitor = ";";
static const char *s_default_file_path = ".;D:/OpenSceneGraph/Data;D:/OpenSceneGraph/Data/Images;D:/OpenSceneGraph/lib";
//static char *s_filePath = (char *)s_default_file_path;
static char *s_filePath = ".;";
#else
char *PathDelimitor = ":";
static const char *s_default_file_path = ".:";
#ifdef __sgi
static const char *s_default_dso_path = "/usr/lib32/osgPlugins/";
#else
static const char *s_default_dso_path = "/usr/lib/osgPlugins/";
#endif
static char *s_filePath = ".:";
//static char *s_filePath = s_default_file_path;
#endif
#include <vector>
#include <algorithm>
using std::vector;
using std::find_if;
void osg::Init( void )
{
char *ptr;
if( (ptr = getenv( "OSGFILEPATH" )) )
{
notify(DEBUG) << "osg::Init("<<ptr<<")"<<endl;
SetFilePath( ptr );
}
else
{
notify(DEBUG) << "osg::Init(NULL)"<<endl;
}
}
void osg::SetFilePath( const char *_path )
{
char buff[1024];
notify(DEBUG) << "In osg::SetFilePath("<<_path<<")"<<endl;
buff[0] = 0;
/* notify(DEBUG) << "filePath " << s_filePath << endl;
notify(DEBUG) << "defPath " << s_default_file_path << endl;
notify(DEBUG) << "&filePath " << &s_filePath << endl;
notify(DEBUG) << "&defPath " << &s_default_file_path << endl;
*/
if( s_filePath != s_default_file_path )
{
strcpy( buff, s_filePath );
// delete s_filePath;
}
// if (strcmp(s_filePath, s_default_file_path) != 0)
// {
// strcpy( buff, s_filePath );
// delete s_filePath;
// }
strcat( buff, PathDelimitor );
strcat( buff, _path );
s_filePath = strdup( buff );
notify(DEBUG) << "Out osg::SetFilePath("<<_path<<")"<<endl;
}
static char *FindFileInPath( const char *_file, const char * filePath )
{
char pathbuff[1024];
char *tptr, *tmppath;
char *path = 0L;
notify(DEBUG) << "FindFileInPath() : trying " << _file << " ...\n";
#ifdef WIN32
if( _access( _file, 4 ) == 0 ) return (char *)_file;
#else
if( access( _file, F_OK ) == 0 ) return (char *)_file;
#endif
tptr = strdup( filePath );
tmppath = strtok( tptr, PathDelimitor );
do
{
sprintf( pathbuff, "%s/%s", tmppath, _file );
notify(DEBUG) << "FindFileInPath() : trying " << pathbuff << " ...\n";
#ifdef WIN32
if( _access( pathbuff, 4 ) == 0 ) break;
#else
if( access( pathbuff, F_OK ) == 0 ) break;
#endif
} while( (tmppath = strtok( 0, PathDelimitor )) );
if( tmppath != (char *)0L )
path = strdup( pathbuff );
::free(tptr);
notify( DEBUG ) << "FindFileInPath() : returning " << path << "\n";
return path;
}
char *osg::FindFile( const char *file )
{
return FindFileInPath( file, s_filePath );
}
/*
Order of precedence for
./
OSG_LD_LIBRARY_PATH
s_default_dso_path
LD_LIBRARY*_PATH
* DO NOT USE PATH or OSGFILEPATH
*/
char *osg::findDSO( const char *name )
{
char path[1024];
char *ptr;
strcpy( path, "./" );
if((ptr = getenv( "OSG_LD_LIBRARY_PATH" )))
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
strcat( path, PathDelimitor );
strcat( path, s_default_dso_path );
#ifdef __sgi
// bloody mess see rld(1) man page
# if (_MIPS_SIM == _MIPS_SIM_ABI32)
if( (ptr = getenv( "LD_LIBRARY_PATH" )))
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
# elif (_MIPS_SIM == _MIPS_SIM_NABI32)
if( !(ptr = getenv( "LD_LIBRARYN32_PATH" )))
ptr = getenv( "LD_LIBRARY_PATH" );
if( ptr )
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
# elif (_MIPS_SIM == _MIPS_SIM_ABI64)
if( !(ptr = getenv( "LD_LIBRARYN32_PATH" )))
ptr = getenv( "LD_LIBRARY_PATH" );
if( ptr )
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
# endif
#else
#if 0 // DO NOT USE PATH or OSGFILEPATH
# ifdef WIN32
if ((ptr = getenv( "PATH" )))
{
notify(DEBUG) << "PATH = "<<ptr<<endl;
strcat( path, PathDelimitor );
strcat( path, ptr );
}
# else
if( (ptr = getenv( "LD_LIBRARY_PATH" )))
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
#endif
#endif
#ifndef WIN32
// #ifdef __sgi
// strcat( path, PathDelimitor );
// strcat( path, "/usr/lib32/osgPlugins" );
// #else
// strcat( path, PathDelimitor );
// strcat( path, "/usr/lib/osgPlugins" );
// #endif
#endif
strcat( path ,PathDelimitor );
strcat( path, s_filePath );
char* fileFound = NULL;
fileFound = FindFileInPath( name , path );
if (fileFound) return fileFound;
// now try prepending the filename with "osgPlugins/"
char* prependosgPlugins = new char[strlen(name)+12];
strcpy(prependosgPlugins,"osgPlugins/");
strcat(prependosgPlugins,name);
fileFound = FindFileInPath( prependosgPlugins , path );
delete prependosgPlugins;
return fileFound;
#endif
return FindFileInPath( name, path );
}

78
src/osg/Object.cpp Normal file
View File

@@ -0,0 +1,78 @@
#include "osg/Object"
#include "osg/Registry"
#include "osg/Input"
#include "osg/Output"
using namespace osg;
Object* Object::readClone(Input& fr)
{
if (fr[0].matchWord("Use"))
{
if (fr[1].isString())
{
Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
if (obj && isSameKindAs(obj))
{
fr+=2;
return obj;
}
}
return NULL;
}
if (!fr[0].matchWord(className()) ||
!fr[1].isOpenBracket()) return NULL;
int entry = fr[0].getNoNestedBrackets();
Object* obj = clone();
fr+=2;
while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
{
bool iteratorAdvanced = false;
if (fr[0].matchWord("UniqueID") && fr[1].isString()) {
fr.regisiterUniqueIDForObject(fr[1].getStr(),obj);
fr += 2;
}
if (obj->readLocalData(fr)) iteratorAdvanced = true;
if (!iteratorAdvanced) ++fr;
}
++fr; // step over trailing '}'
return obj;
}
bool Object::write(Output& fw)
{
if (_refCount>1) {
std::string uniqueID;
if (fw.getUniqueIDForObject(this,uniqueID)) {
fw.indent() << "Use " << uniqueID << endl;
return true;
}
}
fw.indent() << className() << " {"<<endl;
fw.moveIn();
if (_refCount>1) {
std::string uniqueID;
fw.createUniqueIDForObject(this,uniqueID);
fw.registerUniqueIDForObject(this,uniqueID);
fw.indent() << "UniqueID " << uniqueID << endl;
}
writeLocalData(fw);
fw.moveOut();
fw.indent() << "}"<<endl;
return true;
}

75
src/osg/Output.cpp Normal file
View File

@@ -0,0 +1,75 @@
#include <stdio.h>
#include "osg/Output"
#include "osg/Object"
using namespace osg;
Output::Output()
{
_init();
}
Output::~Output()
{
_free();
}
void Output::_init()
{
_indent = 0;
_indentStep = 2;
_numIndicesPerLine = 10;
}
void Output::_free()
{
// should I be calling ofstream's free as well???
}
Output& Output::indent()
{
for(int i=0;i<_indent;++i) *this<<' ';
return *this;
}
void Output::moveIn()
{
_indent += _indentStep;
}
void Output::moveOut()
{
_indent -= _indentStep;
if (_indent<0) _indent=0;
}
bool Output::getUniqueIDForObject(Object* obj,std::string& uniqueID)
{
UniqueIDToLabelMapping::iterator fitr = _objectToUniqueIDMap.find(obj);
if (fitr != _objectToUniqueIDMap.end())
{
uniqueID = (*fitr).second;
return true;
}
else return false;
}
bool Output::createUniqueIDForObject(Object* obj,std::string& uniqueID)
{
char str[256];
sprintf(str,"%s_%i",obj->className(),_objectToUniqueIDMap.size());
uniqueID = str;
return true;
}
bool Output::registerUniqueIDForObject(Object* obj,std::string& uniqueID)
{
_objectToUniqueIDMap[obj] = uniqueID;
return true;
}

178
src/osg/Point.cpp Normal file
View File

@@ -0,0 +1,178 @@
// Ideas and code borrowed from GLUT pointburst demo
// written by Mark J. Kilgard
#ifdef WIN32
#include <windows.h>
#endif
#include "osg/GL"
#include "osg/Point"
#include "osg/ExtensionSupported"
#include "osg/Input"
#include "osg/Output"
using namespace osg;
#if defined(GL_SGIS_point_parameters) && !defined(GL_EXT_point_parameters)
/* Use the EXT point parameters interface for the SGIS implementation. */
# define GL_POINT_SIZE_MIN_EXT GL_POINT_SIZE_MIN_SGIS
# define GL_POINT_SIZE_MAX_EXT GL_POINT_SIZE_MAX_SGIS
# define GL_POINT_FADE_THRESHOLD_SIZE_EXT GL_POINT_FADE_THRESHOLD_SIZE_SGIS
# define GL_DISTANCE_ATTENUATION_EXT GL_DISTANCE_ATTENUATION_SGIS
# define glPointParameterfEXT glPointParameterfSGIS
# define glPointParameterfvEXT glPointParameterfvSGIS
# define GL_EXT_point_parameters 1
#endif
#if !defined(GL_EXT_point_parameters)
# define GL_POINT_SIZE_MIN_EXT 0x8126
# define GL_POINT_SIZE_MAX_EXT 0x8127
# define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
# define GL_DISTANCE_ATTENUATION_EXT 0x8129
# ifdef _WIN32
// Curse Microsoft for the insanity of wglGetProcAddress.
typedef void (APIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
typedef void (APIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);
# define GL_EXT_point_parameters 1
# endif
#endif
#ifdef _WIN32
PFNGLPOINTPARAMETERFEXTPROC glPointParameterfEXT;
PFNGLPOINTPARAMETERFVEXTPROC glPointParameterfvEXT;
#endif
static int s_hasPointParameters;
Point::Point( void )
{
_size = 1.0f; // TODO find proper default
_fadeThresholdSize = 1.0f; // TODO find proper default
_distanceAttenuation = Vec3(0.0f, 1.0f/5.f, 0.0f); // TODO find proper default
}
Point::~Point( void )
{
}
Point* Point::instance()
{
static ref_ptr<Point> s_point(new Point);
return s_point.get();
}
void Point::init_GL_EXT()
{
s_hasPointParameters =
ExtensionSupported("GL_SGIS_point_parameters") ||
ExtensionSupported("GL_EXT_point_parameters");
#ifdef _WIN32
if (s_hasPointParameters)
{
glPointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC)
wglGetProcAddress("glPointParameterfEXT");
glPointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)
wglGetProcAddress("glPointParameterfvEXT");
}
#endif
}
void Point::enableSmooth( void )
{
glEnable( GL_POINT_SMOOTH );
}
void Point::disableSmooth( void )
{
glDisable( GL_POINT_SMOOTH );
}
void Point::setSize( float size )
{
_size = size;
}
void Point::setFadeThresholdSize(float fadeThresholdSize)
{
_fadeThresholdSize = fadeThresholdSize;
}
void Point::setDistanceAttenuation(const Vec3& distanceAttenuation)
{
_distanceAttenuation = distanceAttenuation;
}
void Point::apply( void )
{
glPointSize(_size);
#if GL_EXT_point_parameters
static bool s_gl_ext_init=false;
if (!s_gl_ext_init)
{
s_gl_ext_init = true;
init_GL_EXT();
}
if (s_hasPointParameters)
{
glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, (const GLfloat*)&_distanceAttenuation);
glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, _fadeThresholdSize);
}
#endif
}
bool Point::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
float data;
if (fr[0].matchWord("size") && fr[1].getFloat(data))
{
_size = data;
fr+=2;
iteratorAdvanced = true;
}
if (fr[0].matchWord("fade_threshold_size") && fr[1].getFloat(data))
{
_fadeThresholdSize = data;
fr+=2;
iteratorAdvanced = true;
}
Vec3 distAtten;
if (fr[0].matchWord("distance_attenuation") &&
fr[1].getFloat(distAtten[0]) && fr[2].getFloat(distAtten[1]) && fr[3].getFloat(distAtten[2]))
{
_distanceAttenuation = distAtten;
fr+=4;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool Point::writeLocalData(Output& fw)
{
fw.indent() << "size " << _size << endl;
fw.indent() << "fade_threshold_size " << _fadeThresholdSize << endl;
fw.indent() << "distance_attenuation " << _distanceAttenuation << endl;
return true;
}

85
src/osg/PolygonOffset.cpp Normal file
View File

@@ -0,0 +1,85 @@
#include "osg/GL"
#include "osg/PolygonOffset"
#include "osg/Input"
#include "osg/Output"
using namespace osg;
PolygonOffset::PolygonOffset( void )
{
_factor = 0.0f; // are these sensible defaut values?
_units = 0.0f;
}
PolygonOffset::~PolygonOffset( void )
{
}
PolygonOffset* PolygonOffset::instance()
{
static ref_ptr<PolygonOffset> s_PolygonOffset(new PolygonOffset);
return s_PolygonOffset.get();
}
void PolygonOffset::setOffset(float factor,float units)
{
_factor = factor;
_units = units;
}
void PolygonOffset::enable( void )
{
glEnable( GL_POLYGON_OFFSET_FILL);
glEnable( GL_POLYGON_OFFSET_LINE);
glEnable( GL_POLYGON_OFFSET_POINT);
}
void PolygonOffset::disable( void )
{
glDisable( GL_POLYGON_OFFSET_FILL);
glDisable( GL_POLYGON_OFFSET_LINE);
glDisable( GL_POLYGON_OFFSET_POINT);
}
void PolygonOffset::apply( void )
{
glPolygonOffset(_factor,_units);
}
bool PolygonOffset::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
float data;
if (fr[0].matchWord("factor") && fr[1].getFloat(data))
{
_factor = data;
fr+=2;
iteratorAdvanced = true;
}
if (fr[0].matchWord("units") && fr[1].getFloat(data))
{
_units = data;
fr+=2;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool PolygonOffset::writeLocalData(Output& fw)
{
fw.indent() << "factor " << _factor << endl;
fw.indent() << "units " << _units << endl;
return true;
}

272
src/osg/Quat.cpp Normal file
View File

@@ -0,0 +1,272 @@
#include "osg/Quat"
#include "osg/Vec4"
#include "osg/Vec3"
#include "osg/Types"
#include <math.h>
/// Good introductions to Quaternions at:
/// http://www.gamasutra.com/features/programming/19980703/quaternions_01.htm
/// http://mathworld.wolfram.com/Quaternion.html
using namespace osg;
/// Default constructor is empty
Quat::Quat( void )
{
}
/// Constructor with four floats - just call the constructor for the Vec4
Quat::Quat( const float x, const float y, const float z, const float w )
{
_fv = Vec4( x, y, z, w );
}
/// Constructor with a Vec4
Quat::Quat( const Vec4& vec )
{
_fv = vec;
}
/// Set the elements of the Quat to represent a rotation of angle
/// (radians) around the axis (x,y,z)
void Quat::makeRot( const float angle,
const float x,
const float y,
const float z )
{
float inversenorm = 1.0/sqrt( x*x + y*y + z*z );
float coshalfangle = cos( 0.5*angle );
float sinhalfangle = sin( 0.5*angle );
_fv[0] = x * sinhalfangle * inversenorm;
_fv[1] = y * sinhalfangle * inversenorm;
_fv[2] = z * sinhalfangle * inversenorm;
_fv[3] = coshalfangle;
}
void Quat::makeRot( const float angle, const Vec3& vec )
{
makeRot( angle, vec[0], vec[1], vec[2] );
}
// Make a rotation Quat which will rotate vec1 to vec2
// Generally take adot product to get the angle between these
// and then use a cross product to get the rotation axis
// Watch out for the two special cases of when the vectors
// are co-incident or opposite in direction.
void Quat::makeRot( const Vec3& vec1, const Vec3& vec2 )
{
const float epsilon = 0.00001f;
float length1 = vec1.length();
float length2 = vec2.length();
float cosangle = vec1*vec2/(2*length1*length2); // dot product vec1*vec2
if ( fabs(cosangle - 1) < epsilon )
{
// cosangle is close to 1, so the vectors are close to being coincident
// Need to generate an angle of zero with any vector we like
// We'll choose (1,0,0)
makeRot( 0.0, 1.0, 0.0, 0.0 );
}
else
if ( fabs(cosangle + 1) < epsilon )
{
// cosangle is close to -1, so the vectors are close to being opposite
// The angle of rotation is going to be Pi, but around which axis?
// Basically, any one perpendicular to vec1 = (x,y,z) is going to work.
// Choose a vector to cross product vec1 with. Find the biggest
// in magnitude of x, y and z and then put a zero in that position.
float biggest = fabs(vec1[0]); int bigposn = 0;
if ( fabs(vec1[1]) > biggest ) { biggest=fabs(vec1[1]); bigposn = 1; }
if ( fabs(vec1[2]) > biggest ) { biggest=fabs(vec1[2]); bigposn = 2; }
Vec3 temp = Vec3( 1.0, 1.0, 1.0 );
temp[bigposn] = 0.0;
Vec3 axis = vec1^temp; // this is a cross-product to generate the
// axis around which to rotate
makeRot( (float)M_PI, axis );
}
else
{
// This is the usual situation - take a cross-product of vec1 and vec2
// and that is the axis around which to rotate.
Vec3 axis = vec1^vec2;
float angle = acos( cosangle );
makeRot( angle, axis );
}
}
// Get the angle of rotation and axis of this Quat object.
// Won't give very meaningful results if the Quat is not associated
// with a rotation!
void Quat::getRot( float& angle, Vec3& vec ) const
{
float sinhalfangle = sqrt( _fv[0]*_fv[0] + _fv[1]*_fv[1] + _fv[2]*_fv[2] );
/// float coshalfangle = _fv[3];
/// These are not checked for performance reasons ? (cop out!)
/// Point for discussion - how do one handle errors in the osg?
/// if ( abs(sinhalfangle) > 1.0 ) { error };
/// if ( abs(coshalfangle) > 1.0 ) { error };
// *angle = atan2( sinhalfangle, coshalfangle ); // see man atan2
angle = 2 * atan2( sinhalfangle, _fv[3] ); // -pi < angle < pi
vec = Vec3(_fv[0], _fv[1], _fv[2]) / sinhalfangle;
}
void Quat::getRot( float& angle, float& x, float& y, float& z ) const
{
float sinhalfangle = sqrt( _fv[0]*_fv[0] + _fv[1]*_fv[1] + _fv[2]*_fv[2] );
angle = 2 * atan2( sinhalfangle, _fv[3] );
x = _fv[0] / sinhalfangle;
y = _fv[1] / sinhalfangle;
z = _fv[2] / sinhalfangle;
}
/// Spherical Linear Interpolation
/// As t goes from 0 to 1, the Quat object goes from "from" to "to"
/// Reference: Shoemake at SIGGRAPH 89
/// See also
/// http://www.gamasutra.com/features/programming/19980703/quaternions_01.htm
void Quat::slerp( const float t, const Quat& from, const Quat& to )
{
const double epsilon = 0.00001;
double omega, cosomega, sinomega, scale_from, scale_to ;
cosomega = from.asVec4() * to.asVec4() ; // this is a dot product
if( (1.0 - cosomega) > epsilon )
{
omega= acos(cosomega) ; // 0 <= omega <= Pi (see man acos)
sinomega = sin(omega) ; // this sinomega should always be +ve so
// could try sinomega=sqrt(1-cosomega*cosomega) to avoid a sin()?
scale_from = sin((1.0-t)*omega)/sinomega ;
scale_to = sin(t*omega)/sinomega ;
}
else
{
/* --------------------------------------------------
The ends of the vectors are very close
we can use simple linear interpolation - no need
to worry about the "spherical" interpolation
-------------------------------------------------- */
scale_from = 1.0 - t ;
scale_to = t ;
}
_fv = (from._fv*scale_from) + (to._fv*scale_to); // use Vec4 arithmetic
// so that we get a Vec4
}
#define QX _fv[0]
#define QY _fv[1]
#define QZ _fv[2]
#define QW _fv[3]
void Quat::set( const Matrix& m )
{
// Source: Gamasutra, Rotating Objects Using Quaternions
//
//http://www.gamasutra.com/features/programming/19980703/quaternions_01.htm
float tr, s;
float tq[4];
int i, j, k;
int nxt[3] = {1, 2, 0};
tr = m._mat[0][0] + m._mat[1][1] + m._mat[2][2];
// check the diagonal
if (tr > 0.0)
{
s = (float)sqrt (tr + 1.0);
QW = s / 2.0f;
s = 0.5f / s;
QX = (m._mat[1][2] - m._mat[2][1]) * s;
QY = (m._mat[2][0] - m._mat[0][2]) * s;
QZ = (m._mat[0][1] - m._mat[1][0]) * s;
}
else
{
// diagonal is negative
i = 0;
if (m._mat[1][1] > m._mat[0][0])
i = 1;
if (m._mat[2][2] > m._mat[i][i])
i = 2;
j = nxt[i];
k = nxt[j];
s = (float)sqrt ((m._mat[i][i] - (m._mat[j][j] + m._mat[k][k])) + 1.0);
tq[i] = s * 0.5f;
if (s != 0.0f)
s = 0.5f / s;
tq[3] = (m._mat[j][k] - m._mat[k][j]) * s;
tq[j] = (m._mat[i][j] + m._mat[j][i]) * s;
tq[k] = (m._mat[i][k] + m._mat[k][i]) * s;
QX = tq[0];
QY = tq[1];
QZ = tq[2];
QW = tq[3];
}
}
void Quat::get( Matrix& m ) const
{
// Source: Gamasutra, Rotating Objects Using Quaternions
//
//http://www.gamasutra.com/features/programming/19980703/quaternions_01.htm
float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
// calculate coefficients
x2 = QX + QX;
y2 = QY + QY;
z2 = QZ + QZ;
xx = QX * x2;
xy = QX * y2;
xz = QX * z2;
yy = QY * y2;
yz = QY * z2;
zz = QZ * z2;
wx = QW * x2;
wy = QW * y2;
wz = QW * z2;
m._mat[0][0] = 1.0f - (yy + zz);
m._mat[0][1] = xy - wz;
m._mat[0][2] = xz + wy;
m._mat[0][3] = 0.0f;
m._mat[1][0] = xy + wz;
m._mat[1][1] = 1.0f - (xx + zz);
m._mat[1][2] = yz - wx;
m._mat[1][3] = 0.0f;
m._mat[2][0] = xz - wy;
m._mat[2][1] = yz + wx;
m._mat[2][2] = 1.0f - (xx + yy);
m._mat[2][3] = 0.0f;
m._mat[3][0] = 0;
m._mat[3][1] = 0;
m._mat[3][2] = 0;
m._mat[3][3] = 1;
}

101
src/osg/ReaderWriterOSG.cpp Normal file
View File

@@ -0,0 +1,101 @@
#include "osg/Registry"
#include "osg/Object"
#include "osg/Image"
#include "osg/Node"
#include "osg/Group"
#include "osg/Input"
#include "osg/Output"
#ifdef __sgi
using std::string;
#endif
using namespace osg;
class DefaultReaderWriter : public ReaderWriter
{
public:
virtual const char* className() { return "Default OSG Reader/Writer"; }
virtual bool acceptsExtension(const string& extension) { return extension=="osg" || extension=="OSG"; }
virtual Object* readObject(const string& fileName) { return readNode(fileName); }
virtual Node* readNode(const string& fileName)
{
ifstream fin(fileName.c_str());
if (fin)
{
Input fr;
fr.attach(&fin);
Group* group = new Group;
group->setName("import group");
// load all nodes in file, placing them in a group.
while(!fr.eof())
{
Node *node = fr.readNode();
if (node) group->addChild(node);
else fr.advanceOverCurrentFieldOrBlock();
}
if (group->getNumChildren()>1)
{
return group;
}
else if (group->getNumChildren()==1)
{
// only one node loaded so just return that one node,
// and delete the redundent group. Note, the
// child must be referenced before defrencing
// the group so to avoid delete its children.
Node* node = group->getChild(0);
node->ref();
group->unref();
return node;
} // group->getNumChildren()==0
else
{
return 0L;
}
}
else
{
return 0L;
}
}
virtual bool writeObject(Object& obj,const string& fileName)
{
Output fout;
fout.open(fileName.c_str());
if (fout)
{
obj.write(fout);
fout.close();
return true;
}
return false;
}
virtual bool writeNode(Node& node,const string& fileName)
{
Output fout;
fout.open(fileName.c_str());
if (fout)
{
node.write(fout);
fout.close();
return true;
}
return false;
}
};
// now register with Registry to instantiate the above
// reader/writer.
RegisterReaderWriterProxy<DefaultReaderWriter> g_defaultReaderWriterProxy;

380
src/osg/ReaderWriterRGB.cpp Normal file
View File

@@ -0,0 +1,380 @@
#include "osg/Image"
#include "osg/Input"
#include "osg/Output"
#include "osg/Notify"
#include "osg/FileNameUtils"
#include "osg/Registry"
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/GeoState>
#include <osg/Texture>
#include "osg/GL"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef SEEK_SET
# define SEEK_SET 0
#endif
using namespace osg;
typedef struct _rawImageRec
{
unsigned short imagic;
unsigned short type;
unsigned short dim;
unsigned short sizeX, sizeY, sizeZ;
unsigned long min, max;
unsigned long wasteBytes;
char name[80];
unsigned long colorMap;
FILE *file;
unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
unsigned long rleEnd;
GLuint *rowStart;
GLint *rowSize;
} rawImageRec;
static void ConvertShort(unsigned short *array, long length)
{
unsigned long b1, b2;
unsigned char *ptr;
ptr = (unsigned char *)array;
while (length--)
{
b1 = *ptr++;
b2 = *ptr++;
*array++ = (unsigned short) ((b1 << 8) | (b2));
}
}
static void ConvertLong(GLuint *array, long length)
{
unsigned long b1, b2, b3, b4;
unsigned char *ptr;
ptr = (unsigned char *)array;
while (length--)
{
b1 = *ptr++;
b2 = *ptr++;
b3 = *ptr++;
b4 = *ptr++;
*array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
}
}
static rawImageRec *RawImageOpen(const char *fileName)
{
union
{
int testWord;
char testByte[4];
} endianTest;
rawImageRec *raw;
GLenum swapFlag;
int x;
endianTest.testWord = 1;
if (endianTest.testByte[0] == 1)
{
swapFlag = GL_TRUE;
}
else
{
swapFlag = GL_FALSE;
}
raw = (rawImageRec *)malloc(sizeof(rawImageRec));
if (raw == NULL)
{
notify(WARN)<< "Out of memory!"<<endl;
return NULL;
}
if ((raw->file = fopen(fileName, "rb")) == NULL)
{
perror(fileName);
return NULL;
}
fread(raw, 1, 12, raw->file);
if (swapFlag)
{
ConvertShort(&raw->imagic, 6);
}
raw->tmp = raw->tmpR = raw->tmpG = raw->tmpB = raw->tmpA = 0L;
raw->tmp = (unsigned char *)malloc(raw->sizeX*256);
if (raw->tmp == NULL )
{
notify(FATAL)<< "Out of memory!"<<endl;
return NULL;
}
if( raw->sizeZ >= 1 )
{
if( (raw->tmpR = (unsigned char *)malloc(raw->sizeX)) == NULL )
{
notify(FATAL)<< "Out of memory!"<<endl;
free( raw->tmp );
return NULL;
}
}
if( raw->sizeZ >= 2 )
{
if( (raw->tmpG = (unsigned char *)malloc(raw->sizeX)) == NULL )
{
notify(FATAL)<< "Out of memory!"<<endl;
free( raw->tmp );
free( raw->tmpR );
return NULL;
}
}
if( raw->sizeZ >= 3 )
{
if( (raw->tmpB = (unsigned char *)malloc(raw->sizeX)) == NULL )
{
notify(FATAL)<< "Out of memory!"<<endl;
free( raw->tmp );
free( raw->tmpR );
free( raw->tmpG );
return NULL;
}
}
if (raw->sizeZ >= 4)
{
if( (raw->tmpA = (unsigned char *)malloc(raw->sizeX)) == NULL )
{
notify(FATAL)<< "Out of memory!"<<endl;
free( raw->tmp );
free( raw->tmpR );
free( raw->tmpG );
free( raw->tmpB );
return NULL;
}
}
if ((raw->type & 0xFF00) == 0x0100)
{
x = raw->sizeY * raw->sizeZ * sizeof(GLuint);
raw->rowStart = (GLuint *)malloc(x);
raw->rowSize = (GLint *)malloc(x);
if (raw->rowStart == NULL || raw->rowSize == NULL)
{
notify(FATAL)<< "Out of memory!"<<endl;
return NULL;
}
raw->rleEnd = 512 + (2 * x);
fseek(raw->file, 512, SEEK_SET);
fread(raw->rowStart, 1, x, raw->file);
fread(raw->rowSize, 1, x, raw->file);
if (swapFlag)
{
ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
}
}
return raw;
}
static void RawImageClose(rawImageRec *raw)
{
fclose(raw->file);
free(raw->tmp);
if( raw->tmpR )
free(raw->tmpR);
if( raw->tmpG )
free(raw->tmpG);
if( raw->tmpB )
free(raw->tmpB);
if( raw->tmpA )
free(raw->tmpA);
free(raw);
}
static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
{
unsigned char *iPtr, *oPtr, pixel;
int count, done = 0;
if ((raw->type & 0xFF00) == 0x0100)
{
fseek(raw->file, (long) raw->rowStart[y+z*raw->sizeY], SEEK_SET);
fread(raw->tmp, 1, (unsigned int)raw->rowSize[y+z*raw->sizeY],
raw->file);
iPtr = raw->tmp;
oPtr = buf;
while (!done)
{
pixel = *iPtr++;
count = (int)(pixel & 0x7F);
if (!count)
{
done = 1;
return;
}
if (pixel & 0x80)
{
while (count--)
{
*oPtr++ = *iPtr++;
}
}
else
{
pixel = *iPtr++;
while (count--)
{
*oPtr++ = pixel;
}
}
}
}
else
{
fseek(raw->file, 512+(y*raw->sizeX)+(z*raw->sizeX*raw->sizeY),
SEEK_SET);
fread(buf, 1, raw->sizeX, raw->file);
}
}
static void RawImageGetData(rawImageRec *raw, unsigned char **data )
{
unsigned char *ptr;
int i, j;
// // round the width to a factor 4
// int width = (int)(floorf((float)raw->sizeX/4.0f)*4.0f);
// if (width!=raw->sizeX) width += 4;
*data = (unsigned char *)malloc(2 * (raw->sizeX+1)*(raw->sizeY+1)*4);
// *data = (unsigned char *)malloc(2 * (width+1)*(raw->sizeY+1)*4);
ptr = *data;
for (i = 0; i < (int)(raw->sizeY); i++)
{
if( raw->sizeZ >= 1 )
RawImageGetRow(raw, raw->tmpR, i, 0);
if( raw->sizeZ >= 2 )
RawImageGetRow(raw, raw->tmpG, i, 1);
if( raw->sizeZ >= 3 )
RawImageGetRow(raw, raw->tmpB, i, 2);
if( raw->sizeZ >= 4 )
RawImageGetRow(raw, raw->tmpA, i, 3);
for (j = 0; j < (int)(raw->sizeX); j++)
{
if( raw->sizeZ >= 1 )
*ptr++ = *(raw->tmpR + j);
if( raw->sizeZ >= 2 )
*ptr++ = *(raw->tmpG + j);
if( raw->sizeZ >= 3 )
*ptr++ = *(raw->tmpB + j);
if( raw->sizeZ >= 4 )
*ptr++ = *(raw->tmpA + j);
}
// // pad the image width with blanks to bring it up to the rounded width.
// for(;j<width;++j) *ptr++ = 0;
}
}
class ReaderWriterRGB : public ReaderWriter
{
public:
virtual const char* className() { return "Default RGB Image Reader/Writer"; }
virtual bool acceptsExtension(const std::string& extension)
{
return extension=="rgb" || extension=="rgba" ||
extension=="int" || extension=="inta" ||
extension=="bw";
}
virtual Node* readNode(const std::string& fileName)
{
Image* image = readImage(fileName);
if (image)
{
Geode* geode = createGeodeForImage(image);
if (geode==NULL) image->unref();
return geode;
}
else
{
return NULL;
}
}
virtual Image* readImage(const std::string& fileName)
{
std::string ext = getLowerCaseFileExtension(fileName);
if (!acceptsExtension(ext)) return NULL;
rawImageRec *raw;
if( (raw = RawImageOpen(fileName.c_str())) == NULL )
{
notify(FATAL)<< "Unable to open \""<<fileName<<"\""<<endl;
return NULL;
}
int s = raw->sizeX;
int t = raw->sizeY;
int r = 1;
#if 0
int internalFormat = raw->sizeZ == 3 ? GL_RGB5 :
raw->sizeZ == 4 ? GL_RGB5_A1 : GL_RGB;
#else
int internalFormat = raw->sizeZ;
#endif
unsigned int pixelFormat =
raw->sizeZ == 1 ? GL_LUMINANCE :
raw->sizeZ == 2 ? GL_LUMINANCE_ALPHA :
raw->sizeZ == 3 ? GL_RGB :
raw->sizeZ == 4 ? GL_RGBA : (GLenum)-1;
unsigned int dataType = GL_UNSIGNED_BYTE;
unsigned char *data;
RawImageGetData(raw, &data);
RawImageClose(raw);
Image* image = new Image();
image->setFileName(fileName.c_str());
image->setImage(s,t,r,
internalFormat,
pixelFormat,
dataType,
data);
notify(INFO) << "image read ok "<<s<<" "<<t<<endl;
return image;
}
virtual bool writeImage(Image& ,const std::string& )
{
return false;
}
};
// now register with Registry to instantiate the above
// reader/writer.
RegisterReaderWriterProxy<ReaderWriterRGB> g_readerWriter_RGB_Proxy;

543
src/osg/Registry.cpp Normal file
View File

@@ -0,0 +1,543 @@
#include "osg/Registry"
#include "osg/Notify"
#include "osg/Object"
#include "osg/Image"
#include "osg/Node"
#include "osg/Group"
#include "osg/Input"
#include "osg/Output"
#include "osg/FileNameUtils"
#include <stdio.h>
#include <algorithm>
#include <set>
using namespace osg;
Object* osg::loadObjectFile(const char *name)
{
return Registry::instance()->readObject(name);
}
Image* osg::loadImageFile(const char *name)
{
return Registry::instance()->readImage(name);
}
Node* osg::loadNodeFile(const char *name)
{
return Registry::instance()->readNode(name);
}
bool osg::saveObjectFile(Object& object,const char *name)
{
return Registry::instance()->writeObject(object,name);
}
bool osg::saveImageFile(Image& image,const char *name)
{
return Registry::instance()->writeImage(image,name);
}
bool osg::saveNodeFile(Node& node,const char *name)
{
return Registry::instance()->writeNode(node,name);
}
// definition of the Registry
Registry::Registry()
{
notify(INFO) << "Constructing osg::Registry"<<endl;
_openingLibrary = false;
osg::Init();
}
Registry::~Registry()
{
// Don't write to notify() in here. Destruction order is indeterminate
// (I think) and the notify stream may have been destroyed before this
// is called.
// note, do not need to unregister attached prototype and reader/writers
// as they will be automatically unreferenced by the std::vector
// destructor & ref_ptr combination.
}
Registry* Registry::instance()
{
static Registry s_nodeFactory;
return &s_nodeFactory;
}
void Registry::addPrototype(Object* obj)
{
if (obj==0L) return;
// works under win32, good old C :-)
if (_openingLibrary) notify(INFO) << "Opening Library : ";
notify(INFO) << "osg::Registry::addPrototype("<<obj->className()<<")"<<endl;
int newPos = _nodeProtoList.size();
_protoList.push_back(obj);
if (dynamic_cast<Node*>(obj))
{
_nodeProtoList.push_back(newPos);
}
if (dynamic_cast<Image*>(obj))
{
_imageProtoList.push_back(newPos);
}
}
void Registry::removePrototype(Object* obj)
{
if (obj==0L) return;
notify(INFO) << "osg::Registry::removePrototype()"<<endl;
PrototypeList::iterator pitr = std::find(_protoList.begin(),_protoList.end(),obj);
if (pitr!=_protoList.end())
{
_protoList.erase(pitr);
// note need to handle the node and image lists,
// to be implemented...
}
}
void Registry::addReaderWriter(ReaderWriter* rw)
{
if (rw==0L) return;
if (_openingLibrary) notify(INFO) << "Opening Library : "<<endl;
notify(INFO) << "osg::Registry::addReaderWriter("<<rw->className()<<")"<<endl;
_rwList.push_back(rw);
}
void Registry::removeReaderWriter(ReaderWriter* rw)
{
if (rw==0L) return;
notify(INFO) << "osg::Registry::removeReaderWriter();"<<endl;
ReaderWriterList::iterator rwitr = std::find(_rwList.begin(),_rwList.end(),rw);
if (rwitr!=_rwList.end())
{
_rwList.erase(rwitr);
}
}
std::string Registry::createLibraryNameForFile(const std::string& fileName)
{
std::string ext = getLowerCaseFileExtension(fileName);
return createLibraryNameForExt(ext);
}
std::string Registry::createLibraryNameForExt(const std::string& ext)
{
#ifdef WIN32
# ifdef _DEBUG
return "osgdb_"+ext+"d.dll";
# else
return "osgdb_"+ext+".dll";
# endif
#else
return "osgdb_"+ext+".so";
#endif
}
bool Registry::loadLibrary(const std::string& fileName)
{
DynamicLibrary* dl = getLibrary(fileName);
if (dl) return false;
_openingLibrary=true;
dl = DynamicLibrary::loadLibrary(fileName);
_openingLibrary=false;
if (dl)
{
dl->ref();
_dlList.push_back(dl);
return true;
}
return false;
}
bool Registry::closeLibrary(const std::string& fileName)
{
DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
if (ditr!=_dlList.end())
{
(*ditr)->unref();
_dlList.erase(ditr);
return true;
}
return false;
}
Registry::DynamicLibraryList::iterator Registry::getLibraryItr(const std::string& fileName)
{
DynamicLibraryList::iterator ditr = _dlList.begin();
for(;ditr!=_dlList.end();++ditr)
{
if ((*ditr)->getName()==fileName) return ditr;
}
return _dlList.end();
}
DynamicLibrary* Registry::getLibrary(const std::string& fileName)
{
DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
if (ditr!=_dlList.end()) return ditr->get();
else return NULL;
}
Object* Registry::readObject(Input& fr)
{
if (fr[0].matchWord("Use"))
{
if (fr[1].isString()) {
Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
if (obj) fr+=2;
return obj;
}
else return NULL;
}
for(unsigned int i=0;i<_protoList.size();++i)
{
Object* obj = _protoList[i]->readClone(fr);
if (obj) return obj;
}
return 0L;
}
Object* Registry::readObject(const std::string& fileName)
{
char *file = FindFile( fileName.c_str() );
if (file==NULL) return NULL;
// record the existing reader writer.
std::set<ReaderWriter*> rwOriginal;
// first attempt to load the file from existing ReaderWriter's
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
rwOriginal.insert(itr->get());
Object* obj = (*itr)->readObject(file);
if (obj) return obj;
}
// now look for a plug-in to load the file.
std::string libraryName = createLibraryNameForFile(fileName);
if (Registry::instance()->loadLibrary(libraryName))
{
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
if (rwOriginal.find(itr->get())==rwOriginal.end())
{
Object* obj = (*itr)->readObject(file);
if (obj) return obj;
}
}
}
else
{
notify(NOTICE)<<"Warning: Could not find plugin to read file with extension ."
<<getLowerCaseFileExtension(fileName)<<endl;
}
notify(NOTICE)<<"Warning: Unable to read file "<<fileName<<endl;
return NULL;
}
bool Registry::writeObject(Object& obj,const std::string& fileName)
{
// record the existing reader writer.
std::set<ReaderWriter*> rwOriginal;
// first attempt to load the file from existing ReaderWriter's
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
rwOriginal.insert(itr->get());
if ((*itr)->writeObject(obj,fileName)) return true;
}
// now look for a plug-in to save the file.
std::string libraryName = createLibraryNameForFile(fileName);
if (loadLibrary(libraryName))
{
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
if (rwOriginal.find(itr->get())==rwOriginal.end())
{
if ((*itr)->writeObject(obj,fileName)) return true;
}
}
}
else
{
notify(NOTICE)<<"Warning: Could not find plugin to write file with extension ."
<<getLowerCaseFileExtension(fileName)<<endl;
}
notify(NOTICE)<<"Warning: Unable to write file "<<fileName<<endl;
return false;
}
Image* Registry::readImage(Input& fr)
{
if (fr[0].matchWord("Use"))
{
if (fr[1].isString()) {
Image* image = dynamic_cast<Image*>(fr.getObjectForUniqueID(fr[1].getStr()));
if (image) fr+=2;
return image;
}
else return NULL;
}
for(std::vector<int>::iterator itr=_imageProtoList.begin();
itr!=_imageProtoList.end();
++itr)
{
int i=*itr;
Object* obj = _protoList[i]->readClone(fr);
if (obj)
{
Image* image = static_cast<Image*>(obj);
return image;
}
}
return 0L;
}
Image* Registry::readImage(const std::string& fileName)
{
char *file = FindFile( fileName.c_str() );
if (file==NULL) return NULL;
// record the existing reader writer.
std::set<ReaderWriter*> rwOriginal;
// first attempt to load the file from existing ReaderWriter's
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
rwOriginal.insert(itr->get());
Image* image = (*itr)->readImage(file);
if (image) return image;
}
// now look for a plug-in to load the file.
std::string libraryName = createLibraryNameForFile(fileName);
if (loadLibrary(libraryName))
{
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
if (rwOriginal.find(itr->get())==rwOriginal.end())
{
Image* image = (*itr)->readImage(file);
if (image) return image;
}
}
}
else
{
notify(NOTICE)<<"Warning: Could not find plugin to read file with extension ."
<<getLowerCaseFileExtension(fileName)<<endl;
}
notify(NOTICE)<<"Warning: Unable to read file "<<fileName<<endl;
return NULL;
}
bool Registry::writeImage(Image& image,const std::string& fileName)
{
// record the existing reader writer.
std::set<ReaderWriter*> rwOriginal;
// first attempt to load the file from existing ReaderWriter's
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
rwOriginal.insert(itr->get());
if ((*itr)->writeImage(image,fileName)) return true;
}
// now look for a plug-in to save the file.
std::string libraryName = createLibraryNameForFile(fileName);
if (loadLibrary(libraryName))
{
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
if (rwOriginal.find(itr->get())==rwOriginal.end())
{
if ((*itr)->writeImage(image,fileName)) return true;
}
}
}
else
{
notify(NOTICE)<<"Warning: Could not find plugin to write file with extension ."
<<getLowerCaseFileExtension(fileName)<<endl;
}
notify(NOTICE)<<"Warning: Unable to write file "<<fileName<<endl;
return false;
}
Node* Registry::readNode(Input& fr)
{
if (fr[0].matchWord("Use"))
{
if (fr[1].isString()) {
Node* node = dynamic_cast<Node*>(fr.getObjectForUniqueID(fr[1].getStr()));
if (node) fr+=2;
return node;
}
else return NULL;
}
std::vector<int>::iterator itr=_nodeProtoList.begin();
for(;itr!=_nodeProtoList.end();++itr)
{
int i=*itr;
Object* obj = _protoList[i]->readClone(fr);
if (obj)
{
Node* node = static_cast<Node*>(obj);
return node;
}
}
return 0L;
}
Node* Registry::readNode(const std::string& fileName)
{
char *file = FindFile( fileName.c_str() );
if (file==NULL) return NULL;
// record the existing reader writer.
std::set<ReaderWriter*> rwOriginal;
// first attempt to load the file from existing ReaderWriter's
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
rwOriginal.insert(itr->get());
Node* node = (*itr)->readNode(file);
if (node) return node;
}
// now look for a plug-in to load the file.
std::string libraryName = createLibraryNameForFile(fileName);
notify(INFO) << "Now checking for plug-in "<<libraryName<<endl;
if (loadLibrary(libraryName))
{
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
if (rwOriginal.find(itr->get())==rwOriginal.end())
{
Node* node = (*itr)->readNode(file);
if (node) return node;
}
}
}
else
{
notify(NOTICE)<<"Warning: Could not find plugin to read file with extension ."
<<getLowerCaseFileExtension(fileName)<<endl;
}
notify(NOTICE)<<"Warning: Unable to read file "<<fileName<<endl;
return NULL;
}
bool Registry::writeNode(Node& node,const std::string& fileName)
{
// record the existing reader writer.
std::set<ReaderWriter*> rwOriginal;
// first attempt to load the file from existing ReaderWriter's
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
rwOriginal.insert(itr->get());
if ((*itr)->writeNode(node,fileName)) return true;
}
// now look for a plug-in to save the file.
std::string libraryName = createLibraryNameForFile(fileName);
if (Registry::instance()->loadLibrary(libraryName))
{
for(ReaderWriterList::iterator itr=_rwList.begin();
itr!=_rwList.end();
++itr)
{
if (rwOriginal.find(itr->get())==rwOriginal.end())
{
if ((*itr)->writeNode(node,fileName)) return true;
}
}
}
else
{
notify(NOTICE)<<"Warning: Could not find plugin to write file with extension ."
<<getLowerCaseFileExtension(fileName)<<endl;
}
notify(NOTICE)<<"Warning: Unable to write file "<<fileName<<endl;
return false;
}

69
src/osg/Scene.cpp Normal file
View File

@@ -0,0 +1,69 @@
#include "osg/Scene"
#include "osg/Registry"
#include "osg/Input"
#include "osg/Output"
using namespace osg;
RegisterObjectProxy<Scene> g_SceneProxy;
Scene::Scene()
{
_gstate = NULL;
}
Scene::~Scene()
{
if (_gstate) _gstate->unref();
}
void Scene::setGState(osg::GeoState* gstate)
{
if (gstate==_gstate) return;
if (_gstate) _gstate->unref();
_gstate = gstate;
if (_gstate) _gstate->ref();
}
bool Scene::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (fr[0].matchWord("Use"))
{
if (fr[1].isString()) {
GeoState* geostate = dynamic_cast<GeoState*>(fr.getObjectForUniqueID(fr[1].getStr()));
if (geostate) {
fr+=2;
_gstate = geostate;
_gstate->ref();
iteratorAdvanced = true;
}
}
}
if (GeoState* readState = static_cast<GeoState*>(GeoState::instance()->readClone(fr)))
{
_gstate = readState;
_gstate->ref();
iteratorAdvanced = true;
}
if (Group::readLocalData(fr)) iteratorAdvanced = true;
return iteratorAdvanced;
}
bool Scene::writeLocalData(Output& fw)
{
if (_gstate)
{
_gstate->write(fw);
}
Group::writeLocalData(fw);
return true;
}

270
src/osg/Seg.cpp Normal file
View File

@@ -0,0 +1,270 @@
#include "osg/Seg"
using namespace osg;
bool Seg::intersectAndClip(Vec3& s,Vec3& e,const BoundingBox& bb)
{
// compate s and e against the xMin to xMax range of bb.
if (s.x()<=e.x())
{
// trivial reject of segment wholely outside.
if (e.x()<bb.xMin()) return false;
if (s.x()>bb.xMax()) return false;
if (s.x()<bb.xMin())
{
// clip s to xMin.
s = s+(e-s)*(bb.xMin()-s.x())/(e.x()-s.x());
}
if (e.x()>bb.xMax())
{
// clip e to xMax.
e = s+(e-s)*(bb.xMax()-s.x())/(e.x()-s.x());
}
}
else
{
if (s.x()<bb.xMin()) return false;
if (e.x()>bb.xMax()) return false;
if (e.x()<bb.xMin())
{
// clip s to xMin.
e = s+(e-s)*(bb.xMin()-s.x())/(e.x()-s.x());
}
if (s.x()>bb.xMax())
{
// clip e to xMax.
s = s+(e-s)*(bb.xMax()-s.x())/(e.x()-s.x());
}
}
// compate s and e against the yMin to yMax range of bb.
if (s.y()<=e.y())
{
// trivial reject of segment wholely outside.
if (e.y()<bb.yMin()) return false;
if (s.y()>bb.yMax()) return false;
if (s.y()<bb.yMin())
{
// clip s to yMin.
s = s+(e-s)*(bb.yMin()-s.y())/(e.y()-s.y());
}
if (e.y()>bb.yMax())
{
// clip e to yMax.
e = s+(e-s)*(bb.yMax()-s.y())/(e.y()-s.y());
}
}
else
{
if (s.y()<bb.yMin()) return false;
if (e.y()>bb.yMax()) return false;
if (e.y()<bb.yMin())
{
// clip s to yMin.
e = s+(e-s)*(bb.yMin()-s.y())/(e.y()-s.y());
}
if (s.y()>bb.yMax())
{
// clip e to yMax.
s = s+(e-s)*(bb.yMax()-s.y())/(e.y()-s.y());
}
}
// compate s and e against the zMin to zMax range of bb.
if (s.z()<=e.z())
{
// trivial reject of segment wholely outside.
if (e.z()<bb.zMin()) return false;
if (s.z()>bb.zMax()) return false;
if (s.z()<bb.zMin())
{
// clip s to zMin.
s = s+(e-s)*(bb.zMin()-s.z())/(e.z()-s.z());
}
if (e.z()>bb.zMax())
{
// clip e to zMax.
e = s+(e-s)*(bb.zMax()-s.z())/(e.z()-s.z());
}
}
else
{
if (s.z()<bb.zMin()) return false;
if (e.z()>bb.zMax()) return false;
if (e.z()<bb.zMin())
{
// clip s to zMin.
e = s+(e-s)*(bb.zMin()-s.z())/(e.z()-s.z());
}
if (s.z()>bb.zMax())
{
// clip e to zMax.
s = s+(e-s)*(bb.zMax()-s.z())/(e.z()-s.z());
}
}
return true;
}
bool Seg::intersect(const BoundingBox& bb) const
{
if (!bb.isValid()) return false;
Vec3 s=_s,e=_e;
return intersectAndClip(s,e,bb);
}
bool Seg::intersect(const BoundingBox& bb,float& r1,float& r2) const
{
if (!bb.isValid()) return false;
Vec3 s=_s,e=_e;
return intersectAndClip(s,e,bb);
}
bool Seg::intersect(const BoundingSphere& bs,float& r1,float& r2) const
{
Vec3 sm = _s-bs._center;
float c = sm.length2()-bs._radius*bs._radius;
Vec3 se = _e-_s;
float a = se.length2();
float b = sm*se*2.0f;
float d = b*b-4.0f*a*c;
if (d<0.0f) return false;
d = sqrtf(d);
float div = 1.0f/(2.0f*a);
r1 = (-b-d)*div;
r2 = (-b+d)*div;
if (r1<=0.0f && r2<=0.0f) return false;
if (r1>=1.0f && r2>=1.0f) return false;
return true;
}
bool Seg::intersect(const BoundingSphere& bs) const
{
Vec3 sm = _s-bs._center;
float c = sm.length2()-bs._radius*bs._radius;
if (c<0.0f) return true;
Vec3 se = _e-_s;
float a = se.length2();
float b = (sm*se)*2.0f;
float d = b*b-4.0f*a*c;
if (d<0.0f) return false;
d = sqrtf(d);
float div = 1.0f/(2.0f*a);
float r1 = (-b-d)*div;
float r2 = (-b+d)*div;
if (r1<=0.0f && r2<=0.0f) return false;
if (r1>=1.0f && r2>=1.0f) return false;
return true;
}
bool Seg::intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& r)
{
if (v1==v2 || v2==v3 || v1==v3) return false;
Vec3 vse = _e-_s;
Vec3 v12 = v2-v1;
Vec3 n12 = v12^vse;
float ds12 = (_s-v1)*n12;
float d312 = (v3-v1)*n12;
if (d312>=0.0f)
{
if (ds12<0.0f) return false;
if (ds12>d312) return false;
}
else // d312 < 0
{
if (ds12>0.0f) return false;
if (ds12<d312) return false;
}
Vec3 v23 = v3-v2;
Vec3 n23 = v23^vse;
float ds23 = (_s-v2)*n23;
float d123 = (v1-v2)*n23;
if (d123>=0.0f)
{
if (ds23<0.0f) return false;
if (ds23>d123) return false;
}
else // d123 < 0
{
if (ds23>0.0f) return false;
if (ds23<d123) return false;
}
Vec3 v31 = v1-v3;
Vec3 n31 = v31^vse;
float ds31 = (_s-v3)*n31;
float d231 = (v2-v3)*n31;
if (d231>=0.0f)
{
if (ds31<0.0f) return false;
if (ds31>d231) return false;
}
else // d231 < 0
{
if (ds31>0.0f) return false;
if (ds31<d231) return false;
}
float r3 = ds12/d312;
float r1 = ds23/d123;
float r2 = ds31/d231;
// float rt = r1+r2+r3;
Vec3 in = v1*r1+v2*r2+v3*r3;
float length = vse.length();
vse /= length;
float d = (in-_s)*vse;
if (d<0.0f) return false;
if (d>length) return false;
r = d/length;
return true;
}

8
src/osg/Sequence.cpp Normal file
View File

@@ -0,0 +1,8 @@
#include "osg/Sequence"
#include "osg/Registry"
using namespace osg;
RegisterObjectProxy<Sequence> g_SequenceProxy;
// to be written :-)

87
src/osg/Switch.cpp Normal file
View File

@@ -0,0 +1,87 @@
#include "osg/Switch"
#include "osg/Registry"
#include "osg/Input"
#include "osg/Output"
#include <algorithm>
using namespace osg;
RegisterObjectProxy<Switch> g_SwitchProxy;
Switch::Switch()
{
_value = ALL_CHILDREN_OFF;
}
void Switch::traverse(NodeVisitor& nv)
{
switch(nv.getTraverseMode())
{
case(NodeVisitor::TRAVERSE_ALL_CHILDREN):
std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
break;
case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
switch(_value)
{
case(ALL_CHILDREN_ON):
std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
break;
case(ALL_CHILDREN_OFF):
return;
default:
if (_value>=0 && (unsigned int)_value<_children.size()) _children[_value]->accept(nv);
break;
}
break;
default:
break;
}
}
bool Switch::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (fr.matchSequence("value"))
{
if (fr[1].matchWord("ALL_CHILDREN_ON"))
{
_value = ALL_CHILDREN_ON;
iteratorAdvanced = true;
fr+=2;
}
else if (fr[1].matchWord("ALL_CHILDREN_ON"))
{
_value = ALL_CHILDREN_OFF;
iteratorAdvanced = true;
fr+=2;
}
else if (fr[1].isInt())
{
fr[1].getInt(_value);
iteratorAdvanced = true;
fr+=2;
}
}
if (Group::readLocalData(fr)) iteratorAdvanced = true;
return iteratorAdvanced;
}
bool Switch::writeLocalData(Output& fw)
{
fw.indent() << "value ";
switch(_value)
{
case(ALL_CHILDREN_ON): fw<<"ALL_CHILDREN_ON"<<endl;break;
case(ALL_CHILDREN_OFF): fw<<"ALL_CHILDREN_OFF"<<endl;break;
default: fw<<_value<<endl;break;
}
Group::writeLocalData(fw);
return true;
}

78
src/osg/TexEnv.cpp Normal file
View File

@@ -0,0 +1,78 @@
#include "osg/TexEnv"
#include "osg/Input"
#include "osg/Output"
using namespace osg;
TexEnv::TexEnv( void )
{
_mode = MODULATE;
}
TexEnv::~TexEnv( void )
{
}
TexEnv* TexEnv::instance()
{
static ref_ptr<TexEnv> s_TexEnv(new TexEnv);
return s_TexEnv.get();
}
void TexEnv::setMode( TexEnvMode mode )
{
_mode = (mode == DECAL ||
mode == MODULATE ||
mode == BLEND ) ?
mode : MODULATE;
}
void TexEnv::apply( void )
{
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, _mode);
}
bool TexEnv::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
TexEnvMode mode;
if (fr[0].matchWord("mode") && matchModeStr(fr[1].getStr(),mode))
{
_mode = mode;
fr+=2;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool TexEnv::matchModeStr(const char* str,TexEnvMode& mode)
{
if (strcmp(str,"DECAL")==0) mode = DECAL;
else if (strcmp(str,"MODULATE")==0) mode = MODULATE;
else if (strcmp(str,"BLEND")==0) mode = BLEND;
else return false;
return true;
}
const char* TexEnv::getModeStr(TexEnvMode mode)
{
switch(mode)
{
case(DECAL): return "DECAL";
case(MODULATE): return "MODULATE";
case(BLEND): return "BLEND";
}
return "";
}
bool TexEnv::writeLocalData(Output& fw)
{
fw.indent() << "mode " << getModeStr(_mode) << endl;
return true;
}

89
src/osg/TexGen.cpp Normal file
View File

@@ -0,0 +1,89 @@
#include "osg/TexGen"
#include "osg/Input"
#include "osg/Output"
using namespace osg;
TexGen::TexGen( void )
{
_mode = OBJECT_LINEAR;
}
TexGen::~TexGen( void )
{
}
TexGen* TexGen::instance()
{
static ref_ptr<TexGen> s_texgen(new TexGen);
return s_texgen.get();
}
bool TexGen::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
TexGenMode mode;
if (fr[0].matchWord("mode") && matchModeStr(fr[1].getStr(),mode))
{
_mode = mode;
fr+=2;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool TexGen::matchModeStr(const char* str,TexGenMode& mode)
{
if (strcmp(str,"EYE_LINEAR")==0) mode = EYE_LINEAR;
else if (strcmp(str,"OBJECT_LINEAR")==0) mode = OBJECT_LINEAR;
else if (strcmp(str,"SPHERE_MAP")==0) mode = SPHERE_MAP;
else return false;
return true;
}
const char* TexGen::getModeStr(TexGenMode mode)
{
switch(mode)
{
case(EYE_LINEAR): return "EYE_LINEAR";
case(OBJECT_LINEAR): return "OBJECT_LINEAR";
case(SPHERE_MAP): return "SPHERE_MAP";
}
return "";
}
bool TexGen::writeLocalData(Output& fw)
{
fw.indent() << "mode " << getModeStr(_mode) << endl;
return true;
}
void TexGen::enable( void )
{
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
}
void TexGen::disable( void )
{
glDisable( GL_TEXTURE_GEN_S );
glDisable( GL_TEXTURE_GEN_T );
}
void TexGen::apply( void )
{
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, _mode );
}

25
src/osg/TexMat.cpp Normal file
View File

@@ -0,0 +1,25 @@
#include "osg/GL"
#include "osg/TexMat"
using namespace osg;
TexMat::TexMat( void )
{
}
TexMat::~TexMat( void )
{
}
TexMat* TexMat::instance()
{
static ref_ptr<TexMat> s_texmat(new TexMat);
return s_texmat.get();
}
void TexMat::apply( void )
{
glMatrixMode( GL_TEXTURE );
glLoadMatrixf( (GLfloat *)_mat );
}

257
src/osg/Texture.cpp Normal file
View File

@@ -0,0 +1,257 @@
#include "osg/Texture"
#include "osg/Input"
#include "osg/Output"
#include "osg/Registry"
#include "osg/Image"
#include "osg/Referenced"
#include "osg/Notify"
using namespace osg;
Texture::Texture()
{
_handle = 0;
_wrap_s = CLAMP;
_wrap_t = CLAMP;
_wrap_r = CLAMP;
_min_filter = NEAREST_MIPMAP_LINEAR;
_mag_filter = LINEAR;
}
Texture::~Texture()
{
if (_handle!=0) glDeleteTextures( 1, &_handle );
}
Texture* Texture::instance()
{
static ref_ptr<Texture> s_texture(new Texture);
return s_texture.get();
}
bool Texture::readLocalData(Input& fr)
{
bool iteratorAdvanced = false;
if (fr[0].matchWord("file") && fr[1].isString())
{
_image = fr.readImage(fr[1].getStr());
fr += 2;
iteratorAdvanced = true;
}
WrapMode wrap;
if (fr[0].matchWord("wrap_s") && matchWrapStr(fr[1].getStr(),wrap))
{
_wrap_s = wrap;
fr+=2;
iteratorAdvanced = true;
}
if (fr[0].matchWord("wrap_t") && matchWrapStr(fr[1].getStr(),wrap))
{
_wrap_t = wrap;
fr+=2;
iteratorAdvanced = true;
}
if (fr[0].matchWord("wrap_r") && matchWrapStr(fr[1].getStr(),wrap))
{
_wrap_r = wrap;
fr+=2;
iteratorAdvanced = true;
}
FilterMode filter;
if (fr[0].matchWord("min_filter") && matchFilterStr(fr[1].getStr(),filter))
{
_min_filter = filter;
fr+=2;
iteratorAdvanced = true;
}
if (fr[0].matchWord("mag_filter") && matchFilterStr(fr[1].getStr(),filter))
{
_mag_filter = filter;
fr+=2;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool Texture::writeLocalData(Output& fw)
{
if (_image.valid())
{
fw.indent() << "file \""<<_image->getFileName()<<"\""<<endl;
}
fw.indent() << "wrap_s " << getWrapStr(_wrap_s) << endl;
fw.indent() << "wrap_t " << getWrapStr(_wrap_t) << endl;
fw.indent() << "wrap_r " << getWrapStr(_wrap_r) << endl;
fw.indent() << "min_filter " << getFilterStr(_min_filter) << endl;
fw.indent() << "mag_filter " << getFilterStr(_mag_filter) << endl;
return true;
}
bool Texture::matchWrapStr(const char* str,WrapMode& wrap)
{
if (strcmp(str,"CLAMP")==0) wrap = CLAMP;
else if (strcmp(str,"REPEAT")==0) wrap = REPEAT;
else return false;
return true;
}
const char* Texture::getWrapStr(WrapMode wrap)
{
switch(wrap)
{
case(CLAMP): return "CLAMP";
case(REPEAT): return "REPEAT";
}
return "";
}
bool Texture::matchFilterStr(const char* str,FilterMode& filter)
{
if (strcmp(str,"NEAREST")==0) filter = NEAREST;
else if (strcmp(str,"LINEAR")==0) filter = LINEAR;
else if (strcmp(str,"NEAREST_MIPMAP_NEAREST")==0) filter = NEAREST_MIPMAP_NEAREST;
else if (strcmp(str,"LINEAR_MIPMAP_NEAREST")==0) filter = LINEAR_MIPMAP_NEAREST;
else if (strcmp(str,"NEAREST_MIPMAP_LINEAR")==0) filter = NEAREST_MIPMAP_LINEAR;
else if (strcmp(str,"LINEAR_MIPMAP_LINEAR")==0) filter = LINEAR_MIPMAP_LINEAR;
else return false;
return true;
}
const char* Texture::getFilterStr(FilterMode filter)
{
switch(filter)
{
case(NEAREST): return "NEAREST";
case(LINEAR): return "LINEAR";
case(NEAREST_MIPMAP_NEAREST): return "NEAREST_MIPMAP_NEAREST";
case(LINEAR_MIPMAP_NEAREST): return "LINEAR_MIPMAP_NEAREST";
case(NEAREST_MIPMAP_LINEAR): return "NEAREST_MIPMAP_LINEAR";
case(LINEAR_MIPMAP_LINEAR): return "LINEAR_MIPMAP_LINEAR";
}
return "";
}
void Texture::setImage(Image* image)
{
if (_handle!=0) glDeleteTextures( 1, &_handle );
_handle = 0;
_image = image;
}
void Texture::setWrap(WrapParameter which, WrapMode wrap)
{
switch( which )
{
case WRAP_S : _wrap_s = wrap; break;
case WRAP_T : _wrap_t = wrap; break;
case WRAP_R : _wrap_r = wrap; break;
default : notify(WARN)<<"Error: invalid 'which' passed Texture::setWrap("<<(unsigned int)which<<","<<(unsigned int)wrap<<")"<<endl; break;
}
}
Texture::WrapMode Texture::getWrap(WrapParameter which) const
{
switch( which )
{
case WRAP_S : return _wrap_s;
case WRAP_T : return _wrap_t;
case WRAP_R : return _wrap_r;
default : notify(WARN)<<"Error: invalid 'which' passed Texture::getWrap(which)"<<endl; return _wrap_s;
}
}
void Texture::setFilter(FilterParameter which, FilterMode filter)
{
switch( which )
{
case MIN_FILTER : _min_filter = filter; break;
case MAG_FILTER : _mag_filter = filter; break;
default : notify(WARN)<<"Error: invalid 'which' passed Texture::setFilter("<<(unsigned int)which<<","<<(unsigned int)filter<<")"<<endl; break;
}
}
Texture::FilterMode Texture::getFilter(FilterParameter which) const
{
switch( which )
{
case MIN_FILTER : return _min_filter;
case MAG_FILTER : return _mag_filter;
default : notify(WARN)<<"Error: invalid 'which' passed Texture::getFilter(which)"<<endl; return _min_filter;
}
}
void Texture::enable( void )
{
glEnable( GL_TEXTURE_2D );
}
void Texture::disable( void )
{
glDisable( GL_TEXTURE_2D );
}
void Texture::apply( void )
{
if(_handle!=0)
{
glBindTexture( GL_TEXTURE_2D, _handle );
}
else if (_image.valid())
{
_image->ensureDimensionsArePowerOfTwo();
glPixelStorei(GL_UNPACK_ALIGNMENT,_image->packing());
glGenTextures( 1, &_handle );
glBindTexture( GL_TEXTURE_2D, _handle );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _wrap_s );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _wrap_t );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _min_filter);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _mag_filter);
if( _min_filter == LINEAR || _min_filter == NEAREST )
{
glTexImage2D( GL_TEXTURE_2D, 0, _image->internalFormat(),
_image->s(), _image->t(), 0,
(GLenum)_image->pixelFormat(),
(GLenum)_image->dataType(),
_image->data() );
}
else
{
gluBuild2DMipmaps( GL_TEXTURE_2D, _image->internalFormat(),
_image->s(),_image->t(),
(GLenum)_image->pixelFormat(), (GLenum)_image->dataType(),
_image->data() );
}
glBindTexture( GL_TEXTURE_2D, _handle );
}
}

205
src/osg/Timer.cpp Normal file
View File

@@ -0,0 +1,205 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <osg/Timer>
using namespace osg;
#ifdef WIN32 // [
#include <windows.h>
#include <winbase.h>
int Timer::inited = 0;
double Timer::cpu_mhz = 0.0;
void Timer::init( void )
{
Timer_t start_time = tick();
Sleep (1000);
Timer_t end_time = tick();
cpu_mhz = (double)(end_time-start_time)*1e-6;
inited = 1;
}
Timer::Timer( void )
{
if( !inited ) init();
}
Timer::~Timer( void )
{
}
double Timer::delta_s( Timer_t t1, Timer_t t2 )
{
Timer_t delta = t2 - t1;
return (((double)delta/cpu_mhz)*1e-6);
}
double Timer::delta_m( Timer_t t1, Timer_t t2 )
{
Timer_t delta = t2 - t1;
return (((double)delta/cpu_mhz)*1e-3);
}
Timer_t Timer::delta_u( Timer_t t0, Timer_t t1 )
{
return (Timer_t)((double)(t1 - t0)/cpu_mhz);
}
Timer_t Timer::delta_n( Timer_t t0, Timer_t t1 )
{
return (Timer_t)((double)(t1 - t0) * 1e3/cpu_mhz);
}
#endif // ]
#ifdef __linux // [
#include <unistd.h>
#include <sys/mman.h>
int Timer::inited = 0;
double Timer::cpu_mhz = 0.0;
void Timer::init( void )
{
char buff[128];
FILE *fp = fopen( "/proc/cpuinfo", "r" );
while( fgets( buff, sizeof( buff ), fp ) > 0 )
{
if( !strncmp( buff, "cpu MHz", strlen( "cpu MHz" )))
{
char *ptr = buff;
while( ptr && *ptr != ':' ) ptr++;
if( ptr )
{
ptr++;
sscanf( ptr, "%lf", &cpu_mhz );
}
break;
}
}
fclose( fp );
inited = 1;
}
Timer::Timer( void )
{
if( !inited ) init();
}
Timer::~Timer( void )
{
}
double Timer::delta_s( Timer_t t1, Timer_t t2 )
{
Timer_t delta = t2 - t1;
return ((double)delta/cpu_mhz*1e-6);
}
double Timer::delta_m( Timer_t t1, Timer_t t2 )
{
Timer_t delta = t2 - t1;
return ((double)delta/cpu_mhz*1e-3);
}
Timer_t Timer::delta_u( Timer_t t0, Timer_t t1 )
{
return (Timer_t)((double)(t1 - t0)/cpu_mhz);
}
Timer_t Timer::delta_n( Timer_t t0, Timer_t t1 )
{
return (Timer_t)((double)(t1 - t0) * 1e3/cpu_mhz);
}
#endif // ]
#ifdef __sgi // [
#include <unistd.h>
#include <sys/syssgi.h>
#include <sys/immu.h>
#include <sys/mman.h>
unsigned long Timer::dummy = 0;
Timer::Timer( void )
{
__psunsigned_t phys_addr, raddr;
unsigned int cycleval;
volatile unsigned long counter_value, *iotimer_addr;
int fd, poffmask;
poffmask = getpagesize() - 1;
phys_addr = syssgi( SGI_QUERY_CYCLECNTR, &cycleval );
microseconds_per_click = (double)cycleval/1e6;
nanoseconds_per_click = (double)cycleval/1e3;
raddr = phys_addr & ~poffmask;
clk = &dummy;
if( (fd = open( "/dev/mmem", O_RDONLY )) < 0 )
{
perror( "/dev/mmem" );
return;
}
iotimer_addr = (volatile unsigned long *)mmap(
(void *)0L,
(size_t)poffmask,
(int)PROT_READ,
(int)MAP_PRIVATE, fd, (off_t)raddr);
iotimer_addr = (unsigned long *)(
(__psunsigned_t)iotimer_addr + (phys_addr & poffmask)
);
cycleCntrSize = syssgi( SGI_CYCLECNTR_SIZE );
if( cycleCntrSize > 32 )
++iotimer_addr;
clk = (unsigned long *)iotimer_addr;
}
Timer::~Timer( void )
{
}
double Timer::delta_s( Timer_t t1, Timer_t t2 )
{
Timer_t delta = t2 - t1;
return ((double)delta * microseconds_per_click*1e-6);
}
double Timer::delta_m( Timer_t t1, Timer_t t2 )
{
Timer_t delta = t2 - t1;
return ((double)delta * microseconds_per_click*1e-3);
}
Timer_t Timer::delta_u( Timer_t t1, Timer_t t2 )
{
Timer_t delta = t2 - t1;
return (Timer_t)((double)delta * microseconds_per_click);
}
Timer_t Timer::delta_n( Timer_t t1, Timer_t t2 )
{
unsigned long delta = t2 - t1;
return (Timer_t )((double)delta * nanoseconds_per_click);
}
#endif // ]

46
src/osg/Transparency.cpp Normal file
View File

@@ -0,0 +1,46 @@
#include "osg/OSG"
#include "osg/Transparency"
using namespace osg;
Transparency::Transparency( void )
{
_source_factor = SRC_ALPHA;
_destination_factor = ONE_MINUS_SRC_ALPHA;
}
Transparency::~Transparency( void )
{
}
Transparency* Transparency::instance()
{
static ref_ptr<Transparency> s_transparency(new Transparency);
return s_transparency.get();
}
void Transparency::enable( void )
{
glEnable( GL_BLEND );
}
void Transparency::disable( void )
{
glDisable( GL_BLEND );
}
void Transparency::apply( void )
{
glBlendFunc( (GLenum)_source_factor, (GLenum)_destination_factor );
}
void Transparency::setFunction( int source, int destination )
{
_source_factor = source;
_destination_factor = destination;
}

11
src/osg/Version.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include "osg/Version"
const char* osgGetVersion()
{
return "0.8.34";
}
const char* osgGetLibraryName()
{
return "Open Scene Graph Library";
}

View File

@@ -0,0 +1,144 @@
#include "osgGLUT/GLUTEventAdapter"
#include "GL/glut.h"
using namespace osgGLUT;
// default to no mouse buttons being pressed.
unsigned int GLUTEventAdapter::_s_accumulatedButtonMask = 0;
int GLUTEventAdapter::_s_Xmin = 0;
int GLUTEventAdapter::_s_Xmax = 1280;
int GLUTEventAdapter::_s_Ymin = 0;
int GLUTEventAdapter::_s_Ymax = 1024;
int GLUTEventAdapter::_s_mx = 0;
int GLUTEventAdapter::_s_my = 0;
GLUTEventAdapter::GLUTEventAdapter()
{
_eventType = NONE; // adaptor does not encapsulate any events.
_key = -1; // set to 'invalid' key value.
_button = -1; // set to 'invalid' button value.
_mx = -1; // set to 'invalid' position value.
_my = -1; // set to 'invalid' position value.
_buttonMask = 0; // default to no mouse buttons being pressed.
_time = 0.0f; // default to no time has been set.
copyStaticVariables();
}
void GLUTEventAdapter::copyStaticVariables()
{
_buttonMask = _s_accumulatedButtonMask;
_Xmin = _s_Xmin;
_Xmax = _s_Xmax;
_Ymin = _s_Ymin;
_Ymax = _s_Ymax;
_mx = _s_mx;
_my = _s_my;
}
void GLUTEventAdapter::setWindowSize(int Xmin, int Ymin, int Xmax, int Ymax)
{
_s_Xmin = Xmin;
_s_Xmax = Xmax;
_s_Ymin = Ymin;
_s_Ymax = Ymax;
}
void GLUTEventAdapter::setButtonMask(unsigned int buttonMask)
{
_s_accumulatedButtonMask = buttonMask;
}
void GLUTEventAdapter::adaptResize(float time, int Xmin, int Ymin, int Xmax, int Ymax)
{
setWindowSize(Xmin,Ymin,Xmax,Ymax);
_eventType = RESIZE;
_time = time;
copyStaticVariables();
}
/** method for adapting mouse motion events whilst mouse buttons are pressed.*/
void GLUTEventAdapter::adaptMouseMotion(float time, int x, int y)
{
_eventType = DRAG;
_time = time;
_s_mx = x;
_s_my = y;
copyStaticVariables();
}
/** method for adapting mouse motion events whilst no mouse button are pressed.*/
void GLUTEventAdapter::adaptMousePassiveMotion(float time, int x, int y)
{
_eventType = MOVE;
_time = time;
_s_mx = x;
_s_my = y;
copyStaticVariables();
}
/** method for adapting mouse button pressed/released events.*/
void GLUTEventAdapter::adaptMouse(float time, int button, int state, int x, int y)
{
_time = time;
if( state == GLUT_DOWN )
{
_eventType = PUSH;
_button = button;
switch(button)
{
case(GLUT_LEFT_BUTTON): _s_accumulatedButtonMask = _s_accumulatedButtonMask | LEFT_BUTTON; break;
case(GLUT_MIDDLE_BUTTON): _s_accumulatedButtonMask = _s_accumulatedButtonMask | MIDDLE_BUTTON; break;
case(GLUT_RIGHT_BUTTON): _s_accumulatedButtonMask = _s_accumulatedButtonMask | RIGHT_BUTTON; break;
}
}
else if( state == GLUT_UP )
{
_eventType = RELEASE;
_button = button;
switch(button)
{
case(GLUT_LEFT_BUTTON): _s_accumulatedButtonMask = _s_accumulatedButtonMask & ~LEFT_BUTTON; break;
case(GLUT_MIDDLE_BUTTON): _s_accumulatedButtonMask = _s_accumulatedButtonMask & ~MIDDLE_BUTTON; break;
case(GLUT_RIGHT_BUTTON): _s_accumulatedButtonMask = _s_accumulatedButtonMask & ~RIGHT_BUTTON; break;
}
}
_s_mx = x;
_s_my = y;
copyStaticVariables();
}
/** method for adapting keyboard events.*/
void GLUTEventAdapter::adaptKeyboard(float time, unsigned char key, int x, int y )
{
_eventType = KEYBOARD;
_time = time;
_key = key;
_s_mx = x;
_s_my = y;
copyStaticVariables();
}
/** method for adapting frame events, i.e. iddle/display callback.*/
void GLUTEventAdapter::adaptFrame(float time)
{
_eventType = FRAME;
_time = time;
copyStaticVariables();
}

0
src/osgGLUT/Makedepend Normal file
View File

26
src/osgGLUT/Makefile Normal file
View File

@@ -0,0 +1,26 @@
#!smake
include ../../Make/makedefs
C++FILES = \
GLUTEventAdapter.cpp\
Version.cpp\
Viewer.cpp\
TARGET_BASENAME = osgGLUT
LIBS = -ldl
LIB = ../../lib/lib$(TARGET_BASENAME).so
#LIB = ../../lib/lib$(TARGET_BASENAME).a
TARGET_LIB_FILES = lib$(TARGET_BASENAME).so
TARGET_INCLUDE_FILES = \
osgGLUT/Export\
osgGLUT/Viewer\
osgGLUT/GLUTEventAdapter\
C++FLAGS += -I ../../include
include ../../Make/makerules

12
src/osgGLUT/Version.cpp Executable file
View File

@@ -0,0 +1,12 @@
#include "osgGLUT/Version"
const char* osgGLUTGetVersion()
{
return "0.8.34";
}
const char* osgGLUTGetLibraryName()
{
return "Open Scene Graph GLUT Library";
}

741
src/osgGLUT/Viewer.cpp Normal file
View File

@@ -0,0 +1,741 @@
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <math.h>
#include "osgGLUT/Viewer"
#include "osgGLUT/GLUTEventAdapter"
#include <osg/OSG>
#include <osg/GeoState>
#include <osg/Scene>
#include <osg/Switch>
#include <osg/Billboard>
#include <osg/LOD>
#include <osg/DCS>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Output>
#include <osg/Input>
#include <osg/Registry>
#include <osg/NodeVisitor>
#include <osg/Seg>
#include <osg/Notify>
#include <osgUtil/RenderVisitor>
#include <osgUtil/IntersectVisitor>
#include <osgUtil/DisplayListVisitor>
#include <osgUtil/TrackballManipulator>
#include <osgUtil/FlightManipulator>
#include <osgUtil/DriveManipulator>
#include <osg/Version>
#include <osgUtil/Version>
#ifdef WIN32
#define USE_FLTK
#define USE_GLUT
#endif
#include <GL/glut.h>
#ifdef WIN32
#include <sys/timeb.h>
#else
#endif
#include <osg/Timer>
osg::Timer g_timer;
osg::Timer_t g_initTime;
static GLenum polymodes [] = { GL_FILL, GL_LINE, GL_POINT };
using namespace osgGLUT;
Viewer* Viewer::s_theViewer = 0;
Viewer::Viewer()
{
s_theViewer = this;
fullscreen = false;
_saved_ww = ww = 1024,
_saved_wh = wh = 768;
mx = ww/2,
my = wh/2;
mbutton = 0;
polymode = 0;
texture = 1;
backface = 1;
lighting = 1;
flat_shade = 0;
_printStats = false;
#ifdef SGV_USE_RTFS
fs = new RTfs( RTFS_MODE_RTC_SPIN );
frame_rate = 16;
fs->setUpdateRate( frame_rate );
#endif
_viewFrustumCullingActive = true;
_smallFeatureCullingActive = true;
_two_sided_lighting=0;
_useDisplayLists = true;
_saveFileName = "saved_model.osg";
_sceneView = new osgUtil::SceneView;
_sceneView->setDefaults();
registerCameraManipulator(new osgUtil::TrackballManipulator);
registerCameraManipulator(new osgUtil::FlightManipulator);
registerCameraManipulator(new osgUtil::DriveManipulator);
osg::notify(osg::INFO)<<"Scene Graph Viewer (sgv)"<<endl;
osg::notify(osg::INFO)<<" '"<<osgGetLibraryName()<<"' Version "<<osgGetVersion()<<endl;
osg::notify(osg::INFO)<<" '"<<osgUtilGetLibraryName()<<"' Version "<<osgUtilGetVersion()<<endl;
_initialTick = _timer.tick();
_frameTick = _initialTick;
}
Viewer::~Viewer()
{
}
bool Viewer::init(osg::Node* rootnode)
{
bool saveModel = false;
GLUTEventAdapter::setWindowSize( 0,0,ww, wh );
GLUTEventAdapter::setButtonMask(0);
_sceneView->setViewport(0,0,ww,wh);
glutInitWindowSize( ww, wh );
//glutInit( &argc, argv ); // I moved this into main to avoid passing
// argc and argv to the Viewer
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE);
glutCreateWindow( "OSG Viewer" );
glutReshapeFunc( reshapeCB );
glutVisibilityFunc( visibilityCB );
glutDisplayFunc( displayCB );
glutKeyboardFunc( keyboardCB );
glutMouseFunc( mouseCB );
glutMotionFunc( mouseMotionCB );
glutPassiveMotionFunc( mousePassiveMotionCB );
#ifdef USE_FLTK
// required to specify the idle function when using FLTK.
// GLUT and FLTK GLUT differ in that GLUT implicitly calls visibilityFunc
// on window creation, while FLTK calls it when the windows is iconised
// or deiconsied but not on window creation.
visibilityCB(GLUT_VISIBLE);
#endif
if (_useDisplayLists)
{
// traverse the scene graph setting up all osg::GeoSet's so they will use
// OpenGL display lists.
osgUtil::DisplayListVisitor dlv(osgUtil::DisplayListVisitor::SWITCH_ON_DISPLAY_LISTS);
rootnode->accept(dlv);
}
_sceneView->setSceneData(rootnode);
if (saveModel)
{
osg::saveNodeFile(*rootnode, _saveFileName.c_str());
}
selectCameraManipulator(0);
osg::ref_ptr<GLUTEventAdapter> ea = new GLUTEventAdapter;
_cameraManipulator->home(*ea,*this);
// std::string name = Registry::instance()->createLibraryNameForExt("osg");
// Registry::instance()->loadLibrary(name);
// Registry::instance()->closeLibrary(name);
return true;
}
void Viewer::registerCameraManipulator(osgUtil::CameraManipulator* cm)
{
_cameraManipList.push_back(cm);
}
void Viewer::selectCameraManipulator(unsigned int pos)
{
if (pos>=_cameraManipList.size()) return;
_cameraManipulator = _cameraManipList[pos];
_cameraManipulator->setCamera(_sceneView->getCamera());
_cameraManipulator->setNode(_sceneView->getSceneData());
osg::ref_ptr<GLUTEventAdapter> ea = new GLUTEventAdapter;
_cameraManipulator->init(*ea,*this);
}
void Viewer::needWarpPointer(int x,int y)
{
glutWarpPointer(x,y);
}
bool Viewer::update()
{
osg::ref_ptr<GLUTEventAdapter> ea = new GLUTEventAdapter;
ea->adaptFrame(clockSeconds());
if (_cameraManipulator->update(*ea,*this))
{
// osg::notify(osg::INFO) << "Handled update frame"<<endl;
}
updateFrameTick();
if (_printStats) osg::notify(osg::NOTICE) << "\033[0;0H";
if (_printStats) osg::notify(osg::NOTICE) << "frameRate() = "<<frameRate()<<endl;
return true;
}
bool Viewer::traverse()
{
return true;
}
bool Viewer::draw()
{
// osg::notify(osg::INFO) << "Viewer::draw("<<mx<<","<<my<<") scale("<<bsphere._radius/(float)ww<<")"<<endl;
osg::Timer_t beforeTraversal = _timer.tick();
_sceneView->cull();
float timeTraversal = _timer.delta_m(beforeTraversal,_timer.tick());
if (_printStats) osg::notify(osg::NOTICE) << "Time of Cull Traversal "<<timeTraversal<<"ms "<<endl;
osg::Timer_t beforeDraw = _timer.tick();
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,_two_sided_lighting);
_sceneView->draw();
float timeDraw = _timer.delta_m(beforeDraw,_timer.tick());
if (_printStats) osg::notify(osg::NOTICE) << "Time of Draw "<<timeDraw<<"ms "<<endl;
return true;
}
void Viewer::displayCB()
{
s_theViewer->display();
}
void Viewer::reshapeCB(GLint w, GLint h)
{
s_theViewer->reshape(w, h);
}
void Viewer::visibilityCB( int state )
{
s_theViewer->visibility(state);
}
void Viewer::mouseCB(int button, int state, int x, int y)
{
s_theViewer->mouse(button, state, x, y);
}
void Viewer::mouseMotionCB(int x, int y)
{
s_theViewer->mouseMotion(x,y);
}
void Viewer::mousePassiveMotionCB(int x, int y)
{
s_theViewer->mousePassiveMotion(x,y);
}
void Viewer::keyboardCB(unsigned char key, int x, int y)
{
s_theViewer->keyboard(key,x,y);
}
void Viewer::display()
{
// application traverasal.
update();
draw();
glutSwapBuffers();
// cout << "Time elapsed "<<_timer.delta_s(_initialTick,_timer.tick())<<endl;
#ifdef SGV_USE_RTFS
fs->frame();
#endif
}
void Viewer::reshape(GLint w, GLint h)
{
ww = w;
wh = h;
_sceneView->setViewport(0,0,ww,wh);
osg::ref_ptr<GLUTEventAdapter> ea = new GLUTEventAdapter;
ea->adaptResize(clockSeconds(),0,0,ww,wh);
if (_cameraManipulator->update(*ea,*this))
{
// osg::notify(osg::INFO) << "Handled reshape "<<endl;
}
}
void Viewer::visibility(int state)
{
if (state == GLUT_VISIBLE)
glutIdleFunc( displayCB );
else
glutIdleFunc(0L);
}
void Viewer::mouseMotion(int x, int y)
{
osg::ref_ptr<GLUTEventAdapter> ea = new GLUTEventAdapter;
ea->adaptMouseMotion(clockSeconds(),x,y);
if (_cameraManipulator->update(*ea,*this))
{
// osg::notify(osg::INFO) << "Handled mouseMotion "<<ea->_buttonMask<<" x="<<ea->_mx<<" y="<<ea->_my<<endl;
}
mx = x;
my = y;
}
void Viewer::mousePassiveMotion(int x, int y)
{
osg::ref_ptr<GLUTEventAdapter> ea = new GLUTEventAdapter;
ea->adaptMousePassiveMotion(clockSeconds(),x,y);
if (_cameraManipulator->update(*ea,*this))
{
// osg::notify(osg::INFO) << "Handled mousePassiveMotion "<<ea->_buttonMask<<" x="<<ea->_mx<<" y="<<ea->_my<<endl;
}
}
void Viewer::mouse(int button, int state, int x, int y)
{
osg::ref_ptr<GLUTEventAdapter> ea = new GLUTEventAdapter;
ea->adaptMouse(clockSeconds(),button,state,x,y);
if (_cameraManipulator->update(*ea,*this))
{
// osg::notify(osg::INFO) << "Handled mouse "<<ea->_buttonMask<<" x="<<ea->_mx<<" y="<<ea->_my<<endl;
}
}
void Viewer::keyboard(unsigned char key, int x, int y)
{
osg::ref_ptr<GLUTEventAdapter> ea = new GLUTEventAdapter;
ea->adaptKeyboard(clockSeconds(),key,x,y);
if (_cameraManipulator->update(*ea,*this)) return;
if (key>='1' && key<='3')
{
int pos = key-'1';
selectCameraManipulator(pos);
}
switch( key )
{
case '/' :
if (_sceneView->getLODBias()>0.5) _sceneView->setLODBias(_sceneView->getLODBias()/1.5f);
break;
case '*' :
if (_sceneView->getLODBias()<30) _sceneView->setLODBias(_sceneView->getLODBias()*1.5f);
break;
case '+' :
#ifdef SGV_USE_RTFS
frame_rate <<= 1;
fs->stop();
fs->setUpdateRate( frame_rate );
fs->start();
#endif
break;
case '-' :
#ifdef SGV_USE_RTFS
frame_rate >>= 1;
if( frame_rate < 1 ) frame_rate = 1;
fs->stop();
fs->setUpdateRate( frame_rate );
fs->start();
#endif
break;
case 'd' :
_useDisplayLists = !_useDisplayLists;
if (_useDisplayLists)
{
// traverse the scene graph setting up all osg::GeoSet's so they will use
// OpenGL display lists.
osgUtil::DisplayListVisitor dlv(osgUtil::DisplayListVisitor::SWITCH_ON_DISPLAY_LISTS);
_sceneView->getSceneData()->accept(dlv);
osg::notify(osg::NOTICE) << "Switched on use of OpenGL Display Lists."<<endl;
}
else
{
// traverse the scene graph setting up all osg::GeoSet's so they will use
// OpenGL display lists.
osgUtil::DisplayListVisitor dlv(osgUtil::DisplayListVisitor::SWITCH_OFF_DISPLAY_LISTS);
_sceneView->getSceneData()->accept(dlv);
osg::notify(osg::NOTICE) << "Switched off use of OpenGL Display Lists."<<endl;
}
break;
case 'p' :
_printStats = !_printStats;
break;
case 's' :
flat_shade = 1 - flat_shade ;
if( flat_shade )
glShadeModel( GL_FLAT );
else
glShadeModel( GL_SMOOTH );
break;
case 'b' :
backface = 1 - backface;
if( backface )
_sceneView->getGlobalState()->setMode(osg::GeoState::FACE_CULL,osg::GeoState::ON);
else
_sceneView->getGlobalState()->setMode(osg::GeoState::FACE_CULL,osg::GeoState::OVERRIDE_OFF);
break;
case 'l' :
lighting = 1 - lighting ;
if( lighting )
_sceneView->getGlobalState()->setMode(osg::GeoState::LIGHTING,osg::GeoState::ON);
else
_sceneView->getGlobalState()->setMode(osg::GeoState::LIGHTING,osg::GeoState::OVERRIDE_OFF);
break;
case 'L' :
{
osgUtil::SceneView::LightingMode lm= _sceneView->getLightingMode();
switch(lm)
{
case(osgUtil::SceneView::HEADLIGHT) : lm = osgUtil::SceneView::SKY_LIGHT; break;
case(osgUtil::SceneView::SKY_LIGHT) : lm = osgUtil::SceneView::NO_SCENEVIEW_LIGHT; break;
case(osgUtil::SceneView::NO_SCENEVIEW_LIGHT) : lm = osgUtil::SceneView::HEADLIGHT; break;
}
_sceneView->setLightingMode(lm);
break;
}
case 't' :
texture = 1 - texture;
if (texture)
_sceneView->getGlobalState()->setMode(osg::GeoState::TEXTURE,osg::GeoState::INHERIT);
else
_sceneView->getGlobalState()->setMode(osg::GeoState::TEXTURE,osg::GeoState::OVERRIDE_OFF);
break;
case 'T' :
_two_sided_lighting = 1 - _two_sided_lighting;
break;
case 'w' :
polymode = (polymode+1)%3;
glPolygonMode( GL_FRONT_AND_BACK, polymodes[polymode] );
break;
case 'f' :
fullscreen = !fullscreen;
if (fullscreen)
{
_saved_ww = ww;
_saved_wh = wh;
glutFullScreen();
} else
{
//glutPositionWindow(wx,wy);
glutReshapeWindow(_saved_ww,_saved_wh);
}
break;
case 'o' :
if (_sceneView->getSceneData() && osg::Registry::instance()->writeNode(*_sceneView->getSceneData(),_saveFileName))
{
osg::notify(osg::NOTICE) << "Saved scene to '"<<_saveFileName<<"'"<<endl;
}
break;
case 'c' :
_smallFeatureCullingActive = !_smallFeatureCullingActive;
if (_smallFeatureCullingActive)
{
osg::notify(osg::NOTICE) << "Small feature culling switched on "<<endl;
}
else
{
osg::notify(osg::NOTICE) << "Small feature culling switched off "<<endl;
}
_sceneView->getRenderVisitor()->setCullingActive(osgUtil::RenderVisitor::SMALL_FEATURE_CULLING,_smallFeatureCullingActive);
break;
case 'C' :
_viewFrustumCullingActive = !_viewFrustumCullingActive;
_sceneView->getRenderVisitor()->setCullingActive(osgUtil::RenderVisitor::VIEW_FRUSTUM_CULLING,_viewFrustumCullingActive);
if (_viewFrustumCullingActive)
{
osg::notify(osg::NOTICE) << "View frustum culling switched on "<<endl;
}
else
{
osg::notify(osg::NOTICE) << "View frustum culling switched off "<<endl;
}
break;
case '?' :
case 'h' :
help(osg::notify(osg::NOTICE));
break;
case 'i' :
case 'r' :
{
osg::notify(osg::NOTICE) << "***** Intersecting **************"<< endl;
osg::Vec3 near_point,far_point;
if (!_sceneView->projectWindowXYIntoObject(x,wh-y,near_point,far_point))
{
osg::notify(osg::NOTICE) << "Failed to calculate intersection ray."<<endl;
return;
}
osg::ref_ptr<osg::Seg> seg = new osg::Seg;
seg->set(near_point,far_point);
osg::notify(osg::NOTICE) << "start("<<seg->start()<<") end("<<seg->end()<<")"<<endl;
osgUtil::IntersectVisitor iv;
iv.addSeg(seg.get());
float startTime = clockSeconds();
_sceneView->getSceneData()->accept(iv);
float endTime = clockSeconds();
osg::notify(osg::NOTICE) << "Time for interesection = "<<(endTime-startTime)*1000<<"ms"<<endl;
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(seg.get());
for(osgUtil::IntersectVisitor::HitList::iterator hitr=hitList.begin();
hitr!=hitList.end();
++hitr)
{
osg::Vec3 ip = hitr->_intersectPoint;
osg::Vec3 in = hitr->_intersectNormal;
osg::Geode* geode = hitr->_geode;
osg::notify(osg::NOTICE) << " Itersection Point ("<<ip<<") Normal ("<<in<<")"<<endl;
if (hitr->_matrix)
{
osg::Vec3 ipEye = ip*(*(hitr->_matrix));
osg::Vec3 inEye = (in+ip)*(*(hitr->_matrix))-ipEye;
inEye.normalize();
if (geode) osg::notify(osg::NOTICE) << "Geode '"<<geode->getName()<<endl;
osg::notify(osg::NOTICE) << " Eye Itersection Point ("<<ipEye<<") Normal ("<<inEye<<")"<<endl;
}
if (key=='r' && geode)
{
// remove geoset..
osg::GeoSet* gset = hitr->_geoset;
osg::notify(osg::NOTICE) << " geoset ("<<gset<<") "<<geode->removeGeoSet(gset)<<")"<<endl;
}
}
}
osg::notify(osg::NOTICE) << endl << endl;
}
break;
case 27 : // Escape
exit(0);
break;
}
}
void Viewer::help(ostream& fout)
{
fout <<endl
<<"Scene Graph Viewer (sgv) keyboard bindings:"<<endl
<<endl
<<"1 Select the trackball camera manipulator."<<endl
<<" Left mouse button - rotate,"<<endl
<<" Middle (or Left & Right) mouse button - pan,"<<endl
<<" Right mouse button - zoom."<<endl
<<"2 Select the flight camera manipulator."<<endl
<<" Left mouse button - speed up,"<<endl
<<" Middle (or Left & Right) mouse button - stop,"<<endl
<<" Right mouse button - slow down, reverse."<<endl
<<" Move mouse left to roll left, right to roll right."<<endl
<<" Move mouse back (down) to pitch nose up, forward to pitch down."<<endl
<<" In mode Q, the default, selected by pressing 'q'"<<endl
<<" The flight path is yawed automatically into the turn to"<<endl
<<" produce a similar effect as flying an aircaft."<<endl
<<" In mode A, selected by pressing 'a'"<<endl
<<" The flight path is not yawed automatically into the turn,"<<endl
<<" producing a similar effect as space/marine flight."<<endl
<<"3 Select the drive camera manipulator."<<endl
<<" In mode Q, the default, selected by pressing 'q'"<<endl
<<" Move mouse left to turn left, right to turn right."<<endl
<<" Move mouse back (down) to reverse, forward to drive forward."<<endl
<<" In mode A, selected by pressing 'a'"<<endl
<<" Move mouse left to turn left, right to turn right."<<endl
<<" Left mouse button - speed up,"<<endl
<<" Middle (or Left & Right) mouse button - stop,"<<endl
<<" Right mouse button - slow down, reverse."<<endl
<<endl
<<"+ Half the frame delay which speeds up the frame rate on Linux and Windows."<<endl
<<"- Double the frame delay and therefore reduce the frame rate on Linux"<<endl
<<" and Windows."<<endl
<<endl
<<"/ Divide the Level-Of-Detail (LOD) bias by 1.5, to encourage the"<<endl
<<" selection of more complex LOD children."<<endl
<<"* Multiple the Level-of-Detail (LOD) bias by 1.5, to encourage the"<<endl
<<" selection of less complex LOD children."<<endl
<<endl
<<"c Toggle Small Feature Culling on or off."<<endl
<<"C Toggle View Frustum Culling on or off."<<endl
<<"d Toggle use of OpenGL's display lists."<<endl
<<"b Toggle OpenGL's backface culling."<<endl
<<"t Toggle OpenGL texturing on or off."<<endl
<<"T Toggle OpenGL two-sided lighting on or off."<<endl
<<"l Toggle OpenGL lighting on or off."<<endl
<<"L Toggle SceneView lighting mode between HEADLIGHT, SKY_LIGHT"<<endl
<<" and NO_SCENEVIEW_LIGHT."<<endl
<<"s Toggle OpenGL shade model between flat and smooth shading."<<endl
<<"w Toggle OpenGL polygon mode between solid, wireframe and points modes."<<endl
<<endl
<<"i Calculate and report the intersections with the scene under the"<<endl
<<" current mouse x and mouse y position."<<endl
<<endl
<<"r Calculate and report the intersections with the scene under the"<<endl
<<" current mouse x and mouse y position and delete the nearest"<<endl
<<" interesected geoset."<<endl
<<endl
<<"p Print frame rate statistics on each frame."<<endl
<<"o Output the loaded scene to 'saved_model.osg'."<<endl
<<"?/h Print out sgv's keyboard bindings."<<endl
<<"f Toggle between fullscreen and the previous window size. Note, GLUT"<<endl
<<" fullscreen works properly on Windows and Irix, but on Linux"<<endl
<<" it just maximizes the window and leaves the window's borders."<<endl
<<"Space Reset scene to the default view."<<endl
<<"Esc Exit sgv."<<endl;
}
osg::Timer_t Viewer::clockTick()
{
return _timer.tick();
}
osg::Timer_t Viewer::frameTick()
{
return _frameTick;
}
// update time from the current frame update and the previous one.
osg::Timer_t Viewer::updateFrameTick()
{
_lastFrameTick = _frameTick;
_frameTick = _timer.tick();
return _frameTick;
}
bool Viewer::run()
{
updateFrameTick();
#ifdef SGV_USE_RTFS
fs->start();
#endif
glutMainLoop();
return true;
}

32
src/osgPlugins/Makefile Normal file
View File

@@ -0,0 +1,32 @@
#!smake
SHELL=/bin/sh
#DIRS = fly flt png
#DIRS = fly flt pic png jpeg tga tiff gif png
DIRS = fly osgtgz tgz zip flt pfb pic png jpeg tga tiff gif png
all :
for f in $(DIRS) ; do cd $$f; make ; cd ..; done
clean :
for f in $(DIRS) ; do cd $$f; make clean; cd ..; done
clobber :
for f in $(DIRS) ; do cd $$f; make clobber; cd ..; done
depend :
for f in $(DIRS) ; do cd $$f; make depend; cd ..; done
to_unix :
for f in $(DIRS) ; do cd $$f; to_unix Makefile Makefile; cd ..; done
for f in $(DIRS) ; do cd $$f; make to_unix; cd ..; done
install :
for f in $(DIRS) ; do cd $$f; make install; cd ..; done
instlinks :
for f in $(DIRS) ; do cd $$f; make instlinks; cd ..; done
instclean :
for f in $(DIRS) ; do cd $$f; make instclean; cd ..; done

View File

@@ -0,0 +1,136 @@
// BoundingVolumeRecords.cpp
#include "flt.h"
#include "Registry.h"
#include "BoundingVolumeRecords.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// BoundingBoxRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<BoundingBoxRecord> g_BoundingBoxProxy;
BoundingBoxRecord::BoundingBoxRecord()
{
}
// virtual
BoundingBoxRecord::~BoundingBoxRecord()
{
}
void BoundingBoxRecord::endian()
{
}
////////////////////////////////////////////////////////////////////
//
// BoundingSphereRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<BoundingSphereRecord> g_BoundingSphereProxy;
BoundingSphereRecord::BoundingSphereRecord()
{
}
// virtual
BoundingSphereRecord::~BoundingSphereRecord()
{
}
void BoundingSphereRecord::endian()
{
}
////////////////////////////////////////////////////////////////////
//
// BoundingCylinderRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<BoundingCylinderRecord> g_BoundingCylinderProxy;
BoundingCylinderRecord::BoundingCylinderRecord()
{
}
// virtual
BoundingCylinderRecord::~BoundingCylinderRecord()
{
}
void BoundingCylinderRecord::endian()
{
}
////////////////////////////////////////////////////////////////////
//
// BoundingVolumeCenterRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<BoundingVolumeCenterRecord> g_BoundingVolumeCenterProxy;
BoundingVolumeCenterRecord::BoundingVolumeCenterRecord()
{
}
// virtual
BoundingVolumeCenterRecord::~BoundingVolumeCenterRecord()
{
}
void BoundingVolumeCenterRecord::endian()
{
}
////////////////////////////////////////////////////////////////////
//
// BoundingVolumeOrientationRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<BoundingVolumeOrientationRecord> g_BoundingVolumeOrientationProxy;
BoundingVolumeOrientationRecord::BoundingVolumeOrientationRecord()
{
}
// virtual
BoundingVolumeOrientationRecord::~BoundingVolumeOrientationRecord()
{
}
void BoundingVolumeOrientationRecord::endian()
{
}

View File

@@ -0,0 +1,225 @@
// BoundingVolumeRecords.h
#ifndef __FLT_BOUNDING_VOLUME_RECORDS_H
#define __FLT_BOUNDING_VOLUME_RECORDS_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
////////////////////////////////////////////////////////////////////
//
// BoundingBoxRecord
//
////////////////////////////////////////////////////////////////////
typedef struct BoundingBoxTag
{
SRecHeader RecHeader;
#if 0
Int 4 Reserved
Double 8 x coordinate of lowest corner
Double 8 y coordinate of lowest corner
Double 8 z coordinate of lowest corner
Double 8 x coordinate of highest corner
Double 8 y coordinate of highest corner
Double 8 z coordinate of highest corner
#endif
} SBoundingBox;
class BoundingBoxRecord : public AncillaryRecord
{
public:
BoundingBoxRecord();
virtual Record* clone() const { return new BoundingBoxRecord(); }
virtual const char* className() const { return "BoundingBoxRecord"; }
virtual int classOpcode() const { return BOUNDING_BOX_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~BoundingBoxRecord();
virtual void endian();
};
////////////////////////////////////////////////////////////////////
//
// BoundingSphereRecord
//
////////////////////////////////////////////////////////////////////
typedef struct BoundingSphereTag
{
SRecHeader RecHeader;
#if 0
Unsigned Int 2 Length of the record
Int 4 Reserved
Double 8 Radius of the sphere
#endif
} SBoundingSphere;
class BoundingSphereRecord : public AncillaryRecord
{
public:
BoundingSphereRecord();
virtual Record* clone() const { return new BoundingSphereRecord(); }
virtual const char* className() const { return "BoundingSphereRecord"; }
virtual int classOpcode() const { return BOUNDING_SPHERE_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~BoundingSphereRecord();
virtual void endian();
};
////////////////////////////////////////////////////////////////////
//
// BoundingCylinderRecord
//
////////////////////////////////////////////////////////////////////
typedef struct BoundingCylinderTag
{
SRecHeader RecHeader;
#if 0
Int 4 Reserved
Double 8 Radius of the cylinder base
Double 8 Height of the cylinder
#endif
} SBoundingCylinder;
class BoundingCylinderRecord : public AncillaryRecord
{
public:
BoundingCylinderRecord();
virtual Record* clone() const { return new BoundingCylinderRecord(); }
virtual const char* className() const { return "BoundingCylinderRecord"; }
virtual int classOpcode() const { return BOUNDING_CYLINDER_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~BoundingCylinderRecord();
virtual void endian();
};
////////////////////////////////////////////////////////////////////
//
// BoundingVolumeCenterRecord
//
////////////////////////////////////////////////////////////////////
typedef struct BoundingVolumeCenterTag
{
SRecHeader RecHeader;
#if 0
Int 4 Reserved
Double 8 x coordinate of center
Double 8 y coordinate of center
Double 8 z coordinate of center
#endif
} SBoundingVolumeCenter;
class BoundingVolumeCenterRecord : public AncillaryRecord
{
public:
BoundingVolumeCenterRecord();
virtual Record* clone() const { return new BoundingVolumeCenterRecord(); }
virtual const char* className() const { return "BoundingVolumeCenterRecord"; }
virtual int classOpcode() const { return BOUNDING_VOLUME_CENTER_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~BoundingVolumeCenterRecord();
virtual void endian();
};
////////////////////////////////////////////////////////////////////
//
// BoundingVolumeOrientationRecord
//
////////////////////////////////////////////////////////////////////
typedef struct BoundingVolumeOrientationTag
{
SRecHeader RecHeader;
#if 0
Int 2 Bounding Volume Orientation Opcode 109
Unsigned Int 2 Length of the record
Int 4 Reserved
Double 8 Yaw angle
Double 8 Pitch angle
Double 8 Roll angle
#endif
} SBoundingVolumeOrientation;
class BoundingVolumeOrientationRecord : public AncillaryRecord
{
public:
BoundingVolumeOrientationRecord();
virtual Record* clone() const { return new BoundingVolumeOrientationRecord(); }
virtual const char* className() const { return "BoundingVolumeOrientationRecord"; }
virtual int classOpcode() const { return BOUNDING_VOLUME_ORIENTATION_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~BoundingVolumeOrientationRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,55 @@
// ColorPaletteRecord.cpp
#include "flt.h"
#include "Input.h"
#include "Registry.h"
#include "ColorPaletteRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// MaterialPaletteRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<ColorPaletteRecord> g_ColorPaletteRecordProxy;
ColorPaletteRecord::ColorPaletteRecord()
{
}
// virtual
ColorPaletteRecord::~ColorPaletteRecord()
{
}
// virtual
void ColorPaletteRecord::endian()
{
SColorPalette* pSColor = (SColorPalette*)getData();
int nOffset = sizeof(SColorPalette);
if (nOffset < getSize())
{
int n = 0;
ENDIAN( pSColor->nNames );
while ((n++ < pSColor->nNames) && (nOffset < getSize()))
{
SColorName* pName = (SColorName*)((char*)getData())+nOffset;
ENDIAN( pName->swSize );
ENDIAN( pName->nIndex );
nOffset += pName->swSize;
};
}
}

View File

@@ -0,0 +1,62 @@
// ColorPaletteRecord.h
#ifndef __FLT_COLOR_PALETTE_RECORD_H
#define __FLT_COLOR_PALETTE_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
////////////////////////////////////////////////////////////////////
//
// ColorPaletteRecord
//
////////////////////////////////////////////////////////////////////
struct SColorName
{
uint16 swSize; // Length of color name entry
int16 Reserved1;
int16 nIndex; // Color entry index
int16 Reserved2;
char szName[1]; // Color name string (variable length, up to 80 bytes)
};
struct SColorPalette
{
SRecHeader RecHeader;
char szReserved[128]; // Reserved
color32 Colors[1024]; // Color 0 - 1023
int32 nNames;
// Followed by SColorName. SColorName is of valiable length!
};
class ColorPaletteRecord : public AncillaryRecord
{
public:
ColorPaletteRecord();
virtual Record* clone() const { return new ColorPaletteRecord(); }
virtual const char* className() const { return "ColorPaletteRecord"; }
virtual int classOpcode() const { return COLOR_PALETTE_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
SColorPalette* getData() const { return (SColorPalette*)_pData; }
protected:
virtual ~ColorPaletteRecord();
virtual void endian();
};
}; // end namespace flt
#endif // __FLT_COLOR_PALETTE_RECORD_H

View File

@@ -0,0 +1,37 @@
// CommentRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "CommentRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// CommentRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<CommentRecord> g_CommentRecordProxy;
CommentRecord::CommentRecord()
{
}
// virtual
CommentRecord::~CommentRecord()
{
}
// virtual
void CommentRecord::endian()
{
}

View File

@@ -0,0 +1,53 @@
// CommentRecord.h
#ifndef __FLT_COMMENT_RECORD_H
#define __FLT_COMMENT_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
////////////////////////////////////////////////////////////////////
//
// CommentRecord
//
////////////////////////////////////////////////////////////////////
typedef struct CommentTag
{
SRecHeader RecHeader;
// TODO
} SComment;
class CommentRecord : public AncillaryRecord
{
public:
CommentRecord();
virtual Record* clone() const { return new CommentRecord(); }
virtual const char* className() const { return "CommentRecord"; }
virtual int classOpcode() const { return COMMENT_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~CommentRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,21 @@
// ControlRecord.cpp
#include "Registry.h"
#include "ControlRecord.h"
using namespace flt;
RegisterRecordProxy<PushLevelRecord> g_PushLevelProxy;
RegisterRecordProxy<PopLevelRecord> g_PopLevelProxy;
RegisterRecordProxy<PushSubfaceRecord> g_PushSubfaceProxy;
RegisterRecordProxy<PopSubfaceRecord> g_PopSubfaceProxy;
RegisterRecordProxy<PushExtensionRecord> g_PushExtensionProxy;
RegisterRecordProxy<PopExtensionRecord> g_PopExtensionProxy;

View File

@@ -0,0 +1,125 @@
// ControlRecord.h
#ifndef __FLT_CONTROL_RECORD_H
#define __FLT_CONTROL_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
////////////////////////////////////////////////////////////////////
//
// PushLevelRecord
//
////////////////////////////////////////////////////////////////////
class PushLevelRecord : public ControlRecord
{
public:
PushLevelRecord() {}
virtual Record* clone() const { return new PushLevelRecord(); }
virtual const char* className() const { return "PushLevelRecord"; }
virtual int classOpcode() const { return PUSH_LEVEL_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~PushLevelRecord() {}
};
class PopLevelRecord : public ControlRecord
{
public:
PopLevelRecord() {}
virtual Record* clone() const { return new PopLevelRecord(); }
virtual const char* className() const { return "PopLevelRecord"; }
virtual int classOpcode() const { return POP_LEVEL_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~PopLevelRecord() {}
};
class PushSubfaceRecord : public ControlRecord
{
public:
PushSubfaceRecord() {}
virtual Record* clone() const { return new PushSubfaceRecord(); }
virtual const char* className() const { return "PushSubfaceRecord"; }
virtual int classOpcode() const { return PUSH_SUBFACE_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~PushSubfaceRecord() {}
};
class PopSubfaceRecord : public ControlRecord
{
public:
PopSubfaceRecord() {}
virtual Record* clone() const { return new PopSubfaceRecord(); }
virtual const char* className() const { return "PopSubfaceRecord"; }
virtual int classOpcode() const { return POP_SUBFACE_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~PopSubfaceRecord() {}
};
class PushExtensionRecord : public ControlRecord
{
public:
PushExtensionRecord() {}
virtual Record* clone() const { return new PushExtensionRecord(); }
virtual const char* className() const { return "PushExtensionRecord"; }
virtual int classOpcode() const { return PUSH_EXTENSION_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~PushExtensionRecord() {}
};
class PopExtensionRecord : public ControlRecord
{
public:
PopExtensionRecord() {}
virtual Record* clone() const { return new PopExtensionRecord(); }
virtual const char* className() const { return "PopExtensionRecord"; }
virtual int classOpcode() const { return POP_EXTENSION_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~PopExtensionRecord() {}
};
}; // end namespace flt
#endif // __FLT_CONTROL_RECORD_H

View File

@@ -0,0 +1,52 @@
// DofRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "DofRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// DofRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<DofRecord> g_DofProxy;
DofRecord::DofRecord()
{
}
// virtual
DofRecord::~DofRecord()
{
}
void DofRecord::endian()
{
SDegreeOfFreedom *pSDof = (SDegreeOfFreedom*)getData();
ENDIAN( pSDof->diReserved );
pSDof->OriginLocalDOF.endian();
pSDof->PointOnXaxis.endian();
pSDof->PointInXYplane.endian();
pSDof->dfZ.endian();
pSDof->dfY.endian();
pSDof->dfX.endian();
pSDof->dfPitch.endian();
pSDof->dfRoll.endian();
pSDof->dfYaw.endian();
pSDof->dfZscale.endian();
pSDof->dfYscale.endian();
pSDof->dfXscale.endian();
ENDIAN( pSDof->dwFlags );
}

View File

@@ -0,0 +1,87 @@
// DofRecord.h
#ifndef __FLT_DOF_RECORD_H
#define __FLT_DOF_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
struct SRange
{
float64 _dfMin; // Minimum value with respect to the local coord system
float64 _dfMax; // Maximum value with respect to the local coordsystem
float64 _dfCurrent; // Current value with respect to the local coord system
float64 _dfIncrement; // Increment
inline float64 minRange() { return _dfMin; }
inline float64 maxRange() { return _dfMax; }
inline float64 current() { return _dfCurrent; }
inline float64 increment() { return _dfIncrement; }
void endian() {
ENDIAN( _dfMin );
ENDIAN( _dfMax );
ENDIAN( _dfCurrent );
ENDIAN( _dfIncrement );
}
};
typedef struct DegreeOfFreedomTag
{
SRecHeader RecHeader;
char szIdent[8]; // 7 char ASCII ID; 0 terminates
int32 diReserved; // Reserved
float64x3 OriginLocalDOF; // Origin (x,y,z) of the DOF's local coordinate system
float64x3 PointOnXaxis; // Point (x,y,z) on the x-axis of the DOF's local coord system
float64x3 PointInXYplane; // Point (x,y,z) in xy plane of the DOF's local coord system
SRange dfZ; // Legal z values with respect to the local coord system
SRange dfY; // Legal y values with respect to the local coord system
SRange dfX; // Legal x values with respect to the local coord system
SRange dfPitch; // Legal pitch values (rotation about the x-axis)
SRange dfRoll; // Legal roll values( rotation about the y-axis)
SRange dfYaw; // Legal yaw values (rotation about the z-axis)
SRange dfZscale; // Legal z scale values (about local origin)
SRange dfYscale; // Legal y scale values about local origin)
SRange dfXscale; // Legal x scale values (about local origin)
uint32 dwFlags; // Flags, bits from left to right (see OF doc)
} SDegreeOfFreedom;
class DofRecord : public PrimNodeRecord
{
public:
DofRecord();
virtual Record* clone() const { return new DofRecord(); }
virtual const char* className() const { return "DofRecord"; }
virtual int classOpcode() const { return DOF_OP; }
virtual int sizeofData() const { return sizeof(SDegreeOfFreedom); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
SDegreeOfFreedom* getData() const { return (SDegreeOfFreedom*)_pData; }
virtual const std::string getName( void ) const { return std::string(getData()->szIdent); }
protected:
virtual ~DofRecord();
virtual void endian();
// virtual bool readLocalData(Input& fr);
// virtual bool writeLocalData(Output& fw);
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,39 @@
// ExtensionRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "ExtensionRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// ExtensionRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<ExtensionRecord> g_ExtensionProxy;
ExtensionRecord::ExtensionRecord()
{
}
// virtual
ExtensionRecord::~ExtensionRecord()
{
}
void ExtensionRecord::endian()
{
SExtension *pExtension = (SExtension*)getData();
// VALID_RECORD(SHeader, pRecHdr)
ENDIAN( pExtension->code );
}

View File

@@ -0,0 +1,59 @@
// ExtensionRecord.h
#ifndef __FLT_EXTENSION_RECORD_H
#define __FLT_EXTENSION_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
class Input;
};
namespace flt {
////////////////////////////////////////////////////////////////////
//
// ExtensionRecord
//
////////////////////////////////////////////////////////////////////
typedef struct ExtensionTag
{
SRecHeader RecHeader;
char szIdent[8]; // 7 char ASCII ID; 0 terminates
char site[8]; // Site ID - Unique site name
char reserved; // Reserved
char revision; // Revision - site specific
uint16 code; // Record code - site specific
// char n/a; // Extended data - site specific
}SExtension;
class ExtensionRecord : public PrimNodeRecord
{
public:
ExtensionRecord();
virtual Record* clone() const { return new ExtensionRecord(); }
virtual const char* className() const { return "ExtensionRecord"; }
virtual int classOpcode() const { return EXTENSION_OP; }
virtual int sizeofData() const { return sizeof(SExtension); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~ExtensionRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,52 @@
// ExternalRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "FltFile.h"
#include "ExternalRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// ExternalRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<ExternalRecord> g_ExternalProxy;
ExternalRecord::ExternalRecord()
{
_pExternal = NULL;
}
// virtual
ExternalRecord::~ExternalRecord()
{
if (_pExternal)
_pExternal->unref();
}
void ExternalRecord::setExternal(FltFile* pExternal)
{
if (_pExternal)
_pExternal->unref();
_pExternal = pExternal;
_pExternal->ref();
}
void ExternalRecord::endian()
{
SExternalReference *pSExternal = (SExternalReference*)getData();
ENDIAN( pSExternal->diFlags );
}

View File

@@ -0,0 +1,63 @@
// ExternalRecord.h
#ifndef __FLT_EXTERNAL_RECORD_H
#define __FLT_EXTERNAL_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
struct SExternalReference
{
SRecHeader RecHeader;
char szPath[200]; // 199 char ASCII Path; 0 terminates
uint8 swReserved[4]; // Reserved
int32 diFlags; // Flags (bits from left to right)
// 0 = Color Palette Override
// 1 = Material Palette Override
// 2 = Texture Palette Override
// 3 = Line Palette Override
// 4 = Sound Palette Override
// 5 = Light source Palette Override
// 6-31 Spare
int16 iReserved; // Reserved
};
class ExternalRecord : public PrimNodeRecord
{
public:
ExternalRecord();
virtual Record* clone() const { return new ExternalRecord(); }
virtual const char* className() const { return "ExternalRecord"; }
virtual int classOpcode() const { return EXTERNAL_REFERENCE_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
SExternalReference* getData() const { return (SExternalReference*)_pData; }
void setExternal(FltFile* pExternal);
FltFile* getExternal() { return _pExternal; }
const std::string getFilename( void ) const { return std::string(getData()->szPath); }
protected:
virtual ~ExternalRecord();
// virtual bool readLocalData(Input& fr);
// virtual bool writeLocalData(Output& fw);
virtual void endian();
FltFile* _pExternal;
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,292 @@
// FaceRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "FaceRecord.h"
#include "Input.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// FaceRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<FaceRecord> g_FaceProxy;
FaceRecord::FaceRecord()
{
}
// virtual
FaceRecord::~FaceRecord()
{
}
int FaceRecord::numberOfVertices()
{
for (int n=0; n < getNumChildren(); n++)
{
VertexListRecord* pSVertexList = (VertexListRecord*)getChild(n);
if (pSVertexList && pSVertexList->isOfType(VERTEX_LIST_OP))
return pSVertexList->numberOfVertices();
}
return 0;
}
int FaceRecord::getVertexPoolOffset(int index)
{
for (int n=0; n < getNumChildren(); n++)
{
VertexListRecord* pSVertexList = (VertexListRecord*)getChild(n);
if (pSVertexList && pSVertexList->isOfType(VERTEX_LIST_OP))
return pSVertexList->getVertexPoolOffset(index);
}
return 0;
}
void FaceRecord::endian()
{
SFace *pSFace = (SFace*)getData();
ENDIAN( pSFace->diIRColor );
ENDIAN( pSFace->iObjectRelPriority );
ENDIAN( pSFace->wPrimaryNameIndex );
ENDIAN( pSFace->wSecondaryNameIndex );
ENDIAN( pSFace->iDetailTexturePattern );
ENDIAN( pSFace->iTexturePattern );
ENDIAN( pSFace->iMaterial );
ENDIAN( pSFace->iSurfaceMaterial );
ENDIAN( pSFace->iFeature );
ENDIAN( pSFace->diIRMaterial );
ENDIAN( pSFace->wTransparency );
ENDIAN( pSFace->diFlags );
// ENDIAN( pSFace->PrimaryPackedColor );
// ENDIAN( pSFace->SecondaryPackedColor );
ENDIAN( pSFace->iTextureMapIndex );
ENDIAN( pSFace->dwPrimaryColorIndex );
ENDIAN( pSFace->dwAlternateColorIndex );
}
// virtual
bool FaceRecord::readLocalData(Input& fr)
{
if (!PrimNodeRecord::readLocalData(fr))
return false;
//
// Check for subfaces
//
Record* pRec;
if (!(pRec=fr.readCreateRecord())) return false;
if (pRec->getOpcode() != PUSH_SUBFACE_OP)
return fr.rewindLast();
while ((pRec=fr.readCreateRecord()))
{
if (pRec->getOpcode()==POP_SUBFACE_OP) return true;
if (pRec->isPrimaryNode())
{
addChild(pRec);
if (!((PrimNodeRecord*)pRec)->readLocalData(fr))
return false;
}
}
return (pRec != NULL);
}
////////////////////////////////////////////////////////////////////
//
// VertexListRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<VertexListRecord> g_VertexListProxy;
VertexListRecord::VertexListRecord()
{
}
// virtual
VertexListRecord::~VertexListRecord()
{
}
int VertexListRecord::numberOfVertices()
{
return getBodyLength()/4;
}
int VertexListRecord::getVertexPoolOffset(int index)
{
SSingleVertexList *pSVertexList = (SSingleVertexList*)getData();
if ((index >= 0) && (index < numberOfVertices()))
return pSVertexList->diSOffset[index];
return 0;
}
void VertexListRecord::endian()
{
SSingleVertexList *pSVertexList = (SSingleVertexList*)getData();
int nNumberOfVertices = numberOfVertices();
for(int i=0; i < nNumberOfVertices; i++)
{
ENDIAN( pSVertexList->diSOffset[i] );
}
}
// virtual
bool VertexListRecord::readLocalData(Input& fr)
{
// A vertex node is a leaf node in the database and
// therefore cannot have any children.
return true;
}
////////////////////////////////////////////////////////////////////
//
// MorphVertexListRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<MorphVertexListRecord> g_MorphVertexListRecordProxy;
MorphVertexListRecord::MorphVertexListRecord()
{
}
// virtual
MorphVertexListRecord::~MorphVertexListRecord()
{
}
int MorphVertexListRecord::numberOfVertices()
{
return getBodyLength()/8;
}
void MorphVertexListRecord::endian()
{
// SMorphVertexList *pSMorpVertexList = (SMorphVertexList*)getData();
}
// virtual
bool MorphVertexListRecord::readLocalData(Input& fr)
{
// A vertex node is a leaf node in the database and
// therefore cannot have any children.
return true;
}
////////////////////////////////////////////////////////////////////
//
// UnknownListRecord
//
////////////////////////////////////////////////////////////////////
//RegisterRecordProxy<UnknownListRecord> g_UnknownListProxy;
UnknownListRecord::UnknownListRecord()
{
}
// virtual
UnknownListRecord::~UnknownListRecord()
{
}
void UnknownListRecord::endian()
{
}
// virtual
bool UnknownListRecord::readLocalData(Input& fr)
{
// A vertex node is a leaf node in the database and
// therefore cannot have any children.
return true;
}
////////////////////////////////////////////////////////////////////
//
// VectorRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<VectorRecord> g_VectorProxy;
VectorRecord::VectorRecord()
{
}
// virtual
VectorRecord::~VectorRecord()
{
}
void VectorRecord::endian()
{
SVector *pSVector = (SVector*)getData();
pSVector->Vec.endian();
}

View File

@@ -0,0 +1,288 @@
// FaceRecord.h
#ifndef __FLT_FACE_RECORD_H
#define __FLT_FACE_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
////////////////////////////////////////////////////////////////////
//
// FaceRecord
//
////////////////////////////////////////////////////////////////////
struct SFace
{
SRecHeader RecHeader;
char szIdent[8]; // 7 char ASCII ID; 0 terminates
int32 diIRColor; // IR Color Code
int16 iObjectRelPriority; // Polygon relative priority
uint8 swDrawFlag; // How to draw the polygon
// = 0 Draw solid backfaced
// = 1 Draw solid no backface
// = 2 Draw wireframe and not closed
// = 3 Draw closed wireframe
// = 4 Surround with wireframe in alternate color
// = 8 Omni-directional light
// = 9 Unidirectional light
// = 10 Bidirectional light
uint8 swTexWhite; // if TRUE, draw textured polygon white (see note 1 below)
uint16 wPrimaryNameIndex; // Color name index
uint16 wSecondaryNameIndex; // Alternate color name index
uint8 swNotUsed; // Not used
uint8 swTemplateTrans; // Set template transparency
// = 0 None
// = 1 Fixed
// = 2 Axis type rotate
// = 4 Point rotate
int16 iDetailTexturePattern; // Detail texture pattern no. -1 if none
int16 iTexturePattern; // Texture pattern no. -1 if none
int16 iMaterial; // Material code [0-63]. -1 if none
int16 iSurfaceMaterial; // Surface material code (for DFAD)
int16 iFeature; // Feature ID (for DFAD)
int32 diIRMaterial; // IR Material codes
uint16 wTransparency; // Transparency
// = 0 opaque
// = 65535 for totally clear
uint8 swInfluenceLODGen; // LOD Generation Control
uint8 swLinestyle; // Linestyle Index
int32 diFlags; // Flags (bits from to right)
// 0 = Terrain
// 1 = No Color
// 2 = No Alt Color
// 3 = Packed color
// 4 = Terrain culture cutout (footprint)
// 5 = Hidden (not drawn)
// 6-31 Spare
uint8 swLightMode; // Lightmode
// = 0 use face color, not illuminated
// = 1 use vertex color, not illuminated
// = 2 use face color and vertex normal
// = 3 use vertex color and vertex normal
uint8 swReserved1[7]; // Reserved
color32 PrimaryPackedColor; // Packed Color Primary (A, B, G, R)
color32 SecondaryPackedColor; // Packed Color Secondary (A, B, G, R)
int16 iTextureMapIndex; // Texture mapping index
int16 iReserved2;
uint32 dwPrimaryColorIndex;
uint32 dwAlternateColorIndex;
int16 iReserved3[2];
};
class FaceRecord : public PrimNodeRecord
{
public:
enum DrawFlag {
SOLID_BACKFACED = 0,
SOLID_NO_BACKFACE = 1,
WIREFRAME_NOT_CLOSED = 2,
WIREFRAME_CLOSED = 3,
SURROUND_ALTERNATE_COLOR = 4,
OMNIDIRECTIONAL_LIGHT = 8,
UNIDIRECTIONAL_LIGHT = 9,
BIDIRECTIONAL_LIGHT = 10
};
enum LightMode {
FACE_COLOR = 0,
VERTEX_COLOR = 1,
FACE_COLOR_LIGHTING = 2,
VERTEX_COLOR_LIGHTING = 3,
};
FaceRecord();
virtual Record* clone() const { return new FaceRecord(); }
virtual const char* className() const { return "FaceRecord"; }
virtual int classOpcode() const { return FACE_OP; }
virtual int sizeofData() const { return sizeof(SFace); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
virtual SFace* getData() const { return (SFace*)_pData; }
virtual const std::string getName( void ) const { return std::string(getData()->szIdent); }
int numberOfVertices();
int getVertexPoolOffset(int index);
protected:
virtual ~FaceRecord();
virtual void endian();
virtual bool readLocalData(Input& fr);
// virtual bool writeLocalData(Output& fw);
};
////////////////////////////////////////////////////////////////////
//
// VertexListRecord
//
////////////////////////////////////////////////////////////////////
typedef struct SingleVertexListTag
{
SRecHeader RecHeader;
int32 diSOffset[1]; // Byte offset to this vertex record in vertex table,
// the actual vertex of the face
} SSingleVertexList;
class VertexListRecord : public PrimNodeRecord
{
public:
VertexListRecord();
virtual Record* clone() const { return new VertexListRecord(); }
virtual const char* className() const { return "VertexListRecord"; }
virtual int classOpcode() const { return VERTEX_LIST_OP; }
virtual int sizeofData() const { return sizeof(SSingleVertexList); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
virtual SSingleVertexList* getData() const { return (SSingleVertexList*)_pData; }
int numberOfVertices();
int getVertexPoolOffset(int index);
protected:
virtual ~VertexListRecord();
virtual bool readLocalData(Input& fr);
// virtual bool writeLocalData(Output& fw);
virtual void endian();
};
////////////////////////////////////////////////////////////////////
//
// MorphVertexListRecord
//
////////////////////////////////////////////////////////////////////
typedef struct MorphVertexListTag
{
SRecHeader RecHeader;
uint32 dwOffset0; // Byte offset into vertex palette of the 0% vertex
uint32 dwOffset100; // Byte offset into vertex palette of the 100% vertex
} SMorphVertexList;
class MorphVertexListRecord : public PrimNodeRecord
{
public:
MorphVertexListRecord();
virtual Record* clone() const { return new MorphVertexListRecord(); }
virtual const char* className() const { return "MorphVertexListRecord"; }
virtual int classOpcode() const { return MORPH_VERTEX_LIST_OP; }
virtual int sizeofData() const { return sizeof(SMorphVertexList); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
virtual SMorphVertexList* getData() const { return (SMorphVertexList*)_pData; }
int numberOfVertices();
protected:
virtual ~MorphVertexListRecord();
virtual bool readLocalData(Input& fr);
// virtual bool writeLocalData(Output& fw);
virtual void endian();
};
////////////////////////////////////////////////////////////////////
//
// UnknownListRecord
//
////////////////////////////////////////////////////////////////////
class UnknownListRecord : public PrimNodeRecord
{
public:
UnknownListRecord();
virtual Record* clone() const { return new UnknownListRecord(); }
virtual const char* className() const { return "UnknownListRecord"; }
virtual int classOpcode() const { return 53; }
// virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~UnknownListRecord();
virtual bool readLocalData(Input& fr);
// virtual bool writeLocalData(Output& fw);
virtual void endian();
};
////////////////////////////////////////////////////////////////////
//
// VectorRecord
//
////////////////////////////////////////////////////////////////////
// A vector record is an ancillary record of the (pre V15.4) face node.
// Its only use is to provide the direction vector for old-style
// unidirectional and bidirectional light point faces.
typedef struct VectorTag
{
SRecHeader RecHeader;
float32x3 Vec;
} SVector;
class VectorRecord : public AncillaryRecord
{
public:
VectorRecord();
virtual Record* clone() const { return new VectorRecord(); }
virtual const char* className() const { return "VectorRecord"; }
virtual int classOpcode() const { return VECTOR_OP; }
virtual int sizeofData() const { return sizeof(SVector); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
virtual SVector* getData() const { return (SVector*)_pData; }
protected:
virtual ~VectorRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,166 @@
// FltFile.cpp
#include <osg/OSG>
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osg/Notify>
#include "FltFile.h"
#include "Record.h"
#include "RecordVisitor.h"
#include "ExternalRecord.h"
#include "flt2osg.h" // ConvertFromFLT
#include "Input.h"
using namespace flt;
FltFile::FltFile(
ColorPool* pColorPool,
TexturePool* pTexturePool,
MaterialPool* pMaterialPool)
{
if (pColorPool)
_pColorPool = pColorPool;
else
_pColorPool = &_colorPool;
if (pTexturePool)
_pTexturePool = pTexturePool;
else
_pTexturePool = &_texturePool;
if (pMaterialPool)
_pMaterialPool = pMaterialPool;
else
_pMaterialPool = &_materialPool;
_pHeaderRecord = NULL;
}
FltFile::~FltFile()
{
}
osg::Object* FltFile::readObject(const std::string& fileName)
{
return readNode(fileName);
}
osg::Node* FltFile::readNode(const std::string& fileName)
{
osg::Node* node = NULL;
Record* pRootRec = readModel(fileName);
if (pRootRec == NULL)
return NULL;
// Convert record tree to osg scene graph
node = convert();
pRootRec->unref(); // delete record tree
return node;
}
osg::Node* FltFile::convert()
{
ConvertFromFLT visit(this);
return visit.convert(getHeaderRecord());
}
// Read flight model (include externals)
Record* FltFile::readModel(const std::string& fileName)
{
Record* pRec = readFile(fileName);
if (pRec == NULL) return NULL;
readExternals(pRec);
return pRec;
}
Record* FltFile::readFile(const std::string& fileName)
{
FileInput fin;
if (!fin.open(fileName)) return NULL;
osg::notify(osg::INFO) << "Loading " << fileName << " ... " << endl;
Record* pRec = fin.readCreateRecord();
_pHeaderRecord = pRec;
if (pRec == NULL)
{
osg::notify(osg::WARN) << "File not found " << fileName << endl;
return NULL;
}
if (pRec->isPrimaryNode()) // Header
pRec->readLocalData(fin); // Read rest of file
fin.close();
return pRec;
}
class ReadExternal : public RecordVisitor
{
public:
ReadExternal(FltFile* fltFile)
{
_fltFile = fltFile;
setTraverseMode(RecordVisitor::TRAVERSE_ALL_CHILDREN);
}
virtual void apply(ExternalRecord& rec)
{
SExternalReference* pSExternal = (SExternalReference*)rec.getData();
osg::notify(osg::INFO) << "External=" << pSExternal->szPath << endl;
ColorPool* pColorPool = NULL;
TexturePool* pTexturePool = NULL;
MaterialPool* pMaterialPool = NULL;
if (pSExternal->diFlags & BIT0)
pColorPool = _fltFile->getColorPool();
if (pSExternal->diFlags & BIT2)
pTexturePool = _fltFile->getTexturePool();
if (pSExternal->diFlags & BIT1)
pMaterialPool = _fltFile->getMaterialPool();
FltFile* flt = new FltFile(pColorPool, pTexturePool, pMaterialPool);
if (flt)
{
flt->readModel(pSExternal->szPath);
rec.setExternal(flt);
}
}
public:
FltFile* _fltFile;
};
void FltFile::readExternals(Record* pRec)
{
if (pRec)
{
ReadExternal visitor(this);
pRec->accept(visitor);
}
}

View File

@@ -0,0 +1,60 @@
// FltFile.h
#ifndef __FLT_FILE_H
#define __FLT_FILE_H
#include <map>
#include <string>
#include <osg/Referenced>
#include "Pool.h"
namespace flt {
class Record;
class FltFile : public osg::Referenced
{
public:
FltFile(
ColorPool* pColorPool = NULL,
TexturePool* pTexturePool = NULL,
MaterialPool* pMaterialPool = NULL);
virtual ~FltFile();
virtual osg::Object* readObject(const std::string& fileName);
virtual osg::Node* readNode(const std::string& fileName);
osg::Node* convert();
Record* getHeaderRecord() { return _pHeaderRecord; }
Record* readModel(const std::string& fileName);
ColorPool* getColorPool() { return _pColorPool; }
TexturePool* getTexturePool() { return _pTexturePool; }
MaterialPool* getMaterialPool() { return _pMaterialPool; }
protected:
Record* readFile(const std::string& fileName);
void readExternals(Record* pRec);
private:
Record* _pHeaderRecord;
ColorPool _colorPool;
TexturePool _texturePool;
MaterialPool _materialPool;
ColorPool* _pColorPool;
TexturePool* _pTexturePool;
MaterialPool* _pMaterialPool;
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,95 @@
// FltRecords.h
#ifndef __FLT_RECORDS_H
#define __FLT_RECORDS_H
#include "flt.h"
namespace flt {
///////////////////////////////////////////////////////////////
typedef struct MorphingVertexListTag
{
SRecHeader RecHeader;
int32 diAOffset; // Byte offset to the actual vertex record in the vertex table.
int32 diMOffset; // Byte offset to the morph vertex record in the vertex table.
} SMorphingVertexList; // see OF doc
typedef struct ReplicateTag
{
SRecHeader RecHeader;
int16 iNumber; // Number of replications
int16 iSpare; // Spare for fullword alignment
} SReplicate;
/*
typedef struct ReferenceTag // OBSOLETE
{
SRecHeader RecHeader;
int16 iSpare; // Spare
int16 iNumber; // Instance definition number
} SReference;
typedef struct DefinitionTag // OBSOLETE
{
SRecHeader RecHeader;
int16 iSpare; // Spare
int16 iNumber; // Instance definition number
} SDefinition;
*/
/*
typedef struct ColorTableTag
{
SRecHeader RecHeader;
char szReserved[128];// Reserved
color32 Colors[1024]; // Array of brightest RGB of color 0 - 1024
} SColorTable;
// this record is sometimes immediately followed by a: int32 numberOfColorNames
// and then the specified number of ColorNames as described in the structure below
// to check if such a list exist: compare RecHeaderBuff.wLength with sizeof(SColorTable)
typedef struct ColorNameListTag
{
uint16 wEntryLength;
int16 iReserved_1;
int16 iEntryIndex;
int16 iReserved_2;
char *szName; // calc length of string from wEntryLength
} SColorNameList;
*/
/*
typedef struct ComponentTag
{
float32 sfRed; // red component of material
float32 sfGreen; // green component of material
float32 sfBlue; // blue component of material
} SComponent;
*/
}; // end namespace flt
#endif // __FLT_RECORDS_H

View File

@@ -0,0 +1,574 @@
// GeoSetBuilder.cpp
#include "flt.h"
#include "FltFile.h"
#include "Pool.h"
#include "opcodes.h"
#include "VertexPoolRecords.h"
#include "OldVertexRecords.h"
#include "MaterialPaletteRecord.h"
#include "GeoSetBuilder.h"
#include <osg/Object>
#include <osg/LOD>
#include <osg/GeoState>
#include <osg/Transparency>
#include <osg/GeoSet>
#include <osg/GeoState>
#include <osg/Geode>
#include <osg/Material>
#include <osg/Texture>
#include <osg/TexEnv>
#include <osg/Notify>
#include <algorithm>
#include <map>
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// GeoSetBuilder
//
////////////////////////////////////////////////////////////////////
// OpenFlight don't save data in GeoSets. This class tries to find
// existing GeoSets with matching state before creating a new GeoSet.
GeoSetBuilder::GeoSetBuilder(FltFile* pFltFile)
{
_pFltFile = pFltFile;
initPrimData();
}
// virtual
GeoSetBuilder::~GeoSetBuilder()
{
for(GeoSetList::iterator itr=_aGeoSet.begin();
itr!=_aGeoSet.end();
++itr)
{
delete *itr;
}
}
void GeoSetBuilder::initPrimData()
{
_appearance.init();
_aVertex.erase(_aVertex.begin(), _aVertex.end());
}
// Convert flt::TmpGeoSet's to osg::GeoSet's and add to osg::Geode.
// If geode parameter is NULL create new.
// If geode created inside this function and no osg::GeoSet's
// added free geode.
osg::Geode* GeoSetBuilder::createOsgGeoSets(osg::Geode* geode)
{
bool bInternalGeodeAllocation = false;
if (geode == NULL)
{
geode = new osg::Geode;
bInternalGeodeAllocation = true;
}
for(GeoSetList::iterator itr=_aGeoSet.begin();
itr!=_aGeoSet.end();
++itr)
{
osg::GeoSet* gset = (*itr)->createOsgGeoSet();
if (gset)
geode->addGeoSet(gset);
}
if (bInternalGeodeAllocation && (geode->getNumGeosets() == 0))
{
geode->unref();
return NULL;
}
return geode;
}
void GeoSetBuilder::addVertex(Record* vertex)
{
_aVertex.push_back(vertex);
_appearance.setVertexOp(vertex->getOpcode());
}
bool GeoSetBuilder::addPrimitive()
{
int nVertices = _aVertex.size();
if (nVertices == 0) return false;
if (_appearance.getPrimType() == osg::GeoSet::NO_TYPE)
_appearance.setPrimType(findPrimType(nVertices));
TmpGeoSet* gset = findMatchingGeoSet();
if (gset)
{
addTo(gset);
if (_appearance.getMaterial())
{
_appearance.getMaterial()->unref();
_appearance.setMaterial(NULL);
}
}
else
addToNew();
initPrimData();
return true;
}
//////////////////////// protected /////////////////////////////////
TmpGeoSet* GeoSetBuilder::findMatchingGeoSet()
{
for(std::vector<TmpGeoSet*>::iterator itr=_aGeoSet.begin();
itr!=_aGeoSet.end();
++itr)
{
if (_appearance == (*itr)->_appearance)
return *itr;
}
return NULL;
}
void GeoSetBuilder::addTo(TmpGeoSet* gset)
{
int nVertices = _aVertex.size();
gset->addPrimLen(nVertices);
for(std::vector<Record*>::iterator itr=_aVertex.begin();
itr!=_aVertex.end();
++itr)
{
gset->addVertex(*itr);
}
}
void GeoSetBuilder::addToNew()
{
TmpGeoSet* gset = new TmpGeoSet(_pFltFile);
if (gset == NULL) return;
// Transfer data to TmpGeoSet
gset->_appearance = _appearance;
addTo(gset);
_aGeoSet.push_back(gset);
}
PrimitiveType GeoSetBuilder::findPrimType( int nVertices)
{
PrimitiveType primtype = osg::GeoSet::NO_TYPE;
switch (nVertices)
{
case 1:
primtype = osg::GeoSet::POINTS;
break;
case 2:
primtype = osg::GeoSet::LINES;
break;
case 3:
primtype = osg::GeoSet::TRIANGLES;
break;
case 4:
primtype = osg::GeoSet::QUADS;
break;
default:
if (nVertices >= 5) primtype = osg::GeoSet::POLYGON;
break;
}
return primtype;
}
////////////////////////////////////////////////////////////////////
//
// TmpGeoSet
//
////////////////////////////////////////////////////////////////////
// GeoSet with dynamic size. Used by GeoSetBuilder as a temp. buffer.
TmpGeoSet::TmpGeoSet(FltFile* pFltFile)
{
_pFltFile = pFltFile;
}
TmpGeoSet::~TmpGeoSet()
{
}
void TmpGeoSet::addVertex(Record* vertex)
{
_appearance.setVertexOp(vertex->getOpcode());
_aVertex.push_back(vertex);
}
void TmpGeoSet::addPrimLen(int len)
{
_aPrimLen.push_back(len);
}
osg::GeoSet* TmpGeoSet::createOsgGeoSet()
{
int prims = _aPrimLen.size();
int indices = _aVertex.size();
if (prims==0 || indices==0)
return NULL;
osg::GeoSet* gset = new osg::GeoSet;
gset->setNumPrims(prims);
gset->setPrimType(_appearance.getPrimType());
osg::GeoState* gstate = new osg::GeoState;
gset->setGeoState(gstate);
// Material
osg::Material* osgMaterial = _appearance.getMaterial();
if (osgMaterial)
{
gstate->setAttribute(osg::GeoState::MATERIAL, osgMaterial);
}
// Color BIND_OVERALL
if (_appearance.getColorBinding() == osg::GeoSet::BIND_OVERALL)
{
osg::Vec4* color = new osg::Vec4[1];
*color = _appearance.getColor();
gset->setColorBinding(_appearance.getColorBinding());
gset->setColors(color);
}
// Color BIND_PERVERTEX
if (_appearance.getColorBinding() == osg::GeoSet::BIND_PERVERTEX)
{
gset->setColorBinding(_appearance.getColorBinding());
gset->setColors(new osg::Vec4[indices]);
}
// Transparency
if (_appearance.getTransparency())
{
gstate->setMode(osg::GeoState::TRANSPARENCY, osg::GeoState::ON);
gstate->setAttribute(osg::GeoState::TRANSPARENCY, new osg::Transparency);
}
// Cull face
if (_appearance.getCullface())
{
osg::CullFace* cullface = new osg::CullFace;
if (cullface)
{
gstate->setMode(osg::GeoState::FACE_CULL, osg::GeoState::ON);
cullface->setMode(osg::CullFace::BACK);
gstate->setAttribute(osg::GeoState::FACE_CULL, cullface);
}
}
else
{
gstate->setMode(osg::GeoState::FACE_CULL, osg::GeoState::OFF);
}
// Texture
if (_appearance.getTexture())
{
gstate->setMode( osg::GeoState::TEXTURE, osg::GeoState::ON );
gstate->setAttribute( osg::GeoState::TEXTURE, _appearance.getTexture() );
gstate->setAttribute( osg::GeoState::TEXENV, new osg::TexEnv );
}
// Lighting
if (_appearance.getLighting())
gstate->setMode( osg::GeoState::LIGHTING, osg::GeoState::ON );
else
gstate->setMode( osg::GeoState::LIGHTING, osg::GeoState::OFF );
// Subface
if (_appearance.getSubface() > 0)
{
osg::PolygonOffset* polyoffset = new osg::PolygonOffset;
if (polyoffset)
{
int level = _appearance.getSubface();
gstate->setMode(osg::GeoState::POLYGON_OFFSET,osg::GeoState::ON);
polyoffset->setOffset(-1*level, -20*level);
gstate->setAttribute(osg::GeoState::POLYGON_OFFSET, polyoffset);
}
}
// Point
if (_appearance.getPrimType() == osg::GeoSet::POINTS)
{
osg::Point* point = new osg::Point;
if (point)
{
gstate->setMode(osg::GeoState::POINT,osg::GeoState::ON);
point->setSize(8);
point->enableSmooth();
gstate->setAttribute(osg::GeoState::POINT, point);
}
}
// PrimLengths
int nPrimLenSize = 1;
if (_appearance.getPrimType() == osg::GeoSet::POLYGON)
nPrimLenSize = prims;
int *lens = new int[nPrimLenSize];
gset->setPrimLengths( lens );
for (int n=0; n < nPrimLenSize; n++)
lens[n] = _aPrimLen[n];
// Vertices
switch(_appearance.getVertexOp())
{
case VERTEX_C_OP:
gset->setCoords(new osg::Vec3[indices]);
break;
case VERTEX_CN_OP:
gset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
gset->setCoords(new osg::Vec3[indices]);
gset->setNormals(new osg::Vec3[indices]);
break;
case VERTEX_CT_OP:
gset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
gset->setCoords(new osg::Vec3[indices]);
gset->setTextureCoords(new osg::Vec2[indices]);
break;
case VERTEX_CNT_OP:
gset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
gset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
gset->setCoords(new osg::Vec3[indices]);
gset->setNormals(new osg::Vec3[indices]);
gset->setTextureCoords(new osg::Vec2[indices]);
break;
case OLD_VERTEX_OP:
gset->setCoords(new osg::Vec3[indices]);
break;
case OLD_VERTEX_COLOR_OP:
gset->setCoords(new osg::Vec3[indices]);
break;
case OLD_VERTEX_COLOR_NORMAL_OP:
gset->setCoords(new osg::Vec3[indices]);
// gset->setNormals(new osg::Vec3[indices]);
break;
}
// Copy vertices
{
int index;
std::vector<Record*>::iterator itr;
for(index=0, itr=_aVertex.begin();
itr!=_aVertex.end();
++index, ++itr)
{
setVertex(gset, index, *itr);
}
}
return gset;
}
///////////////////////// private //////////////////////////////////
void TmpGeoSet::setVertex(osg::GeoSet* gset, int index, Record* vertex)
{
bool bColorBindPerVertex = _appearance.getColorBinding() == osg::GeoSet::BIND_PERVERTEX;
switch(_appearance.getVertexOp())
{
case VERTEX_C_OP:
{
SVertex* pVert = (SVertex*)vertex->getData();
osg::Vec3* coords = gset->getCoords();
coords[index].set(
(float)pVert->Coord.x(),
(float)pVert->Coord.y(),
(float)pVert->Coord.z());
if (bColorBindPerVertex)
{
osg::Vec4* colors = gset->getColors();
if (pVert->swFlags & BIT3)
colors[index] = pVert->PackedColor.get();
else
{
ColorPool* pColorPool = _pFltFile->getColorPool();
if (pColorPool)
colors[index] = pColorPool->getColor(pVert->dwVertexColorIndex);
}
}
}
break;
case VERTEX_CN_OP:
{
SNormalVertex* pVert = (SNormalVertex*)vertex->getData();
osg::Vec3* coords = gset->getCoords();
osg::Vec3* normals = gset->getNormals();
coords[index].set(
(float)pVert->Coord.x(),
(float)pVert->Coord.y(),
(float)pVert->Coord.z());
normals[index].set(
(float)pVert->Normal.x(),
(float)pVert->Normal.y(),
(float)pVert->Normal.z());
if (bColorBindPerVertex)
{
osg::Vec4* colors = gset->getColors();
if (pVert->swFlags & BIT3)
colors[index] = pVert->PackedColor.get();
else
{
ColorPool* pColorPool = _pFltFile->getColorPool();
if (pColorPool)
colors[index] = pColorPool->getColor(pVert->dwVertexColorIndex);
}
}
}
break;
case VERTEX_CNT_OP:
{
SNormalTextureVertex* pVert = (SNormalTextureVertex*)vertex->getData();
osg::Vec3* coords = gset->getCoords();
osg::Vec3* normals = gset->getNormals();
osg::Vec2* texuv = gset->getTCoords();
coords[index].set(
(float)pVert->Coord.x(),
(float)pVert->Coord.y(),
(float)pVert->Coord.z());
normals[index].set(
(float)pVert->Normal.x(),
(float)pVert->Normal.y(),
(float)pVert->Normal.z());
texuv[index].set(
(float)pVert->Texture.x(),
(float)pVert->Texture.y());
if (bColorBindPerVertex)
{
osg::Vec4* colors = gset->getColors();
if (pVert->swFlags & BIT3)
colors[index] = pVert->PackedColor.get();
else
{
ColorPool* pColorPool = _pFltFile->getColorPool();
if (pColorPool)
colors[index] = pColorPool->getColor(pVert->dwVertexColorIndex);
}
}
}
break;
case VERTEX_CT_OP:
{
STextureVertex* pVert = (STextureVertex*)vertex->getData();
osg::Vec3* coords = gset->getCoords();
osg::Vec2* texuv = gset->getTCoords();
coords[index].set(
(float)pVert->Coord.x(),
(float)pVert->Coord.y(),
(float)pVert->Coord.z());
texuv[index].set(
(float)pVert->Texture.x(),
(float)pVert->Texture.y());
if (bColorBindPerVertex)
{
osg::Vec4* colors = gset->getColors();
if (pVert->swFlags & BIT3)
colors[index] = pVert->PackedColor.get();
else
{
ColorPool* pColorPool = _pFltFile->getColorPool();
if (pColorPool)
colors[index] = pColorPool->getColor(pVert->dwVertexColorIndex);
}
}
}
break;
case OLD_VERTEX_OP:
{
SOldVertex* pVert = (SOldVertex*)vertex->getData();
osg::Vec3* coords = gset->getCoords();
coords[index].set(
(float)pVert->v[0],
(float)pVert->v[1],
(float)pVert->v[2]);
}
break;
case OLD_VERTEX_COLOR_OP:
{
SOldVertexColor* pVert = (SOldVertexColor*)vertex->getData();
osg::Vec3* coords = gset->getCoords();
coords[index].set(
(float)pVert->v[0],
(float)pVert->v[1],
(float)pVert->v[2]);
}
break;
case OLD_VERTEX_COLOR_NORMAL_OP:
{
SOldVertexColorNormal* pVert = (SOldVertexColorNormal*)vertex->getData();
osg::Vec3* coords = gset->getCoords();
// osg::Vec3* normals = gset->getNormals();
coords[index].set(
(float)pVert->Coord[0],
(float)pVert->Coord[1],
(float)pVert->Coord[2]);
/*
normals[index].set(
(float)pVert->Normal[0],
(float)pVert->Normal[1],
(float)pVert->Normal[2]);
*/
}
break;
}
}

View File

@@ -0,0 +1,234 @@
// GeoSetBuilder.h
#ifndef __FLT_GEOSETS_H
#define __FLT_GEOSETS_H
#include <map>
#include <vector>
#include <osg/GeoSet>
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
namespace osg {
class Node;
class LOD;
class GeoSet;
class Geode;
class GeoState;
class Material;
class Texture;
}
namespace flt {
class Record;
class TmpGeoSet;
typedef osg::GeoSet::PrimitiveType PrimitiveType;
typedef std::vector<osg::Vec3> CoordList;
typedef std::vector<osg::Vec3> NormalList;
typedef std::vector<osg::Vec2> TexUVList;
typedef std::vector<osg::Vec4> ColorList;
typedef std::vector<Record*> VertexList;
typedef std::vector<int> PrimLenList;
class Appearance
{
public:
typedef osg::GeoSet::BindingType BindingType;
Appearance() { init(); }
void init()
{
_nVertexOp = 0;
_primtype = osg::GeoSet::NO_TYPE;
_material = NULL;
_texture = NULL;
_color = osg::Vec4(1,1,1,1);
_color_binding = osg::GeoSet::BIND_OFF;
_cullface = false;
_transparency = false;
_lighting = false;
_subface = 0;
}
void setVertexOp(int op) { _nVertexOp = op; }
int getVertexOp() { return _nVertexOp; }
void setPrimType(PrimitiveType pt) { _primtype = pt; }
PrimitiveType getPrimType() { return _primtype; }
void setColor(osg::Vec4 color) { _color = color; }
osg::Vec4& getColor() { return _color; }
void setColorBinding( BindingType binding ) { _color_binding = binding; }
BindingType getColorBinding() { return _color_binding; }
void setMaterial(osg::Material *material) { _material = material; }
osg::Material* getMaterial() { return _material; }
void setTexture(osg::Texture *texture) { _texture = texture; }
osg::Texture* getTexture() { return _texture; }
void setCullface(bool cullface) { _cullface = cullface; }
bool getCullface() { return _cullface; }
void setTransparency(bool transp) { _transparency = transp; }
bool getTransparency() { return _transparency; }
void setLighting(bool light) { _lighting = light; }
bool getLighting() { return _lighting; }
void setSubface(int level) { _subface = level; }
int getSubface() { return _subface; }
bool mat_equal(const void *m) const
{
if (_material && m)
return !memcmp(_material, m, sizeof(osg::Material));
return (!_material && !m);
}
bool col_equal(const BindingType b, const osg::Vec4 c) const
{
if (_color_binding != b)
return false;
if (_color_binding == osg::GeoSet::BIND_OVERALL)
return (_color == c);
return true;
}
/*inline*/ bool operator == (const Appearance& a) const
{
return ((_nVertexOp == a._nVertexOp)
&& (_primtype == a._primtype)
&& mat_equal(a._material)
&& col_equal(a._color_binding, a._color)
&& (_texture == a._texture)
&& (_cullface == a._cullface)
&& (_transparency == a._transparency)
&& (_lighting == a._lighting)
&& (_subface == a._subface));
}
private:
int _nVertexOp;
PrimitiveType _primtype;
osg::Material* _material;
osg::Texture* _texture;
osg::Vec4 _color; // BIND_OVERALL
BindingType _color_binding;
bool _cullface;
bool _transparency;
bool _lighting;
int _subface;
};
////////////////////////////////////////////////////////////////////
//
// GeoSetBuilder
//
////////////////////////////////////////////////////////////////////
class GeoSetBuilder
{
public:
typedef osg::GeoSet::BindingType BindingType;
GeoSetBuilder(FltFile* pFltFile);
virtual ~GeoSetBuilder();
void addVertex(Record* vertex);
void setPrimType(PrimitiveType pt) { _appearance.setPrimType(pt); }
void setColor(osg::Vec4 color) { _appearance.setColor(color); }
void setColorBinding(BindingType binding ) { _appearance.setColorBinding(binding); }
void setMaterial(osg::Material *material) { _appearance.setMaterial(material); }
void setTexture(osg::Texture *texture) { _appearance.setTexture(texture); }
void setCullface(bool cullface) { _appearance.setCullface(cullface); }
void setTransparency(bool transp) { _appearance.setTransparency(transp); }
void setLighting(bool light) { _appearance.setLighting(light); }
void setSubface(int level) { _appearance.setSubface(level); }
PrimitiveType getPrimType() { return _appearance.getPrimType(); }
osg::Vec4& getColor() { return _appearance.getColor(); }
BindingType getColorBinding() { return _appearance.getColorBinding(); }
osg::Material* getMaterial() { return _appearance.getMaterial(); }
osg::Texture* getTexture() { return _appearance.getTexture(); }
bool getCullface() { return _appearance.getCullface(); }
bool getTransparency() { return _appearance.getTransparency(); }
bool getLighting() { return _appearance.getLighting(); }
int getSubface() { return _appearance.getSubface(); }
bool addPrimitive();
osg::Geode* createOsgGeoSets(osg::Geode* geode=NULL);
protected:
void initPrimData();
TmpGeoSet* findMatchingGeoSet();
void addTo(TmpGeoSet* gset);
void addToNew();
PrimitiveType findPrimType( int nVertices);
private:
VertexList _aVertex;
Appearance _appearance;
typedef std::vector<TmpGeoSet*> GeoSetList;
GeoSetList _aGeoSet;
FltFile* _pFltFile;
};
////////////////////////////////////////////////////////////////////
//
// TmpGeoSet
//
////////////////////////////////////////////////////////////////////
class TmpGeoSet
{
public:
TmpGeoSet(FltFile* pFltFile);
virtual ~TmpGeoSet();
void addVertex(Record* vertex);
void addPrimLen(int len);
osg::GeoSet* createOsgGeoSet();
Appearance _appearance;
private:
void setVertex(osg::GeoSet* gset, int index, Record* vertex);
PrimLenList _aPrimLen;
VertexList _aVertex;
FltFile* _pFltFile;
};
} // end of namespace flt
#endif // __FLT_GEOSETS_H

View File

@@ -0,0 +1,44 @@
// GroupRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "GroupRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// GroupRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<GroupRecord> g_GroupProxy;
GroupRecord::GroupRecord()
{
}
// virtual
GroupRecord::~GroupRecord()
{
}
void GroupRecord::endian()
{
SGroup *pSGroup = (SGroup*)getData();
ENDIAN( pSGroup->iGroupRelPriority );
ENDIAN( pSGroup->dwFlags );
ENDIAN( pSGroup->iSpecialId_1 );
ENDIAN( pSGroup->iSpecialId_2 );
ENDIAN( pSGroup->iSignificance );
}

View File

@@ -0,0 +1,64 @@
// GroupRecord.h
#ifndef __FLT_GROUP_RECORD_H
#define __FLT_GROUP_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
struct SGroup
{
SRecHeader RecHeader;
char szIdent[8]; // 7 char ASCII ID; 0 terminates
int16 iGroupRelPriority; // Group relative priority
int16 iSpare; // Spare for fullword alignment
uint32 dwFlags; // Flags (bits, from left to right)
// 0 = Reserved
// 1 = Forward animation
// 2 = Cycling animation
// 3 = Bounding box follows
// 4 = Freeze bounding box
// 5 = Default parent
// 6-31 Spare
int16 iSpecialId_1; // Special effects ID 1 - defined by real time
int16 iSpecialId_2; // Special effects ID 2 - defined by real time
int16 iSignificance; // Significance Flags
uint8 swLayer; // Layer Number
uint8 swReserved[5]; // Reserved
};
class GroupRecord : public PrimNodeRecord
{
public:
GroupRecord();
virtual Record* clone() const { return new GroupRecord(); }
virtual const char* className() const { return "GroupRecord"; }
virtual int classOpcode() const { return GROUP_OP; }
virtual int sizeofData() const { return sizeof(SGroup); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
SGroup* getData() const { return (SGroup*)_pData; }
virtual const std::string getName( void ) const { return std::string(getData()->szIdent); }
int childLODs();
protected:
virtual ~GroupRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,197 @@
// HeaderRecord.cpp
#include "osg/Group"
#include "flt.h"
#include "Registry.h"
#include "HeaderRecord.h"
#include "Input.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// HeaderRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<HeaderRecord> g_HeaderProxy;
HeaderRecord::HeaderRecord()
{
// _pNode = NULL;
}
// virtual
HeaderRecord::~HeaderRecord()
{
}
void HeaderRecord::endian()
{
SHeader *pHeader = (SHeader*)getData();
// VALID_RECORD(SHeader, pRecHdr)
ENDIAN( pHeader->diFormatRevLev );
ENDIAN( pHeader->diDatabaseRevLev );
ENDIAN( pHeader->iNextGroup );
ENDIAN( pHeader->iNextLOD );
ENDIAN( pHeader->iNextObject );
ENDIAN( pHeader->iNextPolygon );
ENDIAN( pHeader->iMultDivUnit );
ENDIAN( pHeader->diFlags );
ENDIAN( pHeader->diProjection );
ENDIAN( pHeader->iNextDegOfFreedom );
ENDIAN( pHeader->iVertexStorage );
ENDIAN( pHeader->diDatabaseSource );
ENDIAN( pHeader->dfSWDatabaseCoordX );
ENDIAN( pHeader->dfSWDatabaseCoordY );
ENDIAN( pHeader->dfDatabaseOffsetX );
ENDIAN( pHeader->dfDatabaseOffsetY );
ENDIAN( pHeader->iNextSound );
ENDIAN( pHeader->iNextPath );
ENDIAN( pHeader->iNextClippingRegion );
ENDIAN( pHeader->iNextText );
ENDIAN( pHeader->iNextBSP );
ENDIAN( pHeader->iNextSwitch );
pHeader->SWCorner.endian();
pHeader->NECorner.endian();
pHeader->Origin.endian();
ENDIAN( pHeader->dfLambertUpperLat );
ENDIAN( pHeader->dfLambertLowerLat );
ENDIAN( pHeader->iNextLightSource );
}
// virtual
void HeaderRecord::decode()
{
// SHeader *pHeader = (SHeader*)getData();
// Add node to scene graph
// _pNode = new osg::Node;
// _pNode->setName(pHeader->szIdent);
}
// virtual
bool HeaderRecord::readLocalData(Input& fr)
{
return PrimNodeRecord::readLocalData(fr);
}
// virtual
int HeaderRecord::decodeAncillary(int op)
{
/*
switch (op)
{
case COLOUR_TABLE_OP:
G_TRACE0( "\tCOLOUR_TABLE_R\n" );
break;
case MATERIAL_PALETTE_OP:
{
fltMaterialPalette rec( _pFltFile );
rec.readRecordBody();
rec.decodeRecord();
}
break;
case LIGHT_SOURCE_PALETTE_R:
G_TRACE0( "\tLIGHT_SOURCE_PALETTE_R\n" );
break;
case VERTEX_PALETTE_R:
{
fltVertexPalette rec( _pFltFile );
rec.readRecordBody();
rec.decodeRecord();
}
break;
case VERTEX_COORD_R:
{
fltVertex rec( _pFltFile );
rec.readRecordBody();
rec.decodeRecord();
}
break;
case VERTEX_NORMAL_COORD_R:
{
fltNormalVertex rec( _pFltFile );
rec.readRecordBody();
rec.decodeRecord();
}
break;
case VERTEX_NORMAL_UV_COORD_R:
{
fltNormalTextureVertex rec( _pFltFile );
rec.readRecordBody();
rec.decodeRecord();
}
break;
case VERTEX_UV_COORD_R:
{
fltTextureVertex rec( _pFltFile );
rec.readRecordBody();
rec.decodeRecord();
}
break;
default:
return FALSE;
} // end-switch
*/
return true;
}
// virtual
int HeaderRecord::decodeLevel( int op )
{
/*
switch (op)
{
case GROUP_OP:
{
fltGroup rec( _pFltFile, (csGroup*)_pContainer );
rec.readRecordBody();
rec.decodeRecord();
}
break;
default:
return FALSE;
}
*/
return true;
}
/*
void HeaderRecord::write()
{
SHeader *pHeader = (SHeader*)getData();
G_TRACE0("Header\n");
G_TRACE1("\tFormatRevisionLevel %ld\n", pHeader->diFormatRevLev);
G_TRACE1("\tDatabaseRevisionLevel %ld\n", pHeader->diDatabaseRevLev);
G_TRACE1("\tDateAndTimeOfLastRev. %s\n", pHeader->szDaTimLastRev);
G_TRACE1("\tProjection %ld\n", pHeader->diProjection);
G_TRACE1("\tDatabase Source %ld\n", pHeader->diDatabaseSource);
G_TRACE1("\tSWCorner,Lat %lf\n", pHeader->SWCorner.dfLat);
G_TRACE1("\tSWCorner,Lon %lf\n", pHeader->SWCorner.dfLon);
G_TRACE1("\tNECorner,Lat %lf\n", pHeader->NECorner.dfLat);
G_TRACE1("\tNECorner,Lon %lf\n", pHeader->NECorner.dfLon);
G_TRACE1("\tOrigin,Lat %lf\n", pHeader->Origin.dfLat);
G_TRACE1("\tOrigin,Lon %lf\n", pHeader->Origin.dfLon);
}
*/

View File

@@ -0,0 +1,126 @@
// HeaderRecord.h
#ifndef __FLT_HEADER_RECORD_H
#define __FLT_HEADER_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
//namespace flt {
//class Node;
//};
namespace flt {
struct SHeader
{
SRecHeader RecHeader;
char szIdent[8]; // ID field (Not curr used)
int32 diFormatRevLev; // Format revision level
int32 diDatabaseRevLev; // Edit rev. level
char szDaTimLastRev[32]; // Date and time last rev.
int16 iNextGroup; // Next group ID number
int16 iNextLOD; // Next LOD ID number
int16 iNextObject; // Next object ID number
int16 iNextPolygon; // Next polygon ID number
int16 iMultDivUnit; // Unit multiplier/divisor, always = 1
uint8 swVertexCoordUnit; // Vertex coordinate units
// 0 = Meters
// 1 = Kilometers
// 4 = Feet
// 5 = Inches
// 8 = Nautical miles
uint8 swTexWhite; // if TRUE set texwhite on new polygons
int32 diFlags; // Flags (bits, from left to right)
// 0 = Save vertex normals
// 1-31 Spare
int32 diNotUsed_1[6]; // Not Used
int32 diProjection; // Projection Type
// 0 = Flat Earth
// 1 = Trapezoidal
// 2 = Round Earth
// 3 = Lambert
// 4 = UTM
// 5 = Geodetic
// 6 = Geocentric
int32 diNotUsed_2[7]; // Not Used
int16 iNextDegOfFreedom; // Next degree of freedom ID number
int16 iVertexStorage; // Vertex Storage Type
// 1 = Double Precision Float
int32 diDatabaseSource; // Database Source
// 100 = OpenFlight
// 200 = DIG I/DIG II
// 300 = Evans and Sutherland CT5A/CT6
// 400 = PSP DIG
// 600 = General Electric CIV/CV / PT2000
// 700 = Evans and Sutherland GDF
float64 dfSWDatabaseCoordX; // Southwest Database Coordinate (x,y)
float64 dfSWDatabaseCoordY;
float64 dfDatabaseOffsetX; // Delta (x,y) to Place Database
float64 dfDatabaseOffsetY;
int16 iNextSound; // Next Sound Bead Id
int16 iNextPath; // Next Path Bead ID
int32 diReserved_1[2]; // Reserved for MultiGen
int16 iNextClippingRegion;// Next Clipping Region Bead ID
int16 iNextText; // Next Text Bead ID
int16 iNextBSP; // Next BSP ID
int16 iNextSwitch; // Next Switch Bead ID
int32 diReserved_2; // Reserved
float64x2 SWCorner; // South West Corner Lat/Lon (NB: dec. degrees)
float64x2 NECorner; // North East Corner Lat/Lon (NB: dec. degrees)
float64x2 Origin; // Origin Lat/Lon (NB: dec. degrees, not radians)
float64 dfLambertUpperLat; // Lambert Upper Latitude
float64 dfLambertLowerLat; // Lambert Lower Latitude
int16 iNextLightSource; // Next Light Source ID Number
int16 iReserved_3; // Reserved
int16 iNextRoad; // Next road bead ID number
int16 iNextCat; // Next CAT bead ID number
int16 iReserved_4[4]; // Reserved
int32 diEllipsoid; // Earth ellipsoid model
// 0 - WGS 1984
// 1 - WGS 1972
// 2 - Bessel
// 3 - Clarke 1866
// 4 - NAD 1927
};
class HeaderRecord : public PrimNodeRecord
{
public:
HeaderRecord();
virtual Record* clone() const { return new HeaderRecord(); }
virtual const char* className() const { return "HeaderRecord"; }
virtual int classOpcode() const { return HEADER_OP; }
virtual int sizeofData() const { return sizeof(SHeader); }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
SHeader* getData() const { return (SHeader*)_pData; }
virtual const std::string getName( void ) const { return std::string(getData()->szIdent); }
protected:
virtual ~HeaderRecord();
virtual void endian();
virtual void decode();
virtual bool readLocalData(Input& fr);
// virtual bool writeLocalData(Output& fw);
virtual int decodeAncillary(int op);
virtual int decodeLevel(int op);
private:
// vertex pool
// osg::Node* _pNode;
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,202 @@
// Input.cpp
#include <string>
#include <malloc.h>
#include <osg/Notify>
#include "Input.h"
#include "Record.h"
#include "Registry.h"
#ifdef __sgi
using std::string;
#endif
#ifdef OSG_USE_IO_DOT_H
#include <iostream.h>
#else
#include <iostream>
using namespace std;
#endif
using namespace flt;
FileInput::FileInput()
{
_init();
}
FileInput::~FileInput()
{
close();
}
void FileInput::_init()
{
_lRecOffset = 0L;
_file = NULL;
_eof = true;
}
size_t FileInput::_read(void *buffer, size_t size)
{
if (_eof) return 0;
size_t nItemsRead = ::fread(buffer, size, 1, _file);
if (nItemsRead != 1)
_eof = true;
return nItemsRead;
}
bool FileInput::eof()
{
return _eof;
}
bool FileInput::open(const std::string& fileName)
{
_file=::fopen( fileName.c_str(), "rb");
if (_file == NULL) return false;
_eof = false;
return true;
}
void FileInput::close()
{
if (_file) ::fclose(_file);
_init();
}
bool FileInput::rewindLast()
{
if (_file == NULL) return false;
return (fseek(_file, _lRecOffset, SEEK_SET) == 0);
}
long FileInput::offset()
{
return _lRecOffset;
}
// read opcode and size
bool FileInput::_readHeader(SRecHeader* pHdr)
{
int nItemsRead;
_lRecOffset = ::ftell( _file ); // Save file position for rewind operation
// Read record header (4 bytes)
nItemsRead = _read(pHdr, sizeof(SRecHeader));
if (nItemsRead != 1)
return false;
if (isLittleEndianMachine())
pHdr->endian();
if ((unsigned)pHdr->length() < sizeof(SRecHeader))
return false;
return true;
}
bool FileInput::_readBody(SRecHeader* pData)
{
// Read record body
int nBodySize = pData->length() - sizeof(SRecHeader);
if (nBodySize > 0)
{
int nItemsRead = _read(pData+1, nBodySize);
if (nItemsRead != 1)
return false;
}
return true;
}
SRecHeader* FileInput::readRecord()
{
SRecHeader hdr;
SRecHeader* pData;
if (!_readHeader(&hdr))
return NULL;
// Allocate buffer for record (including header)
pData = (SRecHeader*)::malloc(hdr.length());
if (pData == NULL)
return NULL;
*pData = hdr;
// Some records contains only the header
if (hdr.length() == sizeof(SRecHeader))
return pData;
if (!_readBody(pData))
return NULL;
return pData;
}
Record* Input::readCreateRecord()
{
SRecHeader* pData = readRecord();
if (pData == NULL) return NULL;
// find matching record prototype class
Record* pProto = Registry::instance()->getRecordProto(pData->opcode());
if (pProto == NULL)
pProto = Registry::instance()->getRecordProto(0);
if (pProto == NULL)
{
// Should not be possible to end up here!
osg::notify(osg::INFO) << "UnknownRecord not in registry!" << endl;
::free(pData);
return NULL;
}
// clone protoype
Record* pRec = pProto->cloneRecord(pData);
if (pRec == NULL)
{
osg::notify(osg::INFO) << "Can't clone record!" << endl;
::free(pData);
return NULL;
}
#if 0
osg::notify(osg::INFO) << "class=" << pRec->className();
osg::notify(osg::INFO) << " op=" << pRec->getOpcode();
osg::notify(osg::INFO) << " name=" << pRec->getName();
osg::notify(osg::INFO) << " offset=" << offset() << endl;
#endif
if (isLittleEndianMachine()) // From Intel with love :-(
pRec->endian();
return pRec;
}

108
src/osgPlugins/flt/Input.h Normal file
View File

@@ -0,0 +1,108 @@
#ifndef __FLT_INPUT_H
#define __FLT_INPUT_H
#include "Record.h"
#include <map>
#include <list>
#include <string>
#include "stdio.h"
namespace osg {
class Object;
class Image;
class Node;
};
namespace flt {
class Record;
class Input
{
public:
Input() {}
virtual SRecHeader* readRecord() = 0;
virtual bool eof() = 0;
virtual bool rewindLast() = 0;
virtual long offset() = 0;
Record* readCreateRecord();
protected:
/** disallow creation of Objects on the stack.*/
virtual ~Input() {}
private:
virtual bool _readHeader(SRecHeader* pHdr) = 0;
virtual bool _readBody(SRecHeader* pData) = 0;
};
/** Class for managing the reading of binary .flt files.*/
class FileInput : public Input
{
public:
FileInput();
virtual ~FileInput();
bool open(const std::string& fileName);
void close();
virtual bool eof();
virtual bool rewindLast();
virtual long offset();
virtual SRecHeader* readRecord();
private:
virtual bool _readHeader(SRecHeader* pHdr);
virtual bool _readBody(SRecHeader* pData);
void _init();
size_t _read(void *buffer, size_t size);
FILE* _file;
bool _eof;
long _lRecOffset;
};
class MemInput : public Input
{
public:
MemInput();
virtual ~MemInput();
bool open(SRecHeader* pHdr);
void close();
virtual bool eof();
virtual bool rewindLast();
virtual long offset();
virtual SRecHeader* readRecord();
private:
virtual bool _readHeader(SRecHeader* pHdr);
virtual bool _readBody(SRecHeader* pData);
void _init();
size_t _read(void *buffer, size_t size);
bool _eof;
long _lRecOffset;
};
}; // end namespace flt
#endif // __FLT_INPUT_H

View File

@@ -0,0 +1,62 @@
// InstanceRecords.cpp
#include "flt.h"
#include "Registry.h"
#include "InstanceRecords.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// InstanceDefinitionRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<InstanceDefinitionRecord> g_InstanceDefinitionProxy;
InstanceDefinitionRecord::InstanceDefinitionRecord()
{
}
// virtual
InstanceDefinitionRecord::~InstanceDefinitionRecord()
{
}
void InstanceDefinitionRecord::endian()
{
}
////////////////////////////////////////////////////////////////////
//
// InstanceReferenceRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<InstanceReferenceRecord> g_InstanceReferenceProxy;
InstanceReferenceRecord::InstanceReferenceRecord()
{
}
// virtual
InstanceReferenceRecord::~InstanceReferenceRecord()
{
}
void InstanceReferenceRecord::endian()
{
}

View File

@@ -0,0 +1,85 @@
// InstanceRecords.h
#ifndef __FLT_INSTANCE_RECORDS_H
#define __FLT_INSTANCE_RECORDS_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
////////////////////////////////////////////////////////////////////
//
// InstanceDefinitionRecord
//
////////////////////////////////////////////////////////////////////
typedef struct InstanceDefinitionTag
{
SRecHeader RecHeader;
}SInstanceDefinition;
class InstanceDefinitionRecord : public PrimNodeRecord
{
public:
InstanceDefinitionRecord();
virtual Record* clone() const { return new InstanceDefinitionRecord(); }
virtual const char* className() const { return "InstanceDefinitionRecord"; }
virtual int classOpcode() const { return INSTANCE_DEFINITION_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
SInstanceDefinition* getData() const { return (SInstanceDefinition*)_pData; }
protected:
virtual ~InstanceDefinitionRecord();
virtual void endian();
};
////////////////////////////////////////////////////////////////////
//
// InstanceReferenceRecord
//
////////////////////////////////////////////////////////////////////
typedef struct InstanceReferenceTag
{
SRecHeader RecHeader;
}SInstanceReference;
class InstanceReferenceRecord : public PrimNodeRecord
{
public:
InstanceReferenceRecord();
virtual Record* clone() const { return new InstanceReferenceRecord(); }
virtual const char* className() const { return "InstanceReferenceRecord"; }
virtual int classOpcode() const { return INSTANCE_REFERENCE_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
SInstanceReference* getData() const { return (SInstanceReference*)_pData; }
protected:
virtual ~InstanceReferenceRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,73 @@
// LightPointRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "LightPointRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// LightPointRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<LightPointRecord> g_LightPointProxy;
LightPointRecord::LightPointRecord()
{
}
// virtual
LightPointRecord::~LightPointRecord()
{
}
void LightPointRecord::endian()
{
SLightPoint *pSLightPoint = (SLightPoint*)getData();
ENDIAN( pSLightPoint->iMaterial );
ENDIAN( pSLightPoint->iFeature );
ENDIAN( pSLightPoint->diMode );
ENDIAN( pSLightPoint->sfIntensityFront );
ENDIAN( pSLightPoint->sfIntensityBack );
ENDIAN( pSLightPoint->sfMinDefocus );
ENDIAN( pSLightPoint->sfMaxDefocus );
ENDIAN( pSLightPoint->diFadeMode );
ENDIAN( pSLightPoint->diFogPunchMode );
ENDIAN( pSLightPoint->diDirectionalMode );
ENDIAN( pSLightPoint->diRangeMode );
ENDIAN( pSLightPoint->sfMinPixelSize );
ENDIAN( pSLightPoint->sfMaxPixelSize );
ENDIAN( pSLightPoint->afActualPixelSize );
ENDIAN( pSLightPoint->sfTranspFalloff );
ENDIAN( pSLightPoint->sfTranspFalloffExponent );
ENDIAN( pSLightPoint->sfTranspFalloffScalar );
ENDIAN( pSLightPoint->sfTranspFalloffClamp );
ENDIAN( pSLightPoint->sfFog );
ENDIAN( pSLightPoint->sfReserved );
ENDIAN( pSLightPoint->sfSize );
ENDIAN( pSLightPoint->diDirection );
ENDIAN( pSLightPoint->sfLobeHoriz );
ENDIAN( pSLightPoint->sfLobeVert );
ENDIAN( pSLightPoint->sfLobeRoll );
ENDIAN( pSLightPoint->sfFalloff );
ENDIAN( pSLightPoint->sfAmbientIntensity );
ENDIAN( pSLightPoint->sfAnimPeriod );
ENDIAN( pSLightPoint->sfAnimPhaseDelay );
ENDIAN( pSLightPoint->sfAnimPeriodEnable );
ENDIAN( pSLightPoint->sfSignificance );
ENDIAN( pSLightPoint->sfDrawOrder );
ENDIAN( pSLightPoint->sfFlags );
pSLightPoint->animRot.endian();
}

View File

@@ -0,0 +1,135 @@
// LightPointRecord.h
#ifndef __FLT_LIGHT_POINT_RECORD_H
#define __FLT_LIGHT_POINT_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
struct SLightPoint
{
SRecHeader RecHeader;
char szIdent[8]; // 7 char ASCII ID; 0 terminates
int16 iMaterial; // Surface material code (for DFAD)
int16 iFeature; // Feature ID (for DFAD)
color32 dwBackColor; // Back color for all bidirectional points
int32 diMode; // Display mode
// 0 = RASTER
// 1 = CALLIGRAPHIC
// 2 = EITHER
float32 sfIntensityFront; // Intensity - scalar for front colors
float32 sfIntensityBack; // - scalar for back color
float32 sfMinDefocus; // Minimum defocus - limit (0.0 - 1.0) for calligraphic points
float32 sfMaxDefocus; // Maximum defocus - limit (0.0 - 1.0) for calligraphic points
int32 diFadeMode; // Fading mode
// 0 = enable perspective fading calculations
// 1 = disable calculations
int32 diFogPunchMode; // Fog Punch mode
// 0 = enable fog punch through calculations
// 1 = disable calculations
int32 diDirectionalMode; // Directional mode
// 0 = enable directional calculations
// 1 = disable calculations
int32 diRangeMode; // Range mode
// 0 = use depth (Z) buffer calculation
// 1 = use slant range calculation
float32 sfMinPixelSize; // Minimum pixel size
// Minimum diameter of points in pixels
float32 sfMaxPixelSize; // Maximum pixel size
// Maximum diameter of points in pixels
float32 afActualPixelSize; // Actual size
// Actual diameter of points in database coordinates
float32 sfTranspFalloff; // Transparent falloff pixel size
// Diameter in pixels when points become transparent
float32 sfTranspFalloffExponent; // Transparent falloff exponent
// >= 0 - falloff multiplier exponent (1.0 = linear falloff)
float32 sfTranspFalloffScalar; // Transparent falloff scalar
// > 0 - falloff multiplier scale factor
float32 sfTranspFalloffClamp; // Transparent falloff clamp
// Minimum permissible falloff multiplier result
float32 sfFog; // Fog scalar
// >= 0 - adjusts range of points for punch threw effect.
float32 sfReserved;
float32 sfSize; // Size difference threshold
// Point size transition hint to renderer
int32 diDirection; // Directional type
// 0 = OMNIDIRECTIONAL
// 1 = UNIDIRECTIONAL
// 2 = BIDIRECTIONAL
float32 sfLobeHoriz; // Horizontal lobe angle [degrees]
float32 sfLobeVert; // Vertical lobe angle [degrees]
float32 sfLobeRoll; // Rotation of lobe about local Y axis [degrees]
float32 sfFalloff; // Directional falloff exponent
// >= 0 - falloff multiplier exponent
// (1.0 = linear falloff)
float32 sfAmbientIntensity; // Directional ambient intensity
float32 sfAnimPeriod; // Animation period [seconds]
float32 sfAnimPhaseDelay; // Animation phase delay [seconds]
float32 sfAnimPeriodEnable; // Animation enabled period [seconds]
float32 sfSignificance; // Drop out priority for RASCAL lights (0.0 - 1.0)
int32 sfDrawOrder; // Calligraphic draw order
uint32 sfFlags; // Flags (bits, from left to right)
// 0 = reserved
// 1 = No back color
// TRUE = don<6F>t use back color for
// bidirectional points
// FALSE = use back color for
// bidirectional points
// 2 = reserved
// 3 = Calligraphic proximity occulting (Debunching)
// 4 = Reflective, non-emissive point
// 5-7 = Randomize intensity
// 0 = never
// 1 = low
// 2 = medium
// 3 = high
// 8 = Perspective mode
// 9 = Flashing
// 10 = Rotating
// 11 = Rotate Counter Clockwise
// Direction of rotation about local Z axis
// 12 = reserved
// 13-14 = Quality
// 0 = Low
// 1 = Medium
// 2 = High
// 3 = Undefined
// 15 = Visible during day
// 16 = Visible during dusk
// 17 = Visible during night
// 18-31 = Spare
float32x3 animRot; // Axis of rotation for rotating animation
};
class LightPointRecord : public PrimNodeRecord
{
public:
LightPointRecord();
virtual Record* clone() const { return new LightPointRecord(); }
virtual const char* className() const { return "LightPointRecord"; }
virtual int classOpcode() const { return LIGHT_POINT_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
virtual SLightPoint* getData() const { return (SLightPoint*)_pData; }
protected:
virtual ~LightPointRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,38 @@
// LightSourcePaletteRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "LightSourcePaletteRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// LightSourcePaletteRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<LightSourcePaletteRecord> g_LightSourcePaletteProxy;
LightSourcePaletteRecord::LightSourcePaletteRecord()
{
}
// virtual
LightSourcePaletteRecord::~LightSourcePaletteRecord()
{
}
// virtual
void LightSourcePaletteRecord::endian()
{
}

View File

@@ -0,0 +1,66 @@
// LightSourcePaletteRecord.h
#ifndef __FLT_LIGHT_SOURCE_PALETTE_RECORD_H
#define __FLT_LIGHT_SOURCE_PALETTE_RECORD_H
#include "opcodes.h"
#include "Record.h"
#include "RecordVisitor.h"
namespace flt {
typedef struct LightSourcePaletteTag
{
SRecHeader RecHeader;
int32 diIndex; // Palette index
int32 diReserved_1[2];
char szName[20]; // Light source name
int32 diReserved_2;
float32 sfAmbientRGBA[4]; // Alpha comp. currently unused
float32 sfDiffuseRGBA[4]; // Alpha comp. currently unused
float32 sfSpecularRGBA[4]; // Alpha comp. currently unused
int32 diLightType; // 0 = INFINITE
// 1 = LOCAL
// 2 = SPOT
int32 diReserved_3[10];
float32 sfDropoff; // Spot exponential dropoff term
float32 sfCutoff; // Spot cutoff angle (radians)
float32 sfYaw;
float32 sfPitch;
float32 sfConstantAttuenation;
float32 sfLinearAttuenation;
float32 sfQuadraticAttuenation;
int32 diModelingLight; // TRUE/FALSE
int32 diSpare[19];
} SLightSourcePalette;
class LightSourcePaletteRecord : public AncillaryRecord
{
public:
LightSourcePaletteRecord();
virtual Record* clone() const { return new LightSourcePaletteRecord(); }
virtual const char* className() const { return "LightSourcePaletteRecord"; }
virtual int classOpcode() const { return LIGHT_SOURCE_PALETTE_OP; }
virtual void accept(RecordVisitor& rv) { rv.apply(*this); }
// virtual void traverse(RecordVisitor& rv);
protected:
virtual ~LightSourcePaletteRecord();
virtual void endian();
};
}; // end namespace flt
#endif

View File

@@ -0,0 +1,47 @@
// LightSourceRecord.cpp
#include "flt.h"
#include "Registry.h"
#include "LightSourceRecord.h"
using namespace flt;
////////////////////////////////////////////////////////////////////
//
// LightSourceRecord
//
////////////////////////////////////////////////////////////////////
RegisterRecordProxy<LightSourceRecord> g_LightSourceRecordProxy;
LightSourceRecord::LightSourceRecord()
{
}
// virtual
LightSourceRecord::~LightSourceRecord()
{
}
// virtual
void LightSourceRecord::endian()
{
SLightSource *pSLightSource = (SLightSource*)getData();
ENDIAN( pSLightSource->diReserved_1 );
ENDIAN( pSLightSource->diIndex );
ENDIAN( pSLightSource->diReserved_2 );
ENDIAN( pSLightSource->dwFlags );
ENDIAN( pSLightSource->diReserved_3 );
pSLightSource->Coord.endian();
ENDIAN( pSLightSource->sfYaw );
ENDIAN( pSLightSource->sfPitch );
}

Some files were not shown because too many files have changed in this diff Show More