Quake II RTX doxygen  1.0 dev
cmodel.c File Reference
#include "shared/shared.h"
#include "common/bsp.h"
#include "common/cmd.h"
#include "common/cmodel.h"
#include "common/common.h"
#include "common/cvar.h"
#include "common/math.h"
#include "common/zone.h"
#include "system/hunk.h"

Go to the source code of this file.

Macros

#define DIST_EPSILON   (0.03125)
 

Functions

static void FloodAreaConnections (cm_t *cm)
 
void CM_FreeMap (cm_t *cm)
 
qerror_t CM_LoadMap (cm_t *cm, const char *name)
 
mnode_t * CM_NodeNum (cm_t *cm, int number)
 
mleaf_t * CM_LeafNum (cm_t *cm, int number)
 
static void CM_InitBoxHull (void)
 
mnode_t * CM_HeadnodeForBox (vec3_t mins, vec3_t maxs)
 
mleaf_t * CM_PointLeaf (cm_t *cm, vec3_t p)
 
static void CM_BoxLeafs_r (mnode_t *node)
 
static int CM_BoxLeafs_headnode (vec3_t mins, vec3_t maxs, mleaf_t **list, int listsize, mnode_t *headnode, mnode_t **topnode)
 
int CM_BoxLeafs (cm_t *cm, vec3_t mins, vec3_t maxs, mleaf_t **list, int listsize, mnode_t **topnode)
 
int CM_PointContents (vec3_t p, mnode_t *headnode)
 
int CM_TransformedPointContents (vec3_t p, mnode_t *headnode, vec3_t origin, vec3_t angles)
 
static void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2, trace_t *trace, mbrush_t *brush)
 
static void CM_TestBoxInBrush (vec3_t mins, vec3_t maxs, vec3_t p1, trace_t *trace, mbrush_t *brush)
 
static void CM_TraceToLeaf (mleaf_t *leaf)
 
static void CM_TestInLeaf (mleaf_t *leaf)
 
static void CM_RecursiveHullCheck (mnode_t *node, float p1f, float p2f, vec3_t p1, vec3_t p2)
 
void CM_BoxTrace (trace_t *trace, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, mnode_t *headnode, int brushmask)
 
void CM_TransformedBoxTrace (trace_t *trace, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, mnode_t *headnode, int brushmask, vec3_t origin, vec3_t angles)
 
void CM_ClipEntity (trace_t *dst, const trace_t *src, struct edict_s *ent)
 
static void FloodArea_r (cm_t *cm, int number, int floodnum)
 
void CM_SetAreaPortalState (cm_t *cm, int portalnum, qboolean open)
 
qboolean CM_AreasConnected (cm_t *cm, int area1, int area2)
 
int CM_WriteAreaBits (cm_t *cm, byte *buffer, int area)
 
int CM_WritePortalBits (cm_t *cm, byte *buffer)
 
void CM_SetPortalStates (cm_t *cm, byte *buffer, int bytes)
 
qboolean CM_HeadnodeVisible (mnode_t *node, byte *visbits)
 
byte * CM_FatPVS (cm_t *cm, byte *mask, const vec3_t org, int vis)
 
void CM_Init (void)
 

Variables

mtexinfo_t nulltexinfo
 
static mleaf_t nullleaf
 
static int floodvalid
 
static int checkcount
 
static cvar_t * map_noareas
 
static cvar_t * map_allsolid_bug
 
static cplane_t box_planes [12]
 
static mnode_t box_nodes [6]
 
static mnode_t * box_headnode
 
static mbrush_t box_brush
 
static mbrush_t * box_leafbrush
 
static mbrushside_t box_brushsides [6]
 
static mleaf_t box_leaf
 
static mleaf_t box_emptyleaf
 
static int leaf_count
 
static int leaf_maxcount
 
static mleaf_t ** leaf_list
 
static float * leaf_mins
 
static float * leaf_maxs
 
static mnode_t * leaf_topnode
 
static vec3_t trace_start
 
static vec3_t trace_end
 
static vec3_t trace_mins
 
static vec3_t trace_maxs
 
static vec3_t trace_extents
 
static trace_t * trace_trace
 
static int trace_contents
 
static qboolean trace_ispoint
 

Macro Definition Documentation

◆ DIST_EPSILON

#define DIST_EPSILON   (0.03125)

Definition at line 350 of file cmodel.c.

Function Documentation

◆ CM_AreasConnected()

qboolean CM_AreasConnected ( cm_t *  cm,
int  area1,
int  area2 
)

Definition at line 890 of file cmodel.c.

891 {
892  bsp_t *cache = cm->cache;
893 
894  if (!cache) {
895  return qfalse;
896  }
897  if (map_noareas->integer) {
898  return qtrue;
899  }
900  if (area1 < 1 || area2 < 1) {
901  return qfalse;
902  }
903  if (area1 >= cache->numareas || area2 >= cache->numareas) {
904  Com_EPrintf("%s: area > numareas\n", __func__);
905  return qfalse;
906  }
907  if (cm->floodnums[area1] == cm->floodnums[area2]) {
908  return qtrue;
909  }
910 
911  return qfalse;
912 }

Referenced by MVD_ParseMulticast(), MVD_ParseSound(), PF_AreasConnected(), PF_inVIS(), PF_StartSound(), SV_BuildClientFrame(), and SV_Multicast().

◆ CM_BoxLeafs()

int CM_BoxLeafs ( cm_t *  cm,
vec3_t  mins,
vec3_t  maxs,
mleaf_t **  list,
int  listsize,
mnode_t **  topnode 
)

Definition at line 273 of file cmodel.c.

274 {
275  if (!cm->cache) // map not loaded
276  return 0;
277  return CM_BoxLeafs_headnode(mins, maxs, list,
278  listsize, cm->cache->nodes, topnode);
279 }

Referenced by CM_FatPVS(), and SV_LinkEdict().

◆ CM_BoxLeafs_headnode()

static int CM_BoxLeafs_headnode ( vec3_t  mins,
vec3_t  maxs,
mleaf_t **  list,
int  listsize,
mnode_t *  headnode,
mnode_t **  topnode 
)
static

