Fix retard rectangle-point collision check
This commit is contained in:
parent
de510b1f14
commit
5a22d09e47
@ -109,47 +109,63 @@ namespace egn{
|
||||
//If not in the rectangle, we can have 1 or 2 candidate edges to project onto. We want the closest one
|
||||
//to the input point.
|
||||
math::vec3<float> cand1, cand2;
|
||||
if(r1 > r2){
|
||||
cand1 = lineseg_point_proj(line_segment{l.point1, l.point4}, r);
|
||||
if(r4 > r5){
|
||||
//candidates be and bc
|
||||
cand2 = lineseg_point_proj(line_segment{l.point1, l.point2}, r);
|
||||
}else if(r6 < r5){
|
||||
//candidates be and de
|
||||
cand2 = lineseg_point_proj(line_segment{l.point3, l.point4}, r);
|
||||
|
||||
/*
|
||||
now we divide the plane into a voronoi diagram where each region is closest
|
||||
to either a line or a point on the rectangle. We use the r values calculated above
|
||||
to determine which region the point lies within.
|
||||
|
||||
a b c
|
||||
. .
|
||||
1 a1 . b1 . c1
|
||||
. .
|
||||
- - - - -*---------*- - - - -
|
||||
| |
|
||||
2 a2 | b2 | c2
|
||||
| |
|
||||
- - - - -*---------*- - - - -
|
||||
. .
|
||||
3 a3 . b3 . c3
|
||||
. .
|
||||
*/
|
||||
|
||||
if(r5 < r4){
|
||||
//in column a
|
||||
if(r2 < r1){
|
||||
//a3
|
||||
return l.point1;
|
||||
}else if(r2 > r3){
|
||||
//a1
|
||||
return l.point2;
|
||||
}else{
|
||||
//candidate be
|
||||
return cand1;
|
||||
//a2
|
||||
return lineseg_point_proj(line_segment{l.point1, l.point2}, r);
|
||||
}
|
||||
}else if(r3 < r2){
|
||||
cand1 = lineseg_point_proj(line_segment{l.point2, l.point3}, r);
|
||||
if(r4 > r5){
|
||||
//candidates cd and bc
|
||||
cand2 = lineseg_point_proj(line_segment{l.point1, l.point2}, r);
|
||||
}else if(r6 < r5){
|
||||
//candidates cd and de
|
||||
cand2 = lineseg_point_proj(line_segment{l.point3, l.point4}, r);
|
||||
}else if (r5 > r6){
|
||||
//in column c
|
||||
if(r2 < r1){
|
||||
//c3
|
||||
return l.point4;
|
||||
}else if(r2 > r3){
|
||||
//c1
|
||||
return l.point3;
|
||||
}else{
|
||||
//candidate cd
|
||||
return cand1;
|
||||
//c2
|
||||
return lineseg_point_proj(line_segment{l.point3, l.point4}, r);
|
||||
}
|
||||
}else if(r4 > r5){
|
||||
//candidate bc
|
||||
cand1 = lineseg_point_proj(line_segment{l.point1, l.point2}, r);
|
||||
return cand1;
|
||||
}else if(r6 < r5){
|
||||
//candidate de
|
||||
cand1 = lineseg_point_proj(line_segment{l.point3, l.point4}, r);
|
||||
return cand1;
|
||||
}else{
|
||||
//point is inside rectangle
|
||||
//in column b
|
||||
if(r2 < r1){
|
||||
//b3
|
||||
return lineseg_point_proj(line_segment{l.point1, l.point4}, r);
|
||||
}else if(r2 > r3){
|
||||
//b1
|
||||
return lineseg_point_proj(line_segment{l.point2, l.point3}, r);
|
||||
}else{
|
||||
//b2
|
||||
return r;
|
||||
}
|
||||
|
||||
//If we make it here, there are 2 candidate edges and we pick the closer one
|
||||
math::vec3<float> diff1 = r - cand1;
|
||||
math::vec3<float> diff2 = r - cand2;
|
||||
return (diff1 * diff1) > (diff2 * diff2) ? cand1 : cand2;
|
||||
}
|
||||
}
|
||||
/* bool check_collision(const collidable_iface& l, const collidable_iface& r, float epsilon){
|
||||
return l.check_collision(r, epsilon);
|
||||
@ -259,7 +275,8 @@ namespace egn{
|
||||
|
||||
//find the nearest point on the rectangle to the newly created coplanar point and see if it's within
|
||||
//epsilon of the original point
|
||||
return math::magnitude(r - rectangle_point_coplanar_proj(l, projected_point)) <= epsilon;
|
||||
math::vec3<float> proj_dist = r - rectangle_point_coplanar_proj(l, projected_point);
|
||||
return (proj_dist * proj_dist) <= (epsilon * epsilon); //avoid square root
|
||||
}
|
||||
bool check_collision(const point& l, const point& r, float epsilon){
|
||||
return math::fuzzy_eq(l, r, epsilon);
|
||||
|
||||
66
src/tests/collision/rectangle.cpp
Normal file
66
src/tests/collision/rectangle.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "engine/collision.hpp"
|
||||
|
||||
bool run_test(const egn::rectangle& l, const egn::point& r, bool desired_result){
|
||||
if(egn::check_collision(l, r) != desired_result){
|
||||
printf("FAIL\n");
|
||||
return false;
|
||||
}else{
|
||||
printf("Succ\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
struct testval{
|
||||
egn::point p;
|
||||
bool desres;
|
||||
};
|
||||
|
||||
int main(){
|
||||
egn::rectangle rect;
|
||||
rect.point1 = {-1, -2, 1};
|
||||
rect.point2 = {-1, 3, 1};
|
||||
rect.point3 = {2, 3, 1};
|
||||
rect.point4 = {2, -2, 1};
|
||||
|
||||
egn::point p;
|
||||
|
||||
testval tests[] = {
|
||||
{{0,0, 1}, true},
|
||||
{{1,1, 1}, true},
|
||||
{{-1,3, 1}, true},
|
||||
{{2,-2, 1}, true},
|
||||
{{0,0, 0}, false},
|
||||
{{0,0, -1}, false},
|
||||
{{-1.1,0, 1}, false},
|
||||
{{2.1,0, 1}, false},
|
||||
{{0,-2.1, 1}, false},
|
||||
{{0,3.1, 1}, false},
|
||||
{{-1.1,3.1, 1}, false},
|
||||
{{2.1,3.1, 1}, false},
|
||||
{{2.1,-2.1, 1}, false},
|
||||
};
|
||||
|
||||
for(const auto& [point,desres] : tests){
|
||||
if(bool rv;rv = !run_test(rect, point, desres))
|
||||
return rv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user