|
|
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.