UFO: Alien Invasion
Loading...
Searching...
No Matches
faces.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
28#include "bsp.h"
29
30#define INTEGRAL_EPSILON 0.01
31#define POINT_EPSILON 0.0625
32#define OFF_EPSILON 0.5
33
35
36#define MAX_SUPERVERTS 512
38static int numsuperverts;
39
40static const face_t* edgefaces[MAX_MAP_EDGES][2];
42
45
46static int num_edge_verts;
48
49#define HASH_SIZE 64
50
51static int vertexchain[MAX_MAP_VERTS]; /* the next vertex in a hash chain */
52static int hashverts[HASH_SIZE * HASH_SIZE]; /* a vertex number, or 0 for no verts */
53
57static unsigned HashVec (const vec3_t vec)
58{
59 const int x = (4096 + (int)(vec[0] + 0.5)) >> 7;
60 const int y = (4096 + (int)(vec[1] + 0.5)) >> 7;
61
62 if (x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE)
63 Sys_Error("HashVec: point outside valid range");
64
65 return y * HASH_SIZE + x;
66}
67
72static int GetVertexnum (const vec3_t in)
73{
74 vec3_t vert;
75
77
78 for (int i = 0; i < 3; i++) {
79 if (fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON)
80 vert[i] = Q_rint(in[i]);
81 else
82 vert[i] = in[i];
83 }
84
85 int h = HashVec(vert);
86
87 for (int vnum = hashverts[h]; vnum; vnum = vertexchain[vnum]) {
88 const float* p = curTile->vertexes[vnum].point;
89 if (fabs(p[0] - vert[0]) < POINT_EPSILON
90 && fabs(p[1] - vert[1]) < POINT_EPSILON
91 && fabs(p[2] - vert[2]) < POINT_EPSILON)
92 return vnum;
93 }
94
95 /* emit a vertex */
96 if (curTile->numvertexes == MAX_MAP_VERTS)
97 Sys_Error("numvertexes == MAX_MAP_VERTS");
98
99 curTile->vertexes[curTile->numvertexes].point[0] = vert[0];
100 curTile->vertexes[curTile->numvertexes].point[1] = vert[1];
101 curTile->vertexes[curTile->numvertexes].point[2] = vert[2];
102
103 vertexchain[curTile->numvertexes] = hashverts[h];
104 hashverts[h] = curTile->numvertexes;
105
107
108 curTile->numvertexes++;
109 curTile->numnormals++;
110
111 return curTile->numvertexes - 1;
112}
113
114static face_t* AllocFace (void)
115{
116 c_faces++;
117
118 return Mem_AllocType(face_t);
119}
120
122{
123 face_t* newf;
124
125 newf = AllocFace();
126 *newf = *f;
127 newf->merged = nullptr;
128 newf->split[0] = newf->split[1] = nullptr;
129 newf->w = nullptr;
130 return newf;
131}
132
134{
135 if (f->w)
136 FreeWinding(f->w);
137 Mem_Free(f);
138 c_faces--;
139}
140
152static void FaceFromSuperverts (node_t* node, face_t* f, int base)
153{
154 int i, remaining;
155
156 remaining = numsuperverts;
157 /* must split into two faces, because of vertex overload */
158 while (remaining > MAXEDGES) {
160
161 face_t* newf = f->split[0] = NewFaceFromFace(f);
162 newf->next = node->faces;
163 node->faces = newf;
164
165 newf->numpoints = MAXEDGES;
166 for (i = 0; i < MAXEDGES; i++)
167 newf->vertexnums[i] = superverts[(i + base) % numsuperverts];
168
169 f->split[1] = NewFaceFromFace(f);
170 f = f->split[1];
171 f->next = node->faces;
172 node->faces = f;
173
174 remaining -= (MAXEDGES - 2);
175 base = (base + MAXEDGES - 1) % numsuperverts;
176 }
177
178 /* copy the vertexes back to the face */
179 f->numpoints = remaining;
180 for (i = 0; i < remaining; i++)
181 f->vertexnums[i] = superverts[(i + base) % numsuperverts];
182}
183
184static void EmitFaceVertexes (node_t* node, face_t* f)
185{
186 if (f->merged || f->split[0] || f->split[1])
187 return;
188
189 winding_t* w = f->w;
190 for (int i = 0; i < w->numpoints; i++) {
191 /* make every point unique */
192 if (config.noweld) {
193 if (curTile->numvertexes == MAX_MAP_VERTS)
194 Sys_Error("MAX_MAP_VERTS (%i)", curTile->numvertexes);
195 superverts[i] = curTile->numvertexes;
196 VectorCopy(w->p[i], curTile->vertexes[curTile->numvertexes].point);
197 curTile->numvertexes++;
198 curTile->numnormals++;
200 c_totalverts++;
201 } else
202 superverts[i] = GetVertexnum(w->p[i]);
203 }
205
206 /* this may fragment the face if > MAXEDGES */
207 FaceFromSuperverts(node, f, 0);
208}
209
210static void EmitVertexes_r (node_t* node)
211{
212 if (node->planenum == PLANENUM_LEAF)
213 return;
214
215 for (face_t* f = node->faces; f; f = f->next)
216 EmitFaceVertexes(node, f);
217
218 for (int i = 0; i < 2; i++)
219 EmitVertexes_r(node->children[i]);
220}
221
222
226static void FindEdgeVerts (const vec3_t v1, const vec3_t v2)
227{
228 int x1, x2, y1, y2, t;
229 int x, y, vnum;
230
231 x1 = (MAX_WORLD_WIDTH + (int)(v1[0] + 0.5)) >> 7;
232 y1 = (MAX_WORLD_WIDTH + (int)(v1[1] + 0.5)) >> 7;
233 x2 = (MAX_WORLD_WIDTH + (int)(v2[0] + 0.5)) >> 7;
234 y2 = (MAX_WORLD_WIDTH + (int)(v2[1] + 0.5)) >> 7;
235
236 if (x1 > x2) {
237 t = x1;
238 x1 = x2;
239 x2 = t;
240 }
241 if (y1 > y2) {
242 t = y1;
243 y1 = y2;
244 y2 = t;
245 }
246 num_edge_verts = 0;
247 for (x = x1; x <= x2; x++)
248 for (y = y1; y <= y2; y++)
249 for (vnum = hashverts[y * HASH_SIZE + x]; vnum; vnum = vertexchain[vnum])
250 edge_verts[num_edge_verts++] = vnum;
251}
252
256static void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
257{
258 int k;
259 vec_t dist, error;
260 vec3_t delta, exact, off, p;
261
262 if (p1 == p2) {
263 c_degenerate++;
264 return; /* degenerate edge */
265 }
266
267 for (k = startvert; k < num_edge_verts; k++) {
268 const int j = edge_verts[k];
269 if (j == p1 || j == p2)
270 continue;
271
272 VectorCopy(curTile->vertexes[j].point, p);
273
274 VectorSubtract(p, edge_start, delta);
275 dist = DotProduct(delta, edge_dir);
276 if (dist <= start || dist >= end)
277 continue; /* off an end */
278 VectorMA(edge_start, dist, edge_dir, exact);
279 VectorSubtract(p, exact, off);
280 error = VectorLength(off);
281
282 if (fabs(error) > OFF_EPSILON)
283 continue; /* not on the edge */
284
285 /* break the edge */
286 c_tjunctions++;
287 TestEdge(start, dist, p1, j, k + 1);
288 TestEdge(dist, end, j, p2, k + 1);
289 return;
290 }
291
292 /* the edge p1 to p2 is now free of tjunctions */
294 Sys_Error("MAX_SUPERVERTS (%i)", numsuperverts);
297}
298
299static void FixFaceEdges (node_t* node, face_t* f)
300{
301 int i, base;
302 vec3_t e2;
304
305 if (f->merged || f->split[0] || f->split[1])
306 return;
307
308 numsuperverts = 0;
309
310 for (i = 0; i < f->numpoints; i++) {
311 const int p1 = f->vertexnums[i];
312 const int p2 = f->vertexnums[(i + 1) % f->numpoints];
313
314 VectorCopy(curTile->vertexes[p1].point, edge_start);
315 VectorCopy(curTile->vertexes[p2].point, e2);
316
318
321
322 start[i] = numsuperverts;
323 TestEdge(0, len, p1, p2, 0);
324
325 count[i] = numsuperverts - start[i];
326 }
327
328 /* entire face collapsed */
329 if (numsuperverts < 3) {
330 f->numpoints = 0;
332 return;
333 }
334
335 /* we want to pick a vertex that doesn't have tjunctions
336 * on either side, which can cause artifacts on trifans,
337 * especially underwater */
338 for (i = 0; i < f->numpoints; i++) {
339 if (count[i] == 1 && count[(i + f->numpoints - 1) % f->numpoints] == 1)
340 break;
341 }
342 if (i == f->numpoints) {
344 base = 0;
345 } else {
346 /* rotate the vertex order */
347 base = start[i];
348 }
349
350 /* this may fragment the face if > MAXEDGES */
351 FaceFromSuperverts(node, f, base);
352}
353
354static void FixEdges_r (node_t* node)
355{
356 if (node->planenum == PLANENUM_LEAF)
357 return;
358
359 for (face_t* f = node->faces; f; f = f->next)
360 FixFaceEdges(node, f);
361
362 for (int i = 0; i < 2; i++)
363 FixEdges_r(node->children[i]);
364}
365
370void FixTjuncs (node_t* headnode)
371{
372 /* snap and merge all vertexes */
373 Verb_Printf(VERB_EXTRA, "---- snap verts ----\n");
375 c_totalverts = 0;
376 c_uniqueverts = 0;
377 c_faceoverflows = 0;
378 EmitVertexes_r(headnode);
379 Verb_Printf(VERB_EXTRA, "%i unique from %i\n", c_uniqueverts, c_totalverts);
380
381 /* break edges on tjunctions */
382 Verb_Printf(VERB_EXTRA, "---- tjunc ----\n");
383 c_degenerate = 0;
384 c_facecollapse = 0;
385 c_tjunctions = 0;
386 if (!config.notjunc)
387 FixEdges_r(headnode);
388 Verb_Printf(VERB_EXTRA, "%5i edges degenerated\n", c_degenerate);
389 Verb_Printf(VERB_EXTRA, "%5i faces degenerated\n", c_facecollapse);
390 Verb_Printf(VERB_EXTRA, "%5i edges added by tjunctions\n", c_tjunctions);
391 Verb_Printf(VERB_EXTRA, "%5i faces added by tjunctions\n", c_faceoverflows);
392 Verb_Printf(VERB_EXTRA, "%5i bad start verts\n", c_badstartverts);
393}
394
399int GetEdge (int v1, int v2, const face_t* f)
400{
401 dBspEdge_t* edge;
402
403 if (!config.noshare) {
404 int i;
405 for (i = firstmodeledge; i < curTile->numedges; i++) {
406 edge = &curTile->edges[i];
407 if (v1 == edge->v[1] && v2 == edge->v[0]
408 && edgefaces[i][0]->contentFlags == f->contentFlags) {
409 if (edgefaces[i][1])
410 continue;
411 edgefaces[i][1] = f;
412 return -i;
413 }
414 }
415 }
416
417 /* emit an edge */
418 if (curTile->numedges >= MAX_MAP_EDGES)
419 Sys_Error("numedges >= MAX_MAP_EDGES (%i)", curTile->numedges);
420 edge = &curTile->edges[curTile->numedges];
421 edge->v[0] = v1;
422 edge->v[1] = v2;
423 edgefaces[curTile->numedges][0] = f;
424 curTile->numedges++;
425
426 return curTile->numedges - 1;
427}
428
429/*
430===========================================================================
431FACE MERGING
432===========================================================================
433*/
434
435#define CONTINUOUS_EPSILON 0.001
436
443static winding_t* TryMergeWinding (winding_t* f1, winding_t* f2, const vec3_t planenormal)
444{
445 vec_t* p1, *p2, *back;
446 winding_t* newf;
447 int i, j, k, l;
448 vec3_t normal, delta;
449 vec_t dot;
450 bool keep1, keep2;
451
452 p1 = p2 = nullptr;
453 j = 0;
454
455 /* find a common edge */
456 for (i = 0; i < f1->numpoints; i++) {
457 p1 = f1->p[i];
458 p2 = f1->p[(i + 1) % f1->numpoints];
459 for (j = 0; j < f2->numpoints; j++) {
460 const vec_t* p3 = f2->p[j];
461 const vec_t* p4 = f2->p[(j + 1) % f2->numpoints];
462 for (k = 0; k < 3; k++) {
463 if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON)
464 break;
465 if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON)
466 break;
467 }
468 if (k == 3)
469 break;
470 }
471 if (j < f2->numpoints)
472 break;
473 }
474
475 /* no matching edges */
476 if (i == f1->numpoints)
477 return nullptr;
478
479 /* check slope of connected lines */
480 /* if the slopes are colinear, the point can be removed */
481 back = f1->p[(i + f1->numpoints - 1) % f1->numpoints];
482 VectorSubtract(p1, back, delta);
483 CrossProduct(planenormal, delta, normal);
484 VectorNormalize(normal);
485
486 back = f2->p[(j + 2) % f2->numpoints];
487 VectorSubtract(back, p1, delta);
488 dot = DotProduct(delta, normal);
489 /* not a convex polygon */
490 if (dot > CONTINUOUS_EPSILON)
491 return nullptr;
492 keep1 = (bool)(dot < -CONTINUOUS_EPSILON);
493
494 back = f1->p[(i + 2) % f1->numpoints];
495 VectorSubtract(back, p2, delta);
496 CrossProduct(planenormal, delta, normal);
497 VectorNormalize(normal);
498
499 back = f2->p[(j + f2->numpoints - 1) % f2->numpoints];
500 VectorSubtract(back, p2, delta);
501 dot = DotProduct(delta, normal);
502 /* not a convex polygon */
503 if (dot > CONTINUOUS_EPSILON)
504 return nullptr;
505 keep2 = (bool)(dot < -CONTINUOUS_EPSILON);
506
507 /* build the new polygon */
508 newf = AllocWinding(f1->numpoints + f2->numpoints);
509
510 /* copy first polygon */
511 for (k = (i + 1) % f1->numpoints; k != i; k = (k + 1) % f1->numpoints) {
512 if (k == (i + 1) % f1->numpoints && !keep2)
513 continue;
514
515 VectorCopy(f1->p[k], newf->p[newf->numpoints]);
516 newf->numpoints++;
517 }
518
519 /* copy second polygon */
520 for (l = (j + 1) % f2->numpoints; l != j; l = (l + 1) % f2->numpoints) {
521 if (l == (j + 1) % f2->numpoints && !keep1)
522 continue;
523 VectorCopy(f2->p[l], newf->p[newf->numpoints]);
524 newf->numpoints++;
525 }
526
527 return newf;
528}
529
537static face_t* TryMerge (face_t* f1, face_t* f2, const vec3_t planenormal)
538{
539 face_t* newf;
540 winding_t* nw;
541
542 if (!f1->w || !f2->w)
543 return nullptr;
544 if (f1->texinfo != f2->texinfo)
545 return nullptr;
546 if (f1->planenum != f2->planenum) /* on front and back sides */
547 return nullptr;
548 if (f1->contentFlags != f2->contentFlags)
549 return nullptr;
550
551 nw = TryMergeWinding(f1->w, f2->w, planenormal);
552 if (!nw)
553 return nullptr;
554
555 c_merge++;
556 newf = NewFaceFromFace(f1);
557 newf->w = nw;
558
559 f1->merged = newf;
560 f2->merged = newf;
561
562 return newf;
563}
564
565static void MergeNodeFaces (node_t* node)
566{
567 face_t* f1;
568
569 for (f1 = node->faces; f1; f1 = f1->next) {
570 face_t* f2;
571 if (f1->merged || f1->split[0] || f1->split[1])
572 continue;
573 for (f2 = node->faces; f2 != f1; f2 = f2->next) {
574 const plane_t* plane = &mapplanes[node->planenum];
575 face_t* merged;
576 face_t* end;
577
578 if (f2->merged || f2->split[0] || f2->split[1])
579 continue;
580
581 merged = TryMerge(f1, f2, plane->normal);
582 if (!merged)
583 continue;
584
585 /* add merged to the end of the node face list
586 * so it will be checked against all the faces again */
587 for (end = node->faces; end->next; end = end->next);
588
589 merged->next = nullptr;
590 end->next = merged;
591 break;
592 }
593 }
594}
595
596/*===================================================================== */
597
601static void SubdivideFace (node_t* node, face_t* f)
602{
603 if (f->merged)
604 return;
605
606 /* special (non-surface cached) faces don't need subdivision */
607 const dBspTexinfo_t* tex = &curTile->texinfo[f->texinfo];
608 if (tex->surfaceFlags & SURF_WARP)
609 return;
610
611 for (int axis = 0; axis < 2; axis++) {
612 while (1) {
613 const winding_t* w = f->w;
614 winding_t* frontw, *backw;
615 float mins = 999999;
616 float maxs = -999999;
617 vec3_t temp;
618 vec_t v;
619
620 VectorCopy(tex->vecs[axis], temp);
621 for (int i = 0; i < w->numpoints; i++) {
622 v = DotProduct(w->p[i], temp);
623 if (v < mins)
624 mins = v;
625 if (v > maxs)
626 maxs = v;
627 }
628
629 /* no bsp subdivide for this winding? */
630 if (maxs - mins <= config.subdivideSize)
631 break;
632
633 /* split it */
634 c_subdivide++;
635
636 v = VectorNormalize(temp);
637
638 vec_t dist = (mins + config.subdivideSize - 16) / v;
639
640 ClipWindingEpsilon(w, temp, dist, ON_EPSILON, &frontw, &backw);
641 if (!frontw || !backw)
642 Sys_Error("SubdivideFace: didn't split the polygon (texture: '%s')",
643 tex->texture);
644
645 f->split[0] = NewFaceFromFace(f);
646 f->split[0]->w = frontw;
647 f->split[0]->next = node->faces;
648 node->faces = f->split[0];
649
650 f->split[1] = NewFaceFromFace(f);
651 f->split[1]->w = backw;
652 f->split[1]->next = node->faces;
653 node->faces = f->split[1];
654
655 SubdivideFace(node, f->split[0]);
656 SubdivideFace(node, f->split[1]);
657 return;
658 }
659 }
660}
661
662static void SubdivideNodeFaces (node_t* node)
663{
664 face_t* f;
665
666 for (f = node->faces; f; f = f->next)
667 SubdivideFace(node, f);
668}
669
670static int c_nodefaces;
671
672static face_t* FaceFromPortal (portal_t* p, bool pside)
673{
674 face_t* f;
675 side_t* side = p->side;
676
677 /* portal does not bridge different visible contents */
678 if (!side)
679 return nullptr;
680
681 /* nodraw/caulk faces */
682 if (side->surfaceFlags & SURF_NODRAW)
683 return nullptr;
684
685 f = AllocFace();
686
687 f->texinfo = side->texinfo;
688 f->planenum = (side->planenum & ~1) | pside;
689 f->portal = p;
690
691 if ((p->nodes[pside]->contentFlags & CONTENTS_WINDOW)
692 && VisibleContents(p->nodes[!pside]->contentFlags ^ p->nodes[pside]->contentFlags) == CONTENTS_WINDOW)
693 return nullptr; /* don't show insides of windows */
694
695 /* do back-clipping */
696 if (!config.nobackclip && mapplanes[f->planenum].normal[2] < -0.9) {
697 /* this face is not visible from birds view - optimize away
698 * but only if it's not light emitting surface */
699 const entity_t* e = &entities[side->brush->entitynum];
700 if (!Q_streq(ValueForKey(e, "classname"), "func_rotating")) {
701 if (!(curTile->texinfo[f->texinfo].surfaceFlags & SURF_LIGHT)) {
702 /* e.g. water surfaces are removed if we set the surfaceFlags
703 * to SURF_NODRAW for this side */
704 /*side->surfaceFlags |= SURF_NODRAW;*/
705 return nullptr;
706 }
707 }
708 }
709
710 if (pside) {
711 f->w = ReverseWinding(p->winding);
712 f->contentFlags = p->nodes[1]->contentFlags;
713 } else {
714 f->w = CopyWinding(p->winding);
715 f->contentFlags = p->nodes[0]->contentFlags;
716 }
717 return f;
718}
719
720
728static void MakeFaces_r (node_t* node)
729{
730 portal_t* p;
731
732 /* recurse down to leafs */
733 if (node->planenum != PLANENUM_LEAF) {
734 MakeFaces_r(node->children[0]);
735 MakeFaces_r(node->children[1]);
736
737 /* merge together all visible faces on the node */
738 if (!config.nomerge)
739 MergeNodeFaces(node);
740 if (!config.nosubdiv)
741 SubdivideNodeFaces(node);
742
743 return;
744 }
745
746 /* solid leafs never have visible faces */
747 if (node->contentFlags & CONTENTS_SOLID)
748 return;
749
750 /* see which portals are valid */
751 for (p = node->portals; p;) {
752 const int pside = (p->nodes[1] == node);
753
754 p->face[pside] = FaceFromPortal(p, pside);
755 if (p->face[pside]) {
756 c_nodefaces++;
757 p->face[pside]->next = p->onnode->faces;
758 p->onnode->faces = p->face[pside];
759 }
760 p = p->next[pside];
761 }
762}
763
764void MakeFaces (node_t* node)
765{
766 Verb_Printf(VERB_EXTRA, "--- MakeFaces ---\n");
767 c_merge = 0;
768 c_subdivide = 0;
769 c_nodefaces = 0;
770
771 MakeFaces_r(node);
772
773 Verb_Printf(VERB_EXTRA, "%5i makefaces\n", c_nodefaces);
774 Verb_Printf(VERB_EXTRA, "%5i merged\n", c_merge);
775 Verb_Printf(VERB_EXTRA, "%5i subdivided\n", c_subdivide);
776}
plane_t mapplanes[MAX_MAP_PLANES]
Definition map.cpp:43
uint32_t VisibleContents(uint32_t contents)
Returns the single content bit of the strongest visible content present.
Definition portals.cpp:64
entity_t entities[MAX_MAP_ENTITIES]
Definition bspfile.cpp:395
const char * ValueForKey(const entity_t *ent, const char *key)
Definition bspfile.cpp:558
#define ON_EPSILON
Definition defines.h:374
#define MAX_MAP_EDGES
Definition defines.h:146
#define SURF_LIGHT
Definition defines.h:254
#define MAXEDGES
Definition defines.h:49
#define SURF_NODRAW
Definition defines.h:260
#define MAX_MAP_VERTS
Definition defines.h:143
#define CONTENTS_SOLID
Definition defines.h:223
#define PLANENUM_LEAF
Definition defines.h:45
#define SURF_WARP
Definition defines.h:256
#define CONTENTS_WINDOW
Definition defines.h:224
#define MAX_WORLD_WIDTH
-MAX_WORLD_WIDTH up tp +MAX_WORLD_WIDTH
Definition defines.h:288
static int edge_verts[MAX_MAP_VERTS]
Definition faces.cpp:47
static int superverts[MAX_SUPERVERTS]
Definition faces.cpp:37
static void MakeFaces_r(node_t *node)
If a portal will make a visible face, mark the side that originally created it.
Definition faces.cpp:728
static int c_merge
Definition faces.cpp:34
#define CONTINUOUS_EPSILON
Definition faces.cpp:435
static face_t * FaceFromPortal(portal_t *p, bool pside)
Definition faces.cpp:672
#define MAX_SUPERVERTS
Definition faces.cpp:36
static int c_tjunctions
Definition faces.cpp:34
static int c_badstartverts
Definition faces.cpp:34
int firstmodeledge
Definition faces.cpp:41
static int c_subdivide
Definition faces.cpp:34
int GetEdge(int v1, int v2, const face_t *f)
Definition faces.cpp:399
#define INTEGRAL_EPSILON
Definition faces.cpp:30
static int c_uniqueverts
Definition faces.cpp:34
static winding_t * TryMergeWinding(winding_t *f1, winding_t *f2, const vec3_t planenormal)
If two polygons share a common edge and the edges that meet at the common points are both inside the ...
Definition faces.cpp:443
static int hashverts[HASH_SIZE *HASH_SIZE]
Definition faces.cpp:52
static int c_faceoverflows
Definition faces.cpp:34
static int c_nodefaces
Definition faces.cpp:670
static int c_totalverts
Definition faces.cpp:34
static void EmitVertexes_r(node_t *node)
Definition faces.cpp:210
void FixTjuncs(node_t *headnode)
Definition faces.cpp:370
static vec3_t edge_start
Definition faces.cpp:44
void MakeFaces(node_t *node)
Definition faces.cpp:764
static vec3_t edge_dir
Definition faces.cpp:43
static void EmitFaceVertexes(node_t *node, face_t *f)
Definition faces.cpp:184
static void FixFaceEdges(node_t *node, face_t *f)
Definition faces.cpp:299
static void SubdivideFace(node_t *node, face_t *f)
Chop up faces that are larger than we want in the surface cache.
Definition faces.cpp:601
static void SubdivideNodeFaces(node_t *node)
Definition faces.cpp:662
static const face_t * edgefaces[MAX_MAP_EDGES][2]
Definition faces.cpp:40
static void FindEdgeVerts(const vec3_t v1, const vec3_t v2)
Uses the hash tables to cut down to a small number.
Definition faces.cpp:226
static void MergeNodeFaces(node_t *node)
Definition faces.cpp:565
#define OFF_EPSILON
Definition faces.cpp:32
static void FaceFromSuperverts(node_t *node, face_t *f, int base)
The faces vertexes have been added to the superverts[] array, and there may be more there than can be...
Definition faces.cpp:152
void FreeFace(face_t *f)
Definition faces.cpp:133
static face_t * NewFaceFromFace(const face_t *f)
Definition faces.cpp:121
static int numsuperverts
Definition faces.cpp:38
static int num_edge_verts
Definition faces.cpp:46
static int GetVertexnum(const vec3_t in)
Returns the number of an existing vertex or allocates a new one.
Definition faces.cpp:72
static int c_faces
Definition faces.cpp:34
static int c_facecollapse
Definition faces.cpp:34
static void TestEdge(vec_t start, vec_t end, int p1, int p2, int startvert)
Definition faces.cpp:256
#define HASH_SIZE
Definition faces.cpp:49
static face_t * AllocFace(void)
Definition faces.cpp:114
static face_t * TryMerge(face_t *f1, face_t *f2, const vec3_t planenormal)
If two polygons share a common edge and the edges that meet at the common points are both inside the ...
Definition faces.cpp:537
static void FixEdges_r(node_t *node)
Definition faces.cpp:354
static int vertexchain[MAX_MAP_VERTS]
Definition faces.cpp:51
static unsigned HashVec(const vec3_t vec)
Definition faces.cpp:57
static int c_degenerate
Definition faces.cpp:34
#define POINT_EPSILON
Definition faces.cpp:31
void Sys_Error(const char *error,...)
Definition g_main.cpp:421
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
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
vec_t Q_rint(const vec_t in)
Round to nearest integer.
Definition mathlib.cpp:156
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 EQUAL_EPSILON
Definition mathlib.h:40
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_AllocType(type)
Definition mem.h:39
void FreeWinding(winding_t *w)
Definition polylib.cpp:46
winding_t * ReverseWinding(const winding_t *w)
Definition polylib.cpp:193
winding_t * AllocWinding(int points)
Allocate a new winding (polygon).
Definition polylib.cpp:38
winding_t * CopyWinding(const winding_t *w)
Copy a winding with all its points allocated.
Definition polylib.cpp:185
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
QGL_EXTERN GLuint GLchar GLuint * len
Definition r_gl.h:99
QGL_EXTERN GLuint count
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
#define Q_streq(a, b)
Definition shared.h:136
#define OBJZERO(obj)
Definition shared.h:178
unsigned short v[2]
Definition typedefs.h:400
char texture[32]
Definition typedefs.h:392
uint32_t surfaceFlags
Definition typedefs.h:390
float vecs[2][4]
Definition typedefs.h:389
Definition map.h:42
uint16_t planenum
Definition map.h:53
struct face_s * merged
Definition map.h:48
int vertexnums[MAXEDGES]
Definition map.h:57
winding_t * w
Definition map.h:55
uint32_t contentFlags
Definition map.h:54
struct face_s * next
Definition map.h:43
int numpoints
Definition map.h:56
struct face_s * split[2]
Definition map.h:49
int texinfo
Definition map.h:52
Definition bsp.h:42
int32_t planenum
Definition bsp.h:44
int32_t contentFlags
Definition bsp.h:56
face_t * faces
Definition bsp.h:52
struct portal_s * portals
Definition bsp.h:58
struct node_s * children[2]
Definition bsp.h:51
Definition map.h:98
vec3_t normal
Definition map.h:99
struct node_s * nodes[2]
Definition map.h:113
struct side_s * side
Definition map.h:118
winding_t * winding
Definition map.h:115
struct node_s * onnode
Definition map.h:112
face_t * face[2]
Definition map.h:119
struct portal_s * next[2]
Definition map.h:114
Definition map.h:60
uint16_t planenum
Definition map.h:61
uint32_t surfaceFlags
Definition map.h:66
int texinfo
Definition map.h:62
struct mapbrush_s * brush
Definition map.h:72
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
static config_t config
Definition test_all.cpp:43
dMapTile_t * curTile
Definition bsp.cpp:32
void Verb_Printf(const verbosityLevel_t importance, const char *format,...) __attribute__((format(__printf__
@ VERB_EXTRA
Definition shared.h:46
float vec_t
Definition ufotypes.h:37
vec_t vec3_t[3]
Definition ufotypes.h:39
#define VectorSubtract(a, b, dest)
Definition vector.h:45
#define VectorCopy(src, dest)
Definition vector.h:51
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition vector.h:44