/nanobots/src/extern/Opcode/OPC_OptimizedTree.cpp

https://github.com/aras-p/dingus · C++ · 782 lines · 402 code · 78 blank · 302 comment · 51 complexity · 131c08de3d2f65d63bc10a1ab6b3f27d MD5 · raw file

  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 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 = (udword)&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 = (udword)&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 = (udword)&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[mNbNodes];
  228. CHECKALLOC(mNodes);
  229. }
  230. // Build the tree
  231. udword CurID = 1;
  232. _BuildCollisionTree(mNodes, 0, CurID, tree);
  233. ASSERT(CurID==mNbNodes);
  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 NbNodes = tree->GetNbNodes();
  305. if(NbNodes!=NbTriangles*2-1) return false;
  306. // Get nodes
  307. if(mNbNodes!=NbTriangles-1) // Same number of nodes => keep moving
  308. {
  309. mNbNodes = NbTriangles-1;
  310. DELETEARRAY(mNodes);
  311. mNodes = new AABBNoLeafNode[mNbNodes];
  312. CHECKALLOC(mNodes);
  313. }
  314. // Build the tree
  315. udword CurID = 1;
  316. _BuildNoLeafTree(mNodes, 0, CurID, tree);
  317. ASSERT(CurID==mNbNodes);
  318. return true;
  319. }
  320. inline_ void ComputeMinMax(Point& min, Point& max, const VertexPointers& vp)
  321. {
  322. // Compute triangle's AABB = a leaf box
  323. #ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much
  324. min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
  325. max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
  326. min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
  327. max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
  328. min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
  329. max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
  330. #else
  331. min = *vp.Vertex[0];
  332. max = *vp.Vertex[0];
  333. min.Min(*vp.Vertex[1]);
  334. max.Max(*vp.Vertex[1]);
  335. min.Min(*vp.Vertex[2]);
  336. max.Max(*vp.Vertex[2]);
  337. #endif
  338. }
  339. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  340. /**
  341. * Refits the collision tree after vertices have been modified.
  342. * \param mesh_interface [in] mesh interface for current model
  343. * \return true if success
  344. */
  345. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  346. bool AABBNoLeafTree::Refit(const MeshInterface* mesh_interface)
  347. {
  348. // Checkings
  349. if(!mesh_interface) return false;
  350. // Bottom-up update
  351. VertexPointers VP;
  352. Point Min,Max;
  353. Point Min_,Max_;
  354. udword Index = mNbNodes;
  355. while(Index--)
  356. {
  357. AABBNoLeafNode& Current = mNodes[Index];
  358. if(Current.HasPosLeaf())
  359. {
  360. mesh_interface->GetTriangle(VP, Current.GetPosPrimitive());
  361. ComputeMinMax(Min, Max, VP);
  362. }
  363. else
  364. {
  365. const CollisionAABB& CurrentBox = Current.GetPos()->mAABB;
  366. CurrentBox.GetMin(Min);
  367. CurrentBox.GetMax(Max);
  368. }
  369. if(Current.HasNegLeaf())
  370. {
  371. mesh_interface->GetTriangle(VP, Current.GetNegPrimitive());
  372. ComputeMinMax(Min_, Max_, VP);
  373. }
  374. else
  375. {
  376. const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB;
  377. CurrentBox.GetMin(Min_);
  378. CurrentBox.GetMax(Max_);
  379. }
  380. #ifdef OPC_USE_FCOMI
  381. Min.x = FCMin2(Min.x, Min_.x);
  382. Max.x = FCMax2(Max.x, Max_.x);
  383. Min.y = FCMin2(Min.y, Min_.y);
  384. Max.y = FCMax2(Max.y, Max_.y);
  385. Min.z = FCMin2(Min.z, Min_.z);
  386. Max.z = FCMax2(Max.z, Max_.z);
  387. #else
  388. Min.Min(Min_);
  389. Max.Max(Max_);
  390. #endif
  391. Current.mAABB.SetMinMax(Min, Max);
  392. }
  393. return true;
  394. }
  395. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  396. /**
  397. * Walks the tree and call the user back for each node.
  398. * \param callback [in] walking callback
  399. * \param user_data [in] callback's user data
  400. * \return true if success
  401. */
  402. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  403. bool AABBNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const
  404. {
  405. if(!callback) return false;
  406. struct Local
  407. {
  408. static void _Walk(const AABBNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data)
  409. {
  410. if(!current_node || !(callback)(current_node, user_data)) return;
  411. if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data);
  412. if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data);
  413. }
  414. };
  415. Local::_Walk(mNodes, callback, user_data);
  416. return true;
  417. }
  418. // Quantization notes:
  419. // - We could use the highest bits of mData to store some more quantized bits. Dequantization code
  420. // would be slightly more complex, but number of overlap tests would be reduced (and anyhow those
  421. // bits are currently wasted). Of course it's not possible if we move to 16 bits mData.
  422. // - Something like "16 bits floats" could be tested, to bypass the int-to-float conversion.
  423. // - A dedicated BV-BV test could be used, dequantizing while testing for overlap. (i.e. it's some
  424. // lazy-dequantization which may save some work in case of early exits). At the very least some
  425. // muls could be saved by precomputing several more matrices. But maybe not worth the pain.
  426. // - Do we need to dequantize anyway? Not doing the extents-related muls only implies the box has
  427. // been scaled, for example.
  428. // - The deeper we move into the hierarchy, the smaller the extents should be. May not need a fixed
  429. // number of quantization bits. Even better, could probably be best delta-encoded.
  430. // Find max values. Some people asked why I wasn't simply using the first node. Well, I can't.
  431. // I'm not looking for (min, max) values like in a standard AABB, I'm looking for the extremal
  432. // centers/extents in order to quantize them. The first node would only give a single center and
  433. // a single extents. While extents would be the biggest, the center wouldn't.
  434. #define FIND_MAX_VALUES \
  435. /* Get max values */ \
  436. Point CMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \
  437. Point EMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \
  438. for(udword i=0;i<mNbNodes;i++) \
  439. { \
  440. if(fabsf(Nodes[i].mAABB.mCenter.x)>CMax.x) CMax.x = fabsf(Nodes[i].mAABB.mCenter.x); \
  441. if(fabsf(Nodes[i].mAABB.mCenter.y)>CMax.y) CMax.y = fabsf(Nodes[i].mAABB.mCenter.y); \
  442. if(fabsf(Nodes[i].mAABB.mCenter.z)>CMax.z) CMax.z = fabsf(Nodes[i].mAABB.mCenter.z); \
  443. if(fabsf(Nodes[i].mAABB.mExtents.x)>EMax.x) EMax.x = fabsf(Nodes[i].mAABB.mExtents.x); \
  444. if(fabsf(Nodes[i].mAABB.mExtents.y)>EMax.y) EMax.y = fabsf(Nodes[i].mAABB.mExtents.y); \
  445. if(fabsf(Nodes[i].mAABB.mExtents.z)>EMax.z) EMax.z = fabsf(Nodes[i].mAABB.mExtents.z); \
  446. }
  447. #define INIT_QUANTIZATION \
  448. udword nbc=15; /* Keep one bit for sign */ \
  449. udword nbe=15; /* Keep one bit for fix */ \
  450. if(!gFixQuantized) nbe++; \
  451. \
  452. /* Compute quantization coeffs */ \
  453. Point CQuantCoeff, EQuantCoeff; \
  454. CQuantCoeff.x = CMax.x!=0.0f ? float((1<<nbc)-1)/CMax.x : 0.0f; \
  455. CQuantCoeff.y = CMax.y!=0.0f ? float((1<<nbc)-1)/CMax.y : 0.0f; \
  456. CQuantCoeff.z = CMax.z!=0.0f ? float((1<<nbc)-1)/CMax.z : 0.0f; \
  457. EQuantCoeff.x = EMax.x!=0.0f ? float((1<<nbe)-1)/EMax.x : 0.0f; \
  458. EQuantCoeff.y = EMax.y!=0.0f ? float((1<<nbe)-1)/EMax.y : 0.0f; \
  459. EQuantCoeff.z = EMax.z!=0.0f ? float((1<<nbe)-1)/EMax.z : 0.0f; \
  460. /* Compute and save dequantization coeffs */ \
  461. mCenterCoeff.x = CQuantCoeff.x!=0.0f ? 1.0f / CQuantCoeff.x : 0.0f; \
  462. mCenterCoeff.y = CQuantCoeff.y!=0.0f ? 1.0f / CQuantCoeff.y : 0.0f; \
  463. mCenterCoeff.z = CQuantCoeff.z!=0.0f ? 1.0f / CQuantCoeff.z : 0.0f; \
  464. mExtentsCoeff.x = EQuantCoeff.x!=0.0f ? 1.0f / EQuantCoeff.x : 0.0f; \
  465. mExtentsCoeff.y = EQuantCoeff.y!=0.0f ? 1.0f / EQuantCoeff.y : 0.0f; \
  466. mExtentsCoeff.z = EQuantCoeff.z!=0.0f ? 1.0f / EQuantCoeff.z : 0.0f; \
  467. #define PERFORM_QUANTIZATION \
  468. /* Quantize */ \
  469. mNodes[i].mAABB.mCenter[0] = sword(Nodes[i].mAABB.mCenter.x * CQuantCoeff.x); \
  470. mNodes[i].mAABB.mCenter[1] = sword(Nodes[i].mAABB.mCenter.y * CQuantCoeff.y); \
  471. mNodes[i].mAABB.mCenter[2] = sword(Nodes[i].mAABB.mCenter.z * CQuantCoeff.z); \
  472. mNodes[i].mAABB.mExtents[0] = uword(Nodes[i].mAABB.mExtents.x * EQuantCoeff.x); \
  473. mNodes[i].mAABB.mExtents[1] = uword(Nodes[i].mAABB.mExtents.y * EQuantCoeff.y); \
  474. mNodes[i].mAABB.mExtents[2] = uword(Nodes[i].mAABB.mExtents.z * EQuantCoeff.z); \
  475. /* Fix quantized boxes */ \
  476. if(gFixQuantized) \
  477. { \
  478. /* Make sure the quantized box is still valid */ \
  479. Point Max = Nodes[i].mAABB.mCenter + Nodes[i].mAABB.mExtents; \
  480. Point Min = Nodes[i].mAABB.mCenter - Nodes[i].mAABB.mExtents; \
  481. /* For each axis */ \
  482. for(udword j=0;j<3;j++) \
  483. { /* Dequantize the box center */ \
  484. float qc = float(mNodes[i].mAABB.mCenter[j]) * mCenterCoeff[j]; \
  485. bool FixMe=true; \
  486. do \
  487. { /* Dequantize the box extent */ \
  488. float qe = float(mNodes[i].mAABB.mExtents[j]) * mExtentsCoeff[j]; \
  489. /* Compare real & dequantized values */ \
  490. if(qc+qe<Max[j] || qc-qe>Min[j]) mNodes[i].mAABB.mExtents[j]++; \
  491. else FixMe=false; \
  492. /* Prevent wrapping */ \
  493. if(!mNodes[i].mAABB.mExtents[j]) \
  494. { \
  495. mNodes[i].mAABB.mExtents[j]=0xffff; \
  496. FixMe=false; \
  497. } \
  498. }while(FixMe); \
  499. } \
  500. }
  501. #define REMAP_DATA(member) \
  502. /* Fix data */ \
  503. Data = Nodes[i].member; \
  504. if(!(Data&1)) \
  505. { \
  506. /* Compute box number */ \
  507. udword Nb = (Data - udword(Nodes))/Nodes[i].GetNodeSize(); \
  508. Data = udword(&mNodes[Nb]); \
  509. } \
  510. /* ...remapped */ \
  511. mNodes[i].member = Data;
  512. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  513. /**
  514. * Constructor.
  515. */
  516. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  517. AABBQuantizedTree::AABBQuantizedTree() : mNodes(null)
  518. {
  519. }
  520. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  521. /**
  522. * Destructor.
  523. */
  524. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  525. AABBQuantizedTree::~AABBQuantizedTree()
  526. {
  527. DELETEARRAY(mNodes);
  528. }
  529. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  530. /**
  531. * Builds the collision tree from a generic AABB tree.
  532. * \param tree [in] generic AABB tree
  533. * \return true if success
  534. */
  535. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  536. bool AABBQuantizedTree::Build(AABBTree* tree)
  537. {
  538. // Checkings
  539. if(!tree) return false;
  540. // Check the input tree is complete
  541. udword NbTriangles = tree->GetNbPrimitives();
  542. udword NbNodes = tree->GetNbNodes();
  543. if(NbNodes!=NbTriangles*2-1) return false;
  544. // Get nodes
  545. mNbNodes = NbNodes;
  546. DELETEARRAY(mNodes);
  547. AABBCollisionNode* Nodes = new AABBCollisionNode[mNbNodes];
  548. CHECKALLOC(Nodes);
  549. // Build the tree
  550. udword CurID = 1;
  551. _BuildCollisionTree(Nodes, 0, CurID, tree);
  552. // Quantize
  553. {
  554. mNodes = new AABBQuantizedNode[mNbNodes];
  555. CHECKALLOC(mNodes);
  556. // Get max values
  557. FIND_MAX_VALUES
  558. // Quantization
  559. INIT_QUANTIZATION
  560. // Quantize
  561. udword Data;
  562. for(udword i=0;i<mNbNodes;i++)
  563. {
  564. PERFORM_QUANTIZATION
  565. REMAP_DATA(mData)
  566. }
  567. DELETEARRAY(Nodes);
  568. }
  569. return true;
  570. }
  571. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  572. /**
  573. * Refits the collision tree after vertices have been modified.
  574. * \param mesh_interface [in] mesh interface for current model
  575. * \return true if success
  576. */
  577. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  578. bool AABBQuantizedTree::Refit(const MeshInterface* mesh_interface)
  579. {
  580. ASSERT(!"Not implemented since requantizing is painful !");
  581. return false;
  582. }
  583. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  584. /**
  585. * Walks the tree and call the user back for each node.
  586. * \param callback [in] walking callback
  587. * \param user_data [in] callback's user data
  588. * \return true if success
  589. */
  590. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  591. bool AABBQuantizedTree::Walk(GenericWalkingCallback callback, void* user_data) const
  592. {
  593. if(!callback) return false;
  594. struct Local
  595. {
  596. static void _Walk(const AABBQuantizedNode* current_node, GenericWalkingCallback callback, void* user_data)
  597. {
  598. if(!current_node || !(callback)(current_node, user_data)) return;
  599. if(!current_node->IsLeaf())
  600. {
  601. _Walk(current_node->GetPos(), callback, user_data);
  602. _Walk(current_node->GetNeg(), callback, user_data);
  603. }
  604. }
  605. };
  606. Local::_Walk(mNodes, callback, user_data);
  607. return true;
  608. }
  609. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  610. /**
  611. * Constructor.
  612. */
  613. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  614. AABBQuantizedNoLeafTree::AABBQuantizedNoLeafTree() : mNodes(null)
  615. {
  616. }
  617. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  618. /**
  619. * Destructor.
  620. */
  621. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  622. AABBQuantizedNoLeafTree::~AABBQuantizedNoLeafTree()
  623. {
  624. DELETEARRAY(mNodes);
  625. }
  626. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  627. /**
  628. * Builds the collision tree from a generic AABB tree.
  629. * \param tree [in] generic AABB tree
  630. * \return true if success
  631. */
  632. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  633. bool AABBQuantizedNoLeafTree::Build(AABBTree* tree)
  634. {
  635. // Checkings
  636. if(!tree) return false;
  637. // Check the input tree is complete
  638. udword NbTriangles = tree->GetNbPrimitives();
  639. udword NbNodes = tree->GetNbNodes();
  640. if(NbNodes!=NbTriangles*2-1) return false;
  641. // Get nodes
  642. mNbNodes = NbTriangles-1;
  643. DELETEARRAY(mNodes);
  644. AABBNoLeafNode* Nodes = new AABBNoLeafNode[mNbNodes];
  645. CHECKALLOC(Nodes);
  646. // Build the tree
  647. udword CurID = 1;
  648. _BuildNoLeafTree(Nodes, 0, CurID, tree);
  649. ASSERT(CurID==mNbNodes);
  650. // Quantize
  651. {
  652. mNodes = new AABBQuantizedNoLeafNode[mNbNodes];
  653. CHECKALLOC(mNodes);
  654. // Get max values
  655. FIND_MAX_VALUES
  656. // Quantization
  657. INIT_QUANTIZATION
  658. // Quantize
  659. udword Data;
  660. for(udword i=0;i<mNbNodes;i++)
  661. {
  662. PERFORM_QUANTIZATION
  663. REMAP_DATA(mPosData)
  664. REMAP_DATA(mNegData)
  665. }
  666. DELETEARRAY(Nodes);
  667. }
  668. return true;
  669. }
  670. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  671. /**
  672. * Refits the collision tree after vertices have been modified.
  673. * \param mesh_interface [in] mesh interface for current model
  674. * \return true if success
  675. */
  676. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  677. bool AABBQuantizedNoLeafTree::Refit(const MeshInterface* mesh_interface)
  678. {
  679. ASSERT(!"Not implemented since requantizing is painful !");
  680. return false;
  681. }
  682. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  683. /**
  684. * Walks the tree and call the user back for each node.
  685. * \param callback [in] walking callback
  686. * \param user_data [in] callback's user data
  687. * \return true if success
  688. */
  689. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  690. bool AABBQuantizedNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const
  691. {
  692. if(!callback) return false;
  693. struct Local
  694. {
  695. static void _Walk(const AABBQuantizedNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data)
  696. {
  697. if(!current_node || !(callback)(current_node, user_data)) return;
  698. if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data);
  699. if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data);
  700. }
  701. };
  702. Local::_Walk(mNodes, callback, user_data);
  703. return true;
  704. }