Definition at line 254 of file cmodel.c.

256 {
257  leaf_list = list;
258  leaf_count = 0;
259  leaf_maxcount = listsize;
260  leaf_mins = mins;
261  leaf_maxs = maxs;
262 
263  leaf_topnode = NULL;
264 
265  CM_BoxLeafs_r(headnode);
266 
267  if (topnode)
268  *topnode = leaf_topnode;
269 
270  return leaf_count;
271 }

Referenced by CM_BoxLeafs(), and CM_BoxTrace().

◆ CM_BoxLeafs_r()

static void CM_BoxLeafs_r ( mnode_t *  node)
static

Definition at line 229 of file cmodel.c.

230 {
231  int s;
232 
233  while (node->plane) {
234  s = BoxOnPlaneSideFast(leaf_mins, leaf_maxs, node->plane);
235  if (s == 1) {
236  node = node->children[0];
237  } else if (s == 2) {
238  node = node->children[1];
239  } else {
240  // go down both
241  if (!leaf_topnode) {
242  leaf_topnode = node;
243  }
244  CM_BoxLeafs_r(node->children[0]);
245  node = node->children[1];
246  }
247  }
248 
249  if (leaf_count < leaf_maxcount) {
250  leaf_list[leaf_count++] = (mleaf_t *)node;
251  }
252 }

Referenced by CM_BoxLeafs_headnode().

◆ CM_BoxTrace()

void CM_BoxTrace ( trace_t *  trace,
vec3_t  start,
vec3_t  end,
vec3_t  mins,
vec3_t  maxs,
mnode_t *  headnode,
int  brushmask 
)

Definition at line 683 of file cmodel.c.

686 {
687  checkcount++; // for multi-check avoidance
688 
689  // fill in a default trace
690  trace_trace = trace;
691  memset(trace_trace, 0, sizeof(*trace_trace));
692  trace_trace->fraction = 1;
693  trace_trace->surface = &(nulltexinfo.c);
694 
695  if (!headnode) {
696  return;
697  }
698 
699  trace_contents = brushmask;
700  VectorCopy(start, trace_start);
701  VectorCopy(end, trace_end);
702  VectorCopy(mins, trace_mins);
703  VectorCopy(maxs, trace_maxs);
704 
705  //
706  // check for position test special case
707  //
708  if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2]) {
709  mleaf_t *leafs[1024];
710  int i, numleafs;
711  vec3_t c1, c2;
712 
713  VectorAdd(start, mins, c1);
714  VectorAdd(start, maxs, c2);
715  for (i = 0; i < 3; i++) {
716  c1[i] -= 1;
717  c2[i] += 1;
718  }
719 
720  numleafs = CM_BoxLeafs_headnode(c1, c2, leafs, 1024, headnode, NULL);
721  for (i = 0; i < numleafs; i++) {
722  CM_TestInLeaf(leafs[i]);
723  if (trace_trace->allsolid)
724  break;
725  }
726  VectorCopy(start, trace_trace->endpos);
727  return;
728  }
729 
730  //
731  // check for point special case
732  //
733  if (mins[0] == 0 && mins[1] == 0 && mins[2] == 0
734  && maxs[0] == 0 && maxs[1] == 0 && maxs[2] == 0) {
735  trace_ispoint = qtrue;
736  VectorClear(trace_extents);
737  } else {
738  trace_ispoint = qfalse;
739  trace_extents[0] = -mins[0] > maxs[0] ? -mins[0] : maxs[0];
740  trace_extents[1] = -mins[1] > maxs[1] ? -mins[1] : maxs[1];
741  trace_extents[2] = -mins[2] > maxs[2] ? -mins[2] : maxs[2];
742  }
743 
744  //
745  // general sweeping through world
746  //
747  CM_RecursiveHullCheck(headnode, 0, 1, start, end);
748 
749  if (trace_trace->fraction == 1)
750  VectorCopy(end, trace_trace->endpos);
751  else
752  LerpVector(start, end, trace_trace->fraction, trace_trace->endpos);
753 }

Referenced by CL_AddViewWeapon(), CL_SetupThirdPersionView(), CL_Trace(), CM_TransformedBoxTrace(), LOC_FindClosest(), LOC_There_m(), MVD_HitPlayer(), and SV_Trace().

◆ CM_ClipBoxToBrush()

static void CM_ClipBoxToBrush ( vec3_t  mins,
vec3_t  maxs,
vec3_t  p1,
vec3_t  p2,
trace_t *  trace,
mbrush_t *  brush 
)
static

Definition at line 365 of file cmodel.c.

