IceAABB.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. /**
  3. * Contains AABB-related code.
  4. * \file IceAABB.cpp
  5. * \author Pierre Terdiman
  6. * \date January, 29, 2000
  7. */
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. /**
  11. * AABB class.
  12. * \class AABB
  13. * \author Pierre Terdiman
  14. * \version 1.0
  15. */
  16. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  18. // Precompiled Header
  19. #include "Stdafx.h"
  20. using namespace IceMaths;
  21. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  22. /**
  23. * Computes the sum of two AABBs.
  24. * \param aabb [in] the other AABB
  25. * \return Self-Reference
  26. */
  27. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  28. AABB& AABB::Add(const AABB& aabb)
  29. {
  30. // Compute new min & max values
  31. Point Min; GetMin(Min);
  32. Point Tmp; aabb.GetMin(Tmp);
  33. Min.Min(Tmp);
  34. Point Max; GetMax(Max);
  35. aabb.GetMax(Tmp);
  36. Max.Max(Tmp);
  37. // Update this
  38. SetMinMax(Min, Max);
  39. return *this;
  40. }
  41. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  42. /**
  43. * Makes a cube from the AABB.
  44. * \param cube [out] the cube AABB
  45. * \return cube edge length
  46. */
  47. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  48. float AABB::MakeCube(AABB& cube) const
  49. {
  50. Point Ext; GetExtents(Ext);
  51. float Max = Ext.Max();
  52. Point Cnt; GetCenter(Cnt);
  53. cube.SetCenterExtents(Cnt, Point(Max, Max, Max));
  54. return Max;
  55. }
  56. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  57. /**
  58. * Makes a sphere from the AABB.
  59. * \param sphere [out] sphere containing the AABB
  60. */
  61. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. void AABB::MakeSphere(Sphere& sphere) const
  63. {
  64. GetExtents(sphere.mCenter);
  65. sphere.mRadius = sphere.mCenter.Magnitude() * 1.00001f; // To make sure sphere::Contains(*this) succeeds
  66. GetCenter(sphere.mCenter);
  67. }
  68. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  69. /**
  70. * Checks a box is inside another box.
  71. * \param box [in] the other AABB
  72. * \return true if current box is inside input box
  73. */
  74. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  75. bool AABB::IsInside(const AABB& box) const
  76. {
  77. if(box.GetMin(0)>GetMin(0)) return false;
  78. if(box.GetMin(1)>GetMin(1)) return false;
  79. if(box.GetMin(2)>GetMin(2)) return false;
  80. if(box.GetMax(0)<GetMax(0)) return false;
  81. if(box.GetMax(1)<GetMax(1)) return false;
  82. if(box.GetMax(2)<GetMax(2)) return false;
  83. return true;
  84. }
  85. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  86. /**
  87. * Computes the AABB planes.
  88. * \param planes [out] 6 planes surrounding the box
  89. * \return true if success
  90. */
  91. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  92. bool AABB::ComputePlanes(Plane* planes) const
  93. {
  94. // Checkings
  95. if(!planes) return false;
  96. Point Center, Extents;
  97. GetCenter(Center);
  98. GetExtents(Extents);
  99. // Writes normals
  100. planes[0].n = Point(1.0f, 0.0f, 0.0f);
  101. planes[1].n = Point(-1.0f, 0.0f, 0.0f);
  102. planes[2].n = Point(0.0f, 1.0f, 0.0f);
  103. planes[3].n = Point(0.0f, -1.0f, 0.0f);
  104. planes[4].n = Point(0.0f, 0.0f, 1.0f);
  105. planes[5].n = Point(0.0f, 0.0f, -1.0f);
  106. // Compute a point on each plane
  107. Point p0 = Point(Center.x+Extents.x, Center.y, Center.z);
  108. Point p1 = Point(Center.x-Extents.x, Center.y, Center.z);
  109. Point p2 = Point(Center.x, Center.y+Extents.y, Center.z);
  110. Point p3 = Point(Center.x, Center.y-Extents.y, Center.z);
  111. Point p4 = Point(Center.x, Center.y, Center.z+Extents.z);
  112. Point p5 = Point(Center.x, Center.y, Center.z-Extents.z);
  113. // Compute d
  114. planes[0].d = -(planes[0].n|p0);
  115. planes[1].d = -(planes[1].n|p1);
  116. planes[2].d = -(planes[2].n|p2);
  117. planes[3].d = -(planes[3].n|p3);
  118. planes[4].d = -(planes[4].n|p4);
  119. planes[5].d = -(planes[5].n|p5);
  120. return true;
  121. }
  122. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  123. /**
  124. * Computes the aabb points.
  125. * \param pts [out] 8 box points
  126. * \return true if success
  127. */
  128. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  129. bool AABB::ComputePoints(Point* pts) const
  130. {
  131. // Checkings
  132. if(!pts) return false;
  133. // Get box corners
  134. Point min; GetMin(min);
  135. Point max; GetMax(max);
  136. // 7+------+6 0 = ---
  137. // /| /| 1 = +--
  138. // / | / | 2 = ++-
  139. // / 4+---/--+5 3 = -+-
  140. // 3+------+2 / y z 4 = --+
  141. // | / | / | / 5 = +-+
  142. // |/ |/ |/ 6 = +++
  143. // 0+------+1 *---x 7 = -++
  144. // Generate 8 corners of the bbox
  145. pts[0] = Point(min.x, min.y, min.z);
  146. pts[1] = Point(max.x, min.y, min.z);
  147. pts[2] = Point(max.x, max.y, min.z);
  148. pts[3] = Point(min.x, max.y, min.z);
  149. pts[4] = Point(min.x, min.y, max.z);
  150. pts[5] = Point(max.x, min.y, max.z);
  151. pts[6] = Point(max.x, max.y, max.z);
  152. pts[7] = Point(min.x, max.y, max.z);
  153. return true;
  154. }
  155. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  156. /**
  157. * Gets vertex normals.
  158. * \param pts [out] 8 box points
  159. * \return true if success
  160. */
  161. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  162. const Point* AABB::GetVertexNormals() const
  163. {
  164. static const float VertexNormals[] =
  165. {
  166. -INVSQRT3, -INVSQRT3, -INVSQRT3,
  167. INVSQRT3, -INVSQRT3, -INVSQRT3,
  168. INVSQRT3, INVSQRT3, -INVSQRT3,
  169. -INVSQRT3, INVSQRT3, -INVSQRT3,
  170. -INVSQRT3, -INVSQRT3, INVSQRT3,
  171. INVSQRT3, -INVSQRT3, INVSQRT3,
  172. INVSQRT3, INVSQRT3, INVSQRT3,
  173. -INVSQRT3, INVSQRT3, INVSQRT3
  174. };
  175. return (const Point*)VertexNormals;
  176. }
  177. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  178. /**
  179. * Returns edges.
  180. * \return 24 indices (12 edges) indexing the list returned by ComputePoints()
  181. */
  182. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. const udword* AABB::GetEdges() const
  184. {
  185. static const udword Indices[] = {
  186. 0, 1, 1, 2, 2, 3, 3, 0,
  187. 7, 6, 6, 5, 5, 4, 4, 7,
  188. 1, 5, 6, 2,
  189. 3, 7, 4, 0
  190. };
  191. return Indices;
  192. }
  193. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  194. /**
  195. * Returns edge normals.
  196. * \return edge normals in local space
  197. */
  198. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  199. const Point* AABB::GetEdgeNormals() const
  200. {
  201. static const float EdgeNormals[] =
  202. {
  203. 0, -INVSQRT2, -INVSQRT2, // 0-1
  204. INVSQRT2, 0, -INVSQRT2, // 1-2
  205. 0, INVSQRT2, -INVSQRT2, // 2-3
  206. -INVSQRT2, 0, -INVSQRT2, // 3-0
  207. 0, INVSQRT2, INVSQRT2, // 7-6
  208. INVSQRT2, 0, INVSQRT2, // 6-5
  209. 0, -INVSQRT2, INVSQRT2, // 5-4
  210. -INVSQRT2, 0, INVSQRT2, // 4-7
  211. INVSQRT2, -INVSQRT2, 0, // 1-5
  212. INVSQRT2, INVSQRT2, 0, // 6-2
  213. -INVSQRT2, INVSQRT2, 0, // 3-7
  214. -INVSQRT2, -INVSQRT2, 0 // 4-0
  215. };
  216. return (const Point*)EdgeNormals;
  217. }
  218. // ===========================================================================
  219. // (C) 1996-98 Vienna University of Technology
  220. // ===========================================================================
  221. // NAME: bboxarea
  222. // TYPE: c++ code
  223. // PROJECT: Bounding Box Area
  224. // CONTENT: Computes area of 2D projection of 3D oriented bounding box
  225. // VERSION: 1.0
  226. // ===========================================================================
  227. // AUTHORS: ds Dieter Schmalstieg
  228. // ep Erik Pojar
  229. // ===========================================================================
  230. // HISTORY:
  231. //
  232. // 19-sep-99 15:23:03 ds last modification
  233. // 01-dec-98 15:23:03 ep created
  234. // ===========================================================================
  235. //----------------------------------------------------------------------------
  236. // SAMPLE CODE STARTS HERE
  237. //----------------------------------------------------------------------------
  238. // NOTE: This sample program requires OPEN INVENTOR!
  239. //indexlist: this table stores the 64 possible cases of classification of
  240. //the eyepoint with respect to the 6 defining planes of the bbox (2^6=64)
  241. //only 26 (3^3-1, where 1 is "inside" cube) of these cases are valid.
  242. //the first 6 numbers in each row are the indices of the bbox vertices that
  243. //form the outline of which we want to compute the area (counterclockwise
  244. //ordering), the 7th entry means the number of vertices in the outline.
  245. //there are 6 cases with a single face and and a 4-vertex outline, and
  246. //20 cases with 2 or 3 faces and a 6-vertex outline. a value of 0 indicates
  247. //an invalid case.
  248. // Original list was made of 7 items, I added an 8th element:
  249. // - to padd on a cache line
  250. // - to repeat the first entry to avoid modulos
  251. //
  252. // I also replaced original ints with sbytes.
  253. static const sbyte gIndexList[64][8] =
  254. {
  255. {-1,-1,-1,-1,-1,-1,-1, 0}, // 0 inside
  256. { 0, 4, 7, 3, 0,-1,-1, 4}, // 1 left
  257. { 1, 2, 6, 5, 1,-1,-1, 4}, // 2 right
  258. {-1,-1,-1,-1,-1,-1,-1, 0}, // 3 -
  259. { 0, 1, 5, 4, 0,-1,-1, 4}, // 4 bottom
  260. { 0, 1, 5, 4, 7, 3, 0, 6}, // 5 bottom, left
  261. { 0, 1, 2, 6, 5, 4, 0, 6}, // 6 bottom, right
  262. {-1,-1,-1,-1,-1,-1,-1, 0}, // 7 -
  263. { 2, 3, 7, 6, 2,-1,-1, 4}, // 8 top
  264. { 0, 4, 7, 6, 2, 3, 0, 6}, // 9 top, left
  265. { 1, 2, 3, 7, 6, 5, 1, 6}, //10 top, right
  266. {-1,-1,-1,-1,-1,-1,-1, 0}, //11 -
  267. {-1,-1,-1,-1,-1,-1,-1, 0}, //12 -
  268. {-1,-1,-1,-1,-1,-1,-1, 0}, //13 -
  269. {-1,-1,-1,-1,-1,-1,-1, 0}, //14 -
  270. {-1,-1,-1,-1,-1,-1,-1, 0}, //15 -
  271. { 0, 3, 2, 1, 0,-1,-1, 4}, //16 front
  272. { 0, 4, 7, 3, 2, 1, 0, 6}, //17 front, left
  273. { 0, 3, 2, 6, 5, 1, 0, 6}, //18 front, right
  274. {-1,-1,-1,-1,-1,-1,-1, 0}, //19 -
  275. { 0, 3, 2, 1, 5, 4, 0, 6}, //20 front, bottom
  276. { 1, 5, 4, 7, 3, 2, 1, 6}, //21 front, bottom, left
  277. { 0, 3, 2, 6, 5, 4, 0, 6}, //22 front, bottom, right
  278. {-1,-1,-1,-1,-1,-1,-1, 0}, //23 -
  279. { 0, 3, 7, 6, 2, 1, 0, 6}, //24 front, top
  280. { 0, 4, 7, 6, 2, 1, 0, 6}, //25 front, top, left
  281. { 0, 3, 7, 6, 5, 1, 0, 6}, //26 front, top, right
  282. {-1,-1,-1,-1,-1,-1,-1, 0}, //27 -
  283. {-1,-1,-1,-1,-1,-1,-1, 0}, //28 -
  284. {-1,-1,-1,-1,-1,-1,-1, 0}, //29 -
  285. {-1,-1,-1,-1,-1,-1,-1, 0}, //30 -
  286. {-1,-1,-1,-1,-1,-1,-1, 0}, //31 -
  287. { 4, 5, 6, 7, 4,-1,-1, 4}, //32 back
  288. { 0, 4, 5, 6, 7, 3, 0, 6}, //33 back, left
  289. { 1, 2, 6, 7, 4, 5, 1, 6}, //34 back, right
  290. {-1,-1,-1,-1,-1,-1,-1, 0}, //35 -
  291. { 0, 1, 5, 6, 7, 4, 0, 6}, //36 back, bottom
  292. { 0, 1, 5, 6, 7, 3, 0, 6}, //37 back, bottom, left
  293. { 0, 1, 2, 6, 7, 4, 0, 6}, //38 back, bottom, right
  294. {-1,-1,-1,-1,-1,-1,-1, 0}, //39 -
  295. { 2, 3, 7, 4, 5, 6, 2, 6}, //40 back, top
  296. { 0, 4, 5, 6, 2, 3, 0, 6}, //41 back, top, left
  297. { 1, 2, 3, 7, 4, 5, 1, 6}, //42 back, top, right
  298. {-1,-1,-1,-1,-1,-1,-1, 0}, //43 invalid
  299. {-1,-1,-1,-1,-1,-1,-1, 0}, //44 invalid
  300. {-1,-1,-1,-1,-1,-1,-1, 0}, //45 invalid
  301. {-1,-1,-1,-1,-1,-1,-1, 0}, //46 invalid
  302. {-1,-1,-1,-1,-1,-1,-1, 0}, //47 invalid
  303. {-1,-1,-1,-1,-1,-1,-1, 0}, //48 invalid
  304. {-1,-1,-1,-1,-1,-1,-1, 0}, //49 invalid
  305. {-1,-1,-1,-1,-1,-1,-1, 0}, //50 invalid
  306. {-1,-1,-1,-1,-1,-1,-1, 0}, //51 invalid
  307. {-1,-1,-1,-1,-1,-1,-1, 0}, //52 invalid
  308. {-1,-1,-1,-1,-1,-1,-1, 0}, //53 invalid
  309. {-1,-1,-1,-1,-1,-1,-1, 0}, //54 invalid
  310. {-1,-1,-1,-1,-1,-1,-1, 0}, //55 invalid
  311. {-1,-1,-1,-1,-1,-1,-1, 0}, //56 invalid
  312. {-1,-1,-1,-1,-1,-1,-1, 0}, //57 invalid
  313. {-1,-1,-1,-1,-1,-1,-1, 0}, //58 invalid
  314. {-1,-1,-1,-1,-1,-1,-1, 0}, //59 invalid
  315. {-1,-1,-1,-1,-1,-1,-1, 0}, //60 invalid
  316. {-1,-1,-1,-1,-1,-1,-1, 0}, //61 invalid
  317. {-1,-1,-1,-1,-1,-1,-1, 0}, //62 invalid
  318. {-1,-1,-1,-1,-1,-1,-1, 0} //63 invalid
  319. };
  320. const sbyte* AABB::ComputeOutline(const Point& local_eye, sdword& num) const
  321. {
  322. // Get box corners
  323. Point min; GetMin(min);
  324. Point max; GetMax(max);
  325. // Compute 6-bit code to classify eye with respect to the 6 defining planes of the bbox
  326. int pos = ((local_eye.x < min.x) ? 1 : 0) // 1 = left
  327. + ((local_eye.x > max.x) ? 2 : 0) // 2 = right
  328. + ((local_eye.y < min.y) ? 4 : 0) // 4 = bottom
  329. + ((local_eye.y > max.y) ? 8 : 0) // 8 = top
  330. + ((local_eye.z < min.z) ? 16 : 0) // 16 = front
  331. + ((local_eye.z > max.z) ? 32 : 0); // 32 = back
  332. // Look up number of vertices in outline
  333. num = (sdword)gIndexList[pos][7];
  334. // Zero indicates invalid case
  335. if(!num) return null;
  336. return &gIndexList[pos][0];
  337. }
  338. // calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box
  339. //const Point& eye, //eye point (in bbox object coordinates)
  340. //const AABB& box, //3d bbox
  341. //const Matrix4x4& mat, //free transformation for bbox
  342. //float width, float height, int& num)
  343. float AABB::ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num) const
  344. {
  345. const sbyte* Outline = ComputeOutline(eye, num);
  346. if(!Outline) return -1.0f;
  347. // Compute box vertices
  348. Point vertexBox[8], dst[8];
  349. ComputePoints(vertexBox);
  350. // Transform all outline corners into 2D screen space
  351. for(sdword i=0;i<num;i++)
  352. {
  353. HPoint Projected;
  354. vertexBox[Outline[i]].ProjectToScreen(width, height, mat, Projected);
  355. dst[i] = Projected;
  356. }
  357. float Sum = (dst[num-1][0] - dst[0][0]) * (dst[num-1][1] + dst[0][1]);
  358. for(int i=0; i<num-1; i++)
  359. Sum += (dst[i][0] - dst[i+1][0]) * (dst[i][1] + dst[i+1][1]);
  360. return Sum * 0.5f; //return computed value corrected by 0.5
  361. }