OPC_OptimizedTree.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. /*
  3. * OPCODE - Optimized Collision Detection
  4. * Copyright (C) 2001 Pierre Terdiman
  5. * Homepage: http://www.codercorner.com/Opcode.htm
  6. */
  7. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. /**
  10. * Contains code for optimized trees. Implements 4 trees:
  11. * - normal
  12. * - no leaf
  13. * - quantized
  14. * - no leaf / quantized
  15. *
  16. * \file OPC_OptimizedTree.cpp
  17. * \author Pierre Terdiman
  18. * \date March, 20, 2001
  19. */
  20. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  21. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. /**
  23. * A standard AABB tree.
  24. *
  25. * \class AABBCollisionTree
  26. * \author Pierre Terdiman
  27. * \version 1.3
  28. * \date March, 20, 2001
  29. */
  30. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  31. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  32. /**
  33. * A no-leaf AABB tree.
  34. *
  35. * \class AABBNoLeafTree
  36. * \author Pierre Terdiman
  37. * \version 1.3
  38. * \date March, 20, 2001
  39. */
  40. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  41. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  42. /**
  43. * A quantized AABB tree.
  44. *
  45. * \class AABBQuantizedTree
  46. * \author Pierre Terdiman
  47. * \version 1.3
  48. * \date March, 20, 2001
  49. */
  50. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  52. /**
  53. * A quantized no-leaf AABB tree.
  54. *
  55. * \class AABBQuantizedNoLeafTree
  56. * \author Pierre Terdiman
  57. * \version 1.3
  58. * \date March, 20, 2001
  59. */
  60. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  61. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. // Precompiled Header
  63. #include "Stdafx.h"
  64. using namespace Opcode;
  65. //! Compilation flag:
  66. //! - true to fix quantized boxes (i.e. make sure they enclose the original ones)
  67. //! - false to see the effects of quantization errors (faster, but wrong results in some cases)
  68. static const bool gFixQuantized = true;
  69. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  70. /**
  71. * Builds an implicit tree from a standard one. An implicit tree is a complete tree (2*N-1 nodes) whose negative
  72. * box pointers and primitive pointers have been made implicit, hence packing 3 pointers in one.
  73. *
  74. * Layout for implicit trees:
  75. * Node:
  76. * - box
  77. * - data (32-bits value)
  78. *
  79. * if data's LSB = 1 => remaining bits are a primitive pointer
  80. * else remaining bits are a P-node pointer, and N = P + 1
  81. *
  82. * \relates AABBCollisionNode
  83. * \fn _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
  84. * \param linear [in] base address of destination nodes
  85. * \param box_id [in] index of destination node
  86. * \param current_id [in] current running index
  87. * \param current_node [in] current node from input tree
  88. */
  89. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  90. static void _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
  91. {
  92. // Current node from input tree is "current_node". Must be flattened into "linear[boxid]".
  93. // Store the AABB
  94. current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter);
  95. current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents);
  96. // Store remaining info
  97. if(current_node->IsLeaf())
  98. {
  99. // The input tree must be complete => i.e. one primitive/leaf
  100. ASSERT(current_node->GetNbPrimitives()==1);
  101. // Get the primitive index from the input tree
  102. udword PrimitiveIndex = current_node->GetPrimitives()[0];
  103. // Setup box data as the primitive index, marked as leaf
  104. linear[box_id].mData = (PrimitiveIndex<<1)|1;
  105. }
  106. else
  107. {
  108. // To make the negative one implicit, we must store P and N in successive order
  109. udword PosID = current_id++; // Get a new id for positive child
  110. udword NegID = current_id++; // Get a new id for negative child
  111. // Setup box data as the forthcoming new P pointer
  112. linear[box_id].mData = (size_t)&linear[PosID];
  113. // Make sure it's not marked as leaf
  114. ASSERT(!(linear[box_id].mData&1));
  115. // Recurse with new IDs
  116. _BuildCollisionTree(linear, PosID, current_id, current_node->GetPos());
  117. _BuildCollisionTree(linear, NegID, current_id, current_node->GetNeg());
  118. }
  119. }
  120. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  121. /**
  122. * Builds a "no-leaf" tree from a standard one. This is a tree whose leaf nodes have been removed.
  123. *
  124. * Layout for no-leaf trees:
  125. *
  126. * Node:
  127. * - box
  128. * - P pointer => a node (LSB=0) or a primitive (LSB=1)
  129. * - N pointer => a node (LSB=0) or a primitive (LSB=1)
  130. *
  131. * \relates AABBNoLeafNode
  132. * \fn _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
  133. * \param linear [in] base address of destination nodes
  134. * \param box_id [in] index of destination node
  135. * \param current_id [in] current running index
  136. * \param current_node [in] current node from input tree
  137. */
  138. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  139. static void _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
  140. {
  141. const AABBTreeNode* P = current_node->GetPos();
  142. const AABBTreeNode* N = current_node->GetNeg();
  143. // Leaf nodes here?!
  144. ASSERT(P);
  145. ASSERT(N);
  146. // Internal node => keep the box
  147. current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter);
  148. current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents);
  149. if(P->IsLeaf())
  150. {
  151. // The input tree must be complete => i.e. one primitive/leaf
  152. ASSERT(P->GetNbPrimitives()==1);
  153. // Get the primitive index from the input tree
  154. udword PrimitiveIndex = P->GetPrimitives()[0];
  155. // Setup prev box data as the primitive index, marked as leaf
  156. linear[box_id].mPosData = (PrimitiveIndex<<1)|1;
  157. }
  158. else
  159. {
  160. // Get a new id for positive child
  161. udword PosID = current_id++;
  162. // Setup box data
  163. linear[box_id].mPosData = (size_t)&linear[PosID];
  164. // Make sure it's not marked as leaf
  165. ASSERT(!(linear[box_id].mPosData&1));
  166. // Recurse
  167. _BuildNoLeafTree(linear, PosID, current_id, P);
  168. }
  169. if(N->IsLeaf())
  170. {
  171. // The input tree must be complete => i.e. one primitive/leaf
  172. ASSERT(N->GetNbPrimitives()==1);
  173. // Get the primitive index from the input tree
  174. udword PrimitiveIndex = N->GetPrimitives()[0];
  175. // Setup prev box data as the primitive index, marked as leaf
  176. linear[box_id].mNegData = (PrimitiveIndex<<1)|1;
  177. }
  178. else
  179. {
  180. // Get a new id for negative child
  181. udword NegID = current_id++;
  182. // Setup box data
  183. linear[box_id].mNegData = (size_t)&linear[NegID];
  184. // Make sure it's not marked as leaf
  185. ASSERT(!(linear[box_id].mNegData&1));
  186. // Recurse
  187. _BuildNoLeafTree(linear, NegID, current_id, N);
  188. }
  189. }
  190. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  191. /**
  192. * Constructor.
  193. */
  194. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  195. AABBCollisionTree::AABBCollisionTree() : mNodes(null)
  196. {
  197. }
  198. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  199. /**
  200. * Destructor.
  201. */
  202. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  203. AABBCollisionTree::~AABBCollisionTree()
  204. {
  205. DELETEARRAY(mNodes);
  206. }
  207. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  208. /**
  209. * Builds the collision tree from a generic AABB tree.
  210. * \param tree [in] generic AABB tree
  211. * \return true if success
  212. */
  213. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  214. bool AABBCollisionTree::Build(AABBTree* tree)
  215. {
  216. // Checkings
  217. if(!tree) return false;
  218. // Check the input tree is complete
  219. udword NbTriangles = tree->GetNbPrimitives();
  220. udword NbNodes = tree->GetNbNodes();
  221. if(NbNodes!=NbTriangles*2-1) return false;
  222. // Get nodes
  223. if(mNbNodes!=NbNodes) // Same number of nodes => keep moving
  224. {
  225. mNbNodes = NbNodes;
  226. DELETEARRAY(mNodes);
  227. mNodes = new AABBCollisionNode[NbNodes];
  228. CHECKALLOC(mNodes);
  229. }
  230. // Build the tree
  231. udword CurID = 1;
  232. _BuildCollisionTree(mNodes, 0, CurID, tree);
  233. ASSERT(CurID==NbNodes);
  234. return true;
  235. }
  236. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  237. /**
  238. * Refits the collision tree after vertices have been modified.
  239. * \param mesh_interface [in] mesh interface for current model
  240. * \return true if success
  241. */
  242. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  243. bool AABBCollisionTree::Refit(const MeshInterface* /*mesh_interface*/)
  244. {
  245. ASSERT(!"Not implemented since AABBCollisionTrees have twice as more nodes to refit as AABBNoLeafTrees!");
  246. return false;
  247. }
  248. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  249. /**
  250. * Walks the tree and call the user back for each node.
  251. * \param callback [in] walking callback
  252. * \param user_data [in] callback's user data
  253. * \return true if success
  254. */
  255. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  256. bool AABBCollisionTree::Walk(GenericWalkingCallback callback, void* user_data) const
  257. {
  258. if(!callback) return false;
  259. struct Local
  260. {
  261. static void _Walk(const AABBCollisionNode* current_node, GenericWalkingCallback callback, void* user_data)
  262. {
  263. if(!current_node || !(callback)(current_node, user_data)) return;
  264. if(!current_node->IsLeaf())
  265. {
  266. _Walk(current_node->GetPos(), callback, user_data);
  267. _Walk(current_node->GetNeg(), callback, user_data);
  268. }
  269. }
  270. };
  271. Local::_Walk(mNodes, callback, user_data);
  272. return true;
  273. }
  274. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  275. /**
  276. * Constructor.
  277. */
  278. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  279. AABBNoLeafTree::AABBNoLeafTree() : mNodes(null)
  280. {
  281. }
  282. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  283. /**
  284. * Destructor.
  285. */
  286. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  287. AABBNoLeafTree::~AABBNoLeafTree()
  288. {
  289. DELETEARRAY(mNodes);
  290. }
  291. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  292. /**
  293. * Builds the collision tree from a generic AABB tree.
  294. * \param tree [in] generic AABB tree
  295. * \return true if success
  296. */
  297. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  298. bool AABBNoLeafTree::Build(AABBTree* tree)
  299. {
  300. // Checkings
  301. if(!tree) return false;
  302. // Check the input tree is complete
  303. udword NbTriangles = tree->GetNbPrimitives();
  304. udword NbExistingNodes = tree->GetNbNodes();
  305. if(NbExistingNodes!=NbTriangles*2-1) return false;
  306. udword NbNodes = NbTriangles-1;
  307. // Get nodes
  308. if(mNbNodes!=NbNodes) // Same number of nodes => keep moving
  309. {
  310. mNbNodes = NbNodes;
  311. DELETEARRAY(mNodes);
  312. mNodes = new AABBNoLeafNode[NbNodes];
  313. CHECKALLOC(mNodes);
  314. }
  315. // Build the tree
  316. udword CurID = 1;
  317. _BuildNoLeafTree(mNodes, 0, CurID, tree);
  318. ASSERT(CurID==NbNodes);
  319. return true;
  320. }
  321. inline_ void ComputeMinMax(Point& min, Point& max, const VertexPointers& vp)
  322. {
  323. // Compute triangle's AABB = a leaf box
  324. #ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much
  325. min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
  326. max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
  327. min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
  328. max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
  329. min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
  330. max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
  331. #else
  332. min = *vp.Vertex[0];
  333. max = *vp.Vertex[0];
  334. min.Min(*vp.Vertex[1]);
  335. max.Max(*vp.Vertex[1]);
  336. min.Min(*vp.Vertex[2]);
  337. max.Max(*vp.Vertex[2]);
  338. #endif
  339. }
  340. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  341. /**
  342. * Refits the collision tree after vertices have been modified.
  343. * \param mesh_interface [in] mesh interface for current model
  344. * \return true if success
  345. */
  346. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  347. bool AABBNoLeafTree::Refit(const MeshInterface* mesh_interface)
  348. {
  349. // Checkings
  350. if(!mesh_interface) return false;
  351. // Bottom-up update
  352. VertexPointers VP;
  353. ConversionArea VC;
  354. Point Min,Max;
  355. Point Min_,Max_;
  356. udword Index = mNbNodes;
  357. while(Index--)
  358. {
  359. AABBNoLeafNode& Current = mNodes[Index];
  360. if(Current.HasPosLeaf())
  361. {
  362. mesh_interface->GetTriangle(VP, Current.GetPosPrimitive(), VC);
  363. ComputeMinMax(Min, Max, VP);
  364. }
  365. else
  366. {
  367. const CollisionAABB& CurrentBox = Current.GetPos()->mAABB;
  368. CurrentBox.GetMin(Min);
  369. CurrentBox.GetMax(Max);
  370. }
  371. if(Current.HasNegLeaf())
  372. {
  373. mesh_interface->GetTriangle(VP, Current.GetNegPrimitive(), VC);
  374. ComputeMinMax(Min_, Max_, VP);
  375. }
  376. else
  377. {
  378. const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB;
  379. CurrentBox.GetMin(Min_);
  380. CurrentBox.GetMax(Max_);
  381. }
  382. #ifdef OPC_USE_FCOMI
  383. Min.x = FCMin2(Min.x, Min_.x);
  384. Max.x = FCMax2(Max.x, Max_.x);
  385. Min.y = FCMin2(Min.y, Min_.y);
  386. Max.y = FCMax2(Max.y, Max_.y);
  387. Min.z = FCMin2(Min.z, Min_.z);
  388. Max.z = FCMax2(Max.z, Max_.z);
  389. #else
  390. Min.Min(Min_);
  391. Max.Max(Max_);
  392. #endif
  393. Current.mAABB.SetMinMax(Min, Max);
  394. }
  395. return true;
  396. }
  397. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  398. /**
  399. * Walks the tree and call the user back for each node.
  400. * \param callback [in] walking callback
  401. * \param user_data [in] callback's user data
  402. * \return true if success
  403. */
  404. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  405. bool AABBNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const
  406. {
  407. if(!callback) return false;
  408. struct Local
  409. {
  410. static void _Walk(const AABBNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data)
  411. {
  412. if(!current_node || !(callback)(current_node, user_data)) return;
  413. if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data);
  414. if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data);
  415. }
  416. };
  417. Local::_Walk(mNodes, callback, user_data);
  418. return true;
  419. }
  420. // Quantization notes:
  421. // - We could use the highest bits of mData to store some more quantized bits. Dequantization code
  422. // would be slightly more complex, but number of overlap tests would be reduced (and anyhow those
  423. // bits are currently wasted). Of course it's not possible if we move to 16 bits mData.
  424. // - Something like "16 bits floats" could be tested, to bypass the int-to-float conversion.
  425. // - A dedicated BV-BV test could be used, dequantizing while testing for overlap. (i.e. it's some
  426. // lazy-dequantization which may save some work in case of early exits). At the very least some
  427. // muls could be saved by precomputing several more matrices. But maybe not worth the pain.
  428. // - Do we need to dequantize anyway? Not doing the extents-related muls only implies the box has
  429. // been scaled, for example.
  430. // - The deeper we move into the hierarchy, the smaller the extents should be. May not need a fixed
  431. // number of quantization bits. Even better, could probably be best delta-encoded.
  432. // Find max values. Some people asked why I wasn't simply using the first node. Well, I can't.
  433. // I'm not looking for (min, max) values like in a standard AABB, I'm looking for the extremal
  434. // centers/extents in order to quantize them. The first node would only give a single center and
  435. // a single extents. While extents would be the biggest, the center wouldn't.
  436. #define FIND_MAX_VALUES \
  437. /* Get max values */ \
  438. Point CMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \
  439. Point EMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \
  440. const udword NbNodes = mNbNodes; \
  441. for(udword i=0;i<NbNodes;i++) \
  442. { \
  443. float cx = fabsf(Nodes[i].mAABB.mCenter.x); if(cx>CMax.x) CMax.x = cx; \
  444. float cy = fabsf(Nodes[i].mAABB.mCenter.y); if(cy>CMax.y) CMax.y = cy; \
  445. float cz = fabsf(Nodes[i].mAABB.mCenter.z); if(cz>CMax.z) CMax.z = cz; \
  446. float ex = fabsf(Nodes[i].mAABB.mExtents.x); if(ex>EMax.x) EMax.x = ex; \
  447. float ey = fabsf(Nodes[i].mAABB.mExtents.y); if(ey>EMax.y) EMax.y = ey; \
  448. float ez = fabsf(Nodes[i].mAABB.mExtents.z); if(ez>EMax.z) EMax.z = ez; \
  449. }
  450. #define INIT_QUANTIZATION \
  451. udword nbc=15; /* Keep one bit for sign */ \
  452. udword nbe=15; /* Keep one bit for fix */ \
  453. if(!gFixQuantized) nbe++; \
  454. \
  455. /* Compute quantization coeffs */ \
  456. Point CQuantCoeff, EQuantCoeff; \
  457. CQuantCoeff.x = CMax.x!=0.0f ? float((1<<nbc)-1)/CMax.x : 0.0f; \
  458. CQuantCoeff.y = CMax.y!=0.0f ? float((1<<nbc)-1)/CMax.y : 0.0f; \
  459. CQuantCoeff.z = CMax.z!=0.0f ? float((1<<nbc)-1)/CMax.z : 0.0f; \
  460. EQuantCoeff.x = EMax.x!=0.0f ? float((1<<nbe)-1)/EMax.x : 0.0f; \
  461. EQuantCoeff.y = EMax.y!=0.0f ? float((1<<nbe)-1)/EMax.y : 0.0f; \
  462. EQuantCoeff.z = EMax.z!=0.0f ? float((1<<nbe)-1)/EMax.z : 0.0f; \
  463. /* Compute and save dequantization coeffs */ \
  464. mCenterCoeff.x = CQuantCoeff.x!=0.0f ? 1.0f / CQuantCoeff.x : 0.0f; \
  465. mCenterCoeff.y = CQuantCoeff.y!=0.0f ? 1.0f / CQuantCoeff.y : 0.0f; \
  466. mCenterCoeff.z = CQuantCoeff.z!=0.0f ? 1.0f / CQuantCoeff.z : 0.0f; \
  467. mExtentsCoeff.x = EQuantCoeff.x!=0.0f ? 1.0f / EQuantCoeff.x : 0.0f; \
  468. mExtentsCoeff.y = EQuantCoeff.y!=0.0f ? 1.0f / EQuantCoeff.y : 0.0f; \
  469. mExtentsCoeff.z = EQuantCoeff.z!=0.0f ? 1.0f / EQuantCoeff.z : 0.0f; \
  470. #define PERFORM_QUANTIZATION \
  471. /* Quantize */ \
  472. mNodes[i].mAABB.mCenter[0] = sword(Nodes[i].mAABB.mCenter.x * CQuantCoeff.x); \
  473. mNodes[i].mAABB.mCenter[1] = sword(Nodes[i].mAABB.mCenter.y * CQuantCoeff.y); \
  474. mNodes[i].mAABB.mCenter[2] = sword(Nodes[i].mAABB.mCenter.z * CQuantCoeff.z); \
  475. mNodes[i].mAABB.mExtents[0] = uword(Nodes[i].mAABB.mExtents.x * EQuantCoeff.x); \
  476. mNodes[i].mAABB.mExtents[1] = uword(Nodes[i].mAABB.mExtents.y * EQuantCoeff.y); \
  477. mNodes[i].mAABB.mExtents[2] = uword(Nodes[i].mAABB.mExtents.z * EQuantCoeff.z); \
  478. /* Fix quantized boxes */ \
  479. if(gFixQuantized) \
  480. { \
  481. /* Make sure the quantized box is still valid */ \
  482. Point Max = Nodes[i].mAABB.mCenter + Nodes[i].mAABB.mExtents; \
  483. Point Min = Nodes[i].mAABB.mCenter - Nodes[i].mAABB.mExtents; \
  484. /* For each axis */ \
  485. for(udword j=0;j<3;j++) \
  486. { /* Dequantize the box center */ \
  487. float qc = float(mNodes[i].mAABB.mCenter[j]) * mCenterCoeff[j]; \
  488. bool FixMe=true; \
  489. do \
  490. { /* Dequantize the box extent */ \
  491. float qe = float(mNodes[i].mAABB.mExtents[j]) * mExtentsCoeff[j]; \
  492. /* Compare real & dequantized values */ \
  493. if(qc+qe<Max[j] || qc-qe>Min[j]) \
  494. { \
  495. mNodes[i].mAABB.mExtents[j]++; \
  496. /* Prevent wrapping */ \
  497. if(!mNodes[i].mAABB.mExtents[j]) \
  498. { \
  499. mNodes[i].mAABB.mExtents[j]=0xffff; \
  500. FixMe=false; \
  501. } \
  502. } \
  503. else FixMe=false; \
  504. }while(FixMe); \
  505. } \
  506. }
  507. #define REMAP_DATA(member, NodeType) \
  508. /* Fix data */ \
  509. Data = Nodes[i].member; \
  510. if(!(Data&1)) \
  511. { \
  512. /* Compute box number */ \
  513. size_t Nb = ((NodeType *)(Data) - (Nodes)); \
  514. Data = (size_t) &mNodes[Nb]; \
  515. } \
  516. /* ...remapped */ \
  517. mNodes[i].member = Data;
  518. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  519. /**
  520. * Constructor.
  521. */
  522. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  523. AABBQuantizedTree::AABBQuantizedTree() : mNodes(null)
  524. {
  525. }
  526. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  527. /**
  528. * Destructor.
  529. */
  530. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  531. AABBQuantizedTree::~AABBQuantizedTree()
  532. {
  533. DELETEARRAY(mNodes);
  534. }
  535. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  536. /**
  537. * Builds the collision tree from a generic AABB tree.
  538. * \param tree [in] generic AABB tree
  539. * \return true if success
  540. */
  541. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  542. bool AABBQuantizedTree::Build(AABBTree* tree)
  543. {
  544. // Checkings
  545. if(!tree) return false;
  546. // Check the input tree is complete
  547. udword NbTriangles = tree->GetNbPrimitives();
  548. udword NbNodes = tree->GetNbNodes();
  549. if(NbNodes!=NbTriangles*2-1) return false;
  550. // Get nodes
  551. mNbNodes = NbNodes;
  552. DELETEARRAY(mNodes);
  553. AABBCollisionNode* Nodes = new AABBCollisionNode[NbNodes];
  554. CHECKALLOC(Nodes);
  555. // Build the tree
  556. udword CurID = 1;
  557. _BuildCollisionTree(Nodes, 0, CurID, tree);
  558. // Quantize
  559. {
  560. mNodes = new AABBQuantizedNode[NbNodes];
  561. if (mNodes != null)
  562. {
  563. // Get max values
  564. FIND_MAX_VALUES
  565. // Quantization
  566. INIT_QUANTIZATION
  567. // Quantize
  568. size_t Data;
  569. for(udword i=0;i<NbNodes;i++)
  570. {
  571. PERFORM_QUANTIZATION
  572. REMAP_DATA(mData, AABBCollisionNode)
  573. }
  574. }
  575. DELETEARRAY(Nodes);
  576. CHECKALLOC(mNodes);
  577. }
  578. return true;
  579. }
  580. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  581. /**
  582. * Refits the collision tree after vertices have been modified.
  583. * \param mesh_interface [in] mesh interface for current model
  584. * \return true if success
  585. */
  586. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  587. bool AABBQuantizedTree::Refit(const MeshInterface* /*mesh_interface*/)
  588. {
  589. ASSERT(!"Not implemented since requantizing is painful !");
  590. return false;
  591. }
  592. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  593. /**
  594. * Walks the tree and call the user back for each node.
  595. * \param callback [in] walking callback
  596. * \param user_data [in] callback's user data
  597. * \return true if success
  598. */
  599. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  600. bool AABBQuantizedTree::Walk(GenericWalkingCallback callback, void* user_data) const
  601. {
  602. if(!callback) return false;
  603. struct Local
  604. {
  605. static void _Walk(const AABBQuantizedNode* current_node, GenericWalkingCallback callback, void* user_data)
  606. {
  607. if(!current_node || !(callback)(current_node, user_data)) return;
  608. if(!current_node->IsLeaf())
  609. {
  610. _Walk(current_node->GetPos(), callback, user_data);
  611. _Walk(current_node->GetNeg(), callback, user_data);
  612. }
  613. }
  614. };
  615. Local::_Walk(mNodes, callback, user_data);
  616. return true;
  617. }
  618. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  619. /**
  620. * Constructor.
  621. */
  622. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  623. AABBQuantizedNoLeafTree::AABBQuantizedNoLeafTree() : mNodes(null)
  624. {
  625. }
  626. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  627. /**
  628. * Destructor.
  629. */
  630. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  631. AABBQuantizedNoLeafTree::~AABBQuantizedNoLeafTree()
  632. {
  633. DELETEARRAY(mNodes);
  634. }
  635. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  636. /**
  637. * Builds the collision tree from a generic AABB tree.
  638. * \param tree [in] generic AABB tree
  639. * \return true if success
  640. */
  641. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  642. bool AABBQuantizedNoLeafTree::Build(AABBTree* tree)
  643. {
  644. // Checkings
  645. if(!tree) return false;
  646. // Check the input tree is complete
  647. udword NbTriangles = tree->GetNbPrimitives();
  648. udword NbExistingNodes = tree->GetNbNodes();
  649. if(NbExistingNodes!=NbTriangles*2-1) return false;
  650. // Get nodes
  651. udword NbNodes = NbTriangles-1;
  652. mNbNodes = NbNodes;
  653. DELETEARRAY(mNodes);
  654. AABBNoLeafNode* Nodes = new AABBNoLeafNode[NbNodes];
  655. CHECKALLOC(Nodes);
  656. // Build the tree
  657. udword CurID = 1;
  658. _BuildNoLeafTree(Nodes, 0, CurID, tree);
  659. ASSERT(CurID==NbNodes);
  660. // Quantize
  661. {
  662. mNodes = new AABBQuantizedNoLeafNode[NbNodes];
  663. if (mNodes != null)
  664. {
  665. // Get max values
  666. FIND_MAX_VALUES
  667. // Quantization
  668. INIT_QUANTIZATION
  669. // Quantize
  670. size_t Data;
  671. for(udword i=0;i<NbNodes;i++)
  672. {
  673. PERFORM_QUANTIZATION
  674. REMAP_DATA(mPosData, AABBNoLeafNode)
  675. REMAP_DATA(mNegData, AABBNoLeafNode)
  676. }
  677. }
  678. DELETEARRAY(Nodes);
  679. CHECKALLOC(mNodes);
  680. }
  681. return true;
  682. }
  683. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  684. /**
  685. * Refits the collision tree after vertices have been modified.
  686. * \param mesh_interface [in] mesh interface for current model
  687. * \return true if success
  688. */
  689. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  690. bool AABBQuantizedNoLeafTree::Refit(const MeshInterface* /*mesh_interface*/)
  691. {
  692. ASSERT(!"Not implemented since requantizing is painful !");
  693. return false;
  694. }
  695. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  696. /**
  697. * Walks the tree and call the user back for each node.
  698. * \param callback [in] walking callback
  699. * \param user_data [in] callback's user data
  700. * \return true if success
  701. */
  702. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  703. bool AABBQuantizedNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const
  704. {
  705. if(!callback) return false;
  706. struct Local
  707. {
  708. static void _Walk(const AABBQuantizedNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data)
  709. {
  710. if(!current_node || !(callback)(current_node, user_data)) return;
  711. if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data);
  712. if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data);
  713. }
  714. };
  715. Local::_Walk(mNodes, callback, user_data);
  716. return true;
  717. }