visflow.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658
  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. #include "vis.h"
  19. /*
  20. each portal will have a list of all possible to see from first portal
  21. if (!thread->portalmightsee[portalnum])
  22. portal mightsee
  23. for p2 = all other portals in leaf
  24. get sperating planes
  25. for all portals that might be seen by p2
  26. mark as unseen if not present in seperating plane
  27. flood fill a new mightsee
  28. save as passagemightsee
  29. void CalcMightSee (leaf_t *leaf,
  30. */
  31. int CountBits (byte *bits, int numbits)
  32. {
  33. int i;
  34. int c;
  35. c = 0;
  36. for (i=0 ; i<numbits ; i++)
  37. if (bits[i>>3] & (1<<(i&7)) )
  38. c++;
  39. return c;
  40. }
  41. int c_fullskip;
  42. int c_portalskip, c_leafskip;
  43. int c_vistest, c_mighttest;
  44. int c_chop, c_nochop;
  45. int active;
  46. void CheckStack (leaf_t *leaf, threaddata_t *thread)
  47. {
  48. pstack_t *p, *p2;
  49. for (p=thread->pstack_head.next ; p ; p=p->next)
  50. {
  51. // _printf ("=");
  52. if (p->leaf == leaf)
  53. Error ("CheckStack: leaf recursion");
  54. for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next)
  55. if (p2->leaf == p->leaf)
  56. Error ("CheckStack: late leaf recursion");
  57. }
  58. // _printf ("\n");
  59. }
  60. winding_t *AllocStackWinding (pstack_t *stack)
  61. {
  62. int i;
  63. for (i=0 ; i<3 ; i++)
  64. {
  65. if (stack->freewindings[i])
  66. {
  67. stack->freewindings[i] = 0;
  68. return &stack->windings[i];
  69. }
  70. }
  71. Error ("AllocStackWinding: failed");
  72. return NULL;
  73. }
  74. void FreeStackWinding (winding_t *w, pstack_t *stack)
  75. {
  76. int i;
  77. i = w - stack->windings;
  78. if (i<0 || i>2)
  79. return; // not from local
  80. if (stack->freewindings[i])
  81. Error ("FreeStackWinding: allready free");
  82. stack->freewindings[i] = 1;
  83. }
  84. /*
  85. ==============
  86. VisChopWinding
  87. ==============
  88. */
  89. winding_t *VisChopWinding (winding_t *in, pstack_t *stack, plane_t *split)
  90. {
  91. vec_t dists[128];
  92. int sides[128];
  93. int counts[3];
  94. vec_t dot;
  95. int i, j;
  96. vec_t *p1, *p2;
  97. vec3_t mid;
  98. winding_t *neww;
  99. counts[0] = counts[1] = counts[2] = 0;
  100. // determine sides for each point
  101. for (i=0 ; i<in->numpoints ; i++)
  102. {
  103. dot = DotProduct (in->points[i], split->normal);
  104. dot -= split->dist;
  105. dists[i] = dot;
  106. if (dot > ON_EPSILON)
  107. sides[i] = SIDE_FRONT;
  108. else if (dot < -ON_EPSILON)
  109. sides[i] = SIDE_BACK;
  110. else
  111. {
  112. sides[i] = SIDE_ON;
  113. }
  114. counts[sides[i]]++;
  115. }
  116. if (!counts[1])
  117. return in; // completely on front side
  118. if (!counts[0])
  119. {
  120. FreeStackWinding (in, stack);
  121. return NULL;
  122. }
  123. sides[i] = sides[0];
  124. dists[i] = dists[0];
  125. neww = AllocStackWinding (stack);
  126. neww->numpoints = 0;
  127. for (i=0 ; i<in->numpoints ; i++)
  128. {
  129. p1 = in->points[i];
  130. if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
  131. {
  132. FreeStackWinding (neww, stack);
  133. return in; // can't chop -- fall back to original
  134. }
  135. if (sides[i] == SIDE_ON)
  136. {
  137. VectorCopy (p1, neww->points[neww->numpoints]);
  138. neww->numpoints++;
  139. continue;
  140. }
  141. if (sides[i] == SIDE_FRONT)
  142. {
  143. VectorCopy (p1, neww->points[neww->numpoints]);
  144. neww->numpoints++;
  145. }
  146. if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  147. continue;
  148. if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
  149. {
  150. FreeStackWinding (neww, stack);
  151. return in; // can't chop -- fall back to original
  152. }
  153. // generate a split point
  154. p2 = in->points[(i+1)%in->numpoints];
  155. dot = dists[i] / (dists[i]-dists[i+1]);
  156. for (j=0 ; j<3 ; j++)
  157. { // avoid round off error when possible
  158. if (split->normal[j] == 1)
  159. mid[j] = split->dist;
  160. else if (split->normal[j] == -1)
  161. mid[j] = -split->dist;
  162. else
  163. mid[j] = p1[j] + dot*(p2[j]-p1[j]);
  164. }
  165. VectorCopy (mid, neww->points[neww->numpoints]);
  166. neww->numpoints++;
  167. }
  168. // free the original winding
  169. FreeStackWinding (in, stack);
  170. return neww;
  171. }
  172. /*
  173. ==============
  174. ClipToSeperators
  175. Source, pass, and target are an ordering of portals.
  176. Generates seperating planes canidates by taking two points from source and one
  177. point from pass, and clips target by them.
  178. If target is totally clipped away, that portal can not be seen through.
  179. Normal clip keeps target on the same side as pass, which is correct if the
  180. order goes source, pass, target. If the order goes pass, source, target then
  181. flipclip should be set.
  182. ==============
  183. */
  184. winding_t *ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip, pstack_t *stack)
  185. {
  186. int i, j, k, l;
  187. plane_t plane;
  188. vec3_t v1, v2;
  189. float d;
  190. vec_t length;
  191. int counts[3];
  192. qboolean fliptest;
  193. // check all combinations
  194. for (i=0 ; i<source->numpoints ; i++)
  195. {
  196. l = (i+1)%source->numpoints;
  197. VectorSubtract (source->points[l] , source->points[i], v1);
  198. // find a vertex of pass that makes a plane that puts all of the
  199. // vertexes of pass on the front side and all of the vertexes of
  200. // source on the back side
  201. for (j=0 ; j<pass->numpoints ; j++)
  202. {
  203. VectorSubtract (pass->points[j], source->points[i], v2);
  204. plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
  205. plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
  206. plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
  207. // if points don't make a valid plane, skip it
  208. length = plane.normal[0] * plane.normal[0]
  209. + plane.normal[1] * plane.normal[1]
  210. + plane.normal[2] * plane.normal[2];
  211. if (length < ON_EPSILON)
  212. continue;
  213. length = 1/sqrt(length);
  214. plane.normal[0] *= length;
  215. plane.normal[1] *= length;
  216. plane.normal[2] *= length;
  217. plane.dist = DotProduct (pass->points[j], plane.normal);
  218. //
  219. // find out which side of the generated seperating plane has the
  220. // source portal
  221. //
  222. #if 1
  223. fliptest = qfalse;
  224. for (k=0 ; k<source->numpoints ; k++)
  225. {
  226. if (k == i || k == l)
  227. continue;
  228. d = DotProduct (source->points[k], plane.normal) - plane.dist;
  229. if (d < -ON_EPSILON)
  230. { // source is on the negative side, so we want all
  231. // pass and target on the positive side
  232. fliptest = qfalse;
  233. break;
  234. }
  235. else if (d > ON_EPSILON)
  236. { // source is on the positive side, so we want all
  237. // pass and target on the negative side
  238. fliptest = qtrue;
  239. break;
  240. }
  241. }
  242. if (k == source->numpoints)
  243. continue; // planar with source portal
  244. #else
  245. fliptest = flipclip;
  246. #endif
  247. //
  248. // flip the normal if the source portal is backwards
  249. //
  250. if (fliptest)
  251. {
  252. VectorSubtract (vec3_origin, plane.normal, plane.normal);
  253. plane.dist = -plane.dist;
  254. }
  255. #if 1
  256. //
  257. // if all of the pass portal points are now on the positive side,
  258. // this is the seperating plane
  259. //
  260. counts[0] = counts[1] = counts[2] = 0;
  261. for (k=0 ; k<pass->numpoints ; k++)
  262. {
  263. if (k==j)
  264. continue;
  265. d = DotProduct (pass->points[k], plane.normal) - plane.dist;
  266. if (d < -ON_EPSILON)
  267. break;
  268. else if (d > ON_EPSILON)
  269. counts[0]++;
  270. else
  271. counts[2]++;
  272. }
  273. if (k != pass->numpoints)
  274. continue; // points on negative side, not a seperating plane
  275. if (!counts[0])
  276. continue; // planar with seperating plane
  277. #else
  278. k = (j+1)%pass->numpoints;
  279. d = DotProduct (pass->points[k], plane.normal) - plane.dist;
  280. if (d < -ON_EPSILON)
  281. continue;
  282. k = (j+pass->numpoints-1)%pass->numpoints;
  283. d = DotProduct (pass->points[k], plane.normal) - plane.dist;
  284. if (d < -ON_EPSILON)
  285. continue;
  286. #endif
  287. //
  288. // flip the normal if we want the back side
  289. //
  290. if (flipclip)
  291. {
  292. VectorSubtract (vec3_origin, plane.normal, plane.normal);
  293. plane.dist = -plane.dist;
  294. }
  295. #ifdef SEPERATORCACHE
  296. stack->seperators[flipclip][stack->numseperators[flipclip]] = plane;
  297. if (++stack->numseperators[flipclip] >= MAX_SEPERATORS)
  298. Error("MAX_SEPERATORS");
  299. #endif
  300. //MrE: fast check first
  301. d = DotProduct (stack->portal->origin, plane.normal) - plane.dist;
  302. //if completely at the back of the seperator plane
  303. if (d < -stack->portal->radius)
  304. return NULL;
  305. //if completely on the front of the seperator plane
  306. if (d > stack->portal->radius)
  307. break;
  308. //
  309. // clip target by the seperating plane
  310. //
  311. target = VisChopWinding (target, stack, &plane);
  312. if (!target)
  313. return NULL; // target is not visible
  314. break; // optimization by Antony Suter
  315. }
  316. }
  317. return target;
  318. }
  319. /*
  320. ==================
  321. RecursiveLeafFlow
  322. Flood fill through the leafs
  323. If src_portal is NULL, this is the originating leaf
  324. ==================
  325. */
  326. void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
  327. {
  328. pstack_t stack;
  329. vportal_t *p;
  330. plane_t backplane;
  331. leaf_t *leaf;
  332. int i, j, n;
  333. long *test, *might, *prevmight, *vis, more;
  334. int pnum;
  335. thread->c_chains++;
  336. leaf = &leafs[leafnum];
  337. // CheckStack (leaf, thread);
  338. prevstack->next = &stack;
  339. stack.next = NULL;
  340. stack.leaf = leaf;
  341. stack.portal = NULL;
  342. stack.depth = prevstack->depth + 1;
  343. #ifdef SEPERATORCACHE
  344. stack.numseperators[0] = 0;
  345. stack.numseperators[1] = 0;
  346. #endif
  347. might = (long *)stack.mightsee;
  348. vis = (long *)thread->base->portalvis;
  349. // check all portals for flowing into other leafs
  350. for (i = 0; i < leaf->numportals; i++)
  351. {
  352. p = leaf->portals[i];
  353. if (p->removed)
  354. continue;
  355. pnum = p - portals;
  356. /* MrE: portal trace debug code
  357. {
  358. int portaltrace[] = {13, 16, 17, 37};
  359. pstack_t *s;
  360. s = &thread->pstack_head;
  361. for (j = 0; s->next && j < sizeof(portaltrace)/sizeof(int) - 1; j++, s = s->next)
  362. {
  363. if (s->portal->num != portaltrace[j])
  364. break;
  365. }
  366. if (j >= sizeof(portaltrace)/sizeof(int) - 1)
  367. {
  368. if (p->num == portaltrace[j])
  369. n = 0; //traced through all the portals
  370. }
  371. }
  372. */
  373. if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
  374. {
  375. continue; // can't possibly see it
  376. }
  377. // if the portal can't see anything we haven't allready seen, skip it
  378. if (p->status == stat_done)
  379. {
  380. test = (long *)p->portalvis;
  381. }
  382. else
  383. {
  384. test = (long *)p->portalflood;
  385. }
  386. more = 0;
  387. prevmight = (long *)prevstack->mightsee;
  388. for (j=0 ; j<portallongs ; j++)
  389. {
  390. might[j] = prevmight[j] & test[j];
  391. more |= (might[j] & ~vis[j]);
  392. }
  393. if (!more &&
  394. (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
  395. { // can't see anything new
  396. continue;
  397. }
  398. // get plane of portal, point normal into the neighbor leaf
  399. stack.portalplane = p->plane;
  400. VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
  401. backplane.dist = -p->plane.dist;
  402. // c_portalcheck++;
  403. stack.portal = p;
  404. stack.next = NULL;
  405. stack.freewindings[0] = 1;
  406. stack.freewindings[1] = 1;
  407. stack.freewindings[2] = 1;
  408. #if 1
  409. {
  410. float d;
  411. d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
  412. d -= thread->pstack_head.portalplane.dist;
  413. if (d < -p->radius)
  414. {
  415. continue;
  416. }
  417. else if (d > p->radius)
  418. {
  419. stack.pass = p->winding;
  420. }
  421. else
  422. {
  423. stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
  424. if (!stack.pass)
  425. continue;
  426. }
  427. }
  428. #else
  429. stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
  430. if (!stack.pass)
  431. continue;
  432. #endif
  433. #if 1
  434. {
  435. float d;
  436. d = DotProduct (thread->base->origin, p->plane.normal);
  437. d -= p->plane.dist;
  438. //MrE: vis-bug fix
  439. //if (d > p->radius)
  440. if (d > thread->base->radius)
  441. {
  442. continue;
  443. }
  444. //MrE: vis-bug fix
  445. //if (d < -p->radius)
  446. else if (d < -thread->base->radius)
  447. {
  448. stack.source = prevstack->source;
  449. }
  450. else
  451. {
  452. stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
  453. //FIXME: shouldn't we create a new source origin and radius for fast checks?
  454. if (!stack.source)
  455. continue;
  456. }
  457. }
  458. #else
  459. stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
  460. if (!stack.source)
  461. continue;
  462. #endif
  463. if (!prevstack->pass)
  464. { // the second leaf can only be blocked if coplanar
  465. // mark the portal as visible
  466. thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
  467. RecursiveLeafFlow (p->leaf, thread, &stack);
  468. continue;
  469. }
  470. #ifdef SEPERATORCACHE
  471. if (stack.numseperators[0])
  472. {
  473. for (n = 0; n < stack.numseperators[0]; n++)
  474. {
  475. stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]);
  476. if (!stack.pass)
  477. break; // target is not visible
  478. }
  479. if (n < stack.numseperators[0])
  480. continue;
  481. }
  482. else
  483. {
  484. stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack);
  485. }
  486. #else
  487. stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack);
  488. #endif
  489. if (!stack.pass)
  490. continue;
  491. #ifdef SEPERATORCACHE
  492. if (stack.numseperators[1])
  493. {
  494. for (n = 0; n < stack.numseperators[1]; n++)
  495. {
  496. stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]);
  497. if (!stack.pass)
  498. break; // target is not visible
  499. }
  500. }
  501. else
  502. {
  503. stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack);
  504. }
  505. #else
  506. stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack);
  507. #endif
  508. if (!stack.pass)
  509. continue;
  510. // mark the portal as visible
  511. thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
  512. // flow through it for real
  513. RecursiveLeafFlow (p->leaf, thread, &stack);
  514. //
  515. stack.next = NULL;
  516. }
  517. }
  518. /*
  519. ===============
  520. PortalFlow
  521. generates the portalvis bit vector
  522. ===============
  523. */
  524. void PortalFlow (int portalnum)
  525. {
  526. threaddata_t data;
  527. int i;
  528. vportal_t *p;
  529. int c_might, c_can;
  530. #ifdef MREDEBUG
  531. _printf("\r%6d", portalnum);
  532. #endif
  533. p = sorted_portals[portalnum];
  534. if (p->removed)
  535. {
  536. p->status = stat_done;
  537. return;
  538. }
  539. p->status = stat_working;
  540. c_might = CountBits (p->portalflood, numportals*2);
  541. memset (&data, 0, sizeof(data));
  542. data.base = p;
  543. data.pstack_head.portal = p;
  544. data.pstack_head.source = p->winding;
  545. data.pstack_head.portalplane = p->plane;
  546. data.pstack_head.depth = 0;
  547. for (i=0 ; i<portallongs ; i++)
  548. ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
  549. RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
  550. p->status = stat_done;
  551. c_can = CountBits (p->portalvis, numportals*2);
  552. qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n",
  553. (int)(p - portals), c_might, c_can, data.c_chains);
  554. }
  555. /*
  556. ==================
  557. RecursivePassageFlow
  558. ==================
  559. */
  560. void RecursivePassageFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack)
  561. {
  562. pstack_t stack;
  563. vportal_t *p;
  564. leaf_t *leaf;
  565. passage_t *passage, *nextpassage;
  566. int i, j;
  567. long *might, *vis, *prevmight, *cansee, *portalvis, more;
  568. int pnum;
  569. leaf = &leafs[portal->leaf];
  570. prevstack->next = &stack;
  571. stack.next = NULL;
  572. stack.depth = prevstack->depth + 1;
  573. vis = (long *)thread->base->portalvis;
  574. passage = portal->passages;
  575. nextpassage = passage;
  576. // check all portals for flowing into other leafs
  577. for (i = 0; i < leaf->numportals; i++, passage = nextpassage)
  578. {
  579. p = leaf->portals[i];
  580. if ( p->removed ) {
  581. continue;
  582. }
  583. nextpassage = passage->next;
  584. pnum = p - portals;
  585. if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) {
  586. continue; // can't possibly see it
  587. }
  588. // mark the portal as visible
  589. thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
  590. prevmight = (long *)prevstack->mightsee;
  591. cansee = (long *)passage->cansee;
  592. might = (long *)stack.mightsee;
  593. memcpy(might, prevmight, portalbytes);
  594. if (p->status == stat_done)
  595. portalvis = (long *) p->portalvis;
  596. else
  597. portalvis = (long *) p->portalflood;
  598. more = 0;
  599. for (j = 0; j < portallongs; j++)
  600. {
  601. if (*might)
  602. {
  603. *might &= *cansee++ & *portalvis++;
  604. more |= (*might & ~vis[j]);
  605. }
  606. else
  607. {
  608. cansee++;
  609. portalvis++;
  610. }
  611. might++;
  612. }
  613. if ( !more ) {
  614. // can't see anything new
  615. continue;
  616. }
  617. // flow through it for real
  618. RecursivePassageFlow(p, thread, &stack);
  619. stack.next = NULL;
  620. }
  621. }
  622. /*
  623. ===============
  624. PassageFlow
  625. ===============
  626. */
  627. void PassageFlow (int portalnum)
  628. {
  629. threaddata_t data;
  630. int i;
  631. vportal_t *p;
  632. // int c_might, c_can;
  633. #ifdef MREDEBUG
  634. _printf("\r%6d", portalnum);
  635. #endif
  636. p = sorted_portals[portalnum];
  637. if (p->removed)
  638. {
  639. p->status = stat_done;
  640. return;
  641. }
  642. p->status = stat_working;
  643. // c_might = CountBits (p->portalflood, numportals*2);
  644. memset (&data, 0, sizeof(data));
  645. data.base = p;
  646. data.pstack_head.portal = p;
  647. data.pstack_head.source = p->winding;
  648. data.pstack_head.portalplane = p->plane;
  649. data.pstack_head.depth = 0;
  650. for (i=0 ; i<portallongs ; i++)
  651. ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
  652. RecursivePassageFlow (p, &data, &data.pstack_head);
  653. p->status = stat_done;
  654. /*
  655. c_can = CountBits (p->portalvis, numportals*2);
  656. qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n",
  657. (int)(p - portals), c_might, c_can, data.c_chains);
  658. */
  659. }
  660. /*
  661. ==================
  662. RecursivePassagePortalFlow
  663. ==================
  664. */
  665. void RecursivePassagePortalFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack)
  666. {
  667. pstack_t stack;
  668. vportal_t *p;
  669. leaf_t *leaf;
  670. plane_t backplane;
  671. passage_t *passage, *nextpassage;
  672. int i, j, n;
  673. long *might, *vis, *prevmight, *cansee, *portalvis, more;
  674. int pnum;
  675. // thread->c_chains++;
  676. leaf = &leafs[portal->leaf];
  677. // CheckStack (leaf, thread);
  678. prevstack->next = &stack;
  679. stack.next = NULL;
  680. stack.leaf = leaf;
  681. stack.portal = NULL;
  682. stack.depth = prevstack->depth + 1;
  683. #ifdef SEPERATORCACHE
  684. stack.numseperators[0] = 0;
  685. stack.numseperators[1] = 0;
  686. #endif
  687. vis = (long *)thread->base->portalvis;
  688. passage = portal->passages;
  689. nextpassage = passage;
  690. // check all portals for flowing into other leafs
  691. for (i = 0; i < leaf->numportals; i++, passage = nextpassage)
  692. {
  693. p = leaf->portals[i];
  694. if (p->removed)
  695. continue;
  696. nextpassage = passage->next;
  697. pnum = p - portals;
  698. if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
  699. continue; // can't possibly see it
  700. prevmight = (long *)prevstack->mightsee;
  701. cansee = (long *)passage->cansee;
  702. might = (long *)stack.mightsee;
  703. memcpy(might, prevmight, portalbytes);
  704. if (p->status == stat_done)
  705. portalvis = (long *) p->portalvis;
  706. else
  707. portalvis = (long *) p->portalflood;
  708. more = 0;
  709. for (j = 0; j < portallongs; j++)
  710. {
  711. if (*might)
  712. {
  713. *might &= *cansee++ & *portalvis++;
  714. more |= (*might & ~vis[j]);
  715. }
  716. else
  717. {
  718. cansee++;
  719. portalvis++;
  720. }
  721. might++;
  722. }
  723. if (!more && (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
  724. { // can't see anything new
  725. continue;
  726. }
  727. // get plane of portal, point normal into the neighbor leaf
  728. stack.portalplane = p->plane;
  729. VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
  730. backplane.dist = -p->plane.dist;
  731. // c_portalcheck++;
  732. stack.portal = p;
  733. stack.next = NULL;
  734. stack.freewindings[0] = 1;
  735. stack.freewindings[1] = 1;
  736. stack.freewindings[2] = 1;
  737. #if 1
  738. {
  739. float d;
  740. d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
  741. d -= thread->pstack_head.portalplane.dist;
  742. if (d < -p->radius)
  743. {
  744. continue;
  745. }
  746. else if (d > p->radius)
  747. {
  748. stack.pass = p->winding;
  749. }
  750. else
  751. {
  752. stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
  753. if (!stack.pass)
  754. continue;
  755. }
  756. }
  757. #else
  758. stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
  759. if (!stack.pass)
  760. continue;
  761. #endif
  762. #if 1
  763. {
  764. float d;
  765. d = DotProduct (thread->base->origin, p->plane.normal);
  766. d -= p->plane.dist;
  767. //MrE: vis-bug fix
  768. //if (d > p->radius)
  769. if (d > thread->base->radius)
  770. {
  771. continue;
  772. }
  773. //MrE: vis-bug fix
  774. //if (d < -p->radius)
  775. else if (d < -thread->base->radius)
  776. {
  777. stack.source = prevstack->source;
  778. }
  779. else
  780. {
  781. stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
  782. //FIXME: shouldn't we create a new source origin and radius for fast checks?
  783. if (!stack.source)
  784. continue;
  785. }
  786. }
  787. #else
  788. stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
  789. if (!stack.source)
  790. continue;
  791. #endif
  792. if (!prevstack->pass)
  793. { // the second leaf can only be blocked if coplanar
  794. // mark the portal as visible
  795. thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
  796. RecursivePassagePortalFlow (p, thread, &stack);
  797. continue;
  798. }
  799. #ifdef SEPERATORCACHE
  800. if (stack.numseperators[0])
  801. {
  802. for (n = 0; n < stack.numseperators[0]; n++)
  803. {
  804. stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]);
  805. if (!stack.pass)
  806. break; // target is not visible
  807. }
  808. if (n < stack.numseperators[0])
  809. continue;
  810. }
  811. else
  812. {
  813. stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack);
  814. }
  815. #else
  816. stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack);
  817. #endif
  818. if (!stack.pass)
  819. continue;
  820. #ifdef SEPERATORCACHE
  821. if (stack.numseperators[1])
  822. {
  823. for (n = 0; n < stack.numseperators[1]; n++)
  824. {
  825. stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]);
  826. if (!stack.pass)
  827. break; // target is not visible
  828. }
  829. }
  830. else
  831. {
  832. stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack);
  833. }
  834. #else
  835. stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack);
  836. #endif
  837. if (!stack.pass)
  838. continue;
  839. // mark the portal as visible
  840. thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
  841. // flow through it for real
  842. RecursivePassagePortalFlow(p, thread, &stack);
  843. //
  844. stack.next = NULL;
  845. }
  846. }
  847. /*
  848. ===============
  849. PassagePortalFlow
  850. ===============
  851. */
  852. void PassagePortalFlow (int portalnum)
  853. {
  854. threaddata_t data;
  855. int i;
  856. vportal_t *p;
  857. // int c_might, c_can;
  858. #ifdef MREDEBUG
  859. _printf("\r%6d", portalnum);
  860. #endif
  861. p = sorted_portals[portalnum];
  862. if (p->removed)
  863. {
  864. p->status = stat_done;
  865. return;
  866. }
  867. p->status = stat_working;
  868. // c_might = CountBits (p->portalflood, numportals*2);
  869. memset (&data, 0, sizeof(data));
  870. data.base = p;
  871. data.pstack_head.portal = p;
  872. data.pstack_head.source = p->winding;
  873. data.pstack_head.portalplane = p->plane;
  874. data.pstack_head.depth = 0;
  875. for (i=0 ; i<portallongs ; i++)
  876. ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
  877. RecursivePassagePortalFlow (p, &data, &data.pstack_head);
  878. p->status = stat_done;
  879. /*
  880. c_can = CountBits (p->portalvis, numportals*2);
  881. qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n",
  882. (int)(p - portals), c_might, c_can, data.c_chains);
  883. */
  884. }
  885. winding_t *PassageChopWinding (winding_t *in, winding_t *out, plane_t *split)
  886. {
  887. vec_t dists[128];
  888. int sides[128];
  889. int counts[3];
  890. vec_t dot;
  891. int i, j;
  892. vec_t *p1, *p2;
  893. vec3_t mid;
  894. winding_t *neww;
  895. counts[0] = counts[1] = counts[2] = 0;
  896. // determine sides for each point
  897. for (i=0 ; i<in->numpoints ; i++)
  898. {
  899. dot = DotProduct (in->points[i], split->normal);
  900. dot -= split->dist;
  901. dists[i] = dot;
  902. if (dot > ON_EPSILON)
  903. sides[i] = SIDE_FRONT;
  904. else if (dot < -ON_EPSILON)
  905. sides[i] = SIDE_BACK;
  906. else
  907. {
  908. sides[i] = SIDE_ON;
  909. }
  910. counts[sides[i]]++;
  911. }
  912. if (!counts[1])
  913. return in; // completely on front side
  914. if (!counts[0])
  915. {
  916. return NULL;
  917. }
  918. sides[i] = sides[0];
  919. dists[i] = dists[0];
  920. neww = out;
  921. neww->numpoints = 0;
  922. for (i=0 ; i<in->numpoints ; i++)
  923. {
  924. p1 = in->points[i];
  925. if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
  926. {
  927. return in; // can't chop -- fall back to original
  928. }
  929. if (sides[i] == SIDE_ON)
  930. {
  931. VectorCopy (p1, neww->points[neww->numpoints]);
  932. neww->numpoints++;
  933. continue;
  934. }
  935. if (sides[i] == SIDE_FRONT)
  936. {
  937. VectorCopy (p1, neww->points[neww->numpoints]);
  938. neww->numpoints++;
  939. }
  940. if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  941. continue;
  942. if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
  943. {
  944. return in; // can't chop -- fall back to original
  945. }
  946. // generate a split point
  947. p2 = in->points[(i+1)%in->numpoints];
  948. dot = dists[i] / (dists[i]-dists[i+1]);
  949. for (j=0 ; j<3 ; j++)
  950. { // avoid round off error when possible
  951. if (split->normal[j] == 1)
  952. mid[j] = split->dist;
  953. else if (split->normal[j] == -1)
  954. mid[j] = -split->dist;
  955. else
  956. mid[j] = p1[j] + dot*(p2[j]-p1[j]);
  957. }
  958. VectorCopy (mid, neww->points[neww->numpoints]);
  959. neww->numpoints++;
  960. }
  961. return neww;
  962. }
  963. /*
  964. ===============
  965. AddSeperators
  966. ===============
  967. */
  968. int AddSeperators (winding_t *source, winding_t *pass, qboolean flipclip, plane_t *seperators, int maxseperators)
  969. {
  970. int i, j, k, l;
  971. plane_t plane;
  972. vec3_t v1, v2;
  973. float d;
  974. vec_t length;
  975. int counts[3], numseperators;
  976. qboolean fliptest;
  977. numseperators = 0;
  978. // check all combinations
  979. for (i=0 ; i<source->numpoints ; i++)
  980. {
  981. l = (i+1)%source->numpoints;
  982. VectorSubtract (source->points[l] , source->points[i], v1);
  983. // find a vertex of pass that makes a plane that puts all of the
  984. // vertexes of pass on the front side and all of the vertexes of
  985. // source on the back side
  986. for (j=0 ; j<pass->numpoints ; j++)
  987. {
  988. VectorSubtract (pass->points[j], source->points[i], v2);
  989. plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
  990. plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
  991. plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
  992. // if points don't make a valid plane, skip it
  993. length = plane.normal[0] * plane.normal[0]
  994. + plane.normal[1] * plane.normal[1]
  995. + plane.normal[2] * plane.normal[2];
  996. if (length < ON_EPSILON)
  997. continue;
  998. length = 1/sqrt(length);
  999. plane.normal[0] *= length;
  1000. plane.normal[1] *= length;
  1001. plane.normal[2] *= length;
  1002. plane.dist = DotProduct (pass->points[j], plane.normal);
  1003. //
  1004. // find out which side of the generated seperating plane has the
  1005. // source portal
  1006. //
  1007. #if 1
  1008. fliptest = qfalse;
  1009. for (k=0 ; k<source->numpoints ; k++)
  1010. {
  1011. if (k == i || k == l)
  1012. continue;
  1013. d = DotProduct (source->points[k], plane.normal) - plane.dist;
  1014. if (d < -ON_EPSILON)
  1015. { // source is on the negative side, so we want all
  1016. // pass and target on the positive side
  1017. fliptest = qfalse;
  1018. break;
  1019. }
  1020. else if (d > ON_EPSILON)
  1021. { // source is on the positive side, so we want all
  1022. // pass and target on the negative side
  1023. fliptest = qtrue;
  1024. break;
  1025. }
  1026. }
  1027. if (k == source->numpoints)
  1028. continue; // planar with source portal
  1029. #else
  1030. fliptest = flipclip;
  1031. #endif
  1032. //
  1033. // flip the normal if the source portal is backwards
  1034. //
  1035. if (fliptest)
  1036. {
  1037. VectorSubtract (vec3_origin, plane.normal, plane.normal);
  1038. plane.dist = -plane.dist;
  1039. }
  1040. #if 1
  1041. //
  1042. // if all of the pass portal points are now on the positive side,
  1043. // this is the seperating plane
  1044. //
  1045. counts[0] = counts[1] = counts[2] = 0;
  1046. for (k=0 ; k<pass->numpoints ; k++)
  1047. {
  1048. if (k==j)
  1049. continue;
  1050. d = DotProduct (pass->points[k], plane.normal) - plane.dist;
  1051. if (d < -ON_EPSILON)
  1052. break;
  1053. else if (d > ON_EPSILON)
  1054. counts[0]++;
  1055. else
  1056. counts[2]++;
  1057. }
  1058. if (k != pass->numpoints)
  1059. continue; // points on negative side, not a seperating plane
  1060. if (!counts[0])
  1061. continue; // planar with seperating plane
  1062. #else
  1063. k = (j+1)%pass->numpoints;
  1064. d = DotProduct (pass->points[k], plane.normal) - plane.dist;
  1065. if (d < -ON_EPSILON)
  1066. continue;
  1067. k = (j+pass->numpoints-1)%pass->numpoints;
  1068. d = DotProduct (pass->points[k], plane.normal) - plane.dist;
  1069. if (d < -ON_EPSILON)
  1070. continue;
  1071. #endif
  1072. //
  1073. // flip the normal if we want the back side
  1074. //
  1075. if (flipclip)
  1076. {
  1077. VectorSubtract (vec3_origin, plane.normal, plane.normal);
  1078. plane.dist = -plane.dist;
  1079. }
  1080. if (numseperators >= maxseperators)
  1081. Error("max seperators");
  1082. seperators[numseperators] = plane;
  1083. numseperators++;
  1084. break;
  1085. }
  1086. }
  1087. return numseperators;
  1088. }
  1089. /*
  1090. ===============
  1091. CreatePassages
  1092. MrE: create passages from one portal to all the portals in the leaf the portal leads to
  1093. every passage has a cansee bit string with all the portals that can be
  1094. seen through the passage
  1095. ===============
  1096. */
  1097. void CreatePassages(int portalnum)
  1098. {
  1099. int i, j, k, n, numseperators, numsee;
  1100. float d;
  1101. vportal_t *portal, *p, *target;
  1102. leaf_t *leaf;
  1103. passage_t *passage, *lastpassage;
  1104. plane_t seperators[MAX_SEPERATORS*2];
  1105. winding_t *w;
  1106. winding_t in, out, *res;
  1107. #ifdef MREDEBUG
  1108. _printf("\r%6d", portalnum);
  1109. #endif
  1110. portal = sorted_portals[portalnum];
  1111. if (portal->removed)
  1112. {
  1113. portal->status = stat_done;
  1114. return;
  1115. }
  1116. lastpassage = NULL;
  1117. leaf = &leafs[portal->leaf];
  1118. for (i = 0; i < leaf->numportals; i++)
  1119. {
  1120. target = leaf->portals[i];
  1121. if (target->removed)
  1122. continue;
  1123. passage = (passage_t *) malloc(sizeof(passage_t) + portalbytes);
  1124. memset(passage, 0, sizeof(passage_t) + portalbytes);
  1125. numseperators = AddSeperators(portal->winding, target->winding, qfalse, seperators, MAX_SEPERATORS*2);
  1126. numseperators += AddSeperators(target->winding, portal->winding, qtrue, &seperators[numseperators], MAX_SEPERATORS*2-numseperators);
  1127. passage->next = NULL;
  1128. if (lastpassage)
  1129. lastpassage->next = passage;
  1130. else
  1131. portal->passages = passage;
  1132. lastpassage = passage;
  1133. numsee = 0;
  1134. //create the passage->cansee
  1135. for (j = 0; j < numportals * 2; j++)
  1136. {
  1137. p = &portals[j];
  1138. if (p->removed)
  1139. continue;
  1140. if ( ! (target->portalflood[j >> 3] & (1<<(j&7)) ) )
  1141. continue;
  1142. if ( ! (portal->portalflood[j >> 3] & (1<<(j&7)) ) )
  1143. continue;
  1144. for (k = 0; k < numseperators; k++)
  1145. {
  1146. //
  1147. d = DotProduct (p->origin, seperators[k].normal) - seperators[k].dist;
  1148. //if completely at the back of the seperator plane
  1149. if (d < -p->radius + ON_EPSILON)
  1150. break;
  1151. w = p->winding;
  1152. for (n = 0; n < w->numpoints; n++)
  1153. {
  1154. d = DotProduct (w->points[n], seperators[k].normal) - seperators[k].dist;
  1155. //if at the front of the seperator
  1156. if (d > ON_EPSILON)
  1157. break;
  1158. }
  1159. //if no points are at the front of the seperator
  1160. if (n >= w->numpoints)
  1161. break;
  1162. }
  1163. if (k < numseperators)
  1164. continue;
  1165. memcpy(&in, p->winding, sizeof(winding_t));
  1166. for (k = 0; k < numseperators; k++)
  1167. {
  1168. res = PassageChopWinding(&in, &out, &seperators[k]);
  1169. if (res == &out)
  1170. memcpy(&in, &out, sizeof(winding_t));
  1171. if (res == NULL)
  1172. break;
  1173. }
  1174. if (k < numseperators)
  1175. continue;
  1176. passage->cansee[j >> 3] |= (1<<(j&7));
  1177. numsee++;
  1178. }
  1179. }
  1180. }
  1181. void PassageMemory(void)
  1182. {
  1183. int i, j, totalmem, totalportals;
  1184. vportal_t *portal, *target;
  1185. leaf_t *leaf;
  1186. totalmem = 0;
  1187. totalportals = 0;
  1188. for (i = 0; i < numportals; i++)
  1189. {
  1190. portal = sorted_portals[i];
  1191. if (portal->removed)
  1192. continue;
  1193. leaf = &leafs[portal->leaf];
  1194. for (j = 0; j < leaf->numportals; j++)
  1195. {
  1196. target = leaf->portals[j];
  1197. if (target->removed)
  1198. continue;
  1199. totalmem += sizeof(passage_t) + portalbytes;
  1200. totalportals++;
  1201. }
  1202. }
  1203. _printf("%7i average number of passages per leaf\n", totalportals / numportals);
  1204. _printf("%7i MB required passage memory\n", totalmem >> 10 >> 10);
  1205. }
  1206. /*
  1207. ===============================================================================
  1208. This is a rough first-order aproximation that is used to trivially reject some
  1209. of the final calculations.
  1210. Calculates portalfront and portalflood bit vectors
  1211. thinking about:
  1212. typedef struct passage_s
  1213. {
  1214. struct passage_s *next;
  1215. struct portal_s *to;
  1216. stryct sep_s *seperators;
  1217. byte *mightsee;
  1218. } passage_t;
  1219. typedef struct portal_s
  1220. {
  1221. struct passage_s *passages;
  1222. int leaf; // leaf portal faces into
  1223. } portal_s;
  1224. leaf = portal->leaf
  1225. clear
  1226. for all portals
  1227. calc portal visibility
  1228. clear bit vector
  1229. for all passages
  1230. passage visibility
  1231. for a portal to be visible to a passage, it must be on the front of
  1232. all seperating planes, and both portals must be behind the new portal
  1233. ===============================================================================
  1234. */
  1235. int c_flood, c_vis;
  1236. /*
  1237. ==================
  1238. SimpleFlood
  1239. ==================
  1240. */
  1241. void SimpleFlood (vportal_t *srcportal, int leafnum)
  1242. {
  1243. int i;
  1244. leaf_t *leaf;
  1245. vportal_t *p;
  1246. int pnum;
  1247. leaf = &leafs[leafnum];
  1248. for (i=0 ; i<leaf->numportals ; i++)
  1249. {
  1250. p = leaf->portals[i];
  1251. if (p->removed)
  1252. continue;
  1253. pnum = p - portals;
  1254. if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) )
  1255. continue;
  1256. if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) )
  1257. continue;
  1258. srcportal->portalflood[pnum>>3] |= (1<<(pnum&7));
  1259. SimpleFlood (srcportal, p->leaf);
  1260. }
  1261. }
  1262. /*
  1263. ==============
  1264. BasePortalVis
  1265. ==============
  1266. */
  1267. void BasePortalVis (int portalnum)
  1268. {
  1269. int j, k;
  1270. vportal_t *tp, *p;
  1271. float d;
  1272. winding_t *w;
  1273. p = portals+portalnum;
  1274. if (p->removed)
  1275. return;
  1276. p->portalfront = malloc (portalbytes);
  1277. memset (p->portalfront, 0, portalbytes);
  1278. p->portalflood = malloc (portalbytes);
  1279. memset (p->portalflood, 0, portalbytes);
  1280. p->portalvis = malloc (portalbytes);
  1281. memset (p->portalvis, 0, portalbytes);
  1282. for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
  1283. {
  1284. if (j == portalnum)
  1285. continue;
  1286. if (tp->removed)
  1287. continue;
  1288. /*
  1289. if (farplanedist >= 0)
  1290. {
  1291. vec3_t dir;
  1292. VectorSubtract(p->origin, tp->origin, dir);
  1293. if (VectorLength(dir) > farplanedist - p->radius - tp->radius)
  1294. continue;
  1295. }
  1296. */
  1297. w = tp->winding;
  1298. for (k=0 ; k<w->numpoints ; k++)
  1299. {
  1300. d = DotProduct (w->points[k], p->plane.normal)
  1301. - p->plane.dist;
  1302. if (d > ON_EPSILON)
  1303. break;
  1304. }
  1305. if (k == w->numpoints)
  1306. continue; // no points on front
  1307. w = p->winding;
  1308. for (k=0 ; k<w->numpoints ; k++)
  1309. {
  1310. d = DotProduct (w->points[k], tp->plane.normal)
  1311. - tp->plane.dist;
  1312. if (d < -ON_EPSILON)
  1313. break;
  1314. }
  1315. if (k == w->numpoints)
  1316. continue; // no points on front
  1317. p->portalfront[j>>3] |= (1<<(j&7));
  1318. }
  1319. SimpleFlood (p, p->leaf);
  1320. p->nummightsee = CountBits (p->portalflood, numportals*2);
  1321. // _printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee);
  1322. c_flood += p->nummightsee;
  1323. }
  1324. /*
  1325. ===============================================================================
  1326. This is a second order aproximation
  1327. Calculates portalvis bit vector
  1328. WAAAAAAY too slow.
  1329. ===============================================================================
  1330. */
  1331. /*
  1332. ==================
  1333. RecursiveLeafBitFlow
  1334. ==================
  1335. */
  1336. void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee)
  1337. {
  1338. vportal_t *p;
  1339. leaf_t *leaf;
  1340. int i, j;
  1341. long more;
  1342. int pnum;
  1343. byte newmight[MAX_PORTALS/8];
  1344. leaf = &leafs[leafnum];
  1345. // check all portals for flowing into other leafs
  1346. for (i=0 ; i<leaf->numportals ; i++)
  1347. {
  1348. p = leaf->portals[i];
  1349. if (p->removed)
  1350. continue;
  1351. pnum = p - portals;
  1352. // if some previous portal can't see it, skip
  1353. if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) )
  1354. continue;
  1355. // if this portal can see some portals we mightsee, recurse
  1356. more = 0;
  1357. for (j=0 ; j<portallongs ; j++)
  1358. {
  1359. ((long *)newmight)[j] = ((long *)mightsee)[j]
  1360. & ((long *)p->portalflood)[j];
  1361. more |= ((long *)newmight)[j] & ~((long *)cansee)[j];
  1362. }
  1363. if (!more)
  1364. continue; // can't see anything new
  1365. cansee[pnum>>3] |= (1<<(pnum&7));
  1366. RecursiveLeafBitFlow (p->leaf, newmight, cansee);
  1367. }
  1368. }
  1369. /*
  1370. ==============
  1371. BetterPortalVis
  1372. ==============
  1373. */
  1374. void BetterPortalVis (int portalnum)
  1375. {
  1376. vportal_t *p;
  1377. p = portals+portalnum;
  1378. if (p->removed)
  1379. return;
  1380. RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis);
  1381. // build leaf vis information
  1382. p->nummightsee = CountBits (p->portalvis, numportals*2);
  1383. c_vis += p->nummightsee;
  1384. }