367 {
368  int i, j;
369  cplane_t *plane, *clipplane;
370  float dist;
371  float enterfrac, leavefrac;
372  vec3_t ofs;
373  float d1, d2;
374  qboolean getout, startout;
375  float f;
376  mbrushside_t *side, *leadside;
377 
378  enterfrac = -1;
379  leavefrac = 1;
380  clipplane = NULL;
381 
382  if (!brush->numsides)
383  return;
384 
385  getout = qfalse;
386  startout = qfalse;
387  leadside = NULL;
388 
389  side = brush->firstbrushside;
390  for (i = 0; i < brush->numsides; i++, side++) {
391  plane = side->plane;
392 
393  // FIXME: special case for axial
394 
395  if (!trace_ispoint) {
396  // general box case
397 
398  // push the plane out apropriately for mins/maxs
399 
400  // FIXME: use signbits into 8 way lookup for each mins/maxs
401  for (j = 0; j < 3; j++) {
402  if (plane->normal[j] < 0)
403  ofs[j] = maxs[j];
404  else
405  ofs[j] = mins[j];
406  }
407  dist = DotProduct(ofs, plane->normal);
408  dist = plane->dist - dist;
409  } else {
410  // special point case
411  dist = plane->dist;
412  }
413 
414  d1 = DotProduct(p1, plane->normal) - dist;
415  d2 = DotProduct(p2, plane->normal) - dist;
416 
417  if (d2 > 0)
418  getout = qtrue; // endpoint is not in solid
419  if (d1 > 0)
420  startout = qtrue;
421 
422  // if completely in front of face, no intersection
423  if (d1 > 0 && d2 >= d1)
424  return;
425 
426  if (d1 <= 0 && d2 <= 0)
427  continue;
428 
429  // crosses face
430  if (d1 > d2) {
431  // enter
432  f = (d1 - DIST_EPSILON) / (d1 - d2);
433  if (f > enterfrac) {
434  enterfrac = f;
435  clipplane = plane;
436  leadside = side;
437  }
438  } else {
439  // leave
440  f = (d1 + DIST_EPSILON) / (d1 - d2);
441  if (f < leavefrac)
442  leavefrac = f;
443  }
444  }
445 
446  if (!startout) {
447  // original point was inside brush
448  trace->startsolid = qtrue;
449  if (!getout) {
450  trace->allsolid = qtrue;
451  if (!map_allsolid_bug->integer) {
452  // original Q2 didn't set these
453  trace->fraction = 0;
454  trace->contents = brush->contents;
455  }
456  }
457  return;
458  }
459  if (enterfrac < leavefrac) {
460  if (enterfrac > -1 && enterfrac < trace->fraction) {
461  if (enterfrac < 0)
462  enterfrac = 0;
463  trace->fraction = enterfrac;
464  trace->plane = *clipplane;
465  trace->surface = &(leadside->texinfo->c);
466  trace->contents = brush->contents;
467  }
468  }
469 }

Referenced by CM_TraceToLeaf().

◆ CM_ClipEntity()

void CM_ClipEntity ( trace_t *  dst,
const trace_t *  src,
struct edict_s ent 
)

Definition at line 804 of file cmodel.c.

805 {
806  dst->allsolid |= src->allsolid;
807  dst->startsolid |= src->startsolid;
808  if (src->fraction < dst->fraction) {
809  dst->fraction = src->fraction;
810  VectorCopy(src->endpos, dst->endpos);
811  dst->plane = src->plane;
812  dst->surface = src->surface;
813  dst->contents |= src->contents;
814  dst->ent = ent;
815  }
816 }

Referenced by CL_ClipMoveToEntities(), and SV_ClipMoveToEntities().

◆ CM_FatPVS()

byte* CM_FatPVS ( cm_t *  cm,
byte *  mask,
const vec3_t  org,
int  vis 
)

Definition at line 1045 of file cmodel.c.

1046 {
1047  byte temp[VIS_MAX_BYTES];
1048  mleaf_t *leafs[64];
1049  int clusters[64];
1050  int i, j, count, longs;
1051  uint_fast32_t *src, *dst;
1052  vec3_t mins, maxs;
1053 
1054  if (!cm->cache) { // map not loaded
1055  return memset(mask, 0, VIS_MAX_BYTES);
1056  }
1057  if (!cm->cache->vis) {
1058  return memset(mask, 0xff, VIS_MAX_BYTES);
1059  }
1060 
1061  for (i = 0; i < 3; i++) {
1062  mins[i] = org[i] - 8;
1063  maxs[i] = org[i] + 8;
1064  }
1065 
1066  count = CM_BoxLeafs(cm, mins, maxs, leafs, 64, NULL);
1067  if (count < 1)
1068  Com_Error(ERR_DROP, "CM_FatPVS: leaf count < 1");
1069  longs = VIS_FAST_LONGS(cm->cache);
1070 
1071  // convert leafs to clusters
1072  for (i = 0; i < count; i++) {
1073  clusters[i] = leafs[i]->cluster;
1074  }
1075 
1076  BSP_ClusterVis(cm->cache, mask, clusters[0], vis);
1077 
1078  // or in all the other leaf bits
1079  for (i = 1; i < count; i++) {
1080  for (j = 0; j < i; j++) {
1081  if (clusters[i] == clusters[j]) {
1082  goto nextleaf; // already have the cluster we want
1083  }
1084  }
1085  src = (uint_fast32_t *)BSP_ClusterVis(cm->cache, temp, clusters[i], vis);
1086  dst = (uint_fast32_t *)mask;
1087  for (j = 0; j < longs; j++) {
1088  *dst++ |= *src++;
1089  }
1090 
1091 nextleaf:;
1092  }
1093 
1094  return mask;
1095 }

Referenced by SV_BuildClientFrame().

◆ CM_FreeMap()

void CM_FreeMap ( cm_t *  cm)

Definition at line 47 of file cmodel.c.

48 {
49  if (cm->floodnums) {
50  Z_Free(cm->floodnums);
51  }
52  BSP_Free(cm->cache);
53 
54  memset(cm, 0, sizeof(*cm));
55 }

Referenced by abort_func(), MVD_ClearState(), MVD_Free(), MVD_ParseServerData(), SV_InitGame(), SV_Shutdown(), and SV_SpawnServer().

◆ CM_HeadnodeForBox()

mnode_t* CM_HeadnodeForBox ( vec3_t  mins,
vec3_t  maxs 
)

Definition at line 190 of file cmodel.c.

191 {
192  box_planes[0].dist = maxs[0];
193  box_planes[1].dist = -maxs[0];
194  box_planes[2].dist = mins[0];
195  box_planes[3].dist = -mins[0];
196  box_planes[4].dist = maxs[1];
197  box_planes[5].dist = -maxs[1];
198  box_planes[6].dist = mins[1];
199  box_planes[7].dist = -mins[1];
200  box_planes[8].dist = maxs[2];
201  box_planes[9].dist = -maxs[2];
202  box_planes[10].dist = mins[2];
203  box_planes[11].dist = -mins[2];
204 
205  return box_headnode;
206 }

Referenced by CL_ClipMoveToEntities(), MVD_HitPlayer(), and SV_HullForEntity().

◆ CM_HeadnodeVisible()

qboolean CM_HeadnodeVisible ( mnode_t *  node,
byte *  visbits 
)

Definition at line 1016 of file cmodel.c.

