Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

faces.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // faces.c
00023 
00024 #include "qbsp.h"
00025 #include "l_mem.h"
00026 
00027 /*
00028 
00029   some faces will be removed before saving, but still form nodes:
00030 
00031   the insides of sky volumes
00032   meeting planes of different water current volumes
00033 
00034 */
00035 
00036 // undefine for dumb linear searches
00037 #define USE_HASHING
00038 
00039 #define INTEGRAL_EPSILON    0.01
00040 #define POINT_EPSILON       0.5
00041 #define OFF_EPSILON         0.5
00042 
00043 int c_merge;
00044 int c_subdivide;
00045 
00046 int c_totalverts;
00047 int c_uniqueverts;
00048 int c_degenerate;
00049 int c_tjunctions;
00050 int c_faceoverflows;
00051 int c_facecollapse;
00052 int c_badstartverts;
00053 
00054 #define MAX_SUPERVERTS  512
00055 int superverts[MAX_SUPERVERTS];
00056 int numsuperverts;
00057 
00058 face_t      *edgefaces[MAX_MAP_EDGES][2];
00059 int     firstmodeledge = 1;
00060 int     firstmodelface;
00061 
00062 int c_tryedges;
00063 
00064 vec3_t  edge_dir;
00065 vec3_t  edge_start;
00066 vec_t   edge_len;
00067 
00068 int     num_edge_verts;
00069 int     edge_verts[MAX_MAP_VERTS];
00070 
00071 face_t *NewFaceFromFace (face_t *f);
00072 
00073 //===========================================================================
00074 
00075 typedef struct hashvert_s
00076 {
00077     struct hashvert_s   *next;
00078     int     num;
00079 } hashvert_t;
00080 
00081 
00082 #define HASH_SIZE   64
00083 
00084 
00085 int vertexchain[MAX_MAP_VERTS];     // the next vertex in a hash chain
00086 int hashverts[HASH_SIZE*HASH_SIZE]; // a vertex number, or 0 for no verts
00087 
00088 face_t      *edgefaces[MAX_MAP_EDGES][2];
00089 
00090 //============================================================================
00091 
00092 
00093 unsigned HashVec (vec3_t vec)
00094 {
00095     int         x, y;
00096 
00097     x = (4096 + (int)(vec[0]+0.5)) >> 7;
00098     y = (4096 + (int)(vec[1]+0.5)) >> 7;
00099 
00100     if ( x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE )
00101         Error ("HashVec: point outside valid range");
00102     
00103     return y*HASH_SIZE + x;
00104 }
00105 
00106 #ifdef USE_HASHING
00107 /*
00108 =============
00109 GetVertex
00110 
00111 Uses hashing
00112 =============
00113 */
00114 int GetVertexnum (vec3_t in)
00115 {
00116     int         h;
00117     int         i;
00118     float       *p;
00119     vec3_t      vert;
00120     int         vnum;
00121 
00122     c_totalverts++;
00123 
00124     for (i=0 ; i<3 ; i++)
00125     {
00126         if ( fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON)
00127             vert[i] = Q_rint(in[i]);
00128         else
00129             vert[i] = in[i];
00130     }
00131     
00132     h = HashVec (vert);
00133     
00134     for (vnum=hashverts[h] ; vnum ; vnum=vertexchain[vnum])
00135     {
00136         p = dvertexes[vnum].point;
00137         if ( fabs(p[0]-vert[0])<POINT_EPSILON
00138         && fabs(p[1]-vert[1])<POINT_EPSILON
00139         && fabs(p[2]-vert[2])<POINT_EPSILON )
00140             return vnum;
00141     }
00142     
00143 // emit a vertex
00144     if (numvertexes == MAX_MAP_VERTS)
00145         Error ("numvertexes == MAX_MAP_VERTS");
00146 
00147     dvertexes[numvertexes].point[0] = vert[0];
00148     dvertexes[numvertexes].point[1] = vert[1];
00149     dvertexes[numvertexes].point[2] = vert[2];
00150 
00151     vertexchain[numvertexes] = hashverts[h];
00152     hashverts[h] = numvertexes;
00153 
00154     c_uniqueverts++;
00155 
00156     numvertexes++;
00157         
00158     return numvertexes-1;
00159 }
00160 #else
00161 /*
00162 ==================
00163 GetVertexnum
00164 
00165 Dumb linear search
00166 ==================
00167 */
00168 int GetVertexnum (vec3_t v)
00169 {
00170     int         i, j;
00171     dvertex_t   *dv;
00172     vec_t       d;
00173 
00174     c_totalverts++;
00175 
00176     // make really close values exactly integral
00177     for (i=0 ; i<3 ; i++)
00178     {
00179         if ( fabs(v[i] - (int)(v[i]+0.5)) < INTEGRAL_EPSILON )
00180             v[i] = (int)(v[i]+0.5);
00181         if (v[i] < -4096 || v[i] > 4096)
00182             Error ("GetVertexnum: outside +/- 4096");
00183     }
00184 
00185     // search for an existing vertex match
00186     for (i=0, dv=dvertexes ; i<numvertexes ; i++, dv++)
00187     {
00188         for (j=0 ; j<3 ; j++)
00189         {
00190             d = v[j] - dv->point[j];
00191             if ( d > POINT_EPSILON || d < -POINT_EPSILON)
00192                 break;
00193         }
00194         if (j == 3)
00195             return i;       // a match
00196     }
00197 
00198     // new point
00199     if (numvertexes == MAX_MAP_VERTS)
00200         Error ("MAX_MAP_VERTS");
00201     VectorCopy (v, dv->point);
00202     numvertexes++;
00203     c_uniqueverts++;
00204 
00205     return numvertexes-1;
00206 }
00207 #endif
00208 
00209 
00210 /*
00211 ==================
00212 FaceFromSuperverts
00213 
00214 The faces vertexes have been added to the superverts[] array,
00215 and there may be more there than can be held in a face (MAXEDGES).
00216 
00217 If less, the faces vertexnums[] will be filled in, otherwise
00218 face will reference a tree of split[] faces until all of the
00219 vertexnums can be added.
00220 
00221 superverts[base] will become face->vertexnums[0], and the others
00222 will be circularly filled in.
00223 ==================
00224 */
00225 void FaceFromSuperverts (node_t *node, face_t *f, int base)
00226 {
00227     face_t  *newf;
00228     int     remaining;
00229     int     i;
00230 
00231     remaining = numsuperverts;
00232     while (remaining > MAXEDGES)
00233     {   // must split into two faces, because of vertex overload
00234         c_faceoverflows++;
00235 
00236         newf = f->split[0] = NewFaceFromFace (f);
00237         newf = f->split[0];
00238         newf->next = node->faces;
00239         node->faces = newf;
00240 
00241         newf->numpoints = MAXEDGES;
00242         for (i=0 ; i<MAXEDGES ; i++)
00243             newf->vertexnums[i] = superverts[(i+base)%numsuperverts];
00244 
00245         f->split[1] = NewFaceFromFace (f);
00246         f = f->split[1];
00247         f->next = node->faces;
00248         node->faces = f;
00249 
00250         remaining -= (MAXEDGES-2);
00251         base = (base+MAXEDGES-1)%numsuperverts;
00252     }
00253 
00254     // copy the vertexes back to the face
00255     f->numpoints = remaining;
00256     for (i=0 ; i<remaining ; i++)
00257         f->vertexnums[i] = superverts[(i+base)%numsuperverts];
00258 }
00259 
00260 
00261 /*
00262 ==================
00263 EmitFaceVertexes
00264 ==================
00265 */
00266 void EmitFaceVertexes (node_t *node, face_t *f)
00267 {
00268     winding_t   *w;
00269     int         i;
00270 
00271     if (f->merged || f->split[0] || f->split[1])
00272         return;
00273 
00274     w = f->w;
00275     for (i=0 ; i<w->numpoints ; i++)
00276     {
00277         if (noweld)
00278         {   // make every point unique
00279             if (numvertexes == MAX_MAP_VERTS)
00280                 Error ("MAX_MAP_VERTS");
00281             superverts[i] = numvertexes;
00282             VectorCopy (w->p[i], dvertexes[numvertexes].point);
00283             numvertexes++;
00284             c_uniqueverts++;
00285             c_totalverts++;
00286         }
00287         else
00288             superverts[i] = GetVertexnum (w->p[i]);
00289     }
00290     numsuperverts = w->numpoints;
00291 
00292     // this may fragment the face if > MAXEDGES
00293     FaceFromSuperverts (node, f, 0);
00294 }
00295 
00296 /*
00297 ==================
00298 EmitVertexes_r
00299 ==================
00300 */
00301 void EmitVertexes_r (node_t *node)
00302 {
00303     int     i;
00304     face_t  *f;
00305 
00306     if (node->planenum == PLANENUM_LEAF)
00307         return;
00308 
00309     for (f=node->faces ; f ; f=f->next)
00310     {
00311         EmitFaceVertexes (node, f);
00312     }
00313 
00314     for (i=0 ; i<2 ; i++)
00315         EmitVertexes_r (node->children[i]);
00316 }
00317 
00318 
00319 #ifdef USE_HASHING
00320 /*
00321 ==========
00322 FindEdgeVerts
00323 
00324 Uses the hash tables to cut down to a small number
00325 ==========
00326 */
00327 void FindEdgeVerts (vec3_t v1, vec3_t v2)
00328 {
00329     int     x1, x2, y1, y2, t;
00330     int     x, y;
00331     int     vnum;
00332 
00333 #if 0
00334 {
00335     int     i;
00336     num_edge_verts = numvertexes-1;
00337     for (i=0 ; i<numvertexes-1 ; i++)
00338         edge_verts[i] = i+1;
00339 }
00340 #endif
00341 
00342     x1 = (4096 + (int)(v1[0]+0.5)) >> 7;
00343     y1 = (4096 + (int)(v1[1]+0.5)) >> 7;
00344     x2 = (4096 + (int)(v2[0]+0.5)) >> 7;
00345     y2 = (4096 + (int)(v2[1]+0.5)) >> 7;
00346 
00347     if (x1 > x2)
00348     {
00349         t = x1;
00350         x1 = x2;
00351         x2 = t;
00352     }
00353     if (y1 > y2)
00354     {
00355         t = y1;
00356         y1 = y2;
00357         y2 = t;
00358     }
00359 #if 0
00360     x1--;
00361     x2++;
00362     y1--;
00363     y2++;
00364     if (x1 < 0)
00365         x1 = 0;
00366     if (x2 >= HASH_SIZE)
00367         x2 = HASH_SIZE;
00368     if (y1 < 0)
00369         y1 = 0;
00370     if (y2 >= HASH_SIZE)
00371         y2 = HASH_SIZE;
00372 #endif
00373     num_edge_verts = 0;
00374     for (x=x1 ; x <= x2 ; x++)
00375     {
00376         for (y=y1 ; y <= y2 ; y++)
00377         {
00378             for (vnum=hashverts[y*HASH_SIZE+x] ; vnum ; vnum=vertexchain[vnum])
00379             {
00380                 edge_verts[num_edge_verts++] = vnum;
00381             }
00382         }
00383     }
00384 }
00385 
00386 #else
00387 /*
00388 ==========
00389 FindEdgeVerts
00390 
00391 Forced a dumb check of everything
00392 ==========
00393 */
00394 void FindEdgeVerts (vec3_t v1, vec3_t v2)
00395 {
00396     int     i;
00397 
00398     num_edge_verts = numvertexes-1;
00399     for (i=0 ; i<num_edge_verts ; i++)
00400         edge_verts[i] = i+1;
00401 }
00402 #endif
00403 
00404 /*
00405 ==========
00406 TestEdge
00407 
00408 Can be recursively reentered
00409 ==========
00410 */
00411 void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
00412 {
00413     int     j, k;
00414     vec_t   dist;
00415     vec3_t  delta;
00416     vec3_t  exact;
00417     vec3_t  off;
00418     vec_t   error;
00419     vec3_t  p;
00420 
00421     if (p1 == p2)
00422     {
00423         c_degenerate++;
00424         return;     // degenerate edge
00425     }
00426 
00427     for (k=startvert ; k<num_edge_verts ; k++)
00428     {
00429         j = edge_verts[k];
00430         if (j==p1 || j == p2)
00431             continue;
00432 
00433         VectorCopy (dvertexes[j].point, p);
00434 
00435         VectorSubtract (p, edge_start, delta);
00436         dist = DotProduct (delta, edge_dir);
00437         if (dist <=start || dist >= end)
00438             continue;       // off an end
00439         VectorMA (edge_start, dist, edge_dir, exact);
00440         VectorSubtract (p, exact, off);
00441         error = VectorLength (off);
00442 
00443         if (fabs(error) > OFF_EPSILON)
00444             continue;       // not on the edge
00445 
00446         // break the edge
00447         c_tjunctions++;
00448         TestEdge (start, dist, p1, j, k+1);
00449         TestEdge (dist, end, j, p2, k+1);
00450         return;
00451     }
00452 
00453     // the edge p1 to p2 is now free of tjunctions
00454     if (numsuperverts >= MAX_SUPERVERTS)
00455         Error ("MAX_SUPERVERTS");
00456     superverts[numsuperverts] = p1;
00457     numsuperverts++;
00458 }
00459 
00460 /*
00461 ==================
00462 FixFaceEdges
00463 
00464 ==================
00465 */
00466 void FixFaceEdges (node_t *node, face_t *f)
00467 {
00468     int     p1, p2;
00469     int     i;
00470     vec3_t  e2;
00471     vec_t   len;
00472     int     count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];
00473     int     base;
00474 
00475     if (f->merged || f->split[0] || f->split[1])
00476         return;
00477 
00478     numsuperverts = 0;
00479 
00480     for (i=0 ; i<f->numpoints ; i++)
00481     {
00482         p1 = f->vertexnums[i];
00483         p2 = f->vertexnums[(i+1)%f->numpoints];
00484 
00485         VectorCopy (dvertexes[p1].point, edge_start);
00486         VectorCopy (dvertexes[p2].point, e2);
00487 
00488         FindEdgeVerts (edge_start, e2);
00489 
00490         VectorSubtract (e2, edge_start, edge_dir);
00491         len = VectorNormalize(edge_dir);
00492 
00493         start[i] = numsuperverts;
00494         TestEdge (0, len, p1, p2, 0);
00495 
00496         count[i] = numsuperverts - start[i];
00497     }
00498 
00499     if (numsuperverts < 3)
00500     {   // entire face collapsed
00501         f->numpoints = 0;
00502         c_facecollapse++;
00503         return;
00504     }
00505 
00506     // we want to pick a vertex that doesn't have tjunctions
00507     // on either side, which can cause artifacts on trifans,
00508     // especially underwater
00509     for (i=0 ; i<f->numpoints ; i++)
00510     {
00511         if (count[i] == 1 && count[(i+f->numpoints-1)%f->numpoints] == 1)
00512             break;
00513     }
00514     if (i == f->numpoints)
00515     {
00516         f->badstartvert = true;
00517         c_badstartverts++;
00518         base = 0;
00519     }
00520     else
00521     {   // rotate the vertex order
00522         base = start[i];
00523     }
00524 
00525     // this may fragment the face if > MAXEDGES
00526     FaceFromSuperverts (node, f, base);
00527 }
00528 
00529 /*
00530 ==================
00531 FixEdges_r
00532 ==================
00533 */
00534 void FixEdges_r (node_t *node)
00535 {
00536     int     i;
00537     face_t  *f;
00538 
00539     if (node->planenum == PLANENUM_LEAF)
00540         return;
00541 
00542     for (f=node->faces ; f ; f=f->next)
00543         FixFaceEdges (node, f);
00544 
00545     for (i=0 ; i<2 ; i++)
00546         FixEdges_r (node->children[i]);
00547 }
00548 
00549 /*
00550 ===========
00551 FixTjuncs
00552 
00553 ===========
00554 */
00555 void FixTjuncs (node_t *headnode)
00556 {
00557     // snap and merge all vertexes
00558     qprintf ("---- snap verts ----\n");
00559     memset (hashverts, 0, sizeof(hashverts));
00560     c_totalverts = 0;
00561     c_uniqueverts = 0;
00562     c_faceoverflows = 0;
00563     EmitVertexes_r (headnode);
00564     qprintf ("%i unique from %i\n", c_uniqueverts, c_totalverts);
00565 
00566     // break edges on tjunctions
00567     qprintf ("---- tjunc ----\n");
00568     c_tryedges = 0;
00569     c_degenerate = 0;
00570     c_facecollapse = 0;
00571     c_tjunctions = 0;
00572     if (!notjunc)
00573         FixEdges_r (headnode);
00574     qprintf ("%5i edges degenerated\n", c_degenerate);
00575     qprintf ("%5i faces degenerated\n", c_facecollapse);
00576     qprintf ("%5i edges added by tjunctions\n", c_tjunctions);
00577     qprintf ("%5i faces added by tjunctions\n", c_faceoverflows);
00578     qprintf ("%5i bad start verts\n", c_badstartverts);
00579 }
00580 
00581 
00582 //========================================================
00583 
00584 int     c_faces;
00585 
00586 face_t  *AllocFace (void)
00587 {
00588     face_t  *f;
00589 
00590     f = GetMemory(sizeof(*f));
00591     memset (f, 0, sizeof(*f));
00592     c_faces++;
00593 
00594     return f;
00595 }
00596 
00597 face_t *NewFaceFromFace (face_t *f)
00598 {
00599     face_t  *newf;
00600 
00601     newf = AllocFace ();
00602     *newf = *f;
00603     newf->merged = NULL;
00604     newf->split[0] = newf->split[1] = NULL;
00605     newf->w = NULL;
00606     return newf;
00607 }
00608 
00609 void FreeFace (face_t *f)
00610 {
00611     if (f->w)
00612         FreeWinding (f->w);
00613     FreeMemory(f);
00614     c_faces--;
00615 }
00616 
00617 //========================================================
00618 
00619 /*
00620 ==================
00621 GetEdge
00622 
00623 Called by writebsp.
00624 Don't allow four way edges
00625 ==================
00626 */
00627 int GetEdge2 (int v1, int v2,  face_t *f)
00628 {
00629     dedge_t *edge;
00630     int     i;
00631 
00632     c_tryedges++;
00633 
00634     if (!noshare)
00635     {
00636         for (i=firstmodeledge ; i < numedges ; i++)
00637         {
00638             edge = &dedges[i];
00639             if (v1 == edge->v[1] && v2 == edge->v[0]
00640             && edgefaces[i][0]->contents == f->contents)
00641             {
00642                 if (edgefaces[i][1])
00643     //              printf ("WARNING: multiple backward edge\n");
00644                     continue;
00645                 edgefaces[i][1] = f;
00646                 return -i;
00647             }
00648     #if 0
00649             if (v1 == edge->v[0] && v2 == edge->v[1])
00650             {
00651                 printf ("WARNING: multiple forward edge\n");
00652                 return i;
00653             }
00654     #endif
00655         }
00656     }
00657 
00658 // emit an edge
00659     if (numedges >= MAX_MAP_EDGES)
00660         Error ("numedges == MAX_MAP_EDGES");
00661     edge = &dedges[numedges];
00662     numedges++;
00663     edge->v[0] = v1;
00664     edge->v[1] = v2;
00665     edgefaces[numedges-1][0] = f;
00666     
00667     return numedges-1;
00668 }
00669 
00670 /*
00671 ===========================================================================
00672 
00673 FACE MERGING
00674 
00675 ===========================================================================
00676 */
00677 
00678 /*
00679 =============
00680 TryMerge
00681 
00682 If two polygons share a common edge and the edges that meet at the
00683 common points are both inside the other polygons, merge them
00684 
00685 Returns NULL if the faces couldn't be merged, or the new face.
00686 The originals will NOT be freed.
00687 =============
00688 */
00689 face_t *TryMerge (face_t *f1, face_t *f2, vec3_t planenormal)
00690 {
00691     face_t      *newf;
00692     winding_t   *nw;
00693 
00694     if (!f1->w || !f2->w)
00695         return NULL;
00696     if (f1->texinfo != f2->texinfo)
00697         return NULL;
00698     if (f1->planenum != f2->planenum)   // on front and back sides
00699         return NULL;
00700     if (f1->contents != f2->contents)
00701         return NULL;
00702         
00703 
00704     nw = TryMergeWinding (f1->w, f2->w, planenormal);
00705     if (!nw)
00706         return NULL;
00707 
00708     c_merge++;
00709     newf = NewFaceFromFace (f1);
00710     newf->w = nw;
00711 
00712     f1->merged = newf;
00713     f2->merged = newf;
00714 
00715     return newf;
00716 }
00717 
00718 /*
00719 ===============
00720 MergeNodeFaces
00721 ===============
00722 */
00723 void MergeNodeFaces (node_t *node)
00724 {
00725     face_t  *f1, *f2, *end;
00726     face_t  *merged;
00727     plane_t *plane;
00728 
00729     plane = &mapplanes[node->planenum];
00730     merged = NULL;
00731     
00732     for (f1 = node->faces ; f1 ; f1 = f1->next)
00733     {
00734         if (f1->merged || f1->split[0] || f1->split[1])
00735             continue;
00736 
00737         for (f2 = node->faces ; f2 != f1 ; f2=f2->next)
00738         {
00739             if (f2->merged || f2->split[0] || f2->split[1])
00740                 continue;
00741 
00742             //IDBUG: always passes the face's node's normal to TryMerge()
00743             //regardless of which side the face is on. Approximately 50% of
00744             //the time the face will be on the other side of node, and thus
00745             //the result of the convex/concave test in TryMergeWinding(),
00746             //which depends on the normal, is flipped. This causes faces
00747             //that shouldn't be merged to be merged and faces that
00748             //should be merged to not be merged. 
00749             //the following added line fixes this bug
00750             //thanks to: Alexander Malmberg <alexander@malmberg.org>
00751             plane = &mapplanes[f1->planenum];
00752             //
00753             merged = TryMerge (f1, f2, plane->normal);
00754             if (!merged)
00755                 continue;
00756 
00757             // add merged to the end of the node face list 
00758             // so it will be checked against all the faces again
00759             for (end = node->faces ; end->next ; end = end->next)
00760             ;
00761             merged->next = NULL;
00762             end->next = merged;
00763             break;
00764         }
00765     }
00766 }
00767 
00768 //=====================================================================
00769 
00770 /*
00771 ===============
00772 SubdivideFace
00773 
00774 Chop up faces that are larger than we want in the surface cache
00775 ===============
00776 */
00777 void SubdivideFace (node_t *node, face_t *f)
00778 {
00779     float       mins, maxs;
00780     vec_t       v;
00781     int         axis, i;
00782     texinfo_t   *tex;
00783     vec3_t      temp;
00784     vec_t       dist;
00785     winding_t   *w, *frontw, *backw;
00786 
00787     if (f->merged)
00788         return;
00789 
00790 // special (non-surface cached) faces don't need subdivision
00791     tex = &texinfo[f->texinfo];
00792 
00793     if ( tex->flags & (SURF_WARP|SURF_SKY) )
00794     {
00795         return;
00796     }
00797 
00798     for (axis = 0 ; axis < 2 ; axis++)
00799     {
00800         while (1)
00801         {
00802             mins = 999999;
00803             maxs = -999999;
00804             
00805             VectorCopy (tex->vecs[axis], temp);
00806             w = f->w;
00807             for (i=0 ; i<w->numpoints ; i++)
00808             {
00809                 v = DotProduct (w->p[i], temp);
00810                 if (v < mins)
00811                     mins = v;
00812                 if (v > maxs)
00813                     maxs = v;
00814             }
00815 #if 0
00816             if (maxs - mins <= 0)
00817                 Error ("zero extents");
00818 #endif
00819             if (axis == 2)
00820             {   // allow double high walls
00821                 if (maxs - mins <= subdivide_size/* *2 */)
00822                     break;
00823             }
00824             else if (maxs - mins <= subdivide_size)
00825                 break;
00826             
00827         // split it
00828             c_subdivide++;
00829             
00830             v = VectorNormalize (temp);
00831 
00832             dist = (mins + subdivide_size - 16)/v;
00833 
00834             ClipWindingEpsilon (w, temp, dist, ON_EPSILON, &frontw, &backw);
00835             if (!frontw || !backw)
00836                 Error ("SubdivideFace: didn't split the polygon");
00837 
00838             f->split[0] = NewFaceFromFace (f);
00839             f->split[0]->w = frontw;
00840             f->split[0]->next = node->faces;
00841             node->faces = f->split[0];
00842 
00843             f->split[1] = NewFaceFromFace (f);
00844             f->split[1]->w = backw;
00845             f->split[1]->next = node->faces;
00846             node->faces = f->split[1];
00847 
00848             SubdivideFace (node, f->split[0]);
00849             SubdivideFace (node, f->split[1]);
00850             return;
00851         }
00852     }
00853 }
00854 
00855 void SubdivideNodeFaces (node_t *node)
00856 {
00857     face_t  *f;
00858 
00859     for (f = node->faces ; f ; f=f->next)
00860     {
00861         SubdivideFace (node, f);
00862     }
00863 }
00864 
00865 //===========================================================================
00866 
00867 int c_nodefaces;
00868 
00869 
00870 /*
00871 ============
00872 FaceFromPortal
00873 
00874 ============
00875 */
00876 face_t *FaceFromPortal (portal_t *p, int pside)
00877 {
00878     face_t  *f;
00879     side_t  *side;
00880 
00881     side = p->side;
00882     if (!side)
00883         return NULL;    // portal does not bridge different visible contents
00884 
00885     f = AllocFace ();
00886 
00887     f->texinfo = side->texinfo;
00888     f->planenum = (side->planenum & ~1) | pside;
00889     f->portal = p;
00890 
00891     if ( (p->nodes[pside]->contents & CONTENTS_WINDOW)
00892         && VisibleContents(p->nodes[!pside]->contents^p->nodes[pside]->contents) == CONTENTS_WINDOW )
00893         return NULL;    // don't show insides of windows
00894 
00895     if (pside)
00896     {
00897         f->w = ReverseWinding(p->winding);
00898         f->contents = p->nodes[1]->contents;
00899     }
00900     else
00901     {
00902         f->w = CopyWinding(p->winding);
00903         f->contents = p->nodes[0]->contents;
00904     }
00905     return f;
00906 }
00907 
00908 
00909 /*
00910 ===============
00911 MakeFaces_r
00912 
00913 If a portal will make a visible face,
00914 mark the side that originally created it
00915 
00916   solid / empty : solid
00917   solid / water : solid
00918   water / empty : water
00919   water / water : none
00920 ===============
00921 */
00922 void MakeFaces_r (node_t *node)
00923 {
00924     portal_t    *p;
00925     int         s;
00926 
00927     // recurse down to leafs
00928     if (node->planenum != PLANENUM_LEAF)
00929     {
00930         MakeFaces_r (node->children[0]);
00931         MakeFaces_r (node->children[1]);
00932 
00933         // merge together all visible faces on the node
00934         if (!nomerge)
00935             MergeNodeFaces (node);
00936         if (!nosubdiv)
00937             SubdivideNodeFaces (node);
00938 
00939         return;
00940     }
00941 
00942     // solid leafs never have visible faces
00943     if (node->contents & CONTENTS_SOLID)
00944         return;
00945 
00946     // see which portals are valid
00947     for (p=node->portals ; p ; p = p->next[s])
00948     {
00949         s = (p->nodes[1] == node);
00950 
00951         p->face[s] = FaceFromPortal (p, s);
00952         if (p->face[s])
00953         {
00954             c_nodefaces++;
00955             p->face[s]->next = p->onnode->faces;
00956             p->onnode->faces = p->face[s];
00957         }
00958     }
00959 }
00960 
00961 /*
00962 ============
00963 MakeFaces
00964 ============
00965 */
00966 void MakeFaces (node_t *node)
00967 {
00968     qprintf ("--- MakeFaces ---\n");
00969     c_merge = 0;
00970     c_subdivide = 0;
00971     c_nodefaces = 0;
00972 
00973     MakeFaces_r (node);
00974 
00975     qprintf ("%5i makefaces\n", c_nodefaces);
00976     qprintf ("%5i merged\n", c_merge);
00977     qprintf ("%5i subdivided\n", c_subdivide);
00978 }

Generated on Thu Aug 25 12:37:15 2005 for Quake III Arena by  doxygen 1.3.9.1