Move Curt's ssgEntityArray experiment over to SimGear.

This commit is contained in:
ehofman 2005-11-01 09:45:10 +00:00
parent fe4f907099
commit d5eedd2c65
2 changed files with 428 additions and 0 deletions

View File

@ -0,0 +1,362 @@
/*
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information visit http://plib.sourceforge.net
$Id$
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "ssgEntityArray.hxx"
// Forward declaration of internal ssg stuff (for hot/isec/los/etc.)
void _ssgPushPath ( ssgEntity *l ) ;
void _ssgPopPath () ;
void ssgEntityArray::copy_from ( ssgEntityArray *src, int clone_flags )
{
ssgEntity::copy_from ( src, clone_flags ) ;
ssgEntity *k = src -> getModel ( ) ;
if ( k != NULL && ( clone_flags & SSG_CLONE_RECURSIVE ) )
setModel ( (ssgEntity *)( k -> clone ( clone_flags )) ) ;
else
setModel ( k ) ;
ssgTransform *t = src -> getPosTransform();
if ( t != NULL && ( clone_flags & SSG_CLONE_RECURSIVE ) )
pos = (ssgTransform *)( t -> clone ( clone_flags ) );
else
pos = t;
ssgVertexArray *v = src -> getLocations();
if ( v != NULL && ( clone_flags & SSG_CLONE_RECURSIVE ) )
locations = (ssgVertexArray *)( v -> clone ( clone_flags ) );
else
locations = v;
v = src -> getOrientations();
if ( v != NULL && ( clone_flags & SSG_CLONE_RECURSIVE ) )
orientations = (ssgVertexArray *)( v -> clone ( clone_flags ) );
else
orientations = v;
}
ssgBase *ssgEntityArray::clone ( int clone_flags )
{
ssgEntityArray *b = new ssgEntityArray ;
b -> copy_from ( this, clone_flags ) ;
return b ;
}
ssgEntityArray::ssgEntityArray (void)
{
type = ssgTypeBranch () ;
pos = new ssgTransform;
locations = new ssgVertexArray();
orientations = new ssgVertexArray();
}
ssgEntityArray::~ssgEntityArray (void)
{
removeModel() ;
ssgDeRefDelete( pos );
locations->removeAll();
orientations->removeAll();
delete orientations;
delete locations;
delete pos;
}
void ssgEntityArray::zeroSpareRecursive ()
{
zeroSpare () ;
model -> zeroSpareRecursive () ;
pos -> zeroSpareRecursive () ;
locations -> zeroSpareRecursive () ;
orientations -> zeroSpareRecursive () ;
}
void ssgEntityArray::recalcBSphere (void)
{
emptyBSphere () ;
pos->removeAllKids();
pos->addKid( model );
for ( int i = 0; i < locations->getNum(); ++i ) {
sgCoord c;
sgSetCoord( &c, locations->get(i), orientations->get(i) );
pos->setTransform( &c );
extendBSphere( pos->getBSphere() );
}
pos->removeAllKids();
/* FIXME: Traverse placement list
for ( ssgEntity *k = getKid ( 0 ) ; k != NULL ; k = getNextKid () )
extendBSphere ( k -> getBSphere () ) ;
*/
bsphere_is_invalid = FALSE ;
}
void ssgEntityArray::removeModel ()
{
model->deadBeefCheck () ;
ssgDeRefDelete ( model ) ;
}
void ssgEntityArray::replaceModel ( ssgEntity *new_entity )
{
removeModel();
setModel( new_entity );
}
void ssgEntityArray::addPlacement ( sgVec3 loc, sgVec3 orient )
{
locations->add( loc ) ;
orientations->add( orient ) ;
dirtyBSphere () ;
}
void ssgEntityArray::removeAllPlacements()
{
locations->removeAll();
orientations->removeAll();
dirtyBSphere () ;
}
void ssgEntityArray::print ( FILE *fd, char *indent, int how_much )
{
ssgEntity::print ( fd, indent, how_much ) ;
fprintf ( fd, "%s Num Kids=%d\n", indent, getNumKids() ) ;
if ( getNumParents() != getRef() )
ulSetError ( UL_WARNING, "Ref count doesn't tally with parent count" ) ;
if ( how_much > 1 )
{ if ( bsphere.isEmpty() )
fprintf ( fd, "%s BSphere is Empty.\n", indent ) ;
else
fprintf ( fd, "%s BSphere R=%g, C=(%g,%g,%g)\n", indent,
bsphere.getRadius(), bsphere.getCenter()[0], bsphere.getCenter()[1], bsphere.getCenter()[2] ) ;
}
char in [ 100 ] ;
sprintf ( in, "%s ", indent ) ;
model -> print ( fd, in, how_much ) ;
}
#ifdef HAVE_PLIB_PSL
void ssgEntityArray::getStats ( int *num_branches, int *num_leaves, int *num_tris, int *num_verts )
{
int nb, nl, nt, nv ;
*num_branches = 1 ; /* this! */
*num_leaves = 0 ;
*num_tris = 0 ;
*num_verts = 0 ;
model -> getStats ( & nb, & nl, & nt, & nv ) ;
*num_branches += nb * locations->getNum() ;
*num_leaves += nl * locations->getNum() ;
*num_tris += nt * locations->getNum() ;
*num_verts += nv * locations->getNum() ;
}
#endif
void ssgEntityArray::cull ( sgFrustum *f, sgMat4 m, int test_needed )
{
if ( ! preTravTests ( &test_needed, SSGTRAV_CULL ) )
return ;
int cull_result = cull_test ( f, m, test_needed ) ;
if ( cull_result == SSG_OUTSIDE )
return ;
pos->removeAllKids();
pos->addKid( model );
for ( int i = 0; i < locations->getNum(); ++i ) {
sgCoord c;
sgSetCoord( &c, locations->get(i), orientations->get(i) );
pos->setTransform( &c );
pos->cull( f, m, cull_result != SSG_INSIDE );
}
pos->removeAllKids();
postTravTests ( SSGTRAV_CULL ) ;
}
void ssgEntityArray::hot ( sgVec3 s, sgMat4 m, int test_needed )
{
if ( ! preTravTests ( &test_needed, SSGTRAV_HOT ) )
return ;
int hot_result = hot_test ( s, m, test_needed ) ;
if ( hot_result == SSG_OUTSIDE )
return ;
_ssgPushPath ( this ) ;
pos->removeAllKids();
pos->addKid( model );
for ( int i = 0; i < locations->getNum(); ++i ) {
sgCoord c;
sgSetCoord( &c, locations->get(i), orientations->get(i) );
pos->setTransform( &c );
pos->hot ( s, m, hot_result != SSG_INSIDE );
}
pos->removeAllKids();
_ssgPopPath () ;
postTravTests ( SSGTRAV_HOT ) ;
}
void ssgEntityArray::los ( sgVec3 s, sgMat4 m, int test_needed )
{
if ( ! preTravTests ( &test_needed, SSGTRAV_LOS ) )
return ;
int los_result = los_test ( s, m, test_needed ) ;
if ( los_result == SSG_OUTSIDE )
return ;
_ssgPushPath ( this ) ;
pos->removeAllKids();
pos->addKid( model );
for ( int i = 0; i < locations->getNum(); ++i ) {
sgCoord c;
sgSetCoord( &c, locations->get(i), orientations->get(i) );
pos->setTransform( &c );
pos->los ( s, m, los_result != SSG_INSIDE ) ;
}
pos->removeAllKids();
_ssgPopPath () ;
postTravTests ( SSGTRAV_LOS) ;
}
void ssgEntityArray::isect ( sgSphere *s, sgMat4 m, int test_needed )
{
if ( ! preTravTests ( &test_needed, SSGTRAV_ISECT ) )
return ;
int isect_result = isect_test ( s, m, test_needed ) ;
if ( isect_result == SSG_OUTSIDE )
return ;
_ssgPushPath ( this ) ;
pos->removeAllKids();
pos->addKid( model );
for ( int i = 0; i < locations->getNum(); ++i ) {
sgCoord c;
sgSetCoord( &c, locations->get(i), orientations->get(i) );
pos->setTransform( &c );
pos->isect ( s, m, isect_result != SSG_INSIDE ) ;
}
pos->removeAllKids();
_ssgPopPath () ;
postTravTests ( SSGTRAV_ISECT ) ;
}
#if 0
int ssgEntityArray::load ( FILE *fd )
{
int nkids ;
_ssgReadInt ( fd, & nkids ) ;
if ( ! ssgEntity::load ( fd ) )
return FALSE ;
for ( int i = 0 ; i < nkids ; i++ )
{
ssgEntity *kid ;
if ( ! _ssgLoadObject ( fd, (ssgBase **) &kid, ssgTypeEntity () ) )
return FALSE ;
addKid ( kid ) ;
}
return TRUE ;
}
int ssgEntityArray::save ( FILE *fd )
{
_ssgWriteInt ( fd, getNumKids() ) ;
if ( ! ssgEntity::save ( fd ) )
return FALSE ;
for ( int i = 0 ; i < getNumKids() ; i++ )
{
if ( ! _ssgSaveObject ( fd, getKid ( i ) ) )
return FALSE ;
}
return TRUE ;
}
#endif