1017 {
1018  mleaf_t *leaf;
1019  int cluster;
1020 
1021  while (node->plane) {
1022  if (CM_HeadnodeVisible(node->children[0], visbits))
1023  return qtrue;
1024  node = node->children[1];
1025  }
1026 
1027  leaf = (mleaf_t *)node;
1028  cluster = leaf->cluster;
1029  if (cluster == -1)
1030  return qfalse;
1031  if (Q_IsBitSet(visbits, cluster))
1032  return qtrue;
1033  return qfalse;
1034 }

Referenced by SV_EdictIsVisible().

◆ CM_Init()

void CM_Init ( void  )

Definition at line 1102 of file cmodel.c.

1103 {
1104  CM_InitBoxHull();
1105 
1106  nullleaf.cluster = -1;
1107 
1108  map_noareas = Cvar_Get("map_noareas", "0", 0);
1109  map_allsolid_bug = Cvar_Get("map_allsolid_bug", "1", 0);
1110 }

Referenced by Qcommon_Init().

◆ CM_InitBoxHull()

static void CM_InitBoxHull ( void  )
static

Definition at line 129 of file cmodel.c.

130 {
131  int i;
132  int side;
133  mnode_t *c;
134  cplane_t *p;
135  mbrushside_t *s;
136 
137  box_headnode = &box_nodes[0];
138 
139  box_brush.numsides = 6;
140  box_brush.firstbrushside = &box_brushsides[0];
141  box_brush.contents = CONTENTS_MONSTER;
142 
143  box_leaf.contents = CONTENTS_MONSTER;
144  box_leaf.firstleafbrush = &box_leafbrush;
145  box_leaf.numleafbrushes = 1;
146 
148 
149  for (i = 0; i < 6; i++) {
150  side = i & 1;
151 
152  // brush sides
153  s = &box_brushsides[i];
154  s->plane = &box_planes[i * 2 + side];
155  s->texinfo = &nulltexinfo;
156 
157  // nodes
158  c = &box_nodes[i];
159  c->plane = &box_planes[i * 2];
160  c->children[side] = (mnode_t *)&box_emptyleaf;
161  if (i != 5)
162  c->children[side ^ 1] = &box_nodes[i + 1];
163  else
164  c->children[side ^ 1] = (mnode_t *)&box_leaf;
165 
166  // planes
167  p = &box_planes[i * 2];
168  p->type = i >> 1;
169  p->signbits = 0;
170  VectorClear(p->normal);
171  p->normal[i >> 1] = 1;
172 
173  p = &box_planes[i * 2 + 1];
174  p->type = 3 + (i >> 1);
175  p->signbits = 0;
176  VectorClear(p->normal);
177  p->normal[i >> 1] = -1;
178  }
179 }

Referenced by CM_Init().

◆ CM_LeafNum()

mleaf_t* CM_LeafNum ( cm_t *  cm,
int  number 
)

Definition at line 98 of file cmodel.c.

99 {
100  if (!cm->cache) {
101  return &nullleaf;
102  }
103  if (number < 0 || number >= cm->cache->numleafs) {
104  Com_EPrintf("%s: bad number: %d\n", __func__, number);
105  return &nullleaf;
106  }
107  return cm->cache->leafs + number;
108 }

Referenced by MVD_ParseMulticast().

◆ CM_LoadMap()

qerror_t CM_LoadMap ( cm_t *  cm,
const char *  name 
)

Definition at line 64 of file cmodel.c.

65 {
66  bsp_t *cache;
67  qerror_t ret;
68 
69  ret = BSP_Load(name, &cache);
70  if (!cache) {
71  return ret;
72  }
73 
74  cm->cache = cache;
75  cm->floodnums = Z_TagMallocz(sizeof(int) * cm->cache->numareas +
76  sizeof(qboolean) * (cm->cache->lastareaportal + 1), TAG_CMODEL);
77  cm->portalopen = (qboolean *)(cm->floodnums + cm->cache->numareas);
79 
80  return Q_ERR_SUCCESS;
81 }

Referenced by MVD_ParseServerData(), and SV_ParseMapCmd().

◆ CM_NodeNum()

mnode_t* CM_NodeNum ( cm_t *  cm,
int  number 
)

Definition at line 83 of file cmodel.c.

84 {
85  if (!cm->cache) {
86  return (mnode_t *)&nullleaf;
87  }
88  if (number == -1) {
89  return (mnode_t *)cm->cache->leafs; // special case for solid leaf
90  }
91  if (number < 0 || number >= cm->cache->numnodes) {
92  Com_EPrintf("%s: bad number: %d\n", __func__, number);
93  return (mnode_t *)&nullleaf;
94  }
95  return cm->cache->nodes + number;
96 }

Referenced by SV_EdictIsVisible().

◆ CM_PointContents()

int CM_PointContents ( vec3_t  p,
mnode_t *  headnode 
)

Definition at line 289 of file cmodel.c.

290 {
291  mleaf_t *leaf;
292 
293  if (!headnode) {
294  return 0;
295  }
296 
297  leaf = BSP_PointLeaf(headnode, p);
298 
299  return leaf->contents;
300 }

Referenced by CL_PointContents(), and SV_PointContents().

◆ CM_PointLeaf()

mleaf_t* CM_PointLeaf ( cm_t *  cm,
vec3_t  p 
)

Definition at line 209 of file cmodel.c.

210 {
211  if (!cm->cache) {
212  return &nullleaf; // server may call this without map loaded
213  }
214  return BSP_PointLeaf(cm->cache->nodes, p);
215 }

Referenced by MVD_ParseMulticast(), MVD_ParseSound(), PF_StartSound(), SV_BuildClientFrame(), and SV_Multicast().

◆ CM_RecursiveHullCheck()

static void CM_RecursiveHullCheck ( mnode_t *  node,
float  p1f,
float  p2f,
vec3_t  p1,
vec3_t  p2 
)
static

Definition at line 590 of file cmodel.c.

