23 #include "shared/shared.h"
24 #include "shared/list.h"
25 #include "common/cvar.h"
26 #include "common/cmd.h"
27 #include "common/common.h"
28 #include "common/files.h"
29 #include "common/bsp.h"
30 #include "common/math.h"
31 #include "common/utils.h"
32 #include "common/mdfour.h"
33 #include "system/hunk.h"
48 Hunk_Alloc(&bsp->hunk, size)
51 static qerror_t BSP_Load##func(bsp_t *bsp, void *base, size_t count)
54 Com_DPrintf("%s: %s\n", __func__, msg)
58 uint32_t numclusters, bitofs;
66 DEBUG(
"too small header");
70 bsp->numvisibility = count;
71 bsp->vis =
ALLOC(count);
72 memcpy(bsp->vis, base, count);
74 numclusters = LittleLong(bsp->vis->numclusters);
75 if (numclusters > MAX_MAP_LEAFS) {
76 DEBUG(
"bad numclusters");
77 return Q_ERR_TOO_MANY;
80 if (numclusters > (count - 4) / 8) {
81 DEBUG(
"too small header");
85 bsp->vis->numclusters = numclusters;
86 bsp->visrowsize = (numclusters + 7) >> 3;
88 for (i = 0; i < numclusters; i++) {
89 for (j = 0; j < 2; j++) {
90 bitofs = LittleLong(bsp->vis->bitofs[i][j]);
91 if (bitofs >= count) {
93 return Q_ERR_BAD_INDEX;
95 bsp->vis->bitofs[i][j] = bitofs;
113 bsp->numtexinfo = count;
114 bsp->texinfo =
ALLOC(
sizeof(*out) * count);
118 for (i = 0; i < count; i++, in++, out++) {
119 memcpy(out->c.name, in->texture,
sizeof(out->c.name));
120 out->c.name[
sizeof(out->c.name) - 1] = 0;
121 memcpy(out->name, in->texture,
sizeof(out->name));
122 out->name[
sizeof(out->name) - 1] = 0;
123 out->c.flags = LittleLong(in->flags);
124 out->c.value = LittleLong(in->value);
127 out->radiance = in->value;
128 for (j = 0; j < 2; j++) {
129 for (k = 0; k < 3; k++) {
130 out->axis[j][k] = LittleFloat(in->vecs[j][k]);
132 out->offset[j] = LittleFloat(in->vecs[j][k]);
135 next = (int32_t)LittleLong(in->nexttexinfo);
138 DEBUG(
"bad anim chain");
139 return Q_ERR_BAD_INDEX;
141 out->next = bsp->texinfo + next;
151 for (i = 0; i < count; i++, out++) {
153 for (step = out->next; step && step != out; step = step->next) {
154 if (out->numframes == count) {
155 DEBUG(
"infinite anim chain");
156 return Q_ERR_INFINITE_LOOP;
163 return Q_ERR_SUCCESS;
172 bsp->numplanes = count;
173 bsp->planes =
ALLOC(
sizeof(*out) * count);
177 for (i = 0; i < count; i++, in++, out++) {
178 for (j = 0; j < 3; j++) {
179 out->normal[j] = LittleFloat(in->normal[j]);
181 out->dist = LittleFloat(in->dist);
186 return Q_ERR_SUCCESS;
194 uint16_t planenum, texinfo;
196 bsp->numbrushsides = count;
197 bsp->brushsides =
ALLOC(
sizeof(*out) * count);
200 out = bsp->brushsides;
201 for (i = 0; i < count; i++, in++, out++) {
202 planenum = LittleShort(in->planenum);
203 if (planenum >= bsp->numplanes) {
204 DEBUG(
"bad planenum");
205 return Q_ERR_BAD_INDEX;
207 out->plane = bsp->planes + planenum;
208 texinfo = LittleShort(in->texinfo);
209 if (texinfo == (uint16_t)-1) {
212 if (texinfo >= bsp->numtexinfo) {
213 DEBUG(
"bad texinfo");
214 return Q_ERR_BAD_INDEX;
216 out->texinfo = bsp->texinfo + texinfo;
220 return Q_ERR_SUCCESS;
228 uint32_t firstside, numsides, lastside;
230 bsp->numbrushes = count;
231 bsp->brushes =
ALLOC(
sizeof(*out) * count);
235 for (i = 0; i < count; i++, out++, in++) {
236 firstside = LittleLong(in->firstside);
237 numsides = LittleLong(in->numsides);
238 lastside = firstside + numsides;
239 if (lastside < firstside || lastside > bsp->numbrushsides) {
240 DEBUG(
"bad brushsides");
241 return Q_ERR_BAD_INDEX;
243 out->firstbrushside = bsp->brushsides + firstside;
244 out->numsides = numsides;
245 out->contents = LittleLong(in->contents);
249 return Q_ERR_SUCCESS;
259 bsp->numleafbrushes = count;
260 bsp->leafbrushes =
ALLOC(
sizeof(*out) * count);
263 out = bsp->leafbrushes;
264 for (i = 0; i < count; i++, in++, out++) {
265 brushnum = LittleShort(*in);
266 if (brushnum >= bsp->numbrushes) {
267 DEBUG(
"bad brushnum");
268 return Q_ERR_BAD_INDEX;
270 *out = bsp->brushes + brushnum;
273 return Q_ERR_SUCCESS;
281 return Q_ERR_SUCCESS;
284 bsp->numlightmapbytes = count;
285 bsp->lightmap =
ALLOC(count);
287 memcpy(bsp->lightmap, base, count);
289 return Q_ERR_SUCCESS;
298 bsp->numvertices = count;
299 bsp->vertices =
ALLOC(
sizeof(*out) * count);
303 for (i = 0; i < count; i++, out++, in++) {
304 for (j = 0; j < 3; j++) {
305 out->point[j] = LittleFloat(in->point[j]);
309 return Q_ERR_SUCCESS;
319 bsp->numedges = count;
320 bsp->edges =
ALLOC(
sizeof(*out) * count);
324 for (i = 0; i < count; i++, out++, in++) {
325 for (j = 0; j < 2; j++) {
326 vertnum = LittleShort(in->v[j]);
327 if (vertnum >= bsp->numvertices) {
328 DEBUG(
"bad vertnum");
329 return Q_ERR_BAD_INDEX;
331 out->v[j] = bsp->vertices + vertnum;
335 return Q_ERR_SUCCESS;
345 bsp->numsurfedges = count;
346 bsp->surfedges =
ALLOC(
sizeof(*out) * count);
349 out = bsp->surfedges;
350 for (i = 0; i < count; i++, out++, in++) {
351 index = (int32_t)LittleLong(*in);
359 if (index >= bsp->numedges) {
360 DEBUG(
"bad edgenum");
361 return Q_ERR_BAD_INDEX;
364 out->edge = bsp->edges + index;
368 return Q_ERR_SUCCESS;
376 uint32_t firstedge, numedges, lastedge;
377 uint16_t planenum, texinfo, side;
380 bsp->numfaces = count;
381 bsp->faces =
ALLOC(
sizeof(*out) * count);
385 for (i = 0; i < count; i++, in++, out++) {
386 firstedge = LittleLong(in->firstedge);
387 numedges = LittleShort(in->numedges);
388 lastedge = firstedge + numedges;
390 DEBUG(
"bad surfedges");
391 return Q_ERR_TOO_FEW;
393 if (numedges > 4096) {
394 DEBUG(
"bad surfedges");
395 return Q_ERR_TOO_MANY;
397 if (lastedge < firstedge || lastedge > bsp->numsurfedges) {
398 DEBUG(
"bad surfedges");
399 return Q_ERR_BAD_INDEX;
401 out->firstsurfedge = bsp->surfedges + firstedge;
402 out->numsurfedges = numedges;
404 planenum = LittleShort(in->planenum);
405 if (planenum >= bsp->numplanes) {
406 DEBUG(
"bad planenum");
407 return Q_ERR_BAD_INDEX;
409 out->plane = bsp->planes + planenum;
411 texinfo = LittleShort(in->texinfo);
412 if (texinfo >= bsp->numtexinfo) {
413 DEBUG(
"bad texinfo");
414 return Q_ERR_BAD_INDEX;
416 out->texinfo = bsp->texinfo + texinfo;
418 for (j = 0; j < MAX_LIGHTMAPS && in->styles[j] != 255; j++) {
419 out->styles[j] = in->styles[j];
422 for (; j < MAX_LIGHTMAPS; j++) {
423 out->styles[j] = 255;
426 lightofs = LittleLong(in->lightofs);
427 if (lightofs == (uint32_t)-1 || bsp->numlightmapbytes == 0) {
428 out->lightmap = NULL;
430 if (lightofs >= bsp->numlightmapbytes) {
431 DEBUG(
"bad lightofs");
432 return Q_ERR_BAD_INDEX;
434 out->lightmap = bsp->lightmap + lightofs;
437 side = LittleShort(in->side);
438 out->drawflags = side & DSURF_PLANEBACK;
441 return Q_ERR_SUCCESS;
451 bsp->numleaffaces = count;
452 bsp->leaffaces =
ALLOC(
sizeof(*out) * count);
455 out = bsp->leaffaces;
456 for (i = 0; i < count; i++, in++, out++) {
457 facenum = LittleShort(*in);
458 if (facenum >= bsp->numfaces) {
459 DEBUG(
"bad facenum");
460 return Q_ERR_BAD_INDEX;
462 *out = bsp->faces + facenum;
465 return Q_ERR_SUCCESS;
474 uint16_t cluster, area;
475 uint16_t firstleafbrush, numleafbrushes, lastleafbrush;
478 uint16_t firstleafface, numleaffaces, lastleafface;
482 DEBUG(
"map with no leafs");
483 return Q_ERR_TOO_FEW;
486 bsp->numleafs = count;
487 bsp->leafs =
ALLOC(
sizeof(*out) * count);
491 for (i = 0; i < count; i++, in++, out++) {
493 out->contents = LittleLong(in->contents);
494 cluster = LittleShort(in->cluster);
495 if (cluster == (uint16_t)-1) {
498 }
else if (bsp->vis == NULL) {
503 if (cluster >= bsp->vis->numclusters) {
504 DEBUG(
"bad cluster");
505 return Q_ERR_BAD_INDEX;
507 out->cluster = cluster;
510 area = LittleShort(in->area);
511 if (area >= bsp->numareas) {
513 return Q_ERR_BAD_INDEX;
517 firstleafbrush = LittleShort(in->firstleafbrush);
518 numleafbrushes = LittleShort(in->numleafbrushes);
519 lastleafbrush = firstleafbrush + numleafbrushes;
520 if (lastleafbrush < firstleafbrush || lastleafbrush > bsp->numleafbrushes) {
521 DEBUG(
"bad leafbrushes");
522 return Q_ERR_BAD_INDEX;
524 out->firstleafbrush = bsp->leafbrushes + firstleafbrush;
525 out->numleafbrushes = numleafbrushes;
528 firstleafface = LittleShort(in->firstleafface);
529 numleaffaces = LittleShort(in->numleaffaces);
530 lastleafface = firstleafface + numleaffaces;
531 if (lastleafface < firstleafface || lastleafface > bsp->numleaffaces) {
532 DEBUG(
"bad leaffaces");
533 return Q_ERR_BAD_INDEX;
535 out->firstleafface = bsp->leaffaces + firstleafface;
536 out->numleaffaces = numleaffaces;
538 for (j = 0; j < 3; j++) {
539 out->mins[j] = (int16_t)LittleShort(in->mins[j]);
540 out->maxs[j] = (int16_t)LittleShort(in->maxs[j]);
548 if (bsp->leafs[0].contents != CONTENTS_SOLID) {
549 DEBUG(
"map leaf 0 is not CONTENTS_SOLID");
550 return Q_ERR_INVALID_FORMAT;
553 return Q_ERR_SUCCESS;
561 uint32_t planenum, child;
563 uint16_t firstface, numfaces, lastface;
567 DEBUG(
"map with no nodes");
568 return Q_ERR_TOO_FEW;
571 bsp->numnodes = count;
572 bsp->nodes =
ALLOC(
sizeof(*out) * count);
576 for (i = 0; i < count; i++, out++, in++) {
577 planenum = LittleLong(in->planenum);
578 if (planenum >= bsp->numplanes) {
579 DEBUG(
"bad planenum");
580 return Q_ERR_BAD_INDEX;
582 out->plane = bsp->planes + planenum;
584 for (j = 0; j < 2; j++) {
585 child = LittleLong(in->children[j]);
586 if (child & 0x80000000) {
588 if (child >= bsp->numleafs) {
589 DEBUG(
"bad leafnum");
590 return Q_ERR_BAD_INDEX;
592 out->children[j] = (mnode_t *)(bsp->leafs + child);
594 if (child >= count) {
595 DEBUG(
"bad nodenum");
596 return Q_ERR_BAD_INDEX;
598 out->children[j] = bsp->nodes + child;
603 firstface = LittleShort(in->firstface);
604 numfaces = LittleShort(in->numfaces);
605 lastface = firstface + numfaces;
606 if (lastface < firstface || lastface > bsp->numfaces) {
608 return Q_ERR_BAD_INDEX;
610 out->firstface = bsp->faces + firstface;
611 out->numfaces = numfaces;
613 for (j = 0; j < 3; j++) {
614 out->mins[j] = (int16_t)LittleShort(in->mins[j]);
615 out->maxs[j] = (int16_t)LittleShort(in->maxs[j]);
623 return Q_ERR_SUCCESS;
633 uint32_t firstface, numfaces, lastface;
637 DEBUG(
"map with no models");
638 return Q_ERR_TOO_FEW;
641 bsp->models =
ALLOC(
sizeof(*out) * count);
642 bsp->nummodels = count;
646 for (i = 0; i < count; i++, in++, out++) {
647 for (j = 0; j < 3; j++) {
649 out->mins[j] = LittleFloat(in->mins[j]) - 1;
650 out->maxs[j] = LittleFloat(in->maxs[j]) + 1;
651 out->origin[j] = LittleFloat(in->origin[j]);
653 headnode = LittleLong(in->headnode);
654 if (headnode & 0x80000000) {
656 headnode = ~headnode;
657 if (headnode >= bsp->numleafs) {
658 DEBUG(
"bad headleaf");
659 return Q_ERR_BAD_INDEX;
661 out->headnode = (mnode_t *)(bsp->leafs + headnode);
663 if (headnode >= bsp->numnodes) {
664 DEBUG(
"bad headnode");
665 return Q_ERR_BAD_INDEX;
667 out->headnode = bsp->nodes + headnode;
673 firstface = LittleLong(in->firstface);
674 numfaces = LittleLong(in->numfaces);
675 lastface = firstface + numfaces;
676 if (lastface < firstface || lastface > bsp->numfaces) {
678 return Q_ERR_BAD_INDEX;
680 out->firstface = bsp->faces + firstface;
681 out->numfaces = numfaces;
687 return Q_ERR_SUCCESS;
697 bsp->numareaportals = count;
698 bsp->areaportals =
ALLOC(
sizeof(*out) * count);
701 out = bsp->areaportals;
702 for (i = 0; i < count; i++, in++, out++) {
703 out->portalnum = LittleLong(in->portalnum);
704 out->otherarea = LittleLong(in->otherarea);
707 return Q_ERR_SUCCESS;
715 uint32_t numareaportals, firstareaportal, lastareaportal;
717 bsp->numareas = count;
718 bsp->areas =
ALLOC(
sizeof(*out) * count);
722 for (i = 0; i < count; i++, in++, out++) {
723 numareaportals = LittleLong(in->numareaportals);
724 firstareaportal = LittleLong(in->firstareaportal);
725 lastareaportal = firstareaportal + numareaportals;
726 if (lastareaportal < firstareaportal || lastareaportal > bsp->numareaportals) {
727 DEBUG(
"bad areaportals");
728 return Q_ERR_BAD_INDEX;
730 out->numareaportals = numareaportals;
731 out->firstareaportal = bsp->areaportals + firstareaportal;
735 return Q_ERR_SUCCESS;
740 bsp->numentitychars = count;
741 bsp->entitystring =
ALLOC(count + 1);
742 memcpy(bsp->entitystring, base, count);
743 bsp->entitystring[count] = 0;
745 return Q_ERR_SUCCESS;
757 qerror_t (*
load)(bsp_t *,
void *, size_t);
764 #define L(func, lump, disk_t, mem_t) \
765 { BSP_Load##func, LUMP_##lump, sizeof(disk_t), sizeof(mem_t), MAX_MAP_##lump }
768 L(Visibility, VISIBILITY,
byte,
byte),
769 L(Texinfo, TEXINFO, dtexinfo_t, mtexinfo_t),
770 L(Planes, PLANES, dplane_t, cplane_t),
771 L(BrushSides, BRUSHSIDES, dbrushside_t, mbrushside_t),
772 L(Brushes, BRUSHES, dbrush_t, mbrush_t),
773 L(LeafBrushes, LEAFBRUSHES, uint16_t, mbrush_t *),
774 L(AreaPortals, AREAPORTALS, dareaportal_t, mareaportal_t),
775 L(Areas, AREAS, darea_t, marea_t),
777 L(Lightmap, LIGHTING,
byte,
byte),
778 L(Vertices, VERTEXES, dvertex_t, mvertex_t),
779 L(Edges, EDGES, dedge_t, medge_t),
780 L(SurfEdges, SURFEDGES, uint32_t, msurfedge_t),
781 L(Faces, FACES, dface_t, mface_t),
782 L(LeafFaces, LEAFFACES, uint16_t, mface_t *),
784 L(Leafs, LEAFS, dleaf_t, mleaf_t),
785 L(Nodes, NODES, dnode_t, mnode_t),
786 L(Submodels, MODELS, dmodel_t, mmodel_t),
787 L(EntString, ENTSTRING,
char,
char),
801 Com_Printf(
"BSP cache is empty\n");
805 Com_Printf(
"------------------\n");
808 LIST_FOR_EACH(bsp_t, bsp, &
bsp_cache, entry) {
809 Com_Printf(
"%8"PRIz
" : %s (%d refs)\n",
810 bsp->hunk.mapped, bsp->name, bsp->refcount);
811 bytes += bsp->hunk.mapped;
813 Com_Printf(
"Total resident: %"PRIz
"\n", bytes);
820 LIST_FOR_EACH(bsp_t, bsp, &
bsp_cache, entry) {
821 if (!FS_pathcmp(bsp->name, name)) {
837 while (node->plane) {
840 for (i = 0, face = node->firstface; i < node->numfaces; i++, face++) {
841 if (face->drawframe) {
842 DEBUG(
"duplicate face");
843 return Q_ERR_INFINITE_LOOP;
845 face->drawframe = key;
849 child = node->children[0];
851 DEBUG(
"cycle encountered");
852 return Q_ERR_INFINITE_LOOP;
854 child->parent = node;
856 return Q_ERR_INFINITE_LOOP;
859 child = node->children[1];
861 DEBUG(
"cycle encountered");
862 return Q_ERR_INFINITE_LOOP;
864 child->parent = node;
868 return Q_ERR_SUCCESS;
881 for (i = 0, mod = bsp->models; i < bsp->nummodels; i++, mod++) {
882 if (i == 0 && mod->headnode != bsp->nodes) {
883 DEBUG(
"map model 0 headnode is not the first node");
884 return Q_ERR_INVALID_FORMAT;
894 for (j = 0, face = mod->firstface; j < mod->numfaces; j++, face++) {
895 if (face->drawframe && face->drawframe != ~i) {
896 DEBUG(
"duplicate face");
897 return Q_ERR_INFINITE_LOOP;
899 face->drawframe = ~i;
904 return Q_ERR_SUCCESS;
914 bsp->lastareaportal = 0;
915 for (i = 0, p = bsp->areaportals; i < bsp->numareaportals; i++, p++) {
916 if (p->portalnum >= MAX_MAP_AREAPORTALS) {
917 DEBUG(
"bad portalnum");
918 return Q_ERR_TOO_MANY;
920 if (p->portalnum > bsp->lastareaportal) {
921 bsp->lastareaportal = p->portalnum;
923 if (p->otherarea >= bsp->numareas) {
924 DEBUG(
"bad otherarea");
925 return Q_ERR_BAD_INDEX;
929 return Q_ERR_SUCCESS;
937 if (bsp->refcount <= 0) {
938 Com_Error(ERR_FATAL,
"%s: negative refcount", __func__);
940 if (--bsp->refcount == 0) {
941 if (bsp->pvs2_matrix)
945 bsp->pvs2_matrix = NULL;
949 List_Remove(&bsp->entry);
960 size_t matrix_size = bsp->visrowsize * bsp->vis->numclusters;
964 char* pvs_matrix = Z_Mallocz(matrix_size);
966 for (
int cluster = 0; cluster < bsp->vis->numclusters; cluster++)
968 BSP_ClusterVis(bsp, pvs_matrix + bsp->visrowsize * cluster, cluster, DVIS_PVS);
971 bsp->pvs_matrix = pvs_matrix;
976 if (!bsp->vis || !bsp->pvs_matrix)
979 if (cluster < 0 || cluster >= bsp->vis->numclusters)
982 return bsp->pvs_matrix + bsp->visrowsize * cluster;
987 if (!bsp->vis || !bsp->pvs2_matrix)
990 if (cluster < 0 || cluster >= bsp->vis->numclusters)
993 return bsp->pvs2_matrix + bsp->visrowsize * cluster;
999 int path_len = strlen(map_path);
1000 if (path_len < 5 || strcmp(map_path + path_len - 4,
".bsp") != 0)
1003 const char* map_file = strrchr(map_path,
'/');
1007 map_file = map_path;
1009 memset(pvs_path, 0, MAX_QPATH);
1010 strncpy(pvs_path, map_path, map_file - map_path);
1011 strcat(pvs_path,
"pvs/");
1012 strncat(pvs_path, map_file, strlen(map_file) - 4);
1013 strcat(pvs_path,
".bin");
1021 char pvs_path[MAX_QPATH];
1026 unsigned char* filebuf = 0;
1027 ssize_t filelen = 0;
1028 filelen = FS_LoadFile(pvs_path, &filebuf);
1033 size_t matrix_size = bsp->visrowsize * bsp->vis->numclusters;
1034 if (filelen != matrix_size * 2)
1036 FS_FreeFile(filebuf);
1040 bsp->pvs_matrix = Z_Malloc(matrix_size);
1041 memcpy(bsp->pvs_matrix, filebuf, matrix_size);
1043 bsp->pvs2_matrix = Z_Malloc(matrix_size);
1044 memcpy(bsp->pvs2_matrix, filebuf + matrix_size, matrix_size);
1046 FS_FreeFile(filebuf);
1053 char pvs_path[MAX_QPATH];
1058 if (!bsp->pvs_matrix)
1061 if (!bsp->pvs2_matrix)
1064 size_t matrix_size = bsp->visrowsize * bsp->vis->numclusters;
1065 unsigned char* filebuf = Z_Malloc(matrix_size * 2);
1067 memcpy(filebuf, bsp->pvs_matrix, matrix_size);
1068 memcpy(filebuf + matrix_size, bsp->pvs2_matrix, matrix_size);
1093 size_t filelen, ofs, len, end, count;
1095 byte *lumpdata[HEADER_LUMPS];
1096 size_t lumpcount[HEADER_LUMPS];
1099 if (!name || !bsp_p)
1100 Com_Error(ERR_FATAL,
"%s: NULL", __func__);
1107 if ((bsp =
BSP_Find(name)) != NULL) {
1111 return Q_ERR_SUCCESS;
1117 filelen = FS_LoadFile(name, (
void **)&buf);
1123 header = (dheader_t *)buf;
1124 if (LittleLong(header->ident) != IDBSPHEADER) {
1125 ret = Q_ERR_UNKNOWN_FORMAT;
1128 if (LittleLong(header->version) != BSPVERSION) {
1129 ret = Q_ERR_UNKNOWN_FORMAT;
1136 ofs = LittleLong(header->lumps[info->
lump].fileofs);
1137 len = LittleLong(header->lumps[info->
lump].filelen);
1139 if (end < ofs || end > filelen) {
1140 ret = Q_ERR_BAD_EXTENT;
1144 ret = Q_ERR_ODD_SIZE;
1149 ret = Q_ERR_TOO_MANY;
1153 lumpdata[info->
lump] = buf + ofs;
1154 lumpcount[info->
lump] = count;
1156 memsize += count * info->
memsize;
1161 bsp = Z_Mallocz(
sizeof(*bsp) + len);
1162 memcpy(bsp->name, name, len + 1);
1173 ret = info->
load(bsp, lumpdata[info->
lump], lumpcount[info->
lump]);
1192 Com_WPrintf(
"WARNING: Pathced PVS file for %s unavailable. Some entities may disappear.\n"
1193 "Load the map with the RTX renderer once to generate the patched PVS file.\n", bsp->name);
1199 bsp->pvs_patched = qtrue;
1209 return Q_ERR_SUCCESS;
1229 static lightpoint_t *light_point;
1231 static qboolean BSP_RecursiveLightPoint(mnode_t *node,
float p1f,
float p2f, vec3_t p1, vec3_t p2)
1233 vec_t d1, d2, frac, midf;
1237 mtexinfo_t *texinfo;
1239 while (node->plane) {
1241 d1 = PlaneDiffFast(p1, node->plane);
1242 d2 = PlaneDiffFast(p2, node->plane);
1245 if ((d2 < 0) == side) {
1247 node = node->children[side];
1252 frac = d1 / (d1 - d2);
1253 midf = p1f + (p2f - p1f) * frac;
1254 LerpVector(p1, p2, frac, mid);
1257 if (BSP_RecursiveLightPoint(node->children[side], p1f, midf, p1, mid))
1260 for (i = 0, surf = node->firstface; i < node->numfaces; i++, surf++) {
1261 if (!surf->lightmap)
1264 texinfo = surf->texinfo;
1265 if (texinfo->c.flags & SURF_NOLM_MASK)
1268 s = DotProduct(texinfo->axis[0], mid) + texinfo->offset[0];
1269 t = DotProduct(texinfo->axis[1], mid) + texinfo->offset[1];
1271 s -= surf->texturemins[0];
1272 t -= surf->texturemins[1];
1273 if (s < 0 || s > surf->extents[0])
1275 if (t < 0 || t > surf->extents[1])
1278 light_point->surf = surf;
1279 light_point->plane = *surf->plane;
1282 light_point->fraction = midf;
1287 return BSP_RecursiveLightPoint(node->children[side ^ 1], midf, p2f, mid, p2);
1293 void BSP_LightPoint(lightpoint_t *point, vec3_t start, vec3_t end, mnode_t *headnode)
1295 light_point = point;
1296 light_point->surf = NULL;
1297 light_point->fraction = 1;
1299 BSP_RecursiveLightPoint(headnode, 0, 1, start, end);
1302 void BSP_TransformedLightPoint(lightpoint_t *point, vec3_t start, vec3_t end,
1303 mnode_t *headnode, vec3_t
origin, vec3_t angles)
1305 vec3_t start_l, end_l;
1308 light_point = point;
1309 light_point->surf = NULL;
1310 light_point->fraction = 1;
1313 VectorSubtract(start,
origin, start_l);
1314 VectorSubtract(end,
origin, end_l);
1318 AnglesToAxis(angles, axis);
1319 RotatePoint(start_l, axis);
1320 RotatePoint(end_l, axis);
1324 if (!BSP_RecursiveLightPoint(headnode, 0, 1, start_l, end_l))
1329 TransposeAxis(axis);
1330 RotatePoint(point->plane.normal, axis);
1334 point->plane.dist += DotProduct(point->plane.normal,
origin);
1341 byte *in, *out, *in_end, *out_end;
1344 if (!bsp || !bsp->vis) {
1345 return memset(mask, 0xff, VIS_MAX_BYTES);
1347 if (cluster == -1) {
1348 return memset(mask, 0, bsp->visrowsize);
1350 if (cluster < 0 || cluster >= bsp->vis->numclusters) {
1351 Com_Error(ERR_DROP,
"%s: bad cluster", __func__);
1354 if (vis == DVIS_PVS2)
1356 if (bsp->pvs2_matrix)
1359 memcpy(mask, row, bsp->visrowsize);
1367 if (vis == DVIS_PVS && bsp->pvs_matrix)
1370 memcpy(mask, row, bsp->visrowsize);
1375 in_end = (
byte *)bsp->vis + bsp->numvisibility;
1376 in = (
byte *)bsp->vis + bsp->vis->bitofs[cluster][vis];
1377 out_end = mask + bsp->visrowsize;
1388 if (in + 1 >= in_end) {
1393 if (out +
c > out_end) {
1400 }
while (out < out_end);
1404 if (bsp->checksum == 0x1e5b50c5) {
1406 if (cluster == 345 || cluster == 384) {
1407 Q_SetBit(mask, 466);
1408 Q_SetBit(mask, 484);
1409 Q_SetBit(mask, 692);
1411 }
else if (bsp->checksum == 0x04cfa792) {
1413 if (cluster == 395) {
1414 Q_SetBit(mask, 176);
1415 Q_SetBit(mask, 183);
1417 }
else if (bsp->checksum == 0x2c3ab9b0) {
1419 if (cluster == 629 || cluster == 631 ||
1420 cluster == 633 || cluster == 639) {
1421 Q_SetBit(mask, 908);
1422 Q_SetBit(mask, 909);
1423 Q_SetBit(mask, 910);
1424 Q_SetBit(mask, 915);
1425 Q_SetBit(mask, 923);
1426 Q_SetBit(mask, 924);
1427 Q_SetBit(mask, 927);
1428 Q_SetBit(mask, 930);
1429 Q_SetBit(mask, 938);
1430 Q_SetBit(mask, 939);
1431 Q_SetBit(mask, 947);
1443 while (node->plane) {
1444 d = PlaneDiffFast(p, node->plane);
1446 node = node->children[1];
1448 node = node->children[0];
1451 return (mleaf_t *)node;
1463 if (!bsp || !name) {
1464 Com_Error(ERR_DROP,
"%s: NULL", __func__);
1466 if (name[0] !=
'*') {
1467 Com_Error(ERR_DROP,
"%s: bad name: %s", __func__, name);
1469 num = atoi(name + 1);
1470 if (num < 1 || num >= bsp->nummodels) {
1471 Com_Error(ERR_DROP,
"%s: bad number: %d", __func__, num);
1474 return &bsp->models[num];