2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU 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.
9 // This program 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 General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "supertux/collision.hpp"
21 #include "math/aatriangle.hpp"
25 bool intersects(const Rect& r1, const Rect& r2)
27 if(r1.p2.x < r2.p1.x || r1.p1.x > r2.p2.x)
29 if(r1.p2.y < r2.p1.y || r1.p1.y > r2.p2.y)
35 //---------------------------------------------------------------------------
38 inline void makePlane(const Vector& p1, const Vector& p2, Vector& n, float& c)
40 n = Vector(p2.y-p1.y, p1.x-p2.x);
42 float nval = n.norm();
49 bool rectangle_aatriangle(Constraints* constraints, const Rect& rect,
50 const AATriangle& triangle, const Vector& addl_ground_movement)
52 if(!intersects(rect, (const Rect&) triangle))
59 switch(triangle.dir & AATriangle::DEFORM_MASK) {
61 area.p1 = triangle.p1;
62 area.p2 = triangle.p2;
64 case AATriangle::DEFORM1:
65 area.p1 = Vector(triangle.p1.x, triangle.p1.y + triangle.get_height()/2);
66 area.p2 = triangle.p2;
68 case AATriangle::DEFORM2:
69 area.p1 = triangle.p1;
70 area.p2 = Vector(triangle.p2.x, triangle.p1.y + triangle.get_height()/2);
72 case AATriangle::DEFORM3:
73 area.p1 = triangle.p1;
74 area.p2 = Vector(triangle.p1.x + triangle.get_width()/2, triangle.p2.y);
76 case AATriangle::DEFORM4:
77 area.p1 = Vector(triangle.p1.x + triangle.get_width()/2, triangle.p1.y);
78 area.p2 = triangle.p2;
84 switch(triangle.dir & AATriangle::DIRECTION_MASK) {
85 case AATriangle::SOUTHWEST:
86 p1 = Vector(rect.p1.x, rect.p2.y);
87 makePlane(area.p1, area.p2, normal, c);
89 case AATriangle::NORTHEAST:
90 p1 = Vector(rect.p2.x, rect.p1.y);
91 makePlane(area.p2, area.p1, normal, c);
93 case AATriangle::SOUTHEAST:
95 makePlane(Vector(area.p1.x, area.p2.y),
96 Vector(area.p2.x, area.p1.y), normal, c);
98 case AATriangle::NORTHWEST:
100 makePlane(Vector(area.p2.x, area.p1.y),
101 Vector(area.p1.x, area.p2.y), normal, c);
107 float n_p1 = -(normal * p1);
108 float depth = n_p1 - c;
113 std::cout << "R: " << rect << " Tri: " << triangle << "\n";
114 std::cout << "Norm: " << normal << " Depth: " << depth << "\n";
117 Vector outvec = normal * (depth + 0.2f);
119 const float RDELTA = 3;
120 if(p1.x < area.p1.x - RDELTA || p1.x > area.p2.x + RDELTA
121 || p1.y < area.p1.y - RDELTA || p1.y > area.p2.y + RDELTA) {
122 set_rectangle_rectangle_constraints(constraints, rect, area);
123 constraints->hit.left = false;
124 constraints->hit.right = false;
127 constraints->right = rect.get_right() + outvec.x;
129 constraints->left = rect.get_left() + outvec.x;
133 constraints->bottom = rect.get_bottom() + outvec.y;
134 constraints->hit.bottom = true;
135 constraints->ground_movement += addl_ground_movement;
137 constraints->top = rect.get_top() + outvec.y;
138 constraints->hit.top = true;
140 constraints->hit.slope_normal = normal;
146 void set_rectangle_rectangle_constraints(Constraints* constraints,
147 const Rect& r1, const Rect& r2, const Vector& addl_ground_movement)
149 float itop = r1.get_bottom() - r2.get_top();
150 float ibottom = r2.get_bottom() - r1.get_top();
151 float ileft = r1.get_right() - r2.get_left();
152 float iright = r2.get_right() - r1.get_left();
154 float vert_penetration = std::min(itop, ibottom);
155 float horiz_penetration = std::min(ileft, iright);
156 if(vert_penetration < horiz_penetration) {
158 constraints->bottom = std::min(constraints->bottom, r2.get_top());
159 constraints->hit.bottom = true;
160 constraints->ground_movement += addl_ground_movement;
162 constraints->top = std::max(constraints->top, r2.get_bottom());
163 constraints->hit.top = true;
167 constraints->right = std::min(constraints->right, r2.get_left());
168 constraints->hit.right = true;
170 constraints->left = std::max(constraints->left, r2.get_right());
171 constraints->hit.left = true;