|
|
1.1 ! root 1: /* ! 2: Copyright (C) 1996-1997 Id Software, Inc. ! 3: ! 4: This program is free software; you can redistribute it and/or ! 5: modify it under the terms of the GNU General Public License ! 6: as published by the Free Software Foundation; either version 2 ! 7: of the License, or (at your option) any later version. ! 8: ! 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. ! 12: ! 13: See the GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ! 18: ! 19: */ ! 20: #include "quakedef.h" ! 21: ! 22: static hull_t box_hull; ! 23: static dclipnode_t box_clipnodes[6]; ! 24: static mplane_t box_planes[6]; ! 25: ! 26: extern vec3_t player_mins; ! 27: extern vec3_t player_maxs; ! 28: ! 29: /* ! 30: =================== ! 31: PM_InitBoxHull ! 32: ! 33: Set up the planes and clipnodes so that the six floats of a bounding box ! 34: can just be stored out and get a proper hull_t structure. ! 35: =================== ! 36: */ ! 37: void PM_InitBoxHull (void) ! 38: { ! 39: int i; ! 40: int side; ! 41: ! 42: box_hull.clipnodes = box_clipnodes; ! 43: box_hull.planes = box_planes; ! 44: box_hull.firstclipnode = 0; ! 45: box_hull.lastclipnode = 5; ! 46: ! 47: for (i=0 ; i<6 ; i++) ! 48: { ! 49: box_clipnodes[i].planenum = i; ! 50: ! 51: side = i&1; ! 52: ! 53: box_clipnodes[i].children[side] = CONTENTS_EMPTY; ! 54: if (i != 5) ! 55: box_clipnodes[i].children[side^1] = i + 1; ! 56: else ! 57: box_clipnodes[i].children[side^1] = CONTENTS_SOLID; ! 58: ! 59: box_planes[i].type = i>>1; ! 60: box_planes[i].normal[i>>1] = 1; ! 61: } ! 62: ! 63: } ! 64: ! 65: ! 66: /* ! 67: =================== ! 68: PM_HullForBox ! 69: ! 70: To keep everything totally uniform, bounding boxes are turned into small ! 71: BSP trees instead of being compared directly. ! 72: =================== ! 73: */ ! 74: hull_t *PM_HullForBox (vec3_t mins, vec3_t maxs) ! 75: { ! 76: box_planes[0].dist = maxs[0]; ! 77: box_planes[1].dist = mins[0]; ! 78: box_planes[2].dist = maxs[1]; ! 79: box_planes[3].dist = mins[1]; ! 80: box_planes[4].dist = maxs[2]; ! 81: box_planes[5].dist = mins[2]; ! 82: ! 83: return &box_hull; ! 84: } ! 85: ! 86: ! 87: /* ! 88: ================== ! 89: PM_HullPointContents ! 90: ! 91: ================== ! 92: */ ! 93: int PM_HullPointContents (hull_t *hull, int num, vec3_t p) ! 94: { ! 95: float d; ! 96: dclipnode_t *node; ! 97: mplane_t *plane; ! 98: ! 99: while (num >= 0) ! 100: { ! 101: if (num < hull->firstclipnode || num > hull->lastclipnode) ! 102: Sys_Error ("PM_HullPointContents: bad node number"); ! 103: ! 104: node = hull->clipnodes + num; ! 105: plane = hull->planes + node->planenum; ! 106: ! 107: if (plane->type < 3) ! 108: d = p[plane->type] - plane->dist; ! 109: else ! 110: d = DotProduct (plane->normal, p) - plane->dist; ! 111: if (d < 0) ! 112: num = node->children[1]; ! 113: else ! 114: num = node->children[0]; ! 115: } ! 116: ! 117: return num; ! 118: } ! 119: ! 120: /* ! 121: ================== ! 122: PM_PointContents ! 123: ! 124: ================== ! 125: */ ! 126: int PM_PointContents (vec3_t p) ! 127: { ! 128: float d; ! 129: dclipnode_t *node; ! 130: mplane_t *plane; ! 131: hull_t *hull; ! 132: int num; ! 133: ! 134: hull = &pmove.physents[0].model->hulls[0]; ! 135: ! 136: num = hull->firstclipnode; ! 137: ! 138: while (num >= 0) ! 139: { ! 140: if (num < hull->firstclipnode || num > hull->lastclipnode) ! 141: Sys_Error ("PM_HullPointContents: bad node number"); ! 142: ! 143: node = hull->clipnodes + num; ! 144: plane = hull->planes + node->planenum; ! 145: ! 146: if (plane->type < 3) ! 147: d = p[plane->type] - plane->dist; ! 148: else ! 149: d = DotProduct (plane->normal, p) - plane->dist; ! 150: if (d < 0) ! 151: num = node->children[1]; ! 152: else ! 153: num = node->children[0]; ! 154: } ! 155: ! 156: return num; ! 157: } ! 158: ! 159: /* ! 160: =============================================================================== ! 161: ! 162: LINE TESTING IN HULLS ! 163: ! 164: =============================================================================== ! 165: */ ! 166: ! 167: // 1/32 epsilon to keep floating point happy ! 168: #define DIST_EPSILON (0.03125) ! 169: ! 170: /* ! 171: ================== ! 172: PM_RecursiveHullCheck ! 173: ! 174: ================== ! 175: */ ! 176: qboolean PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace) ! 177: { ! 178: dclipnode_t *node; ! 179: mplane_t *plane; ! 180: float t1, t2; ! 181: float frac; ! 182: int i; ! 183: vec3_t mid; ! 184: int side; ! 185: float midf; ! 186: ! 187: // check for empty ! 188: if (num < 0) ! 189: { ! 190: if (num != CONTENTS_SOLID) ! 191: { ! 192: trace->allsolid = false; ! 193: if (num == CONTENTS_EMPTY) ! 194: trace->inopen = true; ! 195: else ! 196: trace->inwater = true; ! 197: } ! 198: else ! 199: trace->startsolid = true; ! 200: return true; // empty ! 201: } ! 202: ! 203: if (num < hull->firstclipnode || num > hull->lastclipnode) ! 204: Sys_Error ("PM_RecursiveHullCheck: bad node number"); ! 205: ! 206: // ! 207: // find the point distances ! 208: // ! 209: node = hull->clipnodes + num; ! 210: plane = hull->planes + node->planenum; ! 211: ! 212: if (plane->type < 3) ! 213: { ! 214: t1 = p1[plane->type] - plane->dist; ! 215: t2 = p2[plane->type] - plane->dist; ! 216: } ! 217: else ! 218: { ! 219: t1 = DotProduct (plane->normal, p1) - plane->dist; ! 220: t2 = DotProduct (plane->normal, p2) - plane->dist; ! 221: } ! 222: ! 223: #if 1 ! 224: if (t1 >= 0 && t2 >= 0) ! 225: return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); ! 226: if (t1 < 0 && t2 < 0) ! 227: return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); ! 228: #else ! 229: if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) ) ! 230: return PM_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); ! 231: if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) ) ! 232: return PM_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); ! 233: #endif ! 234: ! 235: // put the crosspoint DIST_EPSILON pixels on the near side ! 236: if (t1 < 0) ! 237: frac = (t1 + DIST_EPSILON)/(t1-t2); ! 238: else ! 239: frac = (t1 - DIST_EPSILON)/(t1-t2); ! 240: if (frac < 0) ! 241: frac = 0; ! 242: if (frac > 1) ! 243: frac = 1; ! 244: ! 245: midf = p1f + (p2f - p1f)*frac; ! 246: for (i=0 ; i<3 ; i++) ! 247: mid[i] = p1[i] + frac*(p2[i] - p1[i]); ! 248: ! 249: side = (t1 < 0); ! 250: ! 251: // move up to the node ! 252: if (!PM_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) ) ! 253: return false; ! 254: ! 255: #ifdef PARANOID ! 256: if (PM_HullPointContents (pm_hullmodel, mid, node->children[side]) ! 257: == CONTENTS_SOLID) ! 258: { ! 259: Con_Printf ("mid PointInHullSolid\n"); ! 260: return false; ! 261: } ! 262: #endif ! 263: ! 264: if (PM_HullPointContents (hull, node->children[side^1], mid) ! 265: != CONTENTS_SOLID) ! 266: // go past the node ! 267: return PM_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace); ! 268: ! 269: if (trace->allsolid) ! 270: return false; // never got out of the solid area ! 271: ! 272: //================== ! 273: // the other side of the node is solid, this is the impact point ! 274: //================== ! 275: if (!side) ! 276: { ! 277: VectorCopy (plane->normal, trace->plane.normal); ! 278: trace->plane.dist = plane->dist; ! 279: } ! 280: else ! 281: { ! 282: VectorSubtract (vec3_origin, plane->normal, trace->plane.normal); ! 283: trace->plane.dist = -plane->dist; ! 284: } ! 285: ! 286: while (PM_HullPointContents (hull, hull->firstclipnode, mid) ! 287: == CONTENTS_SOLID) ! 288: { // shouldn't really happen, but does occasionally ! 289: frac -= 0.1; ! 290: if (frac < 0) ! 291: { ! 292: trace->fraction = midf; ! 293: VectorCopy (mid, trace->endpos); ! 294: Con_DPrintf ("backup past 0\n"); ! 295: return false; ! 296: } ! 297: midf = p1f + (p2f - p1f)*frac; ! 298: for (i=0 ; i<3 ; i++) ! 299: mid[i] = p1[i] + frac*(p2[i] - p1[i]); ! 300: } ! 301: ! 302: trace->fraction = midf; ! 303: VectorCopy (mid, trace->endpos); ! 304: ! 305: return false; ! 306: } ! 307: ! 308: ! 309: /* ! 310: ================ ! 311: PM_TestPlayerPosition ! 312: ! 313: Returns false if the given player position is not valid (in solid) ! 314: ================ ! 315: */ ! 316: qboolean PM_TestPlayerPosition (vec3_t pos) ! 317: { ! 318: int i; ! 319: physent_t *pe; ! 320: vec3_t mins, maxs, test; ! 321: hull_t *hull; ! 322: ! 323: for (i=0 ; i< pmove.numphysent ; i++) ! 324: { ! 325: pe = &pmove.physents[i]; ! 326: // get the clipping hull ! 327: if (pe->model) ! 328: hull = &pmove.physents[i].model->hulls[1]; ! 329: else ! 330: { ! 331: VectorSubtract (pe->mins, player_maxs, mins); ! 332: VectorSubtract (pe->maxs, player_mins, maxs); ! 333: hull = PM_HullForBox (mins, maxs); ! 334: } ! 335: ! 336: VectorSubtract (pos, pe->origin, test); ! 337: ! 338: if (PM_HullPointContents (hull, hull->firstclipnode, test) == CONTENTS_SOLID) ! 339: return false; ! 340: } ! 341: ! 342: return true; ! 343: } ! 344: ! 345: /* ! 346: ================ ! 347: PM_PlayerMove ! 348: ================ ! 349: */ ! 350: pmtrace_t PM_PlayerMove (vec3_t start, vec3_t end) ! 351: { ! 352: pmtrace_t trace, total; ! 353: vec3_t offset; ! 354: vec3_t start_l, end_l; ! 355: hull_t *hull; ! 356: int i; ! 357: physent_t *pe; ! 358: vec3_t mins, maxs; ! 359: ! 360: // fill in a default trace ! 361: memset (&total, 0, sizeof(pmtrace_t)); ! 362: total.fraction = 1; ! 363: total.ent = -1; ! 364: VectorCopy (end, total.endpos); ! 365: ! 366: for (i=0 ; i< pmove.numphysent ; i++) ! 367: { ! 368: pe = &pmove.physents[i]; ! 369: // get the clipping hull ! 370: if (pe->model) ! 371: hull = &pmove.physents[i].model->hulls[1]; ! 372: else ! 373: { ! 374: VectorSubtract (pe->mins, player_maxs, mins); ! 375: VectorSubtract (pe->maxs, player_mins, maxs); ! 376: hull = PM_HullForBox (mins, maxs); ! 377: } ! 378: ! 379: // PM_HullForEntity (ent, mins, maxs, offset); ! 380: VectorCopy (pe->origin, offset); ! 381: ! 382: VectorSubtract (start, offset, start_l); ! 383: VectorSubtract (end, offset, end_l); ! 384: ! 385: // fill in a default trace ! 386: memset (&trace, 0, sizeof(pmtrace_t)); ! 387: trace.fraction = 1; ! 388: trace.allsolid = true; ! 389: // trace.startsolid = true; ! 390: VectorCopy (end, trace.endpos); ! 391: ! 392: // trace a line through the apropriate clipping hull ! 393: PM_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace); ! 394: ! 395: if (trace.allsolid) ! 396: trace.startsolid = true; ! 397: if (trace.startsolid) ! 398: trace.fraction = 0; ! 399: ! 400: // did we clip the move? ! 401: if (trace.fraction < total.fraction) ! 402: { ! 403: // fix trace up by the offset ! 404: VectorAdd (trace.endpos, offset, trace.endpos); ! 405: total = trace; ! 406: total.ent = i; ! 407: } ! 408: ! 409: } ! 410: ! 411: return total; ! 412: } ! 413: ! 414:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.