#include #include "QF/va.h" #include "getopt.h" #include "world.h" #include "QF/winding.h" #include "hulls.h" #define FloatCompare(a, b) (fabs (a - b) < 1e-5) #undef VectorCompare #define VectorCompare(x, y) \ (FloatCompare (x[0], y[0]) && FloatCompare (x[1], y[1]) \ && FloatCompare (x[2], y[2])) typedef struct { const char *desc; hull_t *hull; struct { int num_portals; } expect; } test_t; test_t tests[] = { {"Three parallel planes 1", &hull_tpp1, { 3}}, {"Three parallel planes 2", &hull_tpp2, { 3}}, {"Three parallel planes with water", &hull_tppw, { 3}}, {"Step 1", &hull_step1, { 5}}, {"Covered Step", &hull_covered_step, { 9}}, {"Step 2", &hull_step2, { 5}}, {"Step 3", &hull_step3, { 5}}, {"Ramp", &hull_ramp, { 4}}, {"Simple Wedge", &hull_simple_wedge, { 3}}, {"Hole", &hull_hole, {13}}, {"ridge", &hull_ridge, { 8}}, {"cave", &hull_cave, {14}}, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) int verbose = 0; typedef struct portlist_s { struct portlist_s *next; clipport_t *portal; } portlist_t; static portlist_t * collect_portals (clipport_t *portal, portlist_t *portal_list) { portlist_t *p; if (!portal) return portal_list; for (p = portal_list; p; p = p->next) if (p->portal == portal) return portal_list; p = malloc (sizeof (portlist_t)); p->portal = portal; p->next = portal_list; portal_list = p; portal_list = collect_portals (portal->next[0], portal_list); portal_list = collect_portals (portal->next[1], portal_list); return portal_list; } static int run_test (test_t *test) { const char *desc; int err = 0; static int output = 0; portlist_t *portal_list = 0; if (!test->hull->nodeleafs) { hull_t *hull = test->hull; int i, j; portlist_t *p; clipport_t *portal; clipleaf_t *leaf; int side; hull->nodeleafs = MOD_BuildBrushes (hull); for (i = hull->firstclipnode; i <= hull->lastclipnode; i++) { for (j = 0; j < 2; j++) { if (((hull->clipnodes[i].children[j] >= 0) != (!hull->nodeleafs[i].leafs[j])) || (hull->nodeleafs[i].leafs[j] && (hull->nodeleafs[i].leafs[j]->contents != hull->clipnodes[i].children[j]))) { printf ("bad nodeleaf %d %d\n", i, j); err = 1; } } if (hull->nodeleafs[i].leafs[0] && (hull->nodeleafs[i].leafs[0] == hull->nodeleafs[i].leafs[1])) { printf ("bad nodeleaf %d %d\n", i, j); err = 1; } } if (err) goto nodeleaf_bail; for (i = hull->firstclipnode; i <= hull->lastclipnode; i++) { for (j = 0; j < 2; j++) { leaf = hull->nodeleafs[i].leafs[j]; if (!leaf) continue; portal_list = collect_portals (leaf->portals, portal_list); } } for (i = 0, p = portal_list; p; i++, p = p->next) { if (!p->portal->winding || !p->portal->edges) { err = 1; printf ("portal with missing vertex/edge information\n"); } } if (err) goto nodeleaf_bail; if (i != test->expect.num_portals) { err = 1; printf ("bad portal count: %d %d\n", test->expect.num_portals, i); goto nodeleaf_bail; } for (p = portal_list; p; p = p->next) { for (j = 0; j < 2; j++) { int found = 0; leaf = p->portal->leafs[j]; for (portal = leaf->portals; portal; portal = portal->next[side]) { //printf("%p %d %p %p %p\n", p, j, leaf, portal, p->portal); side = portal->leafs[1] == leaf; if (!side && portal->leafs[0] != leaf) { printf ("mislinked portal\n"); err = 1; } if (portal == p->portal) found = 1; } if (!found) { printf ("portal unreachable from leaf\n"); err = 1; } } } } nodeleaf_bail: while (portal_list) { portlist_t *t = portal_list; portal_list = portal_list->next; free (t); } MOD_FreeBrushes (test->hull); if (test->desc) desc = va ("(%d) %s", (int)(long)(test - tests), test->desc); else desc = va ("test #%d", (int)(long)(test - tests)); if (verbose >= 0 || err) { if (output) puts(""); output = 1; printf ("%s: %s\n", !err ? "PASS" : "FAIL", desc); } return !err; } #include "main.c"