View File

@ -0,0 +1,66 @@
#ifndef _SSG_ENTITY_ARRAY_HXX
#define _SSG_ENTITY_ARRAY_HXX
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <plib/ssg.h>
class ssgEntityArray : public ssgEntity
{
// The replicated child
ssgEntity *model ;
// The one transformation node
ssgTransform *pos;
// The list of locations and orientations
ssgVertexArray *locations;
ssgVertexArray *orientations;
protected:
virtual void copy_from ( ssgEntityArray *src, int clone_flags ) ;
public:
virtual void zeroSpareRecursive ();
virtual ssgBase *clone ( int clone_flags = 0 ) ;
ssgEntityArray (void) ;
virtual ~ssgEntityArray (void) ;
ssgEntity *getModel () const { return model ; }
void setModel ( ssgEntity *entity ) { model = entity; }
void removeModel () ;
void replaceModel ( ssgEntity *new_entity ) ;
ssgVertexArray *getLocations () const { return locations; }
ssgVertexArray *getOrientations () const { return orientations; }
float *getLocation ( int i ) const { return locations->get( i ); }
float *getOrientation ( int i ) const { return orientations->get( i ); }
void addPlacement ( sgVec3 loc, sgVec3 orient );
virtual int getNumPlacements() const { return locations->getNum(); }
void removeAllPlacements();
ssgTransform *getPosTransform() { return pos; }
virtual const char *getTypeName(void) ;
virtual void cull ( sgFrustum *f, sgMat4 m, int test_needed ) ;
virtual void isect ( sgSphere *s, sgMat4 m, int test_needed ) ;
virtual void hot ( sgVec3 s, sgMat4 m, int test_needed ) ;
virtual void los ( sgVec3 s, sgMat4 m, int test_needed ) ;
virtual void print ( FILE *fd = stderr, char *indent = "", int how_much = 2 ) ;
#ifdef HAVE_PLIB_PSL
virtual void getStats ( int *num_branches, int *num_leaves, int *num_tris, int *num_vertices ) ;
#endif
virtual int load ( FILE *fd ) ;
virtual int save ( FILE *fd ) ;
virtual void recalcBSphere () ;
} ;
#endif // _SSG_ENTITY_ARRAY_HXX