port in OQ's detail, hint and skip brush/texture enhancements

This commit is contained in:
Bill Currie 2003-02-04 23:26:26 +00:00
parent 2dd8a6c39d
commit 7073afc0a4
17 changed files with 463 additions and 127 deletions

View File

@ -43,6 +43,9 @@ typedef struct
// volume. is this still needed?
#define SIDESPACE 24
#define TEX_SKIP -1
#define TEX_HINT -2
//============================================================================
typedef struct
@ -79,6 +82,8 @@ typedef struct visfacet_s
struct visfacet_s *original; // face on node
int outputnumber; // only valid for original faces after
// write surfaces
qboolean detail; // is a detail face
int numpoints;
vec3_t pts[MAXEDGES]; // FIXME: change to use winding_t
int edges[MAXEDGES];
@ -93,6 +98,8 @@ typedef struct surface_s
vec3_t mins, maxs;
qboolean onnode; // true if surface has already been used
// as a splitting node
qboolean has_detail; // true if the surface has detail brushes
qboolean has_struct; // true if the surface has non-detail brushes
face_t *faces; // links to all the faces on either side of the surf
} surface_t;
@ -118,6 +125,8 @@ typedef struct node_s
int visleafnum; // -1 = solid
int valid; // for flood filling
int occupied; // light number in leaf for outside filling
int o_dist; // distance to nearest entity
int detail; // 1 if created by detail split
} node_t;
// brush.c ====================================================================
@ -199,6 +208,7 @@ typedef struct portal_s
extern node_t outside_node; // portals outside the world face this
void PortalizeWorld (node_t *headnode);
void PortalizeWorldDetail (node_t *headnode); // stop at detail nodes
void WritePortalfile (node_t *headnode);
void FreeAllPortals (node_t *node);

View File

@ -32,6 +32,7 @@ typedef struct mbrush_s
{
struct mbrush_s *next;
mface_t *faces;
qboolean detail; // true if brush is detail brush
} mbrush_t;
typedef struct epair_s

View File

@ -610,6 +610,10 @@ LoadBrush (mbrush_t *mb, int hullnum)
if (hullnum) {
ExpandBrush (hullnum);
CreateBrushFaces ();
} else if (mb->detail) {
face_t *f;
for (f = brush_faces; f; f = f->next);
f->detail = 1;
}
// create the brush

View File

