2
#define _CRTDBG_MAP_ALLOC
4
static char THIS_FILE[] = __FILE__;
12
extern int numthreads;
14
// counters are only bumped when running single threaded,
15
// because they are an awefull coherence problem
16
int c_active_windings;
21
#define BOGUS_RANGE 8192
26
for (i=0 ; i<w->numpoints ; i++)
27
printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
36
winding_t *AllocWinding (int points)
44
c_winding_points += points;
46
if (c_active_windings > c_peak_windings)
47
c_peak_windings = c_active_windings;
50
s = sizeof(vec_t)*3*points + sizeof(int);
59
void FreeWinding (winding_t *w)
61
if (*(unsigned *)w == 0xdeaddead)
62
Error ("FreeWinding: freed a freed winding");
63
*(unsigned *)w = 0xdeaddead;
78
void RemoveColinearPoints (winding_t *w)
83
vec3_t p[MAX_POINTS_ON_WINDING];
86
for (i=0 ; i<w->numpoints ; i++)
88
j = (i+1)%w->numpoints;
89
k = (i+w->numpoints-1)%w->numpoints;
90
VectorSubtract (w->p[j], w->p[i], v1);
91
VectorSubtract (w->p[i], w->p[k], v2);
92
VectorNormalize(v1,v1);
93
VectorNormalize(v2,v2);
94
if (DotProduct(v1, v2) < 0.999)
96
VectorCopy (w->p[i], p[nump]);
101
if (nump == w->numpoints)
105
c_removed += w->numpoints - nump;
107
memcpy (w->p, p, nump*sizeof(p[0]));
115
void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
119
VectorSubtract (w->p[1], w->p[0], v1);
120
VectorSubtract (w->p[2], w->p[0], v2);
121
CrossProduct (v2, v1, normal);
122
VectorNormalize (normal, normal);
123
*dist = DotProduct (w->p[0], normal);
132
vec_t WindingArea (winding_t *w)
135
vec3_t d1, d2, cross;
139
for (i=2 ; i<w->numpoints ; i++)
141
VectorSubtract (w->p[i-1], w->p[0], d1);
142
VectorSubtract (w->p[i], w->p[0], d2);
143
CrossProduct (d1, d2, cross);
144
total += 0.5 * VectorLength ( cross );
149
void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
154
mins[0] = mins[1] = mins[2] = 99999;
155
maxs[0] = maxs[1] = maxs[2] = -99999;
157
for (i=0 ; i<w->numpoints ; i++)
159
for (j=0 ; j<3 ; j++)
175
void WindingCenter (winding_t *w, vec3_t center)
180
VectorCopy (vec3_origin, center);
181
for (i=0 ; i<w->numpoints ; i++)
182
VectorAdd (w->p[i], center, center);
184
scale = 1.0/w->numpoints;
185
VectorScale (center, scale, center);
193
winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
197
vec3_t org, vright, vup;
200
// find the major axis
214
Error ("BaseWindingForPlane: no axis found");
216
VectorCopy (vec3_origin, vup);
228
v = DotProduct (vup, normal);
229
VectorMA (vup, -v, normal, vup);
230
VectorNormalize (vup, vup);
232
VectorScale (normal, dist, org);
234
CrossProduct (vup, normal, vright);
236
VectorScale (vup, 8192, vup);
237
VectorScale (vright, 8192, vright);
239
// project a really big axis aligned box onto the plane
240
w = AllocWinding (4);
242
VectorSubtract (org, vright, w->p[0]);
243
VectorAdd (w->p[0], vup, w->p[0]);
245
VectorAdd (org, vright, w->p[1]);
246
VectorAdd (w->p[1], vup, w->p[1]);
248
VectorAdd (org, vright, w->p[2]);
249
VectorSubtract (w->p[2], vup, w->p[2]);
251
VectorSubtract (org, vright, w->p[3]);
252
VectorSubtract (w->p[3], vup, w->p[3]);
264
winding_t *CopyWinding (winding_t *w)
269
c = AllocWinding (w->numpoints);
270
size = (int)((winding_t *)0)->p[w->numpoints];
281
winding_t *ReverseWinding (winding_t *w)
286
c = AllocWinding (w->numpoints);
287
for (i=0 ; i<w->numpoints ; i++)
289
VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
292
c->numpoints = w->numpoints;
303
void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
304
vec_t epsilon, winding_t **front, winding_t **back)
306
vec_t dists[MAX_POINTS_ON_WINDING+4];
307
int sides[MAX_POINTS_ON_WINDING+4];
309
static vec_t dot; // VC 4.2 optimizer bug if not static
316
counts[0] = counts[1] = counts[2] = 0;
318
// determine sides for each point
319
for (i=0 ; i<in->numpoints ; i++)
321
dot = DotProduct (in->p[i], normal);
325
sides[i] = SIDE_FRONT;
326
else if (dot < -epsilon)
327
sides[i] = SIDE_BACK;
337
*front = *back = NULL;
341
*back = CopyWinding (in);
346
*front = CopyWinding (in);
350
maxpts = in->numpoints+4; // cant use counts[0]+2 because
351
// of fp grouping errors
353
*front = f = AllocWinding (maxpts);
354
*back = b = AllocWinding (maxpts);
356
for (i=0 ; i<in->numpoints ; i++)
360
if (sides[i] == SIDE_ON)
362
VectorCopy (p1, f->p[f->numpoints]);
364
VectorCopy (p1, b->p[b->numpoints]);
369
if (sides[i] == SIDE_FRONT)
371
VectorCopy (p1, f->p[f->numpoints]);
374
if (sides[i] == SIDE_BACK)
376
VectorCopy (p1, b->p[b->numpoints]);
380
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
383
// generate a split point
384
p2 = in->p[(i+1)%in->numpoints];
386
dot = dists[i] / (dists[i]-dists[i+1]);
387
for (j=0 ; j<3 ; j++)
388
{ // avoid round off error when possible
391
else if (normal[j] == -1)
394
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
397
VectorCopy (mid, f->p[f->numpoints]);
399
VectorCopy (mid, b->p[b->numpoints]);
403
if (f->numpoints > maxpts || b->numpoints > maxpts)
404
Error ("ClipWinding: points exceeded estimate");
405
if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
406
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
416
void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
419
vec_t dists[MAX_POINTS_ON_WINDING+4];
420
int sides[MAX_POINTS_ON_WINDING+4];
422
static vec_t dot; // VC 4.2 optimizer bug if not static
430
counts[0] = counts[1] = counts[2] = 0;
432
// determine sides for each point
433
for (i=0 ; i<in->numpoints ; i++)
435
dot = DotProduct (in->p[i], normal);
440
sides[i] = SIDE_FRONT;
442
else if (dot < -epsilon)
444
sides[i] = SIDE_BACK;
463
return; // inout stays the same
466
maxpts = in->numpoints+4; // cant use counts[0]+2 because
469
f = AllocWinding (maxpts);
471
for (i=0 ; i<in->numpoints ; i++)
475
if (sides[i] == SIDE_ON)
477
VectorCopy (p1, f->p[f->numpoints]);
482
if (sides[i] == SIDE_FRONT)
484
VectorCopy (p1, f->p[f->numpoints]);
488
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
494
// generate a split point
495
p2 = in->p[(i+1)%in->numpoints];
497
dot = dists[i] / (dists[i]-dists[i+1]);
498
for (j=0 ; j<3 ; j++)
499
{ // avoid round off error when possible
502
else if (normal[j] <= -1)
505
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
508
VectorCopy (mid, f->p[f->numpoints]);
512
if (f->numpoints > maxpts)
513
Error ("ClipWinding: points exceeded estimate");
514
if (f->numpoints > MAX_POINTS_ON_WINDING)
515
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
526
Returns the fragment of in that is on the front side
527
of the cliping plane. The original is freed.
530
winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
534
ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
548
void CheckWinding (winding_t *w)
553
vec3_t dir, edgenormal, facenormal;
557
if (w->numpoints < 3)
558
Error ("CheckWinding: %i points",w->numpoints);
560
area = WindingArea(w);
562
Error ("CheckWinding: %f area", area);
564
WindingPlane (w, facenormal, &facedist);
566
for (i=0 ; i<w->numpoints ; i++)
570
for (j=0 ; j<3 ; j++)
571
if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
572
Error ("CheckFace: BUGUS_RANGE: %f",p1[j]);
574
j = i+1 == w->numpoints ? 0 : i+1;
576
// check the point is on the face plane
577
d = DotProduct (p1, facenormal) - facedist;
578
if (d < -ON_EPSILON || d > ON_EPSILON)
579
Error ("CheckWinding: point off plane");
581
// check the edge isnt degenerate
583
VectorSubtract (p2, p1, dir);
585
if (VectorLength (dir) < ON_EPSILON)
586
Error ("CheckWinding: degenerate edge");
588
CrossProduct (facenormal, dir, edgenormal);
589
VectorNormalize (edgenormal, edgenormal);
590
edgedist = DotProduct (p1, edgenormal);
591
edgedist += ON_EPSILON;
593
// all other points must be on front side
594
for (j=0 ; j<w->numpoints ; j++)
598
d = DotProduct (w->p[j], edgenormal);
600
Error ("CheckWinding: non-convex");
611
int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
613
qboolean front, back;
619
for (i=0 ; i<w->numpoints ; i++)
621
d = DotProduct (w->p[i], normal) - dist;