591 {
592  cplane_t *plane;
593  float t1, t2, offset;
594  float frac, frac2;
595  float idist;
596  vec3_t mid;
597  int side;
598  float midf;
599 
600  if (trace_trace->fraction <= p1f)
601  return; // already hit something nearer
602 
603 recheck:
604  // if plane is NULL, we are in a leaf node
605  plane = node->plane;
606  if (!plane) {
607  CM_TraceToLeaf((mleaf_t *)node);
608  return;
609  }
610 
611  //
612  // find the point distances to the seperating plane
613  // and the offset for the size of the box
614  //
615  if (plane->type < 3) {
616  t1 = p1[plane->type] - plane->dist;
617  t2 = p2[plane->type] - plane->dist;
618  offset = trace_extents[plane->type];
619  } else {
620  t1 = PlaneDiff(p1, plane);
621  t2 = PlaneDiff(p2, plane);
622  if (trace_ispoint)
623  offset = 0;
624  else
625  offset = fabs(trace_extents[0] * plane->normal[0]) +
626  fabs(trace_extents[1] * plane->normal[1]) +
627  fabs(trace_extents[2] * plane->normal[2]);
628  }
629 
630  // see which sides we need to consider
631  if (t1 >= offset && t2 >= offset) {
632  node = node->children[0];
633  goto recheck;
634  }
635  if (t1 < -offset && t2 < -offset) {
636  node = node->children[1];
637  goto recheck;
638  }
639 
640  // put the crosspoint DIST_EPSILON pixels on the near side
641  if (t1 < t2) {
642  idist = 1.0 / (t1 - t2);
643  side = 1;
644  frac2 = (t1 + offset + DIST_EPSILON) * idist;
645  frac = (t1 - offset + DIST_EPSILON) * idist;
646  } else if (t1 > t2) {
647  idist = 1.0 / (t1 - t2);
648  side = 0;
649  frac2 = (t1 - offset - DIST_EPSILON) * idist;
650  frac = (t1 + offset + DIST_EPSILON) * idist;
651  } else {
652  side = 0;
653  frac = 1;
654  frac2 = 0;
655  }
656 
657  // move up to the node
658  clamp(frac, 0, 1);
659 
660  midf = p1f + (p2f - p1f) * frac;
661  LerpVector(p1, p2, frac, mid);
662 
663  CM_RecursiveHullCheck(node->children[side], p1f, midf, p1, mid);
664 
665  // go past the node
666  clamp(frac2, 0, 1);
667 
668  midf = p1f + (p2f - p1f) * frac2;
669  LerpVector(p1, p2, frac2, mid);
670 
671  CM_RecursiveHullCheck(node->children[side ^ 1], midf, p2f, mid, p2);
672 }

Referenced by CM_BoxTrace().

◆ CM_SetAreaPortalState()

void CM_SetAreaPortalState ( cm_t *  cm,
int  portalnum,
qboolean  open 
)

Definition at line 869 of file cmodel.c.

870 {
871  if (!cm->cache) {
872  return;
873  }
874 
875  if (portalnum < 0 || portalnum >= MAX_MAP_AREAPORTALS) {
876  Com_EPrintf("%s: portalnum %d is out of range\n", __func__, portalnum);
877  return;
878  }
879 
880  // ignore areaportals not referenced by areas
881  if (portalnum > cm->cache->lastareaportal) {
882  Com_DPrintf("%s: portalnum %d is not in use\n", __func__, portalnum);
883  return;
884  }
885 
886  cm->portalopen[portalnum] = open;
888 }

Referenced by PF_SetAreaPortalState().

◆ CM_SetPortalStates()

void CM_SetPortalStates ( cm_t *  cm,
byte *  buffer,
int  bytes 
)

Definition at line 982 of file cmodel.c.

983 {
984  int i, numportals;
985 
986  if (!cm->cache) {
987  return;
988  }
989 
990  if (!bytes) {
991  for (i = 0; i <= cm->cache->lastareaportal; i++) {
992  cm->portalopen[i] = qtrue;
993  }
994  } else {
995  numportals = bytes << 3;
996  if (numportals > cm->cache->lastareaportal + 1) {
997  numportals = cm->cache->lastareaportal + 1;
998  }
999  for (i = 0; i < numportals; i++) {
1000  cm->portalopen[i] = Q_IsBitSet(buffer, i);
1001  }
1002  }
1003 
1005 }

Referenced by MVD_ParseFrame(), MVD_Seek_f(), and read_level_file().

◆ CM_TestBoxInBrush()

static void CM_TestBoxInBrush ( vec3_t  mins,
vec3_t  maxs,
vec3_t  p1,
trace_t *  trace,
mbrush_t *  brush 
)
static

Definition at line 476 of file cmodel.c.

478 {
479  int i, j;
480  cplane_t *plane;
481  float dist;
482  vec3_t ofs;
483  float d1;
484  mbrushside_t *side;
485 
486  if (!brush->numsides)
487  return;
488 
489  side = brush->firstbrushside;
490  for (i = 0; i < brush->numsides; i++, side++) {
491  plane = side->plane;
492 
493  // FIXME: special case for axial
494 
495  // general box case
496 
497  // push the plane out apropriately for mins/maxs
498 
499  // FIXME: use signbits into 8 way lookup for each mins/maxs
500  for (j = 0; j < 3; j++) {
501  if (plane->normal[j] < 0)
502  ofs[j] = maxs[j];
503  else
504  ofs[j] = mins[j];
505  }
506  dist = DotProduct(ofs, plane->normal);
507  dist = plane->dist - dist;
508 
509  d1 = DotProduct(p1, plane->normal) - dist;
510 
511  // if completely in front of face, no intersection
512  if (d1 > 0)
513  return;
514 
515  }
516 
517  // inside this brush
518  trace->startsolid = trace->allsolid = qtrue;
519  trace->fraction = 0;
520  trace->contents = brush->contents;
521 }

Referenced by CM_TestInLeaf().

◆ CM_TestInLeaf()

static void CM_TestInLeaf ( mleaf_t *  leaf)
static

Definition at line 559 of file cmodel.c.

