00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "tracing.h"
00030 #include "common.h"
00031 #include "mem.h"
00032
00035 static int checkcount;
00036
00037
00038
00039
00040
00041
00042
00046 static void TR_MakeTracingNode (TR_TILE_TYPE *tile, tnode_t ** tnode, int32_t nodenum)
00047 {
00048 tnode_t *t;
00049 TR_PLANE_TYPE *plane;
00050 int i;
00051 TR_NODE_TYPE *node;
00052
00053 t = (*tnode)++;
00054
00055 node = tile->nodes + nodenum;
00056 #ifdef COMPILE_UFO
00057 plane = node->plane;
00058 #else
00059 plane = tile->planes + node->planenum;
00060 #endif
00061
00062 t->type = plane->type;
00063 VectorCopy(plane->normal, t->normal);
00064 t->dist = plane->dist;
00065
00066 for (i = 0; i < 2; i++) {
00067 if (node->children[i] < 0) {
00068 const int32_t leafnum = -(node->children[i]) - 1;
00069 const TR_LEAF_TYPE *leaf = &tile->leafs[leafnum];
00070 const uint32_t contentFlags = leaf->contentFlags & ~(1 << 31);
00071 if ((contentFlags & (CONTENTS_SOLID | MASK_CLIP)) && !(contentFlags & CONTENTS_PASSABLE))
00072 t->children[i] = -node->children[i] | (1 << 31);
00073 else
00074 t->children[i] = (1 << 31);
00075 } else {
00076 t->children[i] = *tnode - tile->tnodes;
00077 if (t->children[i] > tile->numnodes) {
00078 Com_Printf("Exceeded allocated memory for tracing structure (%i > %i)\n",
00079 t->children[i], tile->numnodes);
00080 }
00081 TR_MakeTracingNode(tile, tnode, node->children[i]);
00082 }
00083 }
00084 }
00085
00090 void TR_BuildTracingNode_r (TR_TILE_TYPE *tile, tnode_t ** tnode, int32_t nodenum, int level)
00091 {
00092 assert(nodenum < tile->numnodes + 6);
00093
00098 #ifdef COMPILE_UFO
00099 if (!tile->nodes[nodenum].plane) {
00100 #else
00101 if (tile->nodes[nodenum].planenum == PLANENUM_LEAF) {
00102 #endif
00103 TR_NODE_TYPE *n;
00104 tnode_t *t;
00105 vec3_t c0maxs, c1mins;
00106 int i;
00107
00108 n = &tile->nodes[nodenum];
00109
00110
00111 t = (*tnode)++;
00112
00113
00114 if (n->children[0] < 0 || n->children[1] < 0)
00115 #ifdef COMPILE_UFO
00116 Com_Error(ERR_DROP, "Unexpected leaf");
00117 #else
00118 Sys_Error("Unexpected leaf");
00119 #endif
00120
00121 VectorCopy(tile->nodes[n->children[0]].maxs, c0maxs);
00122 VectorCopy(tile->nodes[n->children[1]].mins, c1mins);
00123
00124 #if 0
00125 Com_Printf("(%i %i : %i %i) (%i %i : %i %i)\n",
00126 (int)tile->nodes[n->children[0]].mins[0], (int)tile->nodes[n->children[0]].mins[1],
00127 (int)tile->nodes[n->children[0]].maxs[0], (int)tile->nodes[n->children[0]].maxs[1],
00128 (int)tile->nodes[n->children[1]].mins[0], (int)tile->nodes[n->children[1]].mins[1],
00129 (int)tile->nodes[n->children[1]].maxs[0], (int)tile->nodes[n->children[1]].maxs[1]);
00130 #endif
00131
00132 for (i = 0; i < 2; i++)
00133 if (c0maxs[i] <= c1mins[i]) {
00134
00135 t->type = i;
00136 VectorSet(t->normal, i, (i ^ 1), 0);
00137 t->dist = (c0maxs[i] + c1mins[i]) / 2;
00138
00139 t->children[1] = *tnode - tile->tnodes;
00140 TR_BuildTracingNode_r(tile, tnode, n->children[0], level);
00141 t->children[0] = *tnode - tile->tnodes;
00142 TR_BuildTracingNode_r(tile, tnode, n->children[1], level);
00143 return;
00144 }
00145
00146
00147 t->type = PLANE_NONE;
00148
00149 for (i = 0; i < 2; i++) {
00150 t->children[i] = *tnode - tile->tnodes;
00151 TR_BuildTracingNode_r(tile, tnode, n->children[i], level);
00152 }
00153 } else {
00154
00155 tile->cheads[tile->numcheads].cnode = nodenum;
00156 tile->cheads[tile->numcheads].level = level;
00157 tile->numcheads++;
00158 assert(tile->numcheads <= MAX_MAP_NODES);
00159
00160 TR_MakeTracingNode(tile, tnode, nodenum);
00161 }
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00181 int TR_TestLine_r (TR_TILE_TYPE *tile, int32_t nodenum, const vec3_t start, const vec3_t stop)
00182 {
00183 tnode_t *tnode;
00184 float front, back;
00185 int r;
00186
00187
00188
00189 if (nodenum & (1 << 31))
00190 return nodenum & ~(1 << 31);
00191
00192 tnode = &tile->tnodes[nodenum];
00193 assert(tnode);
00194 switch (tnode->type) {
00195 case PLANE_X:
00196 case PLANE_Y:
00197 case PLANE_Z:
00198 front = start[tnode->type] - tnode->dist;
00199 back = stop[tnode->type] - tnode->dist;
00200 break;
00201 case PLANE_NONE:
00202 r = TR_TestLine_r(tile, tnode->children[0], start, stop);
00203 if (r)
00204 return r;
00205 return TR_TestLine_r(tile, tnode->children[1], start, stop);
00206 default:
00207 front = DotProduct(start, tnode->normal) - tnode->dist;
00208 back = DotProduct(stop, tnode->normal) - tnode->dist;
00209 break;
00210 }
00211
00212 if (front >= -ON_EPSILON && back >= -ON_EPSILON)
00213 return TR_TestLine_r(tile, tnode->children[0], start, stop);
00214 else if (front < ON_EPSILON && back < ON_EPSILON)
00215 return TR_TestLine_r(tile, tnode->children[1], start, stop);
00216 else {
00217 const int side = front < 0;
00218 const float frac = front / (front - back);
00219 vec3_t mid;
00220
00221 VectorInterpolation(start, stop, frac, mid);
00222
00223 r = TR_TestLine_r(tile, tnode->children[side], start, mid);
00224 if (r)
00225 return r;
00226 return TR_TestLine_r(tile, tnode->children[!side], mid, stop);
00227 }
00228 }
00229
00230
00252 static qboolean TR_TileTestLine (TR_TILE_TYPE *tile, const vec3_t start, const vec3_t stop, const int levelmask)
00253 {
00254 const int corelevels = (levelmask & TL_FLAG_REGULAR_LEVELS);
00255 int i;
00256
00257
00258 for (i = 0; i < tile->numtheads; i++) {
00259 const int level = tile->theadlevel[i];
00260 if (level && corelevels && !(level & corelevels))
00261 continue;
00262 if (level == LEVEL_LIGHTCLIP)
00263 continue;
00264 if (level == LEVEL_ACTORCLIP && !(levelmask & TL_FLAG_ACTORCLIP))
00265 continue;
00266 if (level == LEVEL_WEAPONCLIP && !(levelmask & TL_FLAG_WEAPONCLIP))
00267 continue;
00268 if (TR_TestLine_r(tile, tile->thead[i], start, stop))
00269 return qtrue;
00270 }
00271 return qfalse;
00272 }
00273
00283 qboolean TR_TestLine (mapTiles_t *mapTiles, const vec3_t start, const vec3_t stop, const int levelmask)
00284 {
00285 int tile;
00286
00287 for (tile = 0; tile < mapTiles->numTiles; tile++) {
00288 if (TR_TileTestLine(&mapTiles->mapTiles[tile], start, stop, levelmask))
00289 return qtrue;
00290 }
00291 return qfalse;
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00311 static int TR_TestLineDist_r (TR_TILE_TYPE *tile, int32_t nodenum, const vec3_t start, const vec3_t stop, vec3_t tr_end)
00312 {
00313 tnode_t *tnode;
00314 float front, back;
00315 vec3_t mid;
00316 float frac;
00317 int side;
00318 int r;
00319
00320 if (nodenum & (1 << 31)) {
00321 r = nodenum & ~(1 << 31);
00322 if (r)
00323 VectorCopy(start, tr_end);
00324 return r;
00325 }
00326
00327 tnode = &tile->tnodes[nodenum];
00328 assert(tnode);
00329 switch (tnode->type) {
00330 case PLANE_X:
00331 case PLANE_Y:
00332 case PLANE_Z:
00333 front = start[tnode->type] - tnode->dist;
00334 back = stop[tnode->type] - tnode->dist;
00335 break;
00336 case PLANE_NONE:
00337 r = TR_TestLineDist_r(tile, tnode->children[0], start, stop, tr_end);
00338 if (r)
00339 VectorCopy(tr_end, mid);
00340 side = TR_TestLineDist_r(tile, tnode->children[1], start, stop, tr_end);
00341 if (side && r) {
00342 if (VectorNearer(mid, tr_end, start)) {
00343 VectorCopy(mid, tr_end);
00344 return r;
00345 } else {
00346 return side;
00347 }
00348 }
00349
00350 if (r) {
00351 VectorCopy(mid, tr_end);
00352 return r;
00353 }
00354
00355 return side;
00356 default:
00357 front = (start[0] * tnode->normal[0] + start[1] * tnode->normal[1] + start[2] * tnode->normal[2]) - tnode->dist;
00358 back = (stop[0] * tnode->normal[0] + stop[1] * tnode->normal[1] + stop[2] * tnode->normal[2]) - tnode->dist;
00359 break;
00360 }
00361
00362 if (front >= -ON_EPSILON && back >= -ON_EPSILON)
00363 return TR_TestLineDist_r(tile, tnode->children[0], start, stop, tr_end);
00364
00365 if (front < ON_EPSILON && back < ON_EPSILON)
00366 return TR_TestLineDist_r(tile, tnode->children[1], start, stop, tr_end);
00367
00368 side = front < 0;
00369
00370 frac = front / (front - back);
00371
00372 VectorInterpolation(start, stop, frac, mid);
00373
00374 r = TR_TestLineDist_r(tile, tnode->children[side], start, mid, tr_end);
00375 if (r)
00376 return r;
00377 return TR_TestLineDist_r(tile, tnode->children[!side], mid, stop, tr_end);
00378 }
00379
00391 static qboolean TR_TileTestLineDM (TR_TILE_TYPE *tile, const vec3_t start, const vec3_t stop, vec3_t end, const int levelmask)
00392 {
00393 #ifdef COMPILE_MAP
00394 const int corelevels = (levelmask & TL_FLAG_REGULAR_LEVELS);
00395 #endif
00396 vec3_t tr_end;
00397 int i;
00398
00399 VectorCopy(stop, end);
00400
00401 for (i = 0; i < tile->numtheads; i++) {
00402 #ifdef COMPILE_MAP
00403 const int level = tile->theadlevel[i];
00404 if (level && corelevels && !(level & levelmask))
00405 continue;
00406
00407
00408 if (level == LEVEL_ACTORCLIP && !(levelmask & TL_FLAG_ACTORCLIP))
00409 continue;
00410 if (level == LEVEL_WEAPONCLIP && !(levelmask & TL_FLAG_WEAPONCLIP))
00411 continue;
00412 #endif
00413 if (TR_TestLineDist_r(tile, tile->thead[i], start, stop, tr_end))
00414 if (VectorNearer(tr_end, end, start))
00415 VectorCopy(tr_end, end);
00416 }
00417
00418 if (VectorCompareEps(end, stop, EQUAL_EPSILON))
00419 return qfalse;
00420 else
00421 return qtrue;
00422 }
00423
00424
00435 qboolean TR_TestLineDM (mapTiles_t* mapTiles, const vec3_t start, const vec3_t stop, vec3_t end, const int levelmask)
00436 {
00437 int tile;
00438 vec3_t t_end;
00439
00440 VectorCopy(stop, end);
00441 VectorCopy(stop, t_end);
00442
00443 for (tile = 0; tile < mapTiles->numTiles; tile++) {
00444 if (TR_TileTestLineDM(&mapTiles->mapTiles[tile], start, stop, t_end, levelmask)) {
00445 if (VectorNearer(t_end, end, start))
00446 VectorCopy(t_end, end);
00447 }
00448 }
00449
00450 if (VectorCompareEps(end, stop, EQUAL_EPSILON))
00451 return qfalse;
00452 else
00453 return qtrue;
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00467 int TR_BoxOnPlaneSide (const vec3_t mins, const vec3_t maxs, const TR_PLANE_TYPE *plane)
00468 {
00469 int side, i;
00470 vec3_t corners[2];
00471 vec_t dist1, dist2;
00472
00473
00474 if (AXIAL(plane)) {
00475 side = 0;
00476 if (maxs[plane->type] > plane->dist + PLANESIDE_EPSILON)
00477 side |= PSIDE_FRONT;
00478 if (mins[plane->type] < plane->dist - PLANESIDE_EPSILON)
00479 side |= PSIDE_BACK;
00480 return side;
00481 }
00482
00483
00484
00485 for (i = 0; i < 3; i++) {
00486 if (plane->normal[i] < 0) {
00487 corners[0][i] = mins[i];
00488 corners[1][i] = maxs[i];
00489 } else {
00490 corners[1][i] = mins[i];
00491 corners[0][i] = maxs[i];
00492 }
00493 }
00494
00495 dist1 = DotProduct(plane->normal, corners[0]) - plane->dist;
00496 dist2 = DotProduct(plane->normal, corners[1]) - plane->dist;
00497 side = 0;
00498 if (dist1 >= PLANESIDE_EPSILON)
00499 side = PSIDE_FRONT;
00500 if (dist2 < PLANESIDE_EPSILON)
00501 side |= PSIDE_BACK;
00502
00503 return side;
00504 }
00505
00506 typedef struct leaf_check_s {
00507 int leaf_count, leaf_maxcount;
00508 int32_t *leaf_list;
00509 int32_t leaf_topnode;
00510 } leaf_check_t;
00511
00517 static void TR_BoxLeafnums_r (boxtrace_t *traceData, int32_t nodenum, leaf_check_t *lc)
00518 {
00519 TR_PLANE_TYPE *plane;
00520 TR_NODE_TYPE *node;
00521 int s;
00522 TR_TILE_TYPE *myTile = traceData->tile;
00523
00524 while (1) {
00525 if (nodenum <= LEAFNODE) {
00526 if (lc->leaf_count >= lc->leaf_maxcount) {
00527
00528 return;
00529 }
00530 lc->leaf_list[lc->leaf_count++] = -1 - nodenum;
00531 return;
00532 }
00533
00534 assert(nodenum < myTile->numnodes + 6);
00535 node = &myTile->nodes[nodenum];
00536 #ifdef COMPILE_UFO
00537 plane = node->plane;
00538 #else
00539 plane = myTile->planes + node->planenum;
00540 #endif
00541
00542 s = TR_BoxOnPlaneSide(traceData->absmins, traceData->absmaxs, plane);
00543 if (s == PSIDE_FRONT)
00544 nodenum = node->children[0];
00545 else if (s == PSIDE_BACK)
00546 nodenum = node->children[1];
00547 else {
00548 if (lc->leaf_topnode == LEAFNODE)
00549 lc->leaf_topnode = nodenum;
00550 TR_BoxLeafnums_r(traceData, node->children[0], lc);
00551 nodenum = node->children[1];
00552 }
00553 }
00554 }
00555
00560 static int TR_BoxLeafnums_headnode (boxtrace_t *traceData, int32_t *list, int listsize, int32_t headnode, int32_t *topnode)
00561 {
00562 leaf_check_t lc;
00563 lc.leaf_list = list;
00564 lc.leaf_count = 0;
00565 lc.leaf_maxcount = listsize;
00566 lc.leaf_topnode = LEAFNODE;
00567
00568 assert(headnode < traceData->tile->numnodes + 6);
00569 TR_BoxLeafnums_r(traceData, headnode, &lc);
00570
00571 if (topnode)
00572 *topnode = lc.leaf_topnode;
00573
00574 return lc.leaf_count;
00575 }
00576
00577
00586 static void TR_ClipBoxToBrush (boxtrace_t *traceData, cBspBrush_t *brush, TR_LEAF_TYPE *leaf)
00587 {
00588 int i, j;
00589 TR_PLANE_TYPE *clipplane;
00590 int clipplanenum;
00591 float dist;
00592 float enterfrac, leavefrac;
00593 vec3_t ofs;
00594 float d1, d2;
00595 qboolean getout, startout;
00596 #ifdef COMPILE_UFO
00597 TR_BRUSHSIDE_TYPE *leadside = NULL;
00598 #endif
00599 TR_TILE_TYPE *myTile = traceData->tile;
00600
00601 enterfrac = -1.0;
00602 leavefrac = 1.0;
00603 clipplane = NULL;
00604
00605 if (!brush || !brush->numsides)
00606 return;
00607
00608 getout = qfalse;
00609 startout = qfalse;
00610 clipplanenum = 0;
00611
00612 for (i = 0; i < brush->numsides; i++) {
00613 TR_BRUSHSIDE_TYPE *side = &myTile->brushsides[brush->firstbrushside + i];
00614 #ifdef COMPILE_UFO
00615 TR_PLANE_TYPE *plane = side->plane;
00616 #else
00617 TR_PLANE_TYPE *plane = myTile->planes + side->planenum;
00618 #endif
00619
00621 if (!traceData->ispoint) {
00622
00623 for (j = 0; j < 3; j++) {
00624 if (plane->normal[j] < 0)
00625 ofs[j] = traceData->maxs[j];
00626 else
00627 ofs[j] = traceData->mins[j];
00628 }
00629 dist = DotProduct(ofs, plane->normal);
00630 dist = plane->dist - dist;
00631 } else {
00632 dist = plane->dist;
00633 }
00634
00635 d1 = DotProduct(traceData->start, plane->normal) - dist;
00636 d2 = DotProduct(traceData->end, plane->normal) - dist;
00637
00638 if (d2 > 0)
00639 getout = qtrue;
00640 if (d1 > 0)
00641 startout = qtrue;
00642
00643
00644 if (d1 > 0 && d2 >= d1)
00645 return;
00646
00647 if (d1 <= 0 && d2 <= 0)
00648 continue;
00649
00650
00651 if (d1 > d2) {
00652 const float f = (d1 - DIST_EPSILON) / (d1 - d2);
00653 if (f > enterfrac) {
00654 enterfrac = f;
00655 clipplane = plane;
00656 #ifdef COMPILE_MAP
00657 clipplanenum = side->planenum;
00658 #else
00659 leadside = side;
00660 #endif
00661 }
00662 } else {
00663 const float f = (d1 + DIST_EPSILON) / (d1 - d2);
00664 if (f < leavefrac)
00665 leavefrac = f;
00666 }
00667 }
00668
00669 if (!startout) {
00670 traceData->trace.startsolid = qtrue;
00671 if (!getout)
00672 traceData->trace.allsolid = qtrue;
00673 traceData->trace.leafnum = leaf - myTile->leafs;
00674 return;
00675 }
00676 if (enterfrac < leavefrac) {
00677 if (enterfrac > -1 && enterfrac < traceData->trace.fraction) {
00678 if (enterfrac < 0)
00679 enterfrac = 0;
00680 traceData->trace.fraction = enterfrac;
00681 traceData->trace.plane = *clipplane;
00682 traceData->trace.planenum = clipplanenum;
00683 #ifdef COMPILE_UFO
00684 traceData->trace.surface = leadside->surface;
00685 #endif
00686 traceData->trace.contentFlags = brush->contentFlags;
00687 traceData->trace.leafnum = leaf - myTile->leafs;
00688 }
00689 }
00690 }
00691
00695 static void TR_TestBoxInBrush (boxtrace_t *traceData, cBspBrush_t * brush)
00696 {
00697 int i, j;
00698 TR_PLANE_TYPE *plane;
00699 float dist;
00700 vec3_t ofs;
00701 float d1;
00702 TR_TILE_TYPE *myTile = traceData->tile;
00703
00704 if (!brush || !brush->numsides)
00705 return;
00706
00707 for (i = 0; i < brush->numsides; i++) {
00708 TR_BRUSHSIDE_TYPE *side = &myTile->brushsides[brush->firstbrushside + i];
00709 #ifdef COMPILE_UFO
00710 plane = side->plane;
00711 #else
00712 plane = myTile->planes + side->planenum;
00713 #endif
00714
00716
00717
00718 for (j = 0; j < 3; j++) {
00719 if (plane->normal[j] < 0)
00720 ofs[j] = traceData->maxs[j];
00721 else
00722 ofs[j] = traceData->mins[j];
00723 }
00724 dist = DotProduct(ofs, plane->normal);
00725 dist = plane->dist - dist;
00726
00727 d1 = DotProduct(traceData->start, plane->normal) - dist;
00728
00729
00730 if (d1 > 0)
00731 return;
00732 }
00733
00734
00735 traceData->trace.startsolid = traceData->trace.allsolid = qtrue;
00736 traceData->trace.fraction = 0;
00737 traceData->trace.contentFlags = brush->contentFlags;
00738 }
00739
00740
00752 static void TR_TraceToLeaf (boxtrace_t *traceData, int32_t leafnum)
00753 {
00754 int k;
00755 TR_LEAF_TYPE *leaf;
00756 TR_TILE_TYPE *myTile = traceData->tile;
00757
00758 assert(leafnum > LEAFNODE);
00759 assert(leafnum <= myTile->numleafs);
00760
00761 leaf = &myTile->leafs[leafnum];
00762
00763 if (traceData->contents != MASK_ALL && (!(leaf->contentFlags & traceData->contents) || (leaf->contentFlags & traceData->rejects)))
00764 return;
00765
00766
00767 for (k = 0; k < leaf->numleafbrushes; k++) {
00768 const int brushnum = myTile->leafbrushes[leaf->firstleafbrush + k];
00769 cBspBrush_t *b = &myTile->brushes[brushnum];
00770
00771 if (b->checkcount == checkcount)
00772 continue;
00773 b->checkcount = checkcount;
00774
00775 if (traceData->contents != MASK_ALL && (!(b->contentFlags & traceData->contents) || (b->contentFlags & traceData->rejects)))
00776 continue;
00777
00778 TR_ClipBoxToBrush(traceData, b, leaf);
00779 if (!traceData->trace.fraction)
00780 return;
00781 }
00782 }
00783
00784
00788 static void TR_TestInLeaf (boxtrace_t *traceData, int32_t leafnum)
00789 {
00790 int k;
00791 const TR_LEAF_TYPE *leaf;
00792 TR_TILE_TYPE *myTile = traceData->tile;
00793
00794 assert(leafnum > LEAFNODE);
00795 assert(leafnum <= myTile->numleafs);
00796
00797 leaf = &myTile->leafs[leafnum];
00798
00799 if (!(leaf->contentFlags & traceData->contents))
00800 return;
00801
00802
00803 for (k = 0; k < leaf->numleafbrushes; k++) {
00804 const int brushnum = myTile->leafbrushes[leaf->firstleafbrush + k];
00805 cBspBrush_t *b = &myTile->brushes[brushnum];
00806 if (b->checkcount == checkcount)
00807 continue;
00808 b->checkcount = checkcount;
00809
00810 if (!(traceData->contents && b->contentFlags & traceData->contents) || (b->contentFlags & traceData->rejects))
00811 continue;
00812 TR_TestBoxInBrush(traceData, b);
00813 if (!traceData->trace.fraction)
00814 return;
00815 }
00816 }
00817
00818
00836 static void TR_RecursiveHullCheck (boxtrace_t *traceData, int32_t nodenum, float p1f, float p2f, const vec3_t p1, const vec3_t p2)
00837 {
00838 TR_NODE_TYPE *node;
00839 TR_PLANE_TYPE *plane;
00840 float t1, t2, offset;
00841 float frac, frac2;
00842 int side;
00843 float midf;
00844 vec3_t mid;
00845 TR_TILE_TYPE *myTile = traceData->tile;
00846
00847 if (traceData->trace.fraction <= p1f)
00848 return;
00849
00850
00851 if (nodenum <= LEAFNODE) {
00852 TR_TraceToLeaf(traceData, LEAFNODE - nodenum);
00853 return;
00854 }
00855
00856 assert(nodenum < MAX_MAP_NODES);
00857
00858
00859
00860 node = myTile->nodes + nodenum;
00861
00862 #ifdef COMPILE_UFO
00863 plane = node->plane;
00864 #else
00865 assert(node->planenum < MAX_MAP_PLANES);
00866 plane = myTile->planes + node->planenum;
00867 #endif
00868
00869 if (AXIAL(plane)) {
00870 const int type = plane->type;
00871 t1 = p1[type] - plane->dist;
00872 t2 = p2[type] - plane->dist;
00873 offset = traceData->extents[type];
00874 } else {
00875 t1 = DotProduct(plane->normal, p1) - plane->dist;
00876 t2 = DotProduct(plane->normal, p2) - plane->dist;
00877 if (traceData->ispoint)
00878 offset = 0;
00879 else
00880 offset = fabs(traceData->extents[0] * plane->normal[0])
00881 + fabs(traceData->extents[1] * plane->normal[1])
00882 + fabs(traceData->extents[2] * plane->normal[2]);
00883 }
00884
00885
00886 if (t1 >= offset && t2 >= offset) {
00887 TR_RecursiveHullCheck(traceData, node->children[0], p1f, p2f, p1, p2);
00888 return;
00889 } else if (t1 < -offset && t2 < -offset) {
00890 TR_RecursiveHullCheck(traceData, node->children[1], p1f, p2f, p1, p2);
00891 return;
00892 }
00893
00894
00901 if (t1 < t2) {
00902 const float idist = 1.0 / (t1 - t2);
00903 side = 1;
00904 frac2 = (t1 + offset + DIST_EPSILON) * idist;
00905 frac = (t1 - offset + DIST_EPSILON) * idist;
00906 } else if (t1 > t2) {
00907 const float idist = 1.0 / (t1 - t2);
00908 side = 0;
00909 frac2 = (t1 - offset - DIST_EPSILON) * idist;
00910 frac = (t1 + offset + DIST_EPSILON) * idist;
00911 } else {
00912 side = 0;
00913 frac = 1;
00914 frac2 = 0;
00915 }
00916
00917
00918 if (frac < 0)
00919 frac = 0;
00920 else if (frac > 1)
00921 frac = 1;
00922
00923 midf = p1f + (p2f - p1f) * frac;
00924 VectorInterpolation(p1, p2, frac, mid);
00925 TR_RecursiveHullCheck(traceData, node->children[side], p1f, midf, p1, mid);
00926
00927
00928 if (frac2 < 0)
00929 frac2 = 0;
00930 else if (frac2 > 1)
00931 frac2 = 1;
00932
00933 midf = p1f + (p2f - p1f) * frac2;
00934 VectorInterpolation(p1, p2, frac2, mid);
00935 TR_RecursiveHullCheck(traceData, node->children[side ^ 1], midf, p2f, mid, p2);
00936 }
00937
00958 trace_t TR_BoxTrace (TR_TILE_TYPE *tile, const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, const int headnode, const int brushmask, const int brushreject, const float fraction)
00959 {
00960 vec3_t offset, amins, amaxs, astart, aend;
00961 boxtrace_t traceData;
00962
00963 checkcount++;
00964
00965 #ifdef COMPILE_UFO
00966 if (headnode >= tile->numnodes + 6)
00967 Com_Error(ERR_DROP, "headnode (%i) is out of bounds: %i", headnode, tile->numnodes + 6);
00968 #else
00969 assert(headnode < tile->numnodes + 6);
00970 #endif
00971
00972
00973 memset(&traceData.trace, 0, sizeof(traceData.trace));
00974 traceData.trace.fraction = min(fraction, 1.0f);
00975 traceData.trace.surface = NULL;
00976
00977 if (!tile->numnodes)
00978 return traceData.trace;
00979
00980
00981
00982 VectorCenterFromMinsMaxs(mins, maxs, offset);
00983
00984
00985
00986 VectorSubtract(mins, offset, amins);
00987 VectorSubtract(maxs, offset, amaxs);
00988 VectorAdd(start, offset, astart);
00989 VectorAdd(end, offset, aend);
00990
00991 traceData.contents = brushmask;
00992 traceData.rejects = brushreject;
00993 traceData.tile = tile;
00994 VectorCopy(astart, traceData.start);
00995 VectorCopy(aend, traceData.end);
00996 VectorCopy(amins, traceData.mins);
00997 VectorCopy(amaxs, traceData.maxs);
00998
00999
01000 if (VectorCompare(astart, aend)) {
01001 int32_t leafs[MAX_LEAFS];
01002 int numleafs;
01003 int32_t topnode;
01004 int i;
01005
01006 VectorAdd(astart, amaxs, traceData.absmaxs);
01007 VectorAdd(astart, amins, traceData.absmins);
01008
01009
01010
01011
01012
01013
01014
01015
01016 numleafs = TR_BoxLeafnums_headnode(&traceData, leafs, MAX_LEAFS, headnode, &topnode);
01017 for (i = 0; i < numleafs; i++) {
01018 TR_TestInLeaf(&traceData, leafs[i]);
01019 if (traceData.trace.allsolid)
01020 break;
01021 }
01022 VectorCopy(start, traceData.trace.endpos);
01023 return traceData.trace;
01024 }
01025
01026
01027 if (VectorCompare(amins, vec3_origin) && VectorCompare(amaxs, vec3_origin)) {
01028 traceData.ispoint = qtrue;
01029 VectorClear(traceData.extents);
01030 } else {
01031 traceData.ispoint = qfalse;
01032 VectorCopy(amaxs, traceData.extents);
01033 }
01034
01035
01037 TR_RecursiveHullCheck(&traceData, headnode, 0.0, 1.0, astart, aend);
01038
01039 if (traceData.trace.fraction >= 1.0) {
01040 VectorCopy(aend, traceData.trace.endpos);
01041 } else {
01042 VectorInterpolation(traceData.start, traceData.end, traceData.trace.fraction, traceData.trace.endpos);
01043 }
01044
01045 VectorSubtract(traceData.trace.endpos, offset, traceData.trace.endpos);
01046 return traceData.trace;
01047 }
01048
01063 trace_t TR_TileBoxTrace (TR_TILE_TYPE *myTile, const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, const int levelmask, const int brushmask, const int brushreject)
01064 {
01065 trace_t newtr, tr;
01066 int i;
01067 cBspHead_t *h;
01068
01069 memset(&tr, 0, sizeof(tr));
01070
01071 tr.fraction = 2.0f;
01072
01073
01074 for (i = 0, h = myTile->cheads; i < myTile->numcheads; i++, h++) {
01075
01076
01077
01078
01079 if (h->level && h->level <= LEVEL_LASTVISIBLE && levelmask && !(h->level & levelmask))
01080 continue;
01081
01082 assert(h->cnode < myTile->numnodes + 6);
01083 newtr = TR_BoxTrace(myTile, start, end, mins, maxs, h->cnode, brushmask, brushreject, tr.fraction);
01084
01085
01086 if (newtr.fraction == 0.0)
01087 return newtr;
01088 if (newtr.fraction < tr.fraction)
01089 tr = newtr;
01090 }
01091 return tr;
01092 }
01093
01094 #ifdef COMPILE_MAP
01095
01106 trace_t TR_SingleTileBoxTrace (mapTiles_t *mapTiles, const vec3_t start, const vec3_t end, const box_t* traceBox, const int levelmask, const int brushmask, const int brushreject)
01107 {
01108 trace_t tr;
01109
01110 tr = TR_TileBoxTrace(&mapTiles->mapTiles[0], start, end, traceBox->mins, traceBox->maxs, levelmask, brushmask, brushreject);
01111 tr.mapTile = 0;
01112 return tr;
01113 }
01114 #endif