PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/utils/qutils/vis/vis.c

https://gitlab.com/fzwoch/fodquake
C | 982 lines | 652 code | 182 blank | 148 comment | 150 complexity | 0a78ca4fcead2d91dfee839174e7f171 MD5 | raw file
Possible License(s): GPL-2.0
  1. /* Copyright (C) 1996-1997 Id Software, Inc.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program; if not, write to the Free Software
  12. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  13. See file, 'COPYING', for details.
  14. */
  15. // vis.c
  16. #include "vis.h"
  17. #define MAX_THREADS 4
  18. int numportals;
  19. int portalleafs;
  20. portal_t *portals;
  21. leaf_t *leafs;
  22. int c_portaltest, c_portalpass, c_portalcheck;
  23. qboolean showgetleaf = true;
  24. int leafon; // the next leaf to be given to a thread to process
  25. #ifdef __alpha
  26. pthread_mutex_t *my_mutex;
  27. #endif
  28. byte *vismap, *vismap_p, *vismap_end; // past visfile
  29. int originalvismapsize;
  30. byte *uncompressed; // [bitbytes*portalleafs]
  31. int bitbytes; // (portalleafs+63)>>3
  32. int bitlongs;
  33. #ifdef __alpha
  34. int numthreads = 4;
  35. #else
  36. int numthreads = 1;
  37. #endif
  38. qboolean fastvis;
  39. qboolean verbose;
  40. int testlevel = 2;
  41. #if 0
  42. void NormalizePlane (plane_t *dp)
  43. {
  44. vec_t ax, ay, az;
  45. if (dp->normal[0] == -1.0)
  46. {
  47. dp->normal[0] = 1.0;
  48. dp->dist = -dp->dist;
  49. return;
  50. }
  51. if (dp->normal[1] == -1.0)
  52. {
  53. dp->normal[1] = 1.0;
  54. dp->dist = -dp->dist;
  55. return;
  56. }
  57. if (dp->normal[2] == -1.0)
  58. {
  59. dp->normal[2] = 1.0;
  60. dp->dist = -dp->dist;
  61. return;
  62. }
  63. ax = fabs(dp->normal[0]);
  64. ay = fabs(dp->normal[1]);
  65. az = fabs(dp->normal[2]);
  66. if (ax >= ay && ax >= az)
  67. {
  68. if (dp->normal[0] < 0)
  69. {
  70. VectorSubtract (vec3_origin, dp->normal, dp->normal);
  71. dp->dist = -dp->dist;
  72. }
  73. return;
  74. }
  75. if (ay >= ax && ay >= az)
  76. {
  77. if (dp->normal[1] < 0)
  78. {
  79. VectorSubtract (vec3_origin, dp->normal, dp->normal);
  80. dp->dist = -dp->dist;
  81. }
  82. return;
  83. }
  84. if (dp->normal[2] < 0)
  85. {
  86. VectorSubtract (vec3_origin, dp->normal, dp->normal);
  87. dp->dist = -dp->dist;
  88. }
  89. }
  90. #endif
  91. void PlaneFromWinding (winding_t *w, plane_t *plane)
  92. {
  93. vec3_t v1, v2;
  94. // calc plane
  95. VectorSubtract (w->points[2], w->points[1], v1);
  96. VectorSubtract (w->points[0], w->points[1], v2);
  97. CrossProduct (v2, v1, plane->normal);
  98. VectorNormalize (plane->normal);
  99. plane->dist = DotProduct (w->points[0], plane->normal);
  100. }
  101. //=============================================================================
  102. /*
  103. ==================
  104. NewWinding
  105. ==================
  106. */
  107. winding_t *NewWinding (int points)
  108. {
  109. winding_t *w;
  110. int size;
  111. if (points > MAX_POINTS_ON_WINDING)
  112. Error ("NewWinding: %i points", points);
  113. size = (int)((winding_t *)0)->points[points];
  114. w = malloc (size);
  115. memset (w, 0, size);
  116. return w;
  117. }
  118. void FreeWinding (winding_t *w)
  119. {
  120. if (!w->original)
  121. free (w);
  122. }
  123. void pw(winding_t *w)
  124. {
  125. int i;
  126. for (i=0 ; i<w->numpoints ; i++)
  127. printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]);
  128. }
  129. void prl(leaf_t *l)
  130. {
  131. int i;
  132. portal_t *p;
  133. plane_t pl;
  134. for (i=0 ; i<l->numportals ; i++)
  135. {
  136. p = l->portals[i];
  137. pl = p->plane;
  138. 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]);
  139. }
  140. }
  141. /*
  142. ==================
  143. CopyWinding
  144. ==================
  145. */
  146. winding_t *CopyWinding (winding_t *w)
  147. {
  148. int size;
  149. winding_t *c;
  150. size = (int)((winding_t *)0)->points[w->numpoints];
  151. c = malloc (size);
  152. memcpy (c, w, size);
  153. c->original = false;
  154. return c;
  155. }
  156. /*
  157. ==================
  158. ClipWinding
  159. Clips the winding to the plane, returning the new winding on the positive side
  160. Frees the input winding.
  161. If keepon is true, an exactly on-plane winding will be saved, otherwise
  162. it will be clipped away.
  163. ==================
  164. */
  165. winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon)
  166. {
  167. vec_t dists[MAX_POINTS_ON_WINDING];
  168. int sides[MAX_POINTS_ON_WINDING];
  169. int counts[3];
  170. vec_t dot;
  171. int i, j;
  172. vec_t *p1, *p2;
  173. vec3_t mid;
  174. winding_t *neww;
  175. int maxpts;
  176. counts[0] = counts[1] = counts[2] = 0;
  177. // determine sides for each point
  178. for (i=0 ; i<in->numpoints ; i++)
  179. {
  180. dot = DotProduct (in->points[i], split->normal);
  181. dot -= split->dist;
  182. dists[i] = dot;
  183. if (dot > ON_EPSILON)
  184. sides[i] = SIDE_FRONT;
  185. else if (dot < -ON_EPSILON)
  186. sides[i] = SIDE_BACK;
  187. else
  188. {
  189. sides[i] = SIDE_ON;
  190. }
  191. counts[sides[i]]++;
  192. }
  193. sides[i] = sides[0];
  194. dists[i] = dists[0];
  195. if (keepon && !counts[0] && !counts[1])
  196. return in;
  197. if (!counts[0])
  198. {
  199. FreeWinding (in);
  200. return NULL;
  201. }
  202. if (!counts[1])
  203. return in;
  204. maxpts = in->numpoints+4; // can't use counts[0]+2 because
  205. // of fp grouping errors
  206. neww = NewWinding (maxpts);
  207. for (i=0 ; i<in->numpoints ; i++)
  208. {
  209. p1 = in->points[i];
  210. if (sides[i] == SIDE_ON)
  211. {
  212. VectorCopy (p1, neww->points[neww->numpoints]);
  213. neww->numpoints++;
  214. continue;
  215. }
  216. if (sides[i] == SIDE_FRONT)
  217. {
  218. VectorCopy (p1, neww->points[neww->numpoints]);
  219. neww->numpoints++;
  220. }
  221. if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  222. continue;
  223. // generate a split point
  224. p2 = in->points[(i+1)%in->numpoints];
  225. dot = dists[i] / (dists[i]-dists[i+1]);
  226. for (j=0 ; j<3 ; j++)
  227. { // avoid round off error when possible
  228. if (split->normal[j] == 1)
  229. mid[j] = split->dist;
  230. else if (split->normal[j] == -1)
  231. mid[j] = -split->dist;
  232. else
  233. mid[j] = p1[j] + dot*(p2[j]-p1[j]);
  234. }
  235. VectorCopy (mid, neww->points[neww->numpoints]);
  236. neww->numpoints++;
  237. }
  238. if (neww->numpoints > maxpts)
  239. Error ("ClipWinding: points exceeded estimate");
  240. // free the original winding
  241. FreeWinding (in);
  242. return neww;
  243. }
  244. //=============================================================================
  245. /*
  246. =============
  247. GetNextPortal
  248. Returns the next portal for a thread to work on
  249. Returns the portals from the least complex, so the later ones can reuse
  250. the earlier information.
  251. =============
  252. */
  253. portal_t *GetNextPortal (void)
  254. {
  255. int j;
  256. portal_t *p, *tp;
  257. int min;
  258. LOCK;
  259. min = 99999;
  260. p = NULL;
  261. for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
  262. {
  263. if (tp->nummightsee < min && tp->status == stat_none)
  264. {
  265. min = tp->nummightsee;
  266. p = tp;
  267. }
  268. }
  269. if (p)
  270. p->status = stat_working;
  271. UNLOCK;
  272. return p;
  273. }
  274. /*
  275. ==============
  276. LeafThread
  277. ==============
  278. */
  279. #ifdef __alpha
  280. pthread_addr_t LeafThread (pthread_addr_t thread)
  281. #else
  282. void *LeafThread (int thread)
  283. #endif
  284. {
  285. portal_t *p;
  286. //printf ("Begining LeafThread: %i\n",(int)thread);
  287. do
  288. {
  289. p = GetNextPortal ();
  290. if (!p)
  291. break;
  292. PortalFlow (p);
  293. if (verbose)
  294. printf ("portal:%4i mightsee:%4i cansee:%4i\n", (int)(p - portals), p->nummightsee, p->numcansee);
  295. } while (1);
  296. //printf ("Completed LeafThread: %i\n",(int)thread);
  297. return NULL;
  298. }
  299. /*
  300. ===============
  301. CompressRow
  302. ===============
  303. */
  304. int CompressRow (byte *vis, byte *dest)
  305. {
  306. int j;
  307. int rep;
  308. int visrow;
  309. byte *dest_p;
  310. dest_p = dest;
  311. visrow = (portalleafs + 7)>>3;
  312. for (j=0 ; j<visrow ; j++)
  313. {
  314. *dest_p++ = vis[j];
  315. if (vis[j])
  316. continue;
  317. rep = 1;
  318. for ( j++; j<visrow ; j++)
  319. if (vis[j] || rep == 255)
  320. break;
  321. else
  322. rep++;
  323. *dest_p++ = rep;
  324. j--;
  325. }
  326. return dest_p - dest;
  327. }
  328. /*
  329. ===============
  330. LeafFlow
  331. Builds the entire visibility list for a leaf
  332. ===============
  333. */
  334. int totalvis;
  335. void LeafFlow (int leafnum)
  336. {
  337. leaf_t *leaf;
  338. byte *outbuffer;
  339. byte compressed[MAX_MAP_LEAFS/8];
  340. int i, j;
  341. int numvis;
  342. byte *dest;
  343. portal_t *p;
  344. //
  345. // flow through all portals, collecting visible bits
  346. //
  347. outbuffer = uncompressed + leafnum*bitbytes;
  348. leaf = &leafs[leafnum];
  349. for (i=0 ; i<leaf->numportals ; i++)
  350. {
  351. p = leaf->portals[i];
  352. if (p->status != stat_done)
  353. Error ("portal not done");
  354. for (j=0 ; j<bitbytes ; j++)
  355. outbuffer[j] |= p->visbits[j];
  356. }
  357. if (outbuffer[leafnum>>3] & (1<<(leafnum&7)))
  358. Error ("Leaf portals saw into leaf");
  359. outbuffer[leafnum>>3] |= (1<<(leafnum&7));
  360. numvis = 0;
  361. for (i=0 ; i<portalleafs ; i++)
  362. if (outbuffer[i>>3] & (1<<(i&3)))
  363. numvis++;
  364. //
  365. // compress the bit string
  366. //
  367. if (verbose)
  368. printf ("leaf %4i : %4i visible\n", leafnum, numvis);
  369. totalvis += numvis;
  370. #if 0
  371. i = (portalleafs+7)>>3;
  372. memcpy (compressed, outbuffer, i);
  373. #else
  374. i = CompressRow (outbuffer, compressed);
  375. #endif
  376. dest = vismap_p;
  377. vismap_p += i;
  378. if (vismap_p > vismap_end)
  379. Error ("Vismap expansion overflow");
  380. dleafs[leafnum+1].visofs = dest-vismap; // leaf 0 is a common solid
  381. memcpy (dest, compressed, i);
  382. }
  383. /*
  384. ==================
  385. CalcPortalVis
  386. ==================
  387. */
  388. void CalcPortalVis (void)
  389. {
  390. int i;
  391. // fastvis just uses mightsee for a very loose bound
  392. if (fastvis)
  393. {
  394. for (i=0 ; i<numportals*2 ; i++)
  395. {
  396. portals[i].visbits = portals[i].mightsee;
  397. portals[i].status = stat_done;
  398. }
  399. return;
  400. }
  401. leafon = 0;
  402. #ifdef __alpha
  403. {
  404. pthread_t work_threads[MAX_THREADS];
  405. pthread_addr_t status;
  406. pthread_attr_t attrib;
  407. pthread_mutexattr_t mattrib;
  408. int i;
  409. my_mutex = malloc (sizeof(*my_mutex));
  410. if (pthread_mutexattr_create (&mattrib) == -1)
  411. Error ("pthread_mutex_attr_create failed");
  412. if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
  413. Error ("pthread_mutexattr_setkind_np failed");
  414. if (pthread_mutex_init (my_mutex, mattrib) == -1)
  415. Error ("pthread_mutex_init failed");
  416. if (pthread_attr_create (&attrib) == -1)
  417. Error ("pthread_attr_create failed");
  418. if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
  419. Error ("pthread_attr_setstacksize failed");
  420. for (i=0 ; i<numthreads ; i++)
  421. {
  422. if (pthread_create(&work_threads[i], attrib
  423. , LeafThread, (pthread_addr_t)i) == -1)
  424. Error ("pthread_create failed");
  425. }
  426. for (i=0 ; i<numthreads ; i++)
  427. {
  428. if (pthread_join (work_threads[i], &status) == -1)
  429. Error ("pthread_join failed");
  430. }
  431. if (pthread_mutex_destroy (my_mutex) == -1)
  432. Error ("pthread_mutex_destroy failed");
  433. }
  434. #else
  435. LeafThread (0);
  436. #endif
  437. if (verbose)
  438. {
  439. printf ("portalcheck: %i portaltest: %i portalpass: %i\n",c_portalcheck, c_portaltest, c_portalpass);
  440. printf ("c_vistest: %i c_mighttest: %i\n",c_vistest, c_mighttest);
  441. }
  442. }
  443. /*
  444. ==================
  445. CalcVis
  446. ==================
  447. */
  448. void CalcVis (void)
  449. {
  450. int i;
  451. BasePortalVis ();
  452. CalcPortalVis ();
  453. //
  454. // assemble the leaf vis lists by oring and compressing the portal lists
  455. //
  456. for (i=0 ; i<portalleafs ; i++)
  457. LeafFlow (i);
  458. printf ("average leafs visible: %i\n", totalvis / portalleafs);
  459. }
  460. /*
  461. ==============================================================================
  462. PASSAGE CALCULATION (not used yet...)
  463. ==============================================================================
  464. */
  465. int count_sep;
  466. qboolean PlaneCompare (plane_t *p1, plane_t *p2)
  467. {
  468. int i;
  469. if ( fabs(p1->dist - p2->dist) > 0.01)
  470. return false;
  471. for (i=0 ; i<3 ; i++)
  472. if ( fabs(p1->normal[i] - p2->normal[i] ) > 0.001)
  473. return false;
  474. return true;
  475. }
  476. sep_t *Findpassages (winding_t *source, winding_t *pass)
  477. {
  478. int i, j, k, l;
  479. plane_t plane;
  480. vec3_t v1, v2;
  481. float d;
  482. double length;
  483. int counts[3];
  484. qboolean fliptest;
  485. sep_t *sep, *list;
  486. list = NULL;
  487. // check all combinations
  488. for (i=0 ; i<source->numpoints ; i++)
  489. {
  490. l = (i+1)%source->numpoints;
  491. VectorSubtract (source->points[l] , source->points[i], v1);
  492. // fing a vertex of pass that makes a plane that puts all of the
  493. // vertexes of pass on the front side and all of the vertexes of
  494. // source on the back side
  495. for (j=0 ; j<pass->numpoints ; j++)
  496. {
  497. VectorSubtract (pass->points[j], source->points[i], v2);
  498. plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
  499. plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
  500. plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
  501. // if points don't make a valid plane, skip it
  502. length = plane.normal[0] * plane.normal[0]
  503. + plane.normal[1] * plane.normal[1]
  504. + plane.normal[2] * plane.normal[2];
  505. if (length < ON_EPSILON)
  506. continue;
  507. length = 1/sqrt(length);
  508. plane.normal[0] *= length;
  509. plane.normal[1] *= length;
  510. plane.normal[2] *= length;
  511. plane.dist = DotProduct (pass->points[j], plane.normal);
  512. //
  513. // find out which side of the generated seperating plane has the
  514. // source portal
  515. //
  516. fliptest = false;
  517. for (k=0 ; k<source->numpoints ; k++)
  518. {
  519. if (k == i || k == l)
  520. continue;
  521. d = DotProduct (source->points[k], plane.normal) - plane.dist;
  522. if (d < -ON_EPSILON)
  523. { // source is on the negative side, so we want all
  524. // pass and target on the positive side
  525. fliptest = false;
  526. break;
  527. }
  528. else if (d > ON_EPSILON)
  529. { // source is on the positive side, so we want all
  530. // pass and target on the negative side
  531. fliptest = true;
  532. break;
  533. }
  534. }
  535. if (k == source->numpoints)
  536. continue; // planar with source portal
  537. //
  538. // flip the normal if the source portal is backwards
  539. //
  540. if (fliptest)
  541. {
  542. VectorSubtract (vec3_origin, plane.normal, plane.normal);
  543. plane.dist = -plane.dist;
  544. }
  545. //
  546. // if all of the pass portal points are now on the positive side,
  547. // this is the seperating plane
  548. //
  549. counts[0] = counts[1] = counts[2] = 0;
  550. for (k=0 ; k<pass->numpoints ; k++)
  551. {
  552. if (k==j)
  553. continue;
  554. d = DotProduct (pass->points[k], plane.normal) - plane.dist;
  555. if (d < -ON_EPSILON)
  556. break;
  557. else if (d > ON_EPSILON)
  558. counts[0]++;
  559. else
  560. counts[2]++;
  561. }
  562. if (k != pass->numpoints)
  563. continue; // points on negative side, not a seperating plane
  564. if (!counts[0])
  565. continue; // planar with pass portal
  566. //
  567. // save this out
  568. //
  569. count_sep++;
  570. sep = malloc(sizeof(*sep));
  571. sep->next = list;
  572. list = sep;
  573. sep->plane = plane;
  574. }
  575. }
  576. return list;
  577. }
  578. /*
  579. ============
  580. CalcPassages
  581. ============
  582. */
  583. void CalcPassages (void)
  584. {
  585. int i, j, k;
  586. int count, count2;
  587. leaf_t *l;
  588. portal_t *p1, *p2;
  589. sep_t *sep;
  590. passage_t *passages;
  591. printf ("building passages...\n");
  592. count = count2 = 0;
  593. for (i=0 ; i<portalleafs ; i++)
  594. {
  595. l = &leafs[i];
  596. for (j=0 ; j<l->numportals ; j++)
  597. {
  598. p1 = l->portals[j];
  599. for (k=0 ; k<l->numportals ; k++)
  600. {
  601. if (k==j)
  602. continue;
  603. count++;
  604. p2 = l->portals[k];
  605. // definately can't see into a coplanar portal
  606. if (PlaneCompare (&p1->plane, &p2->plane) )
  607. continue;
  608. count2++;
  609. sep = Findpassages (p1->winding, p2->winding);
  610. if (!sep)
  611. {
  612. // Error ("No seperating planes found in portal pair");
  613. count_sep++;
  614. sep = malloc(sizeof(*sep));
  615. sep->next = NULL;
  616. sep->plane = p1->plane;
  617. }
  618. passages = malloc(sizeof(*passages));
  619. passages->planes = sep;
  620. passages->from = p1->leaf;
  621. passages->to = p2->leaf;
  622. passages->next = l->passages;
  623. l->passages = passages;
  624. }
  625. }
  626. }
  627. printf ("numpassages: %i (%i)\n", count2, count);
  628. printf ("total passages: %i\n", count_sep);
  629. }
  630. //=============================================================================
  631. /*
  632. ============
  633. LoadPortals
  634. ============
  635. */
  636. void LoadPortals (char *name)
  637. {
  638. int i, j;
  639. portal_t *p;
  640. leaf_t *l;
  641. char magic[80];
  642. FILE *f;
  643. int numpoints;
  644. winding_t *w;
  645. int leafnums[2];
  646. plane_t plane;
  647. if (!strcmp(name,"-"))
  648. f = stdin;
  649. else
  650. {
  651. f = fopen(name, "r");
  652. if (!f)
  653. {
  654. printf ("LoadPortals: couldn't read %s\n",name);
  655. printf ("No vising performed.\n");
  656. exit (1);
  657. }
  658. }
  659. if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalleafs, &numportals) != 3)
  660. Error ("LoadPortals: failed to read header");
  661. if (strcmp(magic,PORTALFILE))
  662. Error ("LoadPortals: not a portal file");
  663. printf ("%4i portalleafs\n", portalleafs);
  664. printf ("%4i numportals\n", numportals);
  665. bitbytes = ((portalleafs+63)&~63)>>3;
  666. bitlongs = bitbytes/sizeof(long);
  667. // each file portal is split into two memory portals
  668. portals = malloc(2*numportals*sizeof(portal_t));
  669. memset (portals, 0, 2*numportals*sizeof(portal_t));
  670. leafs = malloc(portalleafs*sizeof(leaf_t));
  671. memset (leafs, 0, portalleafs*sizeof(leaf_t));
  672. originalvismapsize = portalleafs*((portalleafs+7)/8);
  673. vismap = vismap_p = dvisdata;
  674. vismap_end = vismap + MAX_MAP_VISIBILITY;
  675. for (i=0, p=portals ; i<numportals ; i++)
  676. {
  677. if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
  678. != 3)
  679. Error ("LoadPortals: reading portal %i", i);
  680. if (numpoints > MAX_POINTS_ON_WINDING)
  681. Error ("LoadPortals: portal %i has too many points", i);
  682. if ( (unsigned)leafnums[0] > portalleafs
  683. || (unsigned)leafnums[1] > portalleafs)
  684. Error ("LoadPortals: reading portal %i", i);
  685. w = p->winding = NewWinding (numpoints);
  686. w->original = true;
  687. w->numpoints = numpoints;
  688. for (j=0 ; j<numpoints ; j++)
  689. {
  690. double v[3];
  691. int k;
  692. // scanf into double, then assign to vec_t
  693. if (fscanf (f, "(%lf %lf %lf ) "
  694. , &v[0], &v[1], &v[2]) != 3)
  695. Error ("LoadPortals: reading portal %i", i);
  696. for (k=0 ; k<3 ; k++)
  697. w->points[j][k] = v[k];
  698. }
  699. fscanf (f, "\n");
  700. // calc plane
  701. PlaneFromWinding (w, &plane);
  702. // create forward portal
  703. l = &leafs[leafnums[0]];
  704. if (l->numportals == MAX_PORTALS_ON_LEAF)
  705. Error ("Leaf with too many portals");
  706. l->portals[l->numportals] = p;
  707. l->numportals++;
  708. p->winding = w;
  709. VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
  710. p->plane.dist = -plane.dist;
  711. p->leaf = leafnums[1];
  712. p++;
  713. // create backwards portal
  714. l = &leafs[leafnums[1]];
  715. if (l->numportals == MAX_PORTALS_ON_LEAF)
  716. Error ("Leaf with too many portals");
  717. l->portals[l->numportals] = p;
  718. l->numportals++;
  719. p->winding = w;
  720. p->plane = plane;
  721. p->leaf = leafnums[0];
  722. p++;
  723. }
  724. fclose (f);
  725. }
  726. /*
  727. ===========
  728. main
  729. ===========
  730. */
  731. int main (int argc, char **argv)
  732. {
  733. char portalfile[1024];
  734. char source[1024];
  735. int i;
  736. double start, end;
  737. printf ("---- vis ----\n");
  738. for (i=1 ; i<argc ; i++)
  739. {
  740. if (!strcmp(argv[i],"-threads"))
  741. {
  742. numthreads = atoi (argv[i+1]);
  743. i++;
  744. }
  745. else if (!strcmp(argv[i], "-fast"))
  746. {
  747. printf ("fastvis = true\n");
  748. fastvis = true;
  749. }
  750. else if (!strcmp(argv[i], "-level"))
  751. {
  752. testlevel = atoi(argv[i+1]);
  753. printf ("testlevel = %i\n", testlevel);
  754. i++;
  755. }
  756. else if (!strcmp(argv[i], "-v"))
  757. {
  758. printf ("verbose = true\n");
  759. verbose = true;
  760. }
  761. else if (argv[i][0] == '-')
  762. Error ("Unknown option \"%s\"", argv[i]);
  763. else
  764. break;
  765. }
  766. if (i != argc - 1)
  767. Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");
  768. start = I_FloatTime ();
  769. strcpy (source, argv[i]);
  770. StripExtension (source);
  771. DefaultExtension (source, ".bsp");
  772. LoadBSPFile (source);
  773. strcpy (portalfile, argv[i]);
  774. StripExtension (portalfile);
  775. strcat (portalfile, ".prt");
  776. LoadPortals (portalfile);
  777. uncompressed = malloc(bitbytes*portalleafs);
  778. memset (uncompressed, 0, bitbytes*portalleafs);
  779. // CalcPassages ();
  780. CalcVis ();
  781. printf ("c_chains: %i\n",c_chains);
  782. visdatasize = vismap_p - dvisdata;
  783. printf ("visdatasize:%i compressed from %i\n", visdatasize, originalvismapsize);
  784. CalcAmbientSounds ();
  785. WriteBSPFile (source);
  786. // unlink (portalfile);
  787. end = I_FloatTime ();
  788. printf ("%5.1f seconds elapsed\n", end-start);
  789. return 0;
  790. }