UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
faces.cpp
Go to the documentation of this file.
1 
7 /*
8 Copyright (C) 1997-2001 Id Software, Inc.
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 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
38 static int numsuperverts;
39 
40 static const face_t* edgefaces[MAX_MAP_EDGES][2];
42 
45 
46 static int num_edge_verts;
48 
49 #define HASH_SIZE 64
50 
51 static int vertexchain[MAX_MAP_VERTS]; /* the next vertex in a hash chain */
52 static int hashverts[HASH_SIZE * HASH_SIZE]; /* a vertex number, or 0 for no verts */
53 
57 static 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 
72 static int GetVertexnum (const vec3_t in)
73 {
74  vec3_t vert;
75 
76  c_totalverts++;
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 */
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 
105 
106  c_uniqueverts++;
107 
108  curTile->numvertexes++;
109  curTile->numnormals++;
110 
111  return curTile->numvertexes - 1;
112 }
113 
114 static face_t* AllocFace (void)
115 {
116  c_faces++;
117 
118  return Mem_AllocType(face_t);
119 }
120 
121 static face_t* NewFaceFromFace (const face_t* f)
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 
152 static 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) {
159  c_faceoverflows++;
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 
184 static 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) {
194  Sys_Error("MAX_MAP_VERTS (%i)", curTile->numvertexes);
197  curTile->numvertexes++;
198  curTile->numnormals++;
199  c_uniqueverts++;
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 
210 static 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 
226 static 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 
256 static 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 
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);
296  numsuperverts++;
297 }
298 
299 static void FixFaceEdges (node_t* node, face_t* f)
300 {
301  int i, base;
302  vec3_t e2;
303  int count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];
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 
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;
331  c_facecollapse++;
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) {
343  c_badstartverts++;
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 
354 static 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 
370 void 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 
399 int 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 */
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 ===========================================================================
431 FACE MERGING
432 ===========================================================================
433 */
434 
435 #define CONTINUOUS_EPSILON 0.001
436 
443 static 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 
537 static 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 
565 static 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 
601 static 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 
662 static 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 
670 static int c_nodefaces;
671 
672 static 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")) {
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 
728 static 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 
764 void 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 }
struct node_s * onnode
Definition: map.h:112
int32_t contentFlags
Definition: bsp.h:56
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition: mathlib.cpp:434
#define HASH_SIZE
Definition: faces.cpp:49
int vertexnums[MAXEDGES]
Definition: map.h:57
static int vertexchain[MAX_MAP_VERTS]
Definition: faces.cpp:51
#define SURF_NODRAW
Definition: defines.h:260
vec3_t normal
Definition: map.h:99
dBspEdge_t edges[MAX_MAP_EDGES]
Definition: typedefs.h:493
#define VectorCopy(src, dest)
Definition: vector.h:51
static int c_faces
Definition: faces.cpp:34
void Sys_Error(const char *error,...)
Definition: g_main.cpp:421
int texinfo
Definition: map.h:62
static int edge_verts[MAX_MAP_VERTS]
Definition: faces.cpp:47
unsigned short v[2]
Definition: typedefs.h:400
winding_t * CopyWinding(const winding_t *w)
Copy a winding with all its points allocated.
Definition: polylib.cpp:185
static void TestEdge(vec_t start, vec_t end, int p1, int p2, int startvert)
Definition: faces.cpp:256
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
#define CONTINUOUS_EPSILON
Definition: faces.cpp:435
Definition: map.h:42
int entitynum
Definition: map.h:76
struct face_s * next
Definition: map.h:43
static int c_merge
Definition: faces.cpp:34
#define CONTENTS_SOLID
Definition: defines.h:223
#define MAX_MAP_EDGES
Definition: defines.h:146
static int c_nodefaces
Definition: faces.cpp:670
#define INTEGRAL_EPSILON
Definition: faces.cpp:30
static int c_tjunctions
Definition: faces.cpp:34
struct portal_s * next[2]
Definition: map.h:114
float vec_t
Definition: ufotypes.h:37
float vecs[2][4]
Definition: typedefs.h:389
uint32_t contentFlags
Definition: map.h:54
static unsigned HashVec(const vec3_t vec)
Definition: faces.cpp:57
static int c_uniqueverts
Definition: faces.cpp:34
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
static int hashverts[HASH_SIZE *HASH_SIZE]
Definition: faces.cpp:52
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
winding_t * winding
Definition: map.h:115
int GetEdge(int v1, int v2, const face_t *f)
Definition: faces.cpp:399
#define OFF_EPSILON
Definition: faces.cpp:32
entity_t entities[MAX_MAP_ENTITIES]
Definition: bspfile.cpp:395
static face_t * AllocFace(void)
Definition: faces.cpp:114
static int GetVertexnum(const vec3_t in)
Returns the number of an existing vertex or allocates a new one.
Definition: faces.cpp:72
int numedges
Definition: typedefs.h:492
#define CONTENTS_WINDOW
Definition: defines.h:224
int32_t planenum
Definition: bsp.h:44
static void EmitFaceVertexes(node_t *node, face_t *f)
Definition: faces.cpp:184
#define MAX_MAP_VERTS
Definition: defines.h:143
static void FixEdges_r(node_t *node)
Definition: faces.cpp:354
void FreeFace(face_t *f)
Definition: faces.cpp:133
struct face_s * split[2]
Definition: map.h:49
static vec3_t edge_start
Definition: faces.cpp:44
uint32_t surfaceFlags
Definition: typedefs.h:390
dBspTexinfo_t texinfo[MAX_MAP_TEXINFO]
Definition: typedefs.h:487
static void EmitVertexes_r(node_t *node)
Definition: faces.cpp:210
void MakeFaces(node_t *node)
Definition: faces.cpp:764
static int num_edge_verts
Definition: faces.cpp:46
Definition: map.h:98
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition: vector.h:44
#define OBJZERO(obj)
Definition: shared.h:178
struct node_s * children[2]
Definition: bsp.h:51
winding_t * w
Definition: map.h:55
static int c_subdivide
Definition: faces.cpp:34
winding_t * AllocWinding(int points)
Allocate a new winding (polygon)
Definition: polylib.cpp:38
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
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
int firstmodeledge
Definition: faces.cpp:41
struct node_s * nodes[2]
Definition: map.h:113
uint16_t planenum
Definition: map.h:61
static face_t * FaceFromPortal(portal_t *p, bool pside)
Definition: faces.cpp:672
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
plane_t mapplanes[MAX_MAP_PLANES]
Definition: map.cpp:43
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 vec3_t edge_dir
Definition: faces.cpp:43
struct side_s * side
Definition: map.h:118
void Verb_Printf(const verbosityLevel_t importance, const char *format,...) __attribute__((format(__printf__
float point[3]
Definition: typedefs.h:362
Definition: map.h:60
#define EQUAL_EPSILON
Definition: mathlib.h:40
static config_t config
Definition: test_all.cpp:43
dMapTile_t * curTile
Definition: bsp.cpp:32
int texinfo
Definition: map.h:52
QGL_EXTERN GLuint count
Definition: r_gl.h:99
uint16_t planenum
Definition: map.h:53
struct portal_s * portals
Definition: bsp.h:58
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
struct portal_s * portal
Definition: map.h:51
winding_t * ReverseWinding(const winding_t *w)
Definition: polylib.cpp:193
static int superverts[MAX_SUPERVERTS]
Definition: faces.cpp:37
face_t * face[2]
Definition: map.h:119
static face_t * NewFaceFromFace(const face_t *f)
Definition: faces.cpp:121
static void SubdivideNodeFaces(node_t *node)
Definition: faces.cpp:662
#define MAX_SUPERVERTS
Definition: faces.cpp:36
static void FixFaceEdges(node_t *node, face_t *f)
Definition: faces.cpp:299
#define SURF_LIGHT
Definition: defines.h:254
#define PLANENUM_LEAF
Definition: defines.h:45
QGL_EXTERN GLint i
Definition: r_gl.h:113
int numpoints
Definition: map.h:56
QGL_EXTERN GLuint GLchar GLuint * len
Definition: r_gl.h:99
void FixTjuncs(node_t *headnode)
Definition: faces.cpp:370
vec3_t p[4]
Definition: polylib.h:32
int numnormals
Definition: typedefs.h:477
static int c_badstartverts
Definition: faces.cpp:34
vec_t VectorNormalize(vec3_t v)
Calculate unit vector for a given vec3_t.
Definition: mathlib.cpp:745
static const face_t * edgefaces[MAX_MAP_EDGES][2]
Definition: faces.cpp:40
int numvertexes
Definition: typedefs.h:480
#define Mem_Free(ptr)
Definition: mem.h:35
vec_t vec3_t[3]
Definition: ufotypes.h:39
struct face_s * merged
Definition: map.h:48
uint32_t VisibleContents(uint32_t contents)
Returns the single content bit of the strongest visible content present.
Definition: portals.cpp:64
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
#define MAX_WORLD_WIDTH
-MAX_WORLD_WIDTH up tp +MAX_WORLD_WIDTH
Definition: defines.h:288
static int c_facecollapse
Definition: faces.cpp:34
vec_t Q_rint(const vec_t in)
Round to nearest integer.
Definition: mathlib.cpp:156
#define Mem_AllocType(type)
Definition: mem.h:39
static int numsuperverts
Definition: faces.cpp:38
Definition: map.h:110
face_t * faces
Definition: bsp.h:52
uint32_t surfaceFlags
Definition: map.h:66
#define Q_streq(a, b)
Definition: shared.h:136
Definition: bsp.h:42
dBspVertex_t vertexes[MAX_MAP_VERTS]
Definition: typedefs.h:481
static int c_totalverts
Definition: faces.cpp:34
const char * ValueForKey(const entity_t *ent, const char *key)
Definition: bspfile.cpp:558
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
#define SURF_WARP
Definition: defines.h:256
static int c_faceoverflows
Definition: faces.cpp:34
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
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
#define POINT_EPSILON
Definition: faces.cpp:31
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 int c_degenerate
Definition: faces.cpp:34
static void MergeNodeFaces(node_t *node)
Definition: faces.cpp:565
#define VectorSubtract(a, b, dest)
Definition: vector.h:45
void FreeWinding(winding_t *w)
Definition: polylib.cpp:46
char texture[32]
Definition: typedefs.h:392
#define MAXEDGES
Definition: defines.h:49
int numpoints
Definition: polylib.h:31
#define ON_EPSILON
Definition: defines.h:374