FCL  0.6.0
Flexible Collision Library
OBB-inl.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011-2014, Willow Garage, Inc.
5  * Copyright (c) 2014-2016, Open Source Robotics Foundation
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Open Source Robotics Foundation nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
38 #ifndef FCL_BV_OBB_INL_H
39 #define FCL_BV_OBB_INL_H
40 
41 #include "fcl/math/bv/OBB.h"
42 
43 namespace fcl
44 {
45 
46 //==============================================================================
47 extern template
48 class OBB<double>;
49 
50 //==============================================================================
51 extern template
52 void computeVertices(const OBB<double>& b, Vector3<double> vertices[8]);
53 
54 //==============================================================================
55 extern template
56 OBB<double> merge_largedist(const OBB<double>& b1, const OBB<double>& b2);
57 
58 //==============================================================================
59 extern template
60 OBB<double> merge_smalldist(const OBB<double>& b1, const OBB<double>& b2);
61 
62 //==============================================================================
63 extern template
64 bool obbDisjoint(
65  const Matrix3<double>& B,
66  const Vector3<double>& T,
67  const Vector3<double>& a,
68  const Vector3<double>& b);
69 
70 //==============================================================================
71 extern template
72 bool obbDisjoint(
73  const Transform3<double>& tf,
74  const Vector3<double>& a,
75  const Vector3<double>& b);
76 
77 //==============================================================================
78 template <typename S>
80 {
81  // Do nothing
82 }
83 
84 //==============================================================================
85 template <typename S>
86 OBB<S>::OBB(const Matrix3<S>& axis_,
87  const Vector3<S>& center_,
88  const Vector3<S>& extent_)
89  : axis(axis_), To(center_), extent(extent_)
90 {
91  // Do nothing
92 }
93 
94 //==============================================================================
95 template <typename S>
96 bool OBB<S>::overlap(const OBB<S>& other) const
97 {
100 
101  Vector3<S> t = other.To - To;
102  Vector3<S> T(
103  axis.col(0).dot(t), axis.col(1).dot(t), axis.col(2).dot(t));
104  Matrix3<S> R = axis.transpose() * other.axis;
105 
106  return !obbDisjoint(R, T, extent, other.extent);
107 }
108 
109 //==============================================================================
110 template <typename S>
111 bool OBB<S>::overlap(const OBB& other, OBB& overlap_part) const
112 {
113  return overlap(other);
114 }
115 
116 //==============================================================================
117 template <typename S>
118 bool OBB<S>::contain(const Vector3<S>& p) const
119 {
120  Vector3<S> local_p = p - To;
121  S proj = local_p.dot(axis.col(0));
122  if((proj > extent[0]) || (proj < -extent[0]))
123  return false;
124 
125  proj = local_p.dot(axis.col(1));
126  if((proj > extent[1]) || (proj < -extent[1]))
127  return false;
128 
129  proj = local_p.dot(axis.col(2));
130  if((proj > extent[2]) || (proj < -extent[2]))
131  return false;
132 
133  return true;
134 }
135 
136 //==============================================================================
137 template <typename S>
138 OBB<S>& OBB<S>::operator +=(const Vector3<S>& p)
139 {
140  OBB<S> bvp(axis, p, Vector3<S>::Zero());
141  *this += bvp;
142 
143  return *this;
144 }
145 
146 //==============================================================================
147 template <typename S>
149 {
150  *this = *this + other;
151 
152  return *this;
153 }
154 
155 //==============================================================================
156 template <typename S>
157 OBB<S> OBB<S>::operator +(const OBB<S>& other) const
158 {
159  Vector3<S> center_diff = To - other.To;
160  S max_extent = std::max(std::max(extent[0], extent[1]), extent[2]);
161  S max_extent2 = std::max(std::max(other.extent[0], other.extent[1]), other.extent[2]);
162  if(center_diff.norm() > 2 * (max_extent + max_extent2))
163  {
164  return merge_largedist(*this, other);
165  }
166  else
167  {
168  return merge_smalldist(*this, other);
169  }
170 }
171 
172 //==============================================================================
173 template <typename S>
174 S OBB<S>::width() const
175 {
176  return 2 * extent[0];
177 }
178 
179 //==============================================================================
180 template <typename S>
181 S OBB<S>::height() const
182 {
183  return 2 * extent[1];
184 }
185 
186 //==============================================================================
187 template <typename S>
188 S OBB<S>::depth() const
189 {
190  return 2 * extent[2];
191 }
192 
193 //==============================================================================
194 template <typename S>
195 S OBB<S>::volume() const
196 {
197  return width() * height() * depth();
198 }
199 
200 //==============================================================================
201 template <typename S>
202 S OBB<S>::size() const
203 {
204  return extent.squaredNorm();
205 }
206 
207 //==============================================================================
208 template <typename S>
209 const Vector3<S> OBB<S>::center() const
210 {
211  return To;
212 }
213 
214 //==============================================================================
215 template <typename S>
216 S OBB<S>::distance(const OBB& other, Vector3<S>* P,
217  Vector3<S>* Q) const
218 {
219  std::cerr << "OBB distance not implemented!" << std::endl;
220  return 0.0;
221 }
222 
223 //==============================================================================
224 template <typename S>
225 void computeVertices(const OBB<S>& b, Vector3<S> vertices[8])
226 {
227  const Vector3<S>& extent = b.extent;
228  const Vector3<S>& To = b.To;
229 
230  Vector3<S> extAxis0 = b.axis.col(0) * extent[0];
231  Vector3<S> extAxis1 = b.axis.col(1) * extent[1];
232  Vector3<S> extAxis2 = b.axis.col(2) * extent[2];
233 
234  vertices[0] = To - extAxis0 - extAxis1 - extAxis2;
235  vertices[1] = To + extAxis0 - extAxis1 - extAxis2;
236  vertices[2] = To + extAxis0 + extAxis1 - extAxis2;
237  vertices[3] = To - extAxis0 + extAxis1 - extAxis2;
238  vertices[4] = To - extAxis0 - extAxis1 + extAxis2;
239  vertices[5] = To + extAxis0 - extAxis1 + extAxis2;
240  vertices[6] = To + extAxis0 + extAxis1 + extAxis2;
241  vertices[7] = To - extAxis0 + extAxis1 + extAxis2;
242 }
243 
244 //==============================================================================
245 template <typename S>
246 OBB<S> merge_largedist(const OBB<S>& b1, const OBB<S>& b2)
247 {
248  Vector3<S> vertex[16];
249  computeVertices(b1, vertex);
250  computeVertices(b2, vertex + 8);
251  Matrix3<S> M;
252  Matrix3<S> E;
253  Vector3<S> s(0, 0, 0);
254 
255  OBB<S> b;
256  b.axis.col(0) = b1.To - b2.To;
257  b.axis.col(0).normalize();
258 
259  Vector3<S> vertex_proj[16];
260  for(int i = 0; i < 16; ++i)
261  {
262  vertex_proj[i] = vertex[i];
263  vertex_proj[i].noalias() -= b.axis.col(0) * vertex[i].dot(b.axis.col(0));
264  }
265 
266  getCovariance<S>(vertex_proj, nullptr, nullptr, nullptr, 16, M);
267  eigen_old(M, s, E);
268 
269  int min, mid, max;
270  if (s[0] > s[1])
271  {
272  max = 0;
273  min = 1;
274  }
275  else
276  {
277  min = 0;
278  max = 1;
279  }
280 
281  if (s[2] < s[min])
282  {
283  mid = min;
284  min = 2;
285  }
286  else if (s[2] > s[max])
287  {
288  mid = max;
289  max = 2;
290  }
291  else
292  {
293  mid = 2;
294  }
295 
296  b.axis.col(1) << E.col(0)[max], E.col(1)[max], E.col(2)[max];
297  b.axis.col(2) << E.col(0)[mid], E.col(1)[mid], E.col(2)[mid];
298 
299  // set obb centers and extensions
300  getExtentAndCenter<S>(
301  vertex, nullptr, nullptr, nullptr, 16, b.axis, b.To, b.extent);
302 
303  return b;
304 }
305 
306 //==============================================================================
307 template <typename S>
308 OBB<S> merge_smalldist(const OBB<S>& b1, const OBB<S>& b2)
309 {
310  OBB<S> b;
311  b.To = (b1.To + b2.To) * 0.5;
312  Quaternion<S> q0(b1.axis);
313  Quaternion<S> q1(b2.axis);
314  if(q0.dot(q1) < 0)
315  q1.coeffs() = -q1.coeffs();
316 
317  Quaternion<S> q(q0.coeffs() + q1.coeffs());
318  q.normalize();
319  b.axis = q.toRotationMatrix();
320 
321 
322  Vector3<S> vertex[8], diff;
323  S real_max = std::numeric_limits<S>::max();
324  Vector3<S> pmin(real_max, real_max, real_max);
325  Vector3<S> pmax(-real_max, -real_max, -real_max);
326 
327  computeVertices(b1, vertex);
328  for(int i = 0; i < 8; ++i)
329  {
330  diff = vertex[i] - b.To;
331  for(int j = 0; j < 3; ++j)
332  {
333  S dot = diff.dot(b.axis.col(j));
334  if(dot > pmax[j])
335  pmax[j] = dot;
336  else if(dot < pmin[j])
337  pmin[j] = dot;
338  }
339  }
340 
341  computeVertices(b2, vertex);
342  for(int i = 0; i < 8; ++i)
343  {
344  diff = vertex[i] - b.To;
345  for(int j = 0; j < 3; ++j)
346  {
347  S dot = diff.dot(b.axis.col(j));
348  if(dot > pmax[j])
349  pmax[j] = dot;
350  else if(dot < pmin[j])
351  pmin[j] = dot;
352  }
353  }
354 
355  for(int j = 0; j < 3; ++j)
356  {
357  b.To += (b.axis.col(j) * (0.5 * (pmax[j] + pmin[j])));
358  b.extent[j] = 0.5 * (pmax[j] - pmin[j]);
359  }
360 
361  return b;
362 }
363 
364 //==============================================================================
365 template <typename S, typename Derived>
367  const OBB<S>& bv, const Eigen::MatrixBase<Derived>& t)
368 {
369  OBB<S> res(bv);
370  res.To += t;
371  return res;
372 }
373 
374 //==============================================================================
375 template <typename S, typename DerivedA, typename DerivedB>
376 bool overlap(const Eigen::MatrixBase<DerivedA>& R0,
377  const Eigen::MatrixBase<DerivedB>& T0,
378  const OBB<S>& b1, const OBB<S>& b2)
379 {
380  typename DerivedA::PlainObject R0b2 = R0 * b2.axis;
381  typename DerivedA::PlainObject R = b1.axis.transpose() * R0b2;
382 
383  typename DerivedB::PlainObject Ttemp = R0 * b2.To + T0 - b1.To;
384  typename DerivedB::PlainObject T = Ttemp.transpose() * b1.axis;
385 
386  return !obbDisjoint(R, T, b1.extent, b2.extent);
387 }
388 
389 //==============================================================================
390 template <typename S>
391 bool obbDisjoint(const Matrix3<S>& B, const Vector3<S>& T,
392  const Vector3<S>& a, const Vector3<S>& b)
393 {
394  register S t, s;
395  const S reps = 1e-6;
396 
397  Matrix3<S> Bf = B.cwiseAbs();
398  Bf.array() += reps;
399 
400  // if any of these tests are one-sided, then the polyhedra are disjoint
401 
402  // A1 x A2 = A0
403  t = ((T[0] < 0.0) ? -T[0] : T[0]);
404 
405  if(t > (a[0] + Bf.row(0).dot(b)))
406  return true;
407 
408  // B1 x B2 = B0
409  s = B.col(0).dot(T);
410  t = ((s < 0.0) ? -s : s);
411 
412  if(t > (b[0] + Bf.col(0).dot(a)))
413  return true;
414 
415  // A2 x A0 = A1
416  t = ((T[1] < 0.0) ? -T[1] : T[1]);
417 
418  if(t > (a[1] + Bf.row(1).dot(b)))
419  return true;
420 
421  // A0 x A1 = A2
422  t =((T[2] < 0.0) ? -T[2] : T[2]);
423 
424  if(t > (a[2] + Bf.row(2).dot(b)))
425  return true;
426 
427  // B2 x B0 = B1
428  s = B.col(1).dot(T);
429  t = ((s < 0.0) ? -s : s);
430 
431  if(t > (b[1] + Bf.col(1).dot(a)))
432  return true;
433 
434  // B0 x B1 = B2
435  s = B.col(2).dot(T);
436  t = ((s < 0.0) ? -s : s);
437 
438  if(t > (b[2] + Bf.col(2).dot(a)))
439  return true;
440 
441  // A0 x B0
442  s = T[2] * B(1, 0) - T[1] * B(2, 0);
443  t = ((s < 0.0) ? -s : s);
444 
445  if(t > (a[1] * Bf(2, 0) + a[2] * Bf(1, 0) +
446  b[1] * Bf(0, 2) + b[2] * Bf(0, 1)))
447  return true;
448 
449  // A0 x B1
450  s = T[2] * B(1, 1) - T[1] * B(2, 1);
451  t = ((s < 0.0) ? -s : s);
452 
453  if(t > (a[1] * Bf(2, 1) + a[2] * Bf(1, 1) +
454  b[0] * Bf(0, 2) + b[2] * Bf(0, 0)))
455  return true;
456 
457  // A0 x B2
458  s = T[2] * B(1, 2) - T[1] * B(2, 2);
459  t = ((s < 0.0) ? -s : s);
460 
461  if(t > (a[1] * Bf(2, 2) + a[2] * Bf(1, 2) +
462  b[0] * Bf(0, 1) + b[1] * Bf(0, 0)))
463  return true;
464 
465  // A1 x B0
466  s = T[0] * B(2, 0) - T[2] * B(0, 0);
467  t = ((s < 0.0) ? -s : s);
468 
469  if(t > (a[0] * Bf(2, 0) + a[2] * Bf(0, 0) +
470  b[1] * Bf(1, 2) + b[2] * Bf(1, 1)))
471  return true;
472 
473  // A1 x B1
474  s = T[0] * B(2, 1) - T[2] * B(0, 1);
475  t = ((s < 0.0) ? -s : s);
476 
477  if(t > (a[0] * Bf(2, 1) + a[2] * Bf(0, 1) +
478  b[0] * Bf(1, 2) + b[2] * Bf(1, 0)))
479  return true;
480 
481  // A1 x B2
482  s = T[0] * B(2, 2) - T[2] * B(0, 2);
483  t = ((s < 0.0) ? -s : s);
484 
485  if(t > (a[0] * Bf(2, 2) + a[2] * Bf(0, 2) +
486  b[0] * Bf(1, 1) + b[1] * Bf(1, 0)))
487  return true;
488 
489  // A2 x B0
490  s = T[1] * B(0, 0) - T[0] * B(1, 0);
491  t = ((s < 0.0) ? -s : s);
492 
493  if(t > (a[0] * Bf(1, 0) + a[1] * Bf(0, 0) +
494  b[1] * Bf(2, 2) + b[2] * Bf(2, 1)))
495  return true;
496 
497  // A2 x B1
498  s = T[1] * B(0, 1) - T[0] * B(1, 1);
499  t = ((s < 0.0) ? -s : s);
500 
501  if(t > (a[0] * Bf(1, 1) + a[1] * Bf(0, 1) +
502  b[0] * Bf(2, 2) + b[2] * Bf(2, 0)))
503  return true;
504 
505  // A2 x B2
506  s = T[1] * B(0, 2) - T[0] * B(1, 2);
507  t = ((s < 0.0) ? -s : s);
508 
509  if(t > (a[0] * Bf(1, 2) + a[1] * Bf(0, 2) +
510  b[0] * Bf(2, 1) + b[1] * Bf(2, 0)))
511  return true;
512 
513  return false;
514 
515 }
516 
517 //==============================================================================
518 template <typename S>
519 bool obbDisjoint(
520  const Transform3<S>& tf,
521  const Vector3<S>& a,
522  const Vector3<S>& b)
523 {
524  register S t, s;
525  const S reps = 1e-6;
526 
527  Matrix3<S> Bf = tf.linear().cwiseAbs();
528  Bf.array() += reps;
529 
530  // if any of these tests are one-sided, then the polyhedra are disjoint
531 
532  // A1 x A2 = A0
533  t = ((tf.translation()[0] < 0.0) ? -tf.translation()[0] : tf.translation()[0]);
534 
535  if(t > (a[0] + Bf.row(0).dot(b)))
536  return true;
537 
538  // B1 x B2 = B0
539  s = tf.linear().col(0).dot(tf.translation());
540  t = ((s < 0.0) ? -s : s);
541 
542  if(t > (b[0] + Bf.col(0).dot(a)))
543  return true;
544 
545  // A2 x A0 = A1
546  t = ((tf.translation()[1] < 0.0) ? -tf.translation()[1] : tf.translation()[1]);
547 
548  if(t > (a[1] + Bf.row(1).dot(b)))
549  return true;
550 
551  // A0 x A1 = A2
552  t =((tf.translation()[2] < 0.0) ? -tf.translation()[2] : tf.translation()[2]);
553 
554  if(t > (a[2] + Bf.row(2).dot(b)))
555  return true;
556 
557  // B2 x B0 = B1
558  s = tf.linear().col(1).dot(tf.translation());
559  t = ((s < 0.0) ? -s : s);
560 
561  if(t > (b[1] + Bf.col(1).dot(a)))
562  return true;
563 
564  // B0 x B1 = B2
565  s = tf.linear().col(2).dot(tf.translation());
566  t = ((s < 0.0) ? -s : s);
567 
568  if(t > (b[2] + Bf.col(2).dot(a)))
569  return true;
570 
571  // A0 x B0
572  s = tf.translation()[2] * tf.linear()(1, 0) - tf.translation()[1] * tf.linear()(2, 0);
573  t = ((s < 0.0) ? -s : s);
574 
575  if(t > (a[1] * Bf(2, 0) + a[2] * Bf(1, 0) +
576  b[1] * Bf(0, 2) + b[2] * Bf(0, 1)))
577  return true;
578 
579  // A0 x B1
580  s = tf.translation()[2] * tf.linear()(1, 1) - tf.translation()[1] * tf.linear()(2, 1);
581  t = ((s < 0.0) ? -s : s);
582 
583  if(t > (a[1] * Bf(2, 1) + a[2] * Bf(1, 1) +
584  b[0] * Bf(0, 2) + b[2] * Bf(0, 0)))
585  return true;
586 
587  // A0 x B2
588  s = tf.translation()[2] * tf.linear()(1, 2) - tf.translation()[1] * tf.linear()(2, 2);
589  t = ((s < 0.0) ? -s : s);
590 
591  if(t > (a[1] * Bf(2, 2) + a[2] * Bf(1, 2) +
592  b[0] * Bf(0, 1) + b[1] * Bf(0, 0)))
593  return true;
594 
595  // A1 x B0
596  s = tf.translation()[0] * tf.linear()(2, 0) - tf.translation()[2] * tf.linear()(0, 0);
597  t = ((s < 0.0) ? -s : s);
598 
599  if(t > (a[0] * Bf(2, 0) + a[2] * Bf(0, 0) +
600  b[1] * Bf(1, 2) + b[2] * Bf(1, 1)))
601  return true;
602 
603  // A1 x B1
604  s = tf.translation()[0] * tf.linear()(2, 1) - tf.translation()[2] * tf.linear()(0, 1);
605  t = ((s < 0.0) ? -s : s);
606 
607  if(t > (a[0] * Bf(2, 1) + a[2] * Bf(0, 1) +
608  b[0] * Bf(1, 2) + b[2] * Bf(1, 0)))
609  return true;
610 
611  // A1 x B2
612  s = tf.translation()[0] * tf.linear()(2, 2) - tf.translation()[2] * tf.linear()(0, 2);
613  t = ((s < 0.0) ? -s : s);
614 
615  if(t > (a[0] * Bf(2, 2) + a[2] * Bf(0, 2) +
616  b[0] * Bf(1, 1) + b[1] * Bf(1, 0)))
617  return true;
618 
619  // A2 x B0
620  s = tf.translation()[1] * tf.linear()(0, 0) - tf.translation()[0] * tf.linear()(1, 0);
621  t = ((s < 0.0) ? -s : s);
622 
623  if(t > (a[0] * Bf(1, 0) + a[1] * Bf(0, 0) +
624  b[1] * Bf(2, 2) + b[2] * Bf(2, 1)))
625  return true;
626 
627  // A2 x B1
628  s = tf.translation()[1] * tf.linear()(0, 1) - tf.translation()[0] * tf.linear()(1, 1);
629  t = ((s < 0.0) ? -s : s);
630 
631  if(t > (a[0] * Bf(1, 1) + a[1] * Bf(0, 1) +
632  b[0] * Bf(2, 2) + b[2] * Bf(2, 0)))
633  return true;
634 
635  // A2 x B2
636  s = tf.translation()[1] * tf.linear()(0, 2) - tf.translation()[0] * tf.linear()(1, 2);
637  t = ((s < 0.0) ? -s : s);
638 
639  if(t > (a[0] * Bf(1, 2) + a[1] * Bf(0, 2) +
640  b[0] * Bf(2, 1) + b[1] * Bf(2, 0)))
641  return true;
642 
643  return false;
644 }
645 
646 } // namespace fcl
647 
648 #endif
S volume() const
Volume of the OBB.
Definition: OBB-inl.h:195
OBB< S > & operator+=(const Vector3< S > &p)
A simple way to merge the OBB and a point (the result is not compact).
Definition: OBB-inl.h:138
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
S distance(const OBB &other, Vector3< S > *P=nullptr, Vector3< S > *Q=nullptr) const
Distance between two OBBs, not implemented.
Definition: OBB-inl.h:216
AABB< S > translate(const AABB< S > &aabb, const Eigen::MatrixBase< Derived > &t)
translate the center of AABB by t
Definition: AABB-inl.h:345
bool contain(const Vector3< S > &p) const
Check whether the OBB contains a point.
Definition: OBB-inl.h:118
S width() const
Width of the OBB.
Definition: OBB-inl.h:174
bool overlap(const OBB< S > &other) const
Check collision between two OBB, return true if collision happens.
Definition: OBB-inl.h:96
OBB< S > operator+(const OBB< S > &other) const
Return the merged OBB of current OBB and the other one (the result is not compact).
Definition: OBB-inl.h:157
Vector3< S > extent
Half dimensions of OBB.
Definition: OBB.h:68
Matrix3< S > axis
Orientation of OBB. The axes of the rotation matrix are the principle directions of the box...
Definition: OBB.h:62
S size() const
Size of the OBB (used in BV_Splitter to order two OBBs)
Definition: OBB-inl.h:202
const Vector3< S > center() const
Center of the OBB.
Definition: OBB-inl.h:209
S depth() const
Depth of the OBB.
Definition: OBB-inl.h:188
OBB()
Constructor.
Definition: OBB-inl.h:79
Vector3< S > To
Center of OBB.
Definition: OBB.h:65
S height() const
Height of the OBB.
Definition: OBB-inl.h:181
Oriented bounding box class.
Definition: OBB.h:51