560 {
561  int k;
562  mbrush_t *b, **leafbrush;
563 
564  if (!(leaf->contents & trace_contents))
565  return;
566  // trace line against all brushes in the leaf
567  leafbrush = leaf->firstleafbrush;
568  for (k = 0; k < leaf->numleafbrushes; k++, leafbrush++) {
569  b = *leafbrush;
570  if (b->checkcount == checkcount)
571  continue; // already checked this brush in another leaf
572  b->checkcount = checkcount;
573 
574  if (!(b->contents & trace_contents))
575  continue;
577  if (!trace_trace->fraction)
578  return;
579  }
580 
581 }

Referenced by CM_BoxTrace().

◆ CM_TraceToLeaf()

static void CM_TraceToLeaf ( mleaf_t *  leaf)
static

Definition at line 529 of file cmodel.c.

530 {
531  int k;
532  mbrush_t *b, **leafbrush;
533 
534  if (!(leaf->contents & trace_contents))
535  return;
536  // trace line against all brushes in the leaf
537  leafbrush = leaf->firstleafbrush;
538  for (k = 0; k < leaf->numleafbrushes; k++, leafbrush++) {
539  b = *leafbrush;
540  if (b->checkcount == checkcount)
541  continue; // already checked this brush in another leaf
542  b->checkcount = checkcount;
543 
544  if (!(b->contents & trace_contents))
545  continue;
547  if (!trace_trace->fraction)
548  return;
549  }
550 
551 }

Referenced by CM_RecursiveHullCheck().

◆ CM_TransformedBoxTrace()

void CM_TransformedBoxTrace ( trace_t *  trace,
vec3_t  start,
vec3_t  end,
vec3_t  mins,
vec3_t  maxs,
mnode_t *  headnode,
int  brushmask,
vec3_t  origin,
vec3_t  angles 
)

Definition at line 764 of file cmodel.c.

768 {
769  vec3_t start_l, end_l;
770  vec3_t axis[3];
771  qboolean rotated;
772 
773  // subtract origin offset
774  VectorSubtract(start, origin, start_l);
775  VectorSubtract(end, origin, end_l);
776 
777  // rotate start and end into the models frame of reference
778  if (headnode != box_headnode &&
779  (angles[0] || angles[1] || angles[2]))
780  rotated = qtrue;
781  else
782  rotated = qfalse;
783 
784  if (rotated) {
785  AnglesToAxis(angles, axis);
786  RotatePoint(start_l, axis);
787  RotatePoint(end_l, axis);
788  }
789 
790  // sweep the box through the model
791  CM_BoxTrace(trace, start_l, end_l, mins, maxs, headnode, brushmask);
792 
793  // rotate plane normal into the worlds frame of reference
794  if (rotated && trace->fraction != 1.0) {
795  TransposeAxis(axis);
796  RotatePoint(trace->plane.normal, axis);
797  }
798 
799  // FIXME: offset plane distance?
800 
801  LerpVector(start, end, trace->fraction, trace->endpos);
802 }

Referenced by CL_ClipMoveToEntities(), MVD_HitPlayer(), and SV_ClipMoveToEntities().

◆ CM_TransformedPointContents()

int CM_TransformedPointContents ( vec3_t  p,
mnode_t *  headnode,
vec3_t  origin,
vec3_t  angles 
)

Definition at line 310 of file cmodel.c.

311 {
312  vec3_t p_l;
313  vec3_t temp;
314  vec3_t forward, right, up;
315  mleaf_t *leaf;
316 
317  if (!headnode) {
318  return 0;
319  }
320 
321  // subtract origin offset
322  VectorSubtract(p, origin, p_l);
323 
324  // rotate start and end into the models frame of reference
325  if (headnode != box_headnode &&
326  (angles[0] || angles[1] || angles[2])) {
327  AngleVectors(angles, forward, right, up);
328 
329  VectorCopy(p_l, temp);
330  p_l[0] = DotProduct(temp, forward);
331  p_l[1] = -DotProduct(temp, right);
332  p_l[2] = DotProduct(temp, up);
333  }
334 
335  leaf = BSP_PointLeaf(headnode, p_l);
336 
337  return leaf->contents;
338 }

Referenced by CL_PointContents(), and SV_PointContents().

◆ CM_WriteAreaBits()

int CM_WriteAreaBits ( cm_t *  cm,
byte *  buffer,
int  area 
)

Definition at line 925 of file cmodel.c.

926 {
927  bsp_t *cache = cm->cache;
928  int i;
929  int floodnum;
930  int bytes;
931 
932  if (!cache) {
933  return 0;
934  }
935 
936  bytes = (cache->numareas + 7) >> 3;
937 
938  if (map_noareas->integer || !area) {
939  // for debugging, send everything
940  memset(buffer, 255, bytes);
941  } else {
942  memset(buffer, 0, bytes);
943 
944  floodnum = cm->floodnums[area];
945  for (i = 0; i < cache->numareas; i++) {
946  if (cm->floodnums[i] == floodnum) {
947  Q_SetBit(buffer, i);
948  }
949  }
950  }
951 
952  return bytes;
953 }

Referenced by SV_BuildClientFrame().

◆ CM_WritePortalBits()

int CM_WritePortalBits ( cm_t *  cm,
byte *  buffer 
)

Definition at line 955 of file cmodel.c.

956 {
957  int i, bytes, numportals;
958 
959  if (!cm->cache) {
960  return 0;
961  }
962 
963  numportals = cm->cache->lastareaportal + 1;
964  if (numportals > MAX_MAP_AREAS) {
965  /* HACK: use the same array size as areabytes!
966  * It is nonsense for a map to have > 256 areaportals anyway. */
967  Com_WPrintf("%s: too many areaportals\n", __func__);
968  numportals = MAX_MAP_AREAS;
969  }
970 
971  bytes = (numportals + 7) >> 3;
972  memset(buffer, 0, bytes);
973  for (i = 0; i < numportals; i++) {
974  if (cm->portalopen[i]) {
975  Q_SetBit(buffer, i);
976  }
977  }
978 
979  return bytes;
980 }

Referenced by emit_base_frame(), emit_frame(), emit_gamestate(), and write_level_file().

