diff --git a/src/common/cmodel.c b/src/common/cmodel.c index 54f6da3e..946343c7 100644 --- a/src/common/cmodel.c +++ b/src/common/cmodel.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. typedef struct { cplane_t *plane; - int children[2]; /* negative numbers are leafs */ + int children[2]; /* negative numbers are leafs */ } cnode_t; typedef struct @@ -47,14 +47,14 @@ typedef struct int contents; int numsides; int firstbrushside; - int checkcount; /* to avoid repeated testings */ + int checkcount; /* to avoid repeated testings */ } cbrush_t; typedef struct { int numareaportals; int firstareaportal; - int floodnum; /* if two areas have equal floodnums, they are connected */ + int floodnum; /* if two areas have equal floodnums, they are connected */ int floodvalid; } carea_t; @@ -69,12 +69,12 @@ int numtexinfo; mapsurface_t map_surfaces[MAX_MAP_TEXINFO]; int numplanes; -cplane_t map_planes[MAX_MAP_PLANES+6]; /* extra for box hull */ +cplane_t map_planes[MAX_MAP_PLANES+6]; /* extra for box hull */ int numnodes; -cnode_t map_nodes[MAX_MAP_NODES+6]; /* extra for box hull */ +cnode_t map_nodes[MAX_MAP_NODES+6]; /* extra for box hull */ -int numleafs = 1; /* allow leaf funcs to be called without a map */ +int numleafs = 1; /* allow leaf funcs to be called without a map */ cleaf_t map_leafs[MAX_MAP_LEAFS]; int emptyleaf, solidleaf; @@ -108,7 +108,6 @@ int floodvalid; qboolean portalopen[MAX_MAP_AREAPORTALS]; - cvar_t *map_noareas; void CM_InitBoxHull (void); @@ -130,12 +129,15 @@ void CMod_LoadSubmodels (lump_t *l) int i, j, count; in = (void *)(cmod_base + l->fileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); if (count < 1) Com_Error (ERR_DROP, "Map with no models"); + if (count > MAX_MAP_MODELS) Com_Error (ERR_DROP, "Map has too many models"); @@ -146,11 +148,13 @@ void CMod_LoadSubmodels (lump_t *l) out = &map_cmodels[i]; for (j=0 ; j<3 ; j++) - { /* spread the mins / maxs by a pixel */ + { + /* spread the mins / maxs by a pixel */ out->mins[j] = LittleFloat (in->mins[j]) - 1; out->maxs[j] = LittleFloat (in->maxs[j]) + 1; out->origin[j] = LittleFloat (in->origin[j]); } + out->headnode = LittleLong (in->headnode); } } @@ -162,11 +166,15 @@ void CMod_LoadSurfaces (lump_t *l) int i, count; in = (void *)(cmod_base + l->fileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); + if (count < 1) Com_Error (ERR_DROP, "Map with no surfaces"); + if (count > MAX_MAP_TEXINFO) Com_Error (ERR_DROP, "Map has too many surfaces"); @@ -188,14 +196,17 @@ void CMod_LoadNodes (lump_t *l) int child; cnode_t *out; int i, j, count; - + in = (void *)(cmod_base + l->fileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); if (count < 1) Com_Error (ERR_DROP, "Map has no nodes"); + if (count > MAX_MAP_NODES) Com_Error (ERR_DROP, "Map has too many nodes"); @@ -206,6 +217,7 @@ void CMod_LoadNodes (lump_t *l) for (i=0 ; iplane = map_planes + LittleLong(in->planenum); + for (j=0 ; j<2 ; j++) { child = LittleLong (in->children[j]); @@ -220,10 +232,12 @@ void CMod_LoadBrushes (lump_t *l) dbrush_t *in; cbrush_t *out; int i, count; - + in = (void *)(cmod_base + l->fileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); if (count > MAX_MAP_BRUSHES) @@ -248,19 +262,22 @@ void CMod_LoadLeafs (lump_t *l) cleaf_t *out; dleaf_t *in; int count; - + in = (void *)(cmod_base + l->fileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); if (count < 1) Com_Error (ERR_DROP, "Map with no leafs"); + /* need to save space for box planes */ if (count > MAX_MAP_PLANES) Com_Error (ERR_DROP, "Map has too many planes"); - out = map_leafs; + out = map_leafs; numleafs = count; numclusters = 0; @@ -278,8 +295,10 @@ void CMod_LoadLeafs (lump_t *l) if (map_leafs[0].contents != CONTENTS_SOLID) Com_Error (ERR_DROP, "Map leaf 0 is not CONTENTS_SOLID"); + solidleaf = 0; emptyleaf = -1; + for (i=1 ; ifileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); if (count < 1) Com_Error (ERR_DROP, "Map with no planes"); + /* need to save space for box planes */ if (count > MAX_MAP_PLANES) Com_Error (ERR_DROP, "Map has too many planes"); - out = map_planes; + out = map_planes; numplanes = count; for ( i=0 ; inormal[j] = LittleFloat (in->normal[j]); + if (out->normal[j] < 0) bits |= 1<fileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); if (count < 1) Com_Error (ERR_DROP, "Map with no planes"); + /* need to save space for box planes */ if (count > MAX_MAP_LEAFBRUSHES) Com_Error (ERR_DROP, "Map has too many leafbrushes"); @@ -357,22 +385,24 @@ void CMod_LoadLeafBrushes (lump_t *l) void CMod_LoadBrushSides (lump_t *l) { - int i, j; + int i, j; cbrushside_t *out; dbrushside_t *in; - int count; - int num; + int count; + int num; in = (void *)(cmod_base + l->fileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); /* need to save space for box planes */ if (count > MAX_MAP_BRUSHSIDES) Com_Error (ERR_DROP, "Map has too many planes"); - out = map_brushsides; + out = map_brushsides; numbrushsides = count; for ( i=0 ; iplanenum); out->plane = &map_planes[num]; j = LittleShort (in->texinfo); + if (j >= numtexinfo) Com_Error (ERR_DROP, "Bad brushside texinfo"); + out->surface = &map_surfaces[j]; } } @@ -394,8 +426,10 @@ void CMod_LoadAreas (lump_t *l) int count; in = (void *)(cmod_base + l->fileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); if (count > MAX_MAP_AREAS) @@ -415,13 +449,15 @@ void CMod_LoadAreas (lump_t *l) void CMod_LoadAreaPortals (lump_t *l) { - dareaportal_t *out; + dareaportal_t *out; dareaportal_t *in; - int count; + int count; in = (void *)(cmod_base + l->fileofs); + if (l->filelen % sizeof(*in)) Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); + count = l->filelen / sizeof(*in); if (count > MAX_MAP_AREAS) @@ -436,6 +472,7 @@ void CMod_LoadAreaPortals (lump_t *l) void CMod_LoadVisibility (lump_t *l) { numvisibility = l->filelen; + if (l->filelen > MAX_MAP_VISIBILITY) Com_Error (ERR_DROP, "Map has too large visibility lump"); @@ -447,6 +484,7 @@ void CMod_LoadVisibility (lump_t *l) void CMod_LoadEntityString (lump_t *l) { numentitychars = l->filelen; + if (l->filelen > MAX_MAP_ENTSTRING) Com_Error (ERR_DROP, "Map has too large entity lump"); @@ -469,12 +507,14 @@ cmodel_t *CM_LoadMap (char *name, qboolean clientload, unsigned *checksum) if ( !strcmp (map_name, name) && (clientload || !Cvar_VariableValue ("flushmap")) ) { *checksum = last_checksum; + if (!clientload) { memset (portalopen, 0, sizeof(portalopen)); FloodAreaConnections (); } - return &map_cmodels[0]; /* still have the right version */ + + return &map_cmodels[0]; /* still have the right version */ } /* free old stuff */ @@ -493,10 +533,11 @@ cmodel_t *CM_LoadMap (char *name, qboolean clientload, unsigned *checksum) numclusters = 1; numareas = 1; *checksum = 0; - return &map_cmodels[0]; /* cinematic servers won't have anything at all */ + return &map_cmodels[0]; /* cinematic servers won't have anything at all */ } length = FS_LoadFile (name, (void **)&buf); + if (!buf) Com_Error (ERR_DROP, "Couldn't load %s", name); @@ -504,12 +545,13 @@ cmodel_t *CM_LoadMap (char *name, qboolean clientload, unsigned *checksum) *checksum = last_checksum; header = *(dheader_t *)buf; + for (i=0 ; i= numcmodels) Com_Error (ERR_DROP, "CM_InlineModel: bad number"); return &map_cmodels[num]; } -int CM_NumClusters (void) +int CM_NumClusters (void) { return numclusters; } -int CM_NumInlineModels (void) +int CM_NumInlineModels (void) { return numcmodels; } -char *CM_EntityString (void) +char *CM_EntityString (void) { return map_entitystring; } -int CM_LeafContents (int leafnum) +int CM_LeafContents (int leafnum) { if (leafnum < 0 || leafnum >= numleafs) Com_Error (ERR_DROP, "CM_LeafContents: bad number"); + return map_leafs[leafnum].contents; } -int CM_LeafCluster (int leafnum) +int CM_LeafCluster (int leafnum) { if (leafnum < 0 || leafnum >= numleafs) Com_Error (ERR_DROP, "CM_LeafCluster: bad number"); + return map_leafs[leafnum].cluster; } -int CM_LeafArea (int leafnum) +int CM_LeafArea (int leafnum) { if (leafnum < 0 || leafnum >= numleafs) Com_Error (ERR_DROP, "CM_LeafArea: bad number"); + return map_leafs[leafnum].area; } -//======================================================================= - +/* ======================================================================= */ cplane_t *box_planes; int box_headnode; @@ -610,11 +656,12 @@ void CM_InitBoxHull (void) box_headnode = numnodes; box_planes = &map_planes[numplanes]; + if (numnodes+6 > MAX_MAP_NODES - || numbrushes+1 > MAX_MAP_BRUSHES - || numleafbrushes+1 > MAX_MAP_LEAFBRUSHES - || numbrushsides+6 > MAX_MAP_BRUSHSIDES - || numplanes+12 > MAX_MAP_PLANES) + || numbrushes+1 > MAX_MAP_BRUSHES + || numleafbrushes+1 > MAX_MAP_LEAFBRUSHES + || numbrushsides+6 > MAX_MAP_BRUSHSIDES + || numplanes+12 > MAX_MAP_PLANES) Com_Error (ERR_DROP, "Not enough room for box tree"); box_brush = &map_brushes[numbrushes]; @@ -642,8 +689,10 @@ void CM_InitBoxHull (void) c = &map_nodes[box_headnode+i]; c->plane = map_planes + (numplanes+i*2); c->children[side] = -1 - emptyleaf; + if (i != 5) c->children[side^1] = box_headnode+i + 1; + else c->children[side^1] = -1 - numleafs; @@ -659,7 +708,7 @@ void CM_InitBoxHull (void) p->signbits = 0; VectorClear (p->normal); p->normal[i>>1] = -1; - } + } } /* @@ -694,19 +743,22 @@ int CM_PointLeafnum_r (vec3_t p, int num) { node = map_nodes + num; plane = node->plane; - + if (plane->type < 3) d = p[plane->type] - plane->dist; + else d = DotProduct (plane->normal, p) - plane->dist; + if (d < 0) num = node->children[1]; + else num = node->children[0]; } -#ifndef DEDICATED_ONLY - c_pointcontents++; /* optimize counter */ +#ifndef DEDICATED_ONLY + c_pointcontents++; /* optimize counter */ #endif return -1 - num; @@ -715,7 +767,8 @@ int CM_PointLeafnum_r (vec3_t p, int num) int CM_PointLeafnum (vec3_t p) { if (!numplanes) - return 0; /* sound may call this without map loaded */ + return 0; /* sound may call this without map loaded */ + return CM_PointLeafnum_r (p, 0); } @@ -741,21 +794,27 @@ void CM_BoxLeafnums_r (int nodenum) { return; } + leaf_list[leaf_count++] = -1 - nodenum; return; } - + node = &map_nodes[nodenum]; plane = node->plane; s = BOX_ON_PLANE_SIDE(leaf_mins, leaf_maxs, plane); + if (s == 1) nodenum = node->children[0]; + else if (s == 2) nodenum = node->children[1]; + else - { /* go down both */ + { + /* go down both */ if (leaf_topnode == -1) leaf_topnode = nodenum; + CM_BoxLeafnums_r (node->children[0]); nodenum = node->children[1]; } @@ -763,7 +822,7 @@ void CM_BoxLeafnums_r (int nodenum) } } -int CM_BoxLeafnums_headnode (vec3_t mins, vec3_t maxs, int *list, int listsize, int headnode, int *topnode) +int CM_BoxLeafnums_headnode (vec3_t mins, vec3_t maxs, int *list, int listsize, int headnode, int *topnode) { leaf_list = list; leaf_count = 0; @@ -781,17 +840,17 @@ int CM_BoxLeafnums_headnode (vec3_t mins, vec3_t maxs, int *list, int listsize, return leaf_count; } -int CM_BoxLeafnums (vec3_t mins, vec3_t maxs, int *list, int listsize, int *topnode) +int CM_BoxLeafnums (vec3_t mins, vec3_t maxs, int *list, int listsize, int *topnode) { return CM_BoxLeafnums_headnode (mins, maxs, list, - listsize, map_cmodels[0].headnode, topnode); + listsize, map_cmodels[0].headnode, topnode); } int CM_PointContents (vec3_t p, int headnode) { int l; - if (!numnodes) /* map not loaded */ + if (!numnodes) /* map not loaded */ return 0; l = CM_PointLeafnum_r (p, headnode); @@ -814,8 +873,8 @@ int CM_TransformedPointContents (vec3_t p, int headnode, vec3_t origin, vec3_t a VectorSubtract (p, origin, p_l); /* rotate start and end into the models frame of reference */ - if (headnode != box_headnode && - (angles[0] || angles[1] || angles[2]) ) + if (headnode != box_headnode && + (angles[0] || angles[1] || angles[2]) ) { AngleVectors (angles, forward, right, up); @@ -830,16 +889,9 @@ int CM_TransformedPointContents (vec3_t p, int headnode, vec3_t origin, vec3_t a return map_leafs[l].contents; } +/* BOX TRACING */ -/* -=============================================================================== - -BOX TRACING - -=============================================================================== -*/ - -// 1/32 epsilon to keep floating point happy +/* 1/32 epsilon to keep floating point happy */ #define DIST_EPSILON (0.03125f) vec3_t trace_start, trace_end; @@ -848,15 +900,10 @@ vec3_t trace_extents; trace_t trace_trace; int trace_contents; -qboolean trace_ispoint; // optimized case +qboolean trace_ispoint; /* optimized case */ -/* -================ -CM_ClipBoxToBrush -================ -*/ void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2, - trace_t *trace, cbrush_t *brush) + trace_t *trace, cbrush_t *brush) { int i, j; cplane_t *plane, *clipplane; @@ -875,7 +922,7 @@ void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2, if (!brush->numsides) return; -#ifndef DEDICATED_ONLY +#ifndef DEDICATED_ONLY c_brush_traces++; #endif @@ -888,26 +935,27 @@ void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2, side = &map_brushsides[brush->firstbrushside+i]; plane = side->plane; - // FIXME: special case for axial - if (!trace_ispoint) - { // general box case - - // push the plane out apropriately for mins/maxs - - // FIXME: use signbits into 8 way lookup for each mins/maxs + { + /* general box case + push the plane out + apropriately for mins/maxs */ for (j=0 ; j<3 ; j++) { if (plane->normal[j] < 0) ofs[j] = maxs[j]; + else ofs[j] = mins[j]; } + dist = DotProduct (ofs, plane->normal); dist = plane->dist - dist; } + else - { // special point case + { + /* special point case */ dist = plane->dist; } @@ -915,21 +963,24 @@ void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2, d2 = DotProduct (p2, plane->normal) - dist; if (d2 > 0) - getout = true; // endpoint is not in solid + getout = true; /* endpoint is not in solid */ + if (d1 > 0) startout = true; - // if completely in front of face, no intersection + /* if completely in front of face, no intersection */ if (d1 > 0 && d2 >= d1) return; if (d1 <= 0 && d2 <= 0) continue; - // crosses face + /* crosses face */ if (d1 > d2) - { // enter + { + /* enter */ f = (d1-DIST_EPSILON) / (d1-d2); + if (f > enterfrac) { enterfrac = f; @@ -937,27 +988,35 @@ void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2, leadside = side; } } + else - { // leave + { + /* leave */ f = (d1+DIST_EPSILON) / (d1-d2); + if (f < leavefrac) leavefrac = f; } } if (!startout) - { // original point was inside brush + { + /* original point was inside brush */ trace->startsolid = true; + if (!getout) trace->allsolid = true; + return; } + if (enterfrac < leavefrac) { if (enterfrac > -1 && enterfrac < trace->fraction) { if (enterfrac < 0) enterfrac = 0; + trace->fraction = enterfrac; trace->plane = *clipplane; trace->surface = &(leadside->surface->c); @@ -966,13 +1025,8 @@ void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2, } } -/* -================ -CM_TestBoxInBrush -================ -*/ void CM_TestBoxInBrush (vec3_t mins, vec3_t maxs, vec3_t p1, - trace_t *trace, cbrush_t *brush) + trace_t *trace, cbrush_t *brush) { int i, j; cplane_t *plane; @@ -989,43 +1043,35 @@ void CM_TestBoxInBrush (vec3_t mins, vec3_t maxs, vec3_t p1, side = &map_brushsides[brush->firstbrushside+i]; plane = side->plane; - // FIXME: special case for axial - - // general box case - - // push the plane out apropriately for mins/maxs - - // FIXME: use signbits into 8 way lookup for each mins/maxs + /* general box case + push the plane out + apropriately for mins/maxs */ for (j=0 ; j<3 ; j++) { if (plane->normal[j] < 0) ofs[j] = maxs[j]; + else ofs[j] = mins[j]; } + dist = DotProduct (ofs, plane->normal); dist = plane->dist - dist; d1 = DotProduct (p1, plane->normal) - dist; - // if completely in front of face, no intersection + /* if completely in front of face, no intersection */ if (d1 > 0) return; } - // inside this brush + /* inside this brush */ trace->startsolid = trace->allsolid = true; trace->fraction = 0; trace->contents = brush->contents; } - -/* -================ -CM_TraceToLeaf -================ -*/ void CM_TraceToLeaf (int leafnum) { int k; @@ -1034,32 +1080,32 @@ void CM_TraceToLeaf (int leafnum) cbrush_t *b; leaf = &map_leafs[leafnum]; + if ( !(leaf->contents & trace_contents)) return; - // trace line against all brushes in the leaf + + /* trace line against all brushes in the leaf */ for (k=0 ; knumleafbrushes ; k++) { brushnum = map_leafbrushes[leaf->firstleafbrush+k]; b = &map_brushes[brushnum]; + if (b->checkcount == checkcount) - continue; // already checked this brush in another leaf + continue; /* already checked this brush in another leaf */ + b->checkcount = checkcount; if ( !(b->contents & trace_contents)) continue; + CM_ClipBoxToBrush (trace_mins, trace_maxs, trace_start, trace_end, &trace_trace, b); + if (!trace_trace.fraction) return; } } - -/* -================ -CM_TestInLeaf -================ -*/ void CM_TestInLeaf (int leafnum) { int k; @@ -1068,33 +1114,32 @@ void CM_TestInLeaf (int leafnum) cbrush_t *b; leaf = &map_leafs[leafnum]; + if ( !(leaf->contents & trace_contents)) return; - // trace line against all brushes in the leaf + + /* trace line against all brushes in the leaf */ for (k=0 ; knumleafbrushes ; k++) { brushnum = map_leafbrushes[leaf->firstleafbrush+k]; b = &map_brushes[brushnum]; + if (b->checkcount == checkcount) - continue; // already checked this brush in another leaf + continue; /* already checked this brush in another leaf */ + b->checkcount = checkcount; if ( !(b->contents & trace_contents)) continue; + CM_TestBoxInBrush (trace_mins, trace_maxs, trace_start, &trace_trace, b); + if (!trace_trace.fraction) return; } } - -/* -================== -CM_RecursiveHullCheck - -================== -*/ void CM_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2) { cnode_t *node; @@ -1108,19 +1153,17 @@ void CM_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2) float midf; if (trace_trace.fraction <= p1f) - return; // already hit something nearer + return; /* already hit something nearer */ - // if < 0, we are in a leaf node + /* if < 0, we are in a leaf node */ if (num < 0) { CM_TraceToLeaf (-1-num); return; } - // - // find the point distances to the seperating plane - // and the offset for the size of the box - // + /* find the point distances to the seperating plane + and the offset for the size of the box */ node = map_nodes + num; plane = node->plane; @@ -1130,31 +1173,35 @@ void CM_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2) t2 = p2[plane->type] - plane->dist; offset = trace_extents[plane->type]; } + else { t1 = DotProduct (plane->normal, p1) - plane->dist; t2 = DotProduct (plane->normal, p2) - plane->dist; + if (trace_ispoint) offset = 0; + else offset = (float)fabs(trace_extents[0]*plane->normal[0]) + - (float)fabs(trace_extents[1]*plane->normal[1]) + - (float)fabs(trace_extents[2]*plane->normal[2]); + (float)fabs(trace_extents[1]*plane->normal[1]) + + (float)fabs(trace_extents[2]*plane->normal[2]); } - // see which sides we need to consider + /* see which sides we need to consider */ if (t1 >= offset && t2 >= offset) { CM_RecursiveHullCheck (node->children[0], p1f, p2f, p1, p2); return; } + if (t1 < -offset && t2 < -offset) { CM_RecursiveHullCheck (node->children[1], p1f, p2f, p1, p2); return; } - // put the crosspoint DIST_EPSILON pixels on the near side + /* put the crosspoint DIST_EPSILON pixels on the near side */ if (t1 < t2) { idist = 1.0f/(t1-t2); @@ -1162,6 +1209,7 @@ void CM_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2) frac2 = (t1 + offset + DIST_EPSILON)*idist; frac = (t1 - offset + DIST_EPSILON)*idist; } + else if (t1 > t2) { idist = 1.0/(t1-t2); @@ -1169,6 +1217,7 @@ void CM_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2) frac2 = (t1 - offset - DIST_EPSILON)*idist; frac = (t1 + offset + DIST_EPSILON)*idist; } + else { side = 0; @@ -1176,59 +1225,56 @@ void CM_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2) frac2 = 0; } - // move up to the node + /* move up to the node */ if (frac < 0) frac = 0; + if (frac > 1) frac = 1; - + midf = p1f + (p2f - p1f)*frac; + for (i=0 ; i<3 ; i++) mid[i] = p1[i] + frac*(p2[i] - p1[i]); CM_RecursiveHullCheck (node->children[side], p1f, midf, p1, mid); - // go past the node + /* go past the node */ if (frac2 < 0) frac2 = 0; + if (frac2 > 1) frac2 = 1; - + midf = p1f + (p2f - p1f)*frac2; + for (i=0 ; i<3 ; i++) mid[i] = p1[i] + frac2*(p2[i] - p1[i]); CM_RecursiveHullCheck (node->children[side^1], midf, p2f, mid, p2); } +/* ====================================================================== */ - -//====================================================================== - -/* -================== -CM_BoxTrace -================== -*/ trace_t CM_BoxTrace (vec3_t start, vec3_t end, - vec3_t mins, vec3_t maxs, - int headnode, int brushmask) + vec3_t mins, vec3_t maxs, + int headnode, int brushmask) { int i; - checkcount++; // for multi-check avoidance + checkcount++; /* for multi-check avoidance */ -#ifndef DEDICATED_ONLY - c_traces++; // for statistics, may be zeroed +#ifndef DEDICATED_ONLY + c_traces++; /* for statistics, may be zeroed */ #endif - // fill in a default trace + /* fill in a default trace */ memset (&trace_trace, 0, sizeof(trace_trace)); trace_trace.fraction = 1; trace_trace.surface = &(nullsurface.c); - if (!numnodes) // map not loaded + if (!numnodes) /* map not loaded */ return trace_trace; trace_contents = brushmask; @@ -1237,9 +1283,7 @@ trace_t CM_BoxTrace (vec3_t start, vec3_t end, VectorCopy (mins, trace_mins); VectorCopy (maxs, trace_maxs); - // - // check for position test special case - // + /* check for position test special case */ if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2]) { int leafs[1024]; @@ -1249,6 +1293,7 @@ trace_t CM_BoxTrace (vec3_t start, vec3_t end, VectorAdd (start, mins, c1); VectorAdd (start, maxs, c2); + for (i=0 ; i<3 ; i++) { c1[i] -= 1; @@ -1256,25 +1301,27 @@ trace_t CM_BoxTrace (vec3_t start, vec3_t end, } numleafs = CM_BoxLeafnums_headnode (c1, c2, leafs, 1024, headnode, &topnode); + for (i=0 ; i maxs[2] ? -mins[2] : maxs[2]; } - // - // general sweeping through world - // + /* general sweeping through world */ CM_RecursiveHullCheck (headnode, 0, 1, start, end); if (trace_trace.fraction == 1) { VectorCopy (end, trace_trace.endpos); } + else { for (i=0 ; i<3 ; i++) trace_trace.endpos[i] = start[i] + trace_trace.fraction * (end[i] - start[i]); } + return trace_trace; } - /* -================== -CM_TransformedBoxTrace - -Handles offseting and rotation of the end points for moving and -rotating entities -================== -*/ - -trace_t CM_TransformedBoxTrace (vec3_t start, vec3_t end, - vec3_t mins, vec3_t maxs, - int headnode, int brushmask, - vec3_t origin, vec3_t angles) + * Handles offseting and rotation of the end points for moving and + * rotating entities + */ +trace_t CM_TransformedBoxTrace (vec3_t start, vec3_t end, + vec3_t mins, vec3_t maxs, + int headnode, int brushmask, + vec3_t origin, vec3_t angles) { trace_t trace; vec3_t start_l, end_l; @@ -1322,14 +1363,15 @@ trace_t CM_TransformedBoxTrace (vec3_t start, vec3_t end, vec3_t temp; qboolean rotated; - // subtract origin offset + /* subtract origin offset */ VectorSubtract (start, origin, start_l); VectorSubtract (end, origin, end_l); - // rotate start and end into the models frame of reference - if (headnode != box_headnode && - (angles[0] || angles[1] || angles[2]) ) + /* rotate start and end into the models frame of reference */ + if (headnode != box_headnode && + (angles[0] || angles[1] || angles[2]) ) rotated = true; + else rotated = false; @@ -1348,12 +1390,11 @@ trace_t CM_TransformedBoxTrace (vec3_t start, vec3_t end, end_l[2] = DotProduct (temp, up); } - // sweep the box through the model + /* sweep the box through the model */ trace = CM_BoxTrace (start_l, end_l, mins, maxs, headnode, brushmask); if (rotated && trace.fraction != 1.0) { - // FIXME: figure out how to do this with existing angles VectorNegate (angles, a); AngleVectors (a, forward, right, up); @@ -1370,36 +1411,27 @@ trace_t CM_TransformedBoxTrace (vec3_t start, vec3_t end, return trace; } -/* -=============================================================================== +/* PVS / PHS */ -PVS / PHS - -=============================================================================== -*/ - -/* -=================== -CM_DecompressVis -=================== -*/ void CM_DecompressVis (byte *in, byte *out) { int c; byte *out_p; int row; - row = (numclusters+7)>>3; + row = (numclusters+7)>>3; out_p = out; if (!in || !numvisibility) - { // no vis info, so make all visible + { + /* no vis info, so make all visible */ while (row) { *out_p++ = 0xff; row--; } - return; + + return; } do @@ -1409,31 +1441,36 @@ void CM_DecompressVis (byte *in, byte *out) *out_p++ = *in++; continue; } - + c = in[1]; in += 2; + if ((out_p - out) + c > row) { c = row - (out_p - out); Com_DPrintf ("warning: Vis decompression overrun\n"); } + while (c) { *out_p++ = 0; c--; } - } while (out_p - out < row); + } + while (out_p - out < row); } -byte pvsrow[MAX_MAP_LEAFS/8]; -byte phsrow[MAX_MAP_LEAFS/8]; +byte pvsrow[MAX_MAP_LEAFS/8]; +byte phsrow[MAX_MAP_LEAFS/8]; -byte *CM_ClusterPVS (int cluster) +byte *CM_ClusterPVS (int cluster) { if (cluster == -1) memset (pvsrow, 0, (numclusters+7)>>3); + else CM_DecompressVis (map_visibility + map_vis->bitofs[cluster][DVIS_PVS], pvsrow); + return pvsrow; } @@ -1441,19 +1478,14 @@ byte *CM_ClusterPHS (int cluster) { if (cluster == -1) memset (phsrow, 0, (numclusters+7)>>3); + else CM_DecompressVis (map_visibility + map_vis->bitofs[cluster][DVIS_PHS], phsrow); + return phsrow; } - -/* -=============================================================================== - -AREAPORTALS - -=============================================================================== -*/ +/* AREAPORTALS */ void FloodArea_r (carea_t *area, int floodnum) { @@ -1464,12 +1496,14 @@ void FloodArea_r (carea_t *area, int floodnum) { if (area->floodnum == floodnum) return; + Com_Error (ERR_DROP, "FloodArea_r: reflooded"); } area->floodnum = floodnum; area->floodvalid = floodvalid; p = &map_areaportals[area->firstareaportal]; + for (i=0 ; inumareaportals ; i++, p++) { if (portalopen[p->portalnum]) @@ -1477,36 +1511,31 @@ void FloodArea_r (carea_t *area, int floodnum) } } -/* -==================== -FloodAreaConnections - - -==================== -*/ -void FloodAreaConnections (void) +void FloodAreaConnections (void) { int i; carea_t *area; int floodnum; - // all current floods are now invalid + /* all current floods are now invalid */ floodvalid++; floodnum = 0; - // area 0 is not used + /* area 0 is not used */ for (i=1 ; ifloodvalid == floodvalid) - continue; // already flooded into + continue; /* already flooded into */ + floodnum++; FloodArea_r (area, floodnum); } } -void CM_SetAreaPortalState (int portalnum, qboolean open) +void CM_SetAreaPortalState (int portalnum, qboolean open) { if (portalnum > numareaportals) Com_Error (ERR_DROP, "areaportal > numareaportals"); @@ -1515,7 +1544,7 @@ void CM_SetAreaPortalState (int portalnum, qboolean open) FloodAreaConnections (); } -qboolean CM_AreasConnected (int area1, int area2) +qboolean CM_AreasConnected (int area1, int area2) { if (map_noareas->value) return true; @@ -1525,20 +1554,16 @@ qboolean CM_AreasConnected (int area1, int area2) if (map_areas[area1].floodnum == map_areas[area2].floodnum) return true; + return false; } - /* -================= -CM_WriteAreaBits - -Writes a length byte followed by a bit vector of all the areas -that area in the same flood as the area parameter - -This is used by the client refreshes to cull visibility -================= -*/ + * Writes a length byte followed by a bit vector of all the areas + * that area in the same flood as the area parameter + * + * This is used by the client refreshes to cull visibility + */ int CM_WriteAreaBits (byte *buffer, int area) { int i; @@ -1548,14 +1573,17 @@ int CM_WriteAreaBits (byte *buffer, int area) bytes = (numareas+7)>>3; if (map_noareas->value) - { // for debugging, send everything + { + /* for debugging, send everything */ memset (buffer, 255, bytes); } + else { memset (buffer, 0, bytes); floodnum = map_areas[area].floodnum; + for (i=0 ; i>3] & (1<<(cluster&7))) return true; + return false; } node = &map_nodes[nodenum]; + if (CM_HeadnodeVisible(node->children[0], visbits)) return true; + return CM_HeadnodeVisible(node->children[1], visbits); } -