PageRenderTime 26ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/CS/migrated/branches/R0_98/plugins/engine/3d/meshobj.cpp

#
C++ | 1420 lines | 1104 code | 179 blank | 137 comment | 142 complexity | 5c73557db7fac1a8f60b0e8a6b09c448 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Copyright (C) 2000-2004 by Jorrit Tyberghein
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public
  12. License along with this library; if not, write to the Free
  13. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "cssysdef.h"
  16. #include "qsqrt.h"
  17. #include "csgeom/sphere.h"
  18. #include "igeom/objmodel.h"
  19. #include "plugins/engine/3d/sector.h"
  20. #include "plugins/engine/3d/meshobj.h"
  21. #include "plugins/engine/3d/meshlod.h"
  22. #include "plugins/engine/3d/light.h"
  23. #include "plugins/engine/3d/engine.h"
  24. #include "iengine/portal.h"
  25. #include "csutil/debug.h"
  26. #include "iengine/rview.h"
  27. #include "ivideo/graph3d.h"
  28. // ---------------------------------------------------------------------------
  29. // Implementations of iShadowCaster and iShadowReceiver that are used
  30. // in case of static lod.
  31. // Static shadow caster will cast shadows from the least detailed object
  32. // that actually has a shadow caster.
  33. class csStaticShadowCaster : public iShadowCaster
  34. {
  35. private:
  36. // Pointer back to the mesh with static lod.
  37. csMeshWrapper* static_lod_mesh;
  38. public:
  39. csStaticShadowCaster (csMeshWrapper* m)
  40. {
  41. SCF_CONSTRUCT_IBASE (0);
  42. static_lod_mesh = m;
  43. }
  44. virtual ~csStaticShadowCaster ()
  45. {
  46. SCF_DESTRUCT_IBASE ();
  47. }
  48. SCF_DECLARE_IBASE;
  49. virtual void AppendShadows (iMovable* movable, iShadowBlockList* shadows,
  50. const csVector3& origin)
  51. {
  52. const csMeshMeshList& c = static_lod_mesh->GetChildren ();
  53. int cnt = c.GetCount ();
  54. int i = 0;
  55. while (i < cnt)
  56. {
  57. iMeshWrapper* child = c.Get (i);
  58. if (child && child->GetShadowCaster ())
  59. {
  60. child->GetShadowCaster ()->AppendShadows (movable, shadows, origin);
  61. return;
  62. }
  63. i++;
  64. }
  65. }
  66. };
  67. SCF_IMPLEMENT_IBASE(csStaticShadowCaster)
  68. SCF_IMPLEMENTS_INTERFACE(iShadowCaster)
  69. SCF_IMPLEMENT_IBASE_END
  70. // Static shadow receiver will send the received shadows to all children
  71. // of the static lod mesh.
  72. class csStaticShadowReceiver : public iShadowReceiver
  73. {
  74. private:
  75. // Pointer back to the mesh with static lod.
  76. csMeshWrapper* static_lod_mesh;
  77. public:
  78. csStaticShadowReceiver (csMeshWrapper* m)
  79. {
  80. SCF_CONSTRUCT_IBASE (0);
  81. static_lod_mesh = m;
  82. }
  83. virtual ~csStaticShadowReceiver ()
  84. {
  85. SCF_DESTRUCT_IBASE ();
  86. }
  87. SCF_DECLARE_IBASE;
  88. virtual void CastShadows (iMovable* movable, iFrustumView* fview)
  89. {
  90. const csMeshMeshList& c = static_lod_mesh->GetChildren ();
  91. int cnt = c.GetCount ();
  92. int i;
  93. for (i = 0 ; i < cnt ; i++)
  94. {
  95. iMeshWrapper* child = c.Get (i);
  96. if (child && child->GetShadowReceiver ())
  97. child->GetShadowReceiver ()->CastShadows (movable, fview);
  98. }
  99. }
  100. };
  101. SCF_IMPLEMENT_IBASE(csStaticShadowReceiver)
  102. SCF_IMPLEMENTS_INTERFACE(iShadowReceiver)
  103. SCF_IMPLEMENT_IBASE_END
  104. // ---------------------------------------------------------------------------
  105. // csMeshWrapper
  106. // ---------------------------------------------------------------------------
  107. SCF_IMPLEMENT_IBASE_EXT(csMeshWrapper)
  108. SCF_IMPLEMENTS_EMBEDDED_INTERFACE(iMeshWrapper)
  109. SCF_IMPLEMENTS_EMBEDDED_INTERFACE(iImposter)
  110. SCF_IMPLEMENTS_INTERFACE(csMeshWrapper)
  111. SCF_IMPLEMENTS_INTERFACE(iVisibilityObject)
  112. SCF_IMPLEMENT_IBASE_EXT_END
  113. SCF_IMPLEMENT_EMBEDDED_IBASE (csMeshWrapper::MeshWrapper)
  114. SCF_IMPLEMENTS_INTERFACE(iMeshWrapper)
  115. SCF_IMPLEMENT_EMBEDDED_IBASE_END
  116. SCF_IMPLEMENT_EMBEDDED_IBASE (csMeshWrapper::MeshImposter)
  117. SCF_IMPLEMENTS_INTERFACE(iImposter)
  118. SCF_IMPLEMENT_EMBEDDED_IBASE_END
  119. csMeshWrapper::csMeshWrapper (iMeshWrapper *theParent, iMeshObject *meshobj) :
  120. csObject ()
  121. {
  122. SCF_CONSTRUCT_EMBEDDED_IBASE (scfiMeshWrapper);
  123. SCF_CONSTRUCT_EMBEDDED_IBASE (scfiImposter);
  124. DG_TYPE (this, "csMeshWrapper");
  125. movable.scfParent = (iBase*)(csObject*)this;
  126. visnr = 0;
  127. wor_bbox_movablenr = -1;
  128. movable.SetMeshWrapper (this);
  129. Parent = theParent;
  130. if (Parent)
  131. {
  132. csParent = ((csMeshWrapper::MeshWrapper*)Parent)->scfParent;
  133. movable.SetParent (Parent->GetMovable ());
  134. }
  135. else
  136. {
  137. csParent = 0;
  138. }
  139. render_priority = csEngine::current_engine->GetObjectRenderPriority ();
  140. last_anim_time = 0;
  141. shadow_receiver_valid = false;
  142. shadow_caster_valid = false;
  143. csMeshWrapper::meshobj = meshobj;
  144. if (meshobj)
  145. {
  146. light_info = SCF_QUERY_INTERFACE (meshobj, iLightingInfo);
  147. portal_container = SCF_QUERY_INTERFACE (meshobj, iPortalContainer);
  148. // Only if we have a parent can it possibly be useful to call
  149. // AddToSectorPortalLists. Because if we don't have a parent yet then
  150. // we cannot have a sector either. If we have a parent then the parent
  151. // can have a sector.
  152. if (csParent)
  153. AddToSectorPortalLists ();
  154. }
  155. factory = 0;
  156. zbufMode = CS_ZBUF_USE;
  157. children.SetMesh (this);
  158. imposter_active = false;
  159. imposter_mesh = 0;
  160. cast_hardware_shadow = true;
  161. draw_after_fancy_stuff = false;
  162. relevant_lights_valid = false;
  163. relevant_lights_max = 8;
  164. relevant_lights_flags.SetAll (CS_LIGHTINGUPDATE_SORTRELEVANCE);
  165. }
  166. void csMeshWrapper::SetParentContainer (iMeshWrapper* newParent)
  167. {
  168. Parent = newParent;
  169. if (Parent)
  170. csParent = ((csMeshWrapper::MeshWrapper*)Parent)->scfParent;
  171. else
  172. csParent = 0;
  173. }
  174. iShadowReceiver* csMeshWrapper::GetShadowReceiver ()
  175. {
  176. if (!shadow_receiver_valid)
  177. {
  178. if (static_lod)
  179. {
  180. shadow_receiver_valid = true;
  181. shadow_receiver = csPtr<iShadowReceiver> (
  182. new csStaticShadowReceiver (this));
  183. return shadow_receiver;
  184. }
  185. if (!meshobj) return 0;
  186. shadow_receiver_valid = true;
  187. shadow_receiver = SCF_QUERY_INTERFACE (meshobj, iShadowReceiver);
  188. }
  189. return shadow_receiver;
  190. }
  191. iShadowCaster* csMeshWrapper::GetShadowCaster ()
  192. {
  193. if (!shadow_caster_valid)
  194. {
  195. if (static_lod)
  196. {
  197. shadow_caster_valid = true;
  198. shadow_caster = csPtr<iShadowCaster> (
  199. new csStaticShadowCaster (this));
  200. return shadow_caster;
  201. }
  202. if (!meshobj) return 0;
  203. shadow_caster_valid = true;
  204. shadow_caster = SCF_QUERY_INTERFACE (meshobj, iShadowCaster);
  205. }
  206. return shadow_caster;
  207. }
  208. void csMeshWrapper::AddToSectorPortalLists ()
  209. {
  210. if (portal_container)
  211. {
  212. int i;
  213. csMeshWrapper* prev = this;
  214. csMeshWrapper* m = csParent;
  215. while (m) { prev = m; m = m->GetCsParent (); }
  216. const iSectorList *sectors = prev->GetCsMovable ().GetSectors ();
  217. for (i = 0; i < sectors->GetCount (); i++)
  218. {
  219. iSector *ss = sectors->Get (i);
  220. if (ss) ss->RegisterPortalMesh (&scfiMeshWrapper);
  221. }
  222. }
  223. }
  224. void csMeshWrapper::ClearFromSectorPortalLists ()
  225. {
  226. if (portal_container)
  227. {
  228. int i;
  229. csMeshWrapper* prev = this;
  230. csMeshWrapper* m = csParent;
  231. while (m) { prev = m; m = m->GetCsParent (); }
  232. const iSectorList *sectors = prev->GetCsMovable ().GetSectors ();
  233. for (i = 0; i < sectors->GetCount (); i++)
  234. {
  235. iSector *ss = sectors->Get (i);
  236. if (ss) ss->UnregisterPortalMesh (&scfiMeshWrapper);
  237. }
  238. }
  239. }
  240. void csMeshWrapper::SetMeshObject (iMeshObject *meshobj)
  241. {
  242. ClearFromSectorPortalLists ();
  243. csMeshWrapper::meshobj = meshobj;
  244. shadow_receiver_valid = false;
  245. shadow_caster_valid = false;
  246. shadow_receiver = 0;
  247. shadow_caster = 0;
  248. if (meshobj)
  249. {
  250. light_info = SCF_QUERY_INTERFACE (meshobj, iLightingInfo);
  251. portal_container = SCF_QUERY_INTERFACE (meshobj, iPortalContainer);
  252. AddToSectorPortalLists ();
  253. }
  254. else
  255. {
  256. light_info = 0;
  257. portal_container = 0;
  258. }
  259. }
  260. csMeshWrapper::~csMeshWrapper ()
  261. {
  262. delete imposter_mesh;
  263. ClearFromSectorPortalLists ();
  264. SCF_DESTRUCT_EMBEDDED_IBASE (scfiImposter);
  265. SCF_DESTRUCT_EMBEDDED_IBASE (scfiMeshWrapper);
  266. }
  267. void csMeshWrapper::UpdateMove ()
  268. {
  269. relevant_lights_valid = false;
  270. int i;
  271. for (i = 0; i < children.GetCount (); i++)
  272. {
  273. iMeshWrapper *spr = children.Get (i);
  274. spr->GetMovable ()->UpdateMove ();
  275. }
  276. }
  277. bool csMeshWrapper::SomeParentHasStaticLOD () const
  278. {
  279. if (!csParent) return false;
  280. if (csParent->static_lod) return true;
  281. return csParent->SomeParentHasStaticLOD ();
  282. }
  283. void csMeshWrapper::MoveToSector (iSector *s)
  284. {
  285. // Only add this mesh to a sector if the parent is the engine.
  286. // Otherwise we have a hierarchical object and in that case
  287. // the parent object controls this.
  288. if (!Parent) s->GetMeshes ()->Add (&scfiMeshWrapper);
  289. // If we are a portal container then we have to register ourselves
  290. // to the sector.
  291. if (portal_container) s->RegisterPortalMesh (&scfiMeshWrapper);
  292. int i;
  293. for (i = 0; i < children.GetCount (); i++)
  294. {
  295. iMeshWrapper* spr = children.Get (i);
  296. csMeshWrapper* cspr = ((csMeshWrapper::MeshWrapper*)spr)->scfParent;
  297. // If we have children then we call MoveToSector() on them so that
  298. // any potential portal_containers among them will also register
  299. // themselves to the sector.
  300. cspr->MoveToSector (s);
  301. }
  302. }
  303. void csMeshWrapper::RemoveFromSectors ()
  304. {
  305. ClearFromSectorPortalLists ();
  306. int i;
  307. for (i = 0; i < children.GetCount (); i++)
  308. {
  309. iMeshWrapper* spr = children.Get (i);
  310. csMeshWrapper* cspr = ((csMeshWrapper::MeshWrapper*)spr)->scfParent;
  311. // If we have children then we call RemoveFromSectors() on them so that
  312. // any potential portal_containers among them will also unregister
  313. // themselves from the sector.
  314. cspr->RemoveFromSectors ();
  315. }
  316. if (Parent) return ;
  317. const iSectorList *sectors = movable.GetSectors ();
  318. for (i = 0; i < sectors->GetCount (); i++)
  319. {
  320. iSector *ss = sectors->Get (i);
  321. if (ss)
  322. ss->GetMeshes ()->Remove (&scfiMeshWrapper);
  323. }
  324. }
  325. void csMeshWrapper::SetFlagsRecursive (uint32 mask, uint32 value)
  326. {
  327. flags.Set (mask, value);
  328. const iMeshList* ml = &GetChildren ();
  329. if (!ml) return;
  330. int i;
  331. for (i = 0 ; i < ml->GetCount () ; i++)
  332. ml->Get (i)->SetFlagsRecursive (mask, value);
  333. }
  334. void csMeshWrapper::SetZBufModeRecursive (csZBufMode mode)
  335. {
  336. SetZBufMode (mode);
  337. const iMeshList* ml = &GetChildren ();
  338. if (!ml) return;
  339. int i;
  340. for (i = 0 ; i < ml->GetCount () ; i++)
  341. ml->Get (i)->SetZBufModeRecursive (mode);
  342. }
  343. void csMeshWrapper::SetRenderPriorityRecursive (long rp)
  344. {
  345. SetRenderPriority (rp);
  346. const iMeshList* ml = &GetChildren ();
  347. if (!ml) return;
  348. int i;
  349. for (i = 0 ; i < ml->GetCount () ; i++)
  350. ml->Get (i)->SetRenderPriorityRecursive (rp);
  351. }
  352. void csMeshWrapper::SetRenderPriority (long rp)
  353. {
  354. render_priority = rp;
  355. if (Parent) return ;
  356. int i;
  357. const iSectorList *sectors = movable.GetSectors ();
  358. for (i = 0; i < sectors->GetCount (); i++)
  359. {
  360. iSector *ss = sectors->Get (i);
  361. if (ss) ss->GetPrivateObject ()->RelinkMesh (&scfiMeshWrapper);
  362. }
  363. }
  364. void csMeshWrapper::SetLightingUpdate (int flags, int num_lights)
  365. {
  366. relevant_lights_flags.SetAll (flags);
  367. relevant_lights_max = num_lights;
  368. relevant_lights_valid = false;
  369. }
  370. const csArray<iLight*>& csMeshWrapper::GetRelevantLights (int /*maxLights*/,
  371. bool /*desireSorting*/)
  372. {
  373. bool always_update = relevant_lights_flags.Check (
  374. CS_LIGHTINGUPDATE_ALWAYSUPDATE);
  375. if (!always_update)
  376. {
  377. // Check if updating is needed.
  378. if (relevant_lights_valid)
  379. {
  380. // Object didn't move. Now check lights (moved or destroyed).
  381. bool relevant = true;
  382. int i;
  383. for (i = 0 ; i < relevant_lights.Length () ; i++)
  384. {
  385. iLight* l = relevant_lights[i];
  386. if (!relevant_lights_ref[i].light)
  387. {
  388. relevant = false; // Light was removed!
  389. break;
  390. }
  391. if (l->GetLightNumber () != relevant_lights_ref[i].light_nr)
  392. {
  393. relevant = false; // Light was removed!
  394. break;
  395. }
  396. }
  397. if (relevant)
  398. return relevant_lights;
  399. }
  400. }
  401. relevant_lights.Empty ();
  402. relevant_lights_ref.Empty ();
  403. const iSectorList *movable_sectors = movable.GetSectors ();
  404. if (movable_sectors->GetCount () > 0 && relevant_lights_max > 0)
  405. {
  406. csBox3 box;
  407. GetFullBBox (box);
  408. if (relevant_lights_max > relevant_lights.Length ())
  409. relevant_lights.SetLength (relevant_lights_max);
  410. iSector *sect = movable_sectors->Get (0);
  411. int num_lights = csEngine::current_iengine->GetNearbyLights (
  412. sect,
  413. box,
  414. relevant_lights.GetArray (),
  415. relevant_lights_max);
  416. relevant_lights.SetLength (num_lights);
  417. relevant_lights_ref.SetLength (num_lights);
  418. if (!always_update)
  419. {
  420. // Update our ref list.
  421. int i;
  422. for (i = 0 ; i < num_lights ; i++)
  423. {
  424. relevant_lights_ref[i].light = relevant_lights[i];
  425. relevant_lights_ref[i].light_nr = relevant_lights[i]->GetLightNumber ();
  426. }
  427. }
  428. }
  429. relevant_lights_valid = true;
  430. return relevant_lights;
  431. }
  432. void csMeshWrapper::Draw (iRenderView *rview, uint32 frustum_mask)
  433. {
  434. if (flags.Check (CS_ENTITY_INVISIBLEMESH)) return;
  435. DrawInt (rview, frustum_mask);
  436. }
  437. csRenderMesh** csMeshWrapper::GetRenderMeshes (int& n, iRenderView* rview,
  438. iMovable* mov,
  439. uint32 frustum_mask)
  440. {
  441. // iMeshWrapper *meshwrap = &scfiMeshWrapper;
  442. //int i;
  443. // Callback are traversed in reverse order so that they can safely
  444. // delete themselves.
  445. /* i = draw_cb_vector.Length ()-1;
  446. while (i >= 0)
  447. {
  448. iMeshDrawCallback* cb = draw_cb_vector.Get (i);
  449. if (!cb->BeforeDrawing (meshwrap, rview)) return 0;
  450. i--;
  451. }*/
  452. /*draw_test = meshobj->DrawTest (rview, &movable.scfiMovable);
  453. if (draw_test)
  454. {
  455. csTicks lt = csEngine::current_engine->GetLastAnimationTime ();
  456. if (lt != 0)
  457. {
  458. if (lt != last_anim_time)
  459. {
  460. meshobj->NextFrame (lt,movable.GetPosition ());
  461. last_anim_time = lt;
  462. }
  463. }*/
  464. csTicks lt = csEngine::current_engine->GetLastAnimationTime ();
  465. meshobj->NextFrame (lt,movable.GetPosition ());
  466. csMeshWrapper *meshwrap = this;
  467. last_anim_time = lt;
  468. csMeshWrapper* lastparent = meshwrap;
  469. csMeshWrapper* parent = csParent;
  470. while (parent != 0)
  471. {
  472. parent->GetMeshObject()->PositionChild (lastparent->GetMeshObject(), lt);
  473. lastparent = parent;
  474. parent = parent->csParent;
  475. }
  476. return meshobj->GetRenderMeshes (n, rview, mov, frustum_mask);
  477. /* }
  478. return 0;*/
  479. /*
  480. for (i = 0; i < children.GetCount (); i++)
  481. {
  482. iMeshWrapper *spr = children.Get (i);
  483. spr->DrawZ (rview);
  484. }
  485. */
  486. }
  487. void csMeshWrapper::DrawShadow (iRenderView* rview, iLight* light)
  488. {
  489. /*
  490. if (cast_hardware_shadow)
  491. meshobj->DrawShadow (rview, &movable.scfiMovable, zbufMode, light);
  492. */
  493. }
  494. void csMeshWrapper::DrawLight (iRenderView* rview, iLight* light)
  495. {
  496. /*
  497. if (draw_test)
  498. meshobj->DrawLight (rview, &movable.scfiMovable, zbufMode, light);
  499. */
  500. }
  501. void csMeshWrapper::CastHardwareShadow (bool castShadow)
  502. {
  503. cast_hardware_shadow = castShadow;
  504. }
  505. void csMeshWrapper::SetDrawAfterShadow (bool drawAfter)
  506. {
  507. draw_after_fancy_stuff = drawAfter;
  508. }
  509. bool csMeshWrapper::GetDrawAfterShadow ()
  510. {
  511. return draw_after_fancy_stuff;
  512. }
  513. //----- Static LOD ----------------------------------------------------------
  514. iLODControl* csMeshWrapper::CreateStaticLOD ()
  515. {
  516. shadow_receiver_valid = false;
  517. shadow_caster_valid = false;
  518. static_lod = csPtr<csStaticLODMesh> (new csStaticLODMesh ());
  519. return static_lod;
  520. }
  521. void csMeshWrapper::DestroyStaticLOD ()
  522. {
  523. shadow_receiver_valid = false;
  524. shadow_caster_valid = false;
  525. static_lod = 0;
  526. }
  527. iLODControl* csMeshWrapper::GetStaticLOD ()
  528. {
  529. return (iLODControl*)static_lod;
  530. }
  531. void csMeshWrapper::RemoveMeshFromStaticLOD (iMeshWrapper* mesh)
  532. {
  533. if (!static_lod) return; // No static lod, nothing to do here.
  534. int lod;
  535. for (lod = 0 ; lod < static_lod->GetLODCount () ; lod++)
  536. {
  537. csArray<iMeshWrapper*>& meshes_for_lod = static_lod->GetMeshesForLOD (lod);
  538. meshes_for_lod.Delete (mesh);
  539. }
  540. shadow_receiver_valid = false;
  541. shadow_caster_valid = false;
  542. }
  543. void csMeshWrapper::AddMeshToStaticLOD (int lod, iMeshWrapper* mesh)
  544. {
  545. if (!static_lod) return; // No static lod, nothing to do here.
  546. csArray<iMeshWrapper*>& meshes_for_lod = static_lod->GetMeshesForLOD (lod);
  547. meshes_for_lod.Push (mesh);
  548. shadow_receiver_valid = false;
  549. shadow_caster_valid = false;
  550. }
  551. //---------------------------------------------------------------------------
  552. void csMeshWrapper::DrawInt (iRenderView *rview, uint32 frustum_mask)
  553. {
  554. if (imposter_active && CheckImposterRelevant (rview))
  555. if (DrawImposter (rview))
  556. return;
  557. DrawIntFull (rview, frustum_mask);
  558. }
  559. bool csMeshWrapper::CheckImposterRelevant (iRenderView *rview)
  560. {
  561. float wor_sq_dist = GetSquaredDistance (rview);
  562. float dist = min_imposter_distance->Get ();
  563. return (wor_sq_dist > dist*dist);
  564. }
  565. void csMeshWrapper::DrawIntFull (iRenderView *rview, uint32 frustum_mask)
  566. {
  567. iMeshWrapper *meshwrap = &scfiMeshWrapper;
  568. int i;
  569. // Callback are traversed in reverse order so that they can safely
  570. // delete themselves.
  571. i = draw_cb_vector.Length ()-1;
  572. while (i >= 0)
  573. {
  574. iMeshDrawCallback* cb = draw_cb_vector.Get (i);
  575. if (!cb->BeforeDrawing (meshwrap, rview)) return ;
  576. i--;
  577. }
  578. if (meshobj->DrawTest (rview, &movable.scfiMovable, frustum_mask))
  579. {
  580. csTicks lt = csEngine::current_engine->GetLastAnimationTime ();
  581. if (lt != 0)
  582. {
  583. if (lt != last_anim_time)
  584. {
  585. meshobj->NextFrame (lt, movable.GetPosition ());
  586. last_anim_time = lt;
  587. iMeshWrapper* lastparent = meshwrap;
  588. iMeshWrapper* parent = GetParentContainer();
  589. while(parent != 0)
  590. {
  591. parent->GetMeshObject()->PositionChild(lastparent->GetMeshObject(),lt);
  592. lastparent = parent;
  593. parent = parent->GetParentContainer();
  594. }
  595. }
  596. }
  597. meshobj->Draw (rview, &movable.scfiMovable, zbufMode);
  598. }
  599. #if 0
  600. if (static_lod)
  601. {
  602. // If we have static lod we only draw the children for the right LOD level.
  603. float distance = qsqrt (GetSquaredDistance (rview));
  604. float lod = static_lod->GetLODValue (distance);
  605. csArray<iMeshWrapper*>& meshes = static_lod->GetMeshesForLOD (lod);
  606. for (i = 0 ; i < meshes.Length () ; i++)
  607. {
  608. meshes[i]->Draw (rview);
  609. }
  610. }
  611. #endif
  612. }
  613. bool csMeshWrapper::DrawImposter (iRenderView *rview)
  614. {
  615. // Check for imposter existence. If not, create it.
  616. if (!imposter_mesh)
  617. {
  618. return false;
  619. }
  620. // Check for imposter already ready
  621. if (!imposter_mesh->GetImposterReady ())
  622. return false;
  623. // Check for too much camera movement since last imposter render
  624. if (!imposter_mesh->CheckIncidenceAngle (rview,
  625. imposter_rotation_tolerance->Get ()))
  626. return false;
  627. // Else draw imposter as-is.
  628. imposter_mesh->Draw (rview);
  629. return true;
  630. }
  631. void csMeshWrapper::SetImposterActive (bool flag)
  632. {
  633. imposter_active = flag;
  634. if (flag)
  635. {
  636. imposter_mesh = new csImposterMesh (this);
  637. imposter_mesh->SetImposterReady (false);
  638. }
  639. }
  640. bool csMeshWrapper::HitBeamOutline (
  641. const csVector3 &start,
  642. const csVector3 &end,
  643. csVector3 &isect,
  644. float *pr)
  645. {
  646. return meshobj->HitBeamOutline (start, end, isect, pr);
  647. }
  648. bool csMeshWrapper::HitBeamObject (
  649. const csVector3 &start,
  650. const csVector3 &end,
  651. csVector3 &isect,
  652. float *pr, int* polygon_idx)
  653. {
  654. return meshobj->HitBeamObject (start, end, isect, pr, polygon_idx);
  655. }
  656. bool csMeshWrapper::HitBeam (
  657. const csVector3 &start,
  658. const csVector3 &end,
  659. csVector3 &isect,
  660. float *pr)
  661. {
  662. csVector3 startObj;
  663. csVector3 endObj;
  664. csReversibleTransform trans;
  665. if (movable.IsFullTransformIdentity ())
  666. {
  667. startObj = start;
  668. endObj = end;
  669. }
  670. else
  671. {
  672. trans = movable.GetFullTransform ();
  673. startObj = trans.Other2This (start);
  674. endObj = trans.Other2This (end);
  675. }
  676. bool rc = false;
  677. if (HitBeamBBox (startObj, endObj, isect, 0) > -1)
  678. {
  679. rc = HitBeamOutline (startObj, endObj, isect, pr);
  680. if (rc)
  681. {
  682. if (!movable.IsFullTransformIdentity ())
  683. isect = trans.This2Other (isect);
  684. }
  685. }
  686. return rc;
  687. }
  688. void csMeshWrapper::HardTransform (const csReversibleTransform &t)
  689. {
  690. meshobj->HardTransform (t);
  691. int i;
  692. for (i = 0; i < children.GetCount (); i++)
  693. {
  694. iMeshWrapper *spr = children.Get (i);
  695. spr->HardTransform (t);
  696. }
  697. }
  698. void csMeshWrapper::GetRadius (csVector3 &rad, csVector3 &cent) const
  699. {
  700. meshobj->GetObjectModel ()->GetRadius (rad, cent);
  701. if (children.GetCount () > 0)
  702. {
  703. float max_radius = rad.x;
  704. if (max_radius < rad.y) max_radius = rad.y;
  705. if (max_radius < rad.z) max_radius = rad.z;
  706. csSphere sphere (cent, max_radius);
  707. int i;
  708. for (i = 0; i < children.GetCount (); i++)
  709. {
  710. iMeshWrapper *spr = children.Get (i);
  711. csVector3 childrad, childcent;
  712. spr->GetRadius (childrad, childcent);
  713. float child_max_radius = childrad.x;
  714. if (child_max_radius < childrad.y) child_max_radius = childrad.y;
  715. if (child_max_radius < childrad.z) child_max_radius = childrad.z;
  716. csSphere childsphere (childcent, child_max_radius);
  717. // @@@ Is this the right transform?
  718. childsphere *= spr->GetMovable ()->GetTransform ();
  719. sphere += childsphere;
  720. }
  721. rad.Set (sphere.GetRadius (), sphere.GetRadius (), sphere.GetRadius ());
  722. cent.Set (sphere.GetCenter ());
  723. }
  724. }
  725. float csMeshWrapper::MeshWrapper::GetScreenBoundingBox (
  726. iCamera *camera,
  727. csBox2 &sbox,
  728. csBox3 &cbox)
  729. {
  730. return scfParent->GetScreenBoundingBox (camera, sbox, cbox);
  731. }
  732. float csMeshWrapper::GetSquaredDistance (iRenderView *rview)
  733. {
  734. iCamera* camera = rview->GetCamera ();
  735. // calculate distance from camera to mesh
  736. csBox3 obox;
  737. GetObjectModel ()->GetObjectBoundingBox (obox, CS_BBOX_MAX);
  738. csVector3 obj_center = (obox.Min () + obox.Max ()) / 2;
  739. csVector3 wor_center;
  740. if (movable.IsFullTransformIdentity ())
  741. wor_center = obj_center;
  742. else
  743. wor_center = movable.GetFullTransform ().This2Other (obj_center);
  744. csVector3 cam_origin = camera->GetTransform ().GetOrigin ();
  745. float wor_sq_dist = csSquaredDist::PointPoint (cam_origin, wor_center);
  746. return wor_sq_dist;
  747. }
  748. void csMeshWrapper::GetFullBBox (csBox3& box)
  749. {
  750. GetObjectModel ()->GetObjectBoundingBox (box, CS_BBOX_MAX);
  751. iMovable* mov = &movable.scfiMovable;
  752. while (mov)
  753. {
  754. if (!mov->IsTransformIdentity ())
  755. {
  756. const csReversibleTransform& trans = mov->GetTransform ();
  757. csBox3 b (trans.This2Other (box.GetCorner (0)));
  758. b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (1)));
  759. b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (2)));
  760. b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (3)));
  761. b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (4)));
  762. b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (5)));
  763. b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (6)));
  764. b.AddBoundingVertexSmart (trans.This2Other (box.GetCorner (7)));
  765. box = b;
  766. }
  767. mov = mov->GetParent ();
  768. }
  769. }
  770. void csMeshWrapper::PlaceMesh ()
  771. {
  772. iSectorList *movable_sectors = movable.GetSectors ();
  773. if (movable_sectors->GetCount () == 0) return ; // Do nothing
  774. csSphere sphere;
  775. csVector3 radius;
  776. GetObjectModel ()->GetRadius (radius, sphere.GetCenter ());
  777. iSector *sector = movable_sectors->Get (0);
  778. movable.SetSector (sector); // Make sure all other sectors are removed
  779. // Transform the sphere from object to world space.
  780. float max_radius = radius.x;
  781. if (max_radius < radius.y) max_radius = radius.y;
  782. if (max_radius < radius.z) max_radius = radius.z;
  783. sphere.SetRadius (max_radius);
  784. if (!movable.IsFullTransformIdentity ())
  785. sphere = movable.GetFullTransform ().This2Other (sphere);
  786. max_radius = sphere.GetRadius ();
  787. float max_sq_radius = max_radius * max_radius;
  788. csRef<iMeshWrapperIterator> it = csEngine::current_engine
  789. ->GetNearbyMeshes (sector, sphere.GetCenter (), max_radius, true);
  790. int j;
  791. while (it->HasNext ())
  792. {
  793. iMeshWrapper* mesh = it->Next ();
  794. iPortalContainer* portals = mesh->GetPortalContainer ();
  795. if (!portals) continue; // No portals.
  796. int pc_count = portals->GetPortalCount ();
  797. for (j = 0 ; j < pc_count ; j++)
  798. {
  799. iPortal *portal = portals->GetPortal (j);
  800. iSector *dest_sector = portal->GetSector ();
  801. if (movable_sectors->Find (dest_sector) == -1)
  802. {
  803. const csPlane3 &pl = portal->GetWorldPlane ();
  804. float sqdist = csSquaredDist::PointPlane (sphere.GetCenter (), pl);
  805. if (sqdist <= max_sq_radius)
  806. {
  807. // Plane of portal is close enough.
  808. // If N is the normal of the portal plane then we
  809. // can use that to calculate the point on the portal plane.
  810. csVector3 testpoint = sphere.GetCenter () + pl.Normal () * qsqrt (
  811. sqdist);
  812. if (portal->PointOnPolygon (testpoint))
  813. movable_sectors->Add (dest_sector);
  814. }
  815. }
  816. }
  817. }
  818. }
  819. int csMeshWrapper::HitBeamBBox (
  820. const csVector3 &start,
  821. const csVector3 &end,
  822. csVector3 &isect,
  823. float *pr)
  824. {
  825. csBox3 b;
  826. GetObjectModel ()->GetObjectBoundingBox (b, CS_BBOX_MAX);
  827. csSegment3 seg (start, end);
  828. return csIntersect3::BoxSegment (b, seg, isect, pr);
  829. }
  830. void csMeshWrapper::GetWorldBoundingBox (csBox3 &cbox)
  831. {
  832. if (wor_bbox_movablenr != movable.GetUpdateNumber ())
  833. {
  834. wor_bbox_movablenr = movable.GetUpdateNumber ();
  835. if (movable.IsFullTransformIdentity ())
  836. GetObjectModel ()->GetObjectBoundingBox (wor_bbox, CS_BBOX_MAX);
  837. else
  838. {
  839. csBox3 obj_bbox;
  840. GetObjectModel ()->GetObjectBoundingBox (obj_bbox, CS_BBOX_MAX);
  841. // @@@ Maybe it would be better to really calculate the bounding box
  842. // here instead of just transforming the object space bounding box?
  843. csReversibleTransform mt = movable.GetFullTransform ();
  844. wor_bbox.StartBoundingBox (mt.This2Other (obj_bbox.GetCorner (0)));
  845. wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (1)));
  846. wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (2)));
  847. wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (3)));
  848. wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (4)));
  849. wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (5)));
  850. wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (6)));
  851. wor_bbox.AddBoundingVertexSmart (mt.This2Other (obj_bbox.GetCorner (7)));
  852. }
  853. }
  854. cbox = wor_bbox;
  855. }
  856. void csMeshWrapper::GetTransformedBoundingBox (
  857. const csReversibleTransform &trans,
  858. csBox3 &cbox)
  859. {
  860. csBox3 box;
  861. GetObjectModel ()->GetObjectBoundingBox (box);
  862. cbox.StartBoundingBox (trans * box.GetCorner (0));
  863. cbox.AddBoundingVertexSmart (trans * box.GetCorner (1));
  864. cbox.AddBoundingVertexSmart (trans * box.GetCorner (2));
  865. cbox.AddBoundingVertexSmart (trans * box.GetCorner (3));
  866. cbox.AddBoundingVertexSmart (trans * box.GetCorner (4));
  867. cbox.AddBoundingVertexSmart (trans * box.GetCorner (5));
  868. cbox.AddBoundingVertexSmart (trans * box.GetCorner (6));
  869. cbox.AddBoundingVertexSmart (trans * box.GetCorner (7));
  870. }
  871. float csMeshWrapper::GetScreenBoundingBox (
  872. const iCamera *camera,
  873. csBox2 &sbox,
  874. csBox3 &cbox)
  875. {
  876. csVector2 oneCorner;
  877. csReversibleTransform tr_o2c = camera->GetTransform ();
  878. if (!movable.IsFullTransformIdentity ())
  879. tr_o2c /= movable.GetFullTransform ();
  880. GetTransformedBoundingBox (tr_o2c, cbox);
  881. // if the entire bounding box is behind the camera, we're done
  882. if ((cbox.MinZ () < 0) && (cbox.MaxZ () < 0))
  883. {
  884. return -1;
  885. }
  886. // Transform from camera to screen space.
  887. if (cbox.MinZ () <= 0)
  888. {
  889. // Mesh is very close to camera.
  890. // Just return a maximum bounding box.
  891. sbox.Set (-10000, -10000, 10000, 10000);
  892. }
  893. else
  894. {
  895. camera->Perspective (cbox.Max (), oneCorner);
  896. sbox.StartBoundingBox (oneCorner);
  897. csVector3 v (cbox.MinX (), cbox.MinY (), cbox.MaxZ ());
  898. camera->Perspective (v, oneCorner);
  899. sbox.AddBoundingVertexSmart (oneCorner);
  900. camera->Perspective (cbox.Min (), oneCorner);
  901. sbox.AddBoundingVertexSmart (oneCorner);
  902. v.Set (cbox.MaxX (), cbox.MaxY (), cbox.MinZ ());
  903. camera->Perspective (v, oneCorner);
  904. sbox.AddBoundingVertexSmart (oneCorner);
  905. }
  906. return cbox.MaxZ ();
  907. }
  908. // ---------------------------------------------------------------------------
  909. // csMeshFactoryWrapper
  910. // ---------------------------------------------------------------------------
  911. SCF_IMPLEMENT_IBASE_EXT(csMeshFactoryWrapper)
  912. SCF_IMPLEMENTS_EMBEDDED_INTERFACE(iMeshFactoryWrapper)
  913. SCF_IMPLEMENTS_INTERFACE(csMeshFactoryWrapper)
  914. SCF_IMPLEMENT_IBASE_EXT_END
  915. SCF_IMPLEMENT_EMBEDDED_IBASE (csMeshFactoryWrapper::MeshFactoryWrapper)
  916. SCF_IMPLEMENTS_INTERFACE(iMeshFactoryWrapper)
  917. SCF_IMPLEMENT_EMBEDDED_IBASE_END
  918. csMeshFactoryWrapper::csMeshFactoryWrapper (
  919. iMeshObjectFactory *meshFact)
  920. {
  921. SCF_CONSTRUCT_EMBEDDED_IBASE (scfiMeshFactoryWrapper);
  922. csMeshFactoryWrapper::meshFact = meshFact;
  923. parent = 0;
  924. children.SetMeshFactory (this);
  925. }
  926. csMeshFactoryWrapper::csMeshFactoryWrapper ()
  927. {
  928. SCF_CONSTRUCT_EMBEDDED_IBASE (scfiMeshFactoryWrapper);
  929. parent = 0;
  930. children.SetMeshFactory (this);
  931. }
  932. csMeshFactoryWrapper::~csMeshFactoryWrapper ()
  933. {
  934. // This line MUST be here to ensure that the children are not
  935. // removed after the destructor has already finished.
  936. children.RemoveAll ();
  937. SCF_DESTRUCT_EMBEDDED_IBASE (scfiMeshFactoryWrapper);
  938. }
  939. void csMeshFactoryWrapper::SetMeshObjectFactory (iMeshObjectFactory *meshFact)
  940. {
  941. csMeshFactoryWrapper::meshFact = meshFact;
  942. }
  943. iMeshWrapper *csMeshFactoryWrapper::NewMeshObject ()
  944. {
  945. csRef<iMeshObject> basemesh = meshFact->NewInstance ();
  946. iMeshWrapper *mesh = &(new csMeshWrapper (0, basemesh))->scfiMeshWrapper;
  947. basemesh->SetLogicalParent (mesh);
  948. if (GetName ()) mesh->QueryObject ()->SetName (GetName ());
  949. mesh->SetFactory (&scfiMeshFactoryWrapper);
  950. if (static_lod)
  951. {
  952. iLODControl* lod = mesh->CreateStaticLOD ();
  953. iSharedVariable* varm, * vara;
  954. static_lod->GetLOD (varm, vara);
  955. if (varm)
  956. {
  957. lod->SetLOD (varm, vara);
  958. }
  959. else
  960. {
  961. float m, a;
  962. static_lod->GetLOD (m, a);
  963. lod->SetLOD (m, a);
  964. }
  965. }
  966. int i;
  967. for (i = 0; i < children.GetCount (); i++)
  968. {
  969. iMeshFactoryWrapper *childfact = children.Get (i);
  970. iMeshWrapper *child = childfact->CreateMeshWrapper ();
  971. mesh->GetChildren ()->Add (child);
  972. child->GetMovable ()->SetTransform (childfact->GetTransform ());
  973. child->GetMovable ()->UpdateMove ();
  974. if (static_lod)
  975. {
  976. // We have static lod so we need to put the child in the right
  977. // lod level.
  978. int l;
  979. for (l = 0 ; l < static_lod->GetLODCount () ; l++)
  980. {
  981. csArray<iMeshFactoryWrapper*>& facts_for_lod =
  982. static_lod->GetMeshesForLOD (l);
  983. int j;
  984. for (j = 0 ; j < facts_for_lod.Length () ; j++)
  985. {
  986. if (facts_for_lod[j] == childfact)
  987. mesh->AddMeshToStaticLOD (l, child);
  988. }
  989. }
  990. }
  991. child->DecRef ();
  992. }
  993. return mesh;
  994. }
  995. void csMeshFactoryWrapper::HardTransform (const csReversibleTransform &t)
  996. {
  997. meshFact->HardTransform (t);
  998. }
  999. iLODControl* csMeshFactoryWrapper::CreateStaticLOD ()
  1000. {
  1001. static_lod = csPtr<csStaticLODFactoryMesh> (new csStaticLODFactoryMesh ());
  1002. return static_lod;
  1003. }
  1004. void csMeshFactoryWrapper::DestroyStaticLOD ()
  1005. {
  1006. static_lod = 0;
  1007. }
  1008. iLODControl* csMeshFactoryWrapper::GetStaticLOD ()
  1009. {
  1010. return (iLODControl*)static_lod;
  1011. }
  1012. void csMeshFactoryWrapper::SetStaticLOD (float m, float a)
  1013. {
  1014. if (static_lod) static_lod->SetLOD (m, a);
  1015. }
  1016. void csMeshFactoryWrapper::GetStaticLOD (float& m, float& a) const
  1017. {
  1018. if (static_lod)
  1019. static_lod->GetLOD (m, a);
  1020. else
  1021. {
  1022. m = 0;
  1023. a = 0;
  1024. }
  1025. }
  1026. void csMeshFactoryWrapper::RemoveFactoryFromStaticLOD (
  1027. iMeshFactoryWrapper* fact)
  1028. {
  1029. if (!static_lod) return; // No static lod, nothing to do here.
  1030. int lod;
  1031. for (lod = 0 ; lod < static_lod->GetLODCount () ; lod++)
  1032. {
  1033. csArray<iMeshFactoryWrapper*>& meshes_for_lod =
  1034. static_lod->GetMeshesForLOD (lod);
  1035. meshes_for_lod.Delete (fact);
  1036. }
  1037. }
  1038. void csMeshFactoryWrapper::AddFactoryToStaticLOD (int lod,
  1039. iMeshFactoryWrapper* fact)
  1040. {
  1041. if (!static_lod) return; // No static lod, nothing to do here.
  1042. csArray<iMeshFactoryWrapper*>& meshes_for_lod =
  1043. static_lod->GetMeshesForLOD (lod);
  1044. meshes_for_lod.Push (fact);
  1045. }
  1046. //--------------------------------------------------------------------------
  1047. // csMeshList
  1048. //--------------------------------------------------------------------------
  1049. SCF_IMPLEMENT_IBASE(csMeshList)
  1050. SCF_IMPLEMENTS_INTERFACE(iMeshList)
  1051. SCF_IMPLEMENT_IBASE_END
  1052. csMeshList::csMeshList ()
  1053. {
  1054. SCF_CONSTRUCT_IBASE (0);
  1055. }
  1056. csMeshList::~csMeshList ()
  1057. {
  1058. RemoveAll ();
  1059. SCF_DESTRUCT_IBASE ();
  1060. }
  1061. iMeshWrapper* csMeshList::FindByNameWithChild (const char *Name) const
  1062. {
  1063. char const* p = strchr (Name, ':');
  1064. if (!p) return list.FindByName (Name);
  1065. int i;
  1066. for (i = 0 ; i < list.Length () ; i++)
  1067. {
  1068. iMeshWrapper* m = list.Get (i);
  1069. const char* mn = m->QueryObject ()->GetName ();
  1070. if (mn && !strncmp (mn, Name, p-Name))
  1071. {
  1072. return m->GetChildren ()->FindByName (p+1);
  1073. }
  1074. }
  1075. return 0;
  1076. }
  1077. int csMeshList::Add (iMeshWrapper *obj)
  1078. {
  1079. PrepareMesh (obj);
  1080. list.Push (obj);
  1081. return true;
  1082. }
  1083. bool csMeshList::Remove (iMeshWrapper *obj)
  1084. {
  1085. FreeMesh (obj);
  1086. list.Delete (obj);
  1087. return true;
  1088. }
  1089. bool csMeshList::Remove (int n)
  1090. {
  1091. FreeMesh (list[n]);
  1092. list.DeleteIndex (n);
  1093. return true;
  1094. }
  1095. void csMeshList::RemoveAll ()
  1096. {
  1097. int i;
  1098. for (i = 0 ; i < list.Length () ; i++)
  1099. {
  1100. FreeMesh (list[i]);
  1101. }
  1102. list.DeleteAll ();
  1103. }
  1104. int csMeshList::Find (iMeshWrapper *obj) const
  1105. {
  1106. return list.Find (obj);
  1107. }
  1108. iMeshWrapper *csMeshList::FindByName (const char *Name) const
  1109. {
  1110. if (strchr (Name, ':'))
  1111. return FindByNameWithChild (Name);
  1112. else
  1113. return list.FindByName (Name);
  1114. }
  1115. //--------------------------------------------------------------------------
  1116. // csMeshMeshList
  1117. //--------------------------------------------------------------------------
  1118. void csMeshMeshList::PrepareMesh (iMeshWrapper* child)
  1119. {
  1120. CS_ASSERT (mesh != 0);
  1121. csMeshList::PrepareMesh (child);
  1122. // Unlink the mesh from the engine or another parent.
  1123. csMeshWrapper* cchild = ((csMeshWrapper::MeshWrapper*)child)->scfParent;
  1124. // Make sure that if this child is a portal container that we first
  1125. // uregister it from any sectors it may be in.
  1126. cchild->ClearFromSectorPortalLists ();
  1127. iMeshWrapper *oldParent = child->GetParentContainer ();
  1128. if (oldParent)
  1129. oldParent->GetChildren ()->Remove (child);
  1130. else
  1131. csEngine::current_engine->GetMeshes ()->Remove (child);
  1132. /* csSector->PrepareMesh tells the culler about the mesh
  1133. (since removing the mesh above also removes it from the culler...) */
  1134. // First we find the top-level parent.
  1135. iMeshWrapper* toplevel = &(mesh->scfiMeshWrapper);
  1136. while (toplevel->GetParentContainer ())
  1137. toplevel = toplevel->GetParentContainer ();
  1138. iMovable* mov = toplevel->GetMovable ();
  1139. iSectorList* sl = mov->GetSectors ();
  1140. for (int i = 0 ; i < sl->GetCount() ; i++)
  1141. {
  1142. csSector* sector = sl->Get (i)->GetPrivateObject ();
  1143. sector->UnprepareMesh (child);
  1144. sector->PrepareMesh (child);
  1145. }
  1146. child->SetParentContainer (&mesh->scfiMeshWrapper);
  1147. cchild->GetCsMovable ().SetParent (&mesh->GetCsMovable ().scfiMovable);
  1148. // Readd our child to sectors if it happens to be a portal container.
  1149. cchild->AddToSectorPortalLists ();
  1150. }
  1151. void csMeshMeshList::FreeMesh (iMeshWrapper* item)
  1152. {
  1153. CS_ASSERT (mesh != 0);
  1154. csMeshWrapper* citem = ((csMeshWrapper::MeshWrapper*)item)->scfParent;
  1155. // Make sure that if this child is a portal container that we first
  1156. // uregister it from any sectors it may be in.
  1157. citem->ClearFromSectorPortalLists ();
  1158. for (int i = 0 ; i < mesh->GetCsMovable().GetSectors()->GetCount() ; i++)
  1159. {
  1160. csSector* sector = mesh->GetCsMovable ().GetSectors ()->Get (i)
  1161. ->GetPrivateObject ();
  1162. sector->UnprepareMesh (item);
  1163. }
  1164. item->SetParentContainer (0);
  1165. item->GetMovable ()->SetParent (0);
  1166. mesh->RemoveMeshFromStaticLOD (item);
  1167. csMeshList::FreeMesh (item);
  1168. }
  1169. //--------------------------------------------------------------------------
  1170. // csMeshFactoryList
  1171. //--------------------------------------------------------------------------
  1172. SCF_IMPLEMENT_IBASE(csMeshFactoryList)
  1173. SCF_IMPLEMENTS_INTERFACE(iMeshFactoryList)
  1174. SCF_IMPLEMENT_IBASE_END
  1175. csMeshFactoryList::csMeshFactoryList ()
  1176. {
  1177. SCF_CONSTRUCT_IBASE (0);
  1178. }
  1179. csMeshFactoryList::~csMeshFactoryList ()
  1180. {
  1181. RemoveAll ();
  1182. SCF_DESTRUCT_IBASE ();
  1183. }
  1184. int csMeshFactoryList::Add (iMeshFactoryWrapper *obj)
  1185. {
  1186. PrepareFactory (obj);
  1187. list.Push (obj);
  1188. return true;
  1189. }
  1190. bool csMeshFactoryList::Remove (iMeshFactoryWrapper *obj)
  1191. {
  1192. FreeFactory (obj);
  1193. list.Delete (obj);
  1194. return true;
  1195. }
  1196. bool csMeshFactoryList::Remove (int n)
  1197. {
  1198. FreeFactory (list[n]);
  1199. list.Delete (Get (n));
  1200. return true;
  1201. }
  1202. void csMeshFactoryList::RemoveAll ()
  1203. {
  1204. int i;
  1205. for (i = 0 ; i < list.Length () ; i++)
  1206. {
  1207. FreeFactory (list[i]);
  1208. }
  1209. list.DeleteAll ();
  1210. }
  1211. int csMeshFactoryList::Find (iMeshFactoryWrapper *obj) const
  1212. {
  1213. return list.Find (obj);
  1214. }
  1215. iMeshFactoryWrapper *csMeshFactoryList::FindByName (
  1216. const char *Name) const
  1217. {
  1218. return list.FindByName (Name);
  1219. }
  1220. //--------------------------------------------------------------------------
  1221. // csMeshFactoryFactoryList
  1222. //--------------------------------------------------------------------------
  1223. void csMeshFactoryFactoryList::PrepareFactory (iMeshFactoryWrapper* child)
  1224. {
  1225. CS_ASSERT (meshfact != 0);
  1226. csMeshFactoryList::PrepareFactory (child);
  1227. // unlink the factory from another possible parent.
  1228. if (child->GetParentContainer ())
  1229. child->GetParentContainer ()->GetChildren ()->Remove (child);
  1230. child->SetParentContainer (&meshfact->scfiMeshFactoryWrapper);
  1231. }
  1232. void csMeshFactoryFactoryList::FreeFactory (iMeshFactoryWrapper* item)
  1233. {
  1234. CS_ASSERT (meshfact != 0);
  1235. item->SetParentContainer (0);
  1236. meshfact->RemoveFactoryFromStaticLOD (item);
  1237. csMeshFactoryList::FreeFactory (item);
  1238. }