UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
bsp.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 1997-2001 Id Software, Inc.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 
26 #include "common.h"
27 #include "qfiles.h"
28 #include "tracing.h"
29 #include "routing.h"
30 #include "../shared/parse.h"
31 
34 
35 /*
36 ===============================================================================
37 MAP LOADING
38 ===============================================================================
39 */
40 
41 static int CMod_ValidateLump (const lump_t* lump, const char* functionName, size_t elementSize, const char* elementName, int elementMaxCount)
42 {
43  if (!lump)
44  Com_Error(ERR_DROP, "%s: No lump given", functionName);
45  if (lump->filelen % elementSize)
46  Com_Error(ERR_DROP, "%s: funny lump size (%i => " UFO_SIZE_T ")", functionName, lump->filelen, elementSize);
47  const int count = lump->filelen / elementSize;
48  Com_DPrintf(DEBUG_ENGINE, S_COLOR_GREEN "...%s: %i\n", elementName, count);
49 
50  if (count < 1)
51  Com_Error(ERR_DROP, "Map with no %s", elementName);
52  if (count > elementMaxCount)
53  Com_Error(ERR_DROP, "Map has too many %s: %i", elementName, count);
54 
55  return count;
56 }
57 
68 static void CMod_LoadSubmodels (MapTile& tile, const byte* base, const lump_t* lump, const vec3_t shift)
69 {
70  const int count = CMod_ValidateLump(lump, __FUNCTION__, sizeof(dBspModel_t), "models", MAX_MAP_MODELS);
71 
72  const dBspModel_t* in = (const dBspModel_t*) (base + lump->fileofs);
73 
75  tile.models = out;
76  tile.nummodels = count;
77 
78  for (int i = 0; i < count; i++, in++, out++) {
79  /* Record the shift in case we need to undo it. */
80  VectorCopy(shift, out->shift);
81  /* spread the mins / maxs by a pixel */
82  out->cbmBox.setFromLittleFloat(in->dbmBox);
83  out->cbmBox.expand(1);
84  out->cbmBox.shift(shift);
85  out->headnode = LittleLong(in->headnode);
86  out->tile = tile.idx; /* backlink to the loaded map tile */
87  }
88 }
89 
90 
97 static void CMod_LoadSurfaces (MapTile& tile, const byte* base, const lump_t* lump)
98 {
99  const int count = CMod_ValidateLump(lump, __FUNCTION__, sizeof(dBspTexinfo_t), "surfaces", MAX_MAP_TEXINFO);
100 
101  const dBspTexinfo_t* in = (const dBspTexinfo_t*) (base + lump->fileofs);
102 
104 
105  tile.surfaces = out;
106  tile.numtexinfo = count;
107 
108  for (int i = 0; i < count; i++, in++, out++) {
109  Q_strncpyz(out->name, in->texture, sizeof(out->name));
110  out->surfaceFlags = LittleLong(in->surfaceFlags);
111  }
112 }
113 
114 
123 static void CMod_LoadNodes (MapTile& tile, const byte* base, const lump_t* lump, const vec3_t shift)
124 {
125  const int count = CMod_ValidateLump(lump, __FUNCTION__, sizeof(dBspNode_t), "nodes", MAX_MAP_NODES);
126 
127  const dBspNode_t* in = (const dBspNode_t*) (base + lump->fileofs);
128 
129  /* add some for the box */
131 
132  tile.numnodes = count;
133  tile.nodes = out;
134 
135  for (int i = 0; i < count; i++, out++, in++) {
136  if (LittleLong(in->planenum) == PLANENUM_LEAF)
137  out->plane = nullptr;
138  else
139  out->plane = tile.planes + LittleLong(in->planenum);
140 
141  /* in case this is a map assemble */
142  for (int j = 0; j < 3; j++) {
143  out->mins[j] = LittleShort(in->mins[j]) + shift[j];
144  out->maxs[j] = LittleShort(in->maxs[j]) + shift[j];
145  }
146 
147  for (int j = 0; j < 2; j++) {
148  int child = LittleLong(in->children[j]);
149  out->children[j] = child;
150  }
151  }
152 }
153 
160 static void CMod_LoadBrushes (MapTile& tile, const byte* base, const lump_t* lump)
161 {
162  const int count = CMod_ValidateLump(lump, __FUNCTION__, sizeof(dBspBrush_t), "brushes", MAX_MAP_BRUSHES);
163 
164  const dBspBrush_t* in = (const dBspBrush_t*) (base + lump->fileofs);
165 
166  /* add some for the box */
168 
169  tile.numbrushes = count;
170  tile.brushes = out;
171 
172  for (int i = 0; i < count; i++, out++, in++) {
174  out->numsides = LittleLong(in->numsides);
175  out->brushContentFlags = LittleLong(in->brushContentFlags);
176  }
177 }
178 
185 static void CMod_LoadLeafs (MapTile& tile, const byte* base, const lump_t* lump)
186 {
187  const int count = CMod_ValidateLump(lump, __FUNCTION__, sizeof(dBspLeaf_t), "leafs", MAX_MAP_LEAFS);
188 
189  const dBspLeaf_t* in = (const dBspLeaf_t*) (base + lump->fileofs);
190 
191  /* add some for the box */
193 
194  tile.numleafs = count;
195  tile.leafs = out;
196 
197  for (int i = 0; i < count; i++, in++, out++) {
198  out->contentFlags = LittleLong(in->contentFlags);
199  out->firstleafbrush = LittleShort(in->firstleafbrush);
200  out->numleafbrushes = LittleShort(in->numleafbrushes);
201  }
202 
203  if (tile.leafs[0].contentFlags != CONTENTS_SOLID)
204  Com_Error(ERR_DROP, "Map leaf 0 is not CONTENTS_SOLID");
205  tile.emptyleaf = -1;
206  for (int i = 1; i < tile.numleafs; i++) {
207  if (!tile.leafs[i].contentFlags) {
208  tile.emptyleaf = i;
209  break;
210  }
211  }
212  if (tile.emptyleaf == -1)
213  Com_Error(ERR_DROP, "Map does not have an empty leaf");
214 }
215 
224 static void CMod_LoadPlanes (MapTile& tile, const byte* base, const lump_t* lump, const vec3_t shift)
225 {
226  const int count = CMod_ValidateLump(lump, __FUNCTION__, sizeof(dBspPlane_t), "planes", MAX_MAP_PLANES);
227 
228  const dBspPlane_t* in = (const dBspPlane_t*) (base + lump->fileofs);
229 
230  /* add some for the box */
232 
233  tile.numplanes = count;
234  tile.planes = out;
235 
236  for (int i = 0; i < count; i++, in++, out++) {
237  out->dist = LittleFloat(in->dist);
238  out->type = LittleLong(in->type);
239 
240  /* load normals and shift (map assembly) */
241  for (int j = 0; j < 3; j++) {
242  out->normal[j] = LittleFloat(in->normal[j]);
243  out->dist += out->normal[j] * shift[j];
244  }
245  }
246 }
247 
254 static void CMod_LoadLeafBrushes (MapTile& tile, const byte* base, const lump_t* lump)
255 {
256  const int count = CMod_ValidateLump(lump, __FUNCTION__, sizeof(unsigned short), "leafbrushes", MAX_MAP_LEAFBRUSHES);
257 
258  const unsigned short* in = (const unsigned short*) (base + lump->fileofs);
259 
260  /* add some for the box */
261  unsigned short* out = Mem_PoolAllocTypeN(unsigned short, count + 1, com_cmodelSysPool);
262 
263  tile.numleafbrushes = count;
264  tile.leafbrushes = out;
265 
266  for (int i = 0; i < count; i++, in++, out++)
267  *out = LittleShort(*in);
268 }
269 
276 static void CMod_LoadBrushSides (MapTile& tile, const byte* base, const lump_t* lump)
277 {
278  const int count = CMod_ValidateLump(lump, __FUNCTION__, sizeof(dBspBrushSide_t), "brushsides", MAX_MAP_BRUSHSIDES);
279 
280  const dBspBrushSide_t* in = (const dBspBrushSide_t*) (base + lump->fileofs);
281 
282  /* add some for the box */
284 
285  tile.numbrushsides = count;
286  tile.brushsides = out;
287 
288  for (int i = 0; i < count; i++, in++, out++) {
289  const int num = LittleShort(in->planenum);
290  const int j = LittleShort(in->texinfo);
291  if (j >= tile.numtexinfo)
292  Com_Error(ERR_DROP, "Bad brushside texinfo");
293  out->plane = &tile.planes[num];
294  out->surface = &tile.surfaces[j];
295  }
296 }
297 
304 static int CMod_DeCompressRouting (const byte** source, byte* dataStart)
305 {
306  byte* data_p = dataStart;
307  const byte* src = *source;
308 
309  while (*src) {
310  int c;
311 
312  if (*src & 0x80) {
313  /* repetitions */
314  c = *src++ & ~0x80;
315  /* Remember that the total bytes that are the same is c + 2 */
316  for (int i = 0; i < c + 2; i++)
317  *data_p++ = *src;
318  src++;
319  } else {
320  /* identities */
321  c = *src++;
322  for (int i = 0; i < c; i++)
323  *data_p++ = *src++;
324  }
325  }
326 
327  src++;
328  *source = src;
329 
330  return data_p - dataStart;
331 }
332 
333 /*
334 ===============================================================================
335 TRACING NODES
336 ===============================================================================
337 */
338 
345 static void CM_MakeTracingNodes (MapTile& tile)
346 {
348 
349  tile.numtheads = 0;
350  tile.numcheads = 0;
351 
352  for (int i = 0; i < tile.nummodels; i++) {
353  if (tile.models[i].headnode == LEAFNODE || tile.models[i].headnode >= tile.numnodes + 6)
354  continue;
355 
356  tile.thead[tile.numtheads] = tnode - tile.tnodes;
357  tile.theadlevel[tile.numtheads] = i;
358  tile.numtheads++;
359  assert(tile.numtheads < LEVEL_MAX);
360 
361  /* If this level (i) is the last visible level or earlier, then trace it.
362  * Otherwise don't; we have separate checks for entities. */
363  if (i < NUM_REGULAR_MODELS)
364  TR_BuildTracingNode_r(&tile, &tnode, tile.models[i].headnode, i);
365  }
366 }
367 
380 static void CMod_LoadRouting (MapTile& tile, mapData_t* mapData, const byte* base, const char* name, const lump_t* lump, const int sX, const int sY, const int sZ)
381 {
383  Routing* tempMap = static_cast<Routing*>(Mem_Alloc(sizeof(Routing)));
384  const int targetLength = sizeof(tile.wpMins) + sizeof(tile.wpMaxs) + sizeof(Routing);
385 
386  double start = time(nullptr);
387 
388  if (!lump)
389  Com_Error(ERR_DROP, "CMod_LoadRouting: No lump given");
390 
391  if (!lump->filelen)
392  Com_Error(ERR_DROP, "CMod_LoadRouting: Map has NO routing lump");
393 
394  assert((sX > -(PATHFINDING_WIDTH / 2)) && (sX < (PATHFINDING_WIDTH / 2)));
395  assert((sY > -(PATHFINDING_WIDTH / 2)) && (sY < (PATHFINDING_WIDTH / 2)));
396  assert((sZ >= 0) && (sZ < PATHFINDING_HEIGHT));
397 
398  const byte* source = base + lump->fileofs;
399 
400  int length = CMod_DeCompressRouting(&source, (byte*)tile.wpMins);
401  length += CMod_DeCompressRouting(&source, (byte*)tile.wpMaxs);
402  length += CMod_DeCompressRouting(&source, (byte*)tempMap);
403 
404  if (length != targetLength)
405  Com_Error(ERR_DROP, "CMod_LoadRouting: Map has BAD routing lump; expected %i got %i", targetLength, length);
406 
407  /* endian swap possibly necessary */
408  for (int i = 0; i < 3; i++) {
409  tile.wpMins[i] = LittleLong(tile.wpMins[i]);
410  tile.wpMaxs[i] = LittleLong(tile.wpMaxs[i]);
411  }
412 
413  Com_DPrintf(DEBUG_ROUTING, "Map:%s Offset:(%i, %i, %i)\n", name, sX, sY, sZ);
414  Com_DPrintf(DEBUG_ROUTING, "wpMins:(%i, %i, %i) wpMaxs:(%i, %i, %i)\n", tile.wpMins[0], tile.wpMins[1],
415  tile.wpMins[2], tile.wpMaxs[0], tile.wpMaxs[1], tile.wpMaxs[2]);
416 
417  /* wpMins and wpMaxs have the map size data from the initial build.
418  * Offset this by the given parameters so the stored values are in real coordinates. */
419  tile.wpMins[0] += sX;
420  tile.wpMins[1] += sY;
421  tile.wpMins[2] += sZ;
422  tile.wpMaxs[0] += sX;
423  tile.wpMaxs[1] += sY;
424  tile.wpMaxs[2] += sZ;
425 
426  Com_DPrintf(DEBUG_ROUTING, "Shifted wpMins:(%i, %i, %i) wpMaxs:(%i, %i, %i)\n", tile.wpMins[0],
427  tile.wpMins[1], tile.wpMins[2], tile.wpMaxs[0], tile.wpMaxs[1], tile.wpMaxs[2]);
428 
429  /* Things that need to be done:
430  * The floor, ceiling, and route data can be copied over from the map.
431  * All data must be regenerated for cells with overlapping content or where new
432  * model data is adjacent to a cell with existing model data. */
433 
434  /* Copy the routing information into our master table */
435  const int minX = std::max(tile.wpMins[0], 0);
436  const int minY = std::max(tile.wpMins[1], 0);
437  const int minZ = std::max(tile.wpMins[2], 0);
438  const int maxX = std::min(tile.wpMaxs[0], PATHFINDING_WIDTH - 1);
439  const int maxY = std::min(tile.wpMaxs[1], PATHFINDING_WIDTH - 1);
440  const int maxZ = std::min(tile.wpMaxs[2], PATHFINDING_HEIGHT - 1);
441 
442  assert(minX <= maxX);
443  assert(minY <= maxY);
444  assert(minZ <= maxZ);
445 
446  Com_DPrintf(DEBUG_ROUTING, "Tile bounds: (%i, %i, %i) to (%i, %i, %i)\n", minX, minY, minZ, maxX, maxY, maxZ);
447  Com_DPrintf(DEBUG_ROUTING, "Source bounds: (%i, %i, %i) to (%i, %i, %i)\n", minX - sX, minY - sY, minZ - sZ,
448  maxX - sX, maxY - sY, maxZ - sZ);
449 
451  /* Adjust starting x and y by size to catch large actor cell overlap. */
452  for (int y = minY - size; y <= maxY; y++)
453  for (int x = minX - size; x <= maxX; x++) {
454  /* Just incase x or y start negative. */
455  if (x < 0 || y < 0)
456  continue;
457  for (int z = minZ; z <= maxZ; z++) {
458  mapData->routing.copyPosData(*tempMap, size + 1, x, y, z, sX, sY, sZ);
459  }
460  /* Update the reroute table */
461  if (!mapData->reroute[size][y][x]) {
462  mapData->reroute[size][y][x] = tile.idx + 1;
463  } else {
464  mapData->reroute[size][y][x] = ROUTING_NOT_REACHABLE;
465  }
466  }
467 
468  Com_DPrintf(DEBUG_ROUTING, "Done copying data.\n");
469 
470  double end = time(nullptr);
471  Com_DPrintf(DEBUG_ROUTING, "Loaded routing for tile %s in %5.1fs\n", name, end - start);
472 
473  Mem_Free(tempMap);
474 }
475 
476 
488 static void CMod_LoadEntityString (MapTile& tile, const char* entityString, mapData_t* mapData, const byte* base, const lump_t* l, const vec3_t shift)
489 {
490  if (!l)
491  Com_Error(ERR_DROP, "CMod_LoadEntityString: No lump given (entitystring: '%s')", entityString ? entityString : "none");
492 
493  if (!l->filelen)
494  Com_Error(ERR_DROP, "CMod_LoadEntityString: Map has NO entity lump (offset: %u, length: %u, entitystring: '%s')", l->fileofs, l->filelen, entityString ? entityString : "none");
495 
496  if (l->filelen + 1 > MAX_MAP_ENTSTRING)
497  Com_Error(ERR_DROP, "CMod_LoadEntityString: Map has too large entity lump (offset: %u, length: %u, entitystring: '%s')", l->fileofs, l->filelen, entityString ? entityString : "none");
498 
499  /* merge entitystring information */
500  const char* es = (const char*) (base + l->fileofs);
501  while (1) {
502  cBspModel_t* model = nullptr;
503  /* parse the opening brace */
504  const char* token = Com_Parse(&es);
505  if (!es)
506  break;
507  if (token[0] != '{')
508  Com_Error(ERR_DROP, "CMod_LoadEntityString: found %s when expecting { (offset: %u, length: %u, remaining: '%s')", token, l->fileofs, l->filelen, es);
509 
510  /* new entity */
511  Q_strcat(mapData->mapEntityString, sizeof(mapData->mapEntityString), "{ ");
512 
513  /* go through all the dictionary pairs */
514  while (1) {
515  /* parse key */
516  token = Com_Parse(&es);
517  if (token[0] == '}')
518  break;
519  if (!es)
520  Com_Error(ERR_DROP, "CMod_LoadEntityString: EOF without closing brace");
521 
522  char keyname[256];
523  Q_strncpyz(keyname, token, sizeof(keyname));
524 
525  /* parse value */
526  token = Com_Parse(&es);
527  if (!es)
528  Com_Error(ERR_DROP, "CMod_LoadEntityString: EOF without closing brace");
529 
530  if (token[0] == '}')
531  Com_Error(ERR_DROP, "CMod_LoadEntityString: closing brace without data for keyname %s", keyname);
532 
533  /* alter value, if needed */
534  if (Q_streq(keyname, "origin")) {
535  /* origins are shifted */
536  vec3_t v;
537  if (sscanf(token, "%f %f %f", &(v[0]), &(v[1]), &(v[2])) != 3)
538  Com_Error(ERR_DROP, "CMod_LoadEntityString: invalid origin token '%s' for keyname %s", token, keyname);
539  VectorAdd(v, shift, v);
540  Q_strcat(mapData->mapEntityString, sizeof(mapData->mapEntityString), "%s \"%f %f %f\" ", keyname, v[0], v[1], v[2]);
541  /* If we have a model, then unadjust it's mins and maxs. */
542  if (model) {
543  VectorSubtract(model->cbmBox.mins, shift, model->cbmBox.mins);
544  VectorSubtract(model->cbmBox.maxs, shift, model->cbmBox.maxs);
545  model = nullptr; /* reset it, or the next origin will shift it again */
546  }
547  } else if (Q_streq(keyname, "model") && token[0] == '*') {
548  /* adapt inline model number */
549  int num = atoi(token + 1);
550  /* Get the model */
551  model = &tile.models[NUM_REGULAR_MODELS + num - 1];
552  /* Now update the model number to reflect prior tiles loaded. */
553  num += mapData->numInline;
554  Q_strcat(mapData->mapEntityString, sizeof(mapData->mapEntityString), "%s *%i ", keyname, num);
555  } else if (Q_streq(keyname, "targetname") || Q_streq(keyname, "target")) {
556  Q_strcat(mapData->mapEntityString, sizeof(mapData->mapEntityString), "%s \"%s-%i\" ", keyname, token, tile.idx);
557  } else {
558  if (Q_streq(keyname, "classname") && Q_streq(token, "worldspawn")) {
559  if (Q_strvalid(entityString))
560  Q_strcat(mapData->mapEntityString, sizeof(mapData->mapEntityString), "%s", entityString);
561  }
562  /* just store key and value */
563  Q_strcat(mapData->mapEntityString, sizeof(mapData->mapEntityString), "%s \"%s\" ", keyname, token);
564  }
565  }
566 
567  /* finish entity */
568  Q_strcat(mapData->mapEntityString, sizeof(mapData->mapEntityString), "} ");
569  }
570 }
571 
576 static void CMod_LoadLighting (MapTile& tile, const byte* base, const lump_t* lump)
577 {
578  if (lump->filelen == 0)
579  return;
580 
582  memcpy(tile.lightdata, base + lump->fileofs, lump->filelen);
583 }
584 
589 static void CM_InitBoxHull (MapTile& tile)
590 {
591  tile.box_headnode = tile.numnodes;
592  tile.box_planes = &tile.planes[tile.numplanes];
593  /* sanity check if you only use one maptile => no map assembly */
594  if (tile.idx == 1 && (tile.numnodes + 6 > MAX_MAP_NODES
595  || tile.numbrushes + 1 > MAX_MAP_BRUSHES
596  || tile.numleafbrushes + 1 > MAX_MAP_LEAFBRUSHES
597  || tile.numbrushsides + 6 > MAX_MAP_BRUSHSIDES
598  || tile.numplanes + 12 > MAX_MAP_PLANES))
599  Com_Error(ERR_DROP, "Not enough room for box tree");
600 
601  tile.box_brush = &tile.brushes[tile.numbrushes];
602  tile.box_brush->numsides = 6;
605 
606  tile.box_leaf = &tile.leafs[tile.numleafs];
609  tile.box_leaf->numleafbrushes = 1;
610 
611  tile.leafbrushes[tile.numleafbrushes] = tile.numbrushes;
612 
613  /* each side */
614  for (int i = 0; i < 6; i++) {
615  const int side = i & 1;
616 
617  /* brush sides */
618  cBspBrushSide_t* s = &tile.brushsides[tile.numbrushsides + i];
619  s->plane = tile.planes + (tile.numplanes + i * 2 + side);
620  s->surface = &nullSurface;
621 
622  /* nodes */
623  cBspNode_t* c = &tile.nodes[tile.box_headnode + i];
624  c->plane = tile.planes + (tile.numplanes + i * 2);
625  c->children[side] = -1 - tile.emptyleaf;
626  if (i != 5)
627  c->children[side ^ 1] = tile.box_headnode + i + 1;
628  else
629  c->children[side ^ 1] = LEAFNODE - tile.numleafs;
630 
631  /* planes */
632  cBspPlane_t* p = &tile.box_planes[i * 2];
633  p->type = i >> 1;
634  VectorClear(p->normal);
635  p->normal[i >> 1] = 1;
636 
637  p = &tile.box_planes[i * 2 + 1];
638  p->type = PLANE_ANYX + (i >> 1);
639  VectorClear(p->normal);
640  p->normal[i >> 1] = -1;
641  }
642 }
643 
644 void CM_LoadBsp (MapTile& tile, const dBspHeader_t& header, const vec3_t shift, const byte* base)
645 {
646  /* load into heap */
647  CMod_LoadSurfaces(tile, base, &header.lumps[LUMP_TEXINFO]);
648  CMod_LoadLeafs(tile, base, &header.lumps[LUMP_LEAFS]);
649  CMod_LoadLeafBrushes(tile, base, &header.lumps[LUMP_LEAFBRUSHES]);
650  CMod_LoadPlanes(tile, base, &header.lumps[LUMP_PLANES], shift);
651  CMod_LoadBrushes(tile, base, &header.lumps[LUMP_BRUSHES]);
652  CMod_LoadBrushSides(tile, base, &header.lumps[LUMP_BRUSHSIDES]);
653  CMod_LoadSubmodels(tile, base, &header.lumps[LUMP_MODELS], shift);
654  CMod_LoadNodes(tile, base, &header.lumps[LUMP_NODES], shift);
655 }
656 
674 static void CM_AddMapTile (const char* name, const char* entityString, const bool day, const int sX, const int sY, const byte sZ, mapData_t* mapData, mapTiles_t* mapTiles)
675 {
676  Com_DPrintf(DEBUG_ENGINE, "CM_AddMapTile: %s at %i,%i,%i\n", name, sX, sY, sZ);
677  assert(name);
678  assert(name[0]);
679  assert((sX > -(PATHFINDING_WIDTH / 2)) && (sX < (PATHFINDING_WIDTH / 2)));
680  assert((sY > -(PATHFINDING_WIDTH / 2)) && (sY < (PATHFINDING_WIDTH / 2)));
681  assert(sZ < PATHFINDING_HEIGHT);
682 
683  /* load the file */
684  char filename[MAX_QPATH];
685  Com_sprintf(filename, sizeof(filename), "maps/%s.bsp", name);
686  byte* buf;
687  const int length = FS_LoadFile(filename, &buf);
688  if (!buf)
689  Com_Error(ERR_DROP, "Couldn't load %s", filename);
690 
691  const unsigned checksum = LittleLong(Com_BlockChecksum(buf, length));
692 
693  dBspHeader_t header = *(dBspHeader_t*) buf;
694  BSP_SwapHeader(&header, filename);
695 
696  if (header.version != BSPVERSION)
697  Com_Error(ERR_DROP, "CM_AddMapTile: %s has wrong version number (%i should be %i)", name, header.version, BSPVERSION);
698 
699  const byte* base = (const byte*) buf;
700 
701  /* init */
702  if (mapTiles->numTiles >= MAX_MAPTILES)
703  Com_Error(ERR_FATAL, "CM_AddMapTile: too many tiles loaded %i", mapTiles->numTiles);
704 
705  MapTile& tile = mapTiles->mapTiles[mapTiles->numTiles];
706  OBJZERO(tile);
707  tile.idx = mapTiles->numTiles;
708  Q_strncpyz(tile.name, name, sizeof(tile.name));
709 
710  /* use for random map assembly for shifting origins and so on */
711  vec3_t shift;
712  /* pathfinding and the like must be shifted on the worldplane when we
713  * are assembling a map */
714  VectorSet(shift, sX * UNIT_SIZE, sY * UNIT_SIZE, sZ * UNIT_HEIGHT);
715 
716  CM_LoadBsp(tile, header, shift, base);
717  CMod_LoadEntityString(tile, entityString, mapData, base, &header.lumps[LUMP_ENTITIES], shift);
718  if (day)
719  CMod_LoadLighting(tile, base, &header.lumps[LUMP_LIGHTING_DAY]);
720  else
721  CMod_LoadLighting(tile, base, &header.lumps[LUMP_LIGHTING_NIGHT]);
722 
723  CM_InitBoxHull(tile);
724  CM_MakeTracingNodes(tile);
725 
726  mapData->numInline += tile.nummodels - NUM_REGULAR_MODELS;
727 
728  CMod_LoadRouting(tile, mapData, base, name, &header.lumps[LUMP_ROUTING], sX, sY, sZ);
729 
730  /* now increase the amount of loaded tiles */
731  mapTiles->numTiles++;
732 
733  /* Now find the map bounds with the updated numTiles. */
734  /* calculate new border after merge */
735  RT_GetMapSize(mapTiles, mapData->mapBox);
736 
737  FS_FreeFile(buf);
738 
739  mapData->mapChecksum += checksum;
740 }
741 
746 {
747  int x, y, z;
748  int cols = 0;
749  /* stopwatch */
750  const double start = time(nullptr);
751 
752  GridBox rBox(mapData->mapBox); /* the box we will actually reroute */
753  rBox.clipToMaxBoundaries();
754 
755  /* First, close the borders of the map. This is needed once we produce tiles with open borders.
756  * It's done by setting the connection (height) to 0 */
757  for (actorSizeEnum_t actorSize = 1; actorSize <= ACTOR_MAX_SIZE; actorSize++) {
758  for (z = rBox.getMinZ(); z <= rBox.getMaxZ(); z++) {
759  for (y = rBox.getMinY(); y <= rBox.getMaxY(); y++) {
760  x = rBox.getMinX();
761  mapData->routing.setConn(actorSize, x, y, z, 6, 0); /* NX-PY */
762  mapData->routing.setConn(actorSize, x, y, z, 1, 0); /* NX */
763  mapData->routing.setConn(actorSize, x, y, z, 5, 0); /* NX-NY */
764  x = rBox.getMaxX();
765  mapData->routing.setConn(actorSize, x, y, z, 4, 0); /* PX-PY */
766  mapData->routing.setConn(actorSize, x, y, z, 0, 0); /* PX */
767  mapData->routing.setConn(actorSize, x, y, z, 7, 0); /* PX-NY */
768  }
769  for (x = rBox.getMinX(); x <= rBox.getMaxX(); x++) {
770  y = rBox.getMinY();
771  mapData->routing.setConn(actorSize, x, y, z, 5, 0); /* NY-NX */
772  mapData->routing.setConn(actorSize, x, y, z, 3, 0); /* NY */
773  mapData->routing.setConn(actorSize, x, y, z, 7, 0); /* NY-PX */
774  y = rBox.getMaxY();
775  mapData->routing.setConn(actorSize, x, y, z, 6, 0); /* PY-NX */
776  mapData->routing.setConn(actorSize, x, y, z, 2, 0); /* PY */
777  mapData->routing.setConn(actorSize, x, y, z, 4, 0); /* PY-PX */
778  }
779  }
780  }
781 
782  /* Floor pass */
783  for (actorSizeEnum_t actorSize = ACTOR_SIZE_INVALID; actorSize < ACTOR_MAX_SIZE; actorSize++) {
784  for (y = rBox.getMinY(); y <= rBox.getMaxY(); y++) {
785  for (x = rBox.getMinX(); x <= rBox.getMaxX(); x++) {
786  if (mapData->reroute[actorSize][y][x] == ROUTING_NOT_REACHABLE) {
787  cols++;
788  for (z = rBox.getMaxZ(); z >= rBox.getMinZ(); z--) {
789  const int newZ = RT_CheckCell(mapTiles, mapData->routing, actorSize + 1, x, y, z, nullptr);
790  assert(newZ <= z);
791  z = newZ;
792  }
793  }
794  }
795  }
796  }
797 
798  /* Wall pass */
799  for (actorSizeEnum_t actorSize = ACTOR_SIZE_INVALID; actorSize < ACTOR_MAX_SIZE; actorSize++) {
800  for (y = rBox.getMinY(); y <= rBox.getMaxY(); y++) {
801  for (x = rBox.getMinX(); x <= rBox.getMaxX(); x++) {
802  const byte tile = mapData->reroute[actorSize][y][x];
803  if (tile) {
804  byte fromTile1 = 0;
805  byte fromTile2 = 0;
806  byte fromTile3 = 0;
807  mapTiles->getTilesAt(x ,y, fromTile1, fromTile2, fromTile3);
808  for (int dir = 0; dir < CORE_DIRECTIONS; dir++) {
809  const int dx = x + dvecs[dir][0];
810  const int dy = y + dvecs[dir][1];
811  /* Skip if the destination is out of bounds. */
812  if (dx < 0 || dx >= PATHFINDING_WIDTH || dy < 0 || dy >= PATHFINDING_WIDTH)
813  continue;
814  const int tile2 = mapData->reroute[actorSize][dy][dx];
815  /* Both cells are present and if either cell is ROUTING_NOT_REACHABLE or if the cells are different. */
816  if (tile2 && (tile2 == ROUTING_NOT_REACHABLE || tile2 != tile)) {
817 #if 0 // this causes problems eg. at baseattack entrance (see bug 5292). Disabled until the underlying problem is found
818  byte toTile1 = 0;
819  byte toTile2 = 0;
820  byte toTile3 = 0;
821  mapTiles->getTilesAt(dx ,dy, toTile1, toTile2, toTile3);
822 
823  int minZ = 0;
824  int maxZ = PATHFINDING_HEIGHT;
825  if (fromTile1 == toTile1) { /* same tile */
826  if (fromTile2 && toTile2) { /* and there are stacked tiles */
827  if (fromTile2 == toTile2) { /* the stacked tiles are also the same */
828  mapTiles->getTileOverlap(toTile1, toTile2, minZ, maxZ); /* reduce the z-range to reroute */
829  }
830  }
831  }
832  RT_UpdateConnectionColumn(mapTiles, mapData->routing, actorSize + 1, x, y, dir, nullptr, minZ, maxZ);
833 #else
834  RT_UpdateConnectionColumn(mapTiles, mapData->routing, actorSize + 1, x, y, dir);
835 #endif // 1
836  }
837  }
838  }
839  }
840  }
841  }
842  const double end = time(nullptr);
843  Com_Printf("Rerouted %i cols for RMA in %5.1fs\n", cols, end - start);
844 }
845 
860 void CM_LoadMap (const char* tiles, bool day, const char* pos, const char* entityString, mapData_t* mapData, mapTiles_t* mapTiles)
861 {
862  char name[MAX_VAR];
863  char base[MAX_QPATH];
864 
866 
867  /* init */
868  base[0] = 0;
869 
870  /* Reset the map related data */
871  OBJZERO(*mapData);
872  OBJZERO(*mapTiles);
873 
874  /* load tiles */
875  while (tiles) {
876  /* get tile name */
877  const char* token = Com_Parse(&tiles);
878  if (!tiles) {
879  CMod_RerouteMap(mapTiles, mapData);
880  return;
881  }
882 
883  /* get base path */
884  if (token[0] == '-') {
885  Q_strncpyz(base, token + 1, sizeof(base));
886  continue;
887  }
888 
889  /* get tile name */
890  Com_DPrintf(DEBUG_ENGINE, "CM_LoadMap: token: %s\n", token);
891  if (token[0] == '+')
892  Com_sprintf(name, sizeof(name), "%s%s", base, token + 1);
893  else
894  Q_strncpyz(name, token, sizeof(name));
895 
896  if (pos && pos[0]) {
897  ipos3_t sh;
898  /* get position and add a tile */
899  for (int i = 0; i < 3; i++) {
900  token = Com_Parse(&pos);
901  if (!pos)
902  Com_Error(ERR_DROP, "CM_LoadMap: invalid positions");
903  sh[i] = atoi(token);
904  }
905  if (sh[0] <= -(PATHFINDING_WIDTH / 2) || sh[0] >= PATHFINDING_WIDTH / 2)
906  Com_Error(ERR_DROP, "CM_LoadMap: invalid x position given: %i\n", sh[0]);
907  if (sh[1] <= -(PATHFINDING_WIDTH / 2) || sh[1] >= PATHFINDING_WIDTH / 2)
908  Com_Error(ERR_DROP, "CM_LoadMap: invalid y position given: %i\n", sh[1]);
909  if (sh[2] >= PATHFINDING_HEIGHT)
910  Com_Error(ERR_DROP, "CM_LoadMap: invalid z position given: %i\n", sh[2]);
911  CM_AddMapTile(name, entityString, day, sh[0], sh[1], sh[2], mapData, mapTiles);
912  } else {
913  /* load only a single tile, if no positions are specified */
914  CM_AddMapTile(name, entityString, day, 0, 0, 0, mapData, mapTiles);
915  return;
916  }
917  }
918 
919  Com_Error(ERR_DROP, "CM_LoadMap: invalid tile names");
920 }
921 
930 {
931  /* we only want inline models here */
932  if (!name || name[0] != '*')
933  Com_Error(ERR_DROP, "CM_InlineModel: bad name: '%s'", name ? name : "");
934  /* skip the '*' character and get the inline model number */
935  int num = atoi(name + 1) - 1;
936  if (num < 0 || num >= MAX_MODELS)
937  Com_Error(ERR_DROP, "CM_InlineModel: bad number %i - max inline models are %i", num, MAX_MODELS);
938 
939  /* search all the loaded tiles for the given inline model */
940  for (int i = 0; i < mapTiles->numTiles; i++) {
941  const int models = mapTiles->mapTiles[i].nummodels - NUM_REGULAR_MODELS;
942  assert(models >= 0);
943 
944  if (num >= models)
945  num -= models;
946  else
947  return &(mapTiles->mapTiles[i].models[NUM_REGULAR_MODELS + num]);
948  }
949 
950  Com_Error(ERR_DROP, "CM_InlineModel: Error cannot find model '%s'\n", name);
951 }
952 
964 {
965  cBspModel_t* model = CM_InlineModel(mapTiles, name);
966  assert(model);
967  VectorCopy(origin, model->origin);
968  VectorCopy(angles, model->angles);
969 
970  return model;
971 }
972 
979 void CM_GetInlineModelAABB (mapTiles_t* mapTiles, const char* name, AABB& aabb)
980 {
981  const cBspModel_t* model = CM_InlineModel(mapTiles, name);
982  assert(model);
983  CalculateMinsMaxs(model->angles, model->cbmBox, model->origin, aabb);
984 }
985 
991 float CM_GetVisibility (const mapTiles_t* mapTiles, const pos3_t position)
992 {
993  for (int i = 0; i < mapTiles->numTiles; i++) {
994  const MapTile& tile = mapTiles->mapTiles[i];
995  if (VectorInside(position, tile.wpMins, tile.wpMaxs)) {
996  if (tile.lightdata == nullptr)
997  return 1.0f;
999  return 1.0f;
1000  }
1001  }
1002 
1003  /* point is outside of any loaded tile */
1004  Com_Printf("given point %i:%i:%i is not inside of any loaded tile\n", position[0], position[1], position[2]);
1005  return 1.0f;
1006 }
#define LEAFNODE
Definition: defines.h:44
uint32_t version
Definition: qfiles.h:264
#define LUMP_LIGHTING_DAY
Definition: defines.h:175
void CalculateMinsMaxs(const vec3_t angles, const AABB &relBox, const vec3_t origin, AABB &absBox)
Calculates the bounding box in absolute coordinates, also for rotating objects. WARNING: do not use t...
Definition: mathlib.cpp:546
void getTileOverlap(const byte tile1, const byte tile2, int &minZ, int &maxZ)
Definition: tracing.cpp:498
static void CMod_LoadLeafs(MapTile &tile, const byte *base, const lump_t *lump)
Definition: bsp.cpp:185
static ipos3_t shift
The shift array is used for random map assemblies (RMA) to shift the mins/maxs and stuff like that...
#define VectorCopy(src, dest)
Definition: vector.h:51
int firstbrushside
Definition: typedefs.h:62
static void CMod_LoadNodes(MapTile &tile, const byte *base, const lump_t *lump, const vec3_t shift)
Definition: bsp.cpp:123
cBspModel_t * models
Definition: typedefs.h:110
#define CONTENTS_WEAPONCLIP
Definition: defines.h:249
int numleafs
Definition: typedefs.h:102
pos_t getMinZ() const
Definition: mathlib.h:180
#define VectorSet(v, x, y, z)
Definition: vector.h:59
static cBspSurface_t nullSurface
Definition: bsp.cpp:33
vec3_t origin
Definition: typedefs.h:28
unsigned mapChecksum
Definition: typedefs.h:336
short mins[3]
Definition: typedefs.h:381
cBspPlane_t * plane
Definition: typedefs.h:43
static void CMod_LoadPlanes(MapTile &tile, const byte *base, const lump_t *lump, const vec3_t shift)
Definition: bsp.cpp:224
#define PLANE_ANYX
Definition: defines.h:196
static int CMod_DeCompressRouting(const byte **source, byte *dataStart)
Definition: bsp.cpp:304
pos_t getMaxY() const
Definition: mathlib.h:186
int firstbrushside
Definition: typedefs.h:435
#define LUMP_NODES
Definition: defines.h:171
pos_t getMaxX() const
Definition: mathlib.h:183
mapTiles_t mapTiles
Definition: bsp.cpp:33
cBspLeaf_t * box_leaf
Definition: typedefs.h:119
int numtexinfo
Definition: typedefs.h:93
#define ACTOR_MAX_SIZE
Definition: defines.h:305
vec3_t normal
Definition: typedefs.h:21
cBspNode_t * nodes
Definition: typedefs.h:100
#define CONTENTS_SOLID
Definition: defines.h:223
#define MAX_MAP_PLANES
Definition: defines.h:139
void CM_LoadBsp(MapTile &tile, const dBspHeader_t &header, const vec3_t shift, const byte *base)
Definition: bsp.cpp:644
voidpf uLong int origin
Definition: ioapi.h:45
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
int numbrushes
Definition: typedefs.h:112
int32_t actorSizeEnum_t
Definition: ufotypes.h:77
uint32_t surfaceFlags
Definition: typedefs.h:39
Definition: aabb.h:42
static void CM_InitBoxHull(MapTile &tile)
Set up the planes and nodes so that the six floats of a bounding box can just be stored out and get a...
Definition: bsp.cpp:589
const char * filename
Definition: ioapi.h:41
uint32_t contentFlags
Definition: typedefs.h:54
int numsides
Definition: typedefs.h:436
float dist
Definition: typedefs.h:22
#define MAX_MAP_LEAFS
Definition: defines.h:142
cBspPlane_t * box_planes
Definition: typedefs.h:116
#define UNIT_HEIGHT
Definition: defines.h:122
const vec4_t dvecs[PATHFINDING_DIRECTIONS]
Definition: mathlib.cpp:58
unsigned Com_BlockChecksum(const void *buffer, int length)
Definition: md4.cpp:202
static void CMod_LoadLeafBrushes(MapTile &tile, const byte *base, const lump_t *lump)
Definition: bsp.cpp:254
Data for line tracing (?)
Definition: typedefs.h:69
static void CMod_LoadLighting(MapTile &tile, const byte *base, const lump_t *lump)
Loads the lightmap for server side visibility lookup.
Definition: bsp.cpp:576
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition: files.cpp:384
uint32_t filelen
Definition: qfiles.h:258
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
static void CMod_LoadEntityString(MapTile &tile, const char *entityString, mapData_t *mapData, const byte *base, const lump_t *l, const vec3_t shift)
Definition: bsp.cpp:488
int numbrushsides
Definition: typedefs.h:90
vec3_t maxs
Definition: aabb.h:258
#define LUMP_MODELS
Definition: defines.h:180
cBspBrush_t * brushes
Definition: typedefs.h:113
#define DEBUG_ROUTING
Definition: defines.h:66
convex region of space in the BSP tree
Definition: typedefs.h:416
cBspSurface_t * surfaces
Definition: typedefs.h:94
unsigned short firstleafbrush
Definition: typedefs.h:55
voidpf void * buf
Definition: ioapi.h:42
#define ERR_FATAL
Definition: common.h:210
intptr_t thead[LEVEL_MAX]
Definition: typedefs.h:124
ipos_t ipos3_t[3]
Definition: ufotypes.h:70
int numtheads
Definition: typedefs.h:123
#define LUMP_BRUSHES
Definition: defines.h:181
int tile
Definition: typedefs.h:31
#define LUMP_PLANES
Definition: defines.h:168
#define Q_strvalid(string)
Definition: shared.h:141
Directory of the different data blocks.
Definition: qfiles.h:256
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
Stores the data of a map tile, mostly the BSP stuff.
Definition: typedefs.h:85
vec3_t shift
Definition: typedefs.h:28
void expand(const float byVal)
expand the box in all directions, but clip them to the maximum boundaries
Definition: aabb.h:240
int32_t children[2]
Definition: typedefs.h:45
byte type
Definition: typedefs.h:23
byte reroute[ACTOR_MAX_SIZE][PATHFINDING_WIDTH][PATHFINDING_WIDTH]
Used to track where rerouting needs to occur.
Definition: typedefs.h:340
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
int numInline
Definition: typedefs.h:334
#define MAX_MAP_BRUSHSIDES
Definition: defines.h:141
#define PATHFINDING_WIDTH
absolute max
Definition: defines.h:292
#define LittleShort(X)
Definition: byte.h:35
#define ERR_DROP
Definition: common.h:211
#define DEBUG_ENGINE
Definition: defines.h:56
GLsizei size
Definition: r_gl.h:152
#define LUMP_LIGHTING_NIGHT
Definition: defines.h:174
#define OBJZERO(obj)
Definition: shared.h:178
void TR_BuildTracingNode_r(TR_TILE_TYPE *tile, tnode_t **tnode, int32_t nodenum, int level)
Definition: tracing.cpp:122
#define MAX_VAR
Definition: shared.h:36
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition: r_gl.h:110
#define MAX_MAP_ENTSTRING
Definition: defines.h:137
float CM_GetVisibility(const mapTiles_t *mapTiles, const pos3_t position)
Checks how well a position is visible.
Definition: bsp.cpp:991
#define NUM_REGULAR_MODELS
Definition: defines.h:354
uint32_t fileofs
Definition: qfiles.h:257
pos_t getMinY() const
Definition: mathlib.h:177
#define LUMP_ROUTING
Definition: defines.h:170
pos_t getMinX() const
Definition: mathlib.h:174
#define Mem_Alloc(size)
Definition: mem.h:40
int nummodels
Definition: typedefs.h:109
void CM_GetInlineModelAABB(mapTiles_t *mapTiles, const char *name, AABB &aabb)
This function calculates a model's aabb in world coordinates.
Definition: bsp.cpp:979
#define S_COLOR_GREEN
Definition: common.h:219
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
static void CM_AddMapTile(const char *name, const char *entityString, const bool day, const int sX, const int sY, const byte sZ, mapData_t *mapData, mapTiles_t *mapTiles)
Adds in a single map tile.
Definition: bsp.cpp:674
tnode_t * tnodes
Definition: typedefs.h:122
void getTilesAt(int x, int y, byte &fromTile1, byte &fromTile2, byte &fromTile3)
Definition: tracing.cpp:478
pos_t pos3_t[3]
Definition: ufotypes.h:58
Header for various formats like pak, and model formats as well as bsp format.
cBspLeaf_t * leafs
Definition: typedefs.h:103
vec3_t angles
Definition: typedefs.h:28
void clipToMaxBoundaries()
Definition: mathlib.h:215
static void CMod_LoadSurfaces(MapTile &tile, const byte *base, const lump_t *lump)
Definition: bsp.cpp:97
grid pathfinding and routing
AABB cbmBox
Definition: typedefs.h:27
#define Mem_FreePool(pool)
Definition: mem.h:37
uint32_t brushContentFlags
Definition: typedefs.h:60
#define MAX_MAP_MODELS
Definition: defines.h:134
#define UNIT_SIZE
Definition: defines.h:121
cBspModel_t * CM_InlineModel(const mapTiles_t *mapTiles, const char *name)
Searches all inline models and return the cBspModel_t pointer for the given modelnumber or -name...
Definition: bsp.cpp:929
QGL_EXTERN GLuint count
Definition: r_gl.h:99
#define VectorClear(a)
Definition: vector.h:55
void setFromLittleFloat(const AABB &other)
Definition: aabb.h:87
#define MAX_MODELS
Definition: defines.h:100
void RT_UpdateConnectionColumn(mapTiles_t *mapTiles, Routing &routing, const int actorSize, const int x, const int y, const int dir, const char **list, const int minZ, const int maxZ)
Routing Function to update the connection between two fields.
Definition: routing.cpp:1292
static void CMod_RerouteMap(mapTiles_t *mapTiles, mapData_t *mapData)
Recalculate the seams of the tiles after an RMA.
Definition: bsp.cpp:745
#define LUMP_ENTITIES
Definition: defines.h:167
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
#define PATHFINDING_HEIGHT
15 max, adjusting above 8 will require a rewrite to the DV code
Definition: defines.h:294
#define VectorAdd(a, b, dest)
Definition: vector.h:47
The BSP header definition with the data block directory.
Definition: qfiles.h:262
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition: parse.cpp:107
int numplanes
Definition: typedefs.h:96
lump_t lumps[HEADER_LUMPS]
Definition: qfiles.h:265
memPool_t * com_cmodelSysPool
Definition: common.cpp:70
char name[MAX_QPATH]
Definition: typedefs.h:38
cBspSurface_t * surface
Definition: typedefs.h:50
int numTiles
Definition: tracing.h:82
#define PLANENUM_LEAF
Definition: defines.h:45
TR_TILE_TYPE mapTiles[MAX_MAPTILES]
Definition: tracing.h:79
#define MAX_QPATH
Definition: filesys.h:40
QGL_EXTERN GLint i
Definition: r_gl.h:113
int numnodes
Definition: typedefs.h:99
ipos3_t wpMaxs
Definition: typedefs.h:131
static void CMod_LoadBrushSides(MapTile &tile, const byte *base, const lump_t *lump)
Definition: bsp.cpp:276
pos_t getMaxZ() const
Definition: mathlib.h:189
int idx
Definition: typedefs.h:88
void setConn(const int actorSize, const int x, const int y, const int z, const int dir, const int val)
Definition: typedefs.h:288
void RT_GetMapSize(mapTiles_t *mapTiles, AABB &mapBox)
Calculate the map size via model data and store grid size in map_min and map_max. This is done with e...
Definition: routing.cpp:253
int32_t children[2]
Definition: typedefs.h:380
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
#define CORE_DIRECTIONS
Definition: mathlib.h:88
cBspBrushSide_t * brushsides
Definition: typedefs.h:91
int numsides
Definition: typedefs.h:61
static void CM_MakeTracingNodes(MapTile &tile)
Use the bsp node structure to reconstruct efficient tracing structures that are used for fast visibil...
Definition: bsp.cpp:345
char mapEntityString[MAX_MAP_ENTSTRING]
Definition: typedefs.h:331
#define Mem_Free(ptr)
Definition: mem.h:35
cBspModel_t * CM_SetInlineModelOrientation(mapTiles_t *mapTiles, const char *name, const vec3_t origin, const vec3_t angles)
This function updates a model's orientation.
Definition: bsp.cpp:963
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
#define UFO_SIZE_T
Definition: ufotypes.h:89
vec_t vec3_t[3]
Definition: ufotypes.h:39
int numleafbrushes
Definition: typedefs.h:106
int RT_CheckCell(mapTiles_t *mapTiles, Routing &routing, const int actorSize, const int x, const int y, const int z, const char **list)
This function looks to see if an actor of a given size can occupy a cell(s) and if so identifies the ...
Definition: routing.cpp:360
#define LUMP_BRUSHSIDES
Definition: defines.h:182
unsigned short * leafbrushes
Definition: typedefs.h:107
definitions common between client and server, but not game lib
void shift(const vec3_t shiftVec)
shove the whole box by the given vector
Definition: aabb.h:246
#define LUMP_LEAFBRUSHES
Definition: defines.h:177
ipos3_t wpMins
Definition: typedefs.h:130
cBspPlane_t * plane
Definition: typedefs.h:49
int32_t headnode
Definition: typedefs.h:29
vec3_t mins
Definition: aabb.h:257
AABB mapBox
Definition: typedefs.h:351
static int CMod_ValidateLump(const lump_t *lump, const char *functionName, size_t elementSize, const char *elementName, int elementMaxCount)
Definition: bsp.cpp:41
uint32_t brushContentFlags
Definition: typedefs.h:437
char name[MAX_QPATH]
Definition: typedefs.h:87
#define MAX_MAP_LEAFBRUSHES
Definition: defines.h:145
int32_t planenum
Definition: typedefs.h:379
#define Q_streq(a, b)
Definition: shared.h:136
cBspBrush_t * box_brush
Definition: typedefs.h:118
#define LUMP_TEXINFO
Definition: defines.h:172
#define BSPVERSION
Definition: qfiles.h:253
static void CMod_LoadRouting(MapTile &tile, mapData_t *mapData, const byte *base, const char *name, const lump_t *lump, const int sX, const int sY, const int sZ)
Definition: bsp.cpp:380
static void CMod_LoadBrushes(MapTile &tile, const byte *base, const lump_t *lump)
Definition: bsp.cpp:160
byte * lightdata
Definition: typedefs.h:134
int emptyleaf
Definition: typedefs.h:104
int theadlevel[LEVEL_MAX]
Definition: typedefs.h:125
void copyPosData(const Routing &other, actorSizeEnum_t actorSize, const int x, const int y, const int z, const int sX, const int sY, const int sZ)
Definition: typedefs.h:317
#define BSP_SwapHeader(header, name)
Definition: qfiles.h:269
cBspPlane_t * planes
Definition: typedefs.h:97
#define ROUTING_NOT_REACHABLE
Definition: defines.h:283
Routing routing
Definition: typedefs.h:341
int box_headnode
Definition: typedefs.h:117
short maxs[3]
Definition: typedefs.h:382
#define LUMP_LEAFS
Definition: defines.h:176
uint8_t byte
Definition: ufotypes.h:34
static mapData_t mapData
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
#define LEVEL_MAX
Definition: defines.h:353
#define ACTOR_SIZE_INVALID
Definition: defines.h:301
plane_t structure
Definition: typedefs.h:20
#define MAX_MAP_BRUSHES
Definition: defines.h:135
#define MAX_MAP_TEXINFO
Definition: defines.h:138
int numcheads
Definition: typedefs.h:127
#define VectorSubtract(a, b, dest)
Definition: vector.h:45
Tracing functions.
void CM_LoadMap(const char *tiles, bool day, const char *pos, const char *entityString, mapData_t *mapData, mapTiles_t *mapTiles)
Loads in the map and all submodels.
Definition: bsp.cpp:860
#define VectorInside(vec, mins, maxs)
Definition: vector.h:56
unsigned short numleafbrushes
Definition: typedefs.h:56
#define LittleFloat(X)
Definition: byte.h:57
void FS_FreeFile(void *buffer)
Definition: files.cpp:411
#define LittleLong(X)
Definition: byte.h:37
static void CMod_LoadSubmodels(MapTile &tile, const byte *base, const lump_t *lump, const vec3_t shift)
Loads brush entities like func_door and func_breakable.
Definition: bsp.cpp:68
#define MAX_MAP_NODES
Definition: defines.h:140