~ubuntu-branches/ubuntu/natty/alien-arena/natty

« back to all changes in this revision

Viewing changes to source/utils3/bsp/qvis3/flow.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Mejia, Barry deFreese, Ansgar Burchardt, Gonéri Le Bouder, Andres Mejia
  • Date: 2008-04-18 17:43:24 UTC
  • mfrom: (1.1.2 upstream) (3.1.1 hardy)
  • Revision ID: james.westby@ubuntu.com-20080418174324-si1umi8dngglaha4
Tags: 7.0-1
[ Barry deFreese ]
* Escape - in alien-arena-server.6.
* Add myself to uploaders.

[ Ansgar Burchardt ]
* Remove deprecated Encoding key from .desktop file.

[ Gonéri Le Bouder ]
* Remove Homepage from package description.

[ Andres Mejia ]
* New upstream release.
* Removing XS- part for Vcs-* lines.
* Removing +ssh part of Vcs-Svn line.
* Bumped to Standards-Version 3.7.3.
* Test for existence of *-stamp stamps before removing them.
* Removed Encoding field in desktop file.
* Modify patch for upstream Makefile to make Makefile more useful in building
  Debian packages.
  + Also fixes problem not detecting the existence of libcurl.
* Remove debug packages for release. Will support nostrip option instead.
* Add description for fix-CVE-2007-4754-CVE-2007-4755.dpatch, silences
  lintian warning.
* Add new link for watchfile.
  + Closes: #453555
* Moved debian/scripts/alien-arena-tarball.sh to
  debian/alien-arena-get-orig-source.
* Modified alien-arena-data-get-orig-source to make it easier to maintain.
* Switched from dpatch to quilt.
* Cut down package description.
* Closing bug about mouse constantly looking up. The submitter could not
  reproduce the bug after deleting the ~/.alien-arena directory.
  + Closes: #457700
* Updated copyright file for new release.
* Updated README.Debian files.
* Adding new images for icons. Need build dependency on sharutils.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "vis.h"
 
2
 
 
3
/*
 
4
 
 
5
  each portal will have a list of all possible to see from first portal
 
6
 
 
7
  if (!thread->portalmightsee[portalnum])
 
8
 
 
9
  portal mightsee
 
10
 
 
11
  for p2 = all other portals in leaf
 
12
        get sperating planes
 
13
        for all portals that might be seen by p2
 
14
                mark as unseen if not present in seperating plane
 
15
        flood fill a new mightsee
 
16
        save as passagemightsee
 
17
 
 
18
 
 
19
  void CalcMightSee (leaf_t *leaf, 
 
20
*/
 
21
 
 
22
int CountBits (byte *bits, int numbits)
 
23
{
 
24
        int             i;
 
25
        int             c;
 
26
 
 
27
        c = 0;
 
28
        for (i=0 ; i<numbits ; i++)
 
29
                if (bits[i>>3] & (1<<(i&7)) )
 
30
                        c++;
 
31
 
 
32
        return c;
 
33
}
 
34
 
 
35
int             c_fullskip;
 
36
int             c_portalskip, c_leafskip;
 
37
int             c_vistest, c_mighttest;
 
38
 
 
39
int             c_chop, c_nochop;
 
40
 
 
41
int             active;
 
42
 
 
43
void CheckStack (leaf_t *leaf, threaddata_t *thread)
 
44
{
 
45
        pstack_t        *p, *p2;
 
46
 
 
47
        for (p=thread->pstack_head.next ; p ; p=p->next)
 
48
        {
 
49
//              printf ("=");
 
50
                if (p->leaf == leaf)
 
51
                        Error ("CheckStack: leaf recursion");
 
52
                for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next)
 
53
                        if (p2->leaf == p->leaf)
 
54
                                Error ("CheckStack: late leaf recursion");
 
55
        }
 
56
//      printf ("\n");
 
57
}
 
58
 
 
59
 
 
60
winding_t *AllocStackWinding (pstack_t *stack)
 
61
{
 
62
        int             i;
 
63
 
 
64
        for (i=0 ; i<3 ; i++)
 
65
        {
 
66
                if (stack->freewindings[i])
 
67
                {
 
68
                        stack->freewindings[i] = 0;
 
69
                        return &stack->windings[i];
 
70
                }
 
71
        }
 
72
 
 
73
        Error ("AllocStackWinding: failed");
 
74
 
 
75
        return NULL;
 
76
}
 