◆ FloodArea_r()

static void FloodArea_r ( cm_t *  cm,
int  number,
int  floodnum 
)
static

Definition at line 827 of file cmodel.c.

828 {
829  int i;
830  mareaportal_t *p;
831  marea_t *area;
832 
833  area = &cm->cache->areas[number];
834  if (area->floodvalid == floodvalid) {
835  if (cm->floodnums[number] == floodnum)
836  return;
837  Com_Error(ERR_DROP, "FloodArea_r: reflooded");
838  }
839 
840  cm->floodnums[number] = floodnum;
841  area->floodvalid = floodvalid;
842  p = area->firstareaportal;
843  for (i = 0; i < area->numareaportals; i++, p++) {
844  if (cm->portalopen[p->portalnum])
845  FloodArea_r(cm, p->otherarea, floodnum);
846  }
847 }

Referenced by FloodAreaConnections().

◆ FloodAreaConnections()

static void FloodAreaConnections ( cm_t *  cm)
static

Definition at line 849 of file cmodel.c.

850 {
851  int i;
852  marea_t *area;
853  int floodnum;
854 
855  // all current floods are now invalid
856  floodvalid++;
857  floodnum = 0;
858 
859  // area 0 is not used
860  for (i = 1; i < cm->cache->numareas; i++) {
861  area = &cm->cache->areas[i];
862  if (area->floodvalid == floodvalid)
863  continue; // already flooded into
864  floodnum++;
865  FloodArea_r(cm, i, floodnum);
866  }
867 }

Referenced by CM_LoadMap(), CM_SetAreaPortalState(), and CM_SetPortalStates().

Variable Documentation

◆ box_brush

mbrush_t box_brush
static

Definition at line 115 of file cmodel.c.

Referenced by CM_InitBoxHull().

◆ box_brushsides

mbrushside_t box_brushsides[6]
static

Definition at line 117 of file cmodel.c.

Referenced by CM_InitBoxHull().

◆ box_emptyleaf

mleaf_t box_emptyleaf
static

Definition at line 119 of file cmodel.c.

Referenced by CM_InitBoxHull().

◆ box_headnode

mnode_t* box_headnode
static

◆ box_leaf

mleaf_t box_leaf
static

Definition at line 118 of file cmodel.c.

Referenced by CM_InitBoxHull().

◆ box_leafbrush

mbrush_t* box_leafbrush
static

Definition at line 116 of file cmodel.c.

Referenced by CM_InitBoxHull().

◆ box_nodes

mnode_t box_nodes[6]
static

Definition at line 113 of file cmodel.c.

Referenced by CM_InitBoxHull().

◆ box_planes

cplane_t box_planes[12]
static

Definition at line 112 of file cmodel.c.

Referenced by CM_HeadnodeForBox(), and CM_InitBoxHull().

◆ checkcount

int checkcount
static

Definition at line 35 of file cmodel.c.

Referenced by CM_BoxTrace(), CM_TestInLeaf(), and CM_TraceToLeaf().

◆ floodvalid

int floodvalid
static

Definition at line 34 of file cmodel.c.

Referenced by FloodArea_r(), and FloodAreaConnections().

◆ leaf_count

int leaf_count
static

Definition at line 224 of file cmodel.c.

Referenced by CM_BoxLeafs_headnode(), and CM_BoxLeafs_r().

◆ leaf_list

mleaf_t** leaf_list
static

Definition at line 225 of file cmodel.c.

Referenced by CM_BoxLeafs_headnode(), and CM_BoxLeafs_r().

◆ leaf_maxcount

int leaf_maxcount
static

Definition at line 224 of file cmodel.c.

Referenced by CM_BoxLeafs_headnode(), and CM_BoxLeafs_r().

◆ leaf_maxs

float * leaf_maxs
static

Definition at line 226 of file cmodel.c.

Referenced by CM_BoxLeafs_headnode(), and CM_BoxLeafs_r().

◆ leaf_mins

float* leaf_mins
static

Definition at line 226 of file cmodel.c.

Referenced by CM_BoxLeafs_headnode(), and CM_BoxLeafs_r().

◆ leaf_topnode

mnode_t* leaf_topnode
static

Definition at line 227 of file cmodel.c.

Referenced by CM_BoxLeafs_headnode(), and CM_BoxLeafs_r().

◆ map_allsolid_bug

cvar_t* map_allsolid_bug
static

Definition at line 38 of file cmodel.c.

Referenced by CM_ClipBoxToBrush(), and CM_Init().

◆ map_noareas

cvar_t* map_noareas
static

Definition at line 37 of file cmodel.c.

Referenced by CM_AreasConnected(), CM_Init(), and CM_WriteAreaBits().

◆ nullleaf

mleaf_t nullleaf
static

Definition at line 32 of file cmodel.c.

Referenced by CM_Init(), CM_LeafNum(), CM_NodeNum(), and CM_PointLeaf().

◆ nulltexinfo

mtexinfo_t nulltexinfo

Definition at line 30 of file cmodel.c.

Referenced by CM_BoxTrace(), CM_InitBoxHull(), and LOAD().

◆ trace_contents

int trace_contents
static

Definition at line 357 of file cmodel.c.

Referenced by CM_BoxTrace(), CM_TestInLeaf(), and CM_TraceToLeaf().

◆ trace_end

vec3_t trace_end
static

Definition at line 352 of file cmodel.c.

Referenced by CM_BoxTrace(), and CM_TraceToLeaf().

◆ trace_extents

vec3_t trace_extents
static

Definition at line 354 of file cmodel.c.

Referenced by CM_BoxTrace(), and CM_RecursiveHullCheck().

◆ trace_ispoint

qboolean trace_ispoint
static

Definition at line 358 of file cmodel.c.

Referenced by CM_BoxTrace(), CM_ClipBoxToBrush(), and CM_RecursiveHullCheck().

◆ trace_maxs

vec3_t trace_maxs
static

Definition at line 353 of file cmodel.c.

Referenced by CM_BoxTrace(), CM_TestInLeaf(), and CM_TraceToLeaf().

