#include "qbsp.h"
int32_t c_nofaces;
int32_t c_facenodes;
int32_t planeused[MAX_MAP_PLANES_QBSP];
void EmitPlanes(void) {
int32_t i;
dplane_t *dp;
plane_t *mp;
mp = mapplanes;
for (i = 0; i < nummapplanes; i++, mp++) {
dp = &dplanes[numplanes];
VectorCopy(mp->normal, dp->normal);
dp->dist = mp->dist;
dp->type = mp->type;
numplanes++;
}
}
void EmitMarkFace(dleaf_t *leaf_p, face_t *f) {
int32_t i;
int32_t facenum;
while (f->merged)
f = f->merged;
if (f->split[0]) {
EmitMarkFace(leaf_p, f->split[0]);
EmitMarkFace(leaf_p, f->split[1]);
return;
}
facenum = f->outputnumber;
if (facenum == -1)
return;
if (facenum < 0 || facenum >= numfaces)
Error("Bad leafface");
for (i = leaf_p->firstleafface; i < numleaffaces; i++)
if (dleaffaces[i] == facenum)
break; if (i == numleaffaces) {
if (numleaffaces >= MAX_MAP_LEAFFACES)
Error("MAX_MAP_LEAFFACES");
dleaffaces[numleaffaces] = facenum;
numleaffaces++;
}
}
void EmitMarkFaceX(dleaf_tx *leaf_p, face_t *f) {
int32_t i;
int32_t facenum;
while (f->merged)
f = f->merged;
if (f->split[0]) {
EmitMarkFaceX(leaf_p, f->split[0]);
EmitMarkFaceX(leaf_p, f->split[1]);
return;
}
facenum = f->outputnumber;
if (facenum == -1)
return;
if (facenum < 0 || facenum >= numfaces)
Error("Bad leafface");
for (i = leaf_p->firstleafface; i < numleaffaces; i++)
if (dleaffacesX[i] == facenum)
break; if (i == numleaffaces) {
if (numleaffaces >= MAX_MAP_LEAFFACES_QBSP)
Error("MAX_MAP_LEAFFACES_QBSP");
dleaffacesX[numleaffaces] = facenum;
numleaffaces++;
}
}
void EmitLeaf(node_t *node) {
portal_t *p;
int32_t s;
face_t *f;
bspbrush_t *b;
int32_t i;
int32_t brushnum;
if (use_qbsp) {
dleaf_tx *leaf_p;
if (numleafs >= MAX_MAP_LEAFS_QBSP)
Error("MAX_MAP_LEAFS_QBSP");
leaf_p = &dleafsX[numleafs];
numleafs++;
leaf_p->contents = node->contents;
leaf_p->cluster = node->cluster;
leaf_p->area = node->area;
VectorCopy(node->mins, leaf_p->mins);
VectorCopy(node->maxs, leaf_p->maxs);
leaf_p->firstleafbrush = numleafbrushes;
for (b = node->brushlist; b; b = b->next) {
if (numleafbrushes >= MAX_MAP_LEAFBRUSHES_QBSP)
Error("MAX_MAP_LEAFBRUSHES_QBSP");
brushnum = b->original - mapbrushes;
for (i = leaf_p->firstleafbrush; i < numleafbrushes; i++)
if (dleafbrushesX[i] == brushnum)
break;
if (i == numleafbrushes) {
dleafbrushesX[numleafbrushes] = brushnum;
numleafbrushes++;
}
}
leaf_p->numleafbrushes = numleafbrushes - leaf_p->firstleafbrush;
if (leaf_p->contents & CONTENTS_SOLID)
return;
leaf_p->firstleafface = numleaffaces;
for (p = node->portals; p; p = p->next[s]) {
s = (p->nodes[1] == node);
f = p->face[s];
if (!f)
continue;
EmitMarkFaceX(leaf_p, f);
}
leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface;
}
else {
dleaf_t *leaf_p;
if (numleafs >= MAX_MAP_LEAFS)
Error("MAX_MAP_LEAFS");
leaf_p = &dleafs[numleafs];
numleafs++;
leaf_p->contents = node->contents;
leaf_p->cluster = node->cluster;
leaf_p->area = node->area;
VectorCopy(node->mins, leaf_p->mins);
VectorCopy(node->maxs, leaf_p->maxs);
leaf_p->firstleafbrush = numleafbrushes;
for (b = node->brushlist; b; b = b->next) {
if (numleafbrushes >= MAX_MAP_LEAFBRUSHES)
Error("MAX_MAP_LEAFBRUSHES");
brushnum = b->original - mapbrushes;
for (i = leaf_p->firstleafbrush; i < numleafbrushes; i++)
if (dleafbrushes[i] == brushnum)
break;
if (i == numleafbrushes) {
dleafbrushes[numleafbrushes] = brushnum;
numleafbrushes++;
}
}
leaf_p->numleafbrushes = numleafbrushes - leaf_p->firstleafbrush;
if (leaf_p->contents & CONTENTS_SOLID)
return;
leaf_p->firstleafface = numleaffaces;
for (p = node->portals; p; p = p->next[s]) {
s = (p->nodes[1] == node);
f = p->face[s];
if (!f)
continue;
EmitMarkFace(leaf_p, f);
}
leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface;
}
}
void EmitFace(face_t *f) {
int32_t i;
int32_t e;
f->outputnumber = -1;
if (f->numpoints < 3) {
return; }
if (f->merged || f->split[0] || f->split[1]) {
return; }
f->outputnumber = numfaces;
if (use_qbsp) {
dface_tx *df;
if (numfaces >= MAX_MAP_FACES_QBSP)
Error("numfaces == MAX_MAP_FACES_QBSP");
df = &dfacesX[numfaces];
numfaces++;
df->planenum = f->planenum & (~1);
df->side = f->planenum & 1;
df->firstedge = numsurfedges;
df->numedges = f->numpoints;
df->texinfo = f->texinfo;
for (i = 0; i < f->numpoints; i++) {
e = GetEdge(f->vertexnums[i], f->vertexnums[(i + 1) % f->numpoints], f);
if (numsurfedges >= MAX_MAP_SURFEDGES_QBSP)
Error("numsurfedges == MAX_MAP_SURFEDGES_QBSP");
dsurfedges[numsurfedges] = e;
numsurfedges++;
}
} else {
dface_t *df;
if (numfaces >= MAX_MAP_FACES)
Error("numfaces == MAX_MAP_FACES");
df = &dfaces[numfaces];
numfaces++;
df->planenum = f->planenum & (~1);
df->side = f->planenum & 1;
df->firstedge = numsurfedges;
df->numedges = f->numpoints;
df->texinfo = f->texinfo;
for (i = 0; i < f->numpoints; i++) {
e = GetEdge(f->vertexnums[i], f->vertexnums[(i + 1) % f->numpoints], f);
if (numsurfedges >= MAX_MAP_SURFEDGES)
Error("numsurfedges == MAX_MAP_SURFEDGES");
dsurfedges[numsurfedges] = e;
numsurfedges++;
}
}
}
int32_t EmitDrawNode_r(node_t *node) {
face_t *f;
int32_t i;
if (node->planenum == PLANENUM_LEAF) {
EmitLeaf(node);
return -numleafs;
}
if (use_qbsp) {
dnode_tx *n;
if (numnodes == MAX_MAP_NODES_QBSP)
Error("MAX_MAP_NODES_QBSP");
n = &dnodesX[numnodes];
numnodes++;
VectorCopy(node->mins, n->mins);
VectorCopy(node->maxs, n->maxs);
planeused[node->planenum]++;
planeused[node->planenum ^ 1]++;
if (node->planenum & 1)
Error("WriteDrawNodes_r: odd planenum");
n->planenum = node->planenum;
n->firstface = numfaces;
if (!node->faces)
c_nofaces++;
else
c_facenodes++;
for (f = node->faces; f; f = f->next)
EmitFace(f);
n->numfaces = numfaces - n->firstface;
for (i = 0; i < 2; i++) {
if (node->children[i]->planenum == PLANENUM_LEAF) {
n->children[i] = -(numleafs + 1);
EmitLeaf(node->children[i]);
} else {
n->children[i] = numnodes;
EmitDrawNode_r(node->children[i]);
}
}
return n - dnodesX;
}
else {
dnode_t *n;
if (numnodes == MAX_MAP_NODES)
Error("MAX_MAP_NODES");
n = &dnodes[numnodes];
numnodes++;
VectorCopy(node->mins, n->mins);
VectorCopy(node->maxs, n->maxs);
planeused[node->planenum]++;
planeused[node->planenum ^ 1]++;
if (node->planenum & 1)
Error("WriteDrawNodes_r: odd planenum");
n->planenum = node->planenum;
n->firstface = numfaces;
if (!node->faces)
c_nofaces++;
else
c_facenodes++;
for (f = node->faces; f; f = f->next)
EmitFace(f);
n->numfaces = numfaces - n->firstface;
for (i = 0; i < 2; i++) {
if (node->children[i]->planenum == PLANENUM_LEAF) {
n->children[i] = -(numleafs + 1);
EmitLeaf(node->children[i]);
} else {
n->children[i] = numnodes;
EmitDrawNode_r(node->children[i]);
}
}
return n - dnodes;
}
}
void WriteBSP(node_t *headnode) {
int32_t oldfaces;
c_nofaces = 0;
c_facenodes = 0;
qprintf("--- WriteBSP ---\n");
oldfaces = numfaces;
dmodels[nummodels].headnode = EmitDrawNode_r(headnode);
EmitAreaPortals(headnode);
qprintf("%5i nodes with faces\n", c_facenodes);
qprintf("%5i nodes without faces\n", c_nofaces);
qprintf("%5i faces\n", numfaces - oldfaces);
}
void SetModelNumbers(void) {
int32_t i;
int32_t models;
char value[12];
models = 1;
for (i = 1; i < num_entities; i++) {
if (entities[i].numbrushes) {
sprintf(value, "*%i", models);
models++;
SetKeyValue(&entities[i], "model", value);
}
}
}
#define MAX_SWITCHED_LIGHTS 32
void SetLightStyles(void) {
int32_t stylenum;
char *t;
entity_t *e;
int32_t i, j;
char value[11];
char lighttargets[MAX_SWITCHED_LIGHTS][64];
stylenum = 0;
for (i = 1; i < num_entities; i++) {
e = &entities[i];
t = ValueForKey(e, "classname");
if (Q_strncasecmp(t, "light", 5))
continue;
t = ValueForKey(e, "targetname");
if (!t[0])
continue;
for (j = 0; j < stylenum; j++)
if (!strcmp(lighttargets[j], t))
break;
if (j == stylenum) {
if (stylenum == MAX_SWITCHED_LIGHTS)
Error("stylenum == MAX_SWITCHED_LIGHTS");
strcpy(lighttargets[j], t);
stylenum++;
}
sprintf(value, "%i", 32 + j);
SetKeyValue(e, "style", value);
}
}
void EmitBrushes(void) {
int32_t i, j, bnum, s, x;
dbrush_t *db;
mapbrush_t *b;
vec3_t normal;
vec_t dist;
int32_t planenum;
numbrushsides = 0;
numbrushes = nummapbrushes;
for (bnum = 0; bnum < nummapbrushes; bnum++) {
b = &mapbrushes[bnum];
db = &dbrushes[bnum];
db->contents = b->contents;
db->firstside = numbrushsides;
db->numsides = b->numsides;
if (use_qbsp) {
dbrushside_tx *cp;
for (j = 0; j < b->numsides; j++) {
if (numbrushsides == MAX_MAP_BRUSHSIDES_QBSP)
Error("MAX_MAP_BRUSHSIDES_QBSP");
cp = &dbrushsidesX[numbrushsides];
numbrushsides++;
cp->planenum = b->original_sides[j].planenum;
cp->texinfo = b->original_sides[j].texinfo;
}
} else {
for (j = 0; j < b->numsides; j++) {
dbrushside_t *cp;
if (numbrushsides == MAX_MAP_BRUSHSIDES)
Error("MAX_MAP_BRUSHSIDES");
cp = &dbrushsides[numbrushsides];
numbrushsides++;
cp->planenum = b->original_sides[j].planenum;
cp->texinfo = b->original_sides[j].texinfo;
}
}
for (x = 0; x < 3; x++)
for (s = -1; s <= 1; s += 2) {
VectorCopy(vec3_origin, normal);
normal[x] = s;
if (s == -1)
dist = -b->mins[x];
else
dist = b->maxs[x];
planenum = FindFloatPlane(normal, dist, b->brushnum);
for (i = 0; i < b->numsides; i++)
if (b->original_sides[i].planenum == planenum)
break;
if (i == b->numsides) {
if (use_qbsp) {
if (numbrushsides >= MAX_MAP_BRUSHSIDES_QBSP)
Error("MAX_MAP_BRUSHSIDES_QBSP");
dbrushsidesX[numbrushsides].planenum = planenum;
dbrushsidesX[numbrushsides].texinfo = dbrushsidesX[numbrushsides - 1].texinfo;
} else {
if (numbrushsides >= MAX_MAP_BRUSHSIDES)
Error("MAX_MAP_BRUSHSIDES");
dbrushsides[numbrushsides].planenum = planenum;
dbrushsides[numbrushsides].texinfo = dbrushsides[numbrushsides - 1].texinfo;
}
numbrushsides++;
db->numsides++;
}
}
}
}
void BeginBSPFile(void) {
nummodels = 0;
numfaces = 0;
numnodes = 0;
numbrushsides = 0;
numvertexes = 0;
numleaffaces = 0;
numleafbrushes = 0;
numsurfedges = 0;
numedges = 1;
numvertexes = 1;
numleafs = 1;
dleafs[0].contents = CONTENTS_SOLID;
dleafsX[0].contents = CONTENTS_SOLID;
}
void EndBSPFile(void) {
char path[1030];
EmitBrushes();
EmitPlanes();
UnparseEntities();
#if 0#endif
sprintf(path, "%s.bsp", source);
WriteBSPFile(path);
}
int32_t firstmodleaf;
extern int32_t firstmodeledge;
extern int32_t firstmodelface;
void BeginModel(void) {
dmodel_t *mod;
int32_t start, end;
mapbrush_t *b;
int32_t j;
entity_t *e;
vec3_t mins, maxs;
if (use_qbsp) {
if (nummodels == WARN_MAP_MODELS_QBSP)
printf("WARNING: nummodels may exceed protocol limit (%i)\n", WARN_MAP_MODELS_QBSP);
if (nummodels == MAX_MAP_MODELS_QBSP)
Error("nummodels exceeds MAX_MAP_MODELS_QBSP");
} else if (nummodels == MAX_MAP_MODELS)
Error("nummodels exceeds MAX_MAP_MODELS");
mod = &dmodels[nummodels];
mod->firstface = numfaces;
firstmodleaf = numleafs;
firstmodeledge = numedges;
firstmodelface = numfaces;
e = &entities[entity_num];
start = e->firstbrush;
end = start + e->numbrushes;
ClearBounds(mins, maxs);
for (j = start; j < end; j++) {
b = &mapbrushes[j];
if (!b->numsides)
continue; AddPointToBounds(b->mins, mins, maxs);
AddPointToBounds(b->maxs, mins, maxs);
}
VectorCopy(mins, mod->mins);
VectorCopy(maxs, mod->maxs);
}
void EndModel(void) {
dmodel_t *mod;
mod = &dmodels[nummodels];
mod->numfaces = numfaces - mod->firstface;
nummodels++;
}