77
 
 
78
void FreeStackWinding (winding_t *w, pstack_t *stack)
 
79
{
 
80
        int             i;
 
81
 
 
82
        i = w - stack->windings;
 
83
 
 
84
        if (i<0 || i>2)
 
85
                return;         // not from local
 
86
 
 
87
        if (stack->freewindings[i])
 
88
                Error ("FreeStackWinding: allready free");
 
89
        stack->freewindings[i] = 1;
 
90
}
 
91
 
 
92
/*
 
93
==============
 
94
ChopWinding
 
95
 
 
96
==============
 
97
*/
 
98
winding_t       *ChopWinding (winding_t *in, pstack_t *stack, plane_t *split)
 
99
{
 
100
        vec_t   dists[128];
 
101
        int             sides[128];
 
102
        int             counts[3];
 
103
        vec_t   dot;
 
104
        int             i, j;
 
105
        vec_t   *p1, *p2;
 
106
        vec3_t  mid;
 
107
        winding_t       *neww;
 
108
 
 
109
        counts[0] = counts[1] = counts[2] = 0;
 
110
 
 
111
// determine sides for each point
 
112
        for (i=0 ; i<in->numpoints ; i++)
 
113
        {
 
114
                dot = DotProduct (in->points[i], split->normal);
 
115
                dot -= split->dist;
 
116
                dists[i] = dot;
 
117
                if (dot > ON_EPSILON)
 
118
                        sides[i] = SIDE_FRONT;
 
119
                else if (dot < -ON_EPSILON)
 
120
                        sides[i] = SIDE_BACK;
 
121
                else
 
122
                {
 
123
                        sides[i] = SIDE_ON;
 
124
                }
 
125
                counts[sides[i]]++;
 
126
        }
 
127
 
 
128
        if (!counts[1])
 
129
                return in;              // completely on front side
 
130
        
 
131
        if (!counts[0])
 
132
        {
 
133
                FreeStackWinding (in, stack);
 
134
                return NULL;
 
135
        }
 
136
 
 
137
        sides[i] = sides[0];
 
138
        dists[i] = dists[0];
 
139
        
 
140
        neww = AllocStackWinding (stack);
 
141
 
 
142
        neww->numpoints = 0;
 
143
 
 
144
        for (i=0 ; i<in->numpoints ; i++)
 
145
        {
 
146
                p1 = in->points[i];
 
147
 
 
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
 
 
154
                if (sides[i] == SIDE_ON)
 
155
                {
 
156
                        VectorCopy (p1, neww->points[neww->numpoints]);
 
157
                        neww->numpoints++;
 
158
                        continue;
 
159
                }
 
160
        
 
161
                if (sides[i] == SIDE_FRONT)
 
162
                {
 
163
                        VectorCopy (p1, neww->points[neww->numpoints]);
 
164
                        neww->numpoints++;
 
165
                }
 
166
                
 
167
                if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
 
168
                        continue;
 
169
                        
 
170
                if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
 
171
                {
 
172
                        FreeStackWinding (neww, stack);
 
173
                        return in;              // can't chop -- fall back to original
 
174
                }
 
175
 
 
176
        // generate a split point
 
177
                p2 = in->points[(i+1)%in->numpoints];
 
178
                
 
179
                dot = dists[i] / (dists[i]-dists[i+1]);
 
180
                for (j=0 ; j<3 ; j++)
 
181
                {       // avoid round off error when possible
 
182
                        if (split->normal[j] == 1)
 
183
                                mid[j] = split->dist;
 
184
                        else if (split->normal[j] == -1)
 
185
                                mid[j] = -split->dist;
 
186
                        else
 
187
                                mid[j] = p1[j] + dot*(p2[j]-p1[j]);
 
188
                }
 
189
                        
 
190
                VectorCopy (mid, neww->points[neww->numpoints]);
 
191
                neww->numpoints++;
 
192
        }
 
193
        
 
194
// free the original winding
 
195
        FreeStackWinding (in, stack);
 
196
        
 
197
        return neww;
 
198
}
 
