icculus quake2 doxygen  1.0 dev
cmodel.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 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 // cmodel.c -- model loading
21 
22 #include "qcommon.h"
23 
24 typedef struct
25 {
27  int children[2]; // negative numbers are leafs
28 } cnode_t;
29 
30 typedef struct
31 {
34 } cbrushside_t;
35 
36 typedef struct
37 {
38  int contents;
39  int cluster;
40  int area;
41  unsigned short firstleafbrush;
42  unsigned short numleafbrushes;
43 } cleaf_t;
44 
45 typedef struct
46 {
47  int contents;
48  int numsides;
50  int checkcount; // to avoid repeated testings
51 } cbrush_t;
52 
53 typedef struct
54 {
57  int floodnum; // if two areas have equal floodnums, they are connected
59 } carea_t;
60 
62 
64 
67 
70 
72 cplane_t map_planes[MAX_MAP_PLANES+6]; // extra for box hull
73 
75 cnode_t map_nodes[MAX_MAP_NODES+6]; // extra for box hull
76 
77 int numleafs = 1; // allow leaf funcs to be called without a map
80 
83 
86 
89 
93 
96 
97 int numareas = 1;
99 
102 
103 int numclusters = 1;
104 
106 
108 
110 
111 
113 
114 void CM_InitBoxHull (void);
115 void FloodAreaConnections (void);
116 
117 
120 
121 
122 /*
123 ===============================================================================
124 
125  MAP LOADING
126 
127 ===============================================================================
128 */
129 
130 byte *cmod_base;
131 
132 /*
133 =================
134 CMod_LoadSubmodels
135 =================
136 */
138 {
139  dmodel_t *in;
140  cmodel_t *out;
141  int i, j, count;
142 
143  in = (void *)(cmod_base + l->fileofs);
144  if (l->filelen % sizeof(*in))
145  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
146  count = l->filelen / sizeof(*in);
147 
148  if (count < 1)
149  Com_Error (ERR_DROP, "Map with no models");
150  if (count > MAX_MAP_MODELS)
151  Com_Error (ERR_DROP, "Map has too many models");
152 
153  numcmodels = count;
154 
155  for ( i=0 ; i<count ; i++, in++, out++)
156  {
157  out = &map_cmodels[i];
158 
159  for (j=0 ; j<3 ; j++)
160  { // spread the mins / maxs by a pixel
161  out->mins[j] = LittleFloat (in->mins[j]) - 1;
162  out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
163  out->origin[j] = LittleFloat (in->origin[j]);
164  }
165  out->headnode = LittleLong (in->headnode);
166  }
167 }
168 
169 
170 /*
171 =================
172 CMod_LoadSurfaces
173 =================
174 */
176 {
177  texinfo_t *in;
178  mapsurface_t *out;
179  int i, count;
180 
181  in = (void *)(cmod_base + l->fileofs);
182  if (l->filelen % sizeof(*in))
183  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
184  count = l->filelen / sizeof(*in);
185  if (count < 1)
186  Com_Error (ERR_DROP, "Map with no surfaces");
187  if (count > MAX_MAP_TEXINFO)
188  Com_Error (ERR_DROP, "Map has too many surfaces");
189 
190  numtexinfo = count;
191  out = map_surfaces;
192 
193  for ( i=0 ; i<count ; i++, in++, out++)
194  {
195  strncpy (out->c.name, in->texture, sizeof(out->c.name)-1);
196  strncpy (out->rname, in->texture, sizeof(out->rname)-1);
197  out->c.flags = LittleLong (in->flags);
198  out->c.value = LittleLong (in->value);
199  }
200 }
201 
202 
203 /*
204 =================
205 CMod_LoadNodes
206 
207 =================
208 */
210 {
211  dnode_t *in;
212  int child;
213  cnode_t *out;
214  int i, j, count;
215 
216  in = (void *)(cmod_base + l->fileofs);
217  if (l->filelen % sizeof(*in))
218  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
219  count = l->filelen / sizeof(*in);
220 
221  if (count < 1)
222  Com_Error (ERR_DROP, "Map has no nodes");
223  if (count > MAX_MAP_NODES)
224  Com_Error (ERR_DROP, "Map has too many nodes");
225 
226  out = map_nodes;
227 
228  numnodes = count;
229 
230  for (i=0 ; i<count ; i++, out++, in++)
231  {
232  out->plane = map_planes + LittleLong(in->planenum);
233  for (j=0 ; j<2 ; j++)
234  {
235  child = LittleLong (in->children[j]);
236  out->children[j] = child;
237  }
238  }
239 
240 }
241 
242 /*
243 =================
244 CMod_LoadBrushes
245 
246 =================
247 */
249 {
250  dbrush_t *in;
251  cbrush_t *out;
252  int i, count;
253 
254  in = (void *)(cmod_base + l->fileofs);
255  if (l->filelen % sizeof(*in))
256  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
257  count = l->filelen / sizeof(*in);
258 
259  if (count > MAX_MAP_BRUSHES)
260  Com_Error (ERR_DROP, "Map has too many brushes");
261 
262  out = map_brushes;
263 
264  numbrushes = count;
265 
266  for (i=0 ; i<count ; i++, out++, in++)
267  {
268  out->firstbrushside = LittleLong(in->firstside);
269  out->numsides = LittleLong(in->numsides);
270  out->contents = LittleLong(in->contents);
271  }
272 
273 }
274 
275 /*
276 =================
277 CMod_LoadLeafs
278 =================
279 */
281 {
282  int i;
283  cleaf_t *out;
284  dleaf_t *in;
285  int count;
286 
287  in = (void *)(cmod_base + l->fileofs);
288  if (l->filelen % sizeof(*in))
289  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
290  count = l->filelen / sizeof(*in);
291 
292  if (count < 1)
293  Com_Error (ERR_DROP, "Map with no leafs");
294  // need to save space for box planes
295  if (count > MAX_MAP_PLANES)
296  Com_Error (ERR_DROP, "Map has too many planes");
297 
298  out = map_leafs;
299  numleafs = count;
300  numclusters = 0;
301 
302  for ( i=0 ; i<count ; i++, in++, out++)
303  {
304  out->contents = LittleLong (in->contents);
305  out->cluster = LittleShort (in->cluster);
306  out->area = LittleShort (in->area);
307  out->firstleafbrush = LittleShort (in->firstleafbrush);
308  out->numleafbrushes = LittleShort (in->numleafbrushes);
309 
310  if (out->cluster >= numclusters)
311  numclusters = out->cluster + 1;
312  }
313 
314  if (map_leafs[0].contents != CONTENTS_SOLID)
315  Com_Error (ERR_DROP, "Map leaf 0 is not CONTENTS_SOLID");
316  solidleaf = 0;
317  emptyleaf = -1;
318  for (i=1 ; i<numleafs ; i++)
319  {
320  if (!map_leafs[i].contents)
321  {
322  emptyleaf = i;
323  break;
324  }
325  }
326  if (emptyleaf == -1)
327  Com_Error (ERR_DROP, "Map does not have an empty leaf");
328 }
329 
330 /*
331 =================
332 CMod_LoadPlanes
333 =================
334 */
336 {
337  int i, j;
338  cplane_t *out;
339  dplane_t *in;
340  int count;
341  int bits;
342 
343  in = (void *)(cmod_base + l->fileofs);
344  if (l->filelen % sizeof(*in))
345  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
346  count = l->filelen / sizeof(*in);
347 
348  if (count < 1)
349  Com_Error (ERR_DROP, "Map with no planes");
350  // need to save space for box planes
351  if (count > MAX_MAP_PLANES)
352  Com_Error (ERR_DROP, "Map has too many planes");
353 
354  out = map_planes;
355  numplanes = count;
356 
357  for ( i=0 ; i<count ; i++, in++, out++)
358  {
359  bits = 0;
360  for (j=0 ; j<3 ; j++)
361  {
362  out->normal[j] = LittleFloat (in->normal[j]);
363  if (out->normal[j] < 0)
364  bits |= 1<<j;
365  }
366 
367  out->dist = LittleFloat (in->dist);
368  out->type = LittleLong (in->type);
369  out->signbits = bits;
370  }
371 }
372 
373 /*
374 =================
375 CMod_LoadLeafBrushes
376 =================
377 */
379 {
380  int i;
381  unsigned short *out;
382  unsigned short *in;
383  int count;
384 
385  in = (void *)(cmod_base + l->fileofs);
386  if (l->filelen % sizeof(*in))
387  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
388  count = l->filelen / sizeof(*in);
389 
390  if (count < 1)
391  Com_Error (ERR_DROP, "Map with no planes");
392  // need to save space for box planes
394  Com_Error (ERR_DROP, "Map has too many leafbrushes");
395 
396  out = map_leafbrushes;
398 
399  for ( i=0 ; i<count ; i++, in++, out++)
400  *out = LittleShort (*in);
401 }
402 
403 /*
404 =================
405 CMod_LoadBrushSides
406 =================
407 */
409 {
410  int i, j;
411  cbrushside_t *out;
412  dbrushside_t *in;
413  int count;
414  int num;
415 
416  in = (void *)(cmod_base + l->fileofs);
417  if (l->filelen % sizeof(*in))
418  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
419  count = l->filelen / sizeof(*in);
420 
421  // need to save space for box planes
423  Com_Error (ERR_DROP, "Map has too many planes");
424 
425  out = map_brushsides;
427 
428  for ( i=0 ; i<count ; i++, in++, out++)
429  {
430  num = LittleShort (in->planenum);
431  out->plane = &map_planes[num];
432  j = LittleShort (in->texinfo);
433  if (j >= numtexinfo)
434  Com_Error (ERR_DROP, "Bad brushside texinfo");
435  out->surface = &map_surfaces[j];
436  }
437 }
438 
439 /*
440 =================
441 CMod_LoadAreas
442 =================
443 */
445 {
446  int i;
447  carea_t *out;
448  darea_t *in;
449  int count;
450 
451  in = (void *)(cmod_base + l->fileofs);
452  if (l->filelen % sizeof(*in))
453  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
454  count = l->filelen / sizeof(*in);
455 
456  if (count > MAX_MAP_AREAS)
457  Com_Error (ERR_DROP, "Map has too many areas");
458 
459  out = map_areas;
460  numareas = count;
461 
462  for ( i=0 ; i<count ; i++, in++, out++)
463  {
464  out->numareaportals = LittleLong (in->numareaportals);
465  out->firstareaportal = LittleLong (in->firstareaportal);
466  out->floodvalid = 0;
467  out->floodnum = 0;
468  }
469 }
470 
471 /*
472 =================
473 CMod_LoadAreaPortals
474 =================
475 */
477 {
478  int i;
479  dareaportal_t *out;
480  dareaportal_t *in;
481  int count;
482 
483  in = (void *)(cmod_base + l->fileofs);
484  if (l->filelen % sizeof(*in))
485  Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
486  count = l->filelen / sizeof(*in);
487 
488  if (count > MAX_MAP_AREAS)
489  Com_Error (ERR_DROP, "Map has too many areas");
490 
491  out = map_areaportals;
493 
494  for ( i=0 ; i<count ; i++, in++, out++)
495  {
496  out->portalnum = LittleLong (in->portalnum);
497  out->otherarea = LittleLong (in->otherarea);
498  }
499 }
500 
501 /*
502 =================
503 CMod_LoadVisibility
504 =================
505 */
507 {
508  int i;
509 
510  numvisibility = l->filelen;
511  if (l->filelen > MAX_MAP_VISIBILITY)
512  Com_Error (ERR_DROP, "Map has too large visibility lump");
513 
514  memcpy (map_visibility, cmod_base + l->fileofs, l->filelen);
515 
517  for (i=0 ; i<map_vis->numclusters ; i++)
518  {
519  map_vis->bitofs[i][0] = LittleLong (map_vis->bitofs[i][0]);
520  map_vis->bitofs[i][1] = LittleLong (map_vis->bitofs[i][1]);
521  }
522 }
523 
524 
525 /*
526 =================
527 CMod_LoadEntityString
528 =================
529 */
531 {
532  numentitychars = l->filelen;
533  if (l->filelen > MAX_MAP_ENTSTRING)
534  Com_Error (ERR_DROP, "Map has too large entity lump");
535 
536  memcpy (map_entitystring, cmod_base + l->fileofs, l->filelen);
537 }
538 
539 
540 
541 /*
542 ==================
543 CM_LoadMap
544 
545 Loads in the map and all submodels
546 ==================
547 */
548 cmodel_t *CM_LoadMap (char *name, qboolean clientload, unsigned *checksum)
549 {
550  unsigned *buf;
551  int i;
552  dheader_t header;
553  int length;
554  static unsigned last_checksum;
555 
556  map_noareas = Cvar_Get ("map_noareas", "0", 0);
557 
558  if ( !strcmp (map_name, name) && (clientload || !Cvar_VariableValue ("flushmap")) )
559  {
560  *checksum = last_checksum;
561  if (!clientload)
562  {
563  memset (portalopen, 0, sizeof(portalopen));
565  }
566  return &map_cmodels[0]; // still have the right version
567  }
568 
569  // free old stuff
570  numplanes = 0;
571  numnodes = 0;
572  numleafs = 0;
573  numcmodels = 0;
574  numvisibility = 0;
575  numentitychars = 0;
576  map_entitystring[0] = 0;
577  map_name[0] = 0;
578 
579  if (!name || !name[0])
580  {
581  numleafs = 1;
582  numclusters = 1;
583  numareas = 1;
584  *checksum = 0;
585  return &map_cmodels[0]; // cinematic servers won't have anything at all
586  }
587 
588  //
589  // load the file
590  //
591  length = FS_LoadFile (name, (void **)&buf);
592  if (!buf)
593  Com_Error (ERR_DROP, "Couldn't load %s", name);
594 
595  last_checksum = LittleLong (Com_BlockChecksum (buf, length));
596  *checksum = last_checksum;
597 
598  header = *(dheader_t *)buf;
599  for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
600  ((int *)&header)[i] = LittleLong ( ((int *)&header)[i]);
601 
602  if (header.version != BSPVERSION)
603  Com_Error (ERR_DROP, "CMod_LoadBrushModel: %s has wrong version number (%i should be %i)"
604  , name, header.version, BSPVERSION);
605 
606  cmod_base = (byte *)buf;
607 
608  // load into heap
610  CMod_LoadLeafs (&header.lumps[LUMP_LEAFS]);
612  CMod_LoadPlanes (&header.lumps[LUMP_PLANES]);
616  CMod_LoadNodes (&header.lumps[LUMP_NODES]);
617  CMod_LoadAreas (&header.lumps[LUMP_AREAS]);
621 
622  FS_FreeFile (buf);
623 
624  CM_InitBoxHull ();
625 
626  memset (portalopen, 0, sizeof(portalopen));
628 
629  strcpy (map_name, name);
630 
631  return &map_cmodels[0];
632 }
633 
634 /*
635 ==================
636 CM_InlineModel
637 ==================
638 */
640 {
641  int num;
642 
643  if (!name || name[0] != '*')
644  Com_Error (ERR_DROP, "CM_InlineModel: bad name");
645  num = atoi (name+1);
646  if (num < 1 || num >= numcmodels)
647  Com_Error (ERR_DROP, "CM_InlineModel: bad number");
648 
649  return &map_cmodels[num];
650 }
651 
652 int CM_NumClusters (void)
653 {
654  return numclusters;
655 }
656 
658 {
659  return numcmodels;
660 }
661 
662 char *CM_EntityString (void)
663 {
664  return map_entitystring;
665 }
666 
667 int CM_LeafContents (int leafnum)
668 {
669  if (leafnum < 0 || leafnum >= numleafs)
670  Com_Error (ERR_DROP, "CM_LeafContents: bad number");
671  return map_leafs[leafnum].contents;
672 }
673 
674 int CM_LeafCluster (int leafnum)
675 {
676  if (leafnum < 0 || leafnum >= numleafs)
677  Com_Error (ERR_DROP, "CM_LeafCluster: bad number");
678  return map_leafs[leafnum].cluster;
679 }
680 
681 int CM_LeafArea (int leafnum)
682 {
683  if (leafnum < 0 || leafnum >= numleafs)
684  Com_Error (ERR_DROP, "CM_LeafArea: bad number");
685  return map_leafs[leafnum].area;
686 }
687 
688 //=======================================================================
689 
690 
695 
696 /*
697 ===================
698 CM_InitBoxHull
699 
700 Set up the planes and nodes so that the six floats of a bounding box
701 can just be stored out and get a proper clipping hull structure.
702 ===================
703 */
704 void CM_InitBoxHull (void)
705 {
706  int i;
707  int side;
708  cnode_t *c;
709  cplane_t *p;
710  cbrushside_t *s;
711 
714  if (numnodes+6 > MAX_MAP_NODES
718  || numplanes+12 > MAX_MAP_PLANES)
719  Com_Error (ERR_DROP, "Not enough room for box tree");
720 
722  box_brush->numsides = 6;
725 
730 
732 
733  for (i=0 ; i<6 ; i++)
734  {
735  side = i&1;
736 
737  // brush sides
739  s->plane = map_planes + (numplanes+i*2+side);
740  s->surface = &nullsurface;
741 
742  // nodes
743  c = &map_nodes[box_headnode+i];
744  c->plane = map_planes + (numplanes+i*2);
745  c->children[side] = -1 - emptyleaf;
746  if (i != 5)
747  c->children[side^1] = box_headnode+i + 1;
748  else
749  c->children[side^1] = -1 - numleafs;
750 
751  // planes
752  p = &box_planes[i*2];
753  p->type = i>>1;
754  p->signbits = 0;
755  VectorClear (p->normal);
756  p->normal[i>>1] = 1;
757 
758  p = &box_planes[i*2+1];
759  p->type = 3 + (i>>1);
760  p->signbits = 0;
761  VectorClear (p->normal);
762  p->normal[i>>1] = -1;
763  }
764 }
765 
766 
767 /*
768 ===================
769 CM_HeadnodeForBox
770 
771 To keep everything totally uniform, bounding boxes are turned into small
772 BSP trees instead of being compared directly.
773 ===================
774 */
776 {
777  box_planes[0].dist = maxs[0];
778  box_planes[1].dist = -maxs[0];
779  box_planes[2].dist = mins[0];
780  box_planes[3].dist = -mins[0];
781  box_planes[4].dist = maxs[1];
782  box_planes[5].dist = -maxs[1];
783  box_planes[6].dist = mins[1];
784  box_planes[7].dist = -mins[1];
785  box_planes[8].dist = maxs[2];
786  box_planes[9].dist = -maxs[2];
787  box_planes[10].dist = mins[2];
788  box_planes[11].dist = -mins[2];
789 
790  return box_headnode;
791 }
792 
793 
794 /*
795 ==================
796 CM_PointLeafnum_r
797 
798 ==================
799 */
800 int CM_PointLeafnum_r (vec3_t p, int num)
801 {
802  float d;
803  cnode_t *node;
804  cplane_t *plane;
805 
806  while (num >= 0)
807  {
808  node = map_nodes + num;
809  plane = node->plane;
810 
811  if (plane->type < 3)
812  d = p[plane->type] - plane->dist;
813  else
814  d = DotProduct (plane->normal, p) - plane->dist;
815  if (d < 0)
816  num = node->children[1];
817  else
818  num = node->children[0];
819  }
820 
821  c_pointcontents++; // optimize counter
822 
823  return -1 - num;
824 }
825 
827 {
828  if (!numplanes)
829  return 0; // sound may call this without map loaded
830  return CM_PointLeafnum_r (p, 0);
831 }
832 
833 
834 
835 /*
836 =============
837 CM_BoxLeafnums
838 
839 Fills in a list of all the leafs touched
840 =============
841 */
846 
847 void CM_BoxLeafnums_r (int nodenum)
848 {
849  cplane_t *plane;
850  cnode_t *node;
851  int s;
852 
853  while (1)
854  {
855  if (nodenum < 0)
856  {
857  if (leaf_count >= leaf_maxcount)
858  {
859 // Com_Printf ("CM_BoxLeafnums_r: overflow\n");
860  return;
861  }
862  leaf_list[leaf_count++] = -1 - nodenum;
863  return;
864  }
865 
866  node = &map_nodes[nodenum];
867  plane = node->plane;
868 // s = BoxOnPlaneSide (leaf_mins, leaf_maxs, plane);
870  if (s == 1)
871  nodenum = node->children[0];
872  else if (s == 2)
873  nodenum = node->children[1];
874  else
875  { // go down both
876  if (leaf_topnode == -1)
877  leaf_topnode = nodenum;
878  CM_BoxLeafnums_r (node->children[0]);
879  nodenum = node->children[1];
880  }
881 
882  }
883 }
884 
885 int CM_BoxLeafnums_headnode (vec3_t mins, vec3_t maxs, int *list, int listsize, int headnode, int *topnode)
886 {
887  leaf_list = list;
888  leaf_count = 0;
889  leaf_maxcount = listsize;
890  leaf_mins = mins;
891  leaf_maxs = maxs;
892 
893  leaf_topnode = -1;
894 
895  CM_BoxLeafnums_r (headnode);
896 
897  if (topnode)
898  *topnode = leaf_topnode;
899 
900  return leaf_count;
901 }
902 
903 int CM_BoxLeafnums (vec3_t mins, vec3_t maxs, int *list, int listsize, int *topnode)
904 {
905  return CM_BoxLeafnums_headnode (mins, maxs, list,
906  listsize, map_cmodels[0].headnode, topnode);
907 }
908 
909 
910 
911 /*
912 ==================
913 CM_PointContents
914 
915 ==================
916 */
917 int CM_PointContents (vec3_t p, int headnode)
918 {
919  int l;
920 
921  if (!numnodes) // map not loaded
922  return 0;
923 
924  l = CM_PointLeafnum_r (p, headnode);
925 
926  return map_leafs[l].contents;
927 }
928 
929 /*
930 ==================
931 CM_TransformedPointContents
932 
933 Handles offseting and rotation of the end points for moving and
934 rotating entities
935 ==================
936 */
937 int CM_TransformedPointContents (vec3_t p, int headnode, vec3_t origin, vec3_t angles)
938 {
939  vec3_t p_l;
940  vec3_t temp;
942  int l;
943 
944  // subtract origin offset
945  VectorSubtract (p, origin, p_l);
946 
947  // rotate start and end into the models frame of reference
948  if (headnode != box_headnode &&
949  (angles[0] || angles[1] || angles[2]) )
950  {
951  AngleVectors (angles, forward, right, up);
952 
953  VectorCopy (p_l, temp);
954  p_l[0] = DotProduct (temp, forward);
955  p_l[1] = -DotProduct (temp, right);
956  p_l[2] = DotProduct (temp, up);
957  }
958 
959  l = CM_PointLeafnum_r (p_l, headnode);
960 
961  return map_leafs[l].contents;
962 }
963 
964 
965 /*
966 ===============================================================================
967 
968 BOX TRACING
969 
970 ===============================================================================
971 */
972 
973 // 1/32 epsilon to keep floating point happy
974 #define DIST_EPSILON (0.03125)
975 
979 
982 qboolean trace_ispoint; // optimized case
983 
984 /*
985 ================
986 CM_ClipBoxToBrush
987 ================
988 */
989 void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2,
990  trace_t *trace, cbrush_t *brush)
991 {
992  int i, j;
993  cplane_t *plane, *clipplane;
994  float dist;
995  float enterfrac, leavefrac;
996  vec3_t ofs;
997  float d1, d2;
998  qboolean getout, startout;
999  float f;
1000  cbrushside_t *side, *leadside;
1001 
1002  enterfrac = -1;
1003  leavefrac = 1;
1004  clipplane = NULL;
1005 
1006  if (!brush->numsides)
1007  return;
1008 
1009  c_brush_traces++;
1010 
1011  getout = false;
1012  startout = false;
1013  leadside = NULL;
1014 
1015  for (i=0 ; i<brush->numsides ; i++)
1016  {
1017  side = &map_brushsides[brush->firstbrushside+i];
1018  plane = side->plane;
1019 
1020  // FIXME: special case for axial
1021 
1022  if (!trace_ispoint)
1023  { // general box case
1024 
1025  // push the plane out apropriately for mins/maxs
1026 
1027  // FIXME: use signbits into 8 way lookup for each mins/maxs
1028  for (j=0 ; j<3 ; j++)
1029  {
1030  if (plane->normal[j] < 0)
1031  ofs[j] = maxs[j];
1032  else
1033  ofs[j] = mins[j];
1034  }
1035  dist = DotProduct (ofs, plane->normal);
1036  dist = plane->dist - dist;
1037  }
1038  else
1039  { // special point case
1040  dist = plane->dist;
1041  }
1042 
1043  d1 = DotProduct (p1, plane->normal) - dist;
1044  d2 = DotProduct (p2, plane->normal) - dist;
1045 
1046  if (d2 > 0)
1047  getout = true; // endpoint is not in solid
1048  if (d1 > 0)
1049  startout = true;
1050 
1051  // if completely in front of face, no intersection
1052  if (d1 > 0 && d2 >= d1)
1053  return;
1054 
1055  if (d1 <= 0 && d2 <= 0)
1056  continue;
1057 
1058  // crosses face
1059  if (d1 > d2)
1060  { // enter
1061  f = (d1-DIST_EPSILON) / (d1-d2);
1062  if (f > enterfrac)
1063  {
1064  enterfrac = f;
1065  clipplane = plane;
1066  leadside = side;
1067  }
1068  }
1069  else
1070  { // leave
1071  f = (d1+DIST_EPSILON) / (d1-d2);
1072  if (f < leavefrac)
1073  leavefrac = f;
1074  }
1075  }
1076 
1077  if (!startout)
1078  { // original point was inside brush
1079  trace->startsolid = true;
1080  if (!getout)
1081  trace->allsolid = true;
1082  return;
1083  }
1084  if (enterfrac < leavefrac)
1085  {
1086  if (enterfrac > -1 && enterfrac < trace->fraction)
1087  {
1088  if (enterfrac < 0)
1089  enterfrac = 0;
1090  trace->fraction = enterfrac;
1091  trace->plane = *clipplane;
1092  trace->surface = &(leadside->surface->c);
1093  trace->contents = brush->contents;
1094  }
1095  }
1096 }
1097 
1098 /*
1099 ================
1100 CM_TestBoxInBrush
1101 ================
1102 */
1103 void CM_TestBoxInBrush (vec3_t mins, vec3_t maxs, vec3_t p1,
1104  trace_t *trace, cbrush_t *brush)
1105 {
1106  int i, j;
1107  cplane_t *plane;
1108  float dist;
1109  vec3_t ofs;
1110  float d1;
1111  cbrushside_t *side;
1112 
1113  if (!brush->numsides)
1114  return;
1115 
1116  for (i=0 ; i<brush->numsides ; i++)
1117  {
1118  side = &map_brushsides[brush->firstbrushside+i];
1119  plane = side->plane;
1120 
1121  // FIXME: special case for axial
1122 
1123  // general box case
1124 
1125  // push the plane out apropriately for mins/maxs
1126 
1127  // FIXME: use signbits into 8 way lookup for each mins/maxs
1128  for (j=0 ; j<3 ; j++)
1129  {
1130  if (plane->normal[j] < 0)
1131  ofs[j] = maxs[j];
1132  else
1133  ofs[j] = mins[j];
1134  }
1135  dist = DotProduct (ofs, plane->normal);
1136  dist = plane->dist - dist;
1137 
1138  d1 = DotProduct (p1, plane->normal) - dist;
1139 
1140  // if completely in front of face, no intersection
1141  if (d1 > 0)
1142  return;
1143 
1144  }
1145 
1146  // inside this brush
1147  trace->startsolid = trace->allsolid = true;
1148  trace->fraction = 0;
1149  trace->contents = brush->contents;
1150 }
1151 
1152 
1153 /*
1154 ================
1155 CM_TraceToLeaf
1156 ================
1157 */
1158 void CM_TraceToLeaf (int leafnum)
1159 {
1160  int k;
1161  int brushnum;
1162  cleaf_t *leaf;
1163  cbrush_t *b;
1164 
1165  leaf = &map_leafs[leafnum];
1166  if ( !(leaf->contents & trace_contents))
1167  return;
1168  // trace line against all brushes in the leaf
1169  for (k=0 ; k<leaf->numleafbrushes ; k++)
1170  {
1171  brushnum = map_leafbrushes[leaf->firstleafbrush+k];
1172  b = &map_brushes[brushnum];
1173  if (b->checkcount == checkcount)
1174  continue; // already checked this brush in another leaf
1175  b->checkcount = checkcount;
1176 
1177  if ( !(b->contents & trace_contents))
1178  continue;
1180  if (!trace_trace.fraction)
1181  return;
1182  }
1183 
1184 }
1185 
1186 
1187 /*
1188 ================
1189 CM_TestInLeaf
1190 ================
1191 */
1192 void CM_TestInLeaf (int leafnum)
1193 {
1194  int k;
1195  int brushnum;
1196  cleaf_t *leaf;
1197  cbrush_t *b;
1198 
1199  leaf = &map_leafs[leafnum];
1200  if ( !(leaf->contents & trace_contents))
1201  return;
1202  // trace line against all brushes in the leaf
1203  for (k=0 ; k<leaf->numleafbrushes ; k++)
1204  {
1205  brushnum = map_leafbrushes[leaf->firstleafbrush+k];
1206  b = &map_brushes[brushnum];
1207  if (b->checkcount == checkcount)
1208  continue; // already checked this brush in another leaf
1209  b->checkcount = checkcount;
1210 
1211  if ( !(b->contents & trace_contents))
1212  continue;
1214  if (!trace_trace.fraction)
1215  return;
1216  }
1217 
1218 }
1219 
1220 
1221 /*
1222 ==================
1223 CM_RecursiveHullCheck
1224 
1225 ==================
1226 */
1227 void CM_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2)
1228 {
1229  cnode_t *node;
1230  cplane_t *plane;
1231  float t1, t2, offset;
1232  float frac, frac2;
1233  float idist;
1234  int i;
1235  vec3_t mid;
1236  int side;
1237  float midf;
1238 
1239  if (trace_trace.fraction <= p1f)
1240  return; // already hit something nearer
1241 
1242  // if < 0, we are in a leaf node
1243  if (num < 0)
1244  {
1245  CM_TraceToLeaf (-1-num);
1246  return;
1247  }
1248 
1249  //
1250  // find the point distances to the seperating plane
1251  // and the offset for the size of the box
1252  //
1253  node = map_nodes + num;
1254  plane = node->plane;
1255 
1256  if (plane->type < 3)
1257  {
1258  t1 = p1[plane->type] - plane->dist;
1259  t2 = p2[plane->type] - plane->dist;
1260  offset = trace_extents[plane->type];
1261  }
1262  else
1263  {
1264  t1 = DotProduct (plane->normal, p1) - plane->dist;
1265  t2 = DotProduct (plane->normal, p2) - plane->dist;
1266  if (trace_ispoint)
1267  offset = 0;
1268  else
1269  offset = fabs(trace_extents[0]*plane->normal[0]) +
1270  fabs(trace_extents[1]*plane->normal[1]) +
1271  fabs(trace_extents[2]*plane->normal[2]);
1272  }
1273 
1274 
1275 #if 0
1276 CM_RecursiveHullCheck (node->children[0], p1f, p2f, p1, p2);
1277 CM_RecursiveHullCheck (node->children[1], p1f, p2f, p1, p2);
1278 return;
1279 #endif
1280 
1281  // see which sides we need to consider
1282  if (t1 >= offset && t2 >= offset)
1283  {
1284  CM_RecursiveHullCheck (node->children[0], p1f, p2f, p1, p2);
1285  return;
1286  }
1287  if (t1 < -offset && t2 < -offset)
1288  {
1289  CM_RecursiveHullCheck (node->children[1], p1f, p2f, p1, p2);
1290  return;
1291  }
1292 
1293  // put the crosspoint DIST_EPSILON pixels on the near side
1294  if (t1 < t2)
1295  {
1296  idist = 1.0/(t1-t2);
1297  side = 1;
1298  frac2 = (t1 + offset + DIST_EPSILON)*idist;
1299  frac = (t1 - offset + DIST_EPSILON)*idist;
1300  }
1301  else if (t1 > t2)
1302  {
1303  idist = 1.0/(t1-t2);
1304  side = 0;
1305  frac2 = (t1 - offset - DIST_EPSILON)*idist;
1306  frac = (t1 + offset + DIST_EPSILON)*idist;
1307  }
1308  else
1309  {
1310  side = 0;
1311  frac = 1;
1312  frac2 = 0;
1313  }
1314 
1315  // move up to the node
1316  if (frac < 0)
1317  frac = 0;
1318  if (frac > 1)
1319  frac = 1;
1320 
1321  midf = p1f + (p2f - p1f)*frac;
1322  for (i=0 ; i<3 ; i++)
1323  mid[i] = p1[i] + frac*(p2[i] - p1[i]);
1324 
1325  CM_RecursiveHullCheck (node->children[side], p1f, midf, p1, mid);
1326 
1327 
1328  // go past the node
1329  if (frac2 < 0)
1330  frac2 = 0;
1331  if (frac2 > 1)
1332  frac2 = 1;
1333 
1334  midf = p1f + (p2f - p1f)*frac2;
1335  for (i=0 ; i<3 ; i++)
1336  mid[i] = p1[i] + frac2*(p2[i] - p1[i]);
1337 
1338  CM_RecursiveHullCheck (node->children[side^1], midf, p2f, mid, p2);
1339 }
1340 
1341 
1342 
1343 //======================================================================
1344 
1345 /*
1346 ==================
1347 CM_BoxTrace
1348 ==================
1349 */
1351  vec3_t mins, vec3_t maxs,
1352  int headnode, int brushmask)
1353 {
1354  int i;
1355 
1356  checkcount++; // for multi-check avoidance
1357 
1358  c_traces++; // for statistics, may be zeroed
1359 
1360  // fill in a default trace
1361  memset (&trace_trace, 0, sizeof(trace_trace));
1362  trace_trace.fraction = 1;
1364 
1365  if (!numnodes) // map not loaded
1366  return trace_trace;
1367 
1368  trace_contents = brushmask;
1369  VectorCopy (start, trace_start);
1370  VectorCopy (end, trace_end);
1371  VectorCopy (mins, trace_mins);
1372  VectorCopy (maxs, trace_maxs);
1373 
1374  //
1375  // check for position test special case
1376  //
1377  if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2])
1378  {
1379  int leafs[1024];
1380  int i, numleafs;
1381  vec3_t c1, c2;
1382  int topnode;
1383 
1384  VectorAdd (start, mins, c1);
1385  VectorAdd (start, maxs, c2);
1386  for (i=0 ; i<3 ; i++)
1387  {
1388  c1[i] -= 1;
1389  c2[i] += 1;
1390  }
1391 
1392  numleafs = CM_BoxLeafnums_headnode (c1, c2, leafs, 1024, headnode, &topnode);
1393  for (i=0 ; i<numleafs ; i++)
1394  {
1395  CM_TestInLeaf (leafs[i]);
1396  if (trace_trace.allsolid)
1397  break;
1398  }
1399  VectorCopy (start, trace_trace.endpos);
1400  return trace_trace;
1401  }
1402 
1403  //
1404  // check for point special case
1405  //
1406  if (mins[0] == 0 && mins[1] == 0 && mins[2] == 0
1407  && maxs[0] == 0 && maxs[1] == 0 && maxs[2] == 0)
1408  {
1409  trace_ispoint = true;
1411  }
1412  else
1413  {
1414  trace_ispoint = false;
1415  trace_extents[0] = -mins[0] > maxs[0] ? -mins[0] : maxs[0];
1416  trace_extents[1] = -mins[1] > maxs[1] ? -mins[1] : maxs[1];
1417  trace_extents[2] = -mins[2] > maxs[2] ? -mins[2] : maxs[2];
1418  }
1419 
1420  //
1421  // general sweeping through world
1422  //
1423  CM_RecursiveHullCheck (headnode, 0, 1, start, end);
1424 
1425  if (trace_trace.fraction == 1)
1426  {
1427  VectorCopy (end, trace_trace.endpos);
1428  }
1429  else
1430  {
1431  for (i=0 ; i<3 ; i++)
1432  trace_trace.endpos[i] = start[i] + trace_trace.fraction * (end[i] - start[i]);
1433  }
1434  return trace_trace;
1435 }
1436 
1437 
1438 /*
1439 ==================
1440 CM_TransformedBoxTrace
1441 
1442 Handles offseting and rotation of the end points for moving and
1443 rotating entities
1444 ==================
1445 */
1446 #ifdef _WIN32
1447 #pragma optimize( "", off )
1448 #endif
1449 
1450 
1452  vec3_t mins, vec3_t maxs,
1453  int headnode, int brushmask,
1454  vec3_t origin, vec3_t angles)
1455 {
1456  trace_t trace;
1457  vec3_t start_l, end_l;
1458  vec3_t a;
1459  vec3_t forward, right, up;
1460  vec3_t temp;
1461  qboolean rotated;
1462 
1463  // subtract origin offset
1464  VectorSubtract (start, origin, start_l);
1465  VectorSubtract (end, origin, end_l);
1466 
1467  // rotate start and end into the models frame of reference
1468  if (headnode != box_headnode &&
1469  (angles[0] || angles[1] || angles[2]) )
1470  rotated = true;
1471  else
1472  rotated = false;
1473 
1474  if (rotated)
1475  {
1476  AngleVectors (angles, forward, right, up);
1477 
1478  VectorCopy (start_l, temp);
1479  start_l[0] = DotProduct (temp, forward);
1480  start_l[1] = -DotProduct (temp, right);
1481  start_l[2] = DotProduct (temp, up);
1482 
1483  VectorCopy (end_l, temp);
1484  end_l[0] = DotProduct (temp, forward);
1485  end_l[1] = -DotProduct (temp, right);
1486  end_l[2] = DotProduct (temp, up);
1487  }
1488 
1489  // sweep the box through the model
1490  trace = CM_BoxTrace (start_l, end_l, mins, maxs, headnode, brushmask);
1491 
1492  if (rotated && trace.fraction != 1.0)
1493  {
1494  // FIXME: figure out how to do this with existing angles
1495  VectorNegate (angles, a);
1496  AngleVectors (a, forward, right, up);
1497 
1498  VectorCopy (trace.plane.normal, temp);
1499  trace.plane.normal[0] = DotProduct (temp, forward);
1500  trace.plane.normal[1] = -DotProduct (temp, right);
1501  trace.plane.normal[2] = DotProduct (temp, up);
1502  }
1503 
1504  trace.endpos[0] = start[0] + trace.fraction * (end[0] - start[0]);
1505  trace.endpos[1] = start[1] + trace.fraction * (end[1] - start[1]);
1506  trace.endpos[2] = start[2] + trace.fraction * (end[2] - start[2]);
1507 
1508  return trace;
1509 }
1510 
1511 #ifdef _WIN32
1512 #pragma optimize( "", on )
1513 #endif
1514 
1515 
1516 
1517 /*
1518 ===============================================================================
1519 
1520 PVS / PHS
1521 
1522 ===============================================================================
1523 */
1524 
1525 /*
1526 ===================
1527 CM_DecompressVis
1528 ===================
1529 */
1530 void CM_DecompressVis (byte *in, byte *out)
1531 {
1532  int c;
1533  byte *out_p;
1534  int row;
1535 
1536  row = (numclusters+7)>>3;
1537  out_p = out;
1538 
1539  if (!in || !numvisibility)
1540  { // no vis info, so make all visible
1541  while (row)
1542  {
1543  *out_p++ = 0xff;
1544  row--;
1545  }
1546  return;
1547  }
1548 
1549  do
1550  {
1551  if (*in)
1552  {
1553  *out_p++ = *in++;
1554  continue;
1555  }
1556 
1557  c = in[1];
1558  in += 2;
1559  if ((out_p - out) + c > row)
1560  {
1561  c = row - (out_p - out);
1562  Com_DPrintf ("warning: Vis decompression overrun\n");
1563  }
1564  while (c)
1565  {
1566  *out_p++ = 0;
1567  c--;
1568  }
1569  } while (out_p - out < row);
1570 }
1571 
1574 
1575 byte *CM_ClusterPVS (int cluster)
1576 {
1577  if (cluster == -1)
1578  memset (pvsrow, 0, (numclusters+7)>>3);
1579  else
1581  return pvsrow;
1582 }
1583 
1584 byte *CM_ClusterPHS (int cluster)
1585 {
1586  if (cluster == -1)
1587  memset (phsrow, 0, (numclusters+7)>>3);
1588  else
1590  return phsrow;
1591 }
1592 
1593 
1594 /*
1595 ===============================================================================
1596 
1597 AREAPORTALS
1598 
1599 ===============================================================================
1600 */
1601 
1602 void FloodArea_r (carea_t *area, int floodnum)
1603 {
1604  int i;
1605  dareaportal_t *p;
1606 
1607  if (area->floodvalid == floodvalid)
1608  {
1609  if (area->floodnum == floodnum)
1610  return;
1611  Com_Error (ERR_DROP, "FloodArea_r: reflooded");
1612  }
1613 
1614  area->floodnum = floodnum;
1615  area->floodvalid = floodvalid;
1616  p = &map_areaportals[area->firstareaportal];
1617  for (i=0 ; i<area->numareaportals ; i++, p++)
1618  {
1619  if (portalopen[p->portalnum])
1620  FloodArea_r (&map_areas[p->otherarea], floodnum);
1621  }
1622 }
1623 
1624 /*
1625 ====================
1626 FloodAreaConnections
1627 
1628 
1629 ====================
1630 */
1632 {
1633  int i;
1634  carea_t *area;
1635  int floodnum;
1636 
1637  // all current floods are now invalid
1638  floodvalid++;
1639  floodnum = 0;
1640 
1641  // area 0 is not used
1642  for (i=1 ; i<numareas ; i++)
1643  {
1644  area = &map_areas[i];
1645  if (area->floodvalid == floodvalid)
1646  continue; // already flooded into
1647  floodnum++;
1648  FloodArea_r (area, floodnum);
1649  }
1650 
1651 }
1652 
1653 void CM_SetAreaPortalState (int portalnum, qboolean open)
1654 {
1655  if (portalnum > numareaportals)
1656  Com_Error (ERR_DROP, "areaportal > numareaportals");
1657 
1658  portalopen[portalnum] = open;
1660 }
1661 
1662 qboolean CM_AreasConnected (int area1, int area2)
1663 {
1664  if (map_noareas->value)
1665  return true;
1666 
1667  if (area1 > numareas || area2 > numareas)
1668  Com_Error (ERR_DROP, "area > numareas");
1669 
1670  if (map_areas[area1].floodnum == map_areas[area2].floodnum)
1671  return true;
1672  return false;
1673 }
1674 
1675 
1676 /*
1677 =================
1678 CM_WriteAreaBits
1679 
1680 Writes a length byte followed by a bit vector of all the areas
1681 that area in the same flood as the area parameter
1682 
1683 This is used by the client refreshes to cull visibility
1684 =================
1685 */
1686 int CM_WriteAreaBits (byte *buffer, int area)
1687 {
1688  int i;
1689  int floodnum;
1690  int bytes;
1691 
1692  bytes = (numareas+7)>>3;
1693 
1694  if (map_noareas->value)
1695  { // for debugging, send everything
1696  memset (buffer, 255, bytes);
1697  }
1698  else
1699  {
1700  memset (buffer, 0, bytes);
1701 
1702  floodnum = map_areas[area].floodnum;
1703  for (i=0 ; i<numareas ; i++)
1704  {
1705  if (map_areas[i].floodnum == floodnum || !area)
1706  buffer[i>>3] |= 1<<(i&7);
1707  }
1708  }
1709 
1710  return bytes;
1711 }
1712 
1713 
1714 /*
1715 ===================
1716 CM_WritePortalState
1717 
1718 Writes the portal state to a savegame file
1719 ===================
1720 */
1721 void CM_WritePortalState (FILE *f)
1722 {
1723  fwrite (portalopen, sizeof(portalopen), 1, f);
1724 }
1725 
1726 /*
1727 ===================
1728 CM_ReadPortalState
1729 
1730 Reads the portal state from a savegame file
1731 and recalculates the area connections
1732 ===================
1733 */
1734 void CM_ReadPortalState (FILE *f)
1735 {
1736  FS_Read (portalopen, sizeof(portalopen), f);
1738 }
1739 
1740 /*
1741 =============
1742 CM_HeadnodeVisible
1743 
1744 Returns true if any leaf under headnode has a cluster that
1745 is potentially visible
1746 =============
1747 */
1748 qboolean CM_HeadnodeVisible (int nodenum, byte *visbits)
1749 {
1750  int leafnum;
1751  int cluster;
1752  cnode_t *node;
1753 
1754  if (nodenum < 0)
1755  {
1756  leafnum = -1-nodenum;
1757  cluster = map_leafs[leafnum].cluster;
1758  if (cluster == -1)
1759  return false;
1760  if (visbits[cluster>>3] & (1<<(cluster&7)))
1761  return true;
1762  return false;
1763  }
1764 
1765  node = &map_nodes[nodenum];
1766  if (CM_HeadnodeVisible(node->children[0], visbits))
1767  return true;
1768  return CM_HeadnodeVisible(node->children[1], visbits);
1769 }
1770 
trace_t::contents
int contents
Definition: q_shared.h:457
LUMP_VISIBILITY
#define LUMP_VISIBILITY
Definition: qfiles.h:265
LUMP_BRUSHSIDES
#define LUMP_BRUSHSIDES
Definition: qfiles.h:277
MAX_MAP_LEAFS
#define MAX_MAP_LEAFS
Definition: qfiles.h:239
box_leaf
cleaf_t * box_leaf
Definition: cmodel.c:694
csurface_s::name
char name[16]
Definition: q_shared.h:437
cplane_s::normal
vec3_t normal
Definition: q_shared.h:411
CM_BoxTrace
trace_t CM_BoxTrace(vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int headnode, int brushmask)
Definition: cmodel.c:1350
FS_Read
void FS_Read(void *buffer, int len, FILE *f)
Definition: files.c:346
dareaportal_t
Definition: qfiles.h:472
numvisibility
int numvisibility
Definition: cmodel.c:90
cplane_s::type
byte type
Definition: q_shared.h:413
dheader_t
Definition: qfiles.h:283
cleaf_t
Definition: cmodel.c:36
CM_PointLeafnum_r
int CM_PointLeafnum_r(vec3_t p, int num)
Definition: cmodel.c:800
CONTENTS_MONSTER
#define CONTENTS_MONSTER
Definition: qfiles.h:359
CMod_LoadEntityString
void CMod_LoadEntityString(lump_t *l)
Definition: cmodel.c:530
MAX_QPATH
#define MAX_QPATH
Definition: q_shared.h:73
LittleShort
short LittleShort(short l)
Definition: q_shared.c:946
trace_t::fraction
float fraction
Definition: q_shared.h:453
LUMP_AREAPORTALS
#define LUMP_AREAPORTALS
Definition: qfiles.h:280
dnode_t
Definition: qfiles.h:381
VectorSubtract
#define VectorSubtract(a, b, c)
Definition: q_shared.h:156
cmodel_s::maxs
vec3_t maxs
Definition: q_shared.h:430
cleaf_t::contents
int contents
Definition: cmodel.c:38
lump_t::filelen
int filelen
Definition: qfiles.h:259
trace_start
vec3_t trace_start
Definition: cmodel.c:976
trace_t::plane
cplane_t plane
Definition: q_shared.h:455
BOX_ON_PLANE_SIDE
#define BOX_ON_PLANE_SIDE(emins, emaxs, p)
Definition: q_shared.h:190
CMod_LoadVisibility
void CMod_LoadVisibility(lump_t *l)
Definition: cmodel.c:506
mapsurface_s::rname
char rname[32]
Definition: q_shared.h:445
dplane_t
Definition: qfiles.h:318
dbrush_t
Definition: qfiles.h:447
cbrush_t::firstbrushside
int firstbrushside
Definition: cmodel.c:49
CM_BoxLeafnums_r
void CM_BoxLeafnums_r(int nodenum)
Definition: cmodel.c:847
CMod_LoadSubmodels
void CMod_LoadSubmodels(lump_t *l)
Definition: cmodel.c:137
cbrush_t
Definition: cmodel.c:45
mapsurface_s
Definition: q_shared.h:442
leaf_count
int leaf_count
Definition: cmodel.c:842
cbrushside_t::surface
mapsurface_t * surface
Definition: cmodel.c:33
carea_t::firstareaportal
int firstareaportal
Definition: cmodel.c:56
cleaf_t::cluster
int cluster
Definition: cmodel.c:39
LUMP_MODELS
#define LUMP_MODELS
Definition: qfiles.h:275
dareaportal_t::portalnum
int portalnum
Definition: qfiles.h:474
map_surfaces
mapsurface_t map_surfaces[MAX_MAP_TEXINFO]
Definition: cmodel.c:69
carea_t::floodvalid
int floodvalid
Definition: cmodel.c:58
cplane_s::signbits
byte signbits
Definition: q_shared.h:414
numplanes
int numplanes
Definition: cmodel.c:71
map_areaportals
dareaportal_t map_areaportals[MAX_MAP_AREAPORTALS]
Definition: cmodel.c:101
CM_RecursiveHullCheck
void CM_RecursiveHullCheck(int num, float p1f, float p2f, vec3_t p1, vec3_t p2)
Definition: cmodel.c:1227
numclusters
int numclusters
Definition: cmodel.c:103
CM_WritePortalState
void CM_WritePortalState(FILE *f)
Definition: cmodel.c:1721
DVIS_PHS
#define DVIS_PHS
Definition: qfiles.h:462
box_headnode
int box_headnode
Definition: cmodel.c:692
MAX_MAP_PLANES
#define MAX_MAP_PLANES
Definition: qfiles.h:236
qboolean
qboolean
Definition: q_shared.h:56
map_visibility
byte map_visibility[MAX_MAP_VISIBILITY]
Definition: cmodel.c:91
trace_t
Definition: q_shared.h:449
VectorClear
#define VectorClear(a)
Definition: q_shared.h:159
i
int i
Definition: q_shared.c:305
mapsurface_s::c
csurface_t c
Definition: q_shared.h:444
LUMP_LEAFS
#define LUMP_LEAFS
Definition: qfiles.h:270
portalopen
qboolean portalopen[MAX_MAP_AREAPORTALS]
Definition: cmodel.c:109
CM_WriteAreaBits
int CM_WriteAreaBits(byte *buffer, int area)
Definition: cmodel.c:1686
cmod_base
byte * cmod_base
Definition: cmodel.c:130
CM_TransformedPointContents
int CM_TransformedPointContents(vec3_t p, int headnode, vec3_t origin, vec3_t angles)
Definition: cmodel.c:937
buffer
GLenum GLfloat * buffer
Definition: qgl_win.c:151
dvis_t
Definition: qfiles.h:463
dbrush_t::numsides
int numsides
Definition: qfiles.h:450
MAX_MAP_AREAS
#define MAX_MAP_AREAS
Definition: qfiles.h:234
CONTENTS_SOLID
#define CONTENTS_SOLID
Definition: qfiles.h:333
MAX_MAP_NODES
#define MAX_MAP_NODES
Definition: qfiles.h:237
numnodes
int numnodes
Definition: cmodel.c:74
leaf_maxcount
int leaf_maxcount
Definition: cmodel.c:842
map_cmodels
cmodel_t map_cmodels[MAX_MAP_MODELS]
Definition: cmodel.c:85
Cvar_Get
cvar_t * Cvar_Get(char *var_name, char *var_value, int flags)
Definition: cvar.c:127
DVIS_PVS
#define DVIS_PVS
Definition: qfiles.h:461
cvar_s
Definition: q_shared.h:317
CM_ClipBoxToBrush
void CM_ClipBoxToBrush(vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2, trace_t *trace, cbrush_t *brush)
Definition: cmodel.c:989
LUMP_NODES
#define LUMP_NODES
Definition: qfiles.h:266
lump_t::fileofs
int fileofs
Definition: qfiles.h:259
trace_extents
vec3_t trace_extents
Definition: cmodel.c:978
darea_t
Definition: qfiles.h:478
LUMP_AREAS
#define LUMP_AREAS
Definition: qfiles.h:279
CM_LeafArea
int CM_LeafArea(int leafnum)
Definition: cmodel.c:681
csurface_s::flags
int flags
Definition: q_shared.h:438
cmodel_s::headnode
int headnode
Definition: q_shared.h:432
j
GLint j
Definition: qgl_win.c:150
CM_PointContents
int CM_PointContents(vec3_t p, int headnode)
Definition: cmodel.c:917
cnode_t::children
int children[2]
Definition: cmodel.c:27
trace_ispoint
qboolean trace_ispoint
Definition: cmodel.c:982
trace_end
vec3_t trace_end
Definition: cmodel.c:976
AngleVectors
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition: q_shared.c:93
dnode_t::children
int children[2]
Definition: qfiles.h:384
cbrush_t::numsides
int numsides
Definition: cmodel.c:48
trace_t::allsolid
qboolean allsolid
Definition: q_shared.h:451
dmodel_t
Definition: qfiles.h:290
dbrushside_t
Definition: qfiles.h:441
box_brush
cbrush_t * box_brush
Definition: cmodel.c:693
CM_TestInLeaf
void CM_TestInLeaf(int leafnum)
Definition: cmodel.c:1192
CM_DecompressVis
void CM_DecompressVis(byte *in, byte *out)
Definition: cmodel.c:1530
CMod_LoadAreas
void CMod_LoadAreas(lump_t *l)
Definition: cmodel.c:444
MAX_MAP_LEAFBRUSHES
#define MAX_MAP_LEAFBRUSHES
Definition: qfiles.h:243
LittleFloat
float LittleFloat(float l)
Definition: q_shared.c:950
CM_ClusterPVS
byte * CM_ClusterPVS(int cluster)
Definition: cmodel.c:1575
numleafs
int numleafs
Definition: cmodel.c:77
trace_maxs
vec3_t trace_maxs
Definition: cmodel.c:977
CMod_LoadBrushSides
void CMod_LoadBrushSides(lump_t *l)
Definition: cmodel.c:408
dvis_t::numclusters
int numclusters
Definition: qfiles.h:465
CM_AreasConnected
qboolean CM_AreasConnected(int area1, int area2)
Definition: cmodel.c:1662
CMod_LoadLeafBrushes
void CMod_LoadLeafBrushes(lump_t *l)
Definition: cmodel.c:378
LittleLong
int LittleLong(int l)
Definition: q_shared.c:948
floodvalid
int floodvalid
Definition: cmodel.c:107
dbrush_t::contents
int contents
Definition: qfiles.h:451
LUMP_BRUSHES
#define LUMP_BRUSHES
Definition: qfiles.h:276
box_planes
cplane_t * box_planes
Definition: cmodel.c:691
numareaportals
int numareaportals
Definition: cmodel.c:100
forward
static vec3_t forward
Definition: p_view.c:29
trace_trace
trace_t trace_trace
Definition: cmodel.c:980
MAX_MAP_MODELS
#define MAX_MAP_MODELS
Definition: qfiles.h:228
dareaportal_t::otherarea
int otherarea
Definition: qfiles.h:475
map_leafs
cleaf_t map_leafs[MAX_MAP_LEAFS]
Definition: cmodel.c:78
cleaf_t::numleafbrushes
unsigned short numleafbrushes
Definition: cmodel.c:42
numareas
int numareas
Definition: cmodel.c:97
FS_LoadFile
int FS_LoadFile(char *path, void **buffer)
Definition: files.c:394
DotProduct
#define DotProduct(x, y)
Definition: q_shared.h:155
cbrush_t::contents
int contents
Definition: cmodel.c:47
cvar_s::value
float value
Definition: q_shared.h:324
cplane_s::dist
float dist
Definition: q_shared.h:412
cnode_t
Definition: cmodel.c:24
cmodel_s::mins
vec3_t mins
Definition: q_shared.h:430
LUMP_LEAFBRUSHES
#define LUMP_LEAFBRUSHES
Definition: qfiles.h:272
trace_mins
vec3_t trace_mins
Definition: cmodel.c:977
CM_LeafContents
int CM_LeafContents(int leafnum)
Definition: cmodel.c:667
NULL
#define NULL
Definition: q_shared.h:60
dheader_t::lumps
lump_t lumps[HEADER_LUMPS]
Definition: qfiles.h:287
CMod_LoadNodes
void CMod_LoadNodes(lump_t *l)
Definition: cmodel.c:209
checkcount
int checkcount
Definition: cmodel.c:61
MAX_MAP_BRUSHES
#define MAX_MAP_BRUSHES
Definition: qfiles.h:229
MAX_MAP_AREAPORTALS
#define MAX_MAP_AREAPORTALS
Definition: qfiles.h:235
DIST_EPSILON
#define DIST_EPSILON
Definition: cmodel.c:974
Com_Error
void Com_Error(int code, char *fmt,...)
Definition: common.c:203
CM_NumClusters
int CM_NumClusters(void)
Definition: cmodel.c:652
cmodel_s
Definition: q_shared.h:428
map_vis
dvis_t * map_vis
Definition: cmodel.c:92
dbrush_t::firstside
int firstside
Definition: qfiles.h:449
FloodArea_r
void FloodArea_r(carea_t *area, int floodnum)
Definition: cmodel.c:1602
nullsurface
mapsurface_t nullsurface
Definition: cmodel.c:105
map_nodes
cnode_t map_nodes[MAX_MAP_NODES+6]
Definition: cmodel.c:75
ERR_DROP
#define ERR_DROP
Definition: qcommon.h:736
leaf_topnode
int leaf_topnode
Definition: cmodel.c:845
CM_InlineModel
cmodel_t * CM_InlineModel(char *name)
Definition: cmodel.c:639
leaf_maxs
float * leaf_maxs
Definition: cmodel.c:844
CM_TestBoxInBrush
void CM_TestBoxInBrush(vec3_t mins, vec3_t maxs, vec3_t p1, trace_t *trace, cbrush_t *brush)
Definition: cmodel.c:1103
CM_ReadPortalState
void CM_ReadPortalState(FILE *f)
Definition: cmodel.c:1734
CMod_LoadPlanes
void CMod_LoadPlanes(lump_t *l)
Definition: cmodel.c:335
c_brush_traces
int c_brush_traces
Definition: cmodel.c:119
name
cvar_t * name
Definition: cl_main.c:94
map_areas
carea_t map_areas[MAX_MAP_AREAS]
Definition: cmodel.c:98
CM_BoxLeafnums
int CM_BoxLeafnums(vec3_t mins, vec3_t maxs, int *list, int listsize, int *topnode)
Definition: cmodel.c:903
dvis_t::bitofs
int bitofs[8][2]
Definition: qfiles.h:466
VectorAdd
#define VectorAdd(a, b, c)
Definition: q_shared.h:157
cmodel_s::origin
vec3_t origin
Definition: q_shared.h:431
MAX_MAP_ENTSTRING
#define MAX_MAP_ENTSTRING
Definition: qfiles.h:231
cleaf_t::area
int area
Definition: cmodel.c:40
map_noareas
cvar_t * map_noareas
Definition: cmodel.c:112
carea_t::floodnum
int floodnum
Definition: cmodel.c:57
dheader_t::version
int version
Definition: qfiles.h:286
texinfo_s
Definition: qfiles.h:392
VectorCopy
#define VectorCopy(a, b)
Definition: q_shared.h:158
trace_contents
int trace_contents
Definition: cmodel.c:981
csurface_s::value
int value
Definition: q_shared.h:439
Com_BlockChecksum
unsigned Com_BlockChecksum(void *buffer, int length)
Definition: md4.c:165
CM_LoadMap
cmodel_t * CM_LoadMap(char *name, qboolean clientload, unsigned *checksum)
Definition: cmodel.c:548
emptyleaf
int emptyleaf
Definition: cmodel.c:79
CM_ClusterPHS
byte * CM_ClusterPHS(int cluster)
Definition: cmodel.c:1584
cbrushside_t::plane
cplane_t * plane
Definition: cmodel.c:32
CM_EntityString
char * CM_EntityString(void)
Definition: cmodel.c:662
BSPVERSION
#define BSPVERSION
Definition: qfiles.h:222
lump_t
Definition: qfiles.h:257
trace_t::endpos
vec3_t endpos
Definition: q_shared.h:454
map_brushes
cbrush_t map_brushes[MAX_MAP_BRUSHES]
Definition: cmodel.c:88
qcommon.h
CM_HeadnodeForBox
int CM_HeadnodeForBox(vec3_t mins, vec3_t maxs)
Definition: cmodel.c:775
cnode_t::plane
cplane_t * plane
Definition: cmodel.c:26
up
static vec3_t up
Definition: p_view.c:29
cbrushside_t
Definition: cmodel.c:30
solidleaf
int solidleaf
Definition: cmodel.c:79
numleafbrushes
int numleafbrushes
Definition: cmodel.c:81
map_brushsides
cbrushside_t map_brushsides[MAX_MAP_BRUSHSIDES]
Definition: cmodel.c:66
CM_LeafCluster
int CM_LeafCluster(int leafnum)
Definition: cmodel.c:674
map_entitystring
char map_entitystring[MAX_MAP_ENTSTRING]
Definition: cmodel.c:95
MAX_MAP_BRUSHSIDES
#define MAX_MAP_BRUSHSIDES
Definition: qfiles.h:238
carea_t
Definition: cmodel.c:53
cbrush_t::checkcount
int checkcount
Definition: cmodel.c:50
LUMP_TEXINFO
#define LUMP_TEXINFO
Definition: qfiles.h:267
dleaf_t
Definition: qfiles.h:424
FloodAreaConnections
void FloodAreaConnections(void)
Definition: cmodel.c:1631
trace_t::startsolid
qboolean startsolid
Definition: q_shared.h:452
LUMP_PLANES
#define LUMP_PLANES
Definition: qfiles.h:263
numcmodels
int numcmodels
Definition: cmodel.c:84
CM_NumInlineModels
int CM_NumInlineModels(void)
Definition: cmodel.c:657
cleaf_t::firstleafbrush
unsigned short firstleafbrush
Definition: cmodel.c:41
Com_DPrintf
void Com_DPrintf(char *fmt,...)
Definition: common.c:155
map_planes
cplane_t map_planes[MAX_MAP_PLANES+6]
Definition: cmodel.c:72
FS_FreeFile
void FS_FreeFile(void *buffer)
Definition: files.c:433
trace_t::surface
csurface_t * surface
Definition: q_shared.h:456
phsrow
byte phsrow[MAX_MAP_LEAFS/8]
Definition: cmodel.c:1573
c_pointcontents
int c_pointcontents
Definition: cmodel.c:118
LUMP_ENTITIES
#define LUMP_ENTITIES
Definition: qfiles.h:262
map_name
char map_name[MAX_QPATH]
Definition: cmodel.c:63
right
GLdouble right
Definition: qgl_win.c:159
numentitychars
int numentitychars
Definition: cmodel.c:94
CM_TraceToLeaf
void CM_TraceToLeaf(int leafnum)
Definition: cmodel.c:1158
carea_t::numareaportals
int numareaportals
Definition: cmodel.c:55
leaf_mins
float * leaf_mins
Definition: cmodel.c:844
cplane_s
Definition: q_shared.h:409
MAX_MAP_TEXINFO
#define MAX_MAP_TEXINFO
Definition: qfiles.h:232
CM_SetAreaPortalState
void CM_SetAreaPortalState(int portalnum, qboolean open)
Definition: cmodel.c:1653
CM_TransformedBoxTrace
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)
Definition: cmodel.c:1451
leaf_list
int * leaf_list
Definition: cmodel.c:843
numbrushes
int numbrushes
Definition: cmodel.c:87
CM_BoxLeafnums_headnode
int CM_BoxLeafnums_headnode(vec3_t mins, vec3_t maxs, int *list, int listsize, int headnode, int *topnode)
Definition: cmodel.c:885
CMod_LoadAreaPortals
void CMod_LoadAreaPortals(lump_t *l)
Definition: cmodel.c:476
CM_HeadnodeVisible
qboolean CM_HeadnodeVisible(int nodenum, byte *visbits)
Definition: cmodel.c:1748
pvsrow
byte pvsrow[MAX_MAP_LEAFS/8]
Definition: cmodel.c:1572
map_leafbrushes
unsigned short map_leafbrushes[MAX_MAP_LEAFBRUSHES]
Definition: cmodel.c:82
CMod_LoadBrushes
void CMod_LoadBrushes(lump_t *l)
Definition: cmodel.c:248
MAX_MAP_VISIBILITY
#define MAX_MAP_VISIBILITY
Definition: qfiles.h:248
vec3_t
vec_t vec3_t[3]
Definition: q_shared.h:127
CM_PointLeafnum
int CM_PointLeafnum(vec3_t p)
Definition: cmodel.c:826
numtexinfo
int numtexinfo
Definition: cmodel.c:68
dnode_t::planenum
int planenum
Definition: qfiles.h:383
CMod_LoadSurfaces
void CMod_LoadSurfaces(lump_t *l)
Definition: cmodel.c:175
VectorNegate
#define VectorNegate(a, b)
Definition: q_shared.h:160
c_traces
int c_traces
Definition: cmodel.c:119
CMod_LoadLeafs
void CMod_LoadLeafs(lump_t *l)
Definition: cmodel.c:280
count
GLint GLsizei count
Definition: qgl_win.c:128
numbrushsides
int numbrushsides
Definition: cmodel.c:65
Cvar_VariableValue
float Cvar_VariableValue(char *var_name)
Definition: cvar.c:63
CM_InitBoxHull
void CM_InitBoxHull(void)
Definition: cmodel.c:704