OPC_OptimizedTree.cpp 32 KB

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