qvis3.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1997-2006 Id Software, Inc.
  4. This file is part of Quake 2 Tools source code.
  5. Quake 2 Tools 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 2 Tools 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 Quake 2 Tools source code; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "vis.h"
  19. #include "threads.h"
  20. #include "stdlib.h"
  21. int numportals;
  22. int portalclusters;
  23. char inbase[32];
  24. char outbase[32];
  25. portal_t *portals;
  26. leaf_t *leafs;
  27. int c_portaltest, c_portalpass, c_portalcheck;
  28. byte *uncompressedvis;
  29. byte *vismap, *vismap_p, *vismap_end; // past visfile
  30. int originalvismapsize;
  31. int leafbytes; // (portalclusters+63)>>3
  32. int leaflongs;
  33. int portalbytes, portallongs;
  34. qboolean fastvis;
  35. qboolean nosort;
  36. int testlevel = 2;
  37. int totalvis;
  38. portal_t *sorted_portals[MAX_MAP_PORTALS*2];
  39. //=============================================================================
  40. void PlaneFromWinding (winding_t *w, plane_t *plane)
  41. {
  42. vec3_t v1, v2;
  43. // calc plane
  44. VectorSubtract (w->points[2], w->points[1], v1);
  45. VectorSubtract (w->points[0], w->points[1], v2);
  46. CrossProduct (v2, v1, plane->normal);
  47. VectorNormalize (plane->normal, plane->normal);
  48. plane->dist = DotProduct (w->points[0], plane->normal);
  49. }
  50. /*
  51. ==================
  52. NewWinding
  53. ==================
  54. */
  55. winding_t *NewWinding (int points)
  56. {
  57. winding_t *w;
  58. int size;
  59. if (points > MAX_POINTS_ON_WINDING)
  60. Error ("NewWinding: %i points", points);
  61. size = (int)((winding_t *)0)->points[points];
  62. w = malloc (size);
  63. memset (w, 0, size);
  64. return w;
  65. }
  66. void pw(winding_t *w)
  67. {
  68. int i;
  69. for (i=0 ; i<w->numpoints ; i++)
  70. printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]);
  71. }
  72. void prl(leaf_t *l)
  73. {
  74. int i;
  75. portal_t *p;
  76. plane_t pl;
  77. for (i=0 ; i<l->numportals ; i++)
  78. {
  79. p = l->portals[i];
  80. pl = p->plane;
  81. 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]);
  82. }
  83. }
  84. //=============================================================================
  85. /*
  86. =============
  87. SortPortals
  88. Sorts the portals from the least complex, so the later ones can reuse
  89. the earlier information.
  90. =============
  91. */
  92. int PComp (const void *a, const void *b)
  93. {
  94. if ( (*(portal_t **)a)->nummightsee == (*(portal_t **)b)->nummightsee)
  95. return 0;
  96. if ( (*(portal_t **)a)->nummightsee < (*(portal_t **)b)->nummightsee)
  97. return -1;
  98. return 1;
  99. }
  100. void SortPortals (void)
  101. {
  102. int i;
  103. for (i=0 ; i<numportals*2 ; i++)
  104. sorted_portals[i] = &portals[i];
  105. if (nosort)
  106. return;
  107. qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
  108. }
  109. /*
  110. ==============
  111. LeafVectorFromPortalVector
  112. ==============
  113. */
  114. int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
  115. {
  116. int i;
  117. portal_t *p;
  118. int c_leafs;
  119. memset (leafbits, 0, leafbytes);
  120. for (i=0 ; i<numportals*2 ; i++)
  121. {
  122. if (portalbits[i>>3] & (1<<(i&7)) )
  123. {
  124. p = portals+i;
  125. leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
  126. }
  127. }
  128. c_leafs = CountBits (leafbits, portalclusters);
  129. return c_leafs;
  130. }
  131. /*
  132. ===============
  133. ClusterMerge
  134. Merges the portal visibility for a leaf
  135. ===============
  136. */
  137. void ClusterMerge (int leafnum)
  138. {
  139. leaf_t *leaf;
  140. byte portalvector[MAX_PORTALS/8];
  141. byte uncompressed[MAX_MAP_LEAFS/8];
  142. byte compressed[MAX_MAP_LEAFS/8];
  143. int i, j;
  144. int numvis;
  145. byte *dest;
  146. portal_t *p;
  147. int pnum;
  148. // OR together all the portalvis bits
  149. memset (portalvector, 0, portalbytes);
  150. leaf = &leafs[leafnum];
  151. for (i=0 ; i<leaf->numportals ; i++)
  152. {
  153. p = leaf->portals[i];
  154. if (p->status != stat_done)
  155. Error ("portal not done");
  156. for (j=0 ; j<portallongs ; j++)
  157. ((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
  158. pnum = p - portals;
  159. portalvector[pnum>>3] |= 1<<(pnum&7);
  160. }
  161. // convert portal bits to leaf bits
  162. numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
  163. if (uncompressed[leafnum>>3] & (1<<(leafnum&7)))
  164. printf ("WARNING: Leaf portals saw into leaf\n");
  165. uncompressed[leafnum>>3] |= (1<<(leafnum&7));
  166. numvis++; // count the leaf itself
  167. // save uncompressed for PHS calculation
  168. memcpy (uncompressedvis + leafnum*leafbytes, uncompressed, leafbytes);
  169. //
  170. // compress the bit string
  171. //
  172. qprintf ("cluster %4i : %4i visible\n", leafnum, numvis);
  173. totalvis += numvis;
  174. i = CompressVis (uncompressed, compressed);
  175. dest = vismap_p;
  176. vismap_p += i;
  177. if (vismap_p > vismap_end)
  178. Error ("Vismap expansion overflow");
  179. dvis->bitofs[leafnum][DVIS_PVS] = dest-vismap;
  180. memcpy (dest, compressed, i);
  181. }
  182. /*
  183. ==================
  184. CalcPortalVis
  185. ==================
  186. */
  187. void CalcPortalVis (void)
  188. {
  189. int i;
  190. // fastvis just uses mightsee for a very loose bound
  191. if (fastvis)
  192. {
  193. for (i=0 ; i<numportals*2 ; i++)
  194. {
  195. portals[i].portalvis = portals[i].portalflood;
  196. portals[i].status = stat_done;
  197. }
  198. return;
  199. }
  200. RunThreadsOnIndividual (numportals*2, true, PortalFlow);
  201. }
  202. /*
  203. ==================
  204. CalcVis
  205. ==================
  206. */
  207. void CalcVis (void)
  208. {
  209. int i;
  210. RunThreadsOnIndividual (numportals*2, true, BasePortalVis);
  211. // RunThreadsOnIndividual (numportals*2, true, BetterPortalVis);
  212. SortPortals ();
  213. CalcPortalVis ();
  214. //
  215. // assemble the leaf vis lists by oring and compressing the portal lists
  216. //
  217. for (i=0 ; i<portalclusters ; i++)
  218. ClusterMerge (i);
  219. printf ("Average clusters visible: %i\n", totalvis / portalclusters);
  220. }
  221. void SetPortalSphere (portal_t *p)
  222. {
  223. int i;
  224. vec3_t total, dist;
  225. winding_t *w;
  226. float r, bestr;
  227. w = p->winding;
  228. VectorCopy (vec3_origin, total);
  229. for (i=0 ; i<w->numpoints ; i++)
  230. {
  231. VectorAdd (total, w->points[i], total);
  232. }
  233. for (i=0 ; i<3 ; i++)
  234. total[i] /= w->numpoints;
  235. bestr = 0;
  236. for (i=0 ; i<w->numpoints ; i++)
  237. {
  238. VectorSubtract (w->points[i], total, dist);
  239. r = VectorLength (dist);
  240. if (r > bestr)
  241. bestr = r;
  242. }
  243. VectorCopy (total, p->origin);
  244. p->radius = bestr;
  245. }
  246. /*
  247. ============
  248. LoadPortals
  249. ============
  250. */
  251. void LoadPortals (char *name)
  252. {
  253. int i, j;
  254. portal_t *p;
  255. leaf_t *l;
  256. char magic[80];
  257. FILE *f;
  258. int numpoints;
  259. winding_t *w;
  260. int leafnums[2];
  261. plane_t plane;
  262. if (!strcmp(name,"-"))
  263. f = stdin;
  264. else
  265. {
  266. f = fopen(name, "r");
  267. if (!f)
  268. Error ("LoadPortals: couldn't read %s\n",name);
  269. }
  270. if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalclusters, &numportals) != 3)
  271. Error ("LoadPortals: failed to read header");
  272. if (strcmp(magic,PORTALFILE))
  273. Error ("LoadPortals: not a portal file");
  274. printf ("%4i portalclusters\n", portalclusters);
  275. printf ("%4i numportals\n", numportals);
  276. // these counts should take advantage of 64 bit systems automatically
  277. leafbytes = ((portalclusters+63)&~63)>>3;
  278. leaflongs = leafbytes/sizeof(long);
  279. portalbytes = ((numportals*2+63)&~63)>>3;
  280. portallongs = portalbytes/sizeof(long);
  281. // each file portal is split into two memory portals
  282. portals = malloc(2*numportals*sizeof(portal_t));
  283. memset (portals, 0, 2*numportals*sizeof(portal_t));
  284. leafs = malloc(portalclusters*sizeof(leaf_t));
  285. memset (leafs, 0, portalclusters*sizeof(leaf_t));
  286. originalvismapsize = portalclusters*leafbytes;
  287. uncompressedvis = malloc(originalvismapsize);
  288. vismap = vismap_p = dvisdata;
  289. dvis->numclusters = portalclusters;
  290. vismap_p = (byte *)&dvis->bitofs[portalclusters];
  291. vismap_end = vismap + MAX_MAP_VISIBILITY;
  292. for (i=0, p=portals ; i<numportals ; i++)
  293. {
  294. if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
  295. != 3)
  296. Error ("LoadPortals: reading portal %i", i);
  297. if (numpoints > MAX_POINTS_ON_WINDING)
  298. Error ("LoadPortals: portal %i has too many points", i);
  299. if ( (unsigned)leafnums[0] > portalclusters
  300. || (unsigned)leafnums[1] > portalclusters)
  301. Error ("LoadPortals: reading portal %i", i);
  302. w = p->winding = NewWinding (numpoints);
  303. w->original = true;
  304. w->numpoints = numpoints;
  305. for (j=0 ; j<numpoints ; j++)
  306. {
  307. double v[3];
  308. int k;
  309. // scanf into double, then assign to vec_t
  310. // so we don't care what size vec_t is
  311. if (fscanf (f, "(%lf %lf %lf ) "
  312. , &v[0], &v[1], &v[2]) != 3)
  313. Error ("LoadPortals: reading portal %i", i);
  314. for (k=0 ; k<3 ; k++)
  315. w->points[j][k] = v[k];
  316. }
  317. fscanf (f, "\n");
  318. // calc plane
  319. PlaneFromWinding (w, &plane);
  320. // create forward portal
  321. l = &leafs[leafnums[0]];
  322. if (l->numportals == MAX_PORTALS_ON_LEAF)
  323. Error ("Leaf with too many portals");
  324. l->portals[l->numportals] = p;
  325. l->numportals++;
  326. p->winding = w;
  327. VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
  328. p->plane.dist = -plane.dist;
  329. p->leaf = leafnums[1];
  330. SetPortalSphere (p);
  331. p++;
  332. // create backwards portal
  333. l = &leafs[leafnums[1]];
  334. if (l->numportals == MAX_PORTALS_ON_LEAF)
  335. Error ("Leaf with too many portals");
  336. l->portals[l->numportals] = p;
  337. l->numportals++;
  338. p->winding = NewWinding(w->numpoints);
  339. p->winding->numpoints = w->numpoints;
  340. for (j=0 ; j<w->numpoints ; j++)
  341. {
  342. VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
  343. }
  344. p->plane = plane;
  345. p->leaf = leafnums[0];
  346. SetPortalSphere (p);
  347. p++;
  348. }
  349. fclose (f);
  350. }
  351. /*
  352. ================
  353. CalcPHS
  354. Calculate the PHS (Potentially Hearable Set)
  355. by ORing together all the PVS visible from a leaf
  356. ================
  357. */
  358. void CalcPHS (void)
  359. {
  360. int i, j, k, l, index;
  361. int bitbyte;
  362. long *dest, *src;
  363. byte *scan;
  364. int count;
  365. byte uncompressed[MAX_MAP_LEAFS/8];
  366. byte compressed[MAX_MAP_LEAFS/8];
  367. printf ("Building PHS...\n");
  368. count = 0;
  369. for (i=0 ; i<portalclusters ; i++)
  370. {
  371. scan = uncompressedvis + i*leafbytes;
  372. memcpy (uncompressed, scan, leafbytes);
  373. for (j=0 ; j<leafbytes ; j++)
  374. {
  375. bitbyte = scan[j];
  376. if (!bitbyte)
  377. continue;
  378. for (k=0 ; k<8 ; k++)
  379. {
  380. if (! (bitbyte & (1<<k)) )
  381. continue;
  382. // OR this pvs row into the phs
  383. index = ((j<<3)+k);
  384. if (index >= portalclusters)
  385. Error ("Bad bit in PVS"); // pad bits should be 0
  386. src = (long *)(uncompressedvis + index*leafbytes);
  387. dest = (long *)uncompressed;
  388. for (l=0 ; l<leaflongs ; l++)
  389. ((long *)uncompressed)[l] |= src[l];
  390. }
  391. }
  392. for (j=0 ; j<portalclusters ; j++)
  393. if (uncompressed[j>>3] & (1<<(j&7)) )
  394. count++;
  395. //
  396. // compress the bit string
  397. //
  398. j = CompressVis (uncompressed, compressed);
  399. dest = (long *)vismap_p;
  400. vismap_p += j;
  401. if (vismap_p > vismap_end)
  402. Error ("Vismap expansion overflow");
  403. dvis->bitofs[i][DVIS_PHS] = (byte *)dest-vismap;
  404. memcpy (dest, compressed, j);
  405. }
  406. printf ("Average clusters hearable: %i\n", count/portalclusters);
  407. }
  408. /*
  409. ===========
  410. main
  411. ===========
  412. */
  413. int main (int argc, char **argv)
  414. {
  415. char portalfile[1024];
  416. char source[1024];
  417. char name[1024];
  418. int i;
  419. double start, end;
  420. printf ("---- vis ----\n");
  421. verbose = false;
  422. for (i=1 ; i<argc ; i++)
  423. {
  424. if (!strcmp(argv[i],"-threads"))
  425. {
  426. numthreads = atoi (argv[i+1]);
  427. i++;
  428. }
  429. else if (!strcmp(argv[i], "-fast"))
  430. {
  431. printf ("fastvis = true\n");
  432. fastvis = true;
  433. }
  434. else if (!strcmp(argv[i], "-level"))
  435. {
  436. testlevel = atoi(argv[i+1]);
  437. printf ("testlevel = %i\n", testlevel);
  438. i++;
  439. }
  440. else if (!strcmp(argv[i], "-v"))
  441. {
  442. printf ("verbose = true\n");
  443. verbose = true;
  444. }
  445. else if (!strcmp (argv[i],"-nosort"))
  446. {
  447. printf ("nosort = true\n");
  448. nosort = true;
  449. }
  450. else if (!strcmp (argv[i],"-tmpin"))
  451. strcpy (inbase, "/tmp");
  452. else if (!strcmp (argv[i],"-tmpout"))
  453. strcpy (outbase, "/tmp");
  454. else if (argv[i][0] == '-')
  455. Error ("Unknown option \"%s\"", argv[i]);
  456. else
  457. break;
  458. }
  459. if (i != argc - 1)
  460. Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");
  461. start = I_FloatTime ();
  462. ThreadSetDefault ();
  463. SetQdirFromPath (argv[i]);
  464. strcpy (source, ExpandArg(argv[i]));
  465. StripExtension (source);
  466. DefaultExtension (source, ".bsp");
  467. sprintf (name, "%s%s", inbase, source);
  468. printf ("reading %s\n", name);
  469. LoadBSPFile (name);
  470. if (numnodes == 0 || numfaces == 0)
  471. Error ("Empty map");
  472. sprintf (portalfile, "%s%s", inbase, ExpandArg(argv[i]));
  473. StripExtension (portalfile);
  474. strcat (portalfile, ".prt");
  475. printf ("reading %s\n", portalfile);
  476. LoadPortals (portalfile);
  477. CalcVis ();
  478. CalcPHS ();
  479. visdatasize = vismap_p - dvisdata;
  480. printf ("visdatasize:%i compressed from %i\n", visdatasize, originalvismapsize*2);
  481. sprintf (name, "%s%s", outbase, source);
  482. printf ("writing %s\n", name);
  483. WriteBSPFile (name);
  484. end = I_FloatTime ();
  485. printf ("%5.1f seconds elapsed\n", end-start);
  486. return 0;
  487. }