mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
[qfvis] Remove the cluster portals limit
This removes the last of the arbitrary limits from qfvis. The goal is not so much supporting crazy maps, but more about better data usage (cluster_t is now 24 (or 16) bytes instead of 1048 (or 528). And passages isn't used (yet?)...
This commit is contained in:
parent
fe98a513bc
commit
9461779ba7
4 changed files with 98 additions and 72 deletions
|
@ -79,13 +79,10 @@ extern pthread_rwlock_t *stats_lock;
|
||||||
#include "QF/zone.h"
|
#include "QF/zone.h"
|
||||||
#include "QF/simd/vec4f.h"
|
#include "QF/simd/vec4f.h"
|
||||||
|
|
||||||
#define MAX_PORTALS 32768
|
|
||||||
#define PORTALFILE "PRT1"
|
#define PORTALFILE "PRT1"
|
||||||
#define PORTALFILE_AM "PRT1-AM"
|
#define PORTALFILE_AM "PRT1-AM"
|
||||||
#define PORTALFILE2 "PRT2"
|
#define PORTALFILE2 "PRT2"
|
||||||
#define ON_EPSILON 0.1
|
#define ON_EPSILON 0.1
|
||||||
#define MAX_POINTS_ON_WINDING 64
|
|
||||||
#define MAX_PORTALS_ON_CLUSTER 128
|
|
||||||
|
|
||||||
typedef struct winding_s {
|
typedef struct winding_s {
|
||||||
struct winding_s *next;
|
struct winding_s *next;
|
||||||
|
@ -130,7 +127,7 @@ typedef struct cluster_s {
|
||||||
int numportals;
|
int numportals;
|
||||||
int visofs;
|
int visofs;
|
||||||
passage_t *passages;
|
passage_t *passages;
|
||||||
portal_t *portals[MAX_PORTALS_ON_CLUSTER];
|
portal_t *portals;
|
||||||
} cluster_t;
|
} cluster_t;
|
||||||
|
|
||||||
typedef struct pstack_s {
|
typedef struct pstack_s {
|
||||||
|
|
|
@ -76,7 +76,7 @@ SimpleFlood (basethread_t *thread, portal_t *srcportal, int clusternum)
|
||||||
cluster = &clusters[clusternum];
|
cluster = &clusters[clusternum];
|
||||||
|
|
||||||
for (i = 0; i < cluster->numportals; i++) {
|
for (i = 0; i < cluster->numportals; i++) {
|
||||||
portal = cluster->portals[i];
|
portal = &cluster->portals[i];
|
||||||
if (!set_is_member (thread->portalsee, portal - portals))
|
if (!set_is_member (thread->portalsee, portal - portals))
|
||||||
continue;
|
continue;
|
||||||
SimpleFlood (thread, srcportal, portal->cluster);
|
SimpleFlood (thread, srcportal, portal->cluster);
|
||||||
|
|
|
@ -349,7 +349,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
|
||||||
|
|
||||||
// check all portals for flowing into other clusters
|
// check all portals for flowing into other clusters
|
||||||
for (i = 0; i < cluster->numportals; i++) {
|
for (i = 0; i < cluster->numportals; i++) {
|
||||||
target_portal = cluster->portals[i];
|
target_portal = &cluster->portals[i];
|
||||||
if (!set_is_member (prevstack->mightsee, target_portal->cluster))
|
if (!set_is_member (prevstack->mightsee, target_portal->cluster))
|
||||||
continue; // can't possibly see it
|
continue; // can't possibly see it
|
||||||
|
|
||||||
|
|
|
@ -408,7 +408,7 @@ UpdateMightsee (threaddata_t *thread, cluster_t *source, cluster_t *dest)
|
||||||
|
|
||||||
clusternum = dest - clusters;
|
clusternum = dest - clusters;
|
||||||
for (i = 0; i < source->numportals; i++) {
|
for (i = 0; i < source->numportals; i++) {
|
||||||
portal = source->portals[i];
|
portal = &source->portals[i];
|
||||||
WRLOCK_PORTAL (portal);
|
WRLOCK_PORTAL (portal);
|
||||||
if (portal->status == stat_none) {
|
if (portal->status == stat_none) {
|
||||||
if (set_is_member (portal->mightsee, clusternum)) {
|
if (set_is_member (portal->mightsee, clusternum)) {
|
||||||
|
@ -462,7 +462,7 @@ PortalCompleted (threaddata_t *thread, portal_t *completed)
|
||||||
changed = set_new_size_r (&thread->set_pool, portalclusters);
|
changed = set_new_size_r (&thread->set_pool, portalclusters);
|
||||||
cluster = &clusters[completed->cluster];
|
cluster = &clusters[completed->cluster];
|
||||||
for (i = 0; i < cluster->numportals; i++) {
|
for (i = 0; i < cluster->numportals; i++) {
|
||||||
portal = cluster->portals[i];
|
portal = &cluster->portals[i];
|
||||||
if (portal->status != stat_done)
|
if (portal->status != stat_done)
|
||||||
continue;
|
continue;
|
||||||
set_assign (changed, portal->mightsee);
|
set_assign (changed, portal->mightsee);
|
||||||
|
@ -480,10 +480,10 @@ PortalCompleted (threaddata_t *thread, portal_t *completed)
|
||||||
for (j = 0; j < cluster->numportals; j++) {
|
for (j = 0; j < cluster->numportals; j++) {
|
||||||
if (j == i)
|
if (j == i)
|
||||||
continue;
|
continue;
|
||||||
if (cluster->portals[j]->status == stat_done)
|
if (cluster->portals[j].status == stat_done)
|
||||||
set_difference (changed, cluster->portals[j]->visbits);
|
set_difference (changed, cluster->portals[j].visbits);
|
||||||
else
|
else
|
||||||
set_difference (changed, cluster->portals[j]->mightsee);
|
set_difference (changed, cluster->portals[j].mightsee);
|
||||||
}
|
}
|
||||||
for (ci = set_first_r (&thread->set_pool, changed); ci;
|
for (ci = set_first_r (&thread->set_pool, changed); ci;
|
||||||
ci = set_next_r (&thread->set_pool, ci)) {
|
ci = set_next_r (&thread->set_pool, ci)) {
|
||||||
|
@ -845,7 +845,7 @@ ClusterFlow (int clusternum)
|
||||||
memset (compressed.data, 0, compressed.maxsize);
|
memset (compressed.data, 0, compressed.maxsize);
|
||||||
visclusters = set_new ();
|
visclusters = set_new ();
|
||||||
for (i = 0; i < cluster->numportals; i++) {
|
for (i = 0; i < cluster->numportals; i++) {
|
||||||
portal = cluster->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");
|
||||||
set_union (visclusters, portal->visbits);
|
set_union (visclusters, portal->visbits);
|
||||||
|
@ -1153,20 +1153,58 @@ CalcPassages (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static winding_t *
|
||||||
|
parse_winding (const char *line, int numpoints)
|
||||||
|
{
|
||||||
|
winding_t *winding = NewWinding (&main_thread, numpoints);
|
||||||
|
|
||||||
|
winding->original = true;
|
||||||
|
winding->numpoints = numpoints;
|
||||||
|
|
||||||
|
for (int i = 0; i < numpoints; i++) {
|
||||||
|
// (%ld %ld %ld)
|
||||||
|
while (isspace ((byte) *line))
|
||||||
|
line++;
|
||||||
|
if (*line++ != '(') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
char *err;
|
||||||
|
|
||||||
|
winding->points[i][j] = strtod (line, &err);
|
||||||
|
if (err == line) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
line = err;
|
||||||
|
}
|
||||||
|
winding->points[i][3] = 1;
|
||||||
|
|
||||||
|
while (isspace ((byte) *line))
|
||||||
|
line++;
|
||||||
|
if (*line++ != ')') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return winding;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
LoadPortals (char *name)
|
LoadPortals (char *name)
|
||||||
{
|
{
|
||||||
|
typedef struct {
|
||||||
|
unsigned clusters[2];
|
||||||
|
} clusterpair_t;
|
||||||
|
|
||||||
const char *line;
|
const char *line;
|
||||||
char *err;
|
char *err;
|
||||||
unsigned numpoints, i, j, k;
|
unsigned numpoints;
|
||||||
int read_leafs = 0;
|
int read_leafs = 0;
|
||||||
int clusternums[2];
|
|
||||||
cluster_t *cluster;
|
|
||||||
vec4f_t plane;
|
vec4f_t plane;
|
||||||
portal_t *portal;
|
|
||||||
winding_t *winding;
|
|
||||||
vspheref_t sphere;
|
vspheref_t sphere;
|
||||||
QFile *f;
|
QFile *f;
|
||||||
|
clusterpair_t *clusternums;
|
||||||
|
|
||||||
if (!strcmp (name, "-"))
|
if (!strcmp (name, "-"))
|
||||||
f = Qdopen (0, "rt"); // create a QFile of stdin
|
f = Qdopen (0, "rt"); // create a QFile of stdin
|
||||||
|
@ -1233,22 +1271,24 @@ LoadPortals (char *name)
|
||||||
// direction
|
// direction
|
||||||
portals = calloc (2 * numportals, sizeof (portal_t));
|
portals = calloc (2 * numportals, sizeof (portal_t));
|
||||||
portal_queue = malloc (2 * numportals * sizeof (portal_t *));
|
portal_queue = malloc (2 * numportals * sizeof (portal_t *));
|
||||||
for (i = 0; i < 2 * numportals; i++) {
|
for (unsigned i = 0; i < 2 * numportals; i++) {
|
||||||
portal_queue[i] = &portals[i];
|
portal_queue[i] = &portals[i];
|
||||||
}
|
}
|
||||||
#ifdef USE_PTHREADS
|
#ifdef USE_PTHREADS
|
||||||
portal_locks = calloc (2 * numportals, sizeof (pthread_rwlock_t));
|
portal_locks = calloc (2 * numportals, sizeof (pthread_rwlock_t));
|
||||||
for (i = 0; i < 2 * numportals; i++) {
|
for (unsigned i = 0; i < 2 * numportals; i++) {
|
||||||
if (pthread_rwlock_init (&portal_locks[i], 0))
|
if (pthread_rwlock_init (&portal_locks[i], 0))
|
||||||
Sys_Error ("pthread_rwlock_init failed");
|
Sys_Error ("pthread_rwlock_init failed");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
clusters = calloc (portalclusters, sizeof (cluster_t));
|
|
||||||
|
|
||||||
|
clusters = calloc (portalclusters, sizeof (cluster_t));
|
||||||
originalvismapsize = numrealleafs * ((numrealleafs + 7) / 8);
|
originalvismapsize = numrealleafs * ((numrealleafs + 7) / 8);
|
||||||
|
|
||||||
for (i = 0, portal = portals; i < numportals; i++) {
|
clusternums = calloc (numportals, sizeof (clusterpair_t));
|
||||||
|
winding_t **windings = malloc (numportals * sizeof (winding_t *));
|
||||||
|
for (unsigned i = 0; i < numportals; i++) {
|
||||||
line = Qgetline (f);
|
line = Qgetline (f);
|
||||||
if (!line)
|
if (!line)
|
||||||
Sys_Error ("LoadPortals: reading portal %u", i);
|
Sys_Error ("LoadPortals: reading portal %u", i);
|
||||||
|
@ -1257,41 +1297,36 @@ LoadPortals (char *name)
|
||||||
if (err == line)
|
if (err == line)
|
||||||
Sys_Error ("LoadPortals: reading portal %u", i);
|
Sys_Error ("LoadPortals: reading portal %u", i);
|
||||||
line = err;
|
line = err;
|
||||||
for (j = 0; j < 2; j++) {
|
|
||||||
clusternums[j] = strtol (line, &err, 10);
|
for (int j = 0; j < 2; j++) {
|
||||||
|
clusternums[i].clusters[j] = strtoul (line, &err, 10);
|
||||||
if (err == line)
|
if (err == line)
|
||||||
Sys_Error ("LoadPortals: reading portal %u", i);
|
Sys_Error ("LoadPortals: reading portal %u", i);
|
||||||
line = err;
|
line = err;
|
||||||
}
|
|
||||||
|
|
||||||
if ((unsigned) clusternums[0] > (unsigned) portalclusters
|
if (clusternums[i].clusters[j] > portalclusters)
|
||||||
|| (unsigned) clusternums[1] > (unsigned) portalclusters)
|
|
||||||
Sys_Error ("LoadPortals: reading portal %u", i);
|
|
||||||
|
|
||||||
winding = portal->winding = NewWinding (&main_thread, numpoints);
|
|
||||||
winding->original = true;
|
|
||||||
winding->numpoints = numpoints;
|
|
||||||
|
|
||||||
for (j = 0; j < numpoints; j++) {
|
|
||||||
// (%ld %ld %ld)
|
|
||||||
while (isspace ((byte) *line))
|
|
||||||
line++;
|
|
||||||
if (*line++ != '(')
|
|
||||||
Sys_Error ("LoadPortals: reading portal %u", i);
|
|
||||||
|
|
||||||
for (k = 0; k < 3; k++) {
|
|
||||||
winding->points[j][k] = strtod (line, &err);
|
|
||||||
if (err == line)
|
|
||||||
Sys_Error ("LoadPortals: reading portal %u", i);
|
|
||||||
line = err;
|
|
||||||
}
|
|
||||||
winding->points[j][3] = 1;
|
|
||||||
|
|
||||||
while (isspace ((byte) *line))
|
|
||||||
line++;
|
|
||||||
if (*line++ != ')')
|
|
||||||
Sys_Error ("LoadPortals: reading portal %u", i);
|
Sys_Error ("LoadPortals: reading portal %u", i);
|
||||||
}
|
}
|
||||||
|
clusters[clusternums[i].clusters[0]].numportals++;
|
||||||
|
clusters[clusternums[i].clusters[1]].numportals++;
|
||||||
|
|
||||||
|
if (!(windings[i] = parse_winding (line, numpoints))) {
|
||||||
|
Sys_Error ("LoadPortals: reading portal %u", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clusters[0].portals = portals;
|
||||||
|
for (unsigned i = 1; i < portalclusters; i++) {
|
||||||
|
portal_t *portal = clusters[i - 1].portals;
|
||||||
|
clusters[i].portals = portal + clusters[i - 1].numportals;
|
||||||
|
clusters[i - 1].numportals = 0;
|
||||||
|
}
|
||||||
|
clusters[portalclusters - 1].numportals = 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < numportals; i++) {
|
||||||
|
winding_t *winding = windings[i];
|
||||||
|
cluster_t *cluster;
|
||||||
|
portal_t *portal;
|
||||||
|
|
||||||
sphere = SmallestEnclosingBall_vf(winding->points, winding->numpoints);
|
sphere = SmallestEnclosingBall_vf(winding->points, winding->numpoints);
|
||||||
//printf (VEC4F_FMT" %.9g\n", VEC4_EXP (sphere.center), sphere.radius);
|
//printf (VEC4F_FMT" %.9g\n", VEC4_EXP (sphere.center), sphere.radius);
|
||||||
|
@ -1300,45 +1335,39 @@ LoadPortals (char *name)
|
||||||
plane = PlaneFromWinding (winding);
|
plane = PlaneFromWinding (winding);
|
||||||
|
|
||||||
// create forward portal
|
// create forward portal
|
||||||
cluster = &clusters[clusternums[0]];
|
cluster = &clusters[clusternums[i].clusters[0]];
|
||||||
if (cluster->numportals == MAX_PORTALS_ON_CLUSTER)
|
portal = &cluster->portals[cluster->numportals++];
|
||||||
Sys_Error ("Cluster with too many portals");
|
|
||||||
cluster->portals[cluster->numportals] = portal;
|
|
||||||
cluster->numportals++;
|
|
||||||
|
|
||||||
portal->winding = winding;
|
|
||||||
portal->plane = -plane; // plane is for CW, portal is CCW
|
portal->plane = -plane; // plane is for CW, portal is CCW
|
||||||
portal->cluster = clusternums[1];
|
|
||||||
portal->sphere = sphere;
|
portal->sphere = sphere;
|
||||||
portal++;
|
portal->cluster = clusternums[i].clusters[1];
|
||||||
|
portal->winding = winding;
|
||||||
// create backwards portal
|
|
||||||
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++;
|
|
||||||
|
|
||||||
// Use a flipped winding for the reverse portal so the winding
|
// Use a flipped winding for the reverse portal so the winding
|
||||||
// direction and plane normal match.
|
// direction and plane normal match.
|
||||||
portal->winding = NewFlippedWinding (&main_thread, winding);
|
winding = NewFlippedWinding (&main_thread, winding); // **
|
||||||
portal->winding->original = true;
|
winding->original = true;
|
||||||
|
|
||||||
|
// create backwards portal
|
||||||
|
cluster = &clusters[clusternums[i].clusters[1]];
|
||||||
|
portal = &cluster->portals[cluster->numportals++];
|
||||||
portal->plane = plane;
|
portal->plane = plane;
|
||||||
portal->cluster = clusternums[0];
|
|
||||||
portal->sphere = sphere;
|
portal->sphere = sphere;
|
||||||
portal++;
|
portal->cluster = clusternums[i].clusters[0];
|
||||||
|
portal->winding = winding;
|
||||||
}
|
}
|
||||||
|
free (clusternums);
|
||||||
|
free (windings);
|
||||||
|
|
||||||
leafcluster = calloc (numrealleafs, sizeof (int));
|
leafcluster = calloc (numrealleafs, sizeof (int));
|
||||||
if (read_leafs) {
|
if (read_leafs) {
|
||||||
for (i = 0; i < numrealleafs; i++) {
|
for (unsigned i = 0; i < numrealleafs; i++) {
|
||||||
line = Qgetline (f);
|
line = Qgetline (f);
|
||||||
if (sscanf (line, "%i\n", &leafcluster[i]) != 1)
|
if (sscanf (line, "%i\n", &leafcluster[i]) != 1)
|
||||||
Sys_Error ("LoadPortals: parse error in leaf->cluster "
|
Sys_Error ("LoadPortals: parse error in leaf->cluster "
|
||||||
"mappings");
|
"mappings");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < numrealleafs; i++)
|
for (unsigned i = 0; i < numrealleafs; i++)
|
||||||
leafcluster[i] = i;
|
leafcluster[i] = i;
|
||||||
}
|
}
|
||||||
Qclose (f);
|
Qclose (f);
|
||||||
|
|
Loading…
Reference in a new issue