complete rewrite of validate_solid. also, put the trace points on the other side of the split plane. Just one more set of related tests to fix.

This commit is contained in:
Bill Currie 2009-03-20 11:20:59 +00:00 committed by Jeff Teunissen
parent 0ff4165149
commit fea4189150
2 changed files with 146 additions and 56 deletions

View file

@ -169,29 +169,46 @@ typedef struct {
} test_t;
test_t tests[] = {
{0, &hull1, {0, 47, 40}, {0, 47, 32}, {0.5, 0, 0, 1, 0}},
{0, &hull1, {0, 48, 40}, {0, 48, 32}, {1, 0, 0, 1, 0}},
{"drop on trench edge",
&hull1, {0, 47, 40}, {0, 47, 32}, {0.5, 0, 0, 1, 0}},
{"drop past trench edge",
&hull1, {0, 48, 40}, {0, 48, 32}, {1, 0, 0, 1, 0}},
{0, &hull1, {0, 52, 35}, {0, 44, 35}, {0.5, 0, 0, 1, 0}},
{0, &hull1, {0, 52, 36}, {0, 44, 36}, {1, 0, 0, 1, 0}},
{"run into trench edge",
&hull1, {0, 52, 35}, {0, 44, 35}, {0.5, 0, 0, 1, 0}},
{"run over trench edge",
&hull1, {0, 52, 36}, {0, 44, 36}, {1, 0, 0, 1, 0}},
{0, &hull1, {47, -32, 36}, {49, -32, 36}, {1, 0, 0, 1, 0}},
{0, &hull1, {48, -32, 36}, {50, -32, 36}, {1, 0, 1, 1, 0}},
{"run into end of 2nd shelf",
&hull1, {47, -32, 36}, {49, -32, 36}, {0.5, 0, 0, 1, 0}},
{"run inside end of 2nd shelf",
&hull1, {48, -32, 36}, {50, -32, 36}, {1, 1, 1, 0, 0}},
{0, &hull1, {44, -32, 59}, {52, -32, 59}, {0.5, 0, 0, 1, 0}},
{0, &hull1, {44, -32, 60}, {52, -32, 60}, {1, 0, 0, 1, 0}},
{"run into end of 2nd shelf p2",
&hull1, {44, -32, 59}, {52, -32, 59}, {0.5, 0, 0, 1, 0}},
{"run over end of 2nd shelf",
&hull1, {44, -32, 60}, {52, -32, 60}, {1, 0, 0, 1, 0}},
{0, &hull1, {47, -32, 76}, {47, -32, 44}, {1, 0, 1, 1, 0}},
{0, &hull1, {48, -32, 76}, {48, -32, 44}, {0.5, 0, 1, 1, 0}},
{"drop past end of 2nd shelf",
&hull1, {47, -32, 76}, {47, -32, 44}, {1, 0, 1, 1, 0}},
{"drop onto end of 2nd shelf",
&hull1, {48, -32, 76}, {48, -32, 44}, {0.5, 0, 1, 1, 0}},
{0, &hull2, {896, 2048, -144}, {896, 2048, -152}, {0.5, 0, 0, 1, 0}},
{"drop onto top of ramp: hull2",
&hull2, {896, 2048, -144}, {896, 2048, -152}, {0.5, 0, 0, 1, 0}},
{0, &hull1, {96, -47.9612, 61}, {96, -47.1025, 59}, {0.5, 0, 0, 1, 0}},
{"drop onto edge of 2nd shelf p1",
&hull1, {96, -47, 61}, {96, -47, 59}, {0.5, 0, 0, 1, 0}},
{0, &hull1, {94.8916, -34.8506, 61}, {94.8146, -28.5696, 59},
{1, 0, 0, 1, 0}},
{"drop onto edge of 2nd shelf p2",
&hull1, {96, -47.9612, 61}, {96, -47.1025, 59}, {0.5, 0, 0, 1, 0}},
{0, &hull3, {480, -216, 76}, {480, -200, 76}, {0.5, 0, 0, 1, 0}},
{"drop onto edge of 2nd shelf p3",
&hull1, {94.8916, -34.8506, 61}, {94.8146, -28.5696, 59},
{0.5, 0, 0, 1, 0}},
{"run over top of ramp: hull3",
&hull3, {480, -216, 76}, {480, -200, 76}, {1, 0, 0, 1, 0}},
};
const int num_tests = sizeof (tests) / sizeof (tests[0]);
@ -254,7 +271,7 @@ run_test (test_t *test)
desc = va ("(%d) %s", (int)(long)(test - tests), test->desc);
else
desc = va ("test #%d", (int)(long)(test - tests));
printf ("%s: %s\n", desc, res ? "PASS" : "FAIL");
printf ("%s: %s\n", res ? "PASS" : "FAIL", desc);
return res;
}
@ -282,8 +299,11 @@ main (int argc, char **argv)
}
if (test == -1) {
for (i = 0; i < num_tests; i++)
for (i = 0; i < num_tests; i++) {
if (verbose && i)
puts ("");
pass &= run_test (&tests[i]);
}
} else if (test >= 0 && test < num_tests) {
pass &= run_test (&tests[test]);
} else {

View file

@ -123,6 +123,11 @@ set_impact (tl_t *tl, mplane_t *plane, int side)
tl->impact.side = side;
}
#define print_tp(tp) \
Sys_Printf ("%s [(%g %g %g) %g %d]\n", #tp, \
(tp).plane->normal[0], (tp).plane->normal[1], \
(tp).plane->normal[2], (tp).plane->dist, (tp).side)
static inline vec_t
sgn (vec_t v)
{
@ -140,7 +145,7 @@ select_point (tl_t *tl, tp_t *impact, tp_t *split, vec3_t offs)
s = -s;
if (!s) {
s = sgn (split->plane->normal[axis]);
if (!split->side)
if (split->side)
s = -s;
}
offs[axis] = tl->extents[axis] * s;
@ -198,6 +203,7 @@ impact (tl_t *tl)
if (frac >= 0) {
tl->fraction = frac;
set_impact (tl, tl->split.plane, side);
// print_tp (tl->impact);
}
}
@ -205,15 +211,22 @@ static int
validate_impact (tp_t *split, tl_t *tl)
{
vec3_t dist, point, offs;
int pside;
int side;
VectorSubtract (tl->end, tl->start, dist);
VectorMultAdd (tl->start, tl->fraction, dist, point);
select_point (tl, &tl->impact, split, offs);
VectorAdd (point, offs, point);
pside = PlaneDiff (point, split->plane) < 0;
// Sys_Printf ("impact: (%g %g %g) %d %d\n", point[0], point[1], point[2], pside, split->side);
if (pside != split->side) {
side = PlaneDiff (point, split->plane) < 0;
#if 0
Sys_Printf ("\nimpact: (%g %g %g) (%g %g %g) %d %d\n",
point[0], point[1], point[2],
offs[0], offs[1], offs[2],
side, split->side);
print_tp (tl->impact);
print_tp (*split);
#endif
if (side != split->side) {
tl->fraction = 1;
set_impact (tl, 0, 0);
return 0;
@ -221,33 +234,91 @@ validate_impact (tp_t *split, tl_t *tl)
return 1;
}
static int
validate_solid (const vec3_t p1, const vec3_t p2, float t1, float t2,
tp_t *wall, tp_t *split, tl_t *tl)
{
float frac, offset;
int side;
vec3_t dist, point, offs;
#define set_point(a,s,b,c) \
do { \
(c)[0] = (a)[0] + (s)[0] * (b)[0]; \
(c)[1] = (a)[1] + (s)[1] * (b)[1]; \
(c)[2] = (a)[2] + (s)[2] * (b)[2]; \
} while (0)
// if (!tl->plane)
// return 1;
if (t1 == t2)
static int
validate_solid (const vec3_t p, tp_t *wall, tp_t *split, tl_t *tl)
{
static const vec3_t edges[][2] = {
{{ 1, -1, 1}, { 1, 1, 1}},
{{-1, -1, 1}, { 1, -1, 1}},
{{-1, -1, 1}, {-1, 1, 1}},
{{-1, 1, 1}, { 1, 1, 1}},
{{ 1, 1, -1}, { 1, 1, 1}},
{{ 1, -1, -1}, { 1, -1, 1}},
{{-1, -1, -1}, {-1, -1, 1}},
{{-1, 1, -1}, {-1, 1, 1}},
{{ 1, -1, -1}, { 1, 1, 1}},
{{-1, -1, -1}, { 1, -1, 1}},
{{-1, -1, -1}, {-1, 1, 1}},
{{-1, 1, -1}, { 1, 1, 1}},
};
static const int tests[] = {
0xa0a, 0x505, 0x0f0, 0x5f5, 0xafa, 0xf0f, 0xfff,
};
float t, t1, t2, frac;
int side;
vec3_t p1, p2, dist, point;
int type = wall->plane->type;
int i;
if (!split->plane)
return 1;
offset = calc_offset (tl, wall->plane);
if (t1 < t2)
frac = (t1 - offset) / (t1 - t2);
else
frac = (t1 + offset) / (t1 - t2);
VectorSubtract (p2, p1, dist);
VectorMultAdd (p1, frac, dist, point);
select_point (tl, wall, split, offs);
VectorAdd (point, offs, point);
side = PlaneDiff (point, split->plane) < 0;
// Sys_Printf ("solid: (%g %g %g) %d %d\n", point[0], point[1], point[2], side, split->side);
if (side != split->side) {
return 0;
if (type >= 3) {
// don't trust multi-axial types
if (!wall->plane->normal[0])
type = 3;
else if (!wall->plane->normal[1])
type = 4;
else if (!wall->plane->normal[1])
type = 5;
else
type = 6;
}
return 1;
for (i = 0; i < 12; i++) {
if (!(tests[type] & (1 << i)))
continue;
set_point (p, edges[i][0], tl->extents, p1);
set_point (p, edges[i][1], tl->extents, p2);
t1 = PlaneDiff (p1, wall->plane);
t2 = PlaneDiff (p2, wall->plane);
if (t1 == t2) // shouldn't happen because of the test bits, but...
continue; // the edge is parallel to the plane
frac = t1 / (t1 - t2);
if (frac < 0 || frac > 1)
continue; // the edge didn't hit the plane
VectorSubtract (p2, p1, dist);
VectorMultAdd (p1, frac, dist, point);
t = PlaneDiff (point, split->plane);
side = t < 0;
if (side == split->side)
return 1;
}
#if 0
Sys_Printf ("\nsolid: (%g %g %g) (%g %g %g) %d %d\n",
point[0], point[1], point[2],
offs[0], offs[1], offs[2],
side, split->side);
print_tp (*wall);
print_tp (*split);
#endif
return 0;
}
static int
@ -291,7 +362,7 @@ traceline (int num, float p1f, float p2f, const vec3_t p1, const vec3_t p2,
set_split (tl, plane, 0, &split);
c1 = c2 = traceline (node->children[0], p1f, p2f, p1, p2, tl);
if (c1 == CONTENTS_SOLID) {
if (!validate_solid (p1, p2, t1, t2, &tl->split, &split, tl))
if (!validate_solid (p1, &tl->split, &split, tl))
c1 = CONTENTS_EMPTY;
} else {
if (tl->impact.plane)
@ -300,9 +371,8 @@ traceline (int num, float p1f, float p2f, const vec3_t p1, const vec3_t p2,
if (c1 != CONTENTS_SOLID) {
set_split (tl, plane, 1, 0);
c2 = traceline (node->children[1], p1f, p2f, p1, p2, tl);
if (c2 == CONTENTS_SOLID && !validate_solid (p1, p2, t1, t2,
&tl->split, &split,
tl))
if (c2 == CONTENTS_SOLID && !validate_solid (p1, &tl->split,
&split, tl))
c2 = CONTENTS_EMPTY;
}
restore_split (tl, &split);
@ -311,8 +381,8 @@ traceline (int num, float p1f, float p2f, const vec3_t p1, const vec3_t p2,
tl->flags &= 3;
tl->flags |= 2;
}
if (tl->split.plane)
impact (tl);
// if (tl->split.plane)
// impact (tl);
return CONTENTS_SOLID;
}
if (c1 == CONTENTS_EMPTY && c2 == CONTENTS_EMPTY) {
@ -326,12 +396,12 @@ traceline (int num, float p1f, float p2f, const vec3_t p1, const vec3_t p2,
} else {
if (t1 < t2) {
side = 1;
frac = (t1 - offset) / (t1 - t2);
frac2 = (t1 + offset) / (t1 - t2);
} else /*if (t1 > t2)*/ {
side = 0;
frac = (t1 + offset) / (t1 - t2);
frac2 = (t1 - offset) / (t1 - t2);
} else /*if (t1 > t2)*/ {
side = 0;
frac = (t1 - offset) / (t1 - t2);
frac2 = (t1 + offset) / (t1 - t2);
}
frac = bound (0, frac, 1);