OPC_OptimizedTree.cpp 32 KB

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