Overte C++ Documentation
AABox.h
1 //
2 // AABox.h
3 // libraries/octree/src
4 //
5 // Created by Brad Hefta-Gaub on 04/11/13.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
9 // Simple axis aligned box class.
10 //
11 // Distributed under the Apache License, Version 2.0.
12 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
13 //
14 
15 #ifndef hifi_AABox_h
16 #define hifi_AABox_h
17 
18 #include <glm/glm.hpp>
19 
20 #include <QDebug>
21 
22 #include "BoxBase.h"
23 #include "GeometryUtil.h"
24 #include "StreamUtils.h"
25 
26 class AACube;
27 class Extents;
28 class Transform;
29 
30 class AABox {
31 
32 public:
33  AABox(const AACube& other);
34  AABox(const Extents& other);
35  AABox(const glm::vec3& corner, float size);
36  AABox(const glm::vec3& corner, const glm::vec3& dimensions);
37  AABox();
38  ~AABox() {};
39 
40  void setBox(const glm::vec3& corner, const glm::vec3& scale);
41 
42  void setBox(const glm::vec3& corner, float scale);
43  glm::vec3 getFarthestVertex(const glm::vec3& normal) const; // return vertex most parallel to normal
44  glm::vec3 getNearestVertex(const glm::vec3& normal) const; // return vertex most anti-parallel to normal
45 
46  const glm::vec3& getCorner() const { return _corner; }
47  const glm::vec3& getScale() const { return _scale; }
48  const glm::vec3& getDimensions() const { return _scale; }
49  float getLargestDimension() const { return glm::max(_scale.x, glm::max(_scale.y, _scale.z)); }
50 
51  glm::vec3 calcCenter() const;
52  glm::vec3 calcTopFarLeft() const { return _corner + _scale; }
53 
54  const glm::vec3& getMinimum() const { return _corner; }
55  glm::vec3 getMaximum() const { return _corner + _scale; }
56 
57  glm::vec3 getVertex(BoxVertex vertex) const;
58 
59  const glm::vec3& getMinimumPoint() const { return _corner; }
60  glm::vec3 getMaximumPoint() const { return calcTopFarLeft(); }
61 
62  bool contains(const Triangle& triangle) const;
63  bool contains(const glm::vec3& point) const;
64  bool contains(const AABox& otherBox) const;
65  bool touches(const AABox& otherBox) const;
66 
67  bool contains(const AACube& otherCube) const;
68  bool touches(const AACube& otherCube) const;
69 
70  bool expandedContains(const glm::vec3& point, float expansion) const;
71  bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
72  bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& invDirection, float& distance,
73  BoxFace& face, glm::vec3& surfaceNormal) const;
74  bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
75  float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal) const;
76  bool rayHitsBoundingSphere(const glm::vec3& origin, const glm::vec3& direction) const;
77  bool parabolaPlaneIntersectsBoundingSphere(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, const glm::vec3& normal) const;
78  bool touchesSphere(const glm::vec3& center, float radius) const; // fast but may generate false positives
79  bool touchesAAEllipsoid(const glm::vec3& center, const glm::vec3& radials) const;
80  bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
81  bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
82 
83  bool isNull() const { return _scale == glm::vec3(0.0f, 0.0f, 0.0f); }
84 
85  AABox clamp(const glm::vec3& min, const glm::vec3& max) const;
86  AABox clamp(float min, float max) const;
87 
88  inline AABox& operator+=(const glm::vec3& point) {
89  bool valid = !isInvalid();
90  glm::vec3 maximum = glm::max(_corner + _scale, point);
91  _corner = glm::min(_corner, point);
92  if (valid) {
93  _scale = maximum - _corner;
94  }
95  return (*this);
96  }
97 
98  inline AABox& operator+=(const AABox& box) {
99  if (!box.isInvalid()) {
100  (*this) += box._corner;
101  (*this) += box.calcTopFarLeft();
102  }
103  return (*this);
104  }
105 
106  // Translate the AABox just moving the corner
107  void translate(const glm::vec3& translation) { _corner += translation; }
108 
109  // Rotate the AABox around its frame origin
110  // meaning rotating the corners of the AABox around the point {0,0,0} and reevaluating the min max
111  void rotate(const glm::quat& rotation);
112 
114  void scale(float scale);
115  void scale(const glm::vec3& scale);
116 
118  void embiggen(float scale);
119  void embiggen(const glm::vec3& scale);
120 
121  // Set a new scale for the Box, but keep it centered at its current location
122  void setScaleStayCentered(const glm::vec3& scale);
123 
124  // Transform the extents with transform
125  void transform(const Transform& transform);
126 
127  // Transform the extents with matrix
128  void transform(const glm::mat4& matrix);
129 
130  static const glm::vec3 INFINITY_VECTOR;
131 
132  bool isInvalid() const { return _corner.x == std::numeric_limits<float>::infinity(); }
133 
134  void clear() { _corner = INFINITY_VECTOR; _scale = glm::vec3(0.0f); }
135 
136  typedef enum {
137  topLeftNear,
138  topLeftFar,
139  topRightNear,
140  topRightFar,
141  bottomLeftNear,
142  bottomLeftFar,
143  bottomRightNear,
144  bottomRightFar
145  } OctreeChild;
146 
147  AABox getOctreeChild(OctreeChild child) const; // returns the AABox of the would be octree child of this AABox
148 
149  glm::vec4 getPlane(BoxFace face) const;
150 
151 private:
152  glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const;
153  glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const;
154 
155  static BoxFace getOppositeFace(BoxFace face);
156 
157  void checkPossibleParabolicIntersection(float t, int i, float& minDistance,
158  const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, bool& hit) const;
159 
160  glm::vec3 _corner;
161  glm::vec3 _scale;
162 };
163 
164 inline bool operator==(const AABox& a, const AABox& b) {
165  return a.getCorner() == b.getCorner() && a.getDimensions() == b.getDimensions();
166 }
167 
168 inline QDebug operator<<(QDebug debug, const AABox& box) {
169  debug << "AABox[ ("
170  << box.getCorner().x << "," << box.getCorner().y << "," << box.getCorner().z << " ) to ("
171  << box.calcTopFarLeft().x << "," << box.calcTopFarLeft().y << "," << box.calcTopFarLeft().z << ") size: ("
172  << box.getDimensions().x << "," << box.getDimensions().y << "," << box.getDimensions().z << ")"
173  << "]";
174 
175  return debug;
176 }
177 
178 #endif // hifi_AABox_h