199
 
 
200
 
 
201
/*
 
202
==============
 
203
ClipToSeperators
 
204
 
 
205
Source, pass, and target are an ordering of portals.
 
206
 
 
207
Generates seperating planes canidates by taking two points from source and one
 
208
point from pass, and clips target by them.
 
209
 
 
210
If target is totally clipped away, that portal can not be seen through.
 
211
 
 
212
Normal clip keeps target on the same side as pass, which is correct if the
 
213
order goes source, pass, target.  If the order goes pass, source, target then
 
214
flipclip should be set.
 
215
==============
 
216
*/
 
217
winding_t       *ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip, pstack_t *stack)
 
218
{
 
219
        int                     i, j, k, l;
 
220
        plane_t         plane;
 
221
        vec3_t          v1, v2;
 
222
        float           d;
 
223
        vec_t           length;
 
224
        int                     counts[3];
 
225
        qboolean                fliptest;
 
226
 
 
227
// check all combinations       
 
228
        for (i=0 ; i<source->numpoints ; i++)
 
229
        {
 
230
                l = (i+1)%source->numpoints;
 
231
                VectorSubtract (source->points[l] , source->points[i], v1);
 
232
 
 
233
        // fing a vertex of pass that makes a plane that puts all of the
 
234
        // vertexes of pass on the front side and all of the vertexes of
 
235
        // source on the back side
 
236
                for (j=0 ; j<pass->numpoints ; j++)
 
237
                {
 
238
                        VectorSubtract (pass->points[j], source->points[i], v2);
 
239
 
 
240
                        plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
 
241
                        plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
 
242
                        plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
 
243
                        
 
244
                // if points don't make a valid plane, skip it
 
245
 
 
246
                        length = plane.normal[0] * plane.normal[0]
 
247
                        + plane.normal[1] * plane.normal[1]
 
248
                        + plane.normal[2] * plane.normal[2];
 
249
                        
 
250
                        if (length < ON_EPSILON)
 
251
                                continue;
 
252
 
 
253
                        length = 1/sqrt(length);
 
254
                        
 
255
                        plane.normal[0] *= length;
 
256
                        plane.normal[1] *= length;
 
257
                        plane.normal[2] *= length;
 
258
 
 
259
                        plane.dist = DotProduct (pass->points[j], plane.normal);
 
260
 
 
261
                //
 
262
                // find out which side of the generated seperating plane has the
 
263
                // source portal
 
264
                //
 
265
#if 1
 
266
                        fliptest = false;
 
267
                        for (k=0 ; k<source->numpoints ; k++)
 
268
                        {
 
269
                                if (k == i || k == l)
 
270
                                        continue;
 
271
                                d = DotProduct (source->points[k], plane.normal) - plane.dist;
 
272
                                if (d < -ON_EPSILON)
 
273
                                {       // source is on the negative side, so we want all
 
274
                                        // pass and target on the positive side
 
275
                                        fliptest = false;
 
276
                                        break;
 
277
                                }
 
278
                                else if (d > ON_EPSILON)
 
279
                                {       // source is on the positive side, so we want all
 
280
                                        // pass and target on the negative side
 
281
                                        fliptest = true;
 
282
                                        break;
 
283
                                }
 
284
                        }
 
285
                        if (k == source->numpoints)
 
286
                                continue;               // planar with source portal
 
287
#else
 
288
                        fliptest = flipclip;
 
289
#endif
 
290
                //
 
291
                // flip the normal if the source portal is backwards
 
292
                //
 
293
                        if (fliptest)
 
294
                        {
 
295
                                VectorSubtract (vec3_origin, plane.normal, plane.normal);
 
296
                                plane.dist = -plane.dist;
 
297
                        }
 
298
#if 1
 
299
                //
 
300
                // if all of the pass portal points are now on the positive side,
 
301
                // this is the seperating plane
 
302
                //
 
303
                        counts[0] = counts[1] = counts[2] = 0;
 
304
                        for (k=0 ; k<pass->numpoints ; k++)
 
305
                        {
 
306
                                if (k==j)
 
307
                                        continue;
 
308
                                d = DotProduct (pass->points[k], plane.normal) - plane.dist;
 
309
                                if (d < -ON_EPSILON)
 
310
                                        break;
 
311
                                else if (d > ON_EPSILON)
 
312
                                        counts[0]++;
 
313
                                else
 
314
                                        counts[2]++;
 
315
                        }
 
316
                        if (k != pass->numpoints)
 
317
                                continue;       // points on negative side, not a seperating plane
 
318
                                
 
319
                        if (!counts[0])
 
320
                                continue;       // planar with seperating plane
 
321
#else
 
322
                        k = (j+1)%pass->numpoints;
 
323
                        d = DotProduct (pass->points[k], plane.normal) - plane.dist;
 
324
                        if (d < -ON_EPSILON)
 
325
                                continue;
 
326
                        k = (j+pass->numpoints-1)%pass->numpoints;
 
327
                        d = DotProduct (pass->points[k], plane.normal) - plane.dist;
 
328
                        if (d < -ON_EPSILON)
 
329
                                continue;                       
 
330
#endif
 
331
                //
 
332
                // flip the normal if we want the back side
 
333
                //
 
334
                        if (flipclip)
 
335
                        {
 
336
                                VectorSubtract (vec3_origin, plane.normal, plane.normal);
 
337
                                plane.dist = -plane.dist;
 
338
                        }
 
339
                        
 
340
                //
 
341
                // clip target by the seperating plane
 
342
                //
 
343
                        target = ChopWinding (target, stack, &plane);
 
344
                        if (!target)
 
345
                                return NULL;            // target is not visible
 
346
                }
 
347
        }
 
348
        
 
349
        return target;
 
350
}
 