◆ trace_mins

vec3_t trace_mins
static

Definition at line 353 of file cmodel.c.

Referenced by CM_BoxTrace(), CM_TestInLeaf(), and CM_TraceToLeaf().

◆ trace_start

vec3_t trace_start
static

Definition at line 352 of file cmodel.c.

Referenced by CM_BoxTrace(), CM_TestInLeaf(), and CM_TraceToLeaf().

◆ trace_trace

trace_t* trace_trace
static

Definition at line 356 of file cmodel.c.

Referenced by CM_BoxTrace(), CM_RecursiveHullCheck(), CM_TestInLeaf(), and CM_TraceToLeaf().

CM_BoxTrace
void CM_BoxTrace(trace_t *trace, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, mnode_t *headnode, int brushmask)
Definition: cmodel.c:683
CM_HeadnodeVisible
qboolean CM_HeadnodeVisible(mnode_t *node, byte *visbits)
Definition: cmodel.c:1016
trace_start
static vec3_t trace_start
Definition: cmodel.c:352
CM_TestBoxInBrush
static void CM_TestBoxInBrush(vec3_t mins, vec3_t maxs, vec3_t p1, trace_t *trace, mbrush_t *brush)
Definition: cmodel.c:476
leaf_list
static mleaf_t ** leaf_list
Definition: cmodel.c:225
leaf_count
static int leaf_count
Definition: cmodel.c:224
CM_ClipBoxToBrush
static void CM_ClipBoxToBrush(vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2, trace_t *trace, mbrush_t *brush)
Definition: cmodel.c:365
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
BSP_ClusterVis
byte * BSP_ClusterVis(bsp_t *bsp, byte *mask, int cluster, int vis)
Definition: bsp.c:1339
box_brush
static mbrush_t box_brush
Definition: cmodel.c:115
box_emptyleaf
static mleaf_t box_emptyleaf
Definition: cmodel.c:119
CM_RecursiveHullCheck
static void CM_RecursiveHullCheck(mnode_t *node, float p1f, float p2f, vec3_t p1, vec3_t p2)
Definition: cmodel.c:590
CM_BoxLeafs
int CM_BoxLeafs(cm_t *cm, vec3_t mins, vec3_t maxs, mleaf_t **list, int listsize, mnode_t **topnode)
Definition: cmodel.c:273
leaf_maxcount
static int leaf_maxcount
Definition: cmodel.c:224
trace_extents
static vec3_t trace_extents
Definition: cmodel.c:354
BSP_PointLeaf
mleaf_t * BSP_PointLeaf(mnode_t *node, vec3_t p)
Definition: bsp.c:1439
FloodArea_r
static void FloodArea_r(cm_t *cm, int number, int floodnum)
Definition: cmodel.c:827
trace_ispoint
static qboolean trace_ispoint
Definition: cmodel.c:358
trace_end
static vec3_t trace_end
Definition: cmodel.c:352
trace_maxs
static vec3_t trace_maxs
Definition: cmodel.c:353
floodvalid
static int floodvalid
Definition: cmodel.c:34
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
BSP_Free
void BSP_Free(bsp_t *bsp)
Definition: bsp.c:932
forward
static vec3_t forward
Definition: p_view.c:27
box_leaf
static mleaf_t box_leaf
Definition: cmodel.c:118
FloodAreaConnections
static void FloodAreaConnections(cm_t *cm)
Definition: cmodel.c:849
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
Z_TagMallocz
void * Z_TagMallocz(size_t size, memtag_t tag)
Definition: zone.c:330
CM_BoxLeafs_headnode
static int CM_BoxLeafs_headnode(vec3_t mins, vec3_t maxs, mleaf_t **list, int listsize, mnode_t *headnode, mnode_t **topnode)
Definition: cmodel.c:254
origin
static vec3_t origin
Definition: mesh.c:27
AngleVectors
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition: shared.c:23
trace_mins
static vec3_t trace_mins
Definition: cmodel.c:353
checkcount
static int checkcount
Definition: cmodel.c:35
DIST_EPSILON
#define DIST_EPSILON
Definition: cmodel.c:350
leaf_maxs
static float * leaf_maxs
Definition: cmodel.c:226
nullleaf
static mleaf_t nullleaf
Definition: cmodel.c:32
map_allsolid_bug
static cvar_t * map_allsolid_bug
Definition: cmodel.c:38
CM_InitBoxHull
static void CM_InitBoxHull(void)
Definition: cmodel.c:129
map_noareas
static cvar_t * map_noareas
Definition: cmodel.c:37
CM_TestInLeaf
static void CM_TestInLeaf(mleaf_t *leaf)
Definition: cmodel.c:559
trace_contents
static int trace_contents
Definition: cmodel.c:357
c
statCounters_t c
Definition: main.c:30
up
static vec3_t up
Definition: p_view.c:27
right
static vec3_t right
Definition: p_view.c:27
box_nodes
static mnode_t box_nodes[6]
Definition: cmodel.c:113
CM_BoxLeafs_r
static void CM_BoxLeafs_r(mnode_t *node)
Definition: cmodel.c:229
nulltexinfo
mtexinfo_t nulltexinfo
Definition: cmodel.c:30
box_planes
static cplane_t box_planes[12]
Definition: cmodel.c:112
BSP_Load
qerror_t BSP_Load(const char *name, bsp_t **bsp_p)
Definition: bsp.c:1087
leaf_mins
static float * leaf_mins
Definition: cmodel.c:226
box_leafbrush
static mbrush_t * box_leafbrush
Definition: cmodel.c:116
box_brushsides
static mbrushside_t box_brushsides[6]
Definition: cmodel.c:117
trace_trace
static trace_t * trace_trace
Definition: cmodel.c:356
CM_TraceToLeaf
static void CM_TraceToLeaf(mleaf_t *leaf)
Definition: cmodel.c:529
box_headnode
static mnode_t * box_headnode
Definition: cmodel.c:114
leaf_topnode
static mnode_t * leaf_topnode
Definition: cmodel.c:227