UFO: Alien Invasion
Loading...
Searching...
No Matches
map.cpp
Go to the documentation of this file.
1
4
5/*
6Copyright (C) 1997-2001 Id Software, Inc.
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23*/
24
25
26#include "map.h"
27#include "bsp.h"
28#include "textures.h"
29#include "check/check.h"
30#include "check/checkentities.h"
31#include "common/aselib.h"
32#include "../../shared/parse.h"
33
36
39
41
45
46#define PLANE_HASHES 1024
48
49static int c_boxbevels = 0;
50static int c_edgebevels = 0;
51
52/*
53=============================================================================
54PLANE FINDING
55=============================================================================
56*/
57
62static inline int GetPlaneHashValueForDistance (const vec_t distance)
63{
64 int hash = (int)fabs(distance) * 27;
65 hash &= (PLANE_HASHES - 1);
66 return hash;
67}
68
72static int PlaneTypeForNormal (const vec3_t normal)
73{
74 vec_t ax, ay, az;
75
76 /* NOTE: should these have an epsilon around 1.0? */
77 if (normal[0] == 1.0 || normal[0] == -1.0)
78 return PLANE_X;
79 if (normal[1] == 1.0 || normal[1] == -1.0)
80 return PLANE_Y;
81 if (normal[2] == 1.0 || normal[2] == -1.0)
82 return PLANE_Z;
83
84 ax = fabs(normal[0]);
85 ay = fabs(normal[1]);
86 az = fabs(normal[2]);
87
88 if (ax >= ay && ax >= az)
89 return PLANE_ANYX;
90 if (ay >= ax && ay >= az)
91 return PLANE_ANYY;
92 return PLANE_ANYZ;
93}
94
102static inline bool PlaneEqual (const plane_t* p, const vec3_t normal, const vec_t dist)
103{
104 if (fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON
105 && fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON
106 && fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON
107 && fabs(p->dist - dist) < MAP_DIST_EPSILON)
108 return true;
109 return false;
110}
111
112static inline void AddPlaneToHash (plane_t* p)
113{
114 const int hash = GetPlaneHashValueForDistance(p->dist);
116 planehash[hash] = p;
117}
118
119static uint16_t CreateNewFloatPlane (vec3_t normal, vec_t dist)
120{
121 plane_t* p;
122
123 if (VectorLength(normal) < 0.5)
124 Sys_Error("FloatPlane: bad normal (%.3f:%.3f:%.3f)", normal[0], normal[1], normal[2]);
125 /* create a new plane */
127 Sys_Error("MAX_MAP_PLANES (%i)", nummapplanes + 2);
128
130 VectorCopy(normal, p->normal);
131 p->dist = dist;
132 p->type = (p + 1)->type = PlaneTypeForNormal(p->normal);
133
134 VectorSubtract(vec3_origin, normal, (p + 1)->normal);
135 (p + 1)->dist = -dist;
136
137 nummapplanes += 2;
138
139 /* always put axial planes facing positive first */
140 if (AXIAL(p)) {
141 if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0) {
142 /* flip order by swapping the planes */
143 const plane_t temp = *p;
144 *p = *(p + 1);
145 *(p + 1) = temp;
146
148 AddPlaneToHash(p + 1);
149 return nummapplanes - 1;
150 }
151 }
152
154 AddPlaneToHash(p + 1);
155 return nummapplanes - 2;
156}
157
163static inline bool SnapVector (vec3_t normal)
164{
165 for (int i = 0; i < 3; i++) {
166 if (fabs(normal[i] - 1) < NORMAL_EPSILON) {
167 VectorClear(normal);
168 normal[i] = 1;
169 return true;
170 }
171 if (fabs(normal[i] - -1) < NORMAL_EPSILON) {
172 VectorClear(normal);
173 normal[i] = -1;
174 return true;
175 }
176 }
177 return false;
178}
179
186static inline void SnapPlane (vec3_t normal, vec_t* dist)
187{
188 SnapVector(normal);
189
190 if (fabs(*dist - Q_rint(*dist)) < MAP_DIST_EPSILON)
191 *dist = Q_rint(*dist);
192}
193
194uint16_t FindOrCreateFloatPlane (vec3_t normal, vec_t dist)
195{
196 int i;
197 plane_t* p;
198 int hash;
199
200 SnapPlane(normal, &dist);
202
203 /* search the border bins as well */
204 for (i = -1; i <= 1; i++) {
205 const int h = (hash + i) & (PLANE_HASHES - 1);
206 for (p = planehash[h]; p; p = p->hash_chain) {
207 if (PlaneEqual(p, normal, dist)) {
208 const intptr_t index = p - mapplanes;
209 return (int16_t)index;
210 }
211 }
212 }
213
214 return CreateNewFloatPlane(normal, dist);
215}
216
227static int16_t PlaneFromPoints (const mapbrush_t* b, const vec3_t p0, const vec3_t p1, const vec3_t p2)
228{
229 vec3_t t1, t2, normal;
230 vec_t dist;
231
232 VectorSubtract(p0, p1, t1);
233 VectorSubtract(p2, p1, t2);
234 CrossProduct(t1, t2, normal);
235 VectorNormalize(normal);
236
237 dist = DotProduct(p0, normal);
238
239 if (!VectorNotEmpty(normal))
240 Sys_Error("PlaneFromPoints: Bad normal (null) for brush %i", b->brushnum);
241
242 return FindOrCreateFloatPlane(normal, dist);
243}
244
245
246/*==================================================================== */
247
248
255{
256 int contentFlags, i;
257 const side_t* s;
258
259 s = &b->original_sides[0];
260 contentFlags = s->contentFlags;
261 for (i = 1; i < b->numsides; i++, s++) {
262 if (s->contentFlags != contentFlags) {
263 Verb_Printf(VERB_EXTRA, "Entity %i, Brush %i: mixed face contents (f: %i, %i)\n"
264 , b->entitynum, b->brushnum, s->contentFlags, contentFlags);
265 break;
266 }
267 }
268
269 return contentFlags;
270}
271
278{
279 const byte levelflags = (brush->contentFlags >> 8) & 0xFF;
280 return levelflags;
281}
282
283/*============================================================================ */
284
290{
291 int axis, dir;
292 int i, l, order;
293 vec3_t normal;
294
295 /* add the axial planes */
296 order = 0;
297 for (axis = 0; axis < 3; axis++) {
298 for (dir = -1; dir <= 1; dir += 2, order++) {
299 side_t* s;
300 /* see if the plane is already present */
301 for (i = 0, s = b->original_sides; i < b->numsides; i++, s++) {
302 if (mapplanes[s->planenum].normal[axis] == dir)
303 break;
304 }
305
306 if (i == b->numsides) { /* add a new side */
307 float dist;
309 Sys_Error("MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides);
311 b->numsides++;
312 VectorClear(normal);
313 normal[axis] = dir;
314 if (dir == 1)
315 dist = b->mbBox.maxs[axis];
316 else
317 dist = -b->mbBox.mins[axis];
318 s->planenum = FindOrCreateFloatPlane(normal, dist);
319 s->texinfo = b->original_sides[0].texinfo;
320 s->contentFlags = b->original_sides[0].contentFlags;
321 s->bevel = true;
322 c_boxbevels++;
323 }
324
325 /* if the plane is not in it canonical order, swap it */
326 if (i != order) {
327 const ptrdiff_t index = b->original_sides - brushsides;
328 side_t sidetemp = b->original_sides[order];
329 brush_texture_t tdtemp = side_brushtextures[index + order];
330
331 b->original_sides[order] = b->original_sides[i];
332 b->original_sides[i] = sidetemp;
333
335 side_brushtextures[index + i] = tdtemp;
336 }
337 }
338 }
339
340 /* add the edge bevels */
341 if (b->numsides == 6)
342 return; /* pure axial */
343
344 /* test the non-axial plane edges */
345 for (i = 6; i < b->numsides; i++) {
346 side_t* s = b->original_sides + i;
347 winding_t* w = s->winding;
348 if (!w)
349 continue;
350
351 for (int j = 0; j < w->numpoints; j++) {
352 int k = (j + 1) % w->numpoints;
353 vec3_t vec;
354
355 VectorSubtract(w->p[j], w->p[k], vec);
356 if (VectorNormalize(vec) < 0.5)
357 continue;
358
359 SnapVector(vec);
360
361 for (k = 0; k < 3; k++)
362 if (vec[k] == -1 || vec[k] == 1
363 || (vec[k] == 0.0f && vec[(k + 1) % 3] == 0.0f))
364 break; /* axial */
365 if (k != 3)
366 continue; /* only test non-axial edges */
367
368 /* try the six possible slanted axials from this edge */
369 for (axis = 0; axis < 3; axis++) {
370 for (dir = -1; dir <= 1; dir += 2) {
371 /* construct a plane */
372 vec3_t vec2 = {0, 0, 0};
373 float dist;
374 side_t* s2;
375
376 vec2[axis] = dir;
377 CrossProduct(vec, vec2, normal);
378 if (VectorNormalize(normal) < 0.5)
379 continue;
380 dist = DotProduct(w->p[j], normal);
381
382 /* if all the points on all the sides are
383 * behind this plane, it is a proper edge bevel */
384 for (k = 0; k < b->numsides; k++) {
385 winding_t* w2;
386 float minBack;
387
388 /* @note: This leads to different results on different archs
389 * due to float rounding/precision errors - use the -ffloat-store
390 * feature of gcc to 'fix' this */
391 /* if this plane has already been used, skip it */
392 if (PlaneEqual(&mapplanes[b->original_sides[k].planenum], normal, dist))
393 break;
394
395 w2 = b->original_sides[k].winding;
396 if (!w2)
397 continue;
398 minBack = 0.0f;
399 for (l = 0; l < w2->numpoints; l++) {
400 const float d = DotProduct(w2->p[l], normal) - dist;
401 if (d > 0.1)
402 break; /* point in front */
403 if (d < minBack)
404 minBack = d;
405 }
406 /* if some point was at the front */
407 if (l != w2->numpoints)
408 break;
409 /* if no points at the back then the winding is on the bevel plane */
410 if (minBack > -0.1f)
411 break;
412 }
413
414 if (k != b->numsides)
415 continue; /* wasn't part of the outer hull */
416 /* add this plane */
418 Sys_Error("MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides);
420 s2 = &b->original_sides[b->numsides];
421 s2->planenum = FindOrCreateFloatPlane(normal, dist);
422 s2->texinfo = b->original_sides[0].texinfo;
423 s2->contentFlags = b->original_sides[0].contentFlags;
424 s2->bevel = true;
425 c_edgebevels++;
426 b->numsides++;
427 }
428 }
429 }
430 }
431}
432
436static bool MakeBrushWindings (mapbrush_t* brush)
437{
438 int i, j;
439
440 brush->mbBox.setNegativeVolume();
441
442 for (i = 0; i < brush->numsides; i++) {
443 const plane_t* plane = &mapplanes[brush->original_sides[i].planenum];
444 winding_t* w = BaseWindingForPlane(plane->normal, plane->dist);
445 for (j = 0; j < brush->numsides && w; j++) {
446 if (i == j)
447 continue;
448 /* back side clipaway */
449 if (brush->original_sides[j].planenum == (brush->original_sides[j].planenum ^ 1))
450 continue;
451 if (brush->original_sides[j].bevel)
452 continue;
453 plane = &mapplanes[brush->original_sides[j].planenum ^ 1];
454 ChopWindingInPlace(&w, plane->normal, plane->dist, 0); /*CLIP_EPSILON); */
455 }
456
457 side_t* side = &brush->original_sides[i];
458 side->winding = w;
459 if (w) {
460 side->visible = true;
461 for (j = 0; j < w->numpoints; j++)
462 brush->mbBox.add(w->p[j]);
463 }
464 }
465
466 for (i = 0; i < 3; i++) {
467 if (brush->mbBox.mins[i] < -MAX_WORLD_WIDTH || brush->mbBox.maxs[i] > MAX_WORLD_WIDTH)
468 Com_Printf("entity %i, brush %i: bounds out of world range (%f:%f)\n",
469 brush->entitynum, brush->brushnum, brush->mbBox.mins[i], brush->mbBox.maxs[i]);
470 if (brush->mbBox.mins[i] > MAX_WORLD_WIDTH || brush->mbBox.maxs[i] < -MAX_WORLD_WIDTH) {
471 Com_Printf("entity %i, brush %i: no visible sides on brush\n", brush->entitynum, brush->brushnum);
472 brush->mbBox.reset();
473 }
474 }
475
476 return true;
477}
478
484static inline void CheckFlags (side_t* side, const mapbrush_t* b)
485{
487 Sys_Error("Brush %i (entity %i) has invalid mix of passable and actorclip", b->brushnum, b->entitynum);
489 Sys_Error("Brush %i (entity %i) has invalid mix of clips and solid flags", b->brushnum, b->entitynum);
490}
491
493static int materialsCnt = 0;
494
498static void GenerateMaterialFile (const char* filename, int mipTexIndex, side_t* s)
499{
500 bool terrainByTexture = false;
501 char fileBase[MAX_OSPATH], materialPath[MAX_OSPATH];
502
503 if (!config.generateMaterialFile)
504 return;
505
506 /* we already have a material definition for this texture */
507 if (textureref[mipTexIndex].materialMarked)
508 return;
509
510 assert(filename);
511
512 Com_StripExtension(filename, fileBase, sizeof(fileBase));
513 Com_sprintf(materialPath, sizeof(materialPath), "materials/%s.mat", Com_SkipPath(fileBase));
514
516 FS_OpenFile(materialPath, &f, FILE_APPEND);
517 if (!f) {
518 Com_Printf("Could not open material file '%s' for writing\n", materialPath);
519 config.generateMaterialFile = false;
520 return;
521 }
522
523 if (strstr(textureref[mipTexIndex].name, "dirt")
524 || strstr(textureref[mipTexIndex].name, "rock")
525 || strstr(textureref[mipTexIndex].name, "grass")) {
526 terrainByTexture = true;
527 }
528
529 if ((s->contentFlags & CONTENTS_TERRAIN) || terrainByTexture) {
530 FS_Printf(&f, "{\n\tmaterial %s\n\t{\n\t\ttexture <fillme>\n\t\tterrain 0 64\n\t\tlightmap\n\t}\n}\n", textureref[mipTexIndex].name);
531 textureref[mipTexIndex].materialMarked = true;
532 materialsCnt++;
533 }
534
535 /* envmap for water surfaces */
537 || strstr(textureref[mipTexIndex].name, "glass")
538 || strstr(textureref[mipTexIndex].name, "window")) {
539 FS_Printf(&f, "{\n\tmaterial %s\n\tspecular 2.0\n\t{\n\t\tenvmap 0\n\t}\n}\n", textureref[mipTexIndex].name);
540 textureref[mipTexIndex].materialMarked = true;
541 materialsCnt++;
542 }
543
544 if (strstr(textureref[mipTexIndex].name, "wood")) {
545 FS_Printf(&f, "{\n\tmaterial %s\n\tspecular 0.2\n}\n", textureref[mipTexIndex].name);
546 textureref[mipTexIndex].materialMarked = true;
547 materialsCnt++;
548 }
549
550 if (strstr(textureref[mipTexIndex].name, "wall")) {
551 FS_Printf(&f, "{\n\tmaterial %s\n\tspecular 0.6\n\tbump 2.0\n}\n", textureref[mipTexIndex].name);
552 textureref[mipTexIndex].materialMarked = true;
553 materialsCnt++;
554 }
555}
556
558static int footstepsCnt = 0;
559
568static void GenerateFootstepList (const char* filename, int mipTexIndex)
569{
570 if (!config.generateFootstepFile)
571 return;
572
573 if (textureref[mipTexIndex].footstepMarked)
574 return;
575
576 assert(filename);
577
578 char fileBase[MAX_OSPATH];
579 Com_StripExtension(filename, fileBase, sizeof(fileBase));
580
582 FS_OpenFile(va("%s.footsteps", fileBase), &f, FILE_APPEND);
583 if (!f) {
584 Com_Printf("Could not open footstep file '%s.footsteps' for writing\n", fileBase);
585 config.generateFootstepFile = false;
586 return;
587 }
588#ifdef _WIN32
589 FS_Printf(&f, "terrain %s {\n}\n\n", textureref[mipTexIndex].name);
590#else
591 FS_Printf(&f, "%s\n", textureref[mipTexIndex].name);
592#endif
593 footstepsCnt++;
594 textureref[mipTexIndex].footstepMarked = true;
595}
596
603static void ParseBrush (entity_t* mapent, const char* filename)
604{
605 int j, k;
607 vec3_t planepts[3];
608 const int checkOrFix = config.performMapCheck || config.fixMap ;
609
611 Sys_Error("nummapbrushes == MAX_MAP_BRUSHES (%i)", nummapbrushes);
612
614 OBJZERO(*b);
616 b->entitynum = num_entities - 1;
617 b->brushnum = nummapbrushes - mapent->firstbrush;
618
619 do {
620 if (Q_strnull(GetToken()))
621 break;
622 if (*parsedToken == '}')
623 break;
624
626 Sys_Error("nummapbrushsides == MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides);
628
629 /* read the three point plane definition */
630 for (int i = 0; i < 3; i++) {
631 if (i != 0)
632 GetToken();
633 if (*parsedToken != '(')
634 Sys_Error("parsing brush");
635
636 for (j = 0; j < 3; j++) {
637 GetToken();
638 planepts[i][j] = atof(parsedToken);
639 }
640
641 GetToken();
642 if (*parsedToken != ')')
643 Sys_Error("parsing brush");
644 }
645
646 /* read the texturedef */
647 GetToken();
648 if (strlen(parsedToken) >= MAX_TEXPATH) {
649 if (config.performMapCheck || config.fixMap)
650 Com_Printf(" ");/* hack to make this look like output from Check_Printf() */
651 Com_Printf("ParseBrush: texture name too long (limit %i): %s\n", MAX_TEXPATH, parsedToken);
652 if (config.fixMap)
653 Sys_Error("Aborting, as -fix is active and saving might corrupt *.map by truncating texture name");
654 }
655 Q_strncpyz(td.name, parsedToken, sizeof(td.name));
656
657 td.shift[0] = atof(GetToken());
658 td.shift[1] = atof(GetToken());
659 td.rotate = atof(GetToken());
660 td.scale[0] = atof(GetToken());
661 td.scale[1] = atof(GetToken());
662
663 /* find default flags and values */
664 const int mt = FindMiptex(td.name);
665 side->surfaceFlags = td.surfaceFlags = side->contentFlags = td.value = 0;
666
667 if (TokenAvailable()) {
668 side->contentFlags = atoi(GetToken());
669 side->surfaceFlags = td.surfaceFlags = atoi(GetToken());
670 td.value = atoi(GetToken());
671 }
672
673 /* if in check or fix mode, let them choose to do this (with command line options),
674 * and then call is made elsewhere */
675 if (!checkOrFix) {
676 SetImpliedFlags(side, &td, b);
677 /* if no other content flags are set - make this solid */
678 if (!checkOrFix && side->contentFlags == 0)
680 }
681
682 /* translucent objects are automatically classified as detail and window */
688 }
689 if (config.fulldetail)
691 if (!checkOrFix) {
692 if (!(side->contentFlags & ((LAST_VISIBLE_CONTENTS - 1)
695
696 /* hints and skips are never detail, and have no content */
697 if (side->surfaceFlags & (SURF_HINT | SURF_SKIP)) {
698 side->contentFlags = 0;
700 }
701 }
702
703 /* check whether the flags are ok */
704 CheckFlags(side, b);
705
706 /* generate a list of textures that should have footsteps when walking on them */
707 if (mt > 0 && (side->surfaceFlags & SURF_FOOTSTEP))
710
711 /* find the plane number */
712 int planenum = PlaneFromPoints(b, planepts[0], planepts[1], planepts[2]);
713 if (planenum == PLANENUM_LEAF) {
714 Com_Printf("Entity %i, Brush %i: plane with no normal\n", b->entitynum, b->brushnum);
715 continue;
716 }
717
718 for (j = 0; j < 3; j++)
719 VectorCopy(planepts[j], mapplanes[planenum].planeVector[j]);
720
721 /* see if the plane has been used already */
722 for (k = 0; k < b->numsides; k++) {
723 const side_t* s2 = b->original_sides + k;
724 if (s2->planenum == planenum) {
725 Com_Printf("Entity %i, Brush %i: duplicate plane\n", b->entitynum, b->brushnum);
726 break;
727 }
728 if (s2->planenum == (planenum ^ 1)) {
729 Com_Printf("Entity %i, Brush %i: mirrored plane\n", b->entitynum, b->brushnum);
730 break;
731 }
732 }
733 if (k != b->numsides)
734 continue; /* duplicated */
735
736 /* keep this side */
737 side = b->original_sides + b->numsides;
738 side->planenum = planenum;
739 side->texinfo = TexinfoForBrushTexture(&mapplanes[planenum],
741 side->brush = b;
742
743 /* save the td off in case there is an origin brush and we
744 * have to recalculate the texinfo */
746
747 Verb_Printf(VERB_DUMP, "Brush %i Side %i (%f %f %f) (%f %f %f) (%f %f %f) texinfo:%i[%s] plane:%i\n", nummapbrushes, nummapbrushsides,
748 planepts[0][0], planepts[0][1], planepts[0][2],
749 planepts[1][0], planepts[1][1], planepts[1][2],
750 planepts[2][0], planepts[2][1], planepts[2][2],
751 side->texinfo, td.name, planenum);
752
754 b->numsides++;
755 } while (1);
756
757 /* get the content for the entire brush */
759
760 /* copy all set face contentflags to the brush contentflags */
761 for (int m = 0; m < b->numsides; m++)
762 b->contentFlags |= b->original_sides[m].contentFlags;
763
764 /* set DETAIL, TRANSLUCENT contentflags on all faces, if they have been set on any.
765 * called separately, if in check/fix mode */
766 if (!checkOrFix)
768
769 /* allow detail brushes to be removed */
770 if (config.nodetail && (b->contentFlags & CONTENTS_DETAIL)) {
771 b->numsides = 0;
772 return;
773 }
774
775 /* allow water brushes to be removed */
776 if (config.nowater && (b->contentFlags & CONTENTS_WATER)) {
777 b->numsides = 0;
778 return;
779 }
780
781 /* create windings for sides and bounds for brush */
783
784 Verb_Printf(VERB_DUMP, "Brush %i mins (%f %f %f) maxs (%f %f %f)\n", nummapbrushes,
785 b->mbBox.mins[0], b->mbBox.mins[1], b->mbBox.mins[2],
786 b->mbBox.maxs[0], b->mbBox.maxs[1], b->mbBox.maxs[2]);
787
788 /* origin brushes are removed, but they set
789 * the rotation origin for the rest of the brushes (like func_door)
790 * in the entity. After the entire entity is parsed, the planenums
791 * and texinfos will be adjusted for the origin brush */
792 if (!checkOrFix && (b->contentFlags & CONTENTS_ORIGIN)) {
793 char string[32];
795
796 if (num_entities == 1) {
797 Sys_Error("Entity %i, Brush %i: origin brushes not allowed in world"
798 , b->entitynum, b->brushnum);
799 return;
800 }
801
803
804 Com_sprintf(string, sizeof(string), "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
805 SetKeyValue(&entities[b->entitynum], "origin", string);
806 Verb_Printf(VERB_EXTRA, "Entity %i, Brush %i: set origin to %s\n", b->entitynum, b->brushnum, string);
807
808 VectorCopy(origin, entities[b->entitynum].origin);
809
810 /* don't keep this brush */
811 b->numsides = 0;
812
813 return;
814 }
815
816 if (!checkOrFix)
818
820 mapent->numbrushes++;
821}
822
831static void MoveBrushesToWorld (entity_t* mapent)
832{
833 int newbrushes, worldbrushes, i;
834 mapbrush_t* temp;
835
836 /* this is pretty gross, because the brushes are expected to be
837 * in linear order for each entity */
838
839 newbrushes = mapent->numbrushes;
840 worldbrushes = entities[0].numbrushes;
841
842 if (newbrushes == 0)
843 Sys_Error("Empty func_group - clean your map");
844
845 temp = Mem_AllocTypeN(mapbrush_t, newbrushes);
846 memcpy(temp, mapbrushes + mapent->firstbrush, newbrushes * sizeof(*temp));
847
848 /* make space to move the brushes (overlapped copy) */
849 memmove(mapbrushes + worldbrushes + newbrushes,
850 mapbrushes + worldbrushes,
851 sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes));
852
853 /* copy the new brushes down */
854 memcpy(mapbrushes + worldbrushes, temp, sizeof(*temp) * newbrushes);
855
856 /* fix up indexes */
857 entities[0].numbrushes += newbrushes;
858 for (i = 1; i < num_entities; i++)
859 entities[i].firstbrush += newbrushes;
860 Mem_Free(temp);
861
862 mapent->numbrushes = 0;
863}
864
869static void AdjustBrushesForOrigin (const entity_t* ent)
870{
871 for (int i = 0; i < ent->numbrushes; i++) {
872 mapbrush_t* b = &mapbrushes[ent->firstbrush + i];
873 for (int j = 0; j < b->numsides; j++) {
874 side_t* s = &b->original_sides[j];
875 const ptrdiff_t index = s - brushsides;
876 const vec_t newdist = mapplanes[s->planenum].dist -
877 DotProduct(mapplanes[s->planenum].normal, ent->origin);
879 side_brushtextures[index].surfaceFlags |= SURF_ORIGIN;
880 s->planenum = FindOrCreateFloatPlane(mapplanes[s->planenum].normal, newdist);
883 s->brush = b;
884 }
885 /* create windings for sides and bounds for brush */
887 }
888}
889
895static inline bool IsInlineModelEntity (const char* entName)
896{
897 const bool inlineModelEntity = (Q_streq("func_breakable", entName)
898 || Q_streq("func_door", entName)
899 || Q_streq("func_door_sliding", entName)
900 || Q_streq("func_rotating", entName)
901 || Q_strstart(entName, "trigger_"));
902 return inlineModelEntity;
903}
904
911entity_t* FindTargetEntity (const char* target)
912{
913 for (int i = 0; i < num_entities; i++) {
914 const char* n = ValueForKey(&entities[i], "targetname");
915 if (Q_streq(n, target))
916 return &entities[i];
917 }
918
919 return nullptr;
920}
921
928static bool ParseMapEntity (const char* filename, const char* entityString)
929{
930 entity_t* mapent;
931 const char* entName;
932 static int worldspawnCount = 0;
933 int notCheckOrFix = !(config.performMapCheck || config.fixMap);
934
935 if (Q_strnull(GetToken()))
936 return false;
937
938 if (*parsedToken != '{')
939 Sys_Error("ParseMapEntity: { not found");
940
942 Sys_Error("num_entities == MAX_MAP_ENTITIES (%i)", num_entities);
943
944 mapent = &entities[num_entities++];
945 OBJZERO(*mapent);
946 mapent->firstbrush = nummapbrushes;
947 mapent->numbrushes = 0;
948
949 do {
950 if (Q_strnull(GetToken()))
951 Sys_Error("ParseMapEntity: EOF without closing brace");
952 if (*parsedToken == '}')
953 break;
954 if (*parsedToken == '{')
955 ParseBrush(mapent, filename);
956 else {
958 e->next = mapent->epairs;
959 mapent->epairs = e;
960 }
961 } while (true);
962
963 GetVectorForKey(mapent, "origin", mapent->origin);
964
965 entName = ValueForKey(mapent, "classname");
966
967 /* offset all of the planes and texinfo if needed */
968 if (IsInlineModelEntity(entName) && VectorNotEmpty(mapent->origin))
970
971 if (num_entities == 1 && !Q_streq("worldspawn", entName))
972 Sys_Error("The first entity must be worldspawn, it is: %s", entName);
973 if (notCheckOrFix && Q_streq("func_group", entName)) {
974 /* group entities are just for editor convenience
975 * toss all brushes into the world entity */
976 MoveBrushesToWorld(mapent);
977 num_entities--;
978 } else if (IsInlineModelEntity(entName)) {
979 if (mapent->numbrushes == 0 && notCheckOrFix) {
980 Com_Printf("Warning: %s has no brushes assigned (entnum: %i)\n", entName, num_entities);
981 num_entities--;
982 }
983 } else if (Q_streq("worldspawn", entName)) {
984 worldspawnCount++;
985 if (worldspawnCount > 1)
986 Com_Printf("Warning: more than one %s in one map\n", entName);
987
988 const char* text = entityString;
989 do {
990 const char* token = Com_Parse(&text);
991 if (Q_strnull(token))
992 break;
993 const char* key = Mem_StrDup(token);
994 token = Com_Parse(&text);
995 if (Q_strnull(token))
996 break;
997 const char* value = Mem_StrDup(token);
998 epair_t* e = AddEpair(key, value, num_entities);
999 if (!config.fixMap || !EpairCheckForDuplicate(mapent, e)) {
1000 e->next = mapent->epairs;
1001 e->ump = true;
1002 mapent->epairs = e;
1003 }
1004 } while (true);
1005 }
1006 return true;
1007}
1008
1013static inline void WriteMapEntities (qFILE* f, const epair_t* e)
1014{
1015 if (!e)
1016 return;
1017
1018 if (e->next)
1019 WriteMapEntities(f, e->next);
1020
1021 if (!e->ump)
1022 FS_Printf(f, "\"%s\" \"%s\"\n", e->key, e->value);
1023}
1024
1025
1032static void WriteMapBrush (const mapbrush_t* brush, const int j, qFILE* f)
1033{
1034 FS_Printf(f, "// brush %i\n{\n", j);
1035 for (int k = 0; k < brush->numsides; k++) {
1036 const side_t* side = &brush->original_sides[k];
1037 const ptrdiff_t index = side - brushsides;
1039 const plane_t* p = &mapplanes[side->planenum];
1040
1041 for (int i = 0; i < 3; i++)
1042 FS_Printf(f, "( %.7g %.7g %.7g ) ", p->planeVector[i][0], p->planeVector[i][1], p->planeVector[i][2]);
1043 FS_Printf(f, "%s ", t->name);
1044 FS_Printf(f, "%.7g %.7g %.7g ", t->shift[0], t->shift[1], t->rotate);
1045 FS_Printf(f, "%.7g %.7g ", t->scale[0], t->scale[1]);
1046 FS_Printf(f, "%i %i %i\n", side->contentFlags, t->surfaceFlags, t->value);
1047 }
1048 FS_Printf(f, "}\n");
1049}
1050
1055void WriteMapFile (const char* filename)
1056{
1057 int removed;
1058
1059 Verb_Printf(VERB_NORMAL, "writing map: '%s'\n", filename);
1060
1061 ScopedFile f;
1063 if (!f)
1064 Sys_Error("Could not open %s for writing", filename);
1065
1066 removed = 0;
1067 for (int i = 0; i < num_entities; i++) {
1068 const entity_t* mapent = &entities[i];
1069 const epair_t* e = mapent->epairs;
1070
1071 /* maybe we don't want to write it back into the file */
1072 if (mapent->skip) {
1073 removed++;
1074 continue;
1075 }
1076 FS_Printf(&f, "// entity %i\n{\n", i - removed);
1077 WriteMapEntities(&f, e);
1078
1079 /* need 2 counters. j counts the brushes in the source entity.
1080 * jc counts the brushes written back. they may differ if some are skipped,
1081 * eg they are microbrushes */
1082 int j, jc;
1083 for (j = 0, jc = 0; j < mapent->numbrushes; j++) {
1084 const mapbrush_t* brush = &mapbrushes[mapent->firstbrush + j];
1085 if (brush->skipWriteBack)
1086 continue;
1087 WriteMapBrush(brush, jc++, &f);
1088 }
1089
1090 /* add brushes from func_groups with single members to worldspawn */
1091 if (i == 0) {
1092 int numToAdd;
1093 mapbrush_t** brushesToAdd = Check_ExtraBrushesForWorldspawn(&numToAdd);
1094 if (brushesToAdd != nullptr) {
1095 for (int k = 0; k < numToAdd; k++) {
1096 if (brushesToAdd[k]->skipWriteBack)
1097 continue;
1098 WriteMapBrush(brushesToAdd[k], j++, &f);
1099 }
1100 Mem_Free(brushesToAdd);
1101 }
1102 }
1103 FS_Printf(&f, "}\n");
1104 }
1105
1106 if (removed)
1107 Verb_Printf(VERB_NORMAL, "removed %i entities\n", removed);
1108}
1109
1117static void ParseUMP (const char* name, char* entityString, bool inherit)
1118{
1119 char filename[MAX_QPATH];
1120 byte* buf;
1121 const char* text;
1122
1123 *entityString = '\0';
1124
1125 /* load the map info */
1126 Com_sprintf(filename, sizeof(filename), "maps/%s.ump", name);
1128 if (!buf)
1129 return;
1130
1131 /* parse it */
1132 text = (const char*)buf;
1133 do {
1134 const char* token = Com_Parse(&text);
1135 if (!text)
1136 break;
1137
1138 if (Q_streq(token, "extends")) {
1139 token = Com_Parse(&text);
1140 if (inherit)
1141 Com_Printf("ParseUMP: Too many extends in %s 'extends %s' ignored\n", filename, token);
1142 else
1143 ParseUMP(token, entityString, true);
1144 } else if (Q_streq(token, "worldspawn")) {
1145 const char* start = nullptr;
1146 const int length = Com_GetBlock(&text, &start);
1147 if (length == -1) {
1148 Com_Printf("ParseUMP: Not a valid worldspawn block in '%s'\n", filename);
1149 } else {
1150 if (length >= MAX_TOKEN_CHARS) {
1151 Com_Printf("worldspawn is too big - only %i characters are allowed", MAX_TOKEN_CHARS);
1152 } else if (length == 0) {
1153 Com_Printf("no worldspawn settings in ump file\n");
1154 } else {
1155 Q_strncpyz(entityString, start, length);
1156 Com_Printf("use worldspawn settings from ump file\n");
1157 }
1158 }
1159 } else if (token[0] == '{') {
1160 /* ignore unknown block */
1161 text = strchr(text, '}') + 1;
1162 if (!text)
1163 break;
1164 }
1165 } while (text);
1166
1167 /* free the file */
1169}
1170
1174static const char* GetUMPName (const char* mapFilename)
1175{
1176 static char name[MAX_QPATH];
1177 const char* filename = Com_SkipPath(mapFilename);
1178 /* if we are in no subdir, we don't have any ump */
1179 if (filename == nullptr)
1180 return nullptr;
1181
1182 const char* mapsDir = "maps/";
1183 const int lMaps = strlen(mapsDir);
1184 const int l = strlen(filename);
1185 const int targetLength = strlen(mapFilename) - lMaps - l;
1186 if (targetLength <= 0)
1187 return nullptr;
1188 Q_strncpyz(name, mapFilename + lMaps, targetLength);
1189 Com_Printf("...ump: '%s%s.ump'\n", mapsDir, name);
1190 return name;
1191}
1192
1197void LoadMapFile (const char* filename)
1198{
1199 Verb_Printf(VERB_EXTRA, "--- LoadMapFile ---\n");
1200
1202
1204 nummapbrushes = 0;
1205
1207 nummapbrushsides = 0;
1208
1210
1212
1213 num_entities = 0;
1214 /* Create this shortcut to mapTiles[0] */
1215 curTile = &mapTiles.mapTiles[0];
1216 /* Set the number of tiles to 1. This is fix for ufo2map right now. */
1217 mapTiles.numTiles = 1;
1218
1219 char entityString[2 * MAX_TOKEN_CHARS] = "";
1220 const char* ump = GetUMPName(filename);
1221 if (ump != nullptr)
1222 ParseUMP(ump, entityString, false);
1223
1224 while (ParseMapEntity(filename, entityString));
1225
1226 int subdivide = atoi(ValueForKey(&entities[0], "subdivide"));
1227 if (subdivide >= 256 && subdivide <= 2048) {
1228 Verb_Printf(VERB_EXTRA, "Using subdivide %d from worldspawn.\n", subdivide);
1229 config.subdivideSize = subdivide;
1230 }
1231
1232 if (footstepsCnt)
1233 Com_Printf("Generated footstep file with %i entries\n", footstepsCnt);
1234 if (materialsCnt)
1235 Com_Printf("Generated material file with %i entries\n", materialsCnt);
1236
1237 AABB mapBox;
1238 mapBox.setNegativeVolume();
1239 for (int i = 0; i < entities[0].numbrushes; i++) {
1240 if (mapbrushes[i].mbBox.mins[0] > MAX_WORLD_WIDTH)
1241 continue; /* no valid points */
1242 mapBox.add(mapbrushes[i].mbBox);
1243 }
1244
1245 /* save a copy of the brushes */
1247
1248 Verb_Printf(VERB_EXTRA, "%5i brushes\n", nummapbrushes);
1249 Verb_Printf(VERB_EXTRA, "%5i total sides\n", nummapbrushsides);
1250 Verb_Printf(VERB_EXTRA, "%5i boxbevels\n", c_boxbevels);
1251 Verb_Printf(VERB_EXTRA, "%5i edgebevels\n", c_edgebevels);
1252 Verb_Printf(VERB_EXTRA, "%5i entities\n", num_entities);
1253 Verb_Printf(VERB_EXTRA, "%5i planes\n", nummapplanes);
1254 char sizeStr[AABB_STRING];
1255 mapBox.asIntString(sizeStr, sizeof(sizeStr));
1256 Verb_Printf(VERB_EXTRA, "size: %s\n", sizeStr);
1257}
#define AABB_STRING
Definition aabb.h:40
side_t brushsides[MAX_MAP_SIDES]
Definition map.cpp:37
int nummapbrushsides
Definition map.cpp:38
int nummapbrushes
Definition map.cpp:35
int nummapplanes
Definition map.cpp:44
brush_texture_t side_brushtextures[MAX_MAP_SIDES]
Definition map.cpp:40
plane_t mapplanes[MAX_MAP_PLANES]
Definition map.cpp:43
mapbrush_t mapbrushes[MAX_MAP_BRUSHES]
Definition map.cpp:34
void GetVectorForKey(const entity_t *ent, const char *key, vec3_t vec)
Converts the value of a entity parameter into a vec3_t.
Definition bspfile.cpp:592
void SetKeyValue(entity_t *ent, const char *key, const char *value)
Definition bspfile.cpp:546
int num_entities
Definition bspfile.cpp:394
entity_t entities[MAX_MAP_ENTITIES]
Definition bspfile.cpp:395
bool EpairCheckForDuplicate(const entity_t *ent, const epair_t *e)
Definition bspfile.cpp:418
epair_t * AddEpair(const char *key, const char *value, int entNum)
Definition bspfile.cpp:428
epair_t * ParseEpair(int entNum)
Parses one key and value for an entity from the current tokens.
Definition bspfile.cpp:453
const char * ValueForKey(const entity_t *ent, const char *key)
Definition bspfile.cpp:558
void CheckPropagateParserContentFlags(mapbrush_t *b)
some contentlflags are set as a result of some surface flag. For example, if one face is TRANS* then ...
Definition check.cpp:1619
void SetImpliedFlags(side_t *side, brush_texture_t *tex, const mapbrush_t *brush)
Sets surface flags dependent on assigned texture.
Definition check.cpp:1448
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map.
mapbrush_t ** Check_ExtraBrushesForWorldspawn(int *numBrushes)
single brushes in func_groups are moved to worldspawn. this function allocates space for pointers to ...
unsigned int key
Definition cl_input.cpp:64
Definition aabb.h:42
void asIntString(char *str, size_t len)
Prints a representation of the box.
Definition aabb.h:167
vec3_t maxs
Definition aabb.h:258
void setNegativeVolume()
Sets mins and maxs to their starting points before using addPoint.
Definition aabb.h:98
vec3_t mins
Definition aabb.h:257
void reset()
Definition aabb.h:83
void getCenter(vec3_t center) const
Calculates the center of the bounding box.
Definition aabb.h:155
void add(const vec3_t point)
If the point is outside the box, expand the box to accommodate it.
Definition aabb.cpp:57
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define MAP_DIST_EPSILON
Definition defines.h:380
#define CONTENTS_ORIGIN
Definition defines.h:248
#define MAX_MAP_SIDES
Definition defines.h:383
#define CONTENTS_TRANSLUCENT
Definition defines.h:252
#define PLANE_Y
Definition defines.h:192
#define CONTENTS_WEAPONCLIP
Definition defines.h:249
#define LAST_VISIBLE_CONTENTS
Definition defines.h:230
#define SURF_ALPHATEST
Definition defines.h:268
#define CONTENTS_DETAIL
Definition defines.h:251
#define SURF_ORIGIN
Definition defines.h:266
#define SURF_BLEND66
Definition defines.h:258
#define PLANE_X
Definition defines.h:191
#define MAX_MAP_BRUSHSIDES
Definition defines.h:141
#define CONTENTS_ACTORCLIP
Definition defines.h:243
#define MAX_TEXPATH
Definition defines.h:95
#define PLANE_ANYZ
Definition defines.h:198
#define CONTENTS_SOLID
Definition defines.h:223
#define PLANENUM_LEAF
Definition defines.h:45
#define CONTENTS_PASSABLE
Definition defines.h:244
#define SURF_SKIP
Definition defines.h:262
#define SURF_BLEND33
Definition defines.h:257
#define PLANE_Z
Definition defines.h:193
#define SURF_HINT
Definition defines.h:261
#define MAX_MAP_BRUSHES
Definition defines.h:135
#define MAX_MAP_PLANES
Definition defines.h:139
#define SURF_FOOTSTEP
Definition defines.h:265
#define MAX_TOKEN_CHARS
Definition defines.h:372
#define CONTENTS_WINDOW
Definition defines.h:224
#define PLANE_ANYY
Definition defines.h:197
#define CONTENTS_WATER
Definition defines.h:226
#define PLANE_ANYX
Definition defines.h:196
#define MAX_WORLD_WIDTH
-MAX_WORLD_WIDTH up tp +MAX_WORLD_WIDTH
Definition defines.h:288
#define MAX_MAP_ENTITIES
Definition defines.h:136
#define NORMAL_EPSILON
Definition defines.h:381
#define CONTENTS_LIGHTCLIP
Definition defines.h:246
#define AXIAL(p)
Definition defines.h:201
#define CONTENTS_TERRAIN
Definition defines.h:245
int FS_Printf(qFILE *f, const char *msg,...)
Can print chunks for 1024 chars into a file.
Definition files.cpp:1497
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition files.cpp:384
void FS_FreeFile(void *buffer)
Definition files.cpp:411
int FS_OpenFile(const char *filename, qFILE *file, filemode_t mode)
Finds and opens the file in the search path.
Definition files.cpp:162
#define MAX_OSPATH
Definition filesys.h:44
#define MAX_QPATH
Definition filesys.h:40
@ FILE_APPEND
Definition filesys.h:111
@ FILE_WRITE
Definition filesys.h:111
void Sys_Error(const char *error,...)
Definition g_main.cpp:421
voidpf uLong int origin
Definition ioapi.h:45
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
const char * filename
Definition ioapi.h:41
voidpf void * buf
Definition ioapi.h:42
static int BrushContents(mapbrush_t *b)
Get the content flags for a given brush.
Definition map.cpp:254
#define PLANE_HASHES
Definition map.cpp:46
static plane_t * planehash[PLANE_HASHES]
Definition map.cpp:47
byte GetLevelFlagsFromBrush(const mapbrush_t *brush)
Extract the level flags (1-8) from the content flags of the given brush.
Definition map.cpp:277
entity_t * FindTargetEntity(const char *target)
Searches the entities array for an entity with the parameter targetname that matches the searched tar...
Definition map.cpp:911
static void WriteMapEntities(qFILE *f, const epair_t *e)
Recurse down the epair list.
Definition map.cpp:1013
static bool SnapVector(vec3_t normal)
Round the vector to int values.
Definition map.cpp:163
static bool PlaneEqual(const plane_t *p, const vec3_t normal, const vec_t dist)
Checks whether the given normal and distance vectors match the given plane by some epsilon value.
Definition map.cpp:102
static const char * GetUMPName(const char *mapFilename)
The contract is that the directory name is equal to the base of the ump filename.
Definition map.cpp:1174
static uint16_t CreateNewFloatPlane(vec3_t normal, vec_t dist)
Definition map.cpp:119
static int footstepsCnt
Amount of footstep surfaces found in this map.
Definition map.cpp:558
static void AddPlaneToHash(plane_t *p)
Definition map.cpp:112
static bool ParseMapEntity(const char *filename, const char *entityString)
Parsed map entites and brushes.
Definition map.cpp:928
static int materialsCnt
How many materials were created for this map.
Definition map.cpp:493
static int c_boxbevels
Definition map.cpp:49
static int c_edgebevels
Definition map.cpp:50
static void MoveBrushesToWorld(entity_t *mapent)
Takes all of the brushes from the current entity and adds them to the world's brush list.
Definition map.cpp:831
static void WriteMapBrush(const mapbrush_t *brush, const int j, qFILE *f)
write a brush to the .map file
Definition map.cpp:1032
static int16_t PlaneFromPoints(const mapbrush_t *b, const vec3_t p0, const vec3_t p1, const vec3_t p2)
Builds a plane normal and distance from three points on the plane. If the normal is nearly axial,...
Definition map.cpp:227
void WriteMapFile(const char *filename)
Definition map.cpp:1055
uint16_t FindOrCreateFloatPlane(vec3_t normal, vec_t dist)
Definition map.cpp:194
static void ParseUMP(const char *name, char *entityString, bool inherit)
Parses an ump file that contains the random map definition.
Definition map.cpp:1117
static void AddBrushBevels(mapbrush_t *b)
Adds any additional planes necessary to allow the brush to be expanded against axial bounding boxes.
Definition map.cpp:289
static bool MakeBrushWindings(mapbrush_t *brush)
makes basewindings for sides and mins / maxs for the brush
Definition map.cpp:436
static void GenerateMaterialFile(const char *filename, int mipTexIndex, side_t *s)
Generates material files in case the settings can be guessed from map file.
Definition map.cpp:498
void LoadMapFile(const char *filename)
Definition map.cpp:1197
static int PlaneTypeForNormal(const vec3_t normal)
Set the type of the plane according to it's normal vector.
Definition map.cpp:72
static void ParseBrush(entity_t *mapent, const char *filename)
Parses a brush from the map file.
Definition map.cpp:603
static void SnapPlane(vec3_t normal, vec_t *dist)
Snaps normal to axis-aligned if it is within an epsilon of axial.
Definition map.cpp:186
static void CheckFlags(side_t *side, const mapbrush_t *b)
Checks whether the surface and content flags are correct.
Definition map.cpp:484
static void AdjustBrushesForOrigin(const entity_t *ent)
If there was an origin brush, offset all of the planes and texinfo.
Definition map.cpp:869
static int GetPlaneHashValueForDistance(const vec_t distance)
Planes are stored by their distance (resp. the calculated hash) in the plane hash table.
Definition map.cpp:62
static void GenerateFootstepList(const char *filename, int mipTexIndex)
Generate a list of textures that should have footsteps when walking on them.
Definition map.cpp:568
static bool IsInlineModelEntity(const char *entName)
Checks whether this entity is an inline model that should have brushes.
Definition map.cpp:895
vec_t VectorNormalize(vec3_t v)
Calculate unit vector for a given vec3_t.
Definition mathlib.cpp:745
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition mathlib.cpp:434
vec_t Q_rint(const vec_t in)
Round to nearest integer.
Definition mathlib.cpp:156
const vec3_t vec3_origin
Definition mathlib.cpp:35
void CrossProduct(const vec3_t v1, const vec3_t v2, vec3_t cross)
binary operation on vectors in a three-dimensional space
Definition mathlib.cpp:820
static struct mdfour * m
Definition md4.cpp:35
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_AllocTypeN(type, n)
Definition mem.h:38
#define Mem_StrDup(in)
Definition mem.h:48
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 Com_GetBlock(const char **text, const char **start)
Get the start and end point of a block in the given text.
Definition parse.cpp:272
Shared parsing functions.
void ChopWindingInPlace(winding_t **inout, const vec3_t normal, const vec_t dist, const vec_t epsilon)
Definition polylib.cpp:299
winding_t * BaseWindingForPlane(const vec3_t normal, const vec_t dist)
Definition polylib.cpp:116
static wrapCache_t * hash[MAX_WRAP_HASH]
Definition r_font.cpp:86
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition r_gl.h:110
QGL_EXTERN GLuint index
Definition r_gl.h:110
QGL_EXTERN GLfloat f
Definition r_gl.h:114
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLint GLenum type
Definition r_gl.h:94
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
bool TokenAvailable(void)
Returns true if there is another token on the line.
Definition scriplib.cpp:92
void LoadScriptFile(const char *filename)
Definition scriplib.cpp:47
char parsedToken[MAX_TOKEN_CHARS]
Definition scriplib.cpp:45
const char * GetToken()
Parses the next token from the current script on the stack and store the result in parsedToken.
Definition scriplib.cpp:75
#define Q_streq(a, b)
Definition shared.h:136
bool Q_strnull(const char *string)
Definition shared.h:138
#define OBJZERO(obj)
Definition shared.h:178
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
Definition shared.cpp:259
const char * Com_SkipPath(const char *pathname)
Returns just the filename from a given path.
Definition shared.cpp:37
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition shared.cpp:587
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
vec2_t shift
Definition map.h:34
vec2_t scale
Definition map.h:36
char name[MAX_TEXPATH]
Definition map.h:37
int value
Definition map.h:39
vec_t rotate
Definition map.h:35
uint32_t surfaceFlags
Definition map.h:38
epair_t * epairs
Definition bspfile.h:50
int numbrushes
Definition bspfile.h:49
int firstbrush
Definition bspfile.h:48
bool skip
Definition bspfile.h:51
vec3_t origin
Definition r_entity.h:101
const char * key
Definition bspfile.h:38
struct epair_s * next
Definition bspfile.h:37
bool ump
Definition bspfile.h:40
const char * value
Definition bspfile.h:39
struct side_s * original_sides
Definition map.h:84
int brushnum
Definition map.h:77
bool skipWriteBack
Definition map.h:92
int numsides
Definition map.h:83
uint32_t contentFlags
Definition map.h:79
AABB mbBox
Definition map.h:81
int entitynum
Definition map.h:76
Definition map.h:98
struct plane_s * hash_chain
Definition map.h:107
vec3_t planeVector[3]
Definition map.h:106
int type
Definition map.h:105
vec_t dist
Definition map.h:100
vec3_t normal
Definition map.h:99
Definition map.h:60
uint16_t planenum
Definition map.h:61
winding_t * winding
Definition map.h:63
uint32_t surfaceFlags
Definition map.h:66
int texinfo
Definition map.h:62
bool visible
Definition map.h:67
uint32_t contentFlags
Definition map.h:65
struct mapbrush_s * brush
Definition map.h:72
bool bevel
Definition map.h:69
for storing the vertices of the side of a brush or other polygon
Definition polylib.h:30
int numpoints
Definition polylib.h:31
vec3_t p[4]
Definition polylib.h:32
static config_t config
Definition test_all.cpp:43
static mapTiles_t mapTiles
textureref_t textureref[MAX_MAP_TEXTURES]
Definition textures.cpp:30
int TexinfoForBrushTexture(plane_t *plane, brush_texture_t *bt, const vec3_t origin, bool isTerrain)
Definition textures.cpp:89
int FindMiptex(const char *name)
Definition textures.cpp:38
dMapTile_t * curTile
Definition bsp.cpp:32
void Verb_Printf(const verbosityLevel_t importance, const char *format,...) __attribute__((format(__printf__
@ VERB_NORMAL
Definition shared.h:45
@ VERB_EXTRA
Definition shared.h:46
@ VERB_DUMP
Definition shared.h:47
static char mapFilename[MAX_OSPATH]
Definition ufo2map.cpp:50
float vec_t
Definition ufotypes.h:37
vec_t vec3_t[3]
Definition ufotypes.h:39
#define VectorClear(a)
Definition vector.h:55
#define VectorNotEmpty(a)
Definition vector.h:72
#define VectorSubtract(a, b, dest)
Definition vector.h:45
#define VectorCopy(src, dest)
Definition vector.h:51
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition vector.h:44