351
 
 
352
 
 
353
 
 
354
/*
 
355
==================
 
356
RecursiveLeafFlow
 
357
 
 
358
Flood fill through the leafs
 
359
If src_portal is NULL, this is the originating leaf
 
360
==================
 
361
*/
 
362
void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
 
363
{
 
364
        pstack_t        stack;
 
365
        portal_t        *p;
 
366
        plane_t         backplane;
 
367
        leaf_t          *leaf;
 
368
        int                     i, j;
 
369
        long            *test, *might, *vis, more;
 
370
        int                     pnum;
 
371
 
 
372
        thread->c_chains++;
 
373
 
 
374
        leaf = &leafs[leafnum];
 
375
//      CheckStack (leaf, thread);
 
376
 
 
377
        prevstack->next = &stack;
 
378
 
 
379
        stack.next = NULL;
 
380
        stack.leaf = leaf;
 
381
        stack.portal = NULL;
 
382
 
 
383
        might = (long *)stack.mightsee;
 
384
        vis = (long *)thread->base->portalvis;
 
385
        
 
386
// check all portals for flowing into other leafs       
 
387
        for (i=0 ; i<leaf->numportals ; i++)
 
388
        {
 
389
                p = leaf->portals[i];
 
390
                pnum = p - portals;
 
391
 
 
392
                if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
 
393
                {
 
394
                        continue;       // can't possibly see it
 
395
                }
 
396
 
 
397
        // if the portal can't see anything we haven't allready seen, skip it
 
398
                if (p->status == stat_done)
 
399
                {
 
400
                        test = (long *)p->portalvis;
 
401
                }
 
402
                else
 
403
                {
 
404
                        test = (long *)p->portalflood;
 
405
                }
 
406
 
 
407
                more = 0;
 
408
                for (j=0 ; j<portallongs ; j++)
 
409
                {
 
410
                        might[j] = ((long *)prevstack->mightsee)[j] & test[j];
 
411
                        more |= (might[j] & ~vis[j]);
 
412
                }
 
413
                
 
414
                if (!more && 
 
415
                        (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
 
416
                {       // can't see anything new
 
417
                        continue;
 
418
                }
 
419
 
 
420
                // get plane of portal, point normal into the neighbor leaf
 
421
                stack.portalplane = p->plane;
 
422
                VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
 
423
                backplane.dist = -p->plane.dist;
 
424
                
 
425
//              c_portalcheck++;
 
426
                
 
427
                stack.portal = p;
 
428
                stack.next = NULL;
 
429
                stack.freewindings[0] = 1;
 
430
                stack.freewindings[1] = 1;
 
431
                stack.freewindings[2] = 1;
 
432
                
 
433
#if 1
 
434
{
 
435
float d;
 
436
 
 
437
        d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
 
438
        d -= thread->pstack_head.portalplane.dist;
 
439
        if (d < -p->radius)
 
440
        {
 
441
                continue;
 
442
        }
 
443
        else if (d > p->radius)
 
444
        {
 
445
                stack.pass = p->winding;
 
446
        }
 
447
        else    
 
448
        {
 
449
                stack.pass = ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
 
450
                if (!stack.pass)
 
451
                        continue;
 
452
        }
 
453
}
 
454
#else
 
455
                stack.pass = ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
 
456
                if (!stack.pass)
 
457
                        continue;
 
458
#endif
 
459
 
 
460
        
 
461
#if 1
 
462
{
 
463
float d;
 
464
 
 
465
        d = DotProduct (thread->base->origin, p->plane.normal);
 
466
        d -= p->plane.dist;
 
467
        if (d > thread->base->radius)
 
468
//      if (d > p->radius)
 
469
        {
 
470
                continue;
 
471
        }
 
472
//      else if (d < -p->radius)
 
473
        else if (d < -thread->base->radius)
 
474
        {
 
475
                stack.source = prevstack->source;
 
476
        }
 
477
        else    
 
478
        {
 
479
                stack.source = ChopWinding (prevstack->source, &stack, &backplane);
 
480
                if (!stack.source)
 
481
                        continue;
 
482
        }
 
483
}
 
484
#else
 
485
                stack.source = ChopWinding (prevstack->source, &stack, &backplane);
 
486
                if (!stack.source)
 
487
                        continue;
 
488
#endif
 
489
 
 
490
                if (!prevstack->pass)
 
491
                {       // the second leaf can only be blocked if coplanar
 
492
 
 
493
                        // mark the portal as visible
 
494
                        thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
 
495
 
 
496
                        RecursiveLeafFlow (p->leaf, thread, &stack);
 
497
                        continue;
 
498
                }
 
499
 
 
500
                stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, false, &stack);
 
501
                if (!stack.pass)
 
502
                        continue;
 
503
                
 
504
                stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, true, &stack);
 
505
                if (!stack.pass)
 
506
                        continue;
 
507
 
 
508
                // mark the portal as visible
 
509
                thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
 
510
 
 
511
                // flow through it for real
 
512
                RecursiveLeafFlow (p->leaf, thread, &stack);
 
513
        }       
 
514
}
 