@ -65,6 +65,7 @@ NewFaceFromFace (face_t *in)
newf->original = in->original;
newf->contents[0] = in->contents[0];
newf->contents[1] = in->contents[1];
newf->detail = in->detail;
return newf;
}
@ -306,8 +307,13 @@ BuildSurfaces (void)
s->next = surfhead;
surfhead = s;
s->faces = *f;
for (count = s->faces; count; count = count->next)
for (count = s->faces; count; count = count->next) {
csgmergefaces++;
if (count->detail)
s->has_detail = 1;
else
s->has_struct = 1;
}
CalcSurfaceInfo (s); // bounding box and flags
}
@ -322,6 +328,9 @@ CopyFacesToOutside (brush_t *b)
outside = NULL;
for (f = b->faces; f; f = f->next) {
if (f->texturenum == TEX_SKIP)
continue;
brushfaces++;
newf = AllocFace ();
*newf = *f;
@ -359,9 +368,17 @@ CSGFaces (brushset_t *bs)
// set outside to a copy of the brush's faces
CopyFacesToOutside (b1);
if (b1->faces->texturenum < 0) {
// Don't split HINT and SKIP brushes.
SaveOutside (false);
continue;
}
overwrite = false;
for (b2 = bs->brushes; b2; b2 = b2->next) {
if (b2->faces->texturenum < 0)
continue;
// see if b2 needs to clip a chunk out of b1
if (b1 == b2) {

View File

@ -47,12 +47,18 @@ entity_t entities[MAX_MAP_ENTITIES];
int nummiptex;
char miptex[MAX_MAP_TEXINFO][16];
int numdetailbrushes;
int
FindMiptex (const char *name)
{
int i;
if (strcmp (name, "hint") == 0)
return TEX_HINT;
if (strcmp (name, "skip") == 0)
return TEX_SKIP;
for (i = 0; i < nummiptex; i++) {
if (!strcmp (name, miptex[i]))
return i;
@ -75,6 +81,9 @@ FindTexinfo (texinfo_t *t)
int i, j;
texinfo_t *tex;
if (t->miptex < 0)
return t->miptex; // it's HINT or SKIP
// set the special flag
if (miptex[t->miptex][0] == '*'
|| !strncasecmp (miptex[t->miptex], "sky", 3))
@ -345,11 +354,10 @@ ParseBrush (void)
while (TokenAvailable (false)) {
GetToken (false);
//XXX
//if (!strcmp (token, "detail"))
// b->detail = 1;
//else
// Sys_Error ("Parse error on line %i", scriptline);
if (!strcmp (token, "detail"))
b->detail = 1;
else
Sys_Error ("Parse error on line %i", scriptline);
}
// if the three points are all on a previous plane, it is a duplicate
@ -484,6 +492,26 @@ ParseEntity (void)
ParseEpair ();
} while (1);
if (!strcmp ("am_detail", ValueForKey (mapent, "classname"))) {
mbrush_t *b, *lb;
// set detail flag
for (lb = b = mapent->brushes; b; lb = b, b = b->next) {
b->detail = 1;
numdetailbrushes++;
}
// add to worldspawn
lb->next = entities->brushes;
entities->brushes = mapent->brushes;
num_entities--;
memset (mapent, 0, sizeof (entity_t));
return true;
} else {
mbrush_t *b;
for (b = mapent->brushes; b; b = b->next)
if (b->detail)
numdetailbrushes++;
}
GetVectorForKey (mapent, "origin", mapent->origin);
return true;
}
@ -511,7 +539,7 @@ LoadMapFile (const char *filename)
qprintf ("--- LoadMapFile ---\n");
qprintf ("%s\n", filename);
qprintf ("%5i brushes\n", nummapbrushes);
qprintf ("%5i brushes (%i detail)\n", nummapbrushes, numdetailbrushes);
qprintf ("%5i entities\n", num_entities);
qprintf ("%5i miptex\n", nummiptex);
qprintf ("%5i texinfo\n", bsp->numtexinfo);

View File

@ -47,6 +47,32 @@ PointInLeaf (node_t *node, vec3_t point)
return PointInLeaf (node->children[1], point);
}
static void
FloodEntDist_r (node_t *n, int dist)
{
portal_t *p;
int s;
n->o_dist = dist;
for (p = n->portals; p; p = p->next[s]) {
s = (p->nodes[1] == n);
if (p->nodes[!s]->o_dist)
continue;
if ((p->nodes[0]->contents == CONTENTS_SOLID) ||
(p->nodes[1]->contents == CONTENTS_SOLID))
continue;
if ((p->nodes[0]->contents == CONTENTS_SKY) ||
(p->nodes[1]->contents == CONTENTS_SKY))
continue;
FloodEntDist_r (p->nodes[!s], dist + 1);
}
}
static qboolean
PlaceOccupant (int num, vec3_t point, node_t *headnode)
{
@ -56,6 +82,9 @@ PlaceOccupant (int num, vec3_t point, node_t *headnode)
if (n->contents == CONTENTS_SOLID)
return false;
n->occupied = num;
FloodEntDist_r (n, 1);
return true;
}
@ -230,6 +259,49 @@ FillOutside (node_t *node)
fclose (leakfile);
qprintf ("leak file written to %s\n", options.pointfile);
qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
if (!options.hullnum) {
node_t *n, *nextnode;;
portal_t *p, *p2;
int i, j, next, side;
vec3_t wc;
n = &outside_node;
next = -1;
while ((n->o_dist > 1) || (next == -1)) {
nextnode = NULL;
p2 = NULL;
for (p = n->portals; p; p = p->next[side]) {
side = (p->nodes[1] == n);
if ((next == -1)
|| ((p->nodes[!side]->o_dist < next)
&& (p->nodes[!side]->o_dist))
)
{
next = p->nodes[!side]->o_dist;
nextnode = p->nodes[!side];
p2 = p;
}
}
if (nextnode) {
n = nextnode;
wc[0] = wc[1] = wc[2] = 0;
for (i = 0; i < p2->winding->numpoints; i++) {
for (j = 0; j < 3; j++)
wc[j] += p2->winding->points[i][j];
}
for (j = 0; j < 3; j++)
wc[j] /= p2->winding->numpoints;
fprintf (leakfile, "%g %g %g\n", wc[0], wc[1], wc[2]);
} else
break;
}
v = entities[n->occupied].origin;
fprintf (leakfile, "%g %g %g\n", v[0], v[1], v[2]);
fclose (leakfile);
}
return false;
}
if (!options.hullnum)

View File

@ -159,6 +159,8 @@ PlaneFromWinding (winding_t *w, plane_t *plane)
plane->dist = DotProduct (w->points[0], plane->normal);
}
static int cutnode_detail;
static void
CutNodePortals_r (node_t *node)
{
@ -174,6 +176,9 @@ CutNodePortals_r (node_t *node)
if (node->contents)
return; // at a leaf, no more dividing
if (node->detail && cutnode_detail)
return;
plane = &planes[node->planenum];
f = node->children[0];
@ -275,6 +280,22 @@ PortalizeWorld (node_t *headnode)
qprintf ("----- portalize ----\n");
MakeHeadnodePortals (headnode);
cutnode_detail = 0;
CutNodePortals_r (headnode);
}
/*
PortalizeWorldDetail
Like PortalizeWorld, but stop at detail nodes - Alexander Malmberg.
*/
void
PortalizeWorldDetail (node_t *headnode)
{
qprintf ("----- portalize ----\n");
MakeHeadnodePortals (headnode);
cutnode_detail = 1;
CutNodePortals_r (headnode);
}
@ -302,11 +323,12 @@ FreeAllPortals (node_t *node)
// PORTAL FILE GENERATION
#define PORTALFILE "PRT1"
#define PORTALFILE "PRT1-AM"
FILE *pf;
int num_visleafs; // leafs the player can be in
int num_visportals;
int num_realleafs;
static void
WriteFloat (FILE *f, vec_t v)
@ -317,6 +339,47 @@ WriteFloat (FILE *f, vec_t v)
fprintf (f, "%f ", v);
}
static int
HasContents (node_t *n, int cont)
{
if (n->contents == cont)
return 1;
if (n->contents)
return 0;
if (HasContents (n->children[0], cont))
return 1;
return HasContents (n->children[1], cont);
}
static int
ShareContents (node_t *n1, node_t *n2)
{
if (n1->contents) {
if (n1->contents == CONTENTS_SOLID)
return 0;
else
return HasContents (n2, n1->contents);
}
if (ShareContents (n1->children[0], n2))
return 1;
return ShareContents (n1->children[1], n2);
}
static int
SameContents (node_t *n1, node_t *n2)
{
if (n1->contents == CONTENTS_SOLID || n2->contents == CONTENTS_SOLID)
return 0;
if (n1->detail && n2->detail)
ShareContents (n1, n2);
if (n1->detail)
return HasContents (n1, n2->contents);
if (n2->detail)
return HasContents (n2, n1->contents);
return n1->contents == n2->contents;
}
static void
WritePortalFile_r (node_t *node)
{
@ -325,7 +388,7 @@ WritePortalFile_r (node_t *node)
portal_t *p;
winding_t *w;
if (!node->contents) {
if (!node->contents && !node->detail) {
WritePortalFile_r (node->children[0]);
WritePortalFile_r (node->children[1]);
return;
@ -337,7 +400,7 @@ WritePortalFile_r (node_t *node)
for (p = node->portals; p;) {
w = p->winding;
if (w && p->nodes[0] == node
&& p->nodes[0]->contents == p->nodes[1]->contents) {
&& SameContents (p->nodes[0], p->nodes[1])) {
// write out to the file
// sometimes planes get turned around when they are very near the
@ -369,12 +432,41 @@ WritePortalFile_r (node_t *node)
}
static void
WritePortalLeafs_r (node_t *n)
{
if (!n->contents) {
WritePortalLeafs_r (n->children[0]);
WritePortalLeafs_r (n->children[1]);
} else {
if (n->visleafnum != -1)
fprintf (pf, "%i\n", n->visleafnum);
}
}
static void
SetCluster_r (node_t *n, int num)
{
if (n->contents == CONTENTS_SOLID) {
// solid block, viewpoint never inside
n->visleafnum = -1;
return;
}
n->visleafnum = num;
if (!n->contents) {
SetCluster_r (n->children[0], num);
SetCluster_r (n->children[1], num);
} else
num_realleafs++;
}
static void
NumberLeafs_r (node_t *node)
{
portal_t *p;
if (!node->contents) {
if (!node->contents && !node->detail) {
// decision node
node->visleafnum = -99;
NumberLeafs_r (node->children[0]);
@ -396,12 +488,19 @@ NumberLeafs_r (node_t *node)
for (p = node->portals; p;) {
if (p->nodes[0] == node) {
// only write out from first leaf
if (p->nodes[0]->contents == p->nodes[1]->contents)
if (SameContents(p->nodes[0], p->nodes[1]))
num_visportals++;
p = p->next[0];
} else
p = p->next[1];
}
if (node->detail) {
SetCluster_r (node->children[0], node->visleafnum);
SetCluster_r (node->children[1], node->visleafnum);
} else {
num_realleafs++;
}
}
void
@ -411,6 +510,7 @@ WritePortalfile (node_t *headnode)
// portals
num_visleafs = 0;
num_visportals = 0;
num_realleafs = 0;
NumberLeafs_r (headnode);
// write the file
@ -422,8 +522,11 @@ WritePortalfile (node_t *headnode)
fprintf (pf, "%s\n", PORTALFILE);
fprintf (pf, "%i\n", num_visleafs);
fprintf (pf, "%i\n", num_visportals);
fprintf (pf, "%i\n", num_realleafs);
WritePortalFile_r (headnode);
WritePortalLeafs_r (headnode);
fclose (pf);
}

View File

@ -199,6 +199,9 @@ GrowNodeRegion_r (node_t * node)
node->firstface = bsp->numfaces;
for (f = node->faces; f; f = f->next) {
if (f->texturenum < 0)
continue;
// if (f->outputnumber != -1)
// continue; // allready grown into an earlier region

View File

@ -24,6 +24,9 @@
static __attribute__ ((unused)) const char rcsid[] =
"$Id$";
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#include <stdlib.h>
#include "QF/sys.h"
@ -155,16 +158,16 @@ ChooseMidPlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs)
*/
static surface_t *
ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs,
qboolean usefloors)
qboolean usefloors, qboolean usedetail)
{
face_t *f;
int j, k, l;
int j, k, l, ishint;
plane_t *plane;
surface_t *p, *p2, *bestsurface;
vec_t bestvalue, bestdistribution, value, dist;
// pick the plane that splits the least
bestvalue = 99999;
bestvalue = 999999;
bestsurface = NULL;
bestdistribution = 9e30;
@ -172,6 +175,16 @@ ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs,
if (p->onnode)
continue;
for (f = p->faces; f; f = f->next)
if (f->texturenum == TEX_HINT)
break;
ishint = f != 0;
if (p->has_struct && usedetail)
continue;
if (!p->has_struct && !usedetail)
continue;
plane = &planes[p->planenum];
k = 0;
@ -186,7 +199,10 @@ ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs,
for (f = p2->faces; f; f = f->next) {
if (FaceSide (f, plane) == SIDE_ON) {
k++;
if (!ishint && f->texturenum == TEX_HINT)
k += 9999;
else
k++;
if (k >= bestvalue)
break;
}
@ -239,12 +255,14 @@ ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs,
returns NULL if the surface list can not be divided any more (a leaf)
*/
static surface_t *
SelectPartition (surface_t *surfaces)
SelectPartition (surface_t *surfaces, int *detail)
{
int i, j;
surface_t *p, *bestsurface;
vec3_t mins, maxs;
*detail = 0;
// count onnode surfaces
i = 0;
bestsurface = NULL;
@ -257,8 +275,11 @@ SelectPartition (surface_t *surfaces)
if (i == 0)
return NULL;
if (i == 1)
if (i == 1) {
if (!bestsurface->has_struct && !usemidsplit)
*detail = 1;
return bestsurface; // this is a final split
}
// calculate a bounding box of the entire surfaceset
for (i = 0; i < 3; i++) {
@ -283,7 +304,11 @@ SelectPartition (surface_t *surfaces)
if (bestsurface)
return bestsurface;
#endif
return ChoosePlaneFromList (surfaces, mins, maxs, true);
bestsurface = ChoosePlaneFromList (surfaces, mins, maxs, true, false);
if (bestsurface)
return bestsurface;
*detail = 1;
return ChoosePlaneFromList (surfaces, mins, maxs, true, true);
}
//============================================================================
@ -331,6 +356,8 @@ DividePlane (surface_t *in, plane_t *split, surface_t **front,
plane_t *inplane;
surface_t *news;
int have[2][2]; // [front|back][detail|struct]
inplane = &planes[in->planenum];
// parallel case is easy
@ -345,15 +372,26 @@ DividePlane (surface_t *in, plane_t *split, surface_t **front,
in->faces = NULL;
news->faces = NULL;
in->onnode = news->onnode = true;
in->has_detail = in->has_struct = false;
for (; facet; facet = next) {
next = facet->next;
if (facet->planeside == 1) {
facet->next = news->faces;
news->faces = facet;
if (facet->detail)
news->has_detail = true;
else
news->has_struct = true;
} else {
facet->next = in->faces;
in->faces = facet;
if (facet->detail)
in->has_detail = true;
else
in->has_struct = true;
}
}
@ -382,16 +420,19 @@ DividePlane (surface_t *in, plane_t *split, surface_t **front,
frontlist = NULL;
backlist = NULL;
memset (have, 0, sizeof (have));
for (facet = in->faces; facet; facet = next) {
next = facet->next;
SplitFace (facet, split, &frontfrag, &backfrag);
if (frontfrag) {
frontfrag->next = frontlist;
frontlist = frontfrag;
have[0][frontfrag->detail] = 1;
}
if (backfrag) {
backfrag->next = backlist;
backlist = backfrag;
have[1][backfrag->detail] = 1;
}
}
@ -418,6 +459,12 @@ DividePlane (surface_t *in, plane_t *split, surface_t **front,
in->faces = frontlist;
*front = in;
in->has_struct = have[0][0];
in->has_detail = have[0][1];
news->has_struct = have[1][0];
news->has_detail = have[1][1];
// recalc bboxes and flags
CalcSurfaceInfo (news);
CalcSurfaceInfo (in);
@ -459,6 +506,8 @@ LinkConvexFaces (surface_t *planelist, node_t *leafnode)
count = 0;
for (surf = planelist; surf; surf = surf->next) {
for (f = surf->faces; f; f = f->next) {
if (f->texturenum < 0)
continue;
count++;
if (!leafnode->contents)
leafnode->contents = f->contents[0];
@ -495,8 +544,10 @@ LinkConvexFaces (surface_t *planelist, node_t *leafnode)
pnext = surf->next;
for (f = surf->faces; f; f = next) {
next = f->next;
leafnode->markfaces[i] = f->original;
i++;
if (f->texturenum >= 0) {
leafnode->markfaces[i] = f->original;
i++;
}
FreeFace (f);
}
FreeSurface (surf);
@ -548,8 +599,9 @@ PartitionSurfaces (surface_t *surfaces, node_t *node)
surface_t *frontfrag, *backfrag;
plane_t *splitplane;
split = SelectPartition (surfaces);
split = SelectPartition (surfaces, &node->detail);
if (!split) { // this is a leaf node
node->detail = 0;
node->planenum = PLANENUM_LEAF;
LinkConvexFaces (surfaces, node);
return;

View File

@ -365,7 +365,8 @@ MakeFaceEdges_r (node_t *node)
return;
for (f = node->faces; f; f = f->next)
FindFaceEdges (f);
if (f->texturenum >= 0)
FindFaceEdges (f);
MakeFaceEdges_r (node->children[0]);
MakeFaceEdges_r (node->children[1]);

View File

@ -387,7 +387,8 @@ tjunc_find_r (node_t *node)
return;
for (f = node->faces; f; f = f->next)
AddFaceEdges (f);
if (f->texturenum >= 0)
AddFaceEdges (f);
tjunc_find_r (node->children[0]);
tjunc_find_r (node->children[1]);
@ -405,6 +406,8 @@ tjunc_fix_r (node_t *node)
for (f = node->faces; f; f = next) {
next = f->next;
if (f->texturenum < 0)
continue;
FixFaceEdges (f);
}

View File

@ -173,6 +173,8 @@ WriteLeaf (node_t *node)
if (bsp->nummarksurfaces == MAX_MAP_MARKSURFACES)
Sys_Error ("nummarksurfaces == MAX_MAP_MARKSURFACES");
f = *fp;
if (f->texturenum < 0)
continue;
do {
BSP_AddMarkSurface (bsp, f->outputnumber);
f = f->original; // grab tjunction split faces

View File

@ -45,10 +45,10 @@ extern pthread_mutex_t *my_mutex;
#endif
#define MAX_PORTALS 32768
#define PORTALFILE "PRT1"
#define PORTALFILE "PRT1-AM"
#define ON_EPSILON 0.1
#define MAX_POINTS_ON_WINDING 64
#define MAX_PORTALS_ON_LEAF 128
#define MAX_PORTALS_ON_CLUSTER 128
typedef struct {
vec3_t normal;
@ -70,7 +70,7 @@ typedef enum {
typedef struct {
plane_t plane; // normal pointing into neighbor
int leaf; // neighbor
int cluster; // neighbor
winding_t *winding;
vstatus_t status;
byte *visbits;
@ -86,19 +86,20 @@ typedef struct seperating_plane_s {
typedef struct passage_s {
struct passage_s *next;
int from, to; // leaf numbers
int from, to; // cluster numbers
sep_t *planes;
} passage_t;
typedef struct leaf_s {
typedef struct cluster_s {
int numportals;
passage_t *passages;
portal_t *portals[MAX_PORTALS_ON_LEAF];
} leaf_t;
portal_t *portals[MAX_PORTALS_ON_CLUSTER];
int visofs;
} cluster_t;
typedef struct pstack_s {
struct pstack_s *next;
leaf_t *leaf;
cluster_t *cluster;
portal_t *portal; // portal exiting
winding_t *source, *pass;
plane_t portalplane;
@ -106,22 +107,25 @@ typedef struct pstack_s {
} pstack_t;
typedef struct {
byte *leafvis; // bit string
byte *clustervis; // bit string
portal_t *base;
pstack_t pstack_head;
} threaddata_t;
extern int numportals;
extern int portalleafs;
extern int portalclusters;
extern int numrealleafs;
extern int c_portaltest;
extern int c_portalpass;
extern int c_portalcheck;
extern int bitbytes;
extern int bitbytes_l;
extern int bitlongs;
extern struct bsp_s *bsp;
extern portal_t *portals;
extern leaf_t *leafs;
extern cluster_t *clusters;
extern int *leafcluster;
extern byte *uncompressed;
extern int c_chains;
@ -133,7 +137,7 @@ winding_t *NewWinding (int points);
winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon);
winding_t *CopyWinding (winding_t *winding);
void LeafFlow (int leafnum);
void ClusterFlow (int clusternum);
void BasePortalVis (void);
void PortalFlow (portal_t *portal);
void CalcAmbientSounds (void);

View File

@ -60,7 +60,7 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "vis.h"
#include "options.h"
static int leafsee;
static int clustersee;
static byte portalsee[MAX_PORTALS];
/*
@ -68,24 +68,24 @@ static byte portalsee[MAX_PORTALS];
some of the final calculations.
*/
static void
SimpleFlood (portal_t *srcportal, int leafnum)
SimpleFlood (portal_t *srcportal, int clusternum)
{
int i;
leaf_t *leaf;
cluster_t *cluster;
portal_t *portal;
if (srcportal->mightsee[leafnum >> 3] & (1 << (leafnum & 7)))
if (srcportal->mightsee[clusternum >> 3] & (1 << (clusternum & 7)))
return;
srcportal->mightsee[leafnum >> 3] |= (1 << (leafnum & 7));
leafsee++;
srcportal->mightsee[clusternum >> 3] |= (1 << (clusternum & 7));
clustersee++;
leaf = &leafs[leafnum];
cluster = &clusters[clusternum];
for (i = 0; i < leaf->numportals; i++) {
portal = leaf->portals[i];
for (i = 0; i < cluster->numportals; i++) {
portal = cluster->portals[i];
if (!portalsee[portal - portals])
continue;
SimpleFlood (srcportal, portal->leaf);
SimpleFlood (srcportal, portal->cluster);
}
}
@ -129,8 +129,8 @@ BasePortalVis (void)
portalsee[j] = 1;
}
leafsee = 0;
SimpleFlood (portal, portal->leaf);
portal->nummightsee = leafsee;
clustersee = 0;
SimpleFlood (portal, portal->cluster);
portal->nummightsee = clustersee;
}
}

View File

@ -61,13 +61,13 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "options.h"
static void
CheckStack (leaf_t *leaf, threaddata_t *thread)
CheckStack (cluster_t *cluster, threaddata_t *thread)
{
pstack_t *portal;
for (portal = thread->pstack_head.next; portal; portal = portal->next)
if (portal->leaf == leaf)
Sys_Error ("CheckStack: leaf recursion");
if (portal->cluster == cluster)
Sys_Error ("CheckStack: cluster recursion");
}
/*
@ -188,16 +188,16 @@ ClipToSeparators (winding_t *source, winding_t *pass, winding_t *target,
}
/*
RecursiveLeafFlow
RecursiveClusterFlow
Flood fill through the leafs
If src_portal is NULL, this is the originating leaf
Flood fill through the clusters
If src_portal is NULL, this is the originating cluster
*/
static void
RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
{
int i, j;
leaf_t *leaf;
cluster_t *cluster;
long *test, *might, *vis;
qboolean more;
pstack_t stack;
@ -207,29 +207,29 @@ RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
c_chains++;
leaf = &leafs[leafnum];
CheckStack(leaf, thread);
cluster = &clusters[clusternum];
CheckStack(cluster, thread);
// mark the leaf as visible
if (!(thread->leafvis[leafnum >> 3] & (1 << (leafnum & 7)))) {
thread->leafvis[leafnum >> 3] |= 1 << (leafnum & 7);
// mark the cluster as visible
if (!(thread->clustervis[clusternum >> 3] & (1 << (clusternum & 7)))) {
thread->clustervis[clusternum >> 3] |= 1 << (clusternum & 7);
thread->base->numcansee++;
}
prevstack->next = &stack;
stack.next = NULL;
stack.leaf = leaf;
stack.cluster = cluster;
stack.portal = NULL;
stack.mightsee = malloc(bitbytes);
might = (long *) stack.mightsee;
vis = (long *) thread->leafvis;
vis = (long *) thread->clustervis;
// check all portals for flowing into other leafs
for (i = 0; i < leaf->numportals; i++) {
portal = leaf->portals[i];
// check all portals for flowing into other clusters
for (i = 0; i < cluster->numportals; i++) {
portal = cluster->portals[i];
if (!(prevstack->mightsee[portal->leaf >> 3]
& (1 << (portal->leaf & 7))))
if (!(prevstack->mightsee[portal->cluster >> 3]
& (1 << (portal->cluster & 7))))
continue; // can't possibly see it
// if the portal can't see anything we haven't already seen, skip it
if (portal->status == stat_done) {
@ -249,7 +249,7 @@ RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
if (!more) // can't see anything new
continue;
// get plane of portal, point normal into the neighbor leaf
// get plane of portal, point normal into the neighbor cluster
stack.portalplane = portal->plane;
VectorSubtract (vec3_origin, portal->plane.normal, backplane.normal);
backplane.dist = -portal->plane.dist;
@ -268,11 +268,11 @@ RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
continue;
if (!prevstack->pass) {
// the second leaf can only be blocked if coplanar
// the second cluster can only be blocked if coplanar
stack.source = prevstack->source;
stack.pass = target;
RecursiveLeafFlow (portal->leaf, thread, &stack);
RecursiveClusterFlow (portal->cluster, thread, &stack);
FreeWinding (target);
continue;
}
@ -340,7 +340,7 @@ RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
c_portalpass++;
// flow through it for real
RecursiveLeafFlow (portal->leaf, thread, &stack);
RecursiveClusterFlow (portal->cluster, thread, &stack);
FreeWinding (source);
FreeWinding (target);
@ -363,7 +363,7 @@ PortalFlow (portal_t *portal)
portal->visbits = calloc (1, bitbytes);
memset (&data, 0, sizeof (data));
data.leafvis = portal->visbits;
data.clustervis = portal->visbits;
data.base = portal;
data.pstack_head.portal = portal;
@ -371,7 +371,7 @@ PortalFlow (portal_t *portal)
data.pstack_head.portalplane = portal->plane;
data.pstack_head.mightsee = portal->mightsee;
RecursiveLeafFlow (portal->leaf, &data, &data.pstack_head);
RecursiveClusterFlow (portal->cluster, &data, &data.pstack_head);
portal->status = stat_done;
}

View File

@ -80,17 +80,20 @@ int c_portalcheck;
int c_vistest;
int numportals;
int portalleafs;
int portalclusters;
int numrealleafs;
int originalvismapsize;
int totalvis;
int count_sep;
int bitbytes; // (portalleafs + 63)>>3
int bitlongs;
int bitbytes_l; // (numrealleafs + 63)>>3
portal_t *portals;
leaf_t *leafs;
cluster_t *clusters;
dstring_t *visdata;
byte *uncompressed; // [bitbytes * portalleafs]
int *leafcluster; // leaf to cluster mappings as read from .prt file
static void
@ -305,7 +308,7 @@ CompressRow (byte *vis, byte *dest)
byte *dest_p;
dest_p = dest;
visrow = (portalleafs + 7) >> 3;
visrow = (numrealleafs + 7) >> 3;
for (j = 0; j < visrow; j++) {
*dest_p++ = vis[j];
@ -325,49 +328,70 @@ CompressRow (byte *vis, byte *dest)
return dest_p - dest;
}
/*
LeafFlow
static void
ClusterFlowExpand (byte *src, byte *dest)
{
int i, j;
Builds the entire visibility list for a leaf
for (j = 1, i = 0; i < numrealleafs; i++) {
if (src[leafcluster[i] >> 3] & (1 << (leafcluster[i] & 7)))
*dest |= j;
j <<= 1;
if (j == 256) {
j = 1;
dest++;
}
}
}
/*
ClusterFlow
Builds the entire visibility list for a cluster
*/
void
LeafFlow (int leafnum)
ClusterFlow (int clusternum)
{
byte *outbuffer;
byte compressed[MAX_MAP_LEAFS / 8];
int numvis, i, j;
leaf_t *leaf;
cluster_t *cluster;
portal_t *portal;
outbuffer = uncompressed + clusternum * bitbytes_l;
cluster = &clusters[clusternum];
// flow through all portals, collecting visible bits
outbuffer = uncompressed + leafnum * bitbytes;
leaf = &leafs[leafnum];
for (i = 0; i < leaf->numportals; i++) {
portal = leaf->portals[i];
memset (compressed, 0, sizeof (compressed));
for (i = 0; i < cluster->numportals; i++) {
portal = cluster->portals[i];
if (portal->status != stat_done)
Sys_Error ("portal not done");
for (j = 0; j < bitbytes; j++)
outbuffer[j] |= portal->visbits[j];
compressed[j] |= portal->visbits[j];
}
if (outbuffer[leafnum >> 3] & (1 << (leafnum & 7)))
Sys_Error ("Leaf portals saw into leaf");
if (compressed[clusternum >> 3] & (1 << (clusternum & 7)))
Sys_Error ("Cluster portals saw into cluster");
outbuffer[leafnum >> 3] |= (1 << (leafnum & 7));
compressed[clusternum >> 3] |= (1 << (clusternum & 7));
numvis = 0;
for (i = 0; i < portalleafs; i++)
if (outbuffer[i >> 3] & (1 << (i & 3)))
for (i = 0; i < portalclusters; i++)
if (compressed[i >> 3] & (1 << (i & 3)))
numvis++;
// expand to cluster->leaf PVS
ClusterFlowExpand (compressed, outbuffer);
// compress the bit string
if (options.verbosity > 0)
printf ("leaf %4i : %4i visible\n", leafnum, numvis);
printf ("cluster %4i : %4i visible\n", clusternum, numvis);
totalvis += numvis;
i = CompressRow (outbuffer, compressed);
bsp->leafs[leafnum + 1].visofs = visdata->size;
cluster->visofs = visdata->size;
dstring_append (visdata, compressed, i);
}
@ -436,11 +460,14 @@ CalcVis (void)
CalcPortalVis ();
// assemble the leaf vis lists by oring and compressing the portal lists
for (i = 0; i < portalleafs; i++)
LeafFlow (i);
for (i = 0; i < portalclusters; i++)
ClusterFlow (i);
for (i = 0; i < numrealleafs; i++) {
bsp->leafs[i].visofs = clusters[leafcluster[i]].visofs;
}
if (options.verbosity >= 0)
printf ("average leafs visible: %i\n", totalvis / portalleafs);
printf ("average clusters visible: %i\n", totalvis / portalclusters);
}
#if 0
static qboolean
@ -622,9 +649,9 @@ LoadPortals (char *name)
{
char magic[80];
FILE *f;
int leafnums[2];
int clusternums[2];
int numpoints, i, j;
leaf_t *leaf;
cluster_t *cluster;
plane_t plane;
portal_t *portal;
winding_t *winding;
@ -640,35 +667,39 @@ LoadPortals (char *name)
}
}
if (fscanf (f, "%79s\n%i\n%i\n", magic, &portalleafs, &numportals) != 3)
if (fscanf (f, "%79s\n%i\n%i\n%i\n", magic, &portalclusters, &numportals,
&numrealleafs) != 4)
Sys_Error ("LoadPortals: failed to read header");
if (strcmp (magic, PORTALFILE))
Sys_Error ("LoadPortals: not a portal file");
if (options.verbosity >= 0) {
printf ("%4i portalleafs\n", portalleafs);
printf ("%4i portalclusters\n", portalclusters);
printf ("%4i numportals\n", numportals);
printf ("%4i numrealleafs\n", numrealleafs);
}
bitbytes = ((portalleafs + 63) & ~63) >> 3;
bitbytes = ((portalclusters + 63) & ~63) >> 3;
bitlongs = bitbytes / sizeof (long);
bitbytes_l = ((numrealleafs + 63) & ~63) >> 3;
// each file portal is split into two memory portals, one for each
// direction
portals = calloc (2 * numportals, sizeof (portal_t));
leafs = calloc (portalleafs, sizeof (leaf_t));
clusters = calloc (portalclusters, sizeof (cluster_t));
originalvismapsize = portalleafs * ((portalleafs + 7) / 8);
originalvismapsize = numrealleafs * ((numrealleafs + 7) / 8);
for (i = 0, portal = portals; i < numportals; i++) {
if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0],
&leafnums[1]) != 3)
if (fscanf (f, "%i %i %i ", &numpoints, &clusternums[0],
&clusternums[1]) != 3)
Sys_Error ("LoadPortals: reading portal %i", i);
if (numpoints > MAX_POINTS_ON_WINDING)
Sys_Error ("LoadPortals: portal %i has too many points", i);
if ((unsigned) leafnums[0] > portalleafs
|| (unsigned) leafnums[1] > portalleafs)
if ((unsigned) clusternums[0] > portalclusters
|| (unsigned) clusternums[1] > portalclusters)
Sys_Error ("LoadPortals: reading portal %i", i);
winding = portal->winding = NewWinding (numpoints);
@ -693,30 +724,35 @@ LoadPortals (char *name)
PlaneFromWinding (winding, &plane);
// create forward portal
leaf = &leafs[leafnums[0]];
if (leaf->numportals == MAX_PORTALS_ON_LEAF)
Sys_Error ("Leaf with too many portals");
leaf->portals[leaf->numportals] = portal;
leaf->numportals++;
cluster = &clusters[clusternums[0]];
if (cluster->numportals == MAX_PORTALS_ON_CLUSTER)
Sys_Error ("Cluster with too many portals");
cluster->portals[cluster->numportals] = portal;
cluster->numportals++;
portal->winding = winding;
VectorSubtract (vec3_origin, plane.normal, portal->plane.normal);
portal->plane.dist = -plane.dist;
portal->leaf = leafnums[1];
portal->cluster = clusternums[1];
portal++;
// create backwards portal
leaf = &leafs[leafnums[1]];
if (leaf->numportals == MAX_PORTALS_ON_LEAF)
Sys_Error ("Leaf with too many portals");
leaf->portals[leaf->numportals] = portal;
leaf->numportals++;
cluster = &clusters[clusternums[1]];
if (cluster->numportals == MAX_PORTALS_ON_CLUSTER)
Sys_Error ("Cluster with too many portals");
cluster->portals[cluster->numportals] = portal;
cluster->numportals++;
portal->winding = winding;
portal->plane = plane;
portal->leaf = leafnums[0];
portal->cluster = clusternums[0];
portal++;
}
leafcluster = calloc (numrealleafs, sizeof (int));
for (i = 0; i < numrealleafs; i++)
if (fscanf (f, "%i\n", &leafcluster[i]) != 1)
Sys_Error ("LoadPortals: parse error in leaf->cluster mappings");
fclose (f);
}
@ -753,7 +789,7 @@ main (int argc, char **argv)
dstring_appendstr (portalfile, ".prt");
LoadPortals (portalfile->str);
uncompressed = calloc (bitbytes, portalleafs);
uncompressed = calloc (bitbytes_l, portalclusters);
CalcVis ();

View File

@ -106,16 +106,16 @@ CalcAmbientSounds (void)
texinfo_t *info;
miptex_t *miptex;
for (i = 0; i < portalleafs; i++) {
for (i = 0; i < numrealleafs - 1; i++) {
leaf = &bsp->leafs[i + 1];
// clear ambients
for (j = 0; j < NUM_AMBIENTS; j++)
dists[j] = 1020;
vis = &uncompressed[i * bitbytes];
vis = &uncompressed[leafcluster[i] * bitbytes_l];
for (j = 0; j < portalleafs; j++) {
for (j = 0; j < numrealleafs - 1; j++) {
if (!(vis[j >> 3] & (1 << (j & 7))))
continue;
@ -149,7 +149,7 @@ CalcAmbientSounds (void)
d = mins[l] - leaf->maxs[l];
else if (maxs[l] < leaf->mins[l])
d = leaf->mins[l] - mins[l];
else
else
d = 0;
if (d > maxd)
maxd = d;