Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IceOBB.cpp
Go to the documentation of this file.
1 
8 
11 
17 
20 // Precompiled Header
21 #include "Stdafx.h"
22 
23 
24 using namespace Opcode;
25 
27 
32 bool OBB::ContainsPoint(const Point& p) const
34 {
35  // Point in OBB test using lazy evaluation and early exits
36 
37  // Translate to box space
38  Point RelPoint = p - mCenter;
39 
40  // Point * mRot maps from box space to world space
41  // mRot * Point maps from world space to box space (what we need here)
42 
43  float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z;
44  if(f >= mExtents.x || f <= -mExtents.x) return false;
45 
46  f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z;
47  if(f >= mExtents.y || f <= -mExtents.y) return false;
48 
49  f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z;
50  if(f >= mExtents.z || f <= -mExtents.z) return false;
51  return true;
52 }
53 
55 
60 void OBB::Create(const AABB& aabb, const Matrix4x4& mat)
62 {
63  // Note: must be coherent with Rotate()
64 
65  aabb.GetCenter(mCenter);
66  aabb.GetExtents(mExtents);
67  // Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity).
68 
69  // So following what's done in Rotate:
70  // - x-form the center
71  mCenter *= mat;
72  // - combine rotation with identity, i.e. just use given matrix
73  mRot = mat;
74 }
75 
77 
82 bool OBB::ComputePlanes(Plane* planes) const
84 {
85  // Checkings
86  if(!planes) return false;
87 
88  Point Axis0 = mRot[0];
89  Point Axis1 = mRot[1];
90  Point Axis2 = mRot[2];
91 
92  // Writes normals
93  planes[0].n = Axis0;
94  planes[1].n = -Axis0;
95  planes[2].n = Axis1;
96  planes[3].n = -Axis1;
97  planes[4].n = Axis2;
98  planes[5].n = -Axis2;
99 
100  // Compute a point on each plane
101  Point p0 = mCenter + Axis0 * mExtents.x;
102  Point p1 = mCenter - Axis0 * mExtents.x;
103  Point p2 = mCenter + Axis1 * mExtents.y;
104  Point p3 = mCenter - Axis1 * mExtents.y;
105  Point p4 = mCenter + Axis2 * mExtents.z;
106  Point p5 = mCenter - Axis2 * mExtents.z;
107 
108  // Compute d
109  planes[0].d = -(planes[0].n|p0);
110  planes[1].d = -(planes[1].n|p1);
111  planes[2].d = -(planes[2].n|p2);
112  planes[3].d = -(planes[3].n|p3);
113  planes[4].d = -(planes[4].n|p4);
114  planes[5].d = -(planes[5].n|p5);
115 
116  return true;
117 }
118 
120 
125 bool OBB::ComputePoints(Point* pts) const
127 {
128  // Checkings
129  if(!pts) return false;
130 
131  Point Axis0 = mRot[0];
132  Point Axis1 = mRot[1];
133  Point Axis2 = mRot[2];
134 
135  Axis0 *= mExtents.x;
136  Axis1 *= mExtents.y;
137  Axis2 *= mExtents.z;
138 
139  // 7+------+6 0 = ---
140  // /| /| 1 = +--
141  // / | / | 2 = ++-
142  // / 4+---/--+5 3 = -+-
143  // 3+------+2 / y z 4 = --+
144  // | / | / | / 5 = +-+
145  // |/ |/ |/ 6 = +++
146  // 0+------+1 *---x 7 = -++
147 
148  pts[0] = mCenter - Axis0 - Axis1 - Axis2;
149  pts[1] = mCenter + Axis0 - Axis1 - Axis2;
150  pts[2] = mCenter + Axis0 + Axis1 - Axis2;
151  pts[3] = mCenter - Axis0 + Axis1 - Axis2;
152  pts[4] = mCenter - Axis0 - Axis1 + Axis2;
153  pts[5] = mCenter + Axis0 - Axis1 + Axis2;
154  pts[6] = mCenter + Axis0 + Axis1 + Axis2;
155  pts[7] = mCenter - Axis0 + Axis1 + Axis2;
156 
157  return true;
158 }
159 
161 
166 bool OBB::ComputeVertexNormals(Point* pts) const
168 {
169  static float VertexNormals[] =
170  {
178  -INVSQRT3, INVSQRT3, INVSQRT3
179  };
180 
181  if(!pts) return false;
182 
183  const Point* VN = (const Point*)VertexNormals;
184  for(udword i=0;i<8;i++)
185  {
186  pts[i] = VN[i] * mRot;
187  }
188 
189  return true;
190 }
191 
193 
197 const udword* OBB::GetEdges() const
199 {
200  static udword Indices[] = {
201  0, 1, 1, 2, 2, 3, 3, 0,
202  7, 6, 6, 5, 5, 4, 4, 7,
203  1, 5, 6, 2,
204  3, 7, 4, 0
205  };
206  return Indices;
207 }
208 
210 
214 const Point* OBB::GetLocalEdgeNormals() const
216 {
217  static float EdgeNormals[] =
218  {
219  0, -INVSQRT2, -INVSQRT2, // 0-1
220  INVSQRT2, 0, -INVSQRT2, // 1-2
221  0, INVSQRT2, -INVSQRT2, // 2-3
222  -INVSQRT2, 0, -INVSQRT2, // 3-0
223 
224  0, INVSQRT2, INVSQRT2, // 7-6
225  INVSQRT2, 0, INVSQRT2, // 6-5
226  0, -INVSQRT2, INVSQRT2, // 5-4
227  -INVSQRT2, 0, INVSQRT2, // 4-7
228 
229  INVSQRT2, -INVSQRT2, 0, // 1-5
230  INVSQRT2, INVSQRT2, 0, // 6-2
231  -INVSQRT2, INVSQRT2, 0, // 3-7
232  -INVSQRT2, -INVSQRT2, 0 // 4-0
233  };
234  return (const Point*)EdgeNormals;
235 }
236 
238 
243 void OBB::ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const
245 {
246  OPASSERT(edge_index<12);
247  world_normal = GetLocalEdgeNormals()[edge_index] * mRot;
248 }
249 
251 
255 void OBB::ComputeLSS(LSS& lss) const
257 {
258  Point Axis0 = mRot[0];
259  Point Axis1 = mRot[1];
260  Point Axis2 = mRot[2];
261 
262  switch(mExtents.LargestAxis())
263  {
264  case 0:
265  lss.mRadius = (mExtents.y + mExtents.z)*0.5f;
266  lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius);
267  lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius);
268  break;
269  case 1:
270  lss.mRadius = (mExtents.x + mExtents.z)*0.5f;
271  lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius);
272  lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius);
273  break;
274  case 2:
275  lss.mRadius = (mExtents.x + mExtents.y)*0.5f;
276  lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius);
277  lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius);
278  break;
279  default:
280  // Should not happen
281  break;
282  }
283 }
284 
286 
291 bool OBB::IsInside(const OBB& box) const
293 {
294  // Make a 4x4 from the box & inverse it
295  Matrix4x4 M0Inv;
296  {
297  Matrix4x4 M0 = box.mRot;
298  M0.SetTrans(box.mCenter);
299  InvertPRMatrix(M0Inv, M0);
300  }
301 
302  // With our inversed 4x4, create box1 in space of box0
303  OBB _1in0;
304  Rotate(M0Inv, _1in0);
305 
306  // This should cancel out box0's rotation, i.e. it's now an AABB.
307  // => Center(0,0,0), Rot(identity)
308 
309  // The two boxes are in the same space so now we can compare them.
310 
311  // Create the AABB of (box1 in space of box0)
312  const Matrix3x3& mtx = _1in0.mRot;
313 
314  float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x;
315  if(f > _1in0.mCenter.x) return FALSE;
316  if(-f < _1in0.mCenter.x) return FALSE;
317 
318  f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y;
319  if(f > _1in0.mCenter.y) return FALSE;
320  if(-f < _1in0.mCenter.y) return FALSE;
321 
322  f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z;
323  if(f > _1in0.mCenter.z) return FALSE;
324  if(-f < _1in0.mCenter.z) return FALSE;
325 
326  return TRUE;
327 }
328