515
 
 
516
 
 
517
/*
 
518
===============
 
519
PortalFlow
 
520
 
 
521
generates the portalvis bit vector
 
522
===============
 
523
*/
 
524
void PortalFlow (int portalnum)
 
525
{
 
526
        threaddata_t    data;
 
527
        int                             i;
 
528
        portal_t                *p;
 
529
        int                             c_might, c_can;
 
530
 
 
531
        p = sorted_portals[portalnum];
 
532
        p->status = stat_working;
 
533
 
 
534
        c_might = CountBits (p->portalflood, numportals*2);
 
535
 
 
536
        memset (&data, 0, sizeof(data));
 
537
        data.base = p;
 
538
        
 
539
        data.pstack_head.portal = p;
 
540
        data.pstack_head.source = p->winding;
 
541
        data.pstack_head.portalplane = p->plane;
 
542
        for (i=0 ; i<portallongs ; i++)
 
543
                ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
 
544
        RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
 
545
 
 
546
        p->status = stat_done;
 
547
 
 
548
        c_can = CountBits (p->portalvis, numportals*2);
 
549
 
 
550
        qprintf ("portal:%4i  mightsee:%4i  cansee:%4i (%i chains)\n", 
 
551
                (int)(p - portals),     c_might, c_can, data.c_chains);
 
552
}
 
