00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "vis.h"
00025 #include "threads.h"
00026 #include "stdlib.h"
00027 #ifdef _WIN32
00028 #include "../libs/pakstuff.h"
00029 #endif
00030
00031
00032 #define VIS_HEADER_SIZE 8
00033
00034 extern char outbase[32];
00035
00036 int numportals;
00037 int portalclusters;
00038 int numfaces;
00039
00040 char inbase[32];
00041
00042 vportal_t *portals;
00043 leaf_t *leafs;
00044
00045 vportal_t *faces;
00046 leaf_t *faceleafs;
00047
00048 int c_portaltest, c_portalpass, c_portalcheck;
00049
00050 int leafbytes;
00051 int leaflongs;
00052
00053 int portalbytes, portallongs;
00054
00055 qboolean fastvis;
00056 qboolean noPassageVis;
00057 qboolean passageVisOnly;
00058 qboolean mergevis;
00059 qboolean nosort;
00060 qboolean saveprt;
00061
00062 int testlevel = 2;
00063
00064 int totalvis;
00065
00066 vportal_t *sorted_portals[MAX_MAP_PORTALS*2];
00067
00068 void PassageMemory(void);
00069
00070
00071
00072
00073 void PlaneFromWinding (winding_t *w, plane_t *plane)
00074 {
00075 vec3_t v1, v2;
00076
00077
00078 VectorSubtract (w->points[2], w->points[1], v1);
00079 VectorSubtract (w->points[0], w->points[1], v2);
00080 CrossProduct (v2, v1, plane->normal);
00081 VectorNormalize (plane->normal, plane->normal);
00082 plane->dist = DotProduct (w->points[0], plane->normal);
00083 }
00084
00085
00086
00087
00088
00089
00090
00091 winding_t *NewWinding (int points)
00092 {
00093 winding_t *w;
00094 int size;
00095
00096 if (points > MAX_POINTS_ON_WINDING)
00097 Error ("NewWinding: %i points", points);
00098
00099 size = (int)((winding_t *)0)->points[points];
00100 w = malloc (size);
00101 memset (w, 0, size);
00102
00103 return w;
00104 }
00105
00106
00107
00108 void prl(leaf_t *l)
00109 {
00110 int i;
00111 vportal_t *p;
00112 plane_t pl;
00113
00114 for (i=0 ; i<l->numportals ; i++)
00115 {
00116 p = l->portals[i];
00117 pl = p->plane;
00118 _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]);
00119 }
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 int PComp (const void *a, const void *b)
00134 {
00135 if ( (*(vportal_t **)a)->nummightsee == (*(vportal_t **)b)->nummightsee)
00136 return 0;
00137 if ( (*(vportal_t **)a)->nummightsee < (*(vportal_t **)b)->nummightsee)
00138 return -1;
00139 return 1;
00140 }
00141 void SortPortals (void)
00142 {
00143 int i;
00144
00145 for (i=0 ; i<numportals*2 ; i++)
00146 sorted_portals[i] = &portals[i];
00147
00148 if (nosort)
00149 return;
00150 qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
00160 {
00161 int i, j, leafnum;
00162 vportal_t *p;
00163 int c_leafs;
00164
00165
00166 for (i=0 ; i<numportals*2 ; i++)
00167 {
00168 if (portalbits[i>>3] & (1<<(i&7)) )
00169 {
00170 p = portals+i;
00171 leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
00172 }
00173 }
00174
00175 for (j = 0; j < portalclusters; j++)
00176 {
00177 leafnum = j;
00178 while (leafs[leafnum].merged >= 0)
00179 leafnum = leafs[leafnum].merged;
00180
00181 if (leafbits[leafnum>>3] & (1<<(leafnum&7)))
00182 {
00183 leafbits[j>>3] |= (1<<(j&7));
00184 }
00185 }
00186
00187 c_leafs = CountBits (leafbits, portalclusters);
00188
00189 return c_leafs;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 void ClusterMerge (int leafnum)
00201 {
00202 leaf_t *leaf;
00203 byte portalvector[MAX_PORTALS/8];
00204 byte uncompressed[MAX_MAP_LEAFS/8];
00205 int i, j;
00206 int numvis, mergedleafnum;
00207 vportal_t *p;
00208 int pnum;
00209
00210
00211
00212 mergedleafnum = leafnum;
00213 while(leafs[mergedleafnum].merged >= 0)
00214 mergedleafnum = leafs[mergedleafnum].merged;
00215
00216 memset (portalvector, 0, portalbytes);
00217 leaf = &leafs[mergedleafnum];
00218 for (i = 0; i < leaf->numportals; i++)
00219 {
00220 p = leaf->portals[i];
00221 if (p->removed)
00222 continue;
00223
00224 if (p->status != stat_done)
00225 Error ("portal not done");
00226 for (j=0 ; j<portallongs ; j++)
00227 ((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
00228 pnum = p - portals;
00229 portalvector[pnum>>3] |= 1<<(pnum&7);
00230 }
00231
00232 memset (uncompressed, 0, leafbytes);
00233
00234 uncompressed[mergedleafnum>>3] |= (1<<(mergedleafnum&7));
00235
00236 numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
00237
00238
00239
00240
00241
00242
00243 numvis++;
00244
00245 totalvis += numvis;
00246
00247 qprintf ("cluster %4i : %4i visible\n", leafnum, numvis);
00248
00249 memcpy (visBytes + VIS_HEADER_SIZE + leafnum*leafbytes, uncompressed, leafbytes);
00250 }
00251
00252
00253
00254
00255
00256
00257 void CalcPortalVis (void)
00258 {
00259 #ifdef MREDEBUG
00260 _printf("%6d portals out of %d", 0, numportals*2);
00261
00262 RunThreadsOnIndividual (numportals*2, qfalse, PortalFlow);
00263 #else
00264 RunThreadsOnIndividual (numportals*2, qtrue, PortalFlow);
00265 #endif
00266
00267 }
00268
00269
00270
00271
00272
00273
00274 void CalcPassageVis(void)
00275 {
00276 PassageMemory();
00277
00278 #ifdef MREDEBUG
00279 _printf("%6d portals out of %d", 0, numportals*2);
00280 RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages);
00281 _printf("\n");
00282 _printf("%6d portals out of %d", 0, numportals*2);
00283 RunThreadsOnIndividual (numportals*2, qfalse, PassageFlow);
00284 _printf("\n");
00285 #else
00286 RunThreadsOnIndividual (numportals*2, qtrue, CreatePassages);
00287 RunThreadsOnIndividual (numportals*2, qtrue, PassageFlow);
00288 #endif
00289 }
00290
00291
00292
00293
00294
00295
00296 void CalcPassagePortalVis(void)
00297 {
00298 PassageMemory();
00299
00300 #ifdef MREDEBUG
00301 _printf("%6d portals out of %d", 0, numportals*2);
00302 RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages);
00303 _printf("\n");
00304 _printf("%6d portals out of %d", 0, numportals*2);
00305 RunThreadsOnIndividual (numportals*2, qfalse, PassagePortalFlow);
00306 _printf("\n");
00307 #else
00308 RunThreadsOnIndividual (numportals*2, qtrue, CreatePassages);
00309 RunThreadsOnIndividual (numportals*2, qtrue, PassagePortalFlow);
00310 #endif
00311 }
00312
00313
00314
00315
00316
00317
00318 void CalcFastVis(void)
00319 {
00320 int i;
00321
00322
00323 for (i=0 ; i<numportals*2 ; i++)
00324 {
00325 portals[i].portalvis = portals[i].portalflood;
00326 portals[i].status = stat_done;
00327 }
00328 }
00329
00330
00331
00332
00333
00334
00335 void CalcVis (void)
00336 {
00337 int i;
00338
00339 RunThreadsOnIndividual (numportals*2, qtrue, BasePortalVis);
00340
00341
00342
00343 SortPortals ();
00344
00345 if (fastvis) {
00346 CalcFastVis();
00347 }
00348 else if ( noPassageVis ) {
00349 CalcPortalVis();
00350 }
00351 else if ( passageVisOnly ) {
00352 CalcPassageVis();
00353 }
00354 else {
00355 CalcPassagePortalVis();
00356 }
00357
00358
00359
00360 _printf("creating leaf vis...\n");
00361 for (i=0 ; i<portalclusters ; i++)
00362 ClusterMerge (i);
00363
00364 _printf( "Total visible clusters: %i\n", totalvis );
00365 _printf( "Average clusters visible: %i\n", totalvis / portalclusters );
00366 }
00367
00368
00369
00370
00371
00372
00373 void SetPortalSphere (vportal_t *p)
00374 {
00375 int i;
00376 vec3_t total, dist;
00377 winding_t *w;
00378 float r, bestr;
00379
00380 w = p->winding;
00381 VectorCopy (vec3_origin, total);
00382 for (i=0 ; i<w->numpoints ; i++)
00383 {
00384 VectorAdd (total, w->points[i], total);
00385 }
00386
00387 for (i=0 ; i<3 ; i++)
00388 total[i] /= w->numpoints;
00389
00390 bestr = 0;
00391 for (i=0 ; i<w->numpoints ; i++)
00392 {
00393 VectorSubtract (w->points[i], total, dist);
00394 r = VectorLength (dist);
00395 if (r > bestr)
00396 bestr = r;
00397 }
00398 VectorCopy (total, p->origin);
00399 p->radius = bestr;
00400 }
00401
00402
00403
00404
00405
00406
00407 #define WCONVEX_EPSILON 0.2
00408
00409 int Winding_PlanesConcave(winding_t *w1, winding_t *w2,
00410 vec3_t normal1, vec3_t normal2,
00411 float dist1, float dist2)
00412 {
00413 int i;
00414
00415 if (!w1 || !w2) return qfalse;
00416
00417
00418 for (i = 0; i < w1->numpoints; i++)
00419 {
00420 if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return qtrue;
00421 }
00422
00423 for (i = 0; i < w2->numpoints; i++)
00424 {
00425 if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return qtrue;
00426 }
00427
00428 return qfalse;
00429 }
00430
00431
00432
00433
00434
00435
00436 int TryMergeLeaves(int l1num, int l2num)
00437 {
00438 int i, j, k, n, numportals;
00439 plane_t plane1, plane2;
00440 leaf_t *l1, *l2;
00441 vportal_t *p1, *p2;
00442 vportal_t *portals[MAX_PORTALS_ON_LEAF];
00443
00444 for (k = 0; k < 2; k++)
00445 {
00446 if (k) l1 = &leafs[l1num];
00447 else l1 = &faceleafs[l1num];
00448 for (i = 0; i < l1->numportals; i++)
00449 {
00450 p1 = l1->portals[i];
00451 if (p1->leaf == l2num) continue;
00452 for (n = 0; n < 2; n++)
00453 {
00454 if (n) l2 = &leafs[l2num];
00455 else l2 = &faceleafs[l2num];
00456 for (j = 0; j < l2->numportals; j++)
00457 {
00458 p2 = l2->portals[j];
00459 if (p2->leaf == l1num) continue;
00460
00461 plane1 = p1->plane;
00462 plane2 = p2->plane;
00463 if (Winding_PlanesConcave(p1->winding, p2->winding, plane1.normal, plane2.normal, plane1.dist, plane2.dist))
00464 return qfalse;
00465 }
00466 }
00467 }
00468 }
00469 for (k = 0; k < 2; k++)
00470 {
00471 if (k)
00472 {
00473 l1 = &leafs[l1num];
00474 l2 = &leafs[l2num];
00475 }
00476 else
00477 {
00478 l1 = &faceleafs[l1num];
00479 l2 = &faceleafs[l2num];
00480 }
00481 numportals = 0;
00482
00483 for (i = 0; i < l1->numportals; i++)
00484 {
00485 p1 = l1->portals[i];
00486 if (p1->leaf == l2num)
00487 {
00488 p1->removed = qtrue;
00489 continue;
00490 }
00491 portals[numportals++] = p1;
00492 }
00493 for (j = 0; j < l2->numportals; j++)
00494 {
00495 p2 = l2->portals[j];
00496 if (p2->leaf == l1num)
00497 {
00498 p2->removed = qtrue;
00499 continue;
00500 }
00501 portals[numportals++] = p2;
00502 }
00503 for (i = 0; i < numportals; i++)
00504 {
00505 l2->portals[i] = portals[i];
00506 }
00507 l2->numportals = numportals;
00508 l1->merged = l2num;
00509 }
00510 return qtrue;
00511 }
00512
00513
00514
00515
00516
00517
00518 void UpdatePortals(void)
00519 {
00520 int i;
00521 vportal_t *p;
00522
00523 for (i = 0; i < numportals * 2; i++)
00524 {
00525 p = &portals[i];
00526 if (p->removed)
00527 continue;
00528 while(leafs[p->leaf].merged >= 0)
00529 p->leaf = leafs[p->leaf].merged;
00530 }
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540 void MergeLeaves(void)
00541 {
00542 int i, j, nummerges, totalnummerges;
00543 leaf_t *leaf;
00544 vportal_t *p;
00545
00546 totalnummerges = 0;
00547 do
00548 {
00549 nummerges = 0;
00550 for (i = 0; i < portalclusters; i++)
00551 {
00552 leaf = &leafs[i];
00553
00554 if (leaf->merged >= 0)
00555 continue;
00556
00557 for (j = 0; j < leaf->numportals; j++)
00558 {
00559 p = leaf->portals[j];
00560
00561 if (p->removed)
00562 continue;
00563
00564 if (p->hint)
00565 continue;
00566 if (TryMergeLeaves(i, p->leaf))
00567 {
00568 UpdatePortals();
00569 nummerges++;
00570 break;
00571 }
00572 }
00573 }
00574 totalnummerges += nummerges;
00575 } while (nummerges);
00576 _printf("%6d leaves merged\n", totalnummerges);
00577 }
00578
00579
00580
00581
00582
00583
00584 #define CONTINUOUS_EPSILON 0.005
00585
00586 winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal)
00587 {
00588 vec_t *p1, *p2, *p3, *p4, *back;
00589 winding_t *newf;
00590 int i, j, k, l;
00591 vec3_t normal, delta;
00592 vec_t dot;
00593 qboolean keep1, keep2;
00594
00595
00596
00597
00598
00599 p1 = p2 = NULL;
00600 j = 0;
00601
00602 for (i = 0; i < f1->numpoints; i++)
00603 {
00604 p1 = f1->points[i];
00605 p2 = f1->points[(i+1) % f1->numpoints];
00606 for (j = 0; j < f2->numpoints; j++)
00607 {
00608 p3 = f2->points[j];
00609 p4 = f2->points[(j+1) % f2->numpoints];
00610 for (k = 0; k < 3; k++)
00611 {
00612 if (fabs(p1[k] - p4[k]) > 0.1)
00613 break;
00614 if (fabs(p2[k] - p3[k]) > 0.1)
00615 break;
00616 }
00617 if (k==3)
00618 break;
00619 }
00620 if (j < f2->numpoints)
00621 break;
00622 }
00623
00624 if (i == f1->numpoints)
00625 return NULL;
00626
00627
00628
00629
00630
00631 back = f1->points[(i+f1->numpoints-1)%f1->numpoints];
00632 VectorSubtract (p1, back, delta);
00633 CrossProduct (planenormal, delta, normal);
00634 VectorNormalize (normal, normal);
00635
00636 back = f2->points[(j+2)%f2->numpoints];
00637 VectorSubtract (back, p1, delta);
00638 dot = DotProduct (delta, normal);
00639 if (dot > CONTINUOUS_EPSILON)
00640 return NULL;
00641 keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
00642
00643 back = f1->points[(i+2)%f1->numpoints];
00644 VectorSubtract (back, p2, delta);
00645 CrossProduct (planenormal, delta, normal);
00646 VectorNormalize (normal, normal);
00647
00648 back = f2->points[(j+f2->numpoints-1)%f2->numpoints];
00649 VectorSubtract (back, p2, delta);
00650 dot = DotProduct (delta, normal);
00651 if (dot > CONTINUOUS_EPSILON)
00652 return NULL;
00653 keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
00654
00655
00656
00657
00658 newf = NewWinding (f1->numpoints + f2->numpoints);
00659
00660
00661 for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
00662 {
00663 if (k==(i+1)%f1->numpoints && !keep2)
00664 continue;
00665
00666 VectorCopy (f1->points[k], newf->points[newf->numpoints]);
00667 newf->numpoints++;
00668 }
00669
00670
00671 for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
00672 {
00673 if (l==(j+1)%f2->numpoints && !keep1)
00674 continue;
00675 VectorCopy (f2->points[l], newf->points[newf->numpoints]);
00676 newf->numpoints++;
00677 }
00678
00679 return newf;
00680 }
00681
00682
00683
00684
00685
00686
00687 void MergeLeafPortals(void)
00688 {
00689 int i, j, k, nummerges, hintsmerged;
00690 leaf_t *leaf;
00691 vportal_t *p1, *p2;
00692 winding_t *w;
00693
00694 nummerges = 0;
00695 hintsmerged = 0;
00696 for (i = 0; i < portalclusters; i++)
00697 {
00698 leaf = &leafs[i];
00699 if (leaf->merged >= 0) continue;
00700 for (j = 0; j < leaf->numportals; j++)
00701 {
00702 p1 = leaf->portals[j];
00703 if (p1->removed)
00704 continue;
00705 for (k = j+1; k < leaf->numportals; k++)
00706 {
00707 p2 = leaf->portals[k];
00708 if (p2->removed)
00709 continue;
00710 if (p1->leaf == p2->leaf)
00711 {
00712 w = TryMergeWinding(p1->winding, p2->winding, p1->plane.normal);
00713 if (w)
00714 {
00715 FreeWinding(p1->winding);
00716 p1->winding = w;
00717 if (p1->hint && p2->hint)
00718 hintsmerged++;
00719 p1->hint |= p2->hint;
00720 SetPortalSphere(p1);
00721 p2->removed = qtrue;
00722 nummerges++;
00723 i--;
00724 break;
00725 }
00726 }
00727 }
00728 if (k < leaf->numportals)
00729 break;
00730 }
00731 }
00732 _printf("%6d portals merged\n", nummerges);
00733 _printf("%6d hint portals merged\n", hintsmerged);
00734 }
00735
00736
00737
00738
00739
00740
00741
00742 int CountActivePortals(void)
00743 {
00744 int num, hints, j;
00745 vportal_t *p;
00746
00747 num = 0;
00748 hints = 0;
00749 for (j = 0; j < numportals * 2; j++)
00750 {
00751 p = portals + j;
00752 if (p->removed)
00753 continue;
00754 if (p->hint)
00755 hints++;
00756 num++;
00757 }
00758 _printf("%6d active portals\n", num);
00759 _printf("%6d hint portals\n", hints);
00760 return num;
00761 }
00762
00763
00764
00765
00766
00767
00768 void WriteFloat (FILE *f, vec_t v);
00769
00770 void WritePortals(char *filename)
00771 {
00772 int i, j, num;
00773 FILE *pf;
00774 vportal_t *p;
00775 winding_t *w;
00776
00777
00778 pf = fopen (filename, "w");
00779 if (!pf)
00780 Error ("Error opening %s", filename);
00781
00782 num = 0;
00783 for (j = 0; j < numportals * 2; j++)
00784 {
00785 p = portals + j;
00786 if (p->removed)
00787 continue;
00788
00789
00790 num++;
00791 }
00792
00793 fprintf (pf, "%s\n", PORTALFILE);
00794 fprintf (pf, "%i\n", 0);
00795 fprintf (pf, "%i\n", num);
00796 fprintf (pf, "%i\n", 0);
00797
00798 for (j = 0; j < numportals * 2; j++)
00799 {
00800 p = portals + j;
00801 if (p->removed)
00802 continue;
00803
00804
00805 w = p->winding;
00806 fprintf (pf,"%i %i %i ",w->numpoints, 0, 0);
00807 fprintf (pf, "%d ", p->hint);
00808 for (i=0 ; i<w->numpoints ; i++)
00809 {
00810 fprintf (pf,"(");
00811 WriteFloat (pf, w->points[i][0]);
00812 WriteFloat (pf, w->points[i][1]);
00813 WriteFloat (pf, w->points[i][2]);
00814 fprintf (pf,") ");
00815 }
00816 fprintf (pf,"\n");
00817 }
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 fclose (pf);
00838 }
00839
00840
00841
00842
00843
00844
00845 void LoadPortals (char *name)
00846 {
00847 int i, j, hint;
00848 vportal_t *p;
00849 leaf_t *l;
00850 char magic[80];
00851 FILE *f;
00852 int numpoints;
00853 winding_t *w;
00854 int leafnums[2];
00855 plane_t plane;
00856
00857 if (!strcmp(name,"-"))
00858 f = stdin;
00859 else
00860 {
00861 f = fopen(name, "r");
00862 if (!f)
00863 Error ("LoadPortals: couldn't read %s\n",name);
00864 }
00865
00866 if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4)
00867 Error ("LoadPortals: failed to read header");
00868 if (strcmp(magic,PORTALFILE))
00869 Error ("LoadPortals: not a portal file");
00870
00871 _printf ("%6i portalclusters\n", portalclusters);
00872 _printf ("%6i numportals\n", numportals);
00873 _printf ("%6i numfaces\n", numfaces);
00874
00875
00876 leafbytes = ((portalclusters+63)&~63)>>3;
00877 leaflongs = leafbytes/sizeof(long);
00878
00879 portalbytes = ((numportals*2+63)&~63)>>3;
00880 portallongs = portalbytes/sizeof(long);
00881
00882
00883 portals = malloc(2*numportals*sizeof(vportal_t));
00884 memset (portals, 0, 2*numportals*sizeof(vportal_t));
00885
00886 leafs = malloc(portalclusters*sizeof(leaf_t));
00887 memset (leafs, 0, portalclusters*sizeof(leaf_t));
00888
00889 for (i = 0; i < portalclusters; i++)
00890 leafs[i].merged = -1;
00891
00892 numVisBytes = VIS_HEADER_SIZE + portalclusters*leafbytes;
00893
00894 ((int *)visBytes)[0] = portalclusters;
00895 ((int *)visBytes)[1] = leafbytes;
00896
00897 for (i=0, p=portals ; i<numportals ; i++)
00898 {
00899 if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3)
00900 Error ("LoadPortals: reading portal %i", i);
00901 if (numpoints > MAX_POINTS_ON_WINDING)
00902 Error ("LoadPortals: portal %i has too many points", i);
00903 if ( (unsigned)leafnums[0] > portalclusters
00904 || (unsigned)leafnums[1] > portalclusters)
00905 Error ("LoadPortals: reading portal %i", i);
00906 if (fscanf (f, "%i ", &hint) != 1)
00907 Error ("LoadPortals: reading hint state");
00908
00909 w = p->winding = NewWinding (numpoints);
00910 w->numpoints = numpoints;
00911
00912 for (j=0 ; j<numpoints ; j++)
00913 {
00914 double v[3];
00915 int k;
00916
00917
00918
00919 if (fscanf (f, "(%lf %lf %lf ) "
00920 , &v[0], &v[1], &v[2]) != 3)
00921 Error ("LoadPortals: reading portal %i", i);
00922 for (k=0 ; k<3 ; k++)
00923 w->points[j][k] = v[k];
00924 }
00925 fscanf (f, "\n");
00926
00927
00928 PlaneFromWinding (w, &plane);
00929
00930
00931 l = &leafs[leafnums[0]];
00932 if (l->numportals == MAX_PORTALS_ON_LEAF)
00933 Error ("Leaf with too many portals");
00934 l->portals[l->numportals] = p;
00935 l->numportals++;
00936
00937 p->num = i+1;
00938 p->hint = hint;
00939 p->winding = w;
00940 VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
00941 p->plane.dist = -plane.dist;
00942 p->leaf = leafnums[1];
00943 SetPortalSphere (p);
00944 p++;
00945
00946
00947 l = &leafs[leafnums[1]];
00948 if (l->numportals == MAX_PORTALS_ON_LEAF)
00949 Error ("Leaf with too many portals");
00950 l->portals[l->numportals] = p;
00951 l->numportals++;
00952
00953 p->num = i+1;
00954 p->hint = hint;
00955 p->winding = NewWinding(w->numpoints);
00956 p->winding->numpoints = w->numpoints;
00957 for (j=0 ; j<w->numpoints ; j++)
00958 {
00959 VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
00960 }
00961
00962 p->plane = plane;
00963 p->leaf = leafnums[0];
00964 SetPortalSphere (p);
00965 p++;
00966
00967 }
00968
00969 faces = malloc(2*numfaces*sizeof(vportal_t));
00970 memset (faces, 0, 2*numfaces*sizeof(vportal_t));
00971
00972 faceleafs = malloc(portalclusters*sizeof(leaf_t));
00973 memset(faceleafs, 0, portalclusters*sizeof(leaf_t));
00974
00975 for (i = 0, p = faces; i < numfaces; i++)
00976 {
00977 if (fscanf (f, "%i %i ", &numpoints, &leafnums[0]) != 2)
00978 Error ("LoadPortals: reading portal %i", i);
00979
00980 w = p->winding = NewWinding (numpoints);
00981 w->numpoints = numpoints;
00982
00983 for (j=0 ; j<numpoints ; j++)
00984 {
00985 double v[3];
00986 int k;
00987
00988
00989
00990 if (fscanf (f, "(%lf %lf %lf ) "
00991 , &v[0], &v[1], &v[2]) != 3)
00992 Error ("LoadPortals: reading portal %i", i);
00993 for (k=0 ; k<3 ; k++)
00994 w->points[j][k] = v[k];
00995 }
00996 fscanf (f, "\n");
00997
00998
00999 PlaneFromWinding (w, &plane);
01000
01001 l = &faceleafs[leafnums[0]];
01002 l->merged = -1;
01003 if (l->numportals == MAX_PORTALS_ON_LEAF)
01004 Error ("Leaf with too many faces");
01005 l->portals[l->numportals] = p;
01006 l->numportals++;
01007
01008 p->num = i+1;
01009 p->winding = w;
01010
01011 VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
01012 p->plane.dist = -plane.dist;
01013 p->leaf = -1;
01014 SetPortalSphere (p);
01015 p++;
01016 }
01017
01018 fclose (f);
01019 }
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030 void CalcPHS (void)
01031 {
01032 int i, j, k, l, index;
01033 int bitbyte;
01034 long *dest, *src;
01035 byte *scan;
01036 int count;
01037 byte uncompressed[MAX_MAP_LEAFS/8];
01038
01039 _printf ("Building PHS...\n");
01040
01041 count = 0;
01042 for (i=0 ; i<portalclusters ; i++)
01043 {
01044 scan = visBytes + i*leafbytes;
01045 memcpy (uncompressed, scan, leafbytes);
01046 for (j=0 ; j<leafbytes ; j++)
01047 {
01048 bitbyte = scan[j];
01049 if (!bitbyte)
01050 continue;
01051 for (k=0 ; k<8 ; k++)
01052 {
01053 if (! (bitbyte & (1<<k)) )
01054 continue;
01055
01056 index = ((j<<3)+k);
01057 if (index >= portalclusters)
01058 Error ("Bad bit in PVS");
01059 src = (long *)(visBytes + index*leafbytes);
01060 dest = (long *)uncompressed;
01061 for (l=0 ; l<leaflongs ; l++)
01062 ((long *)uncompressed)[l] |= src[l];
01063 }
01064 }
01065 for (j=0 ; j<portalclusters ; j++)
01066 if (uncompressed[j>>3] & (1<<(j&7)) )
01067 count++;
01068
01069
01070 }
01071
01072 _printf ("Average clusters hearable: %i\n", count/portalclusters);
01073 }
01074
01075
01076
01077
01078
01079
01080 int VisMain (int argc, char **argv)
01081 {
01082 char portalfile[1024];
01083 char name[1024];
01084 int i;
01085 double start, end;
01086
01087 _printf ("---- vis ----\n");
01088
01089 verbose = qfalse;
01090 for (i=1 ; i<argc ; i++) {
01091 if (!strcmp(argv[i],"-threads")) {
01092 numthreads = atoi (argv[i+1]);
01093 i++;
01094 } else if (!strcmp(argv[i],"-threads")) {
01095 numthreads = atoi (argv[i+1]);
01096 i++;
01097 } else if (!strcmp(argv[i], "-fast")) {
01098 _printf ("fastvis = true\n");
01099 fastvis = qtrue;
01100 } else if (!strcmp(argv[i], "-merge")) {
01101 _printf ("merge = true\n");
01102 mergevis = qtrue;
01103 } else if (!strcmp(argv[i], "-nopassage")) {
01104 _printf ("nopassage = true\n");
01105 noPassageVis = qtrue;
01106 } else if (!strcmp(argv[i], "-passageOnly")) {
01107 _printf("passageOnly = true\n");
01108 passageVisOnly = qtrue;
01109 } else if (!strcmp(argv[i], "-level")) {
01110 testlevel = atoi(argv[i+1]);
01111 _printf ("testlevel = %i\n", testlevel);
01112 i++;
01113 } else if (!strcmp(argv[i], "-v")) {
01114 _printf ("verbose = true\n");
01115 verbose = qtrue;
01116 } else if (!strcmp (argv[i],"-nosort")) {
01117 _printf ("nosort = true\n");
01118 nosort = qtrue;
01119 } else if (!strcmp (argv[i],"-saveprt")) {
01120 _printf ("saveprt = true\n");
01121 saveprt = qtrue;
01122 } else if (!strcmp (argv[i],"-tmpin")) {
01123 strcpy (inbase, "/tmp");
01124 } else if (!strcmp (argv[i],"-tmpout")) {
01125 strcpy (outbase, "/tmp");
01126 } else if (argv[i][0] == '-') {
01127 Error ("Unknown option \"%s\"", argv[i]);
01128 } else {
01129 break;
01130 }
01131 }
01132
01133 if (i != argc - 1)
01134 Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");
01135
01136 #ifdef MREDEBUG
01137 start = clock();
01138 #else
01139 start = I_FloatTime ();
01140 #endif
01141
01142 ThreadSetDefault ();
01143
01144 SetQdirFromPath (argv[i]);
01145
01146 #ifdef _WIN32
01147 InitPakFile(gamedir, NULL);
01148 #endif
01149
01150
01151 sprintf (name, "%s%s", inbase, ExpandArg(argv[i]));
01152 StripExtension (name);
01153 strcat (name, ".bsp");
01154 _printf ("reading %s\n", name);
01155 LoadBSPFile (name);
01156
01157
01158 sprintf (portalfile, "%s%s", inbase, ExpandArg(argv[i]));
01159 StripExtension (portalfile);
01160 strcat (portalfile, ".prt");
01161 _printf ("reading %s\n", portalfile);
01162 LoadPortals (portalfile);
01163
01164 if (mergevis)
01165 {
01166 MergeLeaves();
01167 MergeLeafPortals();
01168 }
01169
01170 CountActivePortals();
01171
01172
01173 _printf ("visdatasize:%i\n", numVisBytes);
01174
01175 CalcVis ();
01176
01177
01178
01179
01180 if ( !saveprt ) {
01181 remove( portalfile );
01182 }
01183
01184
01185 _printf ("writing %s\n", name);
01186 WriteBSPFile (name);
01187
01188 #ifdef MREDEBUG
01189 end = clock();
01190 _printf ("%5.2f seconds elapsed\n", (end-start) / CLK_TCK);
01191 #else
01192 end = I_FloatTime ();
01193 _printf ("%5.2f seconds elapsed\n", end-start);
01194 #endif
01195 return 0;
01196 }
01197