Bubba-3D  0.9.0
Awesome game engine!
Octree.cpp
1 /*
2  * This file is part of Bubba-3D.
3  *
4  * Bubba-3D is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Bubba-3D is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with Bubba-3D. If not, see http://www.gnu.org/licenses/.
16  */
17 
18 #include "Triangle.h"
19 #include "Octree.h"
20 
21 #define DEFAULT_ORIGIN chag::make_vector(0.0f, 0.0f, 0.0f)
22 #define DEFAULT_HALFVECTOR chag::make_vector(1.0f, 1.0f, 1.0f)
23 
25  clearChildren();
26  origin = DEFAULT_ORIGIN;
27  halfVector = DEFAULT_HALFVECTOR;
28  setupAABB(DEFAULT_ORIGIN, DEFAULT_HALFVECTOR);
29 }
30 
31 Octree::~Octree() {
32 
33 }
34 
35 Octree::Octree(chag::float3 origin, chag::float3 halfVector)
36  : origin(origin), halfVector(halfVector)
37 {
38  depth = 0;
39  clearChildren();
40  setupAABB(origin, halfVector);
41 }
42 
43 Octree::Octree(chag::float3 origin, chag::float3 halfVector, int depth)
44  : origin(origin), halfVector(halfVector), depth(depth)
45 {
46  clearChildren();
47  setupAABB(origin, halfVector);
48 }
49 
51  for (int i = 0; i < 8; i++) {
52  children[i] = NULL;
53  }
54 }
55 
56 void Octree::setupAABB(chag::float3 origin, chag::float3 halfVector) {
57  chag::float3 p1 = origin + halfVector;
58  chag::float3 p2 = origin - halfVector;
59 
60  aabb.maxV = combineTwoPointsByComparator(p1,p2, [](float point1, float point2)
61  {
62  return point1 > point2;
63  });
64  aabb.minV = combineTwoPointsByComparator(p1,p2, [](float point1, float point2)
65  {
66  return point1 < point2;
67  });
68 }
69 
70 chag::float3 Octree::combineTwoPointsByComparator(
71  chag::float3 p1, chag::float3 p2,
72  std::function<bool (float ,float)> comparator)
73 {
74  chag::float3 maxPoint;
75 
76  maxPoint.x = comparator(p1.x, p2.x) ? p1.x : p2.x;
77  maxPoint.y = comparator(p1.y, p2.y) ? p1.y : p2.y;
78  maxPoint.z = comparator(p1.z, p2.z) ? p1.z : p2.z;
79 
80  return maxPoint;
81 }
82 
83 std::vector<Triangle*> *Octree::getTriangles() {
84  return &ts;
85 }
86 
87 
88 void Octree::insertAll(std::vector<Triangle *> &triangles) {
89  for (unsigned int i = 0; i < triangles.size(); i++) {
90  insertTriangle(triangles[i]);
91  }
92 }
93 
94 void Octree::insertTriangle(Triangle *t) {
95  BoundingBox *boundingBox = t->getBoundingBox(); //TODO USE Triangle/AABB TEST
96  std::set<int> octs;
97  for (int i = 0; i < 8; i++) {
98  octs.insert(getOctantContainingPoint(boundingBox->points[i]));
99  }
100 
101  if(octs.size() > 1 || depth == MAX_DEPTH) {
102  ts.push_back(t);
103  } else {
104  if(!hasChildren()) {
105  createChildren();
106  }
107 
108  for (std::set<int>::iterator it = octs.begin(); it != octs.end(); it++) {
109  children[*it]->insertTriangle(t);
110  }
111  }
112 }
113 
114 void Octree::createChildren() {
115  for (int i = 0; i < 8; ++i) {
116  chag::float3 newOrigin = origin;
117  newOrigin.x += halfVector.x * (i & 4 ? .5f : -.5f);
118  newOrigin.y += halfVector.y * (i & 2 ? .5f : -.5f);
119  newOrigin.z += halfVector.z * (i & 1 ? .5f : -.5f);
120  children[i] = new Octree(newOrigin, halfVector * .5f, depth + 1);
121  }
122 }
123 
125  return *children != NULL;
126 }
127 
128 void Octree::getChildren(std::vector<Octree*> *octs) {
129  if (hasChildren()) {
130  for (int i = 0; i < 8; i++) {
131  octs->push_back(children[i]);
132  }
133  }
134 }
135 
136 
137 int Octree::getOctantContainingPoint(const chag::float3 &point) {
138  int oct = 0;
139  if (point.x >= origin.x) oct |= 4;
140  if (point.y >= origin.y) oct |= 2;
141  if (point.z >= origin.z) oct |= 1;
142  return oct;
143 }
144 
145 int Octree::getTriangleCount() {
146  return ts.size();
147 }
148 
150  return &aabb;
151 }
152 
154  int c = getTriangleCount();
155 
156  if (hasChildren()) {
157  for (int i = 0; i < 8; i++) {
158  c += children[i]->getTriangleCountRecursively();
159  }
160  }
161 
162  return c;
163 }
164 
166  int count = 1;
167  if(hasChildren()) {
168  for (int i = 0; i < 8; i++) {
169  count += children[i]->getNumberOfSubTrees();
170  }
171  }
172 
173  return count;
174 }
175 
176 bool testSlab(float rayO, float rayD, float minV, float maxV, float *tNear, float *tFar) {
177 
178  if (rayD < 0.0001f) {
179  return rayO <= maxV && rayO >= minV;
180  }
181  else {
182 
183  float t1 = (minV - rayO) * rayD;
184  float t2 = (maxV - rayO) * rayD;
185 
186  if (t1 > t2) {
187  std::swap(t1, t2);
188  }
189 
190  if (t1 > *tNear) {
191  *tNear = t1;
192  }
193  if (t2 < *tFar) {
194  *tFar = t2;
195  }
196 
197  if (*tNear < *tFar) {
198  return false;
199  }
200 
201  if (*tFar < 0) {
202  return false;
203  }
204  }
205 
206  return true;
207 }
208 
209 
210 bool Octree::rayCastIntersectsAABB(chag::float3 rayOrigin, chag::float3 rayVector) {
211  chag::float3 maxCorner = chag::make_vector(origin.x + halfVector.x, origin.y + halfVector.y, origin.z + halfVector.z);
212  chag::float3 minCorner = chag::make_vector(origin.x - halfVector.x, origin.y - halfVector.y, origin.z - halfVector.z);
213 
214  float tNear = -FLT_MAX, tFar = FLT_MAX;
215 
216  return testSlab(rayOrigin.x, rayVector.x, minCorner.x, maxCorner.x, &tNear, &tFar)
217  || (testSlab(rayOrigin.y, rayVector.y, minCorner.y, maxCorner.y, &tNear, &tFar))
218  || (testSlab(rayOrigin.z, rayVector.z, minCorner.z, maxCorner.z, &tNear, &tFar));
219 }
220 
221 // TODO(Bubbad) Only add triangles if they are actually intersected
222 void Octree::getTrianglesInsersectedByRayCast(chag::float3 rayOrigin, chag::float3 rayVector, std::vector<Triangle *> *triangleList) {
223  if (!rayCastIntersectsAABB(rayOrigin, rayVector)) {
224  return;
225  }
226 
227  putTrianglesToList(triangleList);
228  if (hasChildren()) {
229  for (int i = 0; i < 8; i++) {
230  children[i]->getTrianglesInsersectedByRayCast(rayOrigin, rayVector, triangleList);
231  }
232  }
233 }
234 
235 void Octree::putTrianglesToList(std::vector<Triangle *> *triangleList) {
236  for (unsigned int i = 0; i < ts.size(); i++) {
237  triangleList->push_back(ts[i]);
238  }
239 }
int getTriangleCountRecursively()
Definition: Octree.cpp:153
std::vector< Triangle * > * getTriangles()
Definition: Octree.cpp:83
void getTrianglesInsersectedByRayCast(chag::float3 rayOrigin, chag::float3 rayVector, std::vector< Triangle * > *triangleList)
Definition: Octree.cpp:222
AABB * getAABB()
Definition: Octree.cpp:149
void clearChildren()
Definition: Octree.cpp:50
void getChildren(std::vector< Octree * > *octs)
Definition: Octree.cpp:128
bool hasChildren()
Definition: Octree.cpp:124
int getNumberOfSubTrees()
Definition: Octree.cpp:165
Definition: AABB2.h:23
Octree()
Definition: Octree.cpp:24