00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "vis.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 int CountBits (byte *bits, int numbits)
00044 {
00045 int i;
00046 int c;
00047
00048 c = 0;
00049 for (i=0 ; i<numbits ; i++)
00050 if (bits[i>>3] & (1<<(i&7)) )
00051 c++;
00052
00053 return c;
00054 }
00055
00056 int c_fullskip;
00057 int c_portalskip, c_leafskip;
00058 int c_vistest, c_mighttest;
00059
00060 int c_chop, c_nochop;
00061
00062 int active;
00063
00064 void CheckStack (leaf_t *leaf, threaddata_t *thread)
00065 {
00066 pstack_t *p, *p2;
00067
00068 for (p=thread->pstack_head.next ; p ; p=p->next)
00069 {
00070
00071 if (p->leaf == leaf)
00072 Error ("CheckStack: leaf recursion");
00073 for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next)
00074 if (p2->leaf == p->leaf)
00075 Error ("CheckStack: late leaf recursion");
00076 }
00077
00078 }
00079
00080
00081 winding_t *AllocStackWinding (pstack_t *stack)
00082 {
00083 int i;
00084
00085 for (i=0 ; i<3 ; i++)
00086 {
00087 if (stack->freewindings[i])
00088 {
00089 stack->freewindings[i] = 0;
00090 return &stack->windings[i];
00091 }
00092 }
00093
00094 Error ("AllocStackWinding: failed");
00095
00096 return NULL;
00097 }
00098
00099 void FreeStackWinding (winding_t *w, pstack_t *stack)
00100 {
00101 int i;
00102
00103 i = w - stack->windings;
00104
00105 if (i<0 || i>2)
00106 return;
00107
00108 if (stack->freewindings[i])
00109 Error ("FreeStackWinding: allready free");
00110 stack->freewindings[i] = 1;
00111 }
00112
00113
00114
00115
00116
00117
00118
00119 winding_t *VisChopWinding (winding_t *in, pstack_t *stack, plane_t *split)
00120 {
00121 vec_t dists[128];
00122 int sides[128];
00123 int counts[3];
00124 vec_t dot;
00125 int i, j;
00126 vec_t *p1, *p2;
00127 vec3_t mid;
00128 winding_t *neww;
00129
00130 counts[0] = counts[1] = counts[2] = 0;
00131
00132
00133 for (i=0 ; i<in->numpoints ; i++)
00134 {
00135 dot = DotProduct (in->points[i], split->normal);
00136 dot -= split->dist;
00137 dists[i] = dot;
00138 if (dot > ON_EPSILON)
00139 sides[i] = SIDE_FRONT;
00140 else if (dot < -ON_EPSILON)
00141 sides[i] = SIDE_BACK;
00142 else
00143 {
00144 sides[i] = SIDE_ON;
00145 }
00146 counts[sides[i]]++;
00147 }
00148
00149 if (!counts[1])
00150 return in;
00151
00152 if (!counts[0])
00153 {
00154 FreeStackWinding (in, stack);
00155 return NULL;
00156 }
00157
00158 sides[i] = sides[0];
00159 dists[i] = dists[0];
00160
00161 neww = AllocStackWinding (stack);
00162
00163 neww->numpoints = 0;
00164
00165 for (i=0 ; i<in->numpoints ; i++)
00166 {
00167 p1 = in->points[i];
00168
00169 if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
00170 {
00171 FreeStackWinding (neww, stack);
00172 return in;
00173 }
00174
00175 if (sides[i] == SIDE_ON)
00176 {
00177 VectorCopy (p1, neww->points[neww->numpoints]);
00178 neww->numpoints++;
00179 continue;
00180 }
00181
00182 if (sides[i] == SIDE_FRONT)
00183 {
00184 VectorCopy (p1, neww->points[neww->numpoints]);
00185 neww->numpoints++;
00186 }
00187
00188 if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
00189 continue;
00190
00191 if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
00192 {
00193 FreeStackWinding (neww, stack);
00194 return in;
00195 }
00196
00197
00198 p2 = in->points[(i+1)%in->numpoints];
00199
00200 dot = dists[i] / (dists[i]-dists[i+1]);
00201 for (j=0 ; j<3 ; j++)
00202 {
00203 if (split->normal[j] == 1)
00204 mid[j] = split->dist;
00205 else if (split->normal[j] == -1)
00206 mid[j] = -split->dist;
00207 else
00208 mid[j] = p1[j] + dot*(p2[j]-p1[j]);
00209 }
00210
00211 VectorCopy (mid, neww->points[neww->numpoints]);
00212 neww->numpoints++;
00213 }
00214
00215
00216 FreeStackWinding (in, stack);
00217
00218 return neww;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 winding_t *ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip, pstack_t *stack)
00238 {
00239 int i, j, k, l;
00240 plane_t plane;
00241 vec3_t v1, v2;
00242 float d;
00243 vec_t length;
00244 int counts[3];
00245 qboolean fliptest;
00246
00247
00248 for (i=0 ; i<source->numpoints ; i++)
00249 {
00250 l = (i+1)%source->numpoints;
00251 VectorSubtract (source->points[l] , source->points[i], v1);
00252
00253
00254
00255
00256 for (j=0 ; j<pass->numpoints ; j++)
00257 {
00258 VectorSubtract (pass->points[j], source->points[i], v2);
00259
00260 plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
00261 plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
00262 plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
00263
00264
00265
00266 length = plane.normal[0] * plane.normal[0]
00267 + plane.normal[1] * plane.normal[1]
00268 + plane.normal[2] * plane.normal[2];
00269
00270 if (length < ON_EPSILON)
00271 continue;
00272
00273 length = 1/sqrt(length);
00274
00275 plane.normal[0] *= length;
00276 plane.normal[1] *= length;
00277 plane.normal[2] *= length;
00278
00279 plane.dist = DotProduct (pass->points[j], plane.normal);
00280
00281
00282
00283
00284
00285 #if 1
00286 fliptest = qfalse;
00287 for (k=0 ; k<source->numpoints ; k++)
00288 {
00289 if (k == i || k == l)
00290 continue;
00291 d = DotProduct (source->points[k], plane.normal) - plane.dist;
00292 if (d < -ON_EPSILON)
00293 {
00294
00295 fliptest = qfalse;
00296 break;
00297 }
00298 else if (d > ON_EPSILON)
00299 {
00300
00301 fliptest = qtrue;
00302 break;
00303 }
00304 }
00305 if (k == source->numpoints)
00306 continue;
00307 #else
00308 fliptest = flipclip;
00309 #endif
00310
00311
00312
00313 if (fliptest)
00314 {
00315 VectorSubtract (vec3_origin, plane.normal, plane.normal);
00316 plane.dist = -plane.dist;
00317 }
00318 #if 1
00319
00320
00321
00322
00323 counts[0] = counts[1] = counts[2] = 0;
00324 for (k=0 ; k<pass->numpoints ; k++)
00325 {
00326 if (k==j)
00327 continue;
00328 d = DotProduct (pass->points[k], plane.normal) - plane.dist;
00329 if (d < -ON_EPSILON)
00330 break;
00331 else if (d > ON_EPSILON)
00332 counts[0]++;
00333 else
00334 counts[2]++;
00335 }
00336 if (k != pass->numpoints)
00337 continue;
00338
00339 if (!counts[0])
00340 continue;
00341 #else
00342 k = (j+1)%pass->numpoints;
00343 d = DotProduct (pass->points[k], plane.normal) - plane.dist;
00344 if (d < -ON_EPSILON)
00345 continue;
00346 k = (j+pass->numpoints-1)%pass->numpoints;
00347 d = DotProduct (pass->points[k], plane.normal) - plane.dist;
00348 if (d < -ON_EPSILON)
00349 continue;
00350 #endif
00351
00352
00353
00354 if (flipclip)
00355 {
00356 VectorSubtract (vec3_origin, plane.normal, plane.normal);
00357 plane.dist = -plane.dist;
00358 }
00359
00360 #ifdef SEPERATORCACHE
00361 stack->seperators[flipclip][stack->numseperators[flipclip]] = plane;
00362 if (++stack->numseperators[flipclip] >= MAX_SEPERATORS)
00363 Error("MAX_SEPERATORS");
00364 #endif
00365
00366 d = DotProduct (stack->portal->origin, plane.normal) - plane.dist;
00367
00368 if (d < -stack->portal->radius)
00369 return NULL;
00370
00371 if (d > stack->portal->radius)
00372 break;
00373
00374
00375
00376
00377 target = VisChopWinding (target, stack, &plane);
00378 if (!target)
00379 return NULL;
00380
00381 break;
00382 }
00383 }
00384
00385 return target;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
00397 {
00398 pstack_t stack;
00399 vportal_t *p;
00400 plane_t backplane;
00401 leaf_t *leaf;
00402 int i, j, n;
00403 long *test, *might, *prevmight, *vis, more;
00404 int pnum;
00405
00406 thread->c_chains++;
00407
00408 leaf = &leafs[leafnum];
00409
00410
00411 prevstack->next = &stack;
00412
00413 stack.next = NULL;
00414 stack.leaf = leaf;
00415 stack.portal = NULL;
00416 stack.depth = prevstack->depth + 1;
00417
00418 #ifdef SEPERATORCACHE
00419 stack.numseperators[0] = 0;
00420 stack.numseperators[1] = 0;
00421 #endif
00422
00423 might = (long *)stack.mightsee;
00424 vis = (long *)thread->base->portalvis;
00425
00426
00427 for (i = 0; i < leaf->numportals; i++)
00428 {
00429 p = leaf->portals[i];
00430 if (p->removed)
00431 continue;
00432 pnum = p - portals;
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
00454 {
00455 continue;
00456 }
00457
00458
00459 if (p->status == stat_done)
00460 {
00461 test = (long *)p->portalvis;
00462 }
00463 else
00464 {
00465 test = (long *)p->portalflood;
00466 }
00467
00468 more = 0;
00469 prevmight = (long *)prevstack->mightsee;
00470 for (j=0 ; j<portallongs ; j++)
00471 {
00472 might[j] = prevmight[j] & test[j];
00473 more |= (might[j] & ~vis[j]);
00474 }
00475
00476 if (!more &&
00477 (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
00478 {
00479 continue;
00480 }
00481
00482
00483 stack.portalplane = p->plane;
00484 VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
00485 backplane.dist = -p->plane.dist;
00486
00487
00488
00489 stack.portal = p;
00490 stack.next = NULL;
00491 stack.freewindings[0] = 1;
00492 stack.freewindings[1] = 1;
00493 stack.freewindings[2] = 1;
00494
00495 #if 1
00496 {
00497 float d;
00498
00499 d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
00500 d -= thread->pstack_head.portalplane.dist;
00501 if (d < -p->radius)
00502 {
00503 continue;
00504 }
00505 else if (d > p->radius)
00506 {
00507 stack.pass = p->winding;
00508 }
00509 else
00510 {
00511 stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
00512 if (!stack.pass)
00513 continue;
00514 }
00515 }
00516 #else
00517 stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
00518 if (!stack.pass)
00519 continue;
00520 #endif
00521
00522
00523 #if 1
00524 {
00525 float d;
00526
00527 d = DotProduct (thread->base->origin, p->plane.normal);
00528 d -= p->plane.dist;
00529
00530
00531 if (d > thread->base->radius)
00532 {
00533 continue;
00534 }
00535
00536
00537 else if (d < -thread->base->radius)
00538 {
00539 stack.source = prevstack->source;
00540 }
00541 else
00542 {
00543 stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
00544
00545 if (!stack.source)
00546 continue;
00547 }
00548 }
00549 #else
00550 stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
00551 if (!stack.source)
00552 continue;
00553 #endif
00554
00555 if (!prevstack->pass)
00556 {
00557
00558
00559 thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
00560
00561 RecursiveLeafFlow (p->leaf, thread, &stack);
00562 continue;
00563 }
00564
00565 #ifdef SEPERATORCACHE
00566 if (stack.numseperators[0])
00567 {
00568 for (n = 0; n < stack.numseperators[0]; n++)
00569 {
00570 stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]);
00571 if (!stack.pass)
00572 break;
00573 }
00574 if (n < stack.numseperators[0])
00575 continue;
00576 }
00577 else
00578 {
00579 stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack);
00580 }
00581 #else
00582 stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack);
00583 #endif
00584 if (!stack.pass)
00585 continue;
00586
00587 #ifdef SEPERATORCACHE
00588 if (stack.numseperators[1])
00589 {
00590 for (n = 0; n < stack.numseperators[1]; n++)
00591 {
00592 stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]);
00593 if (!stack.pass)
00594 break;
00595 }
00596 }
00597 else
00598 {
00599 stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack);
00600 }
00601 #else
00602 stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack);
00603 #endif
00604 if (!stack.pass)
00605 continue;
00606
00607
00608 thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
00609
00610
00611 RecursiveLeafFlow (p->leaf, thread, &stack);
00612
00613 stack.next = NULL;
00614 }
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624 void PortalFlow (int portalnum)
00625 {
00626 threaddata_t data;
00627 int i;
00628 vportal_t *p;
00629 int c_might, c_can;
00630
00631 #ifdef MREDEBUG
00632 _printf("\r%6d", portalnum);
00633 #endif
00634
00635 p = sorted_portals[portalnum];
00636
00637 if (p->removed)
00638 {
00639 p->status = stat_done;
00640 return;
00641 }
00642
00643 p->status = stat_working;
00644
00645 c_might = CountBits (p->portalflood, numportals*2);
00646
00647 memset (&data, 0, sizeof(data));
00648 data.base = p;
00649
00650 data.pstack_head.portal = p;
00651 data.pstack_head.source = p->winding;
00652 data.pstack_head.portalplane = p->plane;
00653 data.pstack_head.depth = 0;
00654 for (i=0 ; i<portallongs ; i++)
00655 ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
00656
00657 RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
00658
00659 p->status = stat_done;
00660
00661 c_can = CountBits (p->portalvis, numportals*2);
00662
00663 qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n",
00664 (int)(p - portals), c_might, c_can, data.c_chains);
00665 }
00666
00667
00668
00669
00670
00671
00672 void RecursivePassageFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack)
00673 {
00674 pstack_t stack;
00675 vportal_t *p;
00676 leaf_t *leaf;
00677 passage_t *passage, *nextpassage;
00678 int i, j;
00679 long *might, *vis, *prevmight, *cansee, *portalvis, more;
00680 int pnum;
00681
00682 leaf = &leafs[portal->leaf];
00683
00684 prevstack->next = &stack;
00685
00686 stack.next = NULL;
00687 stack.depth = prevstack->depth + 1;
00688
00689 vis = (long *)thread->base->portalvis;
00690
00691 passage = portal->passages;
00692 nextpassage = passage;
00693
00694 for (i = 0; i < leaf->numportals; i++, passage = nextpassage)
00695 {
00696 p = leaf->portals[i];
00697 if ( p->removed ) {
00698 continue;
00699 }
00700 nextpassage = passage->next;
00701 pnum = p - portals;
00702
00703 if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) {
00704 continue;
00705 }
00706
00707
00708 thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
00709
00710 prevmight = (long *)prevstack->mightsee;
00711 cansee = (long *)passage->cansee;
00712 might = (long *)stack.mightsee;
00713 memcpy(might, prevmight, portalbytes);
00714 if (p->status == stat_done)
00715 portalvis = (long *) p->portalvis;
00716 else
00717 portalvis = (long *) p->portalflood;
00718 more = 0;
00719 for (j = 0; j < portallongs; j++)
00720 {
00721 if (*might)
00722 {
00723 *might &= *cansee++ & *portalvis++;
00724 more |= (*might & ~vis[j]);
00725 }
00726 else
00727 {
00728 cansee++;
00729 portalvis++;
00730 }
00731 might++;
00732 }
00733
00734 if ( !more ) {
00735
00736 continue;
00737 }
00738
00739
00740 RecursivePassageFlow(p, thread, &stack);
00741
00742 stack.next = NULL;
00743 }
00744 }
00745
00746
00747
00748
00749
00750
00751 void PassageFlow (int portalnum)
00752 {
00753 threaddata_t data;
00754 int i;
00755 vportal_t *p;
00756
00757
00758 #ifdef MREDEBUG
00759 _printf("\r%6d", portalnum);
00760 #endif
00761
00762 p = sorted_portals[portalnum];
00763
00764 if (p->removed)
00765 {
00766 p->status = stat_done;
00767 return;
00768 }
00769
00770 p->status = stat_working;
00771
00772
00773
00774 memset (&data, 0, sizeof(data));
00775 data.base = p;
00776
00777 data.pstack_head.portal = p;
00778 data.pstack_head.source = p->winding;
00779 data.pstack_head.portalplane = p->plane;
00780 data.pstack_head.depth = 0;
00781 for (i=0 ; i<portallongs ; i++)
00782 ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
00783
00784 RecursivePassageFlow (p, &data, &data.pstack_head);
00785
00786 p->status = stat_done;
00787
00788
00789
00790
00791
00792
00793
00794 }
00795
00796
00797
00798
00799
00800
00801 void RecursivePassagePortalFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack)
00802 {
00803 pstack_t stack;
00804 vportal_t *p;
00805 leaf_t *leaf;
00806 plane_t backplane;
00807 passage_t *passage, *nextpassage;
00808 int i, j, n;
00809 long *might, *vis, *prevmight, *cansee, *portalvis, more;
00810 int pnum;
00811
00812
00813
00814 leaf = &leafs[portal->leaf];
00815
00816
00817 prevstack->next = &stack;
00818
00819 stack.next = NULL;
00820 stack.leaf = leaf;
00821 stack.portal = NULL;
00822 stack.depth = prevstack->depth + 1;
00823
00824 #ifdef SEPERATORCACHE
00825 stack.numseperators[0] = 0;
00826 stack.numseperators[1] = 0;
00827 #endif
00828
00829 vis = (long *)thread->base->portalvis;
00830
00831 passage = portal->passages;
00832 nextpassage = passage;
00833
00834 for (i = 0; i < leaf->numportals; i++, passage = nextpassage)
00835 {
00836 p = leaf->portals[i];
00837 if (p->removed)
00838 continue;
00839 nextpassage = passage->next;
00840 pnum = p - portals;
00841
00842 if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
00843 continue;
00844
00845 prevmight = (long *)prevstack->mightsee;
00846 cansee = (long *)passage->cansee;
00847 might = (long *)stack.mightsee;
00848 memcpy(might, prevmight, portalbytes);
00849 if (p->status == stat_done)
00850 portalvis = (long *) p->portalvis;
00851 else
00852 portalvis = (long *) p->portalflood;
00853 more = 0;
00854 for (j = 0; j < portallongs; j++)
00855 {
00856 if (*might)
00857 {
00858 *might &= *cansee++ & *portalvis++;
00859 more |= (*might & ~vis[j]);
00860 }
00861 else
00862 {
00863 cansee++;
00864 portalvis++;
00865 }
00866 might++;
00867 }
00868
00869 if (!more && (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
00870 {
00871 continue;
00872 }
00873
00874
00875 stack.portalplane = p->plane;
00876 VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
00877 backplane.dist = -p->plane.dist;
00878
00879
00880
00881 stack.portal = p;
00882 stack.next = NULL;
00883 stack.freewindings[0] = 1;
00884 stack.freewindings[1] = 1;
00885 stack.freewindings[2] = 1;
00886
00887 #if 1
00888 {
00889 float d;
00890
00891 d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
00892 d -= thread->pstack_head.portalplane.dist;
00893 if (d < -p->radius)
00894 {
00895 continue;
00896 }
00897 else if (d > p->radius)
00898 {
00899 stack.pass = p->winding;
00900 }
00901 else
00902 {
00903 stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
00904 if (!stack.pass)
00905 continue;
00906 }
00907 }
00908 #else
00909 stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
00910 if (!stack.pass)
00911 continue;
00912 #endif
00913
00914
00915 #if 1
00916 {
00917 float d;
00918
00919 d = DotProduct (thread->base->origin, p->plane.normal);
00920 d -= p->plane.dist;
00921
00922
00923 if (d > thread->base->radius)
00924 {
00925 continue;
00926 }
00927
00928
00929 else if (d < -thread->base->radius)
00930 {
00931 stack.source = prevstack->source;
00932 }
00933 else
00934 {
00935 stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
00936
00937 if (!stack.source)
00938 continue;
00939 }
00940 }
00941 #else
00942 stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
00943 if (!stack.source)
00944 continue;
00945 #endif
00946
00947 if (!prevstack->pass)
00948 {
00949
00950
00951 thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
00952
00953 RecursivePassagePortalFlow (p, thread, &stack);
00954 continue;
00955 }
00956
00957 #ifdef SEPERATORCACHE
00958 if (stack.numseperators[0])
00959 {
00960 for (n = 0; n < stack.numseperators[0]; n++)
00961 {
00962 stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]);
00963 if (!stack.pass)
00964 break;
00965 }
00966 if (n < stack.numseperators[0])
00967 continue;
00968 }
00969 else
00970 {
00971 stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack);
00972 }
00973 #else
00974 stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack);
00975 #endif
00976 if (!stack.pass)
00977 continue;
00978
00979 #ifdef SEPERATORCACHE
00980 if (stack.numseperators[1])
00981 {
00982 for (n = 0; n < stack.numseperators[1]; n++)
00983 {
00984 stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]);
00985 if (!stack.pass)
00986 break;
00987 }
00988 }
00989 else
00990 {
00991 stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack);
00992 }
00993 #else
00994 stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack);
00995 #endif
00996 if (!stack.pass)
00997 continue;
00998
00999
01000 thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
01001
01002
01003 RecursivePassagePortalFlow(p, thread, &stack);
01004
01005 stack.next = NULL;
01006 }
01007 }
01008
01009
01010
01011
01012
01013
01014 void PassagePortalFlow (int portalnum)
01015 {
01016 threaddata_t data;
01017 int i;
01018 vportal_t *p;
01019
01020
01021 #ifdef MREDEBUG
01022 _printf("\r%6d", portalnum);
01023 #endif
01024
01025 p = sorted_portals[portalnum];
01026
01027 if (p->removed)
01028 {
01029 p->status = stat_done;
01030 return;
01031 }
01032
01033 p->status = stat_working;
01034
01035
01036
01037 memset (&data, 0, sizeof(data));
01038 data.base = p;
01039
01040 data.pstack_head.portal = p;
01041 data.pstack_head.source = p->winding;
01042 data.pstack_head.portalplane = p->plane;
01043 data.pstack_head.depth = 0;
01044 for (i=0 ; i<portallongs ; i++)
01045 ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
01046
01047 RecursivePassagePortalFlow (p, &data, &data.pstack_head);
01048
01049 p->status = stat_done;
01050
01051
01052
01053
01054
01055
01056
01057 }
01058
01059 winding_t *PassageChopWinding (winding_t *in, winding_t *out, plane_t *split)
01060 {
01061 vec_t dists[128];
01062 int sides[128];
01063 int counts[3];
01064 vec_t dot;
01065 int i, j;
01066 vec_t *p1, *p2;
01067 vec3_t mid;
01068 winding_t *neww;
01069
01070 counts[0] = counts[1] = counts[2] = 0;
01071
01072
01073 for (i=0 ; i<in->numpoints ; i++)
01074 {
01075 dot = DotProduct (in->points[i], split->normal);
01076 dot -= split->dist;
01077 dists[i] = dot;
01078 if (dot > ON_EPSILON)
01079 sides[i] = SIDE_FRONT;
01080 else if (dot < -ON_EPSILON)
01081 sides[i] = SIDE_BACK;
01082 else
01083 {
01084 sides[i] = SIDE_ON;
01085 }
01086 counts[sides[i]]++;
01087 }
01088
01089 if (!counts[1])
01090 return in;
01091
01092 if (!counts[0])
01093 {
01094 return NULL;
01095 }
01096
01097 sides[i] = sides[0];
01098 dists[i] = dists[0];
01099
01100 neww = out;
01101
01102 neww->numpoints = 0;
01103
01104 for (i=0 ; i<in->numpoints ; i++)
01105 {
01106 p1 = in->points[i];
01107
01108 if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
01109 {
01110 return in;
01111 }
01112
01113 if (sides[i] == SIDE_ON)
01114 {
01115 VectorCopy (p1, neww->points[neww->numpoints]);
01116 neww->numpoints++;
01117 continue;
01118 }
01119
01120 if (sides[i] == SIDE_FRONT)
01121 {
01122 VectorCopy (p1, neww->points[neww->numpoints]);
01123 neww->numpoints++;
01124 }
01125
01126 if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
01127 continue;
01128
01129 if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
01130 {
01131 return in;
01132 }
01133
01134
01135 p2 = in->points[(i+1)%in->numpoints];
01136
01137 dot = dists[i] / (dists[i]-dists[i+1]);
01138 for (j=0 ; j<3 ; j++)
01139 {
01140 if (split->normal[j] == 1)
01141 mid[j] = split->dist;
01142 else if (split->normal[j] == -1)
01143 mid[j] = -split->dist;
01144 else
01145 mid[j] = p1[j] + dot*(p2[j]-p1[j]);
01146 }
01147
01148 VectorCopy (mid, neww->points[neww->numpoints]);
01149 neww->numpoints++;
01150 }
01151
01152 return neww;
01153 }
01154
01155
01156
01157
01158
01159
01160 int AddSeperators (winding_t *source, winding_t *pass, qboolean flipclip, plane_t *seperators, int maxseperators)
01161 {
01162 int i, j, k, l;
01163 plane_t plane;
01164 vec3_t v1, v2;
01165 float d;
01166 vec_t length;
01167 int counts[3], numseperators;
01168 qboolean fliptest;
01169
01170 numseperators = 0;
01171
01172 for (i=0 ; i<source->numpoints ; i++)
01173 {
01174 l = (i+1)%source->numpoints;
01175 VectorSubtract (source->points[l] , source->points[i], v1);
01176
01177
01178
01179
01180 for (j=0 ; j<pass->numpoints ; j++)
01181 {
01182 VectorSubtract (pass->points[j], source->points[i], v2);
01183
01184 plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
01185 plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
01186 plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
01187
01188
01189
01190 length = plane.normal[0] * plane.normal[0]
01191 + plane.normal[1] * plane.normal[1]
01192 + plane.normal[2] * plane.normal[2];
01193
01194 if (length < ON_EPSILON)
01195 continue;
01196
01197 length = 1/sqrt(length);
01198
01199 plane.normal[0] *= length;
01200 plane.normal[1] *= length;
01201 plane.normal[2] *= length;
01202
01203 plane.dist = DotProduct (pass->points[j], plane.normal);
01204
01205
01206
01207
01208
01209 #if 1
01210 fliptest = qfalse;
01211 for (k=0 ; k<source->numpoints ; k++)
01212 {
01213 if (k == i || k == l)
01214 continue;
01215 d = DotProduct (source->points[k], plane.normal) - plane.dist;
01216 if (d < -ON_EPSILON)
01217 {
01218
01219 fliptest = qfalse;
01220 break;
01221 }
01222 else if (d > ON_EPSILON)
01223 {
01224
01225 fliptest = qtrue;
01226 break;
01227 }
01228 }
01229 if (k == source->numpoints)
01230 continue;
01231 #else
01232 fliptest = flipclip;
01233 #endif
01234
01235
01236
01237 if (fliptest)
01238 {
01239 VectorSubtract (vec3_origin, plane.normal, plane.normal);
01240 plane.dist = -plane.dist;
01241 }
01242 #if 1
01243
01244
01245
01246
01247 counts[0] = counts[1] = counts[2] = 0;
01248 for (k=0 ; k<pass->numpoints ; k++)
01249 {
01250 if (k==j)
01251 continue;
01252 d = DotProduct (pass->points[k], plane.normal) - plane.dist;
01253 if (d < -ON_EPSILON)
01254 break;
01255 else if (d > ON_EPSILON)
01256 counts[0]++;
01257 else
01258 counts[2]++;
01259 }
01260 if (k != pass->numpoints)
01261 continue;
01262
01263 if (!counts[0])
01264 continue;
01265 #else
01266 k = (j+1)%pass->numpoints;
01267 d = DotProduct (pass->points[k], plane.normal) - plane.dist;
01268 if (d < -ON_EPSILON)
01269 continue;
01270 k = (j+pass->numpoints-1)%pass->numpoints;
01271 d = DotProduct (pass->points[k], plane.normal) - plane.dist;
01272 if (d < -ON_EPSILON)
01273 continue;
01274 #endif
01275
01276
01277
01278 if (flipclip)
01279 {
01280 VectorSubtract (vec3_origin, plane.normal, plane.normal);
01281 plane.dist = -plane.dist;
01282 }
01283
01284 if (numseperators >= maxseperators)
01285 Error("max seperators");
01286 seperators[numseperators] = plane;
01287 numseperators++;
01288 break;
01289 }
01290 }
01291 return numseperators;
01292 }
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303 void CreatePassages(int portalnum)
01304 {
01305 int i, j, k, n, numseperators, numsee;
01306 float d;
01307 vportal_t *portal, *p, *target;
01308 leaf_t *leaf;
01309 passage_t *passage, *lastpassage;
01310 plane_t seperators[MAX_SEPERATORS*2];
01311 winding_t *w;
01312 winding_t in, out, *res;
01313
01314 #ifdef MREDEBUG
01315 _printf("\r%6d", portalnum);
01316 #endif
01317
01318 portal = sorted_portals[portalnum];
01319
01320 if (portal->removed)
01321 {
01322 portal->status = stat_done;
01323 return;
01324 }
01325
01326 lastpassage = NULL;
01327 leaf = &leafs[portal->leaf];
01328 for (i = 0; i < leaf->numportals; i++)
01329 {
01330 target = leaf->portals[i];
01331 if (target->removed)
01332 continue;
01333
01334 passage = (passage_t *) malloc(sizeof(passage_t) + portalbytes);
01335 memset(passage, 0, sizeof(passage_t) + portalbytes);
01336 numseperators = AddSeperators(portal->winding, target->winding, qfalse, seperators, MAX_SEPERATORS*2);
01337 numseperators += AddSeperators(target->winding, portal->winding, qtrue, &seperators[numseperators], MAX_SEPERATORS*2-numseperators);
01338
01339 passage->next = NULL;
01340 if (lastpassage)
01341 lastpassage->next = passage;
01342 else
01343 portal->passages = passage;
01344 lastpassage = passage;
01345
01346 numsee = 0;
01347
01348 for (j = 0; j < numportals * 2; j++)
01349 {
01350 p = &portals[j];
01351 if (p->removed)
01352 continue;
01353 if ( ! (target->portalflood[j >> 3] & (1<<(j&7)) ) )
01354 continue;
01355 if ( ! (portal->portalflood[j >> 3] & (1<<(j&7)) ) )
01356 continue;
01357 for (k = 0; k < numseperators; k++)
01358 {
01359
01360 d = DotProduct (p->origin, seperators[k].normal) - seperators[k].dist;
01361
01362 if (d < -p->radius + ON_EPSILON)
01363 break;
01364 w = p->winding;
01365 for (n = 0; n < w->numpoints; n++)
01366 {
01367