2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
27 some faces will be removed before saving, but still form nodes:
\r
29 the insides of sky volumes
\r
30 meeting planes of different water current volumes
\r
34 // undefine for dumb linear searches
\r
37 #define INTEGRAL_EPSILON 0.01
\r
38 #define POINT_EPSILON 0.5
\r
39 #define OFF_EPSILON 0.5
\r
48 int c_faceoverflows;
\r
50 int c_badstartverts;
\r
52 #define MAX_SUPERVERTS 512
\r
53 int superverts[MAX_SUPERVERTS];
\r
56 face_t *edgefaces[MAX_MAP_EDGES][2];
\r
57 int firstmodeledge = 1;
\r
67 int edge_verts[MAX_MAP_VERTS];
\r
70 float subdivide_size = 240;
\r
73 face_t *NewFaceFromFace (face_t *f);
\r
75 //===========================================================================
\r
77 typedef struct hashvert_s
\r
79 struct hashvert_s *next;
\r
84 #define HASH_SIZE 64
\r
87 int vertexchain[MAX_MAP_VERTS]; // the next vertex in a hash chain
\r
88 int hashverts[HASH_SIZE*HASH_SIZE]; // a vertex number, or 0 for no verts
\r
90 face_t *edgefaces[MAX_MAP_EDGES][2];
\r
92 //============================================================================
\r
95 unsigned HashVec (vec3_t vec)
\r
99 x = (4096 + (int)(vec[0]+0.5)) >> 7;
\r
100 y = (4096 + (int)(vec[1]+0.5)) >> 7;
\r
102 if ( x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE )
\r
103 Error ("HashVec: point outside valid range");
\r
105 return y*HASH_SIZE + x;
\r
116 int GetVertexnum (vec3_t in)
\r
126 for (i=0 ; i<3 ; i++)
\r
128 if ( fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON)
\r
129 vert[i] = Q_rint(in[i]);
\r
134 h = HashVec (vert);
\r
136 for (vnum=hashverts[h] ; vnum ; vnum=vertexchain[vnum])
\r
138 p = dvertexes[vnum].point;
\r
139 if ( fabs(p[0]-vert[0])<POINT_EPSILON
\r
140 && fabs(p[1]-vert[1])<POINT_EPSILON
\r
141 && fabs(p[2]-vert[2])<POINT_EPSILON )
\r
146 if (numvertexes == MAX_MAP_VERTS)
\r
147 Error ("numvertexes == MAX_MAP_VERTS");
\r
149 dvertexes[numvertexes].point[0] = vert[0];
\r
150 dvertexes[numvertexes].point[1] = vert[1];
\r
151 dvertexes[numvertexes].point[2] = vert[2];
\r
153 vertexchain[numvertexes] = hashverts[h];
\r
154 hashverts[h] = numvertexes;
\r
160 return numvertexes-1;
\r
170 int GetVertexnum (vec3_t v)
\r
178 // make really close values exactly integral
\r
179 for (i=0 ; i<3 ; i++)
\r
181 if ( fabs(v[i] - (int)(v[i]+0.5)) < INTEGRAL_EPSILON )
\r
182 v[i] = (int)(v[i]+0.5);
\r
183 if (v[i] < -4096 || v[i] > 4096)
\r
184 Error ("GetVertexnum: outside +/- 4096");
\r
187 // search for an existing vertex match
\r
188 for (i=0, dv=dvertexes ; i<numvertexes ; i++, dv++)
\r
190 for (j=0 ; j<3 ; j++)
\r
192 d = v[j] - dv->point[j];
\r
193 if ( d > POINT_EPSILON || d < -POINT_EPSILON)
\r
197 return i; // a match
\r
201 if (numvertexes == MAX_MAP_VERTS)
\r
202 Error ("MAX_MAP_VERTS");
\r
203 VectorCopy (v, dv->point);
\r
207 return numvertexes-1;
\r
216 The faces vertexes have beeb added to the superverts[] array,
\r
217 and there may be more there than can be held in a face (MAXEDGES).
\r
219 If less, the faces vertexnums[] will be filled in, otherwise
\r
220 face will reference a tree of split[] faces until all of the
\r
221 vertexnums can be added.
\r
223 superverts[base] will become face->vertexnums[0], and the others
\r
224 will be circularly filled in.
\r
227 void FaceFromSuperverts (node_t *node, face_t *f, int base)
\r
233 remaining = numsuperverts;
\r
234 while (remaining > MAXEDGES)
\r
235 { // must split into two faces, because of vertex overload
\r
238 newf = f->split[0] = NewFaceFromFace (f);
\r
239 newf = f->split[0];
\r
240 newf->next = node->faces;
\r
241 node->faces = newf;
\r
243 newf->numpoints = MAXEDGES;
\r
244 for (i=0 ; i<MAXEDGES ; i++)
\r
245 newf->vertexnums[i] = superverts[(i+base)%numsuperverts];
\r
247 f->split[1] = NewFaceFromFace (f);
\r
249 f->next = node->faces;
\r
252 remaining -= (MAXEDGES-2);
\r
253 base = (base+MAXEDGES-1)%numsuperverts;
\r
256 // copy the vertexes back to the face
\r
257 f->numpoints = remaining;
\r
258 for (i=0 ; i<remaining ; i++)
\r
259 f->vertexnums[i] = superverts[(i+base)%numsuperverts];
\r
268 void EmitFaceVertexes (node_t *node, face_t *f)
\r
273 if (f->merged || f->split[0] || f->split[1])
\r
277 for (i=0 ; i<w->numpoints ; i++)
\r
280 { // make every point unique
\r
281 if (numvertexes == MAX_MAP_VERTS)
\r
282 Error ("MAX_MAP_VERTS");
\r
283 superverts[i] = numvertexes;
\r
284 VectorCopy (w->p[i], dvertexes[numvertexes].point);
\r
290 superverts[i] = GetVertexnum (w->p[i]);
\r
292 numsuperverts = w->numpoints;
\r
294 // this may fragment the face if > MAXEDGES
\r
295 FaceFromSuperverts (node, f, 0);
\r
303 void EmitVertexes_r (node_t *node)
\r
308 if (node->planenum == PLANENUM_LEAF)
\r
311 for (f=node->faces ; f ; f=f->next)
\r
313 EmitFaceVertexes (node, f);
\r
316 for (i=0 ; i<2 ; i++)
\r
317 EmitVertexes_r (node->children[i]);
\r
326 Uses the hash tables to cut down to a small number
\r
329 void FindEdgeVerts (vec3_t v1, vec3_t v2)
\r
331 int x1, x2, y1, y2, t;
\r
338 num_edge_verts = numvertexes-1;
\r
339 for (i=0 ; i<numvertexes-1 ; i++)
\r
340 edge_verts[i] = i+1;
\r
344 x1 = (4096 + (int)(v1[0]+0.5)) >> 7;
\r
345 y1 = (4096 + (int)(v1[1]+0.5)) >> 7;
\r
346 x2 = (4096 + (int)(v2[0]+0.5)) >> 7;
\r
347 y2 = (4096 + (int)(v2[1]+0.5)) >> 7;
\r
368 if (x2 >= HASH_SIZE)
\r
372 if (y2 >= HASH_SIZE)
\r
375 num_edge_verts = 0;
\r
376 for (x=x1 ; x <= x2 ; x++)
\r
378 for (y=y1 ; y <= y2 ; y++)
\r
380 for (vnum=hashverts[y*HASH_SIZE+x] ; vnum ; vnum=vertexchain[vnum])
\r
382 edge_verts[num_edge_verts++] = vnum;
\r
393 Forced a dumb check of everything
\r
396 void FindEdgeVerts (vec3_t v1, vec3_t v2)
\r
400 num_edge_verts = numvertexes-1;
\r
401 for (i=0 ; i<num_edge_verts ; i++)
\r
402 edge_verts[i] = i+1;
\r
410 Can be recursively reentered
\r
413 void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
\r
426 return; // degenerate edge
\r
429 for (k=startvert ; k<num_edge_verts ; k++)
\r
432 if (j==p1 || j == p2)
\r
435 VectorCopy (dvertexes[j].point, p);
\r
437 VectorSubtract (p, edge_start, delta);
\r
438 dist = DotProduct (delta, edge_dir);
\r
439 if (dist <=start || dist >= end)
\r
440 continue; // off an end
\r
441 VectorMA (edge_start, dist, edge_dir, exact);
\r
442 VectorSubtract (p, exact, off);
\r
443 error = VectorLength (off);
\r
445 if (fabs(error) > OFF_EPSILON)
\r
446 continue; // not on the edge
\r
450 TestEdge (start, dist, p1, j, k+1);
\r
451 TestEdge (dist, end, j, p2, k+1);
\r
455 // the edge p1 to p2 is now free of tjunctions
\r
456 if (numsuperverts >= MAX_SUPERVERTS)
\r
457 Error ("MAX_SUPERVERTS");
\r
458 superverts[numsuperverts] = p1;
\r
468 void FixFaceEdges (node_t *node, face_t *f)
\r
474 int count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];
\r
477 if (f->merged || f->split[0] || f->split[1])
\r
482 for (i=0 ; i<f->numpoints ; i++)
\r
484 p1 = f->vertexnums[i];
\r
485 p2 = f->vertexnums[(i+1)%f->numpoints];
\r
487 VectorCopy (dvertexes[p1].point, edge_start);
\r
488 VectorCopy (dvertexes[p2].point, e2);
\r
490 FindEdgeVerts (edge_start, e2);
\r
492 VectorSubtract (e2, edge_start, edge_dir);
\r
493 len = VectorNormalize (edge_dir, edge_dir);
\r
495 start[i] = numsuperverts;
\r
496 TestEdge (0, len, p1, p2, 0);
\r
498 count[i] = numsuperverts - start[i];
\r
501 if (numsuperverts < 3)
\r
502 { // entire face collapsed
\r
508 // we want to pick a vertex that doesn't have tjunctions
\r
509 // on either side, which can cause artifacts on trifans,
\r
510 // especially underwater
\r
511 for (i=0 ; i<f->numpoints ; i++)
\r
513 if (count[i] == 1 && count[(i+f->numpoints-1)%f->numpoints] == 1)
\r
516 if (i == f->numpoints)
\r
518 f->badstartvert = true;
\r
523 { // rotate the vertex order
\r
527 // this may fragment the face if > MAXEDGES
\r
528 FaceFromSuperverts (node, f, base);
\r
536 void FixEdges_r (node_t *node)
\r
541 if (node->planenum == PLANENUM_LEAF)
\r
544 for (f=node->faces ; f ; f=f->next)
\r
545 FixFaceEdges (node, f);
\r
547 for (i=0 ; i<2 ; i++)
\r
548 FixEdges_r (node->children[i]);
\r
557 void FixTjuncs (node_t *headnode)
\r
559 // snap and merge all vertexes
\r
560 Sys_FPrintf( SYS_VRB, "---- snap verts ----\n");
\r
561 memset (hashverts, 0, sizeof(hashverts));
\r
564 c_faceoverflows = 0;
\r
565 EmitVertexes_r (headnode);
\r
566 Sys_FPrintf( SYS_VRB, "%i unique from %i\n", c_uniqueverts, c_totalverts);
\r
568 // break edges on tjunctions
\r
569 Sys_FPrintf( SYS_VRB, "---- tjunc ----\n");
\r
572 c_facecollapse = 0;
\r
575 FixEdges_r (headnode);
\r
576 Sys_FPrintf( SYS_VRB, "%5i edges degenerated\n", c_degenerate);
\r
577 Sys_FPrintf( SYS_VRB, "%5i faces degenerated\n", c_facecollapse);
\r
578 Sys_FPrintf( SYS_VRB, "%5i edges added by tjunctions\n", c_tjunctions);
\r
579 Sys_FPrintf( SYS_VRB, "%5i faces added by tjunctions\n", c_faceoverflows);
\r
580 Sys_FPrintf( SYS_VRB, "%5i bad start verts\n", c_badstartverts);
\r
584 //========================================================
\r
588 face_t *AllocFace (void)
\r
592 f = malloc(sizeof(*f));
\r
593 memset (f, 0, sizeof(*f));
\r
599 face_t *NewFaceFromFace (face_t *f)
\r
603 newf = AllocFace ();
\r
605 newf->merged = NULL;
\r
606 newf->split[0] = newf->split[1] = NULL;
\r
611 void FreeFace (face_t *f)
\r
614 FreeWinding (f->w);
\r
619 //========================================================
\r
625 Called by writebsp.
\r
626 Don't allow four way edges
\r
629 int GetEdge2 (int v1, int v2, face_t *f)
\r
638 for (i=firstmodeledge ; i < numedges ; i++)
\r
641 if (v1 == edge->v[1] && v2 == edge->v[0]
\r
642 && edgefaces[i][0]->contents == f->contents)
\r
644 if (edgefaces[i][1])
\r
645 // Sys_Printf ("WARNING: multiple backward edge\n");
\r
647 edgefaces[i][1] = f;
\r
651 if (v1 == edge->v[0] && v2 == edge->v[1])
\r
653 Sys_Printf ("WARNING: multiple forward edge\n");
\r
661 if (numedges >= MAX_MAP_EDGES)
\r
662 Error ("numedges == MAX_MAP_EDGES");
\r
663 edge = &dedges[numedges];
\r
667 edgefaces[numedges-1][0] = f;
\r
673 ===========================================================================
\r
677 ===========================================================================
\r
680 #define CONTINUOUS_EPSILON 0.001
\r
686 If two polygons share a common edge and the edges that meet at the
\r
687 common points are both inside the other polygons, merge them
\r
689 Returns NULL if the faces couldn't be merged, or the new face.
\r
690 The originals will NOT be freed.
\r
693 winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal)
\r
695 vec_t *p1, *p2, *p3, *p4, *back;
\r
698 vec3_t normal, delta;
\r
700 qboolean keep1, keep2;
\r
704 // find a common edge
\r
706 p1 = p2 = NULL; // stop compiler warning
\r
709 for (i=0 ; i<f1->numpoints ; i++)
\r
712 p2 = f1->p[(i+1)%f1->numpoints];
\r
713 for (j=0 ; j<f2->numpoints ; j++)
\r
716 p4 = f2->p[(j+1)%f2->numpoints];
\r
717 for (k=0 ; k<3 ; k++)
\r
719 if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON)
\r
721 if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON)
\r
727 if (j < f2->numpoints)
\r
731 if (i == f1->numpoints)
\r
732 return NULL; // no matching edges
\r
735 // check slope of connected lines
\r
736 // if the slopes are colinear, the point can be removed
\r
738 back = f1->p[(i+f1->numpoints-1)%f1->numpoints];
\r
739 VectorSubtract (p1, back, delta);
\r
740 CrossProduct (planenormal, delta, normal);
\r
741 VectorNormalize (normal, normal);
\r
743 back = f2->p[(j+2)%f2->numpoints];
\r
744 VectorSubtract (back, p1, delta);
\r
745 dot = DotProduct (delta, normal);
\r
746 if (dot > CONTINUOUS_EPSILON)
\r
747 return NULL; // not a convex polygon
\r
748 keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
\r
750 back = f1->p[(i+2)%f1->numpoints];
\r
751 VectorSubtract (back, p2, delta);
\r
752 CrossProduct (planenormal, delta, normal);
\r
753 VectorNormalize (normal, normal);
\r
755 back = f2->p[(j+f2->numpoints-1)%f2->numpoints];
\r
756 VectorSubtract (back, p2, delta);
\r
757 dot = DotProduct (delta, normal);
\r
758 if (dot > CONTINUOUS_EPSILON)
\r
759 return NULL; // not a convex polygon
\r
760 keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
\r
763 // build the new polygon
\r
765 newf = AllocWinding (f1->numpoints + f2->numpoints);
\r
767 // copy first polygon
\r
768 for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
\r
770 if (k==(i+1)%f1->numpoints && !keep2)
\r
773 VectorCopy (f1->p[k], newf->p[newf->numpoints]);
\r
777 // copy second polygon
\r
778 for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
\r
780 if (l==(j+1)%f2->numpoints && !keep1)
\r
782 VectorCopy (f2->p[l], newf->p[newf->numpoints]);
\r
793 If two polygons share a common edge and the edges that meet at the
\r
794 common points are both inside the other polygons, merge them
\r
796 Returns NULL if the faces couldn't be merged, or the new face.
\r
797 The originals will NOT be freed.
\r
800 face_t *TryMerge (face_t *f1, face_t *f2, vec3_t planenormal)
\r
805 if (!f1->w || !f2->w)
\r
807 if (f1->texinfo != f2->texinfo)
\r
809 if (f1->planenum != f2->planenum) // on front and back sides
\r
811 if (f1->contents != f2->contents)
\r
815 nw = TryMergeWinding (f1->w, f2->w, planenormal);
\r
820 newf = NewFaceFromFace (f1);
\r
834 void MergeNodeFaces (node_t *node)
\r
836 face_t *f1, *f2, *end;
\r
840 plane = &mapplanes[node->planenum];
\r
843 for (f1 = node->faces ; f1 ; f1 = f1->next)
\r
845 if (f1->merged || f1->split[0] || f1->split[1])
\r
847 for (f2 = node->faces ; f2 != f1 ; f2=f2->next)
\r
849 if (f2->merged || f2->split[0] || f2->split[1])
\r
851 merged = TryMerge (f1, f2, plane->normal);
\r
855 // add merged to the end of the node face list
\r
856 // so it will be checked against all the faces again
\r
857 for (end = node->faces ; end->next ; end = end->next)
\r
859 merged->next = NULL;
\r
860 end->next = merged;
\r
866 //=====================================================================
\r
872 Chop up faces that are larger than we want in the surface cache
\r
875 void SubdivideFace (node_t *node, face_t *f)
\r
883 winding_t *w, *frontw, *backw;
\r
888 // special (non-surface cached) faces don't need subdivision
\r
889 tex = &texinfo[f->texinfo];
\r
891 if ( tex->flags & (SURF_WARP|SURF_SKY) )
\r
896 for (axis = 0 ; axis < 2 ; axis++)
\r
903 VectorCopy (tex->vecs[axis], temp);
\r
905 for (i=0 ; i<w->numpoints ; i++)
\r
907 v = DotProduct (w->p[i], temp);
\r
914 if (maxs - mins <= 0)
\r
915 Error ("zero extents");
\r
918 { // allow double high walls
\r
919 if (maxs - mins <= subdivide_size/* *2 */)
\r
922 else if (maxs - mins <= subdivide_size)
\r
928 v = VectorNormalize (temp, temp);
\r
930 dist = (mins + subdivide_size - 16)/v;
\r
932 ClipWindingEpsilon (w, temp, dist, ON_EPSILON, &frontw, &backw);
\r
933 if (!frontw || !backw)
\r
934 Error ("SubdivideFace: didn't split the polygon");
\r
936 f->split[0] = NewFaceFromFace (f);
\r
937 f->split[0]->w = frontw;
\r
938 f->split[0]->next = node->faces;
\r
939 node->faces = f->split[0];
\r
941 f->split[1] = NewFaceFromFace (f);
\r
942 f->split[1]->w = backw;
\r
943 f->split[1]->next = node->faces;
\r
944 node->faces = f->split[1];
\r
946 SubdivideFace (node, f->split[0]);
\r
947 SubdivideFace (node, f->split[1]);
\r
953 void SubdivideNodeFaces (node_t *node)
\r
957 for (f = node->faces ; f ; f=f->next)
\r
959 SubdivideFace (node, f);
\r
963 //===========================================================================
\r
974 face_t *FaceFromPortal (portal_t *p, int pside)
\r
981 return NULL; // portal does not bridge different visible contents
\r
985 f->texinfo = side->texinfo;
\r
986 f->planenum = (side->planenum & ~1) | pside;
\r
989 if ( (p->nodes[pside]->contents & CONTENTS_WINDOW)
\r
990 && VisibleContents(p->nodes[!pside]->contents^p->nodes[pside]->contents) == CONTENTS_WINDOW )
\r
991 return NULL; // don't show insides of windows
\r
995 f->w = ReverseWinding(p->winding);
\r
996 f->contents = p->nodes[1]->contents;
\r
1000 f->w = CopyWinding(p->winding);
\r
1001 f->contents = p->nodes[0]->contents;
\r
1011 If a portal will make a visible face,
\r
1012 mark the side that originally created it
\r
1014 solid / empty : solid
\r
1015 solid / water : solid
\r
1016 water / empty : water
\r
1017 water / water : none
\r
1020 void MakeFaces_r (node_t *node)
\r
1025 // recurse down to leafs
\r
1026 if (node->planenum != PLANENUM_LEAF)
\r
1028 MakeFaces_r (node->children[0]);
\r
1029 MakeFaces_r (node->children[1]);
\r
1031 // merge together all visible faces on the node
\r
1033 MergeNodeFaces (node);
\r
1035 SubdivideNodeFaces (node);
\r
1040 // solid leafs never have visible faces
\r
1041 if (node->contents & CONTENTS_SOLID)
\r
1044 // see which portals are valid
\r
1045 for (p=node->portals ; p ; p = p->next[s])
\r
1047 s = (p->nodes[1] == node);
\r
1049 p->face[s] = FaceFromPortal (p, s);
\r
1053 p->face[s]->next = p->onnode->faces;
\r
1054 p->onnode->faces = p->face[s];
\r
1064 void MakeFaces (node_t *node)
\r
1066 Sys_FPrintf( SYS_VRB, "--- MakeFaces ---\n");
\r
1071 MakeFaces_r (node);
\r
1073 Sys_FPrintf( SYS_VRB, "%5i makefaces\n", c_nodefaces);
\r
1074 Sys_FPrintf( SYS_VRB, "%5i merged\n", c_merge);
\r
1075 Sys_FPrintf( SYS_VRB, "%5i subdivided\n", c_subdivide);
\r