UFO: Alien Invasion
Loading...
Searching...
No Matches
polylib.cpp
Go to the documentation of this file.
1
6
7/*
8Copyright (C) 1997-2001 Id Software, Inc.
9
10This program is free software; you can redistribute it and/or
11modify it under the terms of the GNU General Public License
12as published by the Free Software Foundation; either version 2
13of the License, or (at your option) any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18
19See the GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25*/
26
27#include "polylib.h"
28#include "shared.h"
29
30
31#define BOGUS_RANGE 8192
32
39{
40 return (winding_t*)Mem_Alloc(sizeof(vec3_t) * points + sizeof(int));
41}
42
47{
48 if (*(unsigned* )w == 0xdeaddead)
49 Sys_Error("FreeWinding: freed a freed winding");
50 *(unsigned* )w = 0xdeaddead;
51
52 Mem_Free(w);
53}
54
56{
57 int nump = 0;
58 vec3_t v1, v2;
60
61 for (int i = 0; i < w->numpoints; i++) {
62 const int j = (i + 1) % w->numpoints;
63 const int k = (i + w->numpoints - 1) % w->numpoints;
64 VectorSubtract(w->p[j], w->p[i], v1);
65 VectorSubtract(w->p[i], w->p[k], v2);
68 if (DotProduct(v1, v2) < 0.999) {
69 VectorCopy(w->p[i], p[nump]);
70 nump++;
71 }
72 }
73
74 if (nump == w->numpoints)
75 return;
76
77 w->numpoints = nump;
78 memcpy(w->p, p, nump * sizeof(p[0]));
79}
80
82{
83 int i;
84 vec3_t d1, d2, cross;
85 vec_t total;
86
87 total = 0;
88 for (i = 2; i < w->numpoints; i++) {
89 VectorSubtract(w->p[i - 1], w->p[0], d1);
90 VectorSubtract(w->p[i], w->p[0], d2);
91 CrossProduct(d1, d2, cross);
92 total += VectorLength(cross);
93 }
94 return total * 0.5f;
95}
96
97void WindingBounds (const winding_t* w, vec3_t mins, vec3_t maxs)
98{
99 ClearBounds(mins, maxs);
100
101 for (int i = 0; i < w->numpoints; i++) {
102 AddPointToBounds(w->p[i], mins, maxs);
103 }
104}
105
106void WindingCenter (const winding_t* w, vec3_t center)
107{
108 VectorCopy(vec3_origin, center);
109 for (int i = 0; i < w->numpoints; i++)
110 VectorAdd(w->p[i], center, center);
111
112 vec_t scale = 1.0 / w->numpoints;
113 VectorScale(center, scale, center);
114}
115
116winding_t* BaseWindingForPlane (const vec3_t normal, const vec_t dist)
117{
118 vec_t max, v;
119 vec3_t org, vright, vup;
120 winding_t* w;
121
122 /* find the major axis */
123 max = -BOGUS_RANGE;
124 int x = -1;
125 for (int i = 0; i < 3; i++) {
126 v = fabs(normal[i]);
127 if (v > max) {
128 x = i;
129 max = v;
130 }
131 }
132 if (x == -1)
133 Sys_Error("BaseWindingForPlane: no axis found");
134
136 /* axis */
137 switch (x) {
138 case 0:
139 case 1:
140 vup[2] = 1;
141 break;
142 case 2:
143 vup[0] = 1;
144 break;
145 }
146
147 v = DotProduct(vup, normal);
148 VectorMA(vup, -v, normal, vup);
149 VectorNormalize(vup);
150
151 VectorScale(normal, dist, org);
152
153 CrossProduct(vup, normal, vright);
154
155 VectorScale(vup, 8192, vup);
156 VectorScale(vright, 8192, vright);
157
158 /* project a really big axis aligned box onto the plane */
159 w = AllocWinding(4);
160 if (!w)
161 return nullptr;
162
163 VectorSubtract(org, vright, w->p[0]);
164 VectorAdd(w->p[0], vup, w->p[0]);
165
166 VectorAdd(org, vright, w->p[1]);
167 VectorAdd(w->p[1], vup, w->p[1]);
168
169 VectorAdd(org, vright, w->p[2]);
170 VectorSubtract(w->p[2], vup, w->p[2]);
171
172 VectorSubtract(org, vright, w->p[3]);
173 VectorSubtract(w->p[3], vup, w->p[3]);
174
175 w->numpoints = 4;
176
177 return w;
178}
179
186{
188 const ptrdiff_t size = (ptrdiff_t)((winding_t*)0)->p[w->numpoints];
189 memcpy(c, w, size);
190 return c;
191}
192
194{
196
197 for (int i = 0; i < w->numpoints; i++) {
198 VectorCopy(w->p[w->numpoints - 1 - i], c->p[i]);
199 }
200 c->numpoints = w->numpoints;
201 return c;
202}
203
204void ClipWindingEpsilon (const winding_t* in, const vec3_t normal, const vec_t dist,
205 const vec_t epsilon, winding_t** front, winding_t** back)
206{
207 vec_t dists[MAX_POINTS_ON_WINDING + 4];
208 int sides[MAX_POINTS_ON_WINDING + 4];
209 int counts[3];
210 int i;
211 winding_t* f, *b;
212
213 VectorClear(counts);
214
215 /* determine sides for each point */
216 for (i = 0; i < in->numpoints; i++) {
217 const vec_t dot = DotProduct(in->p[i], normal) - dist;
218 dists[i] = dot;
219 if (dot > epsilon)
220 sides[i] = SIDE_FRONT;
221 else if (dot < -epsilon)
222 sides[i] = SIDE_BACK;
223 else
224 sides[i] = SIDE_ON;
225 counts[sides[i]]++;
226 }
227 sides[i] = sides[0];
228 dists[i] = dists[0];
229
230 if (!counts[0]) {
231 *back = CopyWinding(in);
232 *front = nullptr;
233 return;
234 }
235 if (!counts[1]) {
236 *front = CopyWinding(in);
237 *back = nullptr;
238 return;
239 }
240
241 /* can't use counts[0] + 2 because of floating point grouping errors */
242 int maxpts = in->numpoints + 4;
243
244 *front = f = AllocWinding(maxpts);
245 *back = b = AllocWinding(maxpts);
246
247 for (i = 0; i < in->numpoints; i++) {
248 const vec_t* p1 = in->p[i];
249 const vec_t* p2;
250 vec_t dot;
251 vec3_t mid;
252
253 if (sides[i] == SIDE_ON) {
254 VectorCopy(p1, f->p[f->numpoints]);
255 f->numpoints++;
256 VectorCopy(p1, b->p[b->numpoints]);
257 b->numpoints++;
258 continue;
259 }
260
261 if (sides[i] == SIDE_FRONT) {
262 VectorCopy(p1, f->p[f->numpoints]);
263 f->numpoints++;
264 }
265 if (sides[i] == SIDE_BACK) {
266 VectorCopy(p1, b->p[b->numpoints]);
267 b->numpoints++;
268 }
269
270 if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i])
271 continue;
272
273 /* generate a split point */
274 p2 = in->p[(i + 1) % in->numpoints];
275
276 dot = dists[i] / (dists[i] - dists[i + 1]);
277 /* avoid round off error when possible */
278 for (int j = 0; j < 3; j++) {
279 if (normal[j] == 1)
280 mid[j] = dist;
281 else if (normal[j] == -1)
282 mid[j] = -dist;
283 else
284 mid[j] = p1[j] + dot * (p2[j] - p1[j]);
285 }
286
287 VectorCopy(mid, f->p[f->numpoints]);
288 f->numpoints++;
289 VectorCopy(mid, b->p[b->numpoints]);
290 b->numpoints++;
291 }
292
293 if (f->numpoints > maxpts || b->numpoints > maxpts)
294 Sys_Error("ClipWinding: points exceeded estimate");
296 Sys_Error("ClipWinding: MAX_POINTS_ON_WINDING");
297}
298
299void ChopWindingInPlace (winding_t** inout, const vec3_t normal, const vec_t dist, const vec_t epsilon)
300{
302 vec_t dists[MAX_POINTS_ON_WINDING + 4];
303 int sides[MAX_POINTS_ON_WINDING + 4];
304 int counts[3];
305 int i;
306
307 winding_t* in = *inout;
308 VectorClear(counts);
309
310 /* determine sides for each point */
311 for (i = 0; i < in->numpoints; i++) {
312 const vec_t dot = DotProduct(in->p[i], normal) - dist;
313 dists[i] = dot;
314 if (dot > epsilon)
315 sides[i] = SIDE_FRONT;
316 else if (dot < -epsilon)
317 sides[i] = SIDE_BACK;
318 else {
319 sides[i] = SIDE_ON;
320 }
321 counts[sides[i]]++;
322 }
323 sides[i] = sides[0];
324 dists[i] = dists[0];
325
326 if (!counts[0]) {
327 FreeWinding(in);
328 *inout = nullptr;
329 return;
330 }
331 if (!counts[1])
332 return; /* inout stays the same */
333
334 /* cant use counts[0] + 2 because of fp grouping errors */
335 int maxpts = in->numpoints + 4;
336
337 winding_t* f = AllocWinding(maxpts);
338
339 for (i = 0; i < in->numpoints; i++) {
340 const vec_t* p1 = in->p[i];
341 const vec_t* p2;
342 vec_t dot;
343
344 if (sides[i] == SIDE_ON) {
345 VectorCopy(p1, f->p[f->numpoints]);
346 f->numpoints++;
347 continue;
348 }
349
350 if (sides[i] == SIDE_FRONT) {
351 VectorCopy(p1, f->p[f->numpoints]);
352 f->numpoints++;
353 }
354
355 if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i])
356 continue;
357
358 /* generate a split point */
359 p2 = in->p[(i + 1) % in->numpoints];
360
361 dot = dists[i] / (dists[i] - dists[i + 1]);
362 /* avoid round off error when possible */
363 vec3_t mid;
364 for (int j = 0; j < 3; j++) {
365 if (normal[j] == 1)
366 mid[j] = dist;
367 else if (normal[j] == -1)
368 mid[j] = -dist;
369 else
370 mid[j] = p1[j] + dot * (p2[j] - p1[j]);
371 }
372
373 VectorCopy(mid, f->p[f->numpoints]);
374 f->numpoints++;
375 }
376
377 if (f->numpoints > maxpts)
378 Sys_Error("ClipWinding: points exceeded estimate");
379 if (f->numpoints > MAX_POINTS_ON_WINDING)
380 Sys_Error("ClipWinding: MAX_POINTS_ON_WINDING");
381
382 FreeWinding(in);
383 *inout = f;
384}
385
386
392{
393 winding_t* f, *b;
394
395 ClipWindingEpsilon(in, normal, dist, ON_EPSILON, &f, &b);
396 FreeWinding(in);
397 if (b)
398 FreeWinding(b);
399 return f;
400}
401
402#define EDGE_LENGTH 0.2
408{
409 int edges = 0;
410 for (int i = 0; i < w->numpoints; i++) {
411 const int j = ((i == w->numpoints - 1) ? 0 : i) + 1;
412 vec3_t delta;
413 VectorSubtract(w->p[j], w->p[i], delta);
414 vec_t len = VectorLength(delta);
415 if (len > EDGE_LENGTH) {
416 if (++edges == 3)
417 return false;
418 }
419 }
420 return true;
421}
422
428{
429 for (int i = 0; i < w->numpoints; i++) {
430 for (int j = 0; j < 3; j++)
431 if (w->p[i][j] < -MAX_WORLD_WIDTH || w->p[i][j] > MAX_WORLD_WIDTH)
432 return true;
433 }
434 return false;
435}
436
437#define SNAP_EPSILON 0.01
438
443static void SnapWeldVector (const vec3_t a, const vec3_t b, vec3_t out)
444{
445 /* dummy check */
446 if (a == nullptr || b == nullptr || out == nullptr)
447 return;
448
449 /* do each element */
450 for (int i = 0; i < 3; i++) {
451 /* round to integer */
452 const double ai = rint(a[i]);
453 const double bi = rint(a[i]);
454
455 /* prefer exact integer */
456 if (ai == a[i])
457 out[i] = a[i];
458 else if (bi == b[i])
459 out[i] = b[i];
460
461 /* use nearest */
462 else if (fabs(ai - a[i]) < fabs(bi - b[i]))
463 out[i] = a[i];
464 else
465 out[i] = b[i];
466
467 /* snap */
468 vec_t outi = rint(out[i]);
469 if (fabs(outi - out[i]) <= SNAP_EPSILON)
470 out[i] = outi;
471 }
472}
473
479{
480 /* dummy check */
481 if (!w)
482 return false;
483
484 bool valid = true;
485
486 /* check all verts */
487 for (int i = 0; i < w->numpoints; i++) {
488 /* get second point index */
489 const int j = (i + 1) % w->numpoints;
490 vec3_t vec;
491
492 /* don't remove points if winding is a triangle */
493 if (w->numpoints == 3)
494 return valid;
495
496 /* degenerate edge? */
497 VectorSubtract(w->p[i], w->p[j], vec);
498 float dist = VectorLength(vec);
499 if (dist < ON_EPSILON) {
500 valid = false;
501
502 /* create an average point (ydnar 2002-01-26: using nearest-integer weld preference) */
503 SnapWeldVector(w->p[i], w->p[j], vec);
504 VectorCopy(vec, w->p[i]);
505
506 /* move the remaining verts */
507 for (int k = i + 2; k < w->numpoints; k++)
508 VectorCopy(w->p[k], w->p[k - 1]);
509
510 w->numpoints--;
511 }
512 }
513
514 /* one last check and return */
515 if (w->numpoints < 3)
516 valid = false;
517 return valid;
518}
#define ON_EPSILON
Definition defines.h:374
#define SIDE_FRONT
Definition defines.h:186
#define SIDE_ON
Definition defines.h:187
#define SIDE_BACK
Definition defines.h:188
#define MAX_WORLD_WIDTH
-MAX_WORLD_WIDTH up tp +MAX_WORLD_WIDTH
Definition defines.h:288
void Sys_Error(const char *error,...)
Definition g_main.cpp:421
voidpf void uLong size
Definition ioapi.h:42
void ClearBounds(vec3_t mins, vec3_t maxs)
Sets mins and maxs to their starting points before using AddPointToBounds.
Definition mathlib.cpp:1032
vec_t VectorNormalize(vec3_t v)
Calculate unit vector for a given vec3_t.
Definition mathlib.cpp:745
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition mathlib.cpp:434
void VectorMA(const vec3_t veca, const float scale, const vec3_t vecb, vec3_t outVector)
Sets vector_out (vc) to vevtor1 (va) + scale * vector2 (vb).
Definition mathlib.cpp:261
const vec3_t vec3_origin
Definition mathlib.cpp:35
void AddPointToBounds(const vec3_t v, vec3_t mins, vec3_t maxs)
If the point is outside the box defined by mins and maxs, expand the box to accommodate it....
Definition mathlib.cpp:1042
void CrossProduct(const vec3_t v1, const vec3_t v2, vec3_t cross)
binary operation on vectors in a three-dimensional space
Definition mathlib.cpp:820
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_Alloc(size)
Definition mem.h:40
winding_t * ChopWinding(winding_t *in, vec3_t normal, vec_t dist)
Definition polylib.cpp:391
void FreeWinding(winding_t *w)
Definition polylib.cpp:46
void ChopWindingInPlace(winding_t **inout, const vec3_t normal, const vec_t dist, const vec_t epsilon)
Definition polylib.cpp:299
bool WindingIsTiny(winding_t *w)
Returns true if the winding would be crunched out of existance by the vertex snapping.
Definition polylib.cpp:407
winding_t * ReverseWinding(const winding_t *w)
Definition polylib.cpp:193
#define EDGE_LENGTH
Definition polylib.cpp:402
static void SnapWeldVector(const vec3_t a, const vec3_t b, vec3_t out)
welds two vec3_t's into a third, taking into account nearest-to-integer instead of averaging
Definition polylib.cpp:443
winding_t * AllocWinding(int points)
Allocate a new winding (polygon).
Definition polylib.cpp:38
void RemoveColinearPoints(winding_t *w)
Definition polylib.cpp:55
bool WindingIsHuge(const winding_t *w)
Returns true if the winding still has one of the points from basewinding for plane.
Definition polylib.cpp:427
winding_t * BaseWindingForPlane(const vec3_t normal, const vec_t dist)
Definition polylib.cpp:116
void WindingCenter(const winding_t *w, vec3_t center)
Definition polylib.cpp:106
void WindingBounds(const winding_t *w, vec3_t mins, vec3_t maxs)
Definition polylib.cpp:97
#define BOGUS_RANGE
Definition polylib.cpp:31
bool FixWinding(winding_t *w)
removes degenerate edges from a winding
Definition polylib.cpp:478
vec_t WindingArea(const winding_t *w)
Definition polylib.cpp:81
winding_t * CopyWinding(const winding_t *w)
Copy a winding with all its points allocated.
Definition polylib.cpp:185
#define SNAP_EPSILON
Definition polylib.cpp:437
void ClipWindingEpsilon(const winding_t *in, const vec3_t normal, const vec_t dist, const vec_t epsilon, winding_t **front, winding_t **back)
Definition polylib.cpp:204
#define MAX_POINTS_ON_WINDING
Definition polylib.h:36
QGL_EXTERN GLuint GLchar GLuint * len
Definition r_gl.h:99
QGL_EXTERN int GLboolean GLfloat * v
Definition r_gl.h:120
QGL_EXTERN GLfloat f
Definition r_gl.h:114
QGL_EXTERN GLint i
Definition r_gl.h:113
for storing the vertices of the side of a brush or other polygon
Definition polylib.h:30
int numpoints
Definition polylib.h:31
vec3_t p[4]
Definition polylib.h:32
float vec_t
Definition ufotypes.h:37
vec_t vec3_t[3]
Definition ufotypes.h:39
static const vec3_t scale
#define VectorClear(a)
Definition vector.h:55
#define VectorSubtract(a, b, dest)
Definition vector.h:45
#define VectorCopy(src, dest)
Definition vector.h:51
#define VectorAdd(a, b, dest)
Definition vector.h:47
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition vector.h:44
#define VectorScale(in, scale, out)
Definition vector.h:79