Bubba-3D  0.9.0
Awesome game engine!
Collider.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 #include <GameObject.h>
18 #include <Collider.h>
19 #include <Triangle.h>
20 #include "Octree.h"
21 
22 #define EPSILON 0.00001f
23 
24 using namespace chag;
25 
26 bool rayTriangle(chag::float3 r_o, chag::float3 r_d,
27  chag::float3 v1, chag::float3 v2,
28  chag::float3 v3, float *ins) {
29  chag::float3 e2 = v3 - v1; // second edge
30  chag::float3 e1 = v2 - v1; // first edge
31 
32 
33  chag::float3 r = chag::cross(r_d, e2); // (d X e2) is used two times in the formula
34  // so we store it in an appropriate vector
35 
36  chag::float3 s = r_o - v1; // translated ray origin
37  float a = dot(e1, r); // a=(d X e2)*e1
38  float f = 1.0f / a; // slow division*
39 
40  chag::float3 q = chag::cross(s, e1);
41  float u = chag::dot(s, r);
42  float eps = 0.0001f;
43 
44  if (a > eps) { // Front facing triangle...
45  if ((u < 0) || (u > a)) return false;
46  float v = chag::dot(r_d, q);
47  if ((v < 0) || (u + v > a)) return false;
48  }
49  else if (a < -eps) { // Back facing triangle...
50  if ((u > 0) || (u < a)) return false;
51  float v = chag::dot(r_d, q);
52  if ((v > 0) || (u + v < a)) return false;
53  }
54  else return false; // Ray parallel to triangle plane
55  float t = f * chag::dot(e2, q);
56 
57  *ins = t;
58 
59  return true;
60 }
61 
62 
63 #define ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1) \
64  isect0=VV0+(VV1-VV0)*D0/(D0-D1); \
65  isect1=VV0+(VV2-VV0)*D0/(D0-D2);
66 
67 
68 #define EDGE_EDGE_TEST(V0,U0,U1) \
69  Bx=U0[i0]-U1[i0]; \
70  By=U0[i1]-U1[i1]; \
71  Cx=V0[i0]-U0[i0]; \
72  Cy=V0[i1]-U0[i1]; \
73  f=Ay*Bx-Ax*By; \
74  d=By*Cx-Bx*Cy; \
75  if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) \
76  { \
77  e=Ax*Cy-Ay*Cx; \
78  if(f>0) \
79  { \
80  if(e>=0 && e<=f) return 1; \
81  } \
82  else \
83  { \
84  if(e<=0 && e>=f) return 1; \
85  } \
86  }
87 
88 
89 #define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
90 { \
91  float Ax,Ay,Bx,By,Cx,Cy,e,d,f; \
92  Ax=V1[i0]-V0[i0]; \
93  Ay=V1[i1]-V0[i1]; \
94  /* test edge U0,U1 against V0,V1 */ \
95  EDGE_EDGE_TEST(V0,U0,U1); \
96  /* test edge U1,U2 against V0,V1 */ \
97  EDGE_EDGE_TEST(V0,U1,U2); \
98  /* test edge U2,U1 against V0,V1 */ \
99  EDGE_EDGE_TEST(V0,U2,U0); \
100 }
101 
102 #define POINT_IN_TRI(V0,U0,U1,U2) \
103 { \
104  float a,b,c,d0,d1,d2; \
105  /* is T1 completly inside T2? */ \
106  /* check if V0 is inside tri(U0,U1,U2) */ \
107  a=U1[i1]-U0[i1]; \
108  b=-(U1[i0]-U0[i0]); \
109  c=-a*U0[i0]-b*U0[i1]; \
110  d0=a*V0[i0]+b*V0[i1]+c; \
111  \
112  a=U2[i1]-U1[i1]; \
113  b=-(U2[i0]-U1[i0]); \
114  c=-a*U1[i0]-b*U1[i1]; \
115  d1=a*V0[i0]+b*V0[i1]+c; \
116  \
117  a=U0[i1]-U2[i1]; \
118  b=-(U0[i0]-U2[i0]); \
119  c=-a*U2[i0]-b*U2[i1]; \
120  d2=a*V0[i0]+b*V0[i1]+c; \
121  if(d0*d1>0.0) \
122  { \
123  if(d0*d2>0.0) return 1; \
124  } \
125 }
126 
127 bool coplanar_tri_tri(float3 N,float3 V0,float3 V1,float3 V2,
128  float3 U0,float3 U1,float3 U2)
129 {
130  float A[3];
131  short i0,i1;
132  /* first project onto an axis-aligned plane, that maximizes the area */
133  /* of the triangles, compute indices: i0,i1. */
134  A[0]=fabs(N[0]);
135  A[1]=fabs(N[1]);
136  A[2]=fabs(N[2]);
137  if(A[0]>A[1])
138  {
139  if(A[0]>A[2])
140  {
141  i0=1; /* A[0] is greatest */
142  i1=2;
143  }
144  else
145  {
146  i0=0; /* A[2] is greatest */
147  i1=1;
148  }
149  }
150  else /* A[0]<=A[1] */
151  {
152  if(A[2]>A[1])
153  {
154  i0=0; /* A[2] is greatest */
155  i1=1;
156  }
157  else
158  {
159  i0=0; /* A[1] is greatest */
160  i1=2;
161  }
162  }
163 
164  /* test all edges of triangle 1 against the edges of triangle 2 */
165  EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2);
166  EDGE_AGAINST_TRI_EDGES(V1,V2,U0,U1,U2);
167  EDGE_AGAINST_TRI_EDGES(V2,V0,U0,U1,U2);
168 
169  /* finally, test if tri1 is totally contained in tri2 or vice versa */
170  POINT_IN_TRI(V0,U0,U1,U2);
171  POINT_IN_TRI(U0,V0,V1,V2);
172 
173  return false;
174 }
175 
176 #define COMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1) \
177  if(D0D1>0.0f) \
178  { \
179  /* here we know that D0D2<=0.0 */ \
180  /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
181  ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1); \
182  } \
183  else if(D0D2>0.0f) \
184  { \
185  /* here we know that d0d1<=0.0 */ \
186  ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1); \
187  } \
188  else if(D1*D2>0.0f || D0!=0.0f) \
189  { \
190  /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
191  ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1); \
192  } \
193  else if(D1!=0.0f) \
194  { \
195  ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1); \
196  } \
197  else if(D2!=0.0f) \
198  { \
199  ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1); \
200  } \
201  else \
202  { \
203  /* triangles are coplanar */ \
204  return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
205  }
206 
207 
208 /* sort so that a<=b */
209 #define SORT(a,b) \
210  if(a>b) \
211  { \
212  float c; \
213  c=a; \
214  a=b; \
215  b=c; \
216  }
217 
218 
219 bool triangleTriangleIntersection(Triangle *t1, Triangle *t2)
220 {
221  float3 V0 = t1->p1;
222  float3 V1 = t1->p2;
223  float3 V2 = t1->p3;
224  float3 U0 = t2->p1;
225  float3 U1 = t2->p2;
226  float3 U2 = t2->p3;
227 
228  float3 E1,E2;
229  float3 N1,N2;
230  float d1,d2;
231  float du0,du1,du2,dv0,dv1,dv2;
232  float3 D;
233  float isect1[2], isect2[2];
234  float du0du1,du0du2,dv0dv1,dv0dv2;
235  short index;
236  float vp0,vp1,vp2;
237  float up0,up1,up2;
238  float b,c,max;
239 
240  /* compute plane equation of triangle(V0,V1,V2) */
241  E1 = V1-V0;
242  E2 = V2-V0;
243  N1 = cross(E1,E2);
244  d1 = -dot(N1,V0);
245  /* plane equation 1: N1.X+d1=0 */
246 
247  /* put U0,U1,U2 into plane equation 1 to compute signed distances to the plane*/
248  du0=dot(N1,U0)+d1;
249  du1=dot(N1,U1)+d1;
250  du2=dot(N1,U2)+d1;
251 
252  /* coplanarity robustness check */
253  if(fabs(du0)<EPSILON) du0=0.0;
254  if(fabs(du1)<EPSILON) du1=0.0;
255  if(fabs(du2)<EPSILON) du2=0.0;
256  du0du1=du0*du1;
257  du0du2=du0*du2;
258 
259  if(du0du1>0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */
260  return false; /* no intersection occurs */
261 
262  /* compute plane of triangle (U0,U1,U2) */
263  E1 = U1 - U0;
264  E2 = U2 - U0;
265  N2 = cross(E1, E2);
266  d2 = -dot(N2,U0);
267  /* plane equation 2: N2.X+d2=0 */
268 
269  /* put V0,V1,V2 into plane equation 2 */
270  dv0=dot(N2,V0)+d2;
271  dv1=dot(N2,V1)+d2;
272  dv2=dot(N2,V2)+d2;
273 
274  if(fabs(dv0)<EPSILON) dv0=0.0;
275  if(fabs(dv1)<EPSILON) dv1=0.0;
276  if(fabs(dv2)<EPSILON) dv2=0.0;
277 
278  dv0dv1=dv0*dv1;
279  dv0dv2=dv0*dv2;
280 
281  if(dv0dv1>0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */
282  return false; /* no intersection occurs */
283 
284  /* compute direction of intersection line */
285  D = cross(N1,N2);
286 
287  /* compute and index to the largest component of D */
288  max=fabs(D[0]);
289  index=0;
290  b=fabs(D[1]);
291  c=fabs(D[2]);
292  if(b>max) max=b,index=1;
293  if(c>max) max=c,index=2;
294 
295  /* this is the simplified projection onto L*/
296  vp0=V0[index];
297  vp1=V1[index];
298  vp2=V2[index];
299 
300  up0=U0[index];
301  up1=U1[index];
302  up2=U2[index];
303 
304  /* compute interval for triangle 1 */
305  COMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,isect1[0],isect1[1]);
306 
307  /* compute interval for triangle 2 */
308  COMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,isect2[0],isect2[1]);
309 
310  SORT(isect1[0],isect1[1]);
311  SORT(isect2[0],isect2[1]);
312 
313  if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) {return false;}
314  return true;
315 }
316 
317 bool AabbAabbintersection(AABB *aabb1, AABB *aabb2) {
318  if (aabb1->maxV.x < aabb2->minV.x) { return false; }
319  if (aabb1->maxV.y < aabb2->minV.y) { return false; }
320  if (aabb1->maxV.z < aabb2->minV.z) { return false; }
321 
322  if (aabb2->maxV.x < aabb1->minV.x) { return false; }
323  if (aabb2->maxV.y < aabb1->minV.y) { return false; }
324  if (aabb2->maxV.z < aabb1->minV.z) { return false; }
325 
326  return true;
327 }
328 
329 bool sphereIntersection(Sphere sphere1,Sphere sphere2){
330  return length(sphere1.getPosition()-sphere2.getPosition()) < sphere1.getRadius()+sphere2.getRadius();
331 }
332 
333 //Real-time Rendering, Third edition pp. 741
334 bool raySphereIntersection(Sphere sphere, float3 rayOrigin, float3 rayDirection){
335  float3 l = sphere.getPosition() - rayOrigin; //vector from ray origin to sphere pos
336  float projOflOnRayDir = dot(l,rayDirection);
337  float l2 = dot(l,l);
338  float r2 = sphere.getRadius()*sphere.getRadius();
339  if(projOflOnRayDir < 0 && l2 > r2) return false;
340  float m2 = l2 - projOflOnRayDir*projOflOnRayDir;
341  if(m2 > r2) return false;
342  return true;
343  /* The following code would calculate the collision position:
344  float q = sqrt(r2-m2);
345  float t = projOflOnRayDir + (l2 > r2 ? -q : q);
346  return rayOrigin + t*rayDirection;*/
347 }
348 
349 Triangle multiplyTriangleWithModelMatrix(Triangle *triangle, float4x4 *modelMatrix) {
350  float4 p1 = make_vector(triangle->p1.x, triangle->p1.y, triangle->p1.z, 1.0f);
351  float4 p2 = make_vector(triangle->p2.x, triangle->p2.y, triangle->p2.z, 1.0f);
352  float4 p3 = make_vector(triangle->p3.x, triangle->p3.y, triangle->p3.z, 1.0f);
353 
354  float4 convertedP1 = *modelMatrix * p1;
355  float4 convertedP2 = *modelMatrix * p2;
356  float4 convertedP3 = *modelMatrix * p3;
357 
358  float3 p1f3 = make_vector(convertedP1.x, convertedP1.y, convertedP1.z);
359  float3 p2f3 = make_vector(convertedP2.x, convertedP2.y, convertedP2.z);
360  float3 p3f3 = make_vector(convertedP3.x, convertedP3.y, convertedP3.z);
361 
362  return Triangle(p1f3, p2f3, p3f3);
363 }
364 
365 void calculateAndUpdateMinMax(float3 point, float4x4* modelMatrix, float3 *minV, float3 *maxV) {
366  float4 convertedValue = *modelMatrix * make_vector(point.x, point.y, point.z, 1.0f);
367 
368  if( maxV->x < convertedValue.x) { maxV->x = convertedValue.x;}
369  if( maxV->y < convertedValue.y) { maxV->y = convertedValue.y;}
370  if( maxV->z < convertedValue.z) { maxV->z = convertedValue.z;}
371 
372  if( minV->x > convertedValue.x) { minV->x = convertedValue.x;}
373  if( minV->y > convertedValue.y) { minV->y = convertedValue.y;}
374  if( minV->z > convertedValue.z) { minV->z = convertedValue.z;}
375 }
376 
377 
378 AABB multiplyAABBWithModelMatrix(AABB *aabb, float4x4 modelMat) {
379  float4x4* modelMatrix = &modelMat;
380  AABB convertedAabb = AABB();
381 
382  calculateAndUpdateMinMax(make_vector(aabb->maxV.x,aabb->maxV.y,aabb->maxV.z), modelMatrix, &convertedAabb.minV, &convertedAabb.maxV);
383  calculateAndUpdateMinMax(make_vector(aabb->maxV.x,aabb->maxV.y,aabb->minV.z), modelMatrix, &convertedAabb.minV, &convertedAabb.maxV);
384  calculateAndUpdateMinMax(make_vector(aabb->maxV.x,aabb->minV.y,aabb->maxV.z), modelMatrix, &convertedAabb.minV, &convertedAabb.maxV);
385  calculateAndUpdateMinMax(make_vector(aabb->maxV.x,aabb->minV.y,aabb->minV.z), modelMatrix, &convertedAabb.minV, &convertedAabb.maxV);
386 
387  calculateAndUpdateMinMax(make_vector(aabb->minV.x,aabb->maxV.y,aabb->maxV.z), modelMatrix, &convertedAabb.minV, &convertedAabb.maxV);
388  calculateAndUpdateMinMax(make_vector(aabb->minV.x,aabb->maxV.y,aabb->minV.z), modelMatrix, &convertedAabb.minV, &convertedAabb.maxV);
389  calculateAndUpdateMinMax(make_vector(aabb->minV.x,aabb->minV.y,aabb->maxV.z), modelMatrix, &convertedAabb.minV, &convertedAabb.maxV);
390  calculateAndUpdateMinMax(make_vector(aabb->minV.x,aabb->minV.y,aabb->minV.z), modelMatrix, &convertedAabb.minV, &convertedAabb.maxV);
391 
392  return convertedAabb;
393 }
394 
395 bool octreeOctreeIntersection(Octree *object1Octree, float4x4 *object1ModelMatrix, Octree *object2Octree,
396  float4x4 *object2ModelMatrix) {
397  AABB object1Aabb = multiplyAABBWithModelMatrix(object1Octree->getAABB(), *object1ModelMatrix);
398  AABB object2Aabb = multiplyAABBWithModelMatrix(object2Octree->getAABB(), *object2ModelMatrix);
399 
400  if (!AabbAabbintersection(&object1Aabb, &object2Aabb)) {
401  return false;
402  }
403 
404  if (!object1Octree->hasChildren() && !object2Octree->hasChildren()) {
405  return isTrianglesIntersecting(object1Octree, object1ModelMatrix, object2Octree, object2ModelMatrix);
406  } else if (object1Octree->hasChildren() && object2Octree->hasChildren()) {
407  if(isTrianglesIntersecting(object1Octree, object1ModelMatrix, object2Octree, object2ModelMatrix)) {
408  return true;
409  }
410 
411  std::vector<Octree *> object1Children;
412 
413  object1Octree->getChildren(&object1Children);
414  for (auto it = object1Children.begin(); it != object1Children.end(); it++) {
415  if (octreeOctreeIntersection(*it, object1ModelMatrix, object2Octree, object2ModelMatrix)) {
416  return true;
417  }
418  }
419 
420  std::vector<Octree *> object2Children;
421 
422  object2Octree->getChildren(&object2Children);
423  for (auto it = object2Children.begin(); it != object2Children.end(); it++) {
424  if (octreeOctreeIntersection(object1Octree, object1ModelMatrix, *it, object2ModelMatrix)) {
425  return true;
426  }
427  }
428  } else if (!object1Octree->hasChildren() && object2Octree->hasChildren()) {
429  if(isTrianglesIntersecting(object1Octree, object1ModelMatrix, object2Octree, object2ModelMatrix)) {
430  return true;
431  }
432 
433  std::vector<Octree *> object2Children;
434  object2Octree->getChildren(&object2Children);
435 
436  for (auto it = object2Children.begin(); it != object2Children.end(); it++) {
437  if(octreeOctreeIntersection(object1Octree, object1ModelMatrix, *it, object2ModelMatrix)) {
438  return true;
439  }
440 
441  }
442 
443  } else {
444  if(isTrianglesIntersecting(object1Octree, object1ModelMatrix, object2Octree, object2ModelMatrix)) {
445  return true;
446  }
447 
448  std::vector<Octree *> object1Children;
449  object1Octree->getChildren(&object1Children);
450 
451  for (auto it = object1Children.begin(); it != object1Children.end(); it++) {
452  if(octreeOctreeIntersection(*it, object1ModelMatrix, object2Octree, object2ModelMatrix)) {
453  return true;
454  }
455  }
456 
457  }
458 
459  return false;
460 }
461 
462 bool isTrianglesIntersecting(Octree *object1Octree, float4x4 *object1ModelMatrix, Octree *object2Octree,
463  float4x4 *object2ModelMatrix) {
464  std::vector<Triangle *> *triangles1 = object1Octree->getTriangles();
465  std::vector<Triangle *> *triangles2 = object2Octree->getTriangles();
466 
467  if(triangles1->size() == 0 || triangles2->size() == 0) {
468  return false;
469  }
470 
471  for (auto t1 = triangles1->begin(); t1 != triangles1->end(); t1++) {
472  Triangle triangle1 = multiplyTriangleWithModelMatrix(*t1, object1ModelMatrix);
473  for (auto t2 = triangles2->begin(); t2 != triangles2->end(); t2++) {
474  Triangle triangle2 = multiplyTriangleWithModelMatrix(*t2, object2ModelMatrix);
475 
476  if (triangleTriangleIntersection(&triangle1, &triangle2)) {
477  return true;
478  }
479 
480  }
481  }
482 
483  return false;
484 }
485 
486 
487 
488 
489 
490 
491 
492 
493 
std::vector< Triangle * > * getTriangles()
Definition: Octree.cpp:83
AABB * getAABB()
Definition: Octree.cpp:149
Definition: Octree.h:32
void getChildren(std::vector< Octree * > *octs)
Definition: Octree.cpp:128
bool hasChildren()
Definition: Octree.cpp:124
Definition: Sphere.h:19
Definition: AABB2.h:23