mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
port in OQ's detail, hint and skip brush/texture enhancements
This commit is contained in:
parent
2dd8a6c39d
commit
7073afc0a4
17 changed files with 463 additions and 127 deletions
|
@ -43,6 +43,9 @@ typedef struct
|
||||||
// volume. is this still needed?
|
// volume. is this still needed?
|
||||||
#define SIDESPACE 24
|
#define SIDESPACE 24
|
||||||
|
|
||||||
|
#define TEX_SKIP -1
|
||||||
|
#define TEX_HINT -2
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -79,6 +82,8 @@ typedef struct visfacet_s
|
||||||
struct visfacet_s *original; // face on node
|
struct visfacet_s *original; // face on node
|
||||||
int outputnumber; // only valid for original faces after
|
int outputnumber; // only valid for original faces after
|
||||||
// write surfaces
|
// write surfaces
|
||||||
|
qboolean detail; // is a detail face
|
||||||
|
|
||||||
int numpoints;
|
int numpoints;
|
||||||
vec3_t pts[MAXEDGES]; // FIXME: change to use winding_t
|
vec3_t pts[MAXEDGES]; // FIXME: change to use winding_t
|
||||||
int edges[MAXEDGES];
|
int edges[MAXEDGES];
|
||||||
|
@ -93,6 +98,8 @@ typedef struct surface_s
|
||||||
vec3_t mins, maxs;
|
vec3_t mins, maxs;
|
||||||
qboolean onnode; // true if surface has already been used
|
qboolean onnode; // true if surface has already been used
|
||||||
// as a splitting node
|
// 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
|
face_t *faces; // links to all the faces on either side of the surf
|
||||||
} surface_t;
|
} surface_t;
|
||||||
|
|
||||||
|
@ -118,6 +125,8 @@ typedef struct node_s
|
||||||
int visleafnum; // -1 = solid
|
int visleafnum; // -1 = solid
|
||||||
int valid; // for flood filling
|
int valid; // for flood filling
|
||||||
int occupied; // light number in leaf for outside 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;
|
} node_t;
|
||||||
|
|
||||||
// brush.c ====================================================================
|
// brush.c ====================================================================
|
||||||
|
@ -199,6 +208,7 @@ typedef struct portal_s
|
||||||
extern node_t outside_node; // portals outside the world face this
|
extern node_t outside_node; // portals outside the world face this
|
||||||
|
|
||||||
void PortalizeWorld (node_t *headnode);
|
void PortalizeWorld (node_t *headnode);
|
||||||
|
void PortalizeWorldDetail (node_t *headnode); // stop at detail nodes
|
||||||
void WritePortalfile (node_t *headnode);
|
void WritePortalfile (node_t *headnode);
|
||||||
void FreeAllPortals (node_t *node);
|
void FreeAllPortals (node_t *node);
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ typedef struct mbrush_s
|
||||||
{
|
{
|
||||||
struct mbrush_s *next;
|
struct mbrush_s *next;
|
||||||
mface_t *faces;
|
mface_t *faces;
|
||||||
|
qboolean detail; // true if brush is detail brush
|
||||||
} mbrush_t;
|
} mbrush_t;
|
||||||
|
|
||||||
typedef struct epair_s
|
typedef struct epair_s
|
||||||
|
|
|
@ -610,6 +610,10 @@ LoadBrush (mbrush_t *mb, int hullnum)
|
||||||
if (hullnum) {
|
if (hullnum) {
|
||||||
ExpandBrush (hullnum);
|
ExpandBrush (hullnum);
|
||||||
CreateBrushFaces ();
|
CreateBrushFaces ();
|
||||||
|
} else if (mb->detail) {
|
||||||
|
face_t *f;
|
||||||
|
for (f = brush_faces; f; f = f->next);
|
||||||
|
f->detail = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the brush
|
// create the brush
|
||||||
|
|
|
@ -65,6 +65,7 @@ NewFaceFromFace (face_t *in)
|
||||||
newf->original = in->original;
|
newf->original = in->original;
|
||||||
newf->contents[0] = in->contents[0];
|
newf->contents[0] = in->contents[0];
|
||||||
newf->contents[1] = in->contents[1];
|
newf->contents[1] = in->contents[1];
|
||||||
|
newf->detail = in->detail;
|
||||||
|
|
||||||
return newf;
|
return newf;
|
||||||
}
|
}
|
||||||
|
@ -306,8 +307,13 @@ BuildSurfaces (void)
|
||||||
s->next = surfhead;
|
s->next = surfhead;
|
||||||
surfhead = s;
|
surfhead = s;
|
||||||
s->faces = *f;
|
s->faces = *f;
|
||||||
for (count = s->faces; count; count = count->next)
|
for (count = s->faces; count; count = count->next) {
|
||||||
csgmergefaces++;
|
csgmergefaces++;
|
||||||
|
if (count->detail)
|
||||||
|
s->has_detail = 1;
|
||||||
|
else
|
||||||
|
s->has_struct = 1;
|
||||||
|
}
|
||||||
CalcSurfaceInfo (s); // bounding box and flags
|
CalcSurfaceInfo (s); // bounding box and flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,6 +328,9 @@ CopyFacesToOutside (brush_t *b)
|
||||||
outside = NULL;
|
outside = NULL;
|
||||||
|
|
||||||
for (f = b->faces; f; f = f->next) {
|
for (f = b->faces; f; f = f->next) {
|
||||||
|
if (f->texturenum == TEX_SKIP)
|
||||||
|
continue;
|
||||||
|
|
||||||
brushfaces++;
|
brushfaces++;
|
||||||
newf = AllocFace ();
|
newf = AllocFace ();
|
||||||
*newf = *f;
|
*newf = *f;
|
||||||
|
@ -359,9 +368,17 @@ CSGFaces (brushset_t *bs)
|
||||||
// set outside to a copy of the brush's faces
|
// set outside to a copy of the brush's faces
|
||||||
CopyFacesToOutside (b1);
|
CopyFacesToOutside (b1);
|
||||||
|
|
||||||
|
if (b1->faces->texturenum < 0) {
|
||||||
|
// Don't split HINT and SKIP brushes.
|
||||||
|
SaveOutside (false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
overwrite = false;
|
overwrite = false;
|
||||||
|
|
||||||
for (b2 = bs->brushes; b2; b2 = b2->next) {
|
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
|
// see if b2 needs to clip a chunk out of b1
|
||||||
|
|
||||||
if (b1 == b2) {
|
if (b1 == b2) {
|
||||||
|
|
|
@ -47,12 +47,18 @@ entity_t entities[MAX_MAP_ENTITIES];
|
||||||
int nummiptex;
|
int nummiptex;
|
||||||
char miptex[MAX_MAP_TEXINFO][16];
|
char miptex[MAX_MAP_TEXINFO][16];
|
||||||
|
|
||||||
|
int numdetailbrushes;
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
FindMiptex (const char *name)
|
FindMiptex (const char *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (strcmp (name, "hint") == 0)
|
||||||
|
return TEX_HINT;
|
||||||
|
if (strcmp (name, "skip") == 0)
|
||||||
|
return TEX_SKIP;
|
||||||
for (i = 0; i < nummiptex; i++) {
|
for (i = 0; i < nummiptex; i++) {
|
||||||
if (!strcmp (name, miptex[i]))
|
if (!strcmp (name, miptex[i]))
|
||||||
return i;
|
return i;
|
||||||
|
@ -75,6 +81,9 @@ FindTexinfo (texinfo_t *t)
|
||||||
int i, j;
|
int i, j;
|
||||||
texinfo_t *tex;
|
texinfo_t *tex;
|
||||||
|
|
||||||
|
if (t->miptex < 0)
|
||||||
|
return t->miptex; // it's HINT or SKIP
|
||||||
|
|
||||||
// set the special flag
|
// set the special flag
|
||||||
if (miptex[t->miptex][0] == '*'
|
if (miptex[t->miptex][0] == '*'
|
||||||
|| !strncasecmp (miptex[t->miptex], "sky", 3))
|
|| !strncasecmp (miptex[t->miptex], "sky", 3))
|
||||||
|
@ -345,11 +354,10 @@ ParseBrush (void)
|
||||||
|
|
||||||
while (TokenAvailable (false)) {
|
while (TokenAvailable (false)) {
|
||||||
GetToken (false);
|
GetToken (false);
|
||||||
//XXX
|
if (!strcmp (token, "detail"))
|
||||||
//if (!strcmp (token, "detail"))
|
b->detail = 1;
|
||||||
// b->detail = 1;
|
else
|
||||||
//else
|
Sys_Error ("Parse error on line %i", scriptline);
|
||||||
// Sys_Error ("Parse error on line %i", scriptline);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the three points are all on a previous plane, it is a duplicate
|
// if the three points are all on a previous plane, it is a duplicate
|
||||||
|
@ -484,6 +492,26 @@ ParseEntity (void)
|
||||||
ParseEpair ();
|
ParseEpair ();
|
||||||
} while (1);
|
} 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);
|
GetVectorForKey (mapent, "origin", mapent->origin);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -511,7 +539,7 @@ LoadMapFile (const char *filename)
|
||||||
|
|
||||||
qprintf ("--- LoadMapFile ---\n");
|
qprintf ("--- LoadMapFile ---\n");
|
||||||
qprintf ("%s\n", filename);
|
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 entities\n", num_entities);
|
||||||
qprintf ("%5i miptex\n", nummiptex);
|
qprintf ("%5i miptex\n", nummiptex);
|
||||||
qprintf ("%5i texinfo\n", bsp->numtexinfo);
|
qprintf ("%5i texinfo\n", bsp->numtexinfo);
|
||||||
|
|
|
@ -47,6 +47,32 @@ PointInLeaf (node_t *node, vec3_t point)
|
||||||
return PointInLeaf (node->children[1], 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
|
static qboolean
|
||||||
PlaceOccupant (int num, vec3_t point, node_t *headnode)
|
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)
|
if (n->contents == CONTENTS_SOLID)
|
||||||
return false;
|
return false;
|
||||||
n->occupied = num;
|
n->occupied = num;
|
||||||
|
|
||||||
|
FloodEntDist_r (n, 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +259,49 @@ FillOutside (node_t *node)
|
||||||
fclose (leakfile);
|
fclose (leakfile);
|
||||||
qprintf ("leak file written to %s\n", options.pointfile);
|
qprintf ("leak file written to %s\n", options.pointfile);
|
||||||
qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (!options.hullnum)
|
if (!options.hullnum)
|
||||||
|
|
|
@ -159,6 +159,8 @@ PlaneFromWinding (winding_t *w, plane_t *plane)
|
||||||
plane->dist = DotProduct (w->points[0], plane->normal);
|
plane->dist = DotProduct (w->points[0], plane->normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cutnode_detail;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CutNodePortals_r (node_t *node)
|
CutNodePortals_r (node_t *node)
|
||||||
{
|
{
|
||||||
|
@ -174,6 +176,9 @@ CutNodePortals_r (node_t *node)
|
||||||
if (node->contents)
|
if (node->contents)
|
||||||
return; // at a leaf, no more dividing
|
return; // at a leaf, no more dividing
|
||||||
|
|
||||||
|
if (node->detail && cutnode_detail)
|
||||||
|
return;
|
||||||
|
|
||||||
plane = &planes[node->planenum];
|
plane = &planes[node->planenum];
|
||||||
|
|
||||||
f = node->children[0];
|
f = node->children[0];
|
||||||
|
@ -275,6 +280,22 @@ PortalizeWorld (node_t *headnode)
|
||||||
qprintf ("----- portalize ----\n");
|
qprintf ("----- portalize ----\n");
|
||||||
|
|
||||||
MakeHeadnodePortals (headnode);
|
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);
|
CutNodePortals_r (headnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,11 +323,12 @@ FreeAllPortals (node_t *node)
|
||||||
|
|
||||||
// PORTAL FILE GENERATION
|
// PORTAL FILE GENERATION
|
||||||
|
|
||||||
#define PORTALFILE "PRT1"
|
#define PORTALFILE "PRT1-AM"
|
||||||
|
|
||||||
FILE *pf;
|
FILE *pf;
|
||||||
int num_visleafs; // leafs the player can be in
|
int num_visleafs; // leafs the player can be in
|
||||||
int num_visportals;
|
int num_visportals;
|
||||||
|
int num_realleafs;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
WriteFloat (FILE *f, vec_t v)
|
WriteFloat (FILE *f, vec_t v)
|
||||||
|
@ -317,6 +339,47 @@ WriteFloat (FILE *f, vec_t v)
|
||||||
fprintf (f, "%f ", 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
|
static void
|
||||||
WritePortalFile_r (node_t *node)
|
WritePortalFile_r (node_t *node)
|
||||||
{
|
{
|
||||||
|
@ -325,7 +388,7 @@ WritePortalFile_r (node_t *node)
|
||||||
portal_t *p;
|
portal_t *p;
|
||||||
winding_t *w;
|
winding_t *w;
|
||||||
|
|
||||||
if (!node->contents) {
|
if (!node->contents && !node->detail) {
|
||||||
WritePortalFile_r (node->children[0]);
|
WritePortalFile_r (node->children[0]);
|
||||||
WritePortalFile_r (node->children[1]);
|
WritePortalFile_r (node->children[1]);
|
||||||
return;
|
return;
|
||||||
|
@ -337,7 +400,7 @@ WritePortalFile_r (node_t *node)
|
||||||
for (p = node->portals; p;) {
|
for (p = node->portals; p;) {
|
||||||
w = p->winding;
|
w = p->winding;
|
||||||
if (w && p->nodes[0] == node
|
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
|
// write out to the file
|
||||||
|
|
||||||
// sometimes planes get turned around when they are very near the
|
// 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
|
static void
|
||||||
NumberLeafs_r (node_t *node)
|
NumberLeafs_r (node_t *node)
|
||||||
{
|
{
|
||||||
portal_t *p;
|
portal_t *p;
|
||||||
|
|
||||||
if (!node->contents) {
|
if (!node->contents && !node->detail) {
|
||||||
// decision node
|
// decision node
|
||||||
node->visleafnum = -99;
|
node->visleafnum = -99;
|
||||||
NumberLeafs_r (node->children[0]);
|
NumberLeafs_r (node->children[0]);
|
||||||
|
@ -396,12 +488,19 @@ NumberLeafs_r (node_t *node)
|
||||||
for (p = node->portals; p;) {
|
for (p = node->portals; p;) {
|
||||||
if (p->nodes[0] == node) {
|
if (p->nodes[0] == node) {
|
||||||
// only write out from first leaf
|
// 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++;
|
num_visportals++;
|
||||||
p = p->next[0];
|
p = p->next[0];
|
||||||
} else
|
} else
|
||||||
p = p->next[1];
|
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
|
void
|
||||||
|
@ -411,6 +510,7 @@ WritePortalfile (node_t *headnode)
|
||||||
// portals
|
// portals
|
||||||
num_visleafs = 0;
|
num_visleafs = 0;
|
||||||
num_visportals = 0;
|
num_visportals = 0;
|
||||||
|
num_realleafs = 0;
|
||||||
NumberLeafs_r (headnode);
|
NumberLeafs_r (headnode);
|
||||||
|
|
||||||
// write the file
|
// write the file
|
||||||
|
@ -422,8 +522,11 @@ WritePortalfile (node_t *headnode)
|
||||||
fprintf (pf, "%s\n", PORTALFILE);
|
fprintf (pf, "%s\n", PORTALFILE);
|
||||||
fprintf (pf, "%i\n", num_visleafs);
|
fprintf (pf, "%i\n", num_visleafs);
|
||||||
fprintf (pf, "%i\n", num_visportals);
|
fprintf (pf, "%i\n", num_visportals);
|
||||||
|
fprintf (pf, "%i\n", num_realleafs);
|
||||||
|
|
||||||
WritePortalFile_r (headnode);
|
WritePortalFile_r (headnode);
|
||||||
|
|
||||||
|
WritePortalLeafs_r (headnode);
|
||||||
|
|
||||||
fclose (pf);
|
fclose (pf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,6 +199,9 @@ GrowNodeRegion_r (node_t * node)
|
||||||
node->firstface = bsp->numfaces;
|
node->firstface = bsp->numfaces;
|
||||||
|
|
||||||
for (f = node->faces; f; f = f->next) {
|
for (f = node->faces; f; f = f->next) {
|
||||||
|
if (f->texturenum < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
// if (f->outputnumber != -1)
|
// if (f->outputnumber != -1)
|
||||||
// continue; // allready grown into an earlier region
|
// continue; // allready grown into an earlier region
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
static __attribute__ ((unused)) const char rcsid[] =
|
static __attribute__ ((unused)) const char rcsid[] =
|
||||||
"$Id$";
|
"$Id$";
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#endif
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "QF/sys.h"
|
#include "QF/sys.h"
|
||||||
|
@ -155,16 +158,16 @@ ChooseMidPlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||||
*/
|
*/
|
||||||
static surface_t *
|
static surface_t *
|
||||||
ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs,
|
ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs,
|
||||||
qboolean usefloors)
|
qboolean usefloors, qboolean usedetail)
|
||||||
{
|
{
|
||||||
face_t *f;
|
face_t *f;
|
||||||
int j, k, l;
|
int j, k, l, ishint;
|
||||||
plane_t *plane;
|
plane_t *plane;
|
||||||
surface_t *p, *p2, *bestsurface;
|
surface_t *p, *p2, *bestsurface;
|
||||||
vec_t bestvalue, bestdistribution, value, dist;
|
vec_t bestvalue, bestdistribution, value, dist;
|
||||||
|
|
||||||
// pick the plane that splits the least
|
// pick the plane that splits the least
|
||||||
bestvalue = 99999;
|
bestvalue = 999999;
|
||||||
bestsurface = NULL;
|
bestsurface = NULL;
|
||||||
bestdistribution = 9e30;
|
bestdistribution = 9e30;
|
||||||
|
|
||||||
|
@ -172,6 +175,16 @@ ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs,
|
||||||
if (p->onnode)
|
if (p->onnode)
|
||||||
continue;
|
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];
|
plane = &planes[p->planenum];
|
||||||
k = 0;
|
k = 0;
|
||||||
|
|
||||||
|
@ -186,6 +199,9 @@ ChoosePlaneFromList (surface_t *surfaces, vec3_t mins, vec3_t maxs,
|
||||||
|
|
||||||
for (f = p2->faces; f; f = f->next) {
|
for (f = p2->faces; f; f = f->next) {
|
||||||
if (FaceSide (f, plane) == SIDE_ON) {
|
if (FaceSide (f, plane) == SIDE_ON) {
|
||||||
|
if (!ishint && f->texturenum == TEX_HINT)
|
||||||
|
k += 9999;
|
||||||
|
else
|
||||||
k++;
|
k++;
|
||||||
if (k >= bestvalue)
|
if (k >= bestvalue)
|
||||||
break;
|
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)
|
returns NULL if the surface list can not be divided any more (a leaf)
|
||||||
*/
|
*/
|
||||||
static surface_t *
|
static surface_t *
|
||||||
SelectPartition (surface_t *surfaces)
|
SelectPartition (surface_t *surfaces, int *detail)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
surface_t *p, *bestsurface;
|
surface_t *p, *bestsurface;
|
||||||
vec3_t mins, maxs;
|
vec3_t mins, maxs;
|
||||||
|
|
||||||
|
*detail = 0;
|
||||||
|
|
||||||
// count onnode surfaces
|
// count onnode surfaces
|
||||||
i = 0;
|
i = 0;
|
||||||
bestsurface = NULL;
|
bestsurface = NULL;
|
||||||
|
@ -257,8 +275,11 @@ SelectPartition (surface_t *surfaces)
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (i == 1)
|
if (i == 1) {
|
||||||
|
if (!bestsurface->has_struct && !usemidsplit)
|
||||||
|
*detail = 1;
|
||||||
return bestsurface; // this is a final split
|
return bestsurface; // this is a final split
|
||||||
|
}
|
||||||
|
|
||||||
// calculate a bounding box of the entire surfaceset
|
// calculate a bounding box of the entire surfaceset
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
|
@ -283,7 +304,11 @@ SelectPartition (surface_t *surfaces)
|
||||||
if (bestsurface)
|
if (bestsurface)
|
||||||
return bestsurface;
|
return bestsurface;
|
||||||
#endif
|
#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;
|
plane_t *inplane;
|
||||||
surface_t *news;
|
surface_t *news;
|
||||||
|
|
||||||
|
int have[2][2]; // [front|back][detail|struct]
|
||||||
|
|
||||||
inplane = &planes[in->planenum];
|
inplane = &planes[in->planenum];
|
||||||
|
|
||||||
// parallel case is easy
|
// parallel case is easy
|
||||||
|
@ -345,15 +372,26 @@ DividePlane (surface_t *in, plane_t *split, surface_t **front,
|
||||||
in->faces = NULL;
|
in->faces = NULL;
|
||||||
news->faces = NULL;
|
news->faces = NULL;
|
||||||
in->onnode = news->onnode = true;
|
in->onnode = news->onnode = true;
|
||||||
|
in->has_detail = in->has_struct = false;
|
||||||
|
|
||||||
for (; facet; facet = next) {
|
for (; facet; facet = next) {
|
||||||
next = facet->next;
|
next = facet->next;
|
||||||
if (facet->planeside == 1) {
|
if (facet->planeside == 1) {
|
||||||
facet->next = news->faces;
|
facet->next = news->faces;
|
||||||
news->faces = facet;
|
news->faces = facet;
|
||||||
|
|
||||||
|
if (facet->detail)
|
||||||
|
news->has_detail = true;
|
||||||
|
else
|
||||||
|
news->has_struct = true;
|
||||||
} else {
|
} else {
|
||||||
facet->next = in->faces;
|
facet->next = in->faces;
|
||||||
in->faces = facet;
|
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;
|
frontlist = NULL;
|
||||||
backlist = NULL;
|
backlist = NULL;
|
||||||
|
|
||||||
|
memset (have, 0, sizeof (have));
|
||||||
for (facet = in->faces; facet; facet = next) {
|
for (facet = in->faces; facet; facet = next) {
|
||||||
next = facet->next;
|
next = facet->next;
|
||||||
SplitFace (facet, split, &frontfrag, &backfrag);
|
SplitFace (facet, split, &frontfrag, &backfrag);
|
||||||
if (frontfrag) {
|
if (frontfrag) {
|
||||||
frontfrag->next = frontlist;
|
frontfrag->next = frontlist;
|
||||||
frontlist = frontfrag;
|
frontlist = frontfrag;
|
||||||
|
have[0][frontfrag->detail] = 1;
|
||||||
}
|
}
|
||||||
if (backfrag) {
|
if (backfrag) {
|
||||||
backfrag->next = backlist;
|
backfrag->next = backlist;
|
||||||
backlist = backfrag;
|
backlist = backfrag;
|
||||||
|
have[1][backfrag->detail] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,6 +459,12 @@ DividePlane (surface_t *in, plane_t *split, surface_t **front,
|
||||||
in->faces = frontlist;
|
in->faces = frontlist;
|
||||||
*front = in;
|
*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
|
// recalc bboxes and flags
|
||||||
CalcSurfaceInfo (news);
|
CalcSurfaceInfo (news);
|
||||||
CalcSurfaceInfo (in);
|
CalcSurfaceInfo (in);
|
||||||
|
@ -459,6 +506,8 @@ LinkConvexFaces (surface_t *planelist, node_t *leafnode)
|
||||||
count = 0;
|
count = 0;
|
||||||
for (surf = planelist; surf; surf = surf->next) {
|
for (surf = planelist; surf; surf = surf->next) {
|
||||||
for (f = surf->faces; f; f = f->next) {
|
for (f = surf->faces; f; f = f->next) {
|
||||||
|
if (f->texturenum < 0)
|
||||||
|
continue;
|
||||||
count++;
|
count++;
|
||||||
if (!leafnode->contents)
|
if (!leafnode->contents)
|
||||||
leafnode->contents = f->contents[0];
|
leafnode->contents = f->contents[0];
|
||||||
|
@ -495,8 +544,10 @@ LinkConvexFaces (surface_t *planelist, node_t *leafnode)
|
||||||
pnext = surf->next;
|
pnext = surf->next;
|
||||||
for (f = surf->faces; f; f = next) {
|
for (f = surf->faces; f; f = next) {
|
||||||
next = f->next;
|
next = f->next;
|
||||||
|
if (f->texturenum >= 0) {
|
||||||
leafnode->markfaces[i] = f->original;
|
leafnode->markfaces[i] = f->original;
|
||||||
i++;
|
i++;
|
||||||
|
}
|
||||||
FreeFace (f);
|
FreeFace (f);
|
||||||
}
|
}
|
||||||
FreeSurface (surf);
|
FreeSurface (surf);
|
||||||
|
@ -548,8 +599,9 @@ PartitionSurfaces (surface_t *surfaces, node_t *node)
|
||||||
surface_t *frontfrag, *backfrag;
|
surface_t *frontfrag, *backfrag;
|
||||||
plane_t *splitplane;
|
plane_t *splitplane;
|
||||||
|
|
||||||
split = SelectPartition (surfaces);
|
split = SelectPartition (surfaces, &node->detail);
|
||||||
if (!split) { // this is a leaf node
|
if (!split) { // this is a leaf node
|
||||||
|
node->detail = 0;
|
||||||
node->planenum = PLANENUM_LEAF;
|
node->planenum = PLANENUM_LEAF;
|
||||||
LinkConvexFaces (surfaces, node);
|
LinkConvexFaces (surfaces, node);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -365,6 +365,7 @@ MakeFaceEdges_r (node_t *node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (f = node->faces; f; f = f->next)
|
for (f = node->faces; f; f = f->next)
|
||||||
|
if (f->texturenum >= 0)
|
||||||
FindFaceEdges (f);
|
FindFaceEdges (f);
|
||||||
|
|
||||||
MakeFaceEdges_r (node->children[0]);
|
MakeFaceEdges_r (node->children[0]);
|
||||||
|
|
|
@ -387,6 +387,7 @@ tjunc_find_r (node_t *node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (f = node->faces; f; f = f->next)
|
for (f = node->faces; f; f = f->next)
|
||||||
|
if (f->texturenum >= 0)
|
||||||
AddFaceEdges (f);
|
AddFaceEdges (f);
|
||||||
|
|
||||||
tjunc_find_r (node->children[0]);
|
tjunc_find_r (node->children[0]);
|
||||||
|
@ -405,6 +406,8 @@ tjunc_fix_r (node_t *node)
|
||||||
|
|
||||||
for (f = node->faces; f; f = next) {
|
for (f = node->faces; f; f = next) {
|
||||||
next = f->next;
|
next = f->next;
|
||||||
|
if (f->texturenum < 0)
|
||||||
|
continue;
|
||||||
FixFaceEdges (f);
|
FixFaceEdges (f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,8 @@ WriteLeaf (node_t *node)
|
||||||
if (bsp->nummarksurfaces == MAX_MAP_MARKSURFACES)
|
if (bsp->nummarksurfaces == MAX_MAP_MARKSURFACES)
|
||||||
Sys_Error ("nummarksurfaces == MAX_MAP_MARKSURFACES");
|
Sys_Error ("nummarksurfaces == MAX_MAP_MARKSURFACES");
|
||||||
f = *fp;
|
f = *fp;
|
||||||
|
if (f->texturenum < 0)
|
||||||
|
continue;
|
||||||
do {
|
do {
|
||||||
BSP_AddMarkSurface (bsp, f->outputnumber);
|
BSP_AddMarkSurface (bsp, f->outputnumber);
|
||||||
f = f->original; // grab tjunction split faces
|
f = f->original; // grab tjunction split faces
|
||||||
|
|
|
@ -45,10 +45,10 @@ extern pthread_mutex_t *my_mutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_PORTALS 32768
|
#define MAX_PORTALS 32768
|
||||||
#define PORTALFILE "PRT1"
|
#define PORTALFILE "PRT1-AM"
|
||||||
#define ON_EPSILON 0.1
|
#define ON_EPSILON 0.1
|
||||||
#define MAX_POINTS_ON_WINDING 64
|
#define MAX_POINTS_ON_WINDING 64
|
||||||
#define MAX_PORTALS_ON_LEAF 128
|
#define MAX_PORTALS_ON_CLUSTER 128
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vec3_t normal;
|
vec3_t normal;
|
||||||
|
@ -70,7 +70,7 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
plane_t plane; // normal pointing into neighbor
|
plane_t plane; // normal pointing into neighbor
|
||||||
int leaf; // neighbor
|
int cluster; // neighbor
|
||||||
winding_t *winding;
|
winding_t *winding;
|
||||||
vstatus_t status;
|
vstatus_t status;
|
||||||
byte *visbits;
|
byte *visbits;
|
||||||
|
@ -86,19 +86,20 @@ typedef struct seperating_plane_s {
|
||||||
|
|
||||||
typedef struct passage_s {
|
typedef struct passage_s {
|
||||||
struct passage_s *next;
|
struct passage_s *next;
|
||||||
int from, to; // leaf numbers
|
int from, to; // cluster numbers
|
||||||
sep_t *planes;
|
sep_t *planes;
|
||||||
} passage_t;
|
} passage_t;
|
||||||
|
|
||||||
typedef struct leaf_s {
|
typedef struct cluster_s {
|
||||||
int numportals;
|
int numportals;
|
||||||
passage_t *passages;
|
passage_t *passages;
|
||||||
portal_t *portals[MAX_PORTALS_ON_LEAF];
|
portal_t *portals[MAX_PORTALS_ON_CLUSTER];
|
||||||
} leaf_t;
|
int visofs;
|
||||||
|
} cluster_t;
|
||||||
|
|
||||||
typedef struct pstack_s {
|
typedef struct pstack_s {
|
||||||
struct pstack_s *next;
|
struct pstack_s *next;
|
||||||
leaf_t *leaf;
|
cluster_t *cluster;
|
||||||
portal_t *portal; // portal exiting
|
portal_t *portal; // portal exiting
|
||||||
winding_t *source, *pass;
|
winding_t *source, *pass;
|
||||||
plane_t portalplane;
|
plane_t portalplane;
|
||||||
|
@ -106,22 +107,25 @@ typedef struct pstack_s {
|
||||||
} pstack_t;
|
} pstack_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte *leafvis; // bit string
|
byte *clustervis; // bit string
|
||||||
portal_t *base;
|
portal_t *base;
|
||||||
pstack_t pstack_head;
|
pstack_t pstack_head;
|
||||||
} threaddata_t;
|
} threaddata_t;
|
||||||
|
|
||||||
extern int numportals;
|
extern int numportals;
|
||||||
extern int portalleafs;
|
extern int portalclusters;
|
||||||
|
extern int numrealleafs;
|
||||||
extern int c_portaltest;
|
extern int c_portaltest;
|
||||||
extern int c_portalpass;
|
extern int c_portalpass;
|
||||||
extern int c_portalcheck;
|
extern int c_portalcheck;
|
||||||
extern int bitbytes;
|
extern int bitbytes;
|
||||||
|
extern int bitbytes_l;
|
||||||
extern int bitlongs;
|
extern int bitlongs;
|
||||||
extern struct bsp_s *bsp;
|
extern struct bsp_s *bsp;
|
||||||
|
|
||||||
extern portal_t *portals;
|
extern portal_t *portals;
|
||||||
extern leaf_t *leafs;
|
extern cluster_t *clusters;
|
||||||
|
extern int *leafcluster;
|
||||||
extern byte *uncompressed;
|
extern byte *uncompressed;
|
||||||
|
|
||||||
extern int c_chains;
|
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 *ClipWinding (winding_t *in, plane_t *split, qboolean keepon);
|
||||||
winding_t *CopyWinding (winding_t *winding);
|
winding_t *CopyWinding (winding_t *winding);
|
||||||
|
|
||||||
void LeafFlow (int leafnum);
|
void ClusterFlow (int clusternum);
|
||||||
void BasePortalVis (void);
|
void BasePortalVis (void);
|
||||||
void PortalFlow (portal_t *portal);
|
void PortalFlow (portal_t *portal);
|
||||||
void CalcAmbientSounds (void);
|
void CalcAmbientSounds (void);
|
||||||
|
|
|
@ -60,7 +60,7 @@ static __attribute__ ((unused)) const char rcsid[] =
|
||||||
#include "vis.h"
|
#include "vis.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
static int leafsee;
|
static int clustersee;
|
||||||
static byte portalsee[MAX_PORTALS];
|
static byte portalsee[MAX_PORTALS];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -68,24 +68,24 @@ static byte portalsee[MAX_PORTALS];
|
||||||
some of the final calculations.
|
some of the final calculations.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
SimpleFlood (portal_t *srcportal, int leafnum)
|
SimpleFlood (portal_t *srcportal, int clusternum)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
leaf_t *leaf;
|
cluster_t *cluster;
|
||||||
portal_t *portal;
|
portal_t *portal;
|
||||||
|
|
||||||
if (srcportal->mightsee[leafnum >> 3] & (1 << (leafnum & 7)))
|
if (srcportal->mightsee[clusternum >> 3] & (1 << (clusternum & 7)))
|
||||||
return;
|
return;
|
||||||
srcportal->mightsee[leafnum >> 3] |= (1 << (leafnum & 7));
|
srcportal->mightsee[clusternum >> 3] |= (1 << (clusternum & 7));
|
||||||
leafsee++;
|
clustersee++;
|
||||||
|
|
||||||
leaf = &leafs[leafnum];
|
cluster = &clusters[clusternum];
|
||||||
|
|
||||||
for (i = 0; i < leaf->numportals; i++) {
|
for (i = 0; i < cluster->numportals; i++) {
|
||||||
portal = leaf->portals[i];
|
portal = cluster->portals[i];
|
||||||
if (!portalsee[portal - portals])
|
if (!portalsee[portal - portals])
|
||||||
continue;
|
continue;
|
||||||
SimpleFlood (srcportal, portal->leaf);
|
SimpleFlood (srcportal, portal->cluster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,8 +129,8 @@ BasePortalVis (void)
|
||||||
portalsee[j] = 1;
|
portalsee[j] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
leafsee = 0;
|
clustersee = 0;
|
||||||
SimpleFlood (portal, portal->leaf);
|
SimpleFlood (portal, portal->cluster);
|
||||||
portal->nummightsee = leafsee;
|
portal->nummightsee = clustersee;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,13 +61,13 @@ static __attribute__ ((unused)) const char rcsid[] =
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CheckStack (leaf_t *leaf, threaddata_t *thread)
|
CheckStack (cluster_t *cluster, threaddata_t *thread)
|
||||||
{
|
{
|
||||||
pstack_t *portal;
|
pstack_t *portal;
|
||||||
|
|
||||||
for (portal = thread->pstack_head.next; portal; portal = portal->next)
|
for (portal = thread->pstack_head.next; portal; portal = portal->next)
|
||||||
if (portal->leaf == leaf)
|
if (portal->cluster == cluster)
|
||||||
Sys_Error ("CheckStack: leaf recursion");
|
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
|
Flood fill through the clusters
|
||||||
If src_portal is NULL, this is the originating leaf
|
If src_portal is NULL, this is the originating cluster
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
|
RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
leaf_t *leaf;
|
cluster_t *cluster;
|
||||||
long *test, *might, *vis;
|
long *test, *might, *vis;
|
||||||
qboolean more;
|
qboolean more;
|
||||||
pstack_t stack;
|
pstack_t stack;
|
||||||
|
@ -207,29 +207,29 @@ RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
|
||||||
|
|
||||||
c_chains++;
|
c_chains++;
|
||||||
|
|
||||||
leaf = &leafs[leafnum];
|
cluster = &clusters[clusternum];
|
||||||
CheckStack(leaf, thread);
|
CheckStack(cluster, thread);
|
||||||
|
|
||||||
// mark the leaf as visible
|
// mark the cluster as visible
|
||||||
if (!(thread->leafvis[leafnum >> 3] & (1 << (leafnum & 7)))) {
|
if (!(thread->clustervis[clusternum >> 3] & (1 << (clusternum & 7)))) {
|
||||||
thread->leafvis[leafnum >> 3] |= 1 << (leafnum & 7);
|
thread->clustervis[clusternum >> 3] |= 1 << (clusternum & 7);
|
||||||
thread->base->numcansee++;
|
thread->base->numcansee++;
|
||||||
}
|
}
|
||||||
|
|
||||||
prevstack->next = &stack;
|
prevstack->next = &stack;
|
||||||
stack.next = NULL;
|
stack.next = NULL;
|
||||||
stack.leaf = leaf;
|
stack.cluster = cluster;
|
||||||
stack.portal = NULL;
|
stack.portal = NULL;
|
||||||
stack.mightsee = malloc(bitbytes);
|
stack.mightsee = malloc(bitbytes);
|
||||||
might = (long *) stack.mightsee;
|
might = (long *) stack.mightsee;
|
||||||
vis = (long *) thread->leafvis;
|
vis = (long *) thread->clustervis;
|
||||||
|
|
||||||
// check all portals for flowing into other leafs
|
// check all portals for flowing into other clusters
|
||||||
for (i = 0; i < leaf->numportals; i++) {
|
for (i = 0; i < cluster->numportals; i++) {
|
||||||
portal = leaf->portals[i];
|
portal = cluster->portals[i];
|
||||||
|
|
||||||
if (!(prevstack->mightsee[portal->leaf >> 3]
|
if (!(prevstack->mightsee[portal->cluster >> 3]
|
||||||
& (1 << (portal->leaf & 7))))
|
& (1 << (portal->cluster & 7))))
|
||||||
continue; // can't possibly see it
|
continue; // can't possibly see it
|
||||||
// if the portal can't see anything we haven't already seen, skip it
|
// if the portal can't see anything we haven't already seen, skip it
|
||||||
if (portal->status == stat_done) {
|
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
|
if (!more) // can't see anything new
|
||||||
continue;
|
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;
|
stack.portalplane = portal->plane;
|
||||||
VectorSubtract (vec3_origin, portal->plane.normal, backplane.normal);
|
VectorSubtract (vec3_origin, portal->plane.normal, backplane.normal);
|
||||||
backplane.dist = -portal->plane.dist;
|
backplane.dist = -portal->plane.dist;
|
||||||
|
@ -268,11 +268,11 @@ RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!prevstack->pass) {
|
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.source = prevstack->source;
|
||||||
stack.pass = target;
|
stack.pass = target;
|
||||||
RecursiveLeafFlow (portal->leaf, thread, &stack);
|
RecursiveClusterFlow (portal->cluster, thread, &stack);
|
||||||
FreeWinding (target);
|
FreeWinding (target);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -340,7 +340,7 @@ RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
|
||||||
c_portalpass++;
|
c_portalpass++;
|
||||||
|
|
||||||
// flow through it for real
|
// flow through it for real
|
||||||
RecursiveLeafFlow (portal->leaf, thread, &stack);
|
RecursiveClusterFlow (portal->cluster, thread, &stack);
|
||||||
|
|
||||||
FreeWinding (source);
|
FreeWinding (source);
|
||||||
FreeWinding (target);
|
FreeWinding (target);
|
||||||
|
@ -363,7 +363,7 @@ PortalFlow (portal_t *portal)
|
||||||
portal->visbits = calloc (1, bitbytes);
|
portal->visbits = calloc (1, bitbytes);
|
||||||
|
|
||||||
memset (&data, 0, sizeof (data));
|
memset (&data, 0, sizeof (data));
|
||||||
data.leafvis = portal->visbits;
|
data.clustervis = portal->visbits;
|
||||||
data.base = portal;
|
data.base = portal;
|
||||||
|
|
||||||
data.pstack_head.portal = portal;
|
data.pstack_head.portal = portal;
|
||||||
|
@ -371,7 +371,7 @@ PortalFlow (portal_t *portal)
|
||||||
data.pstack_head.portalplane = portal->plane;
|
data.pstack_head.portalplane = portal->plane;
|
||||||
data.pstack_head.mightsee = portal->mightsee;
|
data.pstack_head.mightsee = portal->mightsee;
|
||||||
|
|
||||||
RecursiveLeafFlow (portal->leaf, &data, &data.pstack_head);
|
RecursiveClusterFlow (portal->cluster, &data, &data.pstack_head);
|
||||||
|
|
||||||
portal->status = stat_done;
|
portal->status = stat_done;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,17 +80,20 @@ int c_portalcheck;
|
||||||
int c_vistest;
|
int c_vistest;
|
||||||
|
|
||||||
int numportals;
|
int numportals;
|
||||||
int portalleafs;
|
int portalclusters;
|
||||||
|
int numrealleafs;
|
||||||
int originalvismapsize;
|
int originalvismapsize;
|
||||||
int totalvis;
|
int totalvis;
|
||||||
int count_sep;
|
int count_sep;
|
||||||
int bitbytes; // (portalleafs + 63)>>3
|
int bitbytes; // (portalleafs + 63)>>3
|
||||||
int bitlongs;
|
int bitlongs;
|
||||||
|
int bitbytes_l; // (numrealleafs + 63)>>3
|
||||||
|
|
||||||
portal_t *portals;
|
portal_t *portals;
|
||||||
leaf_t *leafs;
|
cluster_t *clusters;
|
||||||
dstring_t *visdata;
|
dstring_t *visdata;
|
||||||
byte *uncompressed; // [bitbytes * portalleafs]
|
byte *uncompressed; // [bitbytes * portalleafs]
|
||||||
|
int *leafcluster; // leaf to cluster mappings as read from .prt file
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -305,7 +308,7 @@ CompressRow (byte *vis, byte *dest)
|
||||||
byte *dest_p;
|
byte *dest_p;
|
||||||
|
|
||||||
dest_p = dest;
|
dest_p = dest;
|
||||||
visrow = (portalleafs + 7) >> 3;
|
visrow = (numrealleafs + 7) >> 3;
|
||||||
|
|
||||||
for (j = 0; j < visrow; j++) {
|
for (j = 0; j < visrow; j++) {
|
||||||
*dest_p++ = vis[j];
|
*dest_p++ = vis[j];
|
||||||
|
@ -325,49 +328,70 @@ CompressRow (byte *vis, byte *dest)
|
||||||
return dest_p - dest;
|
return dest_p - dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void
|
||||||
LeafFlow
|
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
|
void
|
||||||
LeafFlow (int leafnum)
|
ClusterFlow (int clusternum)
|
||||||
{
|
{
|
||||||
byte *outbuffer;
|
byte *outbuffer;
|
||||||
byte compressed[MAX_MAP_LEAFS / 8];
|
byte compressed[MAX_MAP_LEAFS / 8];
|
||||||
int numvis, i, j;
|
int numvis, i, j;
|
||||||
leaf_t *leaf;
|
cluster_t *cluster;
|
||||||
portal_t *portal;
|
portal_t *portal;
|
||||||
|
|
||||||
|
outbuffer = uncompressed + clusternum * bitbytes_l;
|
||||||
|
cluster = &clusters[clusternum];
|
||||||
|
|
||||||
// flow through all portals, collecting visible bits
|
// flow through all portals, collecting visible bits
|
||||||
outbuffer = uncompressed + leafnum * bitbytes;
|
|
||||||
leaf = &leafs[leafnum];
|
memset (compressed, 0, sizeof (compressed));
|
||||||
for (i = 0; i < leaf->numportals; i++) {
|
for (i = 0; i < cluster->numportals; i++) {
|
||||||
portal = leaf->portals[i];
|
portal = cluster->portals[i];
|
||||||
if (portal->status != stat_done)
|
if (portal->status != stat_done)
|
||||||
Sys_Error ("portal not done");
|
Sys_Error ("portal not done");
|
||||||
for (j = 0; j < bitbytes; j++)
|
for (j = 0; j < bitbytes; j++)
|
||||||
outbuffer[j] |= portal->visbits[j];
|
compressed[j] |= portal->visbits[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outbuffer[leafnum >> 3] & (1 << (leafnum & 7)))
|
if (compressed[clusternum >> 3] & (1 << (clusternum & 7)))
|
||||||
Sys_Error ("Leaf portals saw into leaf");
|
Sys_Error ("Cluster portals saw into cluster");
|
||||||
|
|
||||||
outbuffer[leafnum >> 3] |= (1 << (leafnum & 7));
|
compressed[clusternum >> 3] |= (1 << (clusternum & 7));
|
||||||
|
|
||||||
numvis = 0;
|
numvis = 0;
|
||||||
for (i = 0; i < portalleafs; i++)
|
for (i = 0; i < portalclusters; i++)
|
||||||
if (outbuffer[i >> 3] & (1 << (i & 3)))
|
if (compressed[i >> 3] & (1 << (i & 3)))
|
||||||
numvis++;
|
numvis++;
|
||||||
|
|
||||||
|
// expand to cluster->leaf PVS
|
||||||
|
ClusterFlowExpand (compressed, outbuffer);
|
||||||
|
|
||||||
// compress the bit string
|
// compress the bit string
|
||||||
if (options.verbosity > 0)
|
if (options.verbosity > 0)
|
||||||
printf ("leaf %4i : %4i visible\n", leafnum, numvis);
|
printf ("cluster %4i : %4i visible\n", clusternum, numvis);
|
||||||
totalvis += numvis;
|
totalvis += numvis;
|
||||||
|
|
||||||
i = CompressRow (outbuffer, compressed);
|
i = CompressRow (outbuffer, compressed);
|
||||||
|
cluster->visofs = visdata->size;
|
||||||
bsp->leafs[leafnum + 1].visofs = visdata->size;
|
|
||||||
dstring_append (visdata, compressed, i);
|
dstring_append (visdata, compressed, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,11 +460,14 @@ CalcVis (void)
|
||||||
CalcPortalVis ();
|
CalcPortalVis ();
|
||||||
|
|
||||||
// assemble the leaf vis lists by oring and compressing the portal lists
|
// assemble the leaf vis lists by oring and compressing the portal lists
|
||||||
for (i = 0; i < portalleafs; i++)
|
for (i = 0; i < portalclusters; i++)
|
||||||
LeafFlow (i);
|
ClusterFlow (i);
|
||||||
|
|
||||||
|
for (i = 0; i < numrealleafs; i++) {
|
||||||
|
bsp->leafs[i].visofs = clusters[leafcluster[i]].visofs;
|
||||||
|
}
|
||||||
if (options.verbosity >= 0)
|
if (options.verbosity >= 0)
|
||||||
printf ("average leafs visible: %i\n", totalvis / portalleafs);
|
printf ("average clusters visible: %i\n", totalvis / portalclusters);
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
static qboolean
|
static qboolean
|
||||||
|
@ -622,9 +649,9 @@ LoadPortals (char *name)
|
||||||
{
|
{
|
||||||
char magic[80];
|
char magic[80];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int leafnums[2];
|
int clusternums[2];
|
||||||
int numpoints, i, j;
|
int numpoints, i, j;
|
||||||
leaf_t *leaf;
|
cluster_t *cluster;
|
||||||
plane_t plane;
|
plane_t plane;
|
||||||
portal_t *portal;
|
portal_t *portal;
|
||||||
winding_t *winding;
|
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");
|
Sys_Error ("LoadPortals: failed to read header");
|
||||||
if (strcmp (magic, PORTALFILE))
|
if (strcmp (magic, PORTALFILE))
|
||||||
Sys_Error ("LoadPortals: not a portal file");
|
Sys_Error ("LoadPortals: not a portal file");
|
||||||
|
|
||||||
if (options.verbosity >= 0) {
|
if (options.verbosity >= 0) {
|
||||||
printf ("%4i portalleafs\n", portalleafs);
|
printf ("%4i portalclusters\n", portalclusters);
|
||||||
printf ("%4i numportals\n", numportals);
|
printf ("%4i numportals\n", numportals);
|
||||||
|
printf ("%4i numrealleafs\n", numrealleafs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bitbytes = ((portalleafs + 63) & ~63) >> 3;
|
bitbytes = ((portalclusters + 63) & ~63) >> 3;
|
||||||
bitlongs = bitbytes / sizeof (long);
|
bitlongs = bitbytes / sizeof (long);
|
||||||
|
|
||||||
|
bitbytes_l = ((numrealleafs + 63) & ~63) >> 3;
|
||||||
|
|
||||||
// each file portal is split into two memory portals, one for each
|
// each file portal is split into two memory portals, one for each
|
||||||
// direction
|
// direction
|
||||||
portals = calloc (2 * numportals, sizeof (portal_t));
|
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++) {
|
for (i = 0, portal = portals; i < numportals; i++) {
|
||||||
if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0],
|
if (fscanf (f, "%i %i %i ", &numpoints, &clusternums[0],
|
||||||
&leafnums[1]) != 3)
|
&clusternums[1]) != 3)
|
||||||
Sys_Error ("LoadPortals: reading portal %i", i);
|
Sys_Error ("LoadPortals: reading portal %i", i);
|
||||||
if (numpoints > MAX_POINTS_ON_WINDING)
|
if (numpoints > MAX_POINTS_ON_WINDING)
|
||||||
Sys_Error ("LoadPortals: portal %i has too many points", i);
|
Sys_Error ("LoadPortals: portal %i has too many points", i);
|
||||||
if ((unsigned) leafnums[0] > portalleafs
|
if ((unsigned) clusternums[0] > portalclusters
|
||||||
|| (unsigned) leafnums[1] > portalleafs)
|
|| (unsigned) clusternums[1] > portalclusters)
|
||||||
Sys_Error ("LoadPortals: reading portal %i", i);
|
Sys_Error ("LoadPortals: reading portal %i", i);
|
||||||
|
|
||||||
winding = portal->winding = NewWinding (numpoints);
|
winding = portal->winding = NewWinding (numpoints);
|
||||||
|
@ -693,30 +724,35 @@ LoadPortals (char *name)
|
||||||
PlaneFromWinding (winding, &plane);
|
PlaneFromWinding (winding, &plane);
|
||||||
|
|
||||||
// create forward portal
|
// create forward portal
|
||||||
leaf = &leafs[leafnums[0]];
|
cluster = &clusters[clusternums[0]];
|
||||||
if (leaf->numportals == MAX_PORTALS_ON_LEAF)
|
if (cluster->numportals == MAX_PORTALS_ON_CLUSTER)
|
||||||
Sys_Error ("Leaf with too many portals");
|
Sys_Error ("Cluster with too many portals");
|
||||||
leaf->portals[leaf->numportals] = portal;
|
cluster->portals[cluster->numportals] = portal;
|
||||||
leaf->numportals++;
|
cluster->numportals++;
|
||||||
|
|
||||||
portal->winding = winding;
|
portal->winding = winding;
|
||||||
VectorSubtract (vec3_origin, plane.normal, portal->plane.normal);
|
VectorSubtract (vec3_origin, plane.normal, portal->plane.normal);
|
||||||
portal->plane.dist = -plane.dist;
|
portal->plane.dist = -plane.dist;
|
||||||
portal->leaf = leafnums[1];
|
portal->cluster = clusternums[1];
|
||||||
portal++;
|
portal++;
|
||||||
|
|
||||||
// create backwards portal
|
// create backwards portal
|
||||||
leaf = &leafs[leafnums[1]];
|
cluster = &clusters[clusternums[1]];
|
||||||
if (leaf->numportals == MAX_PORTALS_ON_LEAF)
|
if (cluster->numportals == MAX_PORTALS_ON_CLUSTER)
|
||||||
Sys_Error ("Leaf with too many portals");
|
Sys_Error ("Cluster with too many portals");
|
||||||
leaf->portals[leaf->numportals] = portal;
|
cluster->portals[cluster->numportals] = portal;
|
||||||
leaf->numportals++;
|
cluster->numportals++;
|
||||||
|
|
||||||
portal->winding = winding;
|
portal->winding = winding;
|
||||||
portal->plane = plane;
|
portal->plane = plane;
|
||||||
portal->leaf = leafnums[0];
|
portal->cluster = clusternums[0];
|
||||||
portal++;
|
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);
|
fclose (f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,7 +789,7 @@ main (int argc, char **argv)
|
||||||
dstring_appendstr (portalfile, ".prt");
|
dstring_appendstr (portalfile, ".prt");
|
||||||
LoadPortals (portalfile->str);
|
LoadPortals (portalfile->str);
|
||||||
|
|
||||||
uncompressed = calloc (bitbytes, portalleafs);
|
uncompressed = calloc (bitbytes_l, portalclusters);
|
||||||
|
|
||||||
CalcVis ();
|
CalcVis ();
|
||||||
|
|
||||||
|
|
|
@ -106,16 +106,16 @@ CalcAmbientSounds (void)
|
||||||
texinfo_t *info;
|
texinfo_t *info;
|
||||||
miptex_t *miptex;
|
miptex_t *miptex;
|
||||||
|
|
||||||
for (i = 0; i < portalleafs; i++) {
|
for (i = 0; i < numrealleafs - 1; i++) {
|
||||||
leaf = &bsp->leafs[i + 1];
|
leaf = &bsp->leafs[i + 1];
|
||||||
|
|
||||||
// clear ambients
|
// clear ambients
|
||||||
for (j = 0; j < NUM_AMBIENTS; j++)
|
for (j = 0; j < NUM_AMBIENTS; j++)
|
||||||
dists[j] = 1020;
|
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))))
|
if (!(vis[j >> 3] & (1 << (j & 7))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue