18
int c_portaltest, c_portalpass, c_portalcheck;
20
byte *uncompressedvis;
22
byte *vismap, *vismap_p, *vismap_end; // past visfile
23
int originalvismapsize;
25
int leafbytes; // (portalclusters+63)>>3
28
int portalbytes, portallongs;
38
portal_t *sorted_portals[MAX_MAP_PORTALS*2];
41
//=============================================================================
43
void PlaneFromWinding (winding_t *w, plane_t *plane)
48
VectorSubtract (w->points[2], w->points[1], v1);
49
VectorSubtract (w->points[0], w->points[1], v2);
51
CrossProduct (v2, v1, plane->normal);
52
VectorNormalize (plane->normal, plane->normal);
53
plane->dist = DotProduct (w->points[0], plane->normal);
62
winding_t *NewWinding (int points)
67
if (points > MAX_POINTS_ON_WINDING)
68
Error ("NewWinding: %i points", points);
70
size = (int)((winding_t *)0)->points[points];
82
for (i=0 ; i<w->numpoints ; i++)
83
printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]);
92
for (i=0 ; i<l->numportals ; i++)
96
printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]);
101
//=============================================================================
107
Sorts the portals from the least complex, so the later ones can reuse
108
the earlier information.
111
int PComp (const void *a, const void *b)
113
if ( (*(portal_t **)a)->nummightsee == (*(portal_t **)b)->nummightsee)
115
if ( (*(portal_t **)a)->nummightsee < (*(portal_t **)b)->nummightsee)
120
void SortPortals (void)
124
for (i=0 ; i<numportals*2 ; i++)
125
sorted_portals[i] = &portals[i];
129
qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
135
LeafVectorFromPortalVector
138
int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
145
memset (leafbits, 0, leafbytes);
147
for (i=0 ; i<numportals*2 ; i++)
149
if (portalbits[i>>3] & (1<<(i&7)) )
152
leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
156
c_leafs = CountBits (leafbits, portalclusters);
166
Merges the portal visibility for a leaf
169
void ClusterMerge (int leafnum)
172
byte portalvector[MAX_PORTALS/8];
173
byte uncompressed[MAX_MAP_LEAFS/8];
174
byte compressed[MAX_MAP_LEAFS/8];
181
// OR together all the portalvis bits
183
memset (portalvector, 0, portalbytes);
184
leaf = &leafs[leafnum];
185
for (i=0 ; i<leaf->numportals ; i++)
187
p = leaf->portals[i];
188
if (p->status != stat_done)
189
Error ("portal not done");
190
for (j=0 ; j<portallongs ; j++)
191
((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
193
portalvector[pnum>>3] |= 1<<(pnum&7);
196
// convert portal bits to leaf bits
197
numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
199
if (uncompressed[leafnum>>3] & (1<<(leafnum&7)))
200
printf ("WARNING: Leaf portals saw into leaf (%d)\n", leafnum);
202
uncompressed[leafnum>>3] |= (1<<(leafnum&7));
203
numvis++; // count the leaf itself
205
// save uncompressed for PHS calculation
206
memcpy (uncompressedvis + leafnum*leafbytes, uncompressed, leafbytes);
209
// compress the bit string
211
qprintf ("cluster %4i : %4i visible\n", leafnum, numvis);
214
i = CompressVis (uncompressed, compressed);
219
if (vismap_p > vismap_end)
220
Error ("Vismap expansion overflow");
222
dvis->bitofs[leafnum][DVIS_PVS] = dest-vismap;
224
memcpy (dest, compressed, i);
233
void CalcPortalVis (void)
237
// fastvis just uses mightsee for a very loose bound
240
for (i=0 ; i<numportals*2 ; i++)
242
portals[i].portalvis = portals[i].portalflood;
243
portals[i].status = stat_done;
248
RunThreadsOnIndividual (numportals*2, true, PortalFlow);
262
RunThreadsOnIndividual (numportals*2, true, BasePortalVis);
264
// RunThreadsOnIndividual (numportals*2, true, BetterPortalVis);
271
// assemble the leaf vis lists by oring and compressing the portal lists
273
for (i=0 ; i<portalclusters ; i++)
276
printf ("Average clusters visible: %i\n", totalvis / portalclusters);
280
void SetPortalSphere (portal_t *p)
288
VectorCopy (vec3_origin, total);
289
for (i=0 ; i<w->numpoints ; i++)
291
VectorAdd (total, w->points[i], total);
294
for (i=0 ; i<3 ; i++)
295
total[i] /= w->numpoints;
298
for (i=0 ; i<w->numpoints ; i++)
300
VectorSubtract (w->points[i], total, dist);
301
r = VectorLength (dist);
305
VectorCopy (total, p->origin);
314
void LoadPortals (char *name)
326
if (!strcmp(name,"-"))
330
f = fopen(name, "r");
332
Error ("LoadPortals: couldn't read %s\n",name);
335
if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalclusters, &numportals) != 3)
336
Error ("LoadPortals: failed to read header");
337
if (strcmp(magic,PORTALFILE))
338
Error ("LoadPortals: not a portal file");
340
printf ("%4i portalclusters\n", portalclusters);
341
printf ("%4i numportals\n", numportals);
343
// these counts should take advantage of 64 bit systems automatically
344
leafbytes = ((portalclusters+63)&~63)>>3;
345
leaflongs = leafbytes/sizeof(long);
347
portalbytes = ((numportals*2+63)&~63)>>3;
348
portallongs = portalbytes/sizeof(long);
350
// each file portal is split into two memory portals
351
portals = malloc(2*numportals*sizeof(portal_t));
352
memset (portals, 0, 2*numportals*sizeof(portal_t));
354
leafs = malloc(portalclusters*sizeof(leaf_t));
355
memset (leafs, 0, portalclusters*sizeof(leaf_t));
357
originalvismapsize = portalclusters*leafbytes;
358
uncompressedvis = malloc(originalvismapsize);
360
vismap = vismap_p = dvisdata;
361
dvis->numclusters = portalclusters;
362
vismap_p = (byte *)&dvis->bitofs[portalclusters];
364
vismap_end = vismap + MAX_MAP_VISIBILITY;
366
for (i=0, p=portals ; i<numportals ; i++)
368
if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
370
Error ("LoadPortals: reading portal %i", i);
371
if (numpoints > MAX_POINTS_ON_WINDING)
372
Error ("LoadPortals: portal %i has too many points", i);
373
if ( (unsigned)leafnums[0] > portalclusters
374
|| (unsigned)leafnums[1] > portalclusters)
375
Error ("LoadPortals: reading portal %i", i);
377
w = p->winding = NewWinding (numpoints);
379
w->numpoints = numpoints;
381
for (j=0 ; j<numpoints ; j++)
386
// scanf into double, then assign to vec_t
387
// so we don't care what size vec_t is
388
if (fscanf (f, "(%lf %lf %lf ) "
389
, &v[0], &v[1], &v[2]) != 3)
390
Error ("LoadPortals: reading portal %i", i);
391
for (k=0 ; k<3 ; k++)
392
w->points[j][k] = v[k];
397
PlaneFromWinding (w, &plane);
399
// create forward portal
400
l = &leafs[leafnums[0]];
401
if (l->numportals == MAX_PORTALS_ON_LEAF)
402
Error ("Leaf with too many portals");
403
l->portals[l->numportals] = p;
407
VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
408
p->plane.dist = -plane.dist;
409
p->leaf = leafnums[1];
410
p->owner_leaf = leafnums[0];
414
// create backwards portal
415
l = &leafs[leafnums[1]];
416
if (l->numportals == MAX_PORTALS_ON_LEAF)
417
Error ("Leaf with too many portals");
418
l->portals[l->numportals] = p;
421
p->winding = NewWinding(w->numpoints);
422
p->winding->numpoints = w->numpoints;
423
for (j=0 ; j<w->numpoints ; j++)
425
VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
429
p->leaf = leafnums[0];
430
p->owner_leaf = leafnums[1];
444
Calculate the PHS (Potentially Hearable Set)
445
by ORing together all the PVS visible from a leaf
450
int i, j, k, l, index;
455
byte uncompressed[MAX_MAP_LEAFS/8];
456
byte compressed[MAX_MAP_LEAFS/8];
458
printf ("Building PHS...\n");
461
for (i=0 ; i<portalclusters ; i++)
463
scan = uncompressedvis + i*leafbytes;
464
memcpy (uncompressed, scan, leafbytes);
465
for (j=0 ; j<leafbytes ; j++)
470
for (k=0 ; k<8 ; k++)
472
if (! (bitbyte & (1<<k)) )
474
// OR this pvs row into the phs
476
if (index >= portalclusters)
477
Error ("Bad bit in PVS"); // pad bits should be 0
478
src = (long *)(uncompressedvis + index*leafbytes);
479
dest = (long *)uncompressed;
480
for (l=0 ; l<leaflongs ; l++)
481
((long *)uncompressed)[l] |= src[l];
484
for (j=0 ; j<portalclusters ; j++)
485
if (uncompressed[j>>3] & (1<<(j&7)) )
489
// compress the bit string
491
j = CompressVis (uncompressed, compressed);
493
dest = (long *)vismap_p;
496
if (vismap_p > vismap_end)
497
Error ("Vismap expansion overflow");
499
dvis->bitofs[i][DVIS_PHS] = (byte *)dest-vismap;
501
memcpy (dest, compressed, j);
504
printf ("Average clusters hearable: %i\n", count/portalclusters);
512
int main (int argc, char **argv)
514
char portalfile[1024];
517
char *param, *param2;
520
printf ("----------- qvis3 -----------\n");
521
printf ("original code by id Software\n");
522
printf ("Modified by Geoffrey DeWan\n");
523
printf ("Revision 1.03\n");
524
printf ("-----------------------------\n");
526
LoadConfigurationFile("qvis3", 0);
527
LoadConfiguration(argc-1, argv+1);
531
while((param = WalkConfiguration()) != NULL)
533
if (!strcmp(param,"-threads"))
535
param2 = WalkConfiguration();
536
numthreads = atoi (param2);
538
else if (!strcmp(param, "-fast"))
540
printf ("fastvis = true\n");
543
else if (!strcmp(param, "-level"))
545
param2 = WalkConfiguration();
546
testlevel = atoi (param2);
547
printf ("Test level not used in qvis3\n");
549
else if (!strcmp(param, "-maxdist"))
551
param2 = WalkConfiguration();
552
maxdist = atof (param2);
554
printf ("maxdist = %.2f\n", maxdist);
556
else if (!strcmp(param, "-maxfovdist"))
558
float fov, tmpmaxdist;
560
param2 = WalkConfiguration();
562
param2 = WalkConfiguration();
563
tmpmaxdist = atof (param2);
565
maxdist = tmpmaxdist / (float)cos(atan(tan(fov * Q_PI / 360.0) * 5.0 / 4.0));
567
printf ("maxfovdist = %.2f %.2f -> %2f\n", fov, tmpmaxdist, maxdist);
569
else if (!strcmp(param, "-v"))
571
printf ("verbose = true\n");
574
else if (!strcmp (param,"-nosort"))
576
printf ("nosort = true\n");
579
else if (!strcmp (param,"-cullerror"))
581
printf ("cullerror = true\n");
584
else if (!strcmp (param,"-tmpin"))
585
strcpy (inbase, "/tmp");
586
else if (!strcmp (param,"-tmpout"))
587
strcpy (outbase, "/tmp");
588
else if (param[0] == '+')
589
LoadConfigurationFile(param+1, 1);
590
else if (param[0] == '-')
591
Error ("Unknown option \"%s\"", param);
597
param2 = WalkConfiguration();
599
if (param == NULL || param2 != NULL)
600
Error ("usage: vis [-threads #] [-fast] [-nosort] [-cullerror] [-v] [-maxdist distance] [-maxfovdist fov distance] bspfile");
602
while(param2) // make sure list is clean
603
param2 = WalkConfiguration();
605
start = I_FloatTime ();
609
// if(!IsFullPath(param))
610
// SetQdirFromPath (param);
612
strcpy (source, ExpandArg(param));
613
StripExtension (source);
614
DefaultExtension (source, ".bsp");
616
sprintf (name, "%s%s", inbase, source);
617
printf ("reading %s\n", name);
619
if (numnodes == 0 || numfaces == 0)
622
sprintf (portalfile, "%s%s", inbase, ExpandArg(param));
623
StripExtension (portalfile);
624
strcat (portalfile, ".prt");
626
printf ("reading %s\n", portalfile);
627
LoadPortals (portalfile);
633
visdatasize = vismap_p - dvisdata;
634
printf ("visdatasize:%i compressed from %i\n", visdatasize, originalvismapsize*2);
636
sprintf (name, "%s%s", outbase, source);
637
printf ("writing %s\n", name);
640
end = I_FloatTime ();
641
printf ("%5.1f seconds elapsed\n", end-start);