2 PLIB - A Suite of Portable Game Libraries
3 Copyright (C) 1998,2002 Steve Baker
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 For further information visit http://plib.sourceforge.net
28 #include "ssgEntityArray.hxx"
31 // Forward declaration of internal ssg stuff (for hot/isec/los/etc.)
32 void _ssgPushPath ( ssgEntity *l ) ;
36 void ssgEntityArray::copy_from ( ssgEntityArray *src, int clone_flags )
38 ssgEntity::copy_from ( src, clone_flags ) ;
40 ssgEntity *k = src -> getModel ( ) ;
41 if ( k != NULL && ( clone_flags & SSG_CLONE_RECURSIVE ) )
42 setModel ( (ssgEntity *)( k -> clone ( clone_flags )) ) ;
46 ssgTransform *t = src -> getPosTransform();
47 if ( t != NULL && ( clone_flags & SSG_CLONE_RECURSIVE ) )
48 pos = (ssgTransform *)( t -> clone ( clone_flags ) );
52 ssgVertexArray *v = src -> getLocations();
53 if ( v != NULL && ( clone_flags & SSG_CLONE_RECURSIVE ) )
54 locations = (ssgVertexArray *)( v -> clone ( clone_flags ) );
58 v = src -> getOrientations();
59 if ( v != NULL && ( clone_flags & SSG_CLONE_RECURSIVE ) )
60 orientations = (ssgVertexArray *)( v -> clone ( clone_flags ) );
65 ssgBase *ssgEntityArray::clone ( int clone_flags )
67 ssgEntityArray *b = new ssgEntityArray ;
68 b -> copy_from ( this, clone_flags ) ;
74 ssgEntityArray::ssgEntityArray (void)
76 type = ssgTypeBranch () ;
77 pos = new ssgTransform;
78 locations = new ssgVertexArray();
79 orientations = new ssgVertexArray();
83 ssgEntityArray::~ssgEntityArray (void)
86 ssgDeRefDelete( pos );
87 locations->removeAll();
88 orientations->removeAll();
96 void ssgEntityArray::zeroSpareRecursive ()
100 model -> zeroSpareRecursive () ;
101 pos -> zeroSpareRecursive () ;
102 locations -> zeroSpareRecursive () ;
103 orientations -> zeroSpareRecursive () ;
107 void ssgEntityArray::recalcBSphere (void)
111 pos->removeAllKids();
112 pos->addKid( model );
114 for ( int i = 0; i < locations->getNum(); ++i ) {
116 sgSetCoord( &c, locations->get(i), orientations->get(i) );
117 pos->setTransform( &c );
118 extendBSphere( pos->getBSphere() );
121 pos->removeAllKids();
123 /* FIXME: Traverse placement list
124 for ( ssgEntity *k = getKid ( 0 ) ; k != NULL ; k = getNextKid () )
125 extendBSphere ( k -> getBSphere () ) ;
128 bsphere_is_invalid = FALSE ;
132 void ssgEntityArray::removeModel ()
134 model->deadBeefCheck () ;
135 ssgDeRefDelete ( model ) ;
139 void ssgEntityArray::replaceModel ( ssgEntity *new_entity )
142 setModel( new_entity );
146 void ssgEntityArray::addPlacement ( sgVec3 loc, sgVec3 orient )
148 locations->add( loc ) ;
149 orientations->add( orient ) ;
154 void ssgEntityArray::removeAllPlacements()
156 locations->removeAll();
157 orientations->removeAll();
162 void ssgEntityArray::print ( FILE *fd, char *indent, int how_much )
164 ssgEntity::print ( fd, indent, how_much ) ;
165 fprintf ( fd, "%s Num Kids=%d\n", indent, getNumKids() ) ;
167 if ( getNumParents() != getRef() )
168 ulSetError ( UL_WARNING, "Ref count doesn't tally with parent count" ) ;
171 { if ( bsphere.isEmpty() )
172 fprintf ( fd, "%s BSphere is Empty.\n", indent ) ;
174 fprintf ( fd, "%s BSphere R=%g, C=(%g,%g,%g)\n", indent,
175 bsphere.getRadius(), bsphere.getCenter()[0], bsphere.getCenter()[1], bsphere.getCenter()[2] ) ;
179 sprintf ( in, "%s ", indent ) ;
181 model -> print ( fd, in, how_much ) ;
186 void ssgEntityArray::getStats ( int *num_branches, int *num_leaves, int *num_tris, int *num_verts )
190 *num_branches = 1 ; /* this! */
195 model -> getStats ( & nb, & nl, & nt, & nv ) ;
196 *num_branches += nb * locations->getNum() ;
197 *num_leaves += nl * locations->getNum() ;
198 *num_tris += nt * locations->getNum() ;
199 *num_verts += nv * locations->getNum() ;
204 void ssgEntityArray::cull ( sgFrustum *f, sgMat4 m, int test_needed )
206 if ( ! preTravTests ( &test_needed, SSGTRAV_CULL ) )
209 int cull_result = cull_test ( f, m, test_needed ) ;
211 if ( cull_result == SSG_OUTSIDE )
214 pos->removeAllKids();
215 pos->addKid( model );
217 for ( int i = 0; i < locations->getNum(); ++i ) {
219 sgSetCoord( &c, locations->get(i), orientations->get(i) );
220 pos->setTransform( &c );
221 pos->cull( f, m, cull_result != SSG_INSIDE );
224 pos->removeAllKids();
226 postTravTests ( SSGTRAV_CULL ) ;
231 void ssgEntityArray::hot ( sgVec3 s, sgMat4 m, int test_needed )
233 if ( ! preTravTests ( &test_needed, SSGTRAV_HOT ) )
236 int hot_result = hot_test ( s, m, test_needed ) ;
238 if ( hot_result == SSG_OUTSIDE )
241 _ssgPushPath ( this ) ;
243 pos->removeAllKids();
244 pos->addKid( model );
246 for ( int i = 0; i < locations->getNum(); ++i ) {
248 sgSetCoord( &c, locations->get(i), orientations->get(i) );
249 pos->setTransform( &c );
250 pos->hot ( s, m, hot_result != SSG_INSIDE );
253 pos->removeAllKids();
257 postTravTests ( SSGTRAV_HOT ) ;
262 void ssgEntityArray::los ( sgVec3 s, sgMat4 m, int test_needed )
264 if ( ! preTravTests ( &test_needed, SSGTRAV_LOS ) )
267 int los_result = los_test ( s, m, test_needed ) ;
269 if ( los_result == SSG_OUTSIDE )
272 _ssgPushPath ( this ) ;
274 pos->removeAllKids();
275 pos->addKid( model );
277 for ( int i = 0; i < locations->getNum(); ++i ) {
279 sgSetCoord( &c, locations->get(i), orientations->get(i) );
280 pos->setTransform( &c );
281 pos->los ( s, m, los_result != SSG_INSIDE ) ;
284 pos->removeAllKids();
288 postTravTests ( SSGTRAV_LOS) ;
292 void ssgEntityArray::isect ( sgSphere *s, sgMat4 m, int test_needed )
294 if ( ! preTravTests ( &test_needed, SSGTRAV_ISECT ) )
297 int isect_result = isect_test ( s, m, test_needed ) ;
299 if ( isect_result == SSG_OUTSIDE )
302 _ssgPushPath ( this ) ;
304 pos->removeAllKids();
305 pos->addKid( model );
307 for ( int i = 0; i < locations->getNum(); ++i ) {
309 sgSetCoord( &c, locations->get(i), orientations->get(i) );
310 pos->setTransform( &c );
311 pos->isect ( s, m, isect_result != SSG_INSIDE ) ;
314 pos->removeAllKids();
318 postTravTests ( SSGTRAV_ISECT ) ;
323 int ssgEntityArray::load ( FILE *fd )
327 _ssgReadInt ( fd, & nkids ) ;
329 if ( ! ssgEntity::load ( fd ) )
332 for ( int i = 0 ; i < nkids ; i++ )
336 if ( ! _ssgLoadObject ( fd, (ssgBase **) &kid, ssgTypeEntity () ) )
346 int ssgEntityArray::save ( FILE *fd )
348 _ssgWriteInt ( fd, getNumKids() ) ;
350 if ( ! ssgEntity::save ( fd ) )
353 for ( int i = 0 ; i < getNumKids() ; i++ )
355 if ( ! _ssgSaveObject ( fd, getKid ( i ) ) )