553
 
 
554
 
 
555
/*
 
556
===============================================================================
 
557
 
 
558
This is a rough first-order aproximation that is used to trivially reject some
 
559
of the final calculations.
 
560
 
 
561
 
 
562
Calculates portalfront and portalflood bit vectors
 
563
 
 
564
thinking about:
 
565
 
 
566
typedef struct passage_s
 
567
{
 
568
        struct passage_s        *next;
 
569
        struct portal_s         *to;
 
570
        stryct sep_s            *seperators;
 
571
        byte                            *mightsee;
 
572
} passage_t;
 
573
 
 
574
typedef struct portal_s
 
575
{
 
576
        struct passage_s        *passages;
 
577
        int                                     leaf;           // leaf portal faces into
 
578
} portal_s;
 
579
 
 
580
leaf = portal->leaf
 
581
clear 
 
582
for all portals
 
583
 
 
584
 
 
585
calc portal visibility
 
586
        clear bit vector
 
587
        for all passages
 
588
                passage visibility
 
589
 
 
590
 
 
591
for a portal to be visible to a passage, it must be on the front of
 
592
all seperating planes, and both portals must be behind the mew portal
 
593
 
 
594
===============================================================================
 
595
*/
 
596
 
 
597
int             c_flood, c_vis;
 
598
 
 
599
char test_leaf[MAX_MAP_LEAFS];
 
600
 
 
601
/*
 
602
==================
 
603
SimpleFlood
 
604
 
 
605
==================
 
606
*/
 
607
 
 
608
int cullerror = 0;
 
609
 
 
610
void SimpleFlood (portal_t *srcportal, int leafnum)
 
611
{
 
612
        int             i;
 
613
        leaf_t  *leaf;
 
614
        portal_t        *p;
 
615
        int             pnum;
 
616
 
 
617
        if(cullerror && !test_leaf[leafnum])
 
618
                return;
 
619
 
 
620
        test_leaf[leafnum] = 0;
 
621
 
 
622
        leaf = &leafs[leafnum];
 
623
 
 
624
        for (i=0 ; i<leaf->numportals ; i++)
 
625
        {
 
626
                p = leaf->portals[i];
 
627
 
 
628
                pnum = p - portals;
 
629
 
 
630
                if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) )
 
631
                        continue;
 
632
 
 
633
                if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) )
 
634
                        continue;
 
635
 
 
636
                srcportal->portalflood[pnum>>3] |= (1<<(pnum&7));
 
637
                
 
638
                SimpleFlood (srcportal, p->leaf);
 
639
        }
 
640
}
 
641
/*
 
642
==============
 
643
BasePortalVis
 
644
==============
 
645
*/
 
646
void BasePortalVis (int portalnum)
 
647
{
 
648
        int                     j, k;
 
649
        portal_t        *tp, *p;
 
650
        float           d;
 
651
        winding_t       *w;
 
652
        vec3_t prenormal, normal;
 
653
        float p_dot, tp_dot, p_rad, tp_rad;
 
654
 
 
655
        p = portals+portalnum;
 
656
 
 
657
        p->portalfront = malloc (portalbytes);
 
658
        memset (p->portalfront, 0, portalbytes);
 
659
 
 
660
        p->portalflood = malloc (portalbytes);
 
661
        memset (p->portalflood, 0, portalbytes);
 
662
        
 
663
        p->portalvis = malloc (portalbytes);
 
664
        memset (p->portalvis, 0, portalbytes);
 
665
 
 
666
        memset(test_leaf, 0, MAX_MAP_LEAFS);
 
667
 
 
668
        for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
 
669
        {
 
670
                if (j == portalnum)
 
671
                        continue;
 
672
                else if(cullerror && tp->leaf == p->owner_leaf)
 
673
                        continue;
 
674
 
 
675
                test_leaf[tp->leaf] = 1;
 
676
 
 
677
                w = tp->winding;
 
678
 
 
679
                for (k=0 ; k<w->numpoints ; k++)
 
680
                {
 
681
                        d = DotProduct (w->points[k], p->plane.normal)
 
682
                                - p->plane.dist;
 
683
                        if (d > ON_EPSILON)
 
684
                                break;
 
685
                }
 
686
                if (k == w->numpoints)
 
687
                        continue;       // no points on front
 
688
 
 
689
                w = p->winding;
 
690
                for (k=0 ; k<w->numpoints ; k++)
 
691
                {
 
692
                        d = DotProduct (w->points[k], tp->plane.normal)
 
693
                                - tp->plane.dist;
 
694
                        if (d < -ON_EPSILON)
 
695
                                break;
 
696
                }
 
697
 
 
698
                if (k == w->numpoints)
 
699
                        continue;       // no points on front (or in range if maxdist set)
 
700
 
 
701
                if(maxdist > 0.0)
 
702
                {
 
703
                        // This approximation will consider 2 circles in 3d space with the centeer and radius of the
 
704
                        // polygons on the planes of the polygons.
 
705
 
 
706
                        prenormal[0] = p->origin[0] - tp->origin[0];
 
707
                        prenormal[1] = p->origin[1] - tp->origin[1];
 
708
                        prenormal[2] = p->origin[2] - tp->origin[2];
 
709
 
 
710
                        d = VectorNormalize(prenormal, normal);
 
711
 
 
712
                        p_dot = DotProduct(p->plane.normal, normal);
 
713
 
 
714
                        if(p_dot < 0.0)
 
715
                                p_rad = -p_dot * p->radius;
 
716
                        else
 
717
                                p_rad = p_dot * p->radius;
 
718
 
 
719
                        tp_dot = DotProduct(tp->plane.normal, normal);
 
720
 
 
721
                        if(tp_dot < 0.0)
 
722
                                tp_rad = -tp_dot * tp->radius;
 
723
                        else
 
724
                                tp_rad = tp_dot * tp->radius;
 
725
 
 
726
                        if(d > (maxdist + tp_rad + p_rad))
 
727
                                continue;
 
728
                }
 
729
 
 
730
                p->portalfront[j>>3] |= (1<<(j&7));
 
731
        }
 
732
 
 
733
        SimpleFlood (p, p->leaf);
 
734
 
 
735
        p->nummightsee = CountBits (p->portalflood, numportals*2);
 
736
//      printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee);
 
737
        c_flood += p->nummightsee;
 
738
}
 
