forestDataFile.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "forest/forestDataFile.h"
  24. #include "forest/forest.h"
  25. #include "forest/forestCell.h"
  26. #include "T3D/physics/physicsBody.h"
  27. #include "core/stream/fileStream.h"
  28. #include "core/resource.h"
  29. #include "math/mathIO.h"
  30. #include "math/mPoint2.h"
  31. #include "platform/profiler.h"
  32. template<> ResourceBase::Signature Resource<ForestData>::signature()
  33. {
  34. return MakeFourCC('f','k','d','f');
  35. }
  36. template<>
  37. void* Resource<ForestData>::create( const Torque::Path &path )
  38. {
  39. FileStream stream;
  40. stream.open( path.getFullPath(), Torque::FS::File::Read );
  41. if ( stream.getStatus() != Stream::Ok )
  42. return NULL;
  43. ForestData *file = new ForestData();
  44. if ( !file->read( stream ) )
  45. {
  46. delete file;
  47. return NULL;
  48. }
  49. return file;
  50. }
  51. U32 ForestData::smNextItemId = 1;
  52. ForestData::ForestData()
  53. : mIsDirty( false )
  54. {
  55. ForestItemData::getReloadSignal().notify( this, &ForestData::_onItemReload );
  56. }
  57. ForestData::~ForestData()
  58. {
  59. ForestItemData::getReloadSignal().remove( this, &ForestData::_onItemReload );
  60. clear();
  61. }
  62. void ForestData::clear()
  63. {
  64. // We only have to delete the top level cells and ForestCell will
  65. // clean up its sub-cells in its destructor.
  66. BucketTable::Iterator iter = mBuckets.begin();
  67. for ( ; iter != mBuckets.end(); iter++ ) delete iter->value;
  68. mBuckets.clear();
  69. mIsDirty = true;
  70. }
  71. bool ForestData::read( Stream &stream )
  72. {
  73. // Read our identifier... so we know we're
  74. // not reading in pure garbage.
  75. char id[4] = { 0 };
  76. stream.read( 4, id );
  77. if ( dMemcmp( id, "FKDF", 4 ) != 0 )
  78. {
  79. Con::errorf( "ForestDataFile::read() - This is not a Forest planting file!" );
  80. return false;
  81. }
  82. // Empty ourselves before we really begin reading.
  83. clear();
  84. // Now the version number.
  85. U8 version;
  86. stream.read( &version );
  87. if ( version > (U8)FILE_VERSION )
  88. {
  89. Con::errorf( "ForestDataFile::read() - This file was created with an newer version of Forest!" );
  90. return false;
  91. }
  92. // Read in the names of the ForestItemData datablocks
  93. // and recover the datablock.
  94. Vector<ForestItemData*> allDatablocks;
  95. U32 count;
  96. stream.read( &count );
  97. allDatablocks.setSize( count );
  98. for ( U32 i=0; i < count; i++ )
  99. {
  100. StringTableEntry name = stream.readSTString();
  101. ForestItemData* data = ForestItemData::find( name );
  102. // TODO: Change this to instead create a dummy forest data
  103. // for each so that the user can swap it with the right one.
  104. if ( data == NULL )
  105. {
  106. Con::warnf( "ForestData::read - ForestItemData named %s was not found.", name );
  107. Con::warnf( "Note this can occur if you have deleted or renamed datablocks prior to loading this forest and is not an 'error' in this scenario." );
  108. }
  109. allDatablocks[ i ] = data;
  110. }
  111. U8 dataIndex;
  112. Point3F pos;
  113. QuatF rot;
  114. F32 scale;
  115. ForestItemData* data;
  116. MatrixF xfm;
  117. U32 skippedItems = 0;
  118. // Read in the items.
  119. stream.read( &count );
  120. for ( U32 i=0; i < count; i++ )
  121. {
  122. stream.read( &dataIndex );
  123. mathRead( stream, &pos );
  124. mathRead( stream, &rot );
  125. stream.read( &scale );
  126. data = allDatablocks[ dataIndex ];
  127. if ( data )
  128. {
  129. rot.setMatrix( &xfm );
  130. xfm.setPosition( pos );
  131. addItem( smNextItemId++, data, xfm, scale );
  132. }
  133. else
  134. {
  135. skippedItems++;
  136. }
  137. }
  138. if ( skippedItems > 0 )
  139. Con::warnf( "ForestData::read - %i items were skipped because their datablocks were not found.", skippedItems );
  140. // Clear the dirty flag.
  141. mIsDirty = false;
  142. return true;
  143. }
  144. bool ForestData::write( const char *path )
  145. {
  146. // Open the stream.
  147. FileStream stream;
  148. if ( !stream.open( path, Torque::FS::File::Write ) )
  149. {
  150. Con::errorf( "ForestDataFile::write() - Failed opening stream!" );
  151. return false;
  152. }
  153. // Write our identifier... so we have a better
  154. // idea if we're reading pure garbage.
  155. stream.write( 4, "FKDF" );
  156. // Now the version number.
  157. stream.write( (U8)FILE_VERSION );
  158. // First gather all the ForestItemData datablocks
  159. // used by the items in the forest.
  160. Vector<ForestItemData*> allDatablocks;
  161. getDatablocks( &allDatablocks );
  162. // Write out the datablock list.
  163. U32 count = allDatablocks.size();
  164. stream.write( count );
  165. for ( U32 i=0; i < count; i++ )
  166. {
  167. StringTableEntry localName = allDatablocks[i]->getInternalName();
  168. TORQUE_UNUSED(localName);
  169. AssertFatal( localName != NULL && localName[0] != '\0', "ForestData::write - ForestItemData had no internal name set!" );
  170. stream.writeString( allDatablocks[i]->getInternalName() );
  171. }
  172. // Get a copy of all the items.
  173. Vector<ForestItem> items;
  174. getItems( &items );
  175. // Save the item count.
  176. stream.write( (U32)items.size() );
  177. // Save the items.
  178. Vector<ForestItem>::const_iterator iter = items.begin();
  179. for ( ; iter != items.end(); iter++ )
  180. {
  181. U8 dataIndex = find( allDatablocks.begin(), allDatablocks.end(), iter->getData() ) - allDatablocks.begin();
  182. stream.write( dataIndex );
  183. mathWrite( stream, iter->getPosition() );
  184. QuatF quat;
  185. quat.set( iter->getTransform() );
  186. mathWrite( stream, quat );
  187. stream.write( iter->getScale() );
  188. }
  189. // Clear the dirty flag.
  190. mIsDirty = false;
  191. return true;
  192. }
  193. void ForestData::regenCells()
  194. {
  195. Vector<ForestItem> items;
  196. getItems( &items );
  197. clear();
  198. for ( U32 i=0; i < items.size(); i++ )
  199. {
  200. const ForestItem &item = items[i];
  201. addItem( item.getKey(), item.getData(), item.getTransform(), item.getScale() );
  202. }
  203. mIsDirty = true;
  204. }
  205. ForestCell* ForestData::_findBucket( const Point2I &key ) const
  206. {
  207. BucketTable::ConstIterator iter = mBuckets.find( key );
  208. if ( iter != mBuckets.end() )
  209. return iter->value;
  210. else
  211. return NULL;
  212. }
  213. ForestCell* ForestData::_findOrCreateBucket( const Point3F &pos )
  214. {
  215. // Look it up.
  216. const Point2I key = _getBucketKey( pos );
  217. BucketTable::Iterator iter = mBuckets.find( key );
  218. ForestCell *bucket = NULL;
  219. if ( iter != mBuckets.end() )
  220. bucket = iter->value;
  221. else
  222. {
  223. bucket = new ForestCell( RectF( key.x, key.y, BUCKET_DIM, BUCKET_DIM ) );
  224. mBuckets.insertUnique( key, bucket );
  225. mIsDirty = true;
  226. }
  227. return bucket;
  228. }
  229. void ForestData::_onItemReload()
  230. {
  231. // Invalidate cell batches and bounds so they
  232. // will be regenerated next render.
  233. Vector<ForestCell*> stack;
  234. getCells( &stack );
  235. ForestCell *pCell;
  236. while ( !stack.empty() )
  237. {
  238. pCell = stack.last();
  239. stack.pop_back();
  240. if ( !pCell )
  241. continue;
  242. pCell->freeBatches();
  243. pCell->invalidateBounds();
  244. pCell->getChildren( &stack );
  245. }
  246. }
  247. const ForestItem& ForestData::addItem( ForestItemData *data,
  248. const Point3F &position,
  249. F32 rotation,
  250. F32 scale )
  251. {
  252. MatrixF xfm;
  253. xfm.set( EulerF( 0, 0, rotation ), position );
  254. return addItem( smNextItemId++,
  255. data,
  256. xfm,
  257. scale );
  258. }
  259. const ForestItem& ForestData::addItem( ForestItemKey key,
  260. ForestItemData *data,
  261. const MatrixF &xfm,
  262. F32 scale )
  263. {
  264. ForestCell *bucket = _findOrCreateBucket( xfm.getPosition() );
  265. mIsDirty = true;
  266. return bucket->insertItem( key, data, xfm, scale );
  267. }
  268. const ForestItem& ForestData::updateItem( ForestItemKey key,
  269. const Point3F &keyPosition,
  270. ForestItemData *newData,
  271. const MatrixF &newXfm,
  272. F32 newScale )
  273. {
  274. Point2I bucketKey = _getBucketKey( keyPosition );
  275. ForestCell *bucket = _findBucket( bucketKey );
  276. if ( !bucket || !bucket->removeItem( key, keyPosition, true ) )
  277. return ForestItem::Invalid;
  278. if ( bucket->isEmpty() )
  279. {
  280. delete bucket;
  281. mBuckets.erase( bucketKey );
  282. }
  283. return addItem( key, newData, newXfm, newScale );
  284. }
  285. const ForestItem& ForestData::updateItem( ForestItem &item )
  286. {
  287. return updateItem( item.getKey(),
  288. item.getPosition(),
  289. item.getData(),
  290. item.getTransform(),
  291. item.getScale() );
  292. }
  293. bool ForestData::removeItem( ForestItemKey key, const Point3F &keyPosition )
  294. {
  295. Point2I bucketkey = _getBucketKey( keyPosition );
  296. ForestCell *bucket = _findBucket( keyPosition );
  297. if ( !bucket || !bucket->removeItem( key, keyPosition, true ) )
  298. return false;
  299. if ( bucket->isEmpty() )
  300. {
  301. delete bucket;
  302. mBuckets.erase( bucketkey );
  303. }
  304. mIsDirty = true;
  305. return true;
  306. }
  307. const ForestItem& ForestData::findItem( ForestItemKey key, const Point3F &keyPos ) const
  308. {
  309. PROFILE_SCOPE( ForestData_findItem );
  310. AssertFatal( key != 0, "ForestCell::findItem() - Got null key!" );
  311. ForestCell *cell = _findBucket( keyPos );
  312. while ( cell && !cell->isLeaf() )
  313. cell = cell->getChildAt( keyPos );
  314. U32 index;
  315. if ( cell && cell->findIndexByKey( key, &index ) )
  316. return cell->getItems()[ index ];
  317. return ForestItem::Invalid;
  318. }
  319. const ForestItem& ForestData::findItem( ForestItemKey key ) const
  320. {
  321. PROFILE_SCOPE( ForestData_findItem_Slow );
  322. AssertFatal( key != 0, "ForestData::findItem() - Got null key!" );
  323. // Do an exhaustive search thru all the cells... this
  324. // is really crappy... we shouldn't do this regularly.
  325. Vector<const ForestCell*> stack;
  326. BucketTable::ConstIterator iter = mBuckets.begin();
  327. for ( ; iter != mBuckets.end(); iter++ )
  328. stack.push_back( iter->value );
  329. // Now loop till we run out of cells.
  330. while ( !stack.empty() )
  331. {
  332. // Pop off the next cell.
  333. const ForestCell *cell = stack.last();
  334. stack.pop_back();
  335. // Recurse thru non-leaf cells.
  336. if ( !cell->isLeaf() )
  337. {
  338. cell->getChildren( &stack );
  339. continue;
  340. }
  341. // Finally search for the item.
  342. U32 index;
  343. if ( cell->findIndexByKey( key, &index ) )
  344. return cell->getItems()[ index ];
  345. }
  346. return ForestItem::Invalid;
  347. }
  348. U32 ForestData::getItems( Vector<ForestItem> *outItems ) const
  349. {
  350. AssertFatal( outItems, "ForestData::getItems() - The output vector was NULL!" );
  351. PROFILE_SCOPE( ForestData_getItems );
  352. Vector<const ForestCell*> stack;
  353. U32 count = 0;
  354. BucketTable::ConstIterator iter = mBuckets.begin();
  355. for ( ; iter != mBuckets.end(); iter++ )
  356. stack.push_back( iter->value );
  357. // Now loop till we run out of cells.
  358. while ( !stack.empty() )
  359. {
  360. // Pop off the next cell.
  361. const ForestCell *cell = stack.last();
  362. stack.pop_back();
  363. // Recurse thru non-leaf cells.
  364. if ( !cell->isLeaf() )
  365. {
  366. cell->getChildren( &stack );
  367. continue;
  368. }
  369. // Get the items.
  370. count += cell->getItems().size();
  371. outItems->merge( cell->getItems() );
  372. }
  373. return count;
  374. }
  375. U32 ForestData::getItems( const Frustum &culler, Vector<ForestItem> *outItems ) const
  376. {
  377. AssertFatal( outItems, "ForestData::getItems() - The output vector was NULL!" );
  378. PROFILE_SCOPE( ForestData_getItems_ByFrustum );
  379. Vector<ForestCell*> stack;
  380. getCells( &stack );
  381. Vector<ForestItem>::const_iterator iter;
  382. U32 count = 0;
  383. // Now loop till we run out of cells.
  384. while ( !stack.empty() )
  385. {
  386. // Pop off the next cell.
  387. const ForestCell *cell = stack.last();
  388. stack.pop_back();
  389. if ( culler.isCulled( cell->getBounds() ) )
  390. continue;
  391. // Recurse thru non-leaf cells.
  392. if ( cell->isBranch() )
  393. {
  394. cell->getChildren( &stack );
  395. continue;
  396. }
  397. // Get the items.
  398. iter = cell->getItems().begin();
  399. for ( ; iter != cell->getItems().end(); iter++ )
  400. {
  401. if ( !culler.isCulled( iter->getWorldBox() ) )
  402. {
  403. outItems->merge( cell->getItems() );
  404. count++;
  405. }
  406. }
  407. }
  408. return count;
  409. }
  410. U32 ForestData::getItems( const Box3F &box, Vector<ForestItem> *outItems ) const
  411. {
  412. PROFILE_SCOPE( ForestData_getItems_ByBox );
  413. Vector<const ForestCell*> stack;
  414. U32 count = 0;
  415. BucketTable::ConstIterator iter = mBuckets.begin();
  416. for ( ; iter != mBuckets.end(); iter++ )
  417. stack.push_back( iter->value );
  418. // Now loop till we run out of cells.
  419. while ( !stack.empty() )
  420. {
  421. // Pop off the next cell.
  422. const ForestCell *cell = stack.last();
  423. stack.pop_back();
  424. // If the cell is empty or doesn't overlap the box... skip it.
  425. if ( cell->isEmpty() ||
  426. !cell->getBounds().isOverlapped( box ) )
  427. continue;
  428. // Recurse thru non-leaf cells.
  429. if ( !cell->isLeaf() )
  430. {
  431. cell->getChildren( &stack );
  432. continue;
  433. }
  434. // Finally look thru the items.
  435. const Vector<ForestItem> &items = cell->getItems();
  436. Vector<ForestItem>::const_iterator item = items.begin();
  437. for ( ; item != items.end(); item++ )
  438. {
  439. if ( item->getWorldBox().isOverlapped( box ) )
  440. {
  441. // If we don't have an output vector then the user just
  442. // wanted to know if any object existed... so early out.
  443. if ( !outItems )
  444. return 1;
  445. ++count;
  446. outItems->push_back( *item );
  447. }
  448. }
  449. }
  450. return count;
  451. }
  452. U32 ForestData::getItems( const Point3F &point, F32 radius, Vector<ForestItem> *outItems ) const
  453. {
  454. PROFILE_SCOPE( ForestData_getItems_BySphere );
  455. Vector<const ForestCell*> stack;
  456. U32 count = 0;
  457. BucketTable::ConstIterator iter = mBuckets.begin();
  458. for ( ; iter != mBuckets.end(); iter++ )
  459. stack.push_back( iter->value );
  460. const F32 radiusSq = radius * radius;
  461. // Now loop till we run out of cells.
  462. while ( !stack.empty() )
  463. {
  464. // Pop off the next cell.
  465. const ForestCell *cell = stack.last();
  466. stack.pop_back();
  467. // TODO: If we could know here that the cell is fully within
  468. // the sphere... we could do a fast gather of all its elements
  469. // without any further testing of it or its children.
  470. // If the cell is empty or doesn't overlap the sphere... skip it.
  471. if ( cell->isEmpty() ||
  472. cell->getBounds().getSqDistanceToPoint( point ) > radiusSq )
  473. continue;
  474. // Recurse thru non-leaf cells.
  475. if ( !cell->isLeaf() )
  476. {
  477. cell->getChildren( &stack );
  478. continue;
  479. }
  480. // Finally look thru the items.
  481. const Vector<ForestItem> &items = cell->getItems();
  482. Vector<ForestItem>::const_iterator item = items.begin();
  483. for ( ; item != items.end(); item++ )
  484. {
  485. if ( item->getWorldBox().getSqDistanceToPoint( point ) < radiusSq )
  486. {
  487. // If we don't have an output vector then the user just
  488. // wanted to know if any object existed... so early out.
  489. if ( !outItems )
  490. return 1;
  491. ++count;
  492. outItems->push_back( *item );
  493. }
  494. }
  495. }
  496. return count;
  497. }
  498. U32 ForestData::getItems( const Point2F &point, F32 radius, Vector<ForestItem> *outItems ) const
  499. {
  500. PROFILE_SCOPE( ForestData_getItems_ByCircle );
  501. Vector<const ForestCell*> stack;
  502. U32 count = 0;
  503. BucketTable::ConstIterator iter = mBuckets.begin();
  504. for ( ; iter != mBuckets.end(); iter++ )
  505. stack.push_back( iter->value );
  506. const F32 radiusSq = radius * radius;
  507. // Now loop till we run out of cells.
  508. while ( !stack.empty() )
  509. {
  510. // Pop off the next cell.
  511. const ForestCell *cell = stack.last();
  512. stack.pop_back();
  513. // If the cell is empty or doesn't overlap the sphere... skip it.
  514. if ( cell->isEmpty() ||
  515. cell->getRect().getSqDistanceToPoint( point ) > radiusSq )
  516. continue;
  517. // Recurse thru non-leaf cells.
  518. if ( !cell->isLeaf() )
  519. {
  520. cell->getChildren( &stack );
  521. continue;
  522. }
  523. // Finally look thru the items.
  524. const Vector<ForestItem> &items = cell->getItems();
  525. Vector<ForestItem>::const_iterator item = items.begin();
  526. F32 compareDist;
  527. for ( ; item != items.end(); item++ )
  528. {
  529. compareDist = mSquared( radius + item->getData()->mRadius );
  530. if ( item->getSqDistanceToPoint( point ) < compareDist )
  531. {
  532. // If we don't have an output vector then the user just
  533. // wanted to know if any object existed... so early out.
  534. if ( !outItems )
  535. return 1;
  536. ++count;
  537. outItems->push_back( *item );
  538. }
  539. }
  540. }
  541. return count;
  542. }
  543. U32 ForestData::getItems( const ForestItemData *data, Vector<ForestItem> *outItems ) const
  544. {
  545. AssertFatal( outItems, "ForestData::getItems() - The output vector was NULL!" );
  546. PROFILE_SCOPE( ForestData_getItems_ByDatablock );
  547. Vector<const ForestCell*> stack;
  548. U32 count = 0;
  549. BucketTable::ConstIterator iter = mBuckets.begin();
  550. for ( ; iter != mBuckets.end(); iter++ )
  551. stack.push_back( iter->value );
  552. // Now loop till we run out of cells.
  553. while ( !stack.empty() )
  554. {
  555. // Pop off the next cell.
  556. const ForestCell *cell = stack.last();
  557. stack.pop_back();
  558. // Recurse thru non-leaf cells.
  559. if ( !cell->isLeaf() )
  560. {
  561. cell->getChildren( &stack );
  562. continue;
  563. }
  564. // Get the items.
  565. const Vector<ForestItem> &items = cell->getItems();
  566. Vector<ForestItem>::const_iterator item = items.begin();
  567. for ( ; item != items.end(); item++ )
  568. {
  569. if ( item->getData() == data )
  570. {
  571. ++count;
  572. outItems->push_back( *item );
  573. }
  574. }
  575. }
  576. return count;
  577. }
  578. void ForestData::getCells( const Frustum &frustum, Vector<ForestCell*> *outCells ) const
  579. {
  580. PROFILE_SCOPE( ForestData_getCells_frustum );
  581. BucketTable::ConstIterator iter = mBuckets.begin();
  582. for ( ; iter != mBuckets.end(); iter++ )
  583. {
  584. if ( !frustum.isCulled( iter->value->getBounds() ) )
  585. outCells->push_back( iter->value );
  586. }
  587. }
  588. void ForestData::getCells( Vector<ForestCell*> *outCells ) const
  589. {
  590. PROFILE_SCOPE( ForestData_getCells_nofrustum );
  591. BucketTable::ConstIterator iter = mBuckets.begin();
  592. for ( ; iter != mBuckets.end(); iter++ )
  593. outCells->push_back( iter->value );
  594. }
  595. U32 ForestData::getDatablocks( Vector<ForestItemData*> *outVector ) const
  596. {
  597. Vector<const ForestCell*> stack;
  598. U32 count = 0;
  599. BucketTable::ConstIterator iter = mBuckets.begin();
  600. for ( ; iter != mBuckets.end(); iter++ )
  601. stack.push_back( iter->value );
  602. // Now loop till we run out of cells.
  603. while ( !stack.empty() )
  604. {
  605. // Pop off the next cell.
  606. const ForestCell *cell = stack.last();
  607. stack.pop_back();
  608. // Recurse thru non-leaf cells.
  609. if ( !cell->isLeaf() )
  610. {
  611. cell->getChildren( &stack );
  612. continue;
  613. }
  614. // Go thru the items.
  615. const Vector<ForestItem> &items = cell->getItems();
  616. Vector<ForestItem>::const_iterator item = items.begin();
  617. for ( ; item != items.end(); item++ )
  618. {
  619. ForestItemData *data = item->getData();
  620. if ( find( outVector->begin(), outVector->end(), data ) != outVector->end() )
  621. continue;
  622. count++;
  623. outVector->push_back( data );
  624. }
  625. }
  626. return count;
  627. }
  628. void ForestData::clearPhysicsRep( Forest *forest )
  629. {
  630. Vector<ForestCell*> stack;
  631. BucketTable::Iterator iter = mBuckets.begin();
  632. for ( ; iter != mBuckets.end(); iter++ )
  633. stack.push_back( iter->value );
  634. // Now loop till we run out of cells.
  635. while ( !stack.empty() )
  636. {
  637. // Pop off the next cell.
  638. ForestCell *cell = stack.last();
  639. stack.pop_back();
  640. // Recurse thru non-leaf cells.
  641. if ( !cell->isLeaf() )
  642. {
  643. cell->getChildren( &stack );
  644. continue;
  645. }
  646. cell->clearPhysicsRep( forest );
  647. }
  648. }
  649. void ForestData::buildPhysicsRep( Forest *forest )
  650. {
  651. Vector<ForestCell*> stack;
  652. BucketTable::Iterator iter = mBuckets.begin();
  653. for ( ; iter != mBuckets.end(); iter++ )
  654. stack.push_back( iter->value );
  655. // Now loop till we run out of cells.
  656. while ( !stack.empty() )
  657. {
  658. // Pop off the next cell.
  659. ForestCell *cell = stack.last();
  660. stack.pop_back();
  661. // Recurse thru non-leaf cells.
  662. if ( !cell->isLeaf() )
  663. {
  664. cell->getChildren( &stack );
  665. continue;
  666. }
  667. cell->buildPhysicsRep( forest );
  668. }
  669. }