From d5eedd2c6573ebfe044fa0ee1f31bb76062a0873 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 1 Nov 2005 09:45:10 +0000 Subject: [PATCH] Move Curt's ssgEntityArray experiment over to SimGear. --- simgear/screen/ssgEntityArray.cxx | 362 ++++++++++++++++++++++++++++++ simgear/screen/ssgEntityArray.hxx | 66 ++++++ 2 files changed, 428 insertions(+) create mode 100644 simgear/screen/ssgEntityArray.cxx create mode 100644 simgear/screen/ssgEntityArray.hxx diff --git a/simgear/screen/ssgEntityArray.cxx b/simgear/screen/ssgEntityArray.cxx new file mode 100644 index 00000000..d8ca2c64 --- /dev/null +++ b/simgear/screen/ssgEntityArray.cxx @@ -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 +#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 + diff --git a/simgear/screen/ssgEntityArray.hxx b/simgear/screen/ssgEntityArray.hxx new file mode 100644 index 00000000..659d6d6c --- /dev/null +++ b/simgear/screen/ssgEntityArray.hxx @@ -0,0 +1,66 @@ +#ifndef _SSG_ENTITY_ARRAY_HXX +#define _SSG_ENTITY_ARRAY_HXX + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + + +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 -- 2.39.5