The BIG COMMIT(tm)
[supertux.git] / lib / special / collision.cpp
1 #include <config.h>
2
3 #include "collision.h"
4
5 #include <algorithm>
6 #include <iostream>
7 #include <stdio.h>
8 #include <float.h>
9 #include <math.h>
10 #include "math/vector.h"
11 #include "math/aatriangle.h"
12 #include "math/rectangle.h"
13 #include "collision_hit.h"
14
15 namespace SuperTux
16 {
17
18 bool
19 Collision::rectangle_rectangle(CollisionHit& hit, const Rectangle& r1,
20     const Rectangle& r2)
21 {
22   if(r1.p2.x < r2.p1.x || r1.p1.x > r2.p2.x)
23     return false;
24   if(r1.p2.y < r2.p1.y || r1.p1.y > r2.p2.y)
25     return false;
26   
27   hit.depth = r1.p2.x - r2.p1.x;
28   hit.normal.x = -1;
29   hit.normal.y = 0;
30
31   float px2 = r2.p2.x - r1.p1.x;
32   if(px2 < hit.depth) {
33     hit.depth = px2;
34     hit.normal.x = 1;
35     hit.normal.y = 0;
36   }
37
38   float py1 = r1.p2.y - r2.p1.y;
39   if(py1 < hit.depth) {
40     hit.depth = py1;
41     hit.normal.x = 0;
42     hit.normal.y = -1;
43   }
44
45   float py2 = r2.p2.y - r1.p1.y;
46   if(py2 < hit.depth) {
47     hit.depth = py2;
48     hit.normal.x = 0;
49     hit.normal.y = 1;
50   }
51
52   return true;
53 }
54
55 //---------------------------------------------------------------------------
56
57 static void makePlane(const Vector& p1, const Vector& p2, Vector& n, float& c)
58 {
59   n = Vector(p2.y-p1.y, p1.x-p2.x);
60   c = -(p2 * n);
61   float nval = n.norm();             
62   n /= nval;
63   c /= nval;
64 }
65
66 bool
67 Collision::rectangle_aatriangle(CollisionHit& hit, const Rectangle& rect,
68     const AATriangle& triangle)
69 {
70   if(!rectangle_rectangle(hit, rect, (const Rectangle&) triangle))
71     return false;
72   
73   Vector normal;
74   float c;
75   Vector p1;
76   switch(triangle.dir) {
77     case AATriangle::SOUTHWEST:
78       p1 = Vector(rect.p1.x, rect.p2.y);
79       makePlane(triangle.p1, triangle.p2, normal, c);
80       break;
81     case AATriangle::NORTHEAST:
82       p1 = Vector(rect.p2.x, rect.p1.y);
83       makePlane(triangle.p2, triangle.p1, normal, c);
84       break;
85     case AATriangle::SOUTHEAST:
86       p1 = rect.p2;
87       makePlane(Vector(triangle.p1.x, triangle.p2.y),
88           Vector(triangle.p2.x, triangle.p1.y), normal, c);
89       break;
90     case AATriangle::NORTHWEST:
91       p1 = rect.p1;
92       makePlane(Vector(triangle.p2.x, triangle.p1.y),
93           Vector(triangle.p1.x, triangle.p2.y), normal, c);
94       break;
95   }
96
97   float depth = -(normal * p1) - c;
98   if(depth < 0)
99     return false;
100   if(depth < hit.depth) {
101     hit.depth = depth;
102     hit.normal = normal;
103   }
104
105   return true;
106 }
107
108 }