faces.c

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 1997-2001 Id Software, Inc.
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019 See the GNU General Public License for more details.
00020 
00021 You should have received a copy of the GNU General Public License
00022 along with this program; if not, write to the Free Software
00023 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00024 
00025 */
00026 
00027 
00028 #include "bsp.h"
00029 
00030 #define INTEGRAL_EPSILON    0.01
00031 #define POINT_EPSILON       0.5
00032 #define OFF_EPSILON         0.5
00033 
00034 static int c_merge, c_subdivide, c_totalverts, c_uniqueverts, c_degenerate, c_tjunctions, c_faceoverflows, c_facecollapse, c_badstartverts, c_faces;
00035 
00036 #define MAX_SUPERVERTS  512
00037 static int superverts[MAX_SUPERVERTS];
00038 static int numsuperverts;
00039 
00040 static const face_t *edgefaces[MAX_MAP_EDGES][2];
00041 int firstmodeledge = 1;
00042 
00043 static vec3_t edge_dir;
00044 static vec3_t edge_start;
00045 
00046 static int num_edge_verts;
00047 static int edge_verts[MAX_MAP_VERTS];
00048 
00049 #define HASH_SIZE   64
00050 
00051 static int vertexchain[MAX_MAP_VERTS];      /* the next vertex in a hash chain */
00052 static int hashverts[HASH_SIZE * HASH_SIZE];    /* a vertex number, or 0 for no verts */
00053 
00057 static unsigned HashVec (const vec3_t vec)
00058 {
00059     const int x = (4096 + (int)(vec[0] + 0.5)) >> 7;
00060     const int y = (4096 + (int)(vec[1] + 0.5)) >> 7;
00061 
00062     if (x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE)
00063         Sys_Error("HashVec: point outside valid range");
00064 
00065     return y * HASH_SIZE + x;
00066 }
00067 
00072 static int GetVertexnum (const vec3_t in)
00073 {
00074     int h, i, vnum;
00075     vec3_t vert;
00076 
00077     c_totalverts++;
00078 
00079     for (i = 0; i < 3; i++) {
00080         if (fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON)
00081             vert[i] = Q_rint(in[i]);
00082         else
00083             vert[i] = in[i];
00084     }
00085 
00086     h = HashVec(vert);
00087 
00088     for (vnum = hashverts[h]; vnum; vnum = vertexchain[vnum]) {
00089         const float *p = curTile->vertexes[vnum].point;
00090         if (fabs(p[0] - vert[0]) < POINT_EPSILON
00091          && fabs(p[1] - vert[1]) < POINT_EPSILON
00092          && fabs(p[2] - vert[2]) < POINT_EPSILON)
00093             return vnum;
00094     }
00095 
00096     /* emit a vertex */
00097     if (curTile->numvertexes == MAX_MAP_VERTS)
00098         Sys_Error("numvertexes == MAX_MAP_VERTS");
00099 
00100     curTile->vertexes[curTile->numvertexes].point[0] = vert[0];
00101     curTile->vertexes[curTile->numvertexes].point[1] = vert[1];
00102     curTile->vertexes[curTile->numvertexes].point[2] = vert[2];
00103 
00104     vertexchain[curTile->numvertexes] = hashverts[h];
00105     hashverts[h] = curTile->numvertexes;
00106 
00107     c_uniqueverts++;
00108 
00109     curTile->numvertexes++;
00110     curTile->numnormals++;
00111 
00112     return curTile->numvertexes - 1;
00113 }
00114 
00115 static face_t *AllocFace (void)
00116 {
00117     c_faces++;
00118 
00119     return Mem_Alloc(sizeof(face_t));
00120 }
00121 
00122 static face_t *NewFaceFromFace (const face_t *f)
00123 {
00124     face_t  *newf;
00125 
00126     newf = AllocFace();
00127     *newf = *f;
00128     newf->merged = NULL;
00129     newf->split[0] = newf->split[1] = NULL;
00130     newf->w = NULL;
00131     return newf;
00132 }
00133 
00134 void FreeFace (face_t *f)
00135 {
00136     if (f->w)
00137         FreeWinding(f->w);
00138     Mem_Free(f);
00139     c_faces--;
00140 }
00141 
00153 static void FaceFromSuperverts (node_t *node, face_t *f, int base)
00154 {
00155     face_t *newf;
00156     int i, remaining;
00157 
00158     remaining = numsuperverts;
00159     /* must split into two faces, because of vertex overload */
00160     while (remaining > MAXEDGES) {
00161         c_faceoverflows++;
00162 
00163         newf = f->split[0] = NewFaceFromFace(f);
00164         newf = f->split[0];
00165         newf->next = node->faces;
00166         node->faces = newf;
00167 
00168         newf->numpoints = MAXEDGES;
00169         for (i = 0; i < MAXEDGES; i++)
00170             newf->vertexnums[i] = superverts[(i + base) % numsuperverts];
00171 
00172         f->split[1] = NewFaceFromFace(f);
00173         f = f->split[1];
00174         f->next = node->faces;
00175         node->faces = f;
00176 
00177         remaining -= (MAXEDGES - 2);
00178         base = (base + MAXEDGES - 1) % numsuperverts;
00179     }
00180 
00181     /* copy the vertexes back to the face */
00182     f->numpoints = remaining;
00183     for (i = 0; i < remaining; i++)
00184         f->vertexnums[i] = superverts[(i + base) % numsuperverts];
00185 }
00186 
00187 static void EmitFaceVertexes (node_t *node, face_t *f)
00188 {
00189     winding_t *w;
00190     int i;
00191 
00192     if (f->merged || f->split[0] || f->split[1])
00193         return;
00194 
00195     w = f->w;
00196     for (i = 0; i < w->numpoints; i++) {
00197         /* make every point unique */
00198         if (config.noweld) {
00199             if (curTile->numvertexes == MAX_MAP_VERTS)
00200                 Sys_Error("MAX_MAP_VERTS (%i)", curTile->numvertexes);
00201             superverts[i] = curTile->numvertexes;
00202             VectorCopy(w->p[i], curTile->vertexes[curTile->numvertexes].point);
00203             curTile->numvertexes++;
00204             curTile->numnormals++;
00205             c_uniqueverts++;
00206             c_totalverts++;
00207         } else
00208             superverts[i] = GetVertexnum(w->p[i]);
00209     }
00210     numsuperverts = w->numpoints;
00211 
00212     /* this may fragment the face if > MAXEDGES */
00213     FaceFromSuperverts(node, f, 0);
00214 }
00215 
00216 static void EmitVertexes_r (node_t *node)
00217 {
00218     int i;
00219     face_t *f;
00220 
00221     if (node->planenum == PLANENUM_LEAF)
00222         return;
00223 
00224     for (f = node->faces; f; f = f->next)
00225         EmitFaceVertexes(node, f);
00226 
00227     for (i = 0; i < 2; i++)
00228         EmitVertexes_r(node->children[i]);
00229 }
00230 
00231 
00235 static void FindEdgeVerts (const vec3_t v1, const vec3_t v2)
00236 {
00237     int x1, x2, y1, y2, t;
00238     int x, y, vnum;
00239 
00240     x1 = (MAX_WORLD_WIDTH + (int)(v1[0] + 0.5)) >> 7;
00241     y1 = (MAX_WORLD_WIDTH + (int)(v1[1] + 0.5)) >> 7;
00242     x2 = (MAX_WORLD_WIDTH + (int)(v2[0] + 0.5)) >> 7;
00243     y2 = (MAX_WORLD_WIDTH + (int)(v2[1] + 0.5)) >> 7;
00244 
00245     if (x1 > x2) {
00246         t = x1;
00247         x1 = x2;
00248         x2 = t;
00249     }
00250     if (y1 > y2) {
00251         t = y1;
00252         y1 = y2;
00253         y2 = t;
00254     }
00255     num_edge_verts = 0;
00256     for (x = x1; x <= x2; x++)
00257         for (y = y1; y <= y2; y++)
00258             for (vnum = hashverts[y * HASH_SIZE + x]; vnum; vnum = vertexchain[vnum])
00259                 edge_verts[num_edge_verts++] = vnum;
00260 }
00261 
00265 static void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
00266 {
00267     int k;
00268     vec_t dist, error;
00269     vec3_t  delta, exact, off, p;
00270 
00271     if (p1 == p2) {
00272         c_degenerate++;
00273         return;     /* degenerate edge */
00274     }
00275 
00276     for (k = startvert; k < num_edge_verts; k++) {
00277         const int j = edge_verts[k];
00278         if (j == p1 || j == p2)
00279             continue;
00280 
00281         VectorCopy(curTile->vertexes[j].point, p);
00282 
00283         VectorSubtract(p, edge_start, delta);
00284         dist = DotProduct(delta, edge_dir);
00285         if (dist <= start || dist >= end)
00286             continue;       /* off an end */
00287         VectorMA(edge_start, dist, edge_dir, exact);
00288         VectorSubtract(p, exact, off);
00289         error = VectorLength(off);
00290 
00291         if (fabs(error) > OFF_EPSILON)
00292             continue;       /* not on the edge */
00293 
00294         /* break the edge */
00295         c_tjunctions++;
00296         TestEdge(start, dist, p1, j, k + 1);
00297         TestEdge(dist, end, j, p2, k + 1);
00298         return;
00299     }
00300 
00301     /* the edge p1 to p2 is now free of tjunctions */
00302     if (numsuperverts >= MAX_SUPERVERTS)
00303         Sys_Error("MAX_SUPERVERTS (%i)", numsuperverts);
00304     superverts[numsuperverts] = p1;
00305     numsuperverts++;
00306 }
00307 
00308 static void FixFaceEdges (node_t *node, face_t *f)
00309 {
00310     int i, base;
00311     vec3_t e2;
00312     vec_t len;
00313     int count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];
00314 
00315     if (f->merged || f->split[0] || f->split[1])
00316         return;
00317 
00318     numsuperverts = 0;
00319 
00320     for (i = 0; i < f->numpoints; i++) {
00321         const int p1 = f->vertexnums[i];
00322         const int p2 = f->vertexnums[(i + 1) % f->numpoints];
00323 
00324         VectorCopy(curTile->vertexes[p1].point, edge_start);
00325         VectorCopy(curTile->vertexes[p2].point, e2);
00326 
00327         FindEdgeVerts(edge_start, e2);
00328 
00329         VectorSubtract(e2, edge_start, edge_dir);
00330         len = VectorNormalize(edge_dir);
00331 
00332         start[i] = numsuperverts;
00333         TestEdge(0, len, p1, p2, 0);
00334 
00335         count[i] = numsuperverts - start[i];
00336     }
00337 
00338     /* entire face collapsed */
00339     if (numsuperverts < 3) {
00340         f->numpoints = 0;
00341         c_facecollapse++;
00342         return;
00343     }
00344 
00345     /* we want to pick a vertex that doesn't have tjunctions
00346      * on either side, which can cause artifacts on trifans,
00347      * especially underwater */
00348     for (i = 0; i < f->numpoints; i++) {
00349         if (count[i] == 1 && count[(i + f->numpoints - 1) % f->numpoints] == 1)
00350             break;
00351     }
00352     if (i == f->numpoints) {
00353         c_badstartverts++;
00354         base = 0;
00355     } else {
00356         /* rotate the vertex order */
00357         base = start[i];
00358     }
00359 
00360     /* this may fragment the face if > MAXEDGES */
00361     FaceFromSuperverts(node, f, base);
00362 }
00363 
00364 static void FixEdges_r (node_t *node)
00365 {
00366     int i;
00367     face_t *f;
00368 
00369     if (node->planenum == PLANENUM_LEAF)
00370         return;
00371 
00372     for (f = node->faces; f; f = f->next)
00373         FixFaceEdges(node, f);
00374 
00375     for (i = 0; i < 2; i++)
00376         FixEdges_r(node->children[i]);
00377 }
00378 
00383 void FixTjuncs (node_t *headnode)
00384 {
00385     /* snap and merge all vertexes */
00386     Verb_Printf(VERB_EXTRA, "---- snap verts ----\n");
00387     memset(hashverts, 0, sizeof(hashverts));
00388     c_totalverts = 0;
00389     c_uniqueverts = 0;
00390     c_faceoverflows = 0;
00391     EmitVertexes_r(headnode);
00392     Verb_Printf(VERB_EXTRA, "%i unique from %i\n", c_uniqueverts, c_totalverts);
00393 
00394     /* break edges on tjunctions */
00395     Verb_Printf(VERB_EXTRA, "---- tjunc ----\n");
00396     c_degenerate = 0;
00397     c_facecollapse = 0;
00398     c_tjunctions = 0;
00399     if (!config.notjunc)
00400         FixEdges_r(headnode);
00401     Verb_Printf(VERB_EXTRA, "%5i edges degenerated\n", c_degenerate);
00402     Verb_Printf(VERB_EXTRA, "%5i faces degenerated\n", c_facecollapse);
00403     Verb_Printf(VERB_EXTRA, "%5i edges added by tjunctions\n", c_tjunctions);
00404     Verb_Printf(VERB_EXTRA, "%5i faces added by tjunctions\n", c_faceoverflows);
00405     Verb_Printf(VERB_EXTRA, "%5i bad start verts\n", c_badstartverts);
00406 }
00407 
00412 int GetEdge (int v1, int v2, const face_t *f)
00413 {
00414     dBspEdge_t *edge;
00415 
00416     if (!config.noshare) {
00417         int i;
00418         for (i = firstmodeledge; i < curTile->numedges; i++) {
00419             edge = &curTile->edges[i];
00420             if (v1 == edge->v[1] && v2 == edge->v[0]
00421                 && edgefaces[i][0]->contentFlags == f->contentFlags) {
00422                 if (edgefaces[i][1])
00423                     continue;
00424                 edgefaces[i][1] = f;
00425                 return -i;
00426             }
00427         }
00428     }
00429 
00430     /* emit an edge */
00431     if (curTile->numedges >= MAX_MAP_EDGES)
00432         Sys_Error("numedges >= MAX_MAP_EDGES (%i)", curTile->numedges);
00433     edge = &curTile->edges[curTile->numedges];
00434     edge->v[0] = v1;
00435     edge->v[1] = v2;
00436     edgefaces[curTile->numedges][0] = f;
00437     curTile->numedges++;
00438 
00439     return curTile->numedges - 1;
00440 }
00441 
00442 /*
00443 ===========================================================================
00444 FACE MERGING
00445 ===========================================================================
00446 */
00447 
00448 #define CONTINUOUS_EPSILON 0.001
00449 
00456 static winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, const vec3_t planenormal)
00457 {
00458     vec_t *p1, *p2, *back;
00459     winding_t *newf;
00460     int i, j, k, l;
00461     vec3_t normal, delta;
00462     vec_t dot;
00463     qboolean keep1, keep2;
00464 
00465     p1 = p2 = NULL;
00466     j = 0;
00467 
00468     /* find a common edge */
00469     for (i = 0; i < f1->numpoints; i++) {
00470         p1 = f1->p[i];
00471         p2 = f1->p[(i + 1) % f1->numpoints];
00472         for (j = 0; j < f2->numpoints; j++) {
00473             const vec_t *p3 = f2->p[j];
00474             const vec_t *p4 = f2->p[(j + 1) % f2->numpoints];
00475             for (k = 0; k < 3; k++) {
00476                 if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON)
00477                     break;
00478                 if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON)
00479                     break;
00480             }
00481             if (k == 3)
00482                 break;
00483         }
00484         if (j < f2->numpoints)
00485             break;
00486     }
00487 
00488     /* no matching edges */
00489     if (i == f1->numpoints)
00490         return NULL;
00491 
00492     /* check slope of connected lines */
00493     /* if the slopes are colinear, the point can be removed */
00494     back = f1->p[(i + f1->numpoints - 1) % f1->numpoints];
00495     VectorSubtract(p1, back, delta);
00496     CrossProduct(planenormal, delta, normal);
00497     VectorNormalize(normal);
00498 
00499     back = f2->p[(j + 2) % f2->numpoints];
00500     VectorSubtract(back, p1, delta);
00501     dot = DotProduct(delta, normal);
00502     /* not a convex polygon */
00503     if (dot > CONTINUOUS_EPSILON)
00504         return NULL;
00505     keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
00506 
00507     back = f1->p[(i + 2) % f1->numpoints];
00508     VectorSubtract(back, p2, delta);
00509     CrossProduct(planenormal, delta, normal);
00510     VectorNormalize(normal);
00511 
00512     back = f2->p[(j + f2->numpoints - 1) % f2->numpoints];
00513     VectorSubtract(back, p2, delta);
00514     dot = DotProduct(delta, normal);
00515     /* not a convex polygon */
00516     if (dot > CONTINUOUS_EPSILON)
00517         return NULL;
00518     keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
00519 
00520     /* build the new polygon */
00521     newf = AllocWinding(f1->numpoints + f2->numpoints);
00522 
00523     /* copy first polygon */
00524     for (k = (i + 1) % f1->numpoints; k != i; k = (k + 1) % f1->numpoints) {
00525         if (k == (i + 1) % f1->numpoints && !keep2)
00526             continue;
00527 
00528         VectorCopy(f1->p[k], newf->p[newf->numpoints]);
00529         newf->numpoints++;
00530     }
00531 
00532     /* copy second polygon */
00533     for (l = (j + 1) % f2->numpoints; l != j; l = (l + 1) % f2->numpoints) {
00534         if (l == (j + 1) % f2->numpoints && !keep1)
00535             continue;
00536         VectorCopy(f2->p[l], newf->p[newf->numpoints]);
00537         newf->numpoints++;
00538     }
00539 
00540     return newf;
00541 }
00542 
00550 static face_t *TryMerge (face_t *f1, face_t *f2, const vec3_t planenormal)
00551 {
00552     face_t *newf;
00553     winding_t *nw;
00554 
00555     if (!f1->w || !f2->w)
00556         return NULL;
00557     if (f1->texinfo != f2->texinfo)
00558         return NULL;
00559     if (f1->planenum != f2->planenum)   /* on front and back sides */
00560         return NULL;
00561     if (f1->contentFlags != f2->contentFlags)
00562         return NULL;
00563 
00564     nw = TryMergeWinding(f1->w, f2->w, planenormal);
00565     if (!nw)
00566         return NULL;
00567 
00568     c_merge++;
00569     newf = NewFaceFromFace(f1);
00570     newf->w = nw;
00571 
00572     f1->merged = newf;
00573     f2->merged = newf;
00574 
00575     return newf;
00576 }
00577 
00578 static void MergeNodeFaces (node_t *node)
00579 {
00580     face_t *f1, *f2, *end;
00581     face_t *merged;
00582     const plane_t *plane = &mapplanes[node->planenum];
00583 
00584     for (f1 = node->faces; f1; f1 = f1->next) {
00585         if (f1->merged || f1->split[0] || f1->split[1])
00586             continue;
00587         for (f2 = node->faces; f2 != f1; f2 = f2->next) {
00588             if (f2->merged || f2->split[0] || f2->split[1])
00589                 continue;
00590             merged = TryMerge(f1, f2, plane->normal);
00591             if (!merged)
00592                 continue;
00593 
00594             /* add merged to the end of the node face list
00595              * so it will be checked against all the faces again */
00596             for (end = node->faces; end->next; end = end->next);
00597 
00598             merged->next = NULL;
00599             end->next = merged;
00600             break;
00601         }
00602     }
00603 }
00604 
00605 /*===================================================================== */
00606 
00610 static void SubdivideFace (node_t *node, face_t *f)
00611 {
00612     int axis, i;
00613     const dBspTexinfo_t *tex;
00614     vec3_t temp;
00615     vec_t dist;
00616 
00617     if (f->merged)
00618         return;
00619 
00620     /* special (non-surface cached) faces don't need subdivision */
00621     tex = &curTile->texinfo[f->texinfo];
00622     if (tex->surfaceFlags & SURF_WARP)
00623         return;
00624 
00625     for (axis = 0; axis < 2; axis++) {
00626         while (1) {
00627             const winding_t *w = f->w;
00628             winding_t *frontw, *backw;
00629             float mins = 999999;
00630             float maxs = -999999;
00631             vec_t v;
00632 
00633             VectorCopy(tex->vecs[axis], temp);
00634             for (i = 0; i < w->numpoints; i++) {
00635                 v = DotProduct(w->p[i], temp);
00636                 if (v < mins)
00637                     mins = v;
00638                 if (v > maxs)
00639                     maxs = v;
00640             }
00641 
00642             /* no bsp subdivide for this winding? */
00643             if (maxs - mins <= config.subdivideSize)
00644                 break;
00645 
00646             /* split it */
00647             c_subdivide++;
00648 
00649             v = VectorNormalize(temp);
00650 
00651             dist = (mins + config.subdivideSize - 16) / v;
00652 
00653             ClipWindingEpsilon(w, temp, dist, ON_EPSILON, &frontw, &backw);
00654             if (!frontw || !backw)
00655                 Sys_Error("SubdivideFace: didn't split the polygon (texture: '%s')",
00656                     tex->texture);
00657 
00658             f->split[0] = NewFaceFromFace(f);
00659             f->split[0]->w = frontw;
00660             f->split[0]->next = node->faces;
00661             node->faces = f->split[0];
00662 
00663             f->split[1] = NewFaceFromFace(f);
00664             f->split[1]->w = backw;
00665             f->split[1]->next = node->faces;
00666             node->faces = f->split[1];
00667 
00668             SubdivideFace(node, f->split[0]);
00669             SubdivideFace(node, f->split[1]);
00670             return;
00671         }
00672     }
00673 }
00674 
00675 static void SubdivideNodeFaces (node_t *node)
00676 {
00677     face_t *f;
00678 
00679     for (f = node->faces; f; f = f->next)
00680         SubdivideFace(node, f);
00681 }
00682 
00683 static int c_nodefaces;
00684 
00685 static face_t *FaceFromPortal (portal_t *p, int pside)
00686 {
00687     face_t *f;
00688     side_t *side = p->side;
00689 
00690     /* portal does not bridge different visible contents */
00691     if (!side)
00692         return NULL;
00693 
00694     /* nodraw/caulk faces */
00695     if (side->surfaceFlags & SURF_NODRAW)
00696         return NULL;
00697 
00698     f = AllocFace();
00699 
00700     f->texinfo = side->texinfo;
00701     f->planenum = (side->planenum & ~1) | pside;
00702     f->portal = p;
00703 
00704     if ((p->nodes[pside]->contentFlags & CONTENTS_WINDOW)
00705      && VisibleContents(p->nodes[!pside]->contentFlags ^ p->nodes[pside]->contentFlags) == CONTENTS_WINDOW)
00706         return NULL;    /* don't show insides of windows */
00707 
00708     /* do back-clipping */
00709     if (!config.nobackclip && mapplanes[f->planenum].normal[2] < -0.9) {
00710         /* this face is not visible from birds view - optimize away
00711          * but only if it's not light emitting surface */
00712         const entity_t *e = &entities[side->brush->entitynum];
00713         if (strcmp(ValueForKey(e, "classname"), "func_rotating")) {
00714             if (!(curTile->texinfo[f->texinfo].surfaceFlags & SURF_LIGHT)) {
00715                 /* e.g. water surfaces are removed if we set the surfaceFlags
00716                  * to SURF_NODRAW for this side */
00717                 /*side->surfaceFlags |= SURF_NODRAW;*/
00718                 return NULL;
00719             }
00720         }
00721     }
00722 
00723     if (pside) {
00724         f->w = ReverseWinding(p->winding);
00725         f->contentFlags = p->nodes[1]->contentFlags;
00726     } else {
00727         f->w = CopyWinding(p->winding);
00728         f->contentFlags = p->nodes[0]->contentFlags;
00729     }
00730     return f;
00731 }
00732 
00733 
00741 static void MakeFaces_r (node_t *node)
00742 {
00743     portal_t *p;
00744 
00745     /* recurse down to leafs */
00746     if (node->planenum != PLANENUM_LEAF) {
00747         MakeFaces_r(node->children[0]);
00748         MakeFaces_r(node->children[1]);
00749 
00750         /* merge together all visible faces on the node */
00751         if (!config.nomerge)
00752             MergeNodeFaces(node);
00753         if (!config.nosubdiv)
00754             SubdivideNodeFaces(node);
00755 
00756         return;
00757     }
00758 
00759     /* solid leafs never have visible faces */
00760     if (node->contentFlags & CONTENTS_SOLID)
00761         return;
00762 
00763     /* see which portals are valid */
00764     for (p = node->portals; p;) {
00765         const int pside = (p->nodes[1] == node);
00766 
00767         p->face[pside] = FaceFromPortal(p, pside);
00768         if (p->face[pside]) {
00769             c_nodefaces++;
00770             p->face[pside]->next = p->onnode->faces;
00771             p->onnode->faces = p->face[pside];
00772         }
00773         p = p->next[pside];
00774     }
00775 }
00776 
00777 void MakeFaces (node_t *node)
00778 {
00779     Verb_Printf(VERB_EXTRA, "--- MakeFaces ---\n");
00780     c_merge = 0;
00781     c_subdivide = 0;
00782     c_nodefaces = 0;
00783 
00784     MakeFaces_r(node);
00785 
00786     Verb_Printf(VERB_EXTRA, "%5i makefaces\n", c_nodefaces);
00787     Verb_Printf(VERB_EXTRA, "%5i merged\n", c_merge);
00788     Verb_Printf(VERB_EXTRA, "%5i subdivided\n", c_subdivide);
00789 }

Generated by  doxygen 1.6.2