vis.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // vis.c
  19. #include "vis.h"
  20. #include "threads.h"
  21. #include "stdlib.h"
  22. #ifdef _WIN32
  23. #include "../libs/pakstuff.h"
  24. #endif
  25. #define VIS_HEADER_SIZE 8
  26. extern char outbase[32];
  27. int numportals;
  28. int portalclusters;
  29. int numfaces;
  30. char inbase[32];
  31. vportal_t *portals;
  32. leaf_t *leafs;
  33. vportal_t *faces;
  34. leaf_t *faceleafs;
  35. int c_portaltest, c_portalpass, c_portalcheck;
  36. int leafbytes; // (portalclusters+63)>>3
  37. int leaflongs;
  38. int portalbytes, portallongs;
  39. qboolean fastvis;
  40. qboolean noPassageVis;
  41. qboolean passageVisOnly;
  42. qboolean mergevis;
  43. qboolean nosort;
  44. qboolean saveprt;
  45. int testlevel = 2;
  46. int totalvis;
  47. vportal_t *sorted_portals[MAX_MAP_PORTALS*2];
  48. void PassageMemory(void);
  49. //=============================================================================
  50. void PlaneFromWinding (winding_t *w, plane_t *plane)
  51. {
  52. vec3_t v1, v2;
  53. // calc plane
  54. VectorSubtract (w->points[2], w->points[1], v1);
  55. VectorSubtract (w->points[0], w->points[1], v2);
  56. CrossProduct (v2, v1, plane->normal);
  57. VectorNormalize (plane->normal, plane->normal);
  58. plane->dist = DotProduct (w->points[0], plane->normal);
  59. }
  60. /*
  61. ==================
  62. NewWinding
  63. ==================
  64. */
  65. winding_t *NewWinding (int points)
  66. {
  67. winding_t *w;
  68. int size;
  69. if (points > MAX_POINTS_ON_WINDING)
  70. Error ("NewWinding: %i points", points);
  71. size = (int)((winding_t *)0)->points[points];
  72. w = malloc (size);
  73. memset (w, 0, size);
  74. return w;
  75. }
  76. void prl(leaf_t *l)
  77. {
  78. int i;
  79. vportal_t *p;
  80. plane_t pl;
  81. for (i=0 ; i<l->numportals ; i++)
  82. {
  83. p = l->portals[i];
  84. pl = p->plane;
  85. _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]);
  86. }
  87. }
  88. //=============================================================================
  89. /*
  90. =============
  91. SortPortals
  92. Sorts the portals from the least complex, so the later ones can reuse
  93. the earlier information.
  94. =============
  95. */
  96. int PComp (const void *a, const void *b)
  97. {
  98. if ( (*(vportal_t **)a)->nummightsee == (*(vportal_t **)b)->nummightsee)
  99. return 0;
  100. if ( (*(vportal_t **)a)->nummightsee < (*(vportal_t **)b)->nummightsee)
  101. return -1;
  102. return 1;
  103. }
  104. void SortPortals (void)
  105. {
  106. int i;
  107. for (i=0 ; i<numportals*2 ; i++)
  108. sorted_portals[i] = &portals[i];
  109. if (nosort)
  110. return;
  111. qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
  112. }
  113. /*
  114. ==============
  115. LeafVectorFromPortalVector
  116. ==============
  117. */
  118. int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
  119. {
  120. int i, j, leafnum;
  121. vportal_t *p;
  122. int c_leafs;
  123. for (i=0 ; i<numportals*2 ; i++)
  124. {
  125. if (portalbits[i>>3] & (1<<(i&7)) )
  126. {
  127. p = portals+i;
  128. leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
  129. }
  130. }
  131. for (j = 0; j < portalclusters; j++)
  132. {
  133. leafnum = j;
  134. while (leafs[leafnum].merged >= 0)
  135. leafnum = leafs[leafnum].merged;
  136. //if the merged leaf is visible then the original leaf is visible
  137. if (leafbits[leafnum>>3] & (1<<(leafnum&7)))
  138. {
  139. leafbits[j>>3] |= (1<<(j&7));
  140. }
  141. }
  142. c_leafs = CountBits (leafbits, portalclusters);
  143. return c_leafs;
  144. }
  145. /*
  146. ===============
  147. ClusterMerge
  148. Merges the portal visibility for a leaf
  149. ===============
  150. */
  151. void ClusterMerge (int leafnum)
  152. {
  153. leaf_t *leaf;
  154. byte portalvector[MAX_PORTALS/8];
  155. byte uncompressed[MAX_MAP_LEAFS/8];
  156. int i, j;
  157. int numvis, mergedleafnum;
  158. vportal_t *p;
  159. int pnum;
  160. // OR together all the portalvis bits
  161. mergedleafnum = leafnum;
  162. while(leafs[mergedleafnum].merged >= 0)
  163. mergedleafnum = leafs[mergedleafnum].merged;
  164. memset (portalvector, 0, portalbytes);
  165. leaf = &leafs[mergedleafnum];
  166. for (i = 0; i < leaf->numportals; i++)
  167. {
  168. p = leaf->portals[i];
  169. if (p->removed)
  170. continue;
  171. if (p->status != stat_done)
  172. Error ("portal not done");
  173. for (j=0 ; j<portallongs ; j++)
  174. ((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
  175. pnum = p - portals;
  176. portalvector[pnum>>3] |= 1<<(pnum&7);
  177. }
  178. memset (uncompressed, 0, leafbytes);
  179. uncompressed[mergedleafnum>>3] |= (1<<(mergedleafnum&7));
  180. // convert portal bits to leaf bits
  181. numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
  182. // if (uncompressed[leafnum>>3] & (1<<(leafnum&7)))
  183. // _printf ("WARNING: Leaf portals saw into leaf\n");
  184. // uncompressed[leafnum>>3] |= (1<<(leafnum&7));
  185. numvis++; // count the leaf itself
  186. totalvis += numvis;
  187. qprintf ("cluster %4i : %4i visible\n", leafnum, numvis);
  188. memcpy (visBytes + VIS_HEADER_SIZE + leafnum*leafbytes, uncompressed, leafbytes);
  189. }
  190. /*
  191. ==================
  192. CalcPortalVis
  193. ==================
  194. */
  195. void CalcPortalVis (void)
  196. {
  197. #ifdef MREDEBUG
  198. _printf("%6d portals out of %d", 0, numportals*2);
  199. //get rid of the counter
  200. RunThreadsOnIndividual (numportals*2, qfalse, PortalFlow);
  201. #else
  202. RunThreadsOnIndividual (numportals*2, qtrue, PortalFlow);
  203. #endif
  204. }
  205. /*
  206. ==================
  207. CalcPassageVis
  208. ==================
  209. */
  210. void CalcPassageVis(void)
  211. {
  212. PassageMemory();
  213. #ifdef MREDEBUG
  214. _printf("%6d portals out of %d", 0, numportals*2);
  215. RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages);
  216. _printf("\n");
  217. _printf("%6d portals out of %d", 0, numportals*2);
  218. RunThreadsOnIndividual (numportals*2, qfalse, PassageFlow);
  219. _printf("\n");
  220. #else
  221. RunThreadsOnIndividual (numportals*2, qtrue, CreatePassages);
  222. RunThreadsOnIndividual (numportals*2, qtrue, PassageFlow);
  223. #endif
  224. }
  225. /*
  226. ==================
  227. CalcPassagePortalVis
  228. ==================
  229. */
  230. void CalcPassagePortalVis(void)
  231. {
  232. PassageMemory();
  233. #ifdef MREDEBUG
  234. _printf("%6d portals out of %d", 0, numportals*2);
  235. RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages);
  236. _printf("\n");
  237. _printf("%6d portals out of %d", 0, numportals*2);
  238. RunThreadsOnIndividual (numportals*2, qfalse, PassagePortalFlow);
  239. _printf("\n");
  240. #else
  241. RunThreadsOnIndividual (numportals*2, qtrue, CreatePassages);
  242. RunThreadsOnIndividual (numportals*2, qtrue, PassagePortalFlow);
  243. #endif
  244. }
  245. /*
  246. ==================
  247. CalcFastVis
  248. ==================
  249. */
  250. void CalcFastVis(void)
  251. {
  252. int i;
  253. // fastvis just uses mightsee for a very loose bound
  254. for (i=0 ; i<numportals*2 ; i++)
  255. {
  256. portals[i].portalvis = portals[i].portalflood;
  257. portals[i].status = stat_done;
  258. }
  259. }
  260. /*
  261. ==================
  262. CalcVis
  263. ==================
  264. */
  265. void CalcVis (void)
  266. {
  267. int i;
  268. RunThreadsOnIndividual (numportals*2, qtrue, BasePortalVis);
  269. // RunThreadsOnIndividual (numportals*2, qtrue, BetterPortalVis);
  270. SortPortals ();
  271. if (fastvis) {
  272. CalcFastVis();
  273. }
  274. else if ( noPassageVis ) {
  275. CalcPortalVis();
  276. }
  277. else if ( passageVisOnly ) {
  278. CalcPassageVis();
  279. }
  280. else {
  281. CalcPassagePortalVis();
  282. }
  283. //
  284. // assemble the leaf vis lists by oring and compressing the portal lists
  285. //
  286. _printf("creating leaf vis...\n");
  287. for (i=0 ; i<portalclusters ; i++)
  288. ClusterMerge (i);
  289. _printf( "Total visible clusters: %i\n", totalvis );
  290. _printf( "Average clusters visible: %i\n", totalvis / portalclusters );
  291. }
  292. /*
  293. ==================
  294. SetPortalSphere
  295. ==================
  296. */
  297. void SetPortalSphere (vportal_t *p)
  298. {
  299. int i;
  300. vec3_t total, dist;
  301. winding_t *w;
  302. float r, bestr;
  303. w = p->winding;
  304. VectorCopy (vec3_origin, total);
  305. for (i=0 ; i<w->numpoints ; i++)
  306. {
  307. VectorAdd (total, w->points[i], total);
  308. }
  309. for (i=0 ; i<3 ; i++)
  310. total[i] /= w->numpoints;
  311. bestr = 0;
  312. for (i=0 ; i<w->numpoints ; i++)
  313. {
  314. VectorSubtract (w->points[i], total, dist);
  315. r = VectorLength (dist);
  316. if (r > bestr)
  317. bestr = r;
  318. }
  319. VectorCopy (total, p->origin);
  320. p->radius = bestr;
  321. }
  322. /*
  323. =============
  324. Winding_PlanesConcave
  325. =============
  326. */
  327. #define WCONVEX_EPSILON 0.2
  328. int Winding_PlanesConcave(winding_t *w1, winding_t *w2,
  329. vec3_t normal1, vec3_t normal2,
  330. float dist1, float dist2)
  331. {
  332. int i;
  333. if (!w1 || !w2) return qfalse;
  334. // check if one of the points of winding 1 is at the front of the plane of winding 2
  335. for (i = 0; i < w1->numpoints; i++)
  336. {
  337. if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return qtrue;
  338. }
  339. // check if one of the points of winding 2 is at the front of the plane of winding 1
  340. for (i = 0; i < w2->numpoints; i++)
  341. {
  342. if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return qtrue;
  343. }
  344. return qfalse;
  345. }
  346. /*
  347. ============
  348. TryMergeLeaves
  349. ============
  350. */
  351. int TryMergeLeaves(int l1num, int l2num)
  352. {
  353. int i, j, k, n, numportals;
  354. plane_t plane1, plane2;
  355. leaf_t *l1, *l2;
  356. vportal_t *p1, *p2;
  357. vportal_t *portals[MAX_PORTALS_ON_LEAF];
  358. for (k = 0; k < 2; k++)
  359. {
  360. if (k) l1 = &leafs[l1num];
  361. else l1 = &faceleafs[l1num];
  362. for (i = 0; i < l1->numportals; i++)
  363. {
  364. p1 = l1->portals[i];
  365. if (p1->leaf == l2num) continue;
  366. for (n = 0; n < 2; n++)
  367. {
  368. if (n) l2 = &leafs[l2num];
  369. else l2 = &faceleafs[l2num];
  370. for (j = 0; j < l2->numportals; j++)
  371. {
  372. p2 = l2->portals[j];
  373. if (p2->leaf == l1num) continue;
  374. //
  375. plane1 = p1->plane;
  376. plane2 = p2->plane;
  377. if (Winding_PlanesConcave(p1->winding, p2->winding, plane1.normal, plane2.normal, plane1.dist, plane2.dist))
  378. return qfalse;
  379. }
  380. }
  381. }
  382. }
  383. for (k = 0; k < 2; k++)
  384. {
  385. if (k)
  386. {
  387. l1 = &leafs[l1num];
  388. l2 = &leafs[l2num];
  389. }
  390. else
  391. {
  392. l1 = &faceleafs[l1num];
  393. l2 = &faceleafs[l2num];
  394. }
  395. numportals = 0;
  396. //the leaves can be merged now
  397. for (i = 0; i < l1->numportals; i++)
  398. {
  399. p1 = l1->portals[i];
  400. if (p1->leaf == l2num)
  401. {
  402. p1->removed = qtrue;
  403. continue;
  404. }
  405. portals[numportals++] = p1;
  406. }
  407. for (j = 0; j < l2->numportals; j++)
  408. {
  409. p2 = l2->portals[j];
  410. if (p2->leaf == l1num)
  411. {
  412. p2->removed = qtrue;
  413. continue;
  414. }
  415. portals[numportals++] = p2;
  416. }
  417. for (i = 0; i < numportals; i++)
  418. {
  419. l2->portals[i] = portals[i];
  420. }
  421. l2->numportals = numportals;
  422. l1->merged = l2num;
  423. }
  424. return qtrue;
  425. }
  426. /*
  427. ============
  428. UpdatePortals
  429. ============
  430. */
  431. void UpdatePortals(void)
  432. {
  433. int i;
  434. vportal_t *p;
  435. for (i = 0; i < numportals * 2; i++)
  436. {
  437. p = &portals[i];
  438. if (p->removed)
  439. continue;
  440. while(leafs[p->leaf].merged >= 0)
  441. p->leaf = leafs[p->leaf].merged;
  442. }
  443. }
  444. /*
  445. ============
  446. MergeLeaves
  447. try to merge leaves but don't merge through hint splitters
  448. ============
  449. */
  450. void MergeLeaves(void)
  451. {
  452. int i, j, nummerges, totalnummerges;
  453. leaf_t *leaf;
  454. vportal_t *p;
  455. totalnummerges = 0;
  456. do
  457. {
  458. nummerges = 0;
  459. for (i = 0; i < portalclusters; i++)
  460. {
  461. leaf = &leafs[i];
  462. //if this leaf is merged already
  463. if (leaf->merged >= 0)
  464. continue;
  465. //
  466. for (j = 0; j < leaf->numportals; j++)
  467. {
  468. p = leaf->portals[j];
  469. //
  470. if (p->removed)
  471. continue;
  472. //never merge through hint portals
  473. if (p->hint)
  474. continue;
  475. if (TryMergeLeaves(i, p->leaf))
  476. {
  477. UpdatePortals();
  478. nummerges++;
  479. break;
  480. }
  481. }
  482. }
  483. totalnummerges += nummerges;
  484. } while (nummerges);
  485. _printf("%6d leaves merged\n", totalnummerges);
  486. }
  487. /*
  488. ============
  489. TryMergeWinding
  490. ============
  491. */
  492. #define CONTINUOUS_EPSILON 0.005
  493. winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal)
  494. {
  495. vec_t *p1, *p2, *p3, *p4, *back;
  496. winding_t *newf;
  497. int i, j, k, l;
  498. vec3_t normal, delta;
  499. vec_t dot;
  500. qboolean keep1, keep2;
  501. //
  502. // find a common edge
  503. //
  504. p1 = p2 = NULL; // stop compiler warning
  505. j = 0; //
  506. for (i = 0; i < f1->numpoints; i++)
  507. {
  508. p1 = f1->points[i];
  509. p2 = f1->points[(i+1) % f1->numpoints];
  510. for (j = 0; j < f2->numpoints; j++)
  511. {
  512. p3 = f2->points[j];
  513. p4 = f2->points[(j+1) % f2->numpoints];
  514. for (k = 0; k < 3; k++)
  515. {
  516. if (fabs(p1[k] - p4[k]) > 0.1)//EQUAL_EPSILON) //ME
  517. break;
  518. if (fabs(p2[k] - p3[k]) > 0.1)//EQUAL_EPSILON) //ME
  519. break;
  520. } //end for
  521. if (k==3)
  522. break;
  523. } //end for
  524. if (j < f2->numpoints)
  525. break;
  526. } //end for
  527. if (i == f1->numpoints)
  528. return NULL; // no matching edges
  529. //
  530. // check slope of connected lines
  531. // if the slopes are colinear, the point can be removed
  532. //
  533. back = f1->points[(i+f1->numpoints-1)%f1->numpoints];
  534. VectorSubtract (p1, back, delta);
  535. CrossProduct (planenormal, delta, normal);
  536. VectorNormalize (normal, normal);
  537. back = f2->points[(j+2)%f2->numpoints];
  538. VectorSubtract (back, p1, delta);
  539. dot = DotProduct (delta, normal);
  540. if (dot > CONTINUOUS_EPSILON)
  541. return NULL; // not a convex polygon
  542. keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
  543. back = f1->points[(i+2)%f1->numpoints];
  544. VectorSubtract (back, p2, delta);
  545. CrossProduct (planenormal, delta, normal);
  546. VectorNormalize (normal, normal);
  547. back = f2->points[(j+f2->numpoints-1)%f2->numpoints];
  548. VectorSubtract (back, p2, delta);
  549. dot = DotProduct (delta, normal);
  550. if (dot > CONTINUOUS_EPSILON)
  551. return NULL; // not a convex polygon
  552. keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
  553. //
  554. // build the new polygon
  555. //
  556. newf = NewWinding (f1->numpoints + f2->numpoints);
  557. // copy first polygon
  558. for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
  559. {
  560. if (k==(i+1)%f1->numpoints && !keep2)
  561. continue;
  562. VectorCopy (f1->points[k], newf->points[newf->numpoints]);
  563. newf->numpoints++;
  564. }
  565. // copy second polygon
  566. for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
  567. {
  568. if (l==(j+1)%f2->numpoints && !keep1)
  569. continue;
  570. VectorCopy (f2->points[l], newf->points[newf->numpoints]);
  571. newf->numpoints++;
  572. }
  573. return newf;
  574. }
  575. /*
  576. ============
  577. MergeLeafPortals
  578. ============
  579. */
  580. void MergeLeafPortals(void)
  581. {
  582. int i, j, k, nummerges, hintsmerged;
  583. leaf_t *leaf;
  584. vportal_t *p1, *p2;
  585. winding_t *w;
  586. nummerges = 0;
  587. hintsmerged = 0;
  588. for (i = 0; i < portalclusters; i++)
  589. {
  590. leaf = &leafs[i];
  591. if (leaf->merged >= 0) continue;
  592. for (j = 0; j < leaf->numportals; j++)
  593. {
  594. p1 = leaf->portals[j];
  595. if (p1->removed)
  596. continue;
  597. for (k = j+1; k < leaf->numportals; k++)
  598. {
  599. p2 = leaf->portals[k];
  600. if (p2->removed)
  601. continue;
  602. if (p1->leaf == p2->leaf)
  603. {
  604. w = TryMergeWinding(p1->winding, p2->winding, p1->plane.normal);
  605. if (w)
  606. {
  607. FreeWinding(p1->winding);
  608. p1->winding = w;
  609. if (p1->hint && p2->hint)
  610. hintsmerged++;
  611. p1->hint |= p2->hint;
  612. SetPortalSphere(p1);
  613. p2->removed = qtrue;
  614. nummerges++;
  615. i--;
  616. break;
  617. }
  618. }
  619. }
  620. if (k < leaf->numportals)
  621. break;
  622. }
  623. }
  624. _printf("%6d portals merged\n", nummerges);
  625. _printf("%6d hint portals merged\n", hintsmerged);
  626. }
  627. /*
  628. ============
  629. WritePortals
  630. ============
  631. */
  632. int CountActivePortals(void)
  633. {
  634. int num, hints, j;
  635. vportal_t *p;
  636. num = 0;
  637. hints = 0;
  638. for (j = 0; j < numportals * 2; j++)
  639. {
  640. p = portals + j;
  641. if (p->removed)
  642. continue;
  643. if (p->hint)
  644. hints++;
  645. num++;
  646. }
  647. _printf("%6d active portals\n", num);
  648. _printf("%6d hint portals\n", hints);
  649. return num;
  650. }
  651. /*
  652. ============
  653. WritePortals
  654. ============
  655. */
  656. void WriteFloat (FILE *f, vec_t v);
  657. void WritePortals(char *filename)
  658. {
  659. int i, j, num;
  660. FILE *pf;
  661. vportal_t *p;
  662. winding_t *w;
  663. // write the file
  664. pf = fopen (filename, "w");
  665. if (!pf)
  666. Error ("Error opening %s", filename);
  667. num = 0;
  668. for (j = 0; j < numportals * 2; j++)
  669. {
  670. p = portals + j;
  671. if (p->removed)
  672. continue;
  673. // if (!p->hint)
  674. // continue;
  675. num++;
  676. }
  677. fprintf (pf, "%s\n", PORTALFILE);
  678. fprintf (pf, "%i\n", 0);
  679. fprintf (pf, "%i\n", num);// + numfaces);
  680. fprintf (pf, "%i\n", 0);
  681. for (j = 0; j < numportals * 2; j++)
  682. {
  683. p = portals + j;
  684. if (p->removed)
  685. continue;
  686. // if (!p->hint)
  687. // continue;
  688. w = p->winding;
  689. fprintf (pf,"%i %i %i ",w->numpoints, 0, 0);
  690. fprintf (pf, "%d ", p->hint);
  691. for (i=0 ; i<w->numpoints ; i++)
  692. {
  693. fprintf (pf,"(");
  694. WriteFloat (pf, w->points[i][0]);
  695. WriteFloat (pf, w->points[i][1]);
  696. WriteFloat (pf, w->points[i][2]);
  697. fprintf (pf,") ");
  698. }
  699. fprintf (pf,"\n");
  700. }
  701. /*
  702. for (j = 0; j < numfaces; j++)
  703. {
  704. p = faces + j;
  705. w = p->winding;
  706. fprintf (pf,"%i %i %i ",w->numpoints, 0, 0);
  707. fprintf (pf, "0 ");
  708. for (i=0 ; i<w->numpoints ; i++)
  709. {
  710. fprintf (pf,"(");
  711. WriteFloat (pf, w->points[i][0]);
  712. WriteFloat (pf, w->points[i][1]);
  713. WriteFloat (pf, w->points[i][2]);
  714. fprintf (pf,") ");
  715. }
  716. fprintf (pf,"\n");
  717. }*/
  718. fclose (pf);
  719. }
  720. /*
  721. ============
  722. LoadPortals
  723. ============
  724. */
  725. void LoadPortals (char *name)
  726. {
  727. int i, j, hint;
  728. vportal_t *p;
  729. leaf_t *l;
  730. char magic[80];
  731. FILE *f;
  732. int numpoints;
  733. winding_t *w;
  734. int leafnums[2];
  735. plane_t plane;
  736. if (!strcmp(name,"-"))
  737. f = stdin;
  738. else
  739. {
  740. f = fopen(name, "r");
  741. if (!f)
  742. Error ("LoadPortals: couldn't read %s\n",name);
  743. }
  744. if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4)
  745. Error ("LoadPortals: failed to read header");
  746. if (strcmp(magic,PORTALFILE))
  747. Error ("LoadPortals: not a portal file");
  748. _printf ("%6i portalclusters\n", portalclusters);
  749. _printf ("%6i numportals\n", numportals);
  750. _printf ("%6i numfaces\n", numfaces);
  751. // these counts should take advantage of 64 bit systems automatically
  752. leafbytes = ((portalclusters+63)&~63)>>3;
  753. leaflongs = leafbytes/sizeof(long);
  754. portalbytes = ((numportals*2+63)&~63)>>3;
  755. portallongs = portalbytes/sizeof(long);
  756. // each file portal is split into two memory portals
  757. portals = malloc(2*numportals*sizeof(vportal_t));
  758. memset (portals, 0, 2*numportals*sizeof(vportal_t));
  759. leafs = malloc(portalclusters*sizeof(leaf_t));
  760. memset (leafs, 0, portalclusters*sizeof(leaf_t));
  761. for (i = 0; i < portalclusters; i++)
  762. leafs[i].merged = -1;
  763. numVisBytes = VIS_HEADER_SIZE + portalclusters*leafbytes;
  764. ((int *)visBytes)[0] = portalclusters;
  765. ((int *)visBytes)[1] = leafbytes;
  766. for (i=0, p=portals ; i<numportals ; i++)
  767. {
  768. if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3)
  769. Error ("LoadPortals: reading portal %i", i);
  770. if (numpoints > MAX_POINTS_ON_WINDING)
  771. Error ("LoadPortals: portal %i has too many points", i);
  772. if ( (unsigned)leafnums[0] > portalclusters
  773. || (unsigned)leafnums[1] > portalclusters)
  774. Error ("LoadPortals: reading portal %i", i);
  775. if (fscanf (f, "%i ", &hint) != 1)
  776. Error ("LoadPortals: reading hint state");
  777. w = p->winding = NewWinding (numpoints);
  778. w->numpoints = numpoints;
  779. for (j=0 ; j<numpoints ; j++)
  780. {
  781. double v[3];
  782. int k;
  783. // scanf into double, then assign to vec_t
  784. // so we don't care what size vec_t is
  785. if (fscanf (f, "(%lf %lf %lf ) "
  786. , &v[0], &v[1], &v[2]) != 3)
  787. Error ("LoadPortals: reading portal %i", i);
  788. for (k=0 ; k<3 ; k++)
  789. w->points[j][k] = v[k];
  790. }
  791. fscanf (f, "\n");
  792. // calc plane
  793. PlaneFromWinding (w, &plane);
  794. // create forward portal
  795. l = &leafs[leafnums[0]];
  796. if (l->numportals == MAX_PORTALS_ON_LEAF)
  797. Error ("Leaf with too many portals");
  798. l->portals[l->numportals] = p;
  799. l->numportals++;
  800. p->num = i+1;
  801. p->hint = hint;
  802. p->winding = w;
  803. VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
  804. p->plane.dist = -plane.dist;
  805. p->leaf = leafnums[1];
  806. SetPortalSphere (p);
  807. p++;
  808. // create backwards portal
  809. l = &leafs[leafnums[1]];
  810. if (l->numportals == MAX_PORTALS_ON_LEAF)
  811. Error ("Leaf with too many portals");
  812. l->portals[l->numportals] = p;
  813. l->numportals++;
  814. p->num = i+1;
  815. p->hint = hint;
  816. p->winding = NewWinding(w->numpoints);
  817. p->winding->numpoints = w->numpoints;
  818. for (j=0 ; j<w->numpoints ; j++)
  819. {
  820. VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
  821. }
  822. p->plane = plane;
  823. p->leaf = leafnums[0];
  824. SetPortalSphere (p);
  825. p++;
  826. }
  827. faces = malloc(2*numfaces*sizeof(vportal_t));
  828. memset (faces, 0, 2*numfaces*sizeof(vportal_t));
  829. faceleafs = malloc(portalclusters*sizeof(leaf_t));
  830. memset(faceleafs, 0, portalclusters*sizeof(leaf_t));
  831. for (i = 0, p = faces; i < numfaces; i++)
  832. {
  833. if (fscanf (f, "%i %i ", &numpoints, &leafnums[0]) != 2)
  834. Error ("LoadPortals: reading portal %i", i);
  835. w = p->winding = NewWinding (numpoints);
  836. w->numpoints = numpoints;
  837. for (j=0 ; j<numpoints ; j++)
  838. {
  839. double v[3];
  840. int k;
  841. // scanf into double, then assign to vec_t
  842. // so we don't care what size vec_t is
  843. if (fscanf (f, "(%lf %lf %lf ) "
  844. , &v[0], &v[1], &v[2]) != 3)
  845. Error ("LoadPortals: reading portal %i", i);
  846. for (k=0 ; k<3 ; k++)
  847. w->points[j][k] = v[k];
  848. }
  849. fscanf (f, "\n");
  850. // calc plane
  851. PlaneFromWinding (w, &plane);
  852. l = &faceleafs[leafnums[0]];
  853. l->merged = -1;
  854. if (l->numportals == MAX_PORTALS_ON_LEAF)
  855. Error ("Leaf with too many faces");
  856. l->portals[l->numportals] = p;
  857. l->numportals++;
  858. p->num = i+1;
  859. p->winding = w;
  860. // normal pointing out of the leaf
  861. VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
  862. p->plane.dist = -plane.dist;
  863. p->leaf = -1;
  864. SetPortalSphere (p);
  865. p++;
  866. }
  867. fclose (f);
  868. }
  869. /*
  870. ================
  871. CalcPHS
  872. Calculate the PHS (Potentially Hearable Set)
  873. by ORing together all the PVS visible from a leaf
  874. ================
  875. */
  876. void CalcPHS (void)
  877. {
  878. int i, j, k, l, index;
  879. int bitbyte;
  880. long *dest, *src;
  881. byte *scan;
  882. int count;
  883. byte uncompressed[MAX_MAP_LEAFS/8];
  884. _printf ("Building PHS...\n");
  885. count = 0;
  886. for (i=0 ; i<portalclusters ; i++)
  887. {
  888. scan = visBytes + i*leafbytes;
  889. memcpy (uncompressed, scan, leafbytes);
  890. for (j=0 ; j<leafbytes ; j++)
  891. {
  892. bitbyte = scan[j];
  893. if (!bitbyte)
  894. continue;
  895. for (k=0 ; k<8 ; k++)
  896. {
  897. if (! (bitbyte & (1<<k)) )
  898. continue;
  899. // OR this pvs row into the phs
  900. index = ((j<<3)+k);
  901. if (index >= portalclusters)
  902. Error ("Bad bit in PVS"); // pad bits should be 0
  903. src = (long *)(visBytes + index*leafbytes);
  904. dest = (long *)uncompressed;
  905. for (l=0 ; l<leaflongs ; l++)
  906. ((long *)uncompressed)[l] |= src[l];
  907. }
  908. }
  909. for (j=0 ; j<portalclusters ; j++)
  910. if (uncompressed[j>>3] & (1<<(j&7)) )
  911. count++;
  912. // FIXME: copy it off
  913. }
  914. _printf ("Average clusters hearable: %i\n", count/portalclusters);
  915. }
  916. /*
  917. ===========
  918. VisMain
  919. ===========
  920. */
  921. int VisMain (int argc, char **argv)
  922. {
  923. char portalfile[1024];
  924. char name[1024];
  925. int i;
  926. double start, end;
  927. _printf ("---- vis ----\n");
  928. verbose = qfalse;
  929. for (i=1 ; i<argc ; i++) {
  930. if (!strcmp(argv[i],"-threads")) {
  931. numthreads = atoi (argv[i+1]);
  932. i++;
  933. } else if (!strcmp(argv[i],"-threads")) {
  934. numthreads = atoi (argv[i+1]);
  935. i++;
  936. } else if (!strcmp(argv[i], "-fast")) {
  937. _printf ("fastvis = true\n");
  938. fastvis = qtrue;
  939. } else if (!strcmp(argv[i], "-merge")) {
  940. _printf ("merge = true\n");
  941. mergevis = qtrue;
  942. } else if (!strcmp(argv[i], "-nopassage")) {
  943. _printf ("nopassage = true\n");
  944. noPassageVis = qtrue;
  945. } else if (!strcmp(argv[i], "-passageOnly")) {
  946. _printf("passageOnly = true\n");
  947. passageVisOnly = qtrue;
  948. } else if (!strcmp(argv[i], "-level")) {
  949. testlevel = atoi(argv[i+1]);
  950. _printf ("testlevel = %i\n", testlevel);
  951. i++;
  952. } else if (!strcmp(argv[i], "-v")) {
  953. _printf ("verbose = true\n");
  954. verbose = qtrue;
  955. } else if (!strcmp (argv[i],"-nosort")) {
  956. _printf ("nosort = true\n");
  957. nosort = qtrue;
  958. } else if (!strcmp (argv[i],"-saveprt")) {
  959. _printf ("saveprt = true\n");
  960. saveprt = qtrue;
  961. } else if (!strcmp (argv[i],"-tmpin")) {
  962. strcpy (inbase, "/tmp");
  963. } else if (!strcmp (argv[i],"-tmpout")) {
  964. strcpy (outbase, "/tmp");
  965. } else if (argv[i][0] == '-') {
  966. Error ("Unknown option \"%s\"", argv[i]);
  967. } else {
  968. break;
  969. }
  970. }
  971. if (i != argc - 1)
  972. Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");
  973. #ifdef MREDEBUG
  974. start = clock();
  975. #else
  976. start = I_FloatTime ();
  977. #endif
  978. ThreadSetDefault ();
  979. SetQdirFromPath (argv[i]);
  980. #ifdef _WIN32
  981. InitPakFile(gamedir, NULL);
  982. #endif
  983. // load the bsp
  984. sprintf (name, "%s%s", inbase, ExpandArg(argv[i]));
  985. StripExtension (name);
  986. strcat (name, ".bsp");
  987. _printf ("reading %s\n", name);
  988. LoadBSPFile (name);
  989. // load the portal file
  990. sprintf (portalfile, "%s%s", inbase, ExpandArg(argv[i]));
  991. StripExtension (portalfile);
  992. strcat (portalfile, ".prt");
  993. _printf ("reading %s\n", portalfile);
  994. LoadPortals (portalfile);
  995. if (mergevis)
  996. {
  997. MergeLeaves();
  998. MergeLeafPortals();
  999. }
  1000. CountActivePortals();
  1001. // WritePortals("maps/hints.prs");
  1002. _printf ("visdatasize:%i\n", numVisBytes);
  1003. CalcVis ();
  1004. // CalcPHS ();
  1005. // delete the prt file
  1006. if ( !saveprt ) {
  1007. remove( portalfile );
  1008. }
  1009. // write the bsp file
  1010. _printf ("writing %s\n", name);
  1011. WriteBSPFile (name);
  1012. #ifdef MREDEBUG
  1013. end = clock();
  1014. _printf ("%5.2f seconds elapsed\n", (end-start) / CLK_TCK);
  1015. #else
  1016. end = I_FloatTime ();
  1017. _printf ("%5.2f seconds elapsed\n", end-start);
  1018. #endif
  1019. return 0;
  1020. }