739
 
 
740
 
 
741
 
 
742
 
 
743
 
 
744
/*
 
745
===============================================================================
 
746
 
 
747
This is a second order aproximation 
 
748
 
 
749
Calculates portalvis bit vector
 
750
 
 
751
WAAAAAAY too slow.
 
752
 
 
753
===============================================================================
 
754
*/
 
755
 
 
756
/*
 
757
==================
 
758
RecursiveLeafBitFlow
 
759
 
 
760
==================
 
761
*/
 
762
void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee)
 
763
{
 
764
        portal_t        *p;
 
765
        leaf_t          *leaf;
 
766
        int                     i, j;
 
767
        long            more;
 
768
        int                     pnum;
 
769
        byte            newmight[MAX_PORTALS/8];
 
770
 
 
771
        leaf = &leafs[leafnum];
 
772
        
 
773
// check all portals for flowing into other leafs       
 
774
        for (i=0 ; i<leaf->numportals ; i++)
 
775
        {
 
776
                p = leaf->portals[i];
 
777
                pnum = p - portals;
 
778
 
 
779
                // if some previous portal can't see it, skip
 
780
                if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) )
 
781
                        continue;
 
782
 
 
783
                // if this portal can see some portals we mightsee, recurse
 
784
                more = 0;
 
785
                for (j=0 ; j<portallongs ; j++)
 
786
                {
 
787
                        ((long *)newmight)[j] = ((long *)mightsee)[j] 
 
788
                                & ((long *)p->portalflood)[j];
 
789
                        more |= ((long *)newmight)[j] & ~((long *)cansee)[j];
 
790
                }
 
791
 
 
792
                if (!more)
 
793
                        continue;       // can't see anything new
 
794
 
 
795
                cansee[pnum>>3] |= (1<<(pnum&7));
 
796
 
 
797
                RecursiveLeafBitFlow (p->leaf, newmight, cansee);
 
798
        }       
 
799
}
 
800
 
 
801
/*
 
802
==============
 
803
BetterPortalVis
 
804
==============
 
805
*/
 
806
void BetterPortalVis (int portalnum)
 
807
{
 
808
        portal_t        *p;
 
809
 
 
810
        p = portals+portalnum;
 
811
 
 
812
        RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis);
 
813
 
 
814
        // build leaf vis information
 
815
        p->nummightsee = CountBits (p->portalvis, numportals*2);
 
816
        c_vis += p->nummightsee;
 
817
}
 
818
 
 
819