qbsp: write portals to a new file format if using detail clusters

Fairly simple extension of the original "PRT1" format; the first four
lines are:

Identifier := "PRT2"
Number of Leafs := INTEGER
Number of Clusters := INTEGER
Number of Portals := INTEGER

Followed by one line for each portal made up of the following, separated
by whitespace:

Number of points on the portal winding := INTEGER
Cluster Number on the front side of the portal := INTEGER
Cluster Number on the back side of the portal := INTEGER
For each point, a coordinate in the format ( x y z ), where x, y, z are FLOATs.

After the portal descriptions, there will be one line for each cluster
which lists the leaf numbers included in that cluster.

LEAF1 LEAF2 LEAF3 ...

I should probably write this up in BNF somewhere, but it's pretty straight
forward.

Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
Kevin Shanahan 2013-02-24 12:00:30 +10:30
parent 520a8bbfdf
commit 0835b01da5
1 changed files with 52 additions and 45 deletions

View File

@ -38,7 +38,7 @@ PORTAL FILE GENERATION
==============================================================================
*/
static void PlaneFromWinding(winding_t *w, plane_t *plane);
static void PlaneFromWinding(const winding_t *w, plane_t *plane);
static void
WriteFloat(vec_t v)
@ -86,55 +86,53 @@ PortalThru(int contents0, int contents1)
}
static void
WritePortalFile_r(node_t *node)
WritePortals_r(node_t *node, bool clusters)
{
int i;
portal_t *p;
winding_t *w;
plane_t *pl, plane2;
const portal_t *p, *next;
const winding_t *w;
const plane_t *pl;
int i, front, back;
plane_t plane2;
if (!node->contents) {
WritePortalFile_r(node->children[0]);
WritePortalFile_r(node->children[1]);
WritePortals_r(node->children[0], clusters);
WritePortals_r(node->children[1], clusters);
return;
}
if (node->contents == CONTENTS_SOLID)
return;
for (p = node->portals; p;) {
for (p = node->portals; p; p = next) {
next = (p->nodes[0] == node) ? p->next[0] : p->next[1];
if (!p->winding || p->nodes[0] != node)
continue;
if (!PortalThru(p->nodes[0]->contents, p->nodes[1]->contents))
continue;
w = p->winding;
if (w && p->nodes[0] == node
&& PortalThru(p->nodes[0]->contents, p->nodes[1]->contents)) {
/*
* sometimes planes get turned around when they are very near
* the changeover point between different axis. interpret the
* plane the same way vis will, and flip the side orders if needed
*/
pl = &map.planes[p->planenum];
PlaneFromWinding(w, &plane2);
front = clusters ? p->nodes[0]->viscluster : p->nodes[0]->visleafnum;
back = clusters ? p->nodes[1]->viscluster : p->nodes[1]->visleafnum;
if (DotProduct(pl->normal, plane2.normal) < 1.0 - ANGLEEPSILON) {
/* backwards... */
fprintf(PortalFile, "%i %i %i ", w->numpoints,
p->nodes[1]->visleafnum, p->nodes[0]->visleafnum);
} else
fprintf(PortalFile, "%i %i %i ", w->numpoints,
p->nodes[0]->visleafnum, p->nodes[1]->visleafnum);
for (i = 0; i < w->numpoints; i++) {
fprintf(PortalFile, "(");
WriteFloat(w->points[i][0]);
WriteFloat(w->points[i][1]);
WriteFloat(w->points[i][2]);
fprintf(PortalFile, ") ");
}
fprintf(PortalFile, "\n");
}
if (p->nodes[0] == node)
p = p->next[0];
/*
* sometimes planes get turned around when they are very near the
* changeover point between different axis. interpret the plane the
* same way vis will, and flip the side orders if needed
*/
pl = &map.planes[p->planenum];
PlaneFromWinding(w, &plane2);
if (DotProduct(pl->normal, plane2.normal) < 1.0 - ANGLEEPSILON)
fprintf(PortalFile, "%i %i %i ", w->numpoints, back, front);
else
p = p->next[1];
fprintf(PortalFile, "%i %i %i ", w->numpoints, front, back);
for (i = 0; i < w->numpoints; i++) {
fprintf(PortalFile, "(");
WriteFloat(w->points[i][0]);
WriteFloat(w->points[i][1]);
WriteFloat(w->points[i][2]);
fprintf(PortalFile, ") ");
}
fprintf(PortalFile, "\n");
}
}
@ -209,11 +207,20 @@ WritePortalfile(node_t *headnode)
if (PortalFile == NULL)
Error(errOpenFailed, options.szBSPName, strerror(errno));
fprintf(PortalFile, "PRT1\n");
fprintf(PortalFile, "%i\n", num_visleafs);
fprintf(PortalFile, "%i\n", num_visportals);
WritePortalFile_r(headnode);
/* If no detail clusters, just use a normal PRT1 format */
if (num_visclusters == num_visleafs) {
fprintf(PortalFile, "PRT1\n");
fprintf(PortalFile, "%i\n", num_visleafs);
fprintf(PortalFile, "%i\n", num_visportals);
WritePortals_r(headnode, false);
} else {
fprintf(PortalFile, "PRT2\n");
fprintf(PortalFile, "%i\n", num_visleafs);
fprintf(PortalFile, "%i\n", num_visclusters);
fprintf(PortalFile, "%i\n", num_visportals);
WritePortals_r(headnode, true);
fprintf(PortalFile, "CLUSTERMAP NOT YET IMPLEMENTED\n");
}
fclose(PortalFile);
}
@ -342,7 +349,7 @@ MakeHeadnodePortals(const mapentity_t *ent, node_t *node)
}
static void
PlaneFromWinding(winding_t *w, plane_t *plane)
PlaneFromWinding(const winding_t *w, plane_t *plane)
{
vec3_t v1, v2;