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

faces.c File Reference

#include "qbsp.h"
#include "l_mem.h"

Include dependency graph for faces.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  hashvert_s

Defines

#define HASH_SIZE   64
#define INTEGRAL_EPSILON   0.01
#define MAX_SUPERVERTS   512
#define OFF_EPSILON   0.5
#define POINT_EPSILON   0.5
#define USE_HASHING

Typedefs

typedef hashvert_s hashvert_t

Functions

face_tAllocFace (void)
void EmitFaceVertexes (node_t *node, face_t *f)
void EmitVertexes_r (node_t *node)
face_tFaceFromPortal (portal_t *p, int pside)
void FaceFromSuperverts (node_t *node, face_t *f, int base)
void FindEdgeVerts (vec3_t v1, vec3_t v2)
void FixEdges_r (node_t *node)
void FixFaceEdges (node_t *node, face_t *f)
void FixTjuncs (node_t *headnode)
void FreeFace (face_t *f)
int GetEdge2 (int v1, int v2, face_t *f)
int GetVertexnum (vec3_t in)
unsigned HashVec (vec3_t vec)
void MakeFaces (node_t *node)
void MakeFaces_r (node_t *node)
void MergeNodeFaces (node_t *node)
face_tNewFaceFromFace (face_t *f)
void SubdivideFace (node_t *node, face_t *f)
void SubdivideNodeFaces (node_t *node)
void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
face_tTryMerge (face_t *f1, face_t *f2, vec3_t planenormal)

Variables

int c_badstartverts
int c_degenerate
int c_facecollapse
int c_faceoverflows
int c_faces
int c_merge
int c_nodefaces
int c_subdivide
int c_tjunctions
int c_totalverts
int c_tryedges
int c_uniqueverts
vec3_t edge_dir
vec_t edge_len
vec3_t edge_start
int edge_verts [MAX_MAP_VERTS]
face_tedgefaces [MAX_MAP_EDGES][2]
int firstmodeledge = 1
int firstmodelface
int hashverts [HASH_SIZE *HASH_SIZE]
int num_edge_verts
int numsuperverts
int superverts [MAX_SUPERVERTS]
int vertexchain [MAX_MAP_VERTS]


Define Documentation

#define HASH_SIZE   64
 

Definition at line 82 of file faces.c.

Referenced by FindEdgeVerts(), and HashVec().

#define INTEGRAL_EPSILON   0.01
 

Definition at line 39 of file faces.c.

#define MAX_SUPERVERTS   512
 

Definition at line 54 of file faces.c.

#define OFF_EPSILON   0.5
 

Definition at line 41 of file faces.c.

#define POINT_EPSILON   0.5
 

Definition at line 40 of file faces.c.

Referenced by Brush_MoveVertex_old1(), CM_ComparePoints(), and GetVertexnum().

#define USE_HASHING
 

Definition at line 37 of file faces.c.


Typedef Documentation

typedef struct hashvert_s hashvert_t
 


Function Documentation

face_t* AllocFace void   ) 
 

Definition at line 586 of file faces.c.

References c_faces, f, face_t, GetMemory(), and memset().

Referenced by FaceFromPortal(), and NewFaceFromFace().

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 }

Here is the call graph for this function:

void EmitFaceVertexes node_t node,
face_t f
 

Definition at line 266 of file faces.c.

References c_totalverts, c_uniqueverts, dvertexes, Error(), f, face_t, FaceFromSuperverts(), GetVertexnum(), i, face_s::merged, node_t, winding_t::numpoints, numsuperverts, numvertexes, winding_t::p, dvertex_t::point, face_s::split, superverts, VectorCopy, face_s::w, and w.

Referenced by EmitVertexes_r().

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 }

Here is the call graph for this function:

void EmitVertexes_r node_t node  ) 
 

Definition at line 301 of file faces.c.

References node_s::children, EmitFaceVertexes(), f, face_t, node_s::faces, i, face_s::next, node_t, and node_s::planenum.

Referenced by FixTjuncs().

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 }

Here is the call graph for this function:

face_t* FaceFromPortal portal_t p,
int  pside
 

Definition at line 876 of file faces.c.

References AllocFace(), face_s::contents, node_s::contents, CopyWinding(), f, face_t, portal_s::nodes, p, side_s::planenum, face_s::planenum, face_s::portal, portal_t, ReverseWinding(), portal_s::side, side_t, side_s::texinfo, face_s::texinfo, VisibleContents(), face_s::w, and portal_s::winding.

Referenced by MakeFaces_r().

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 }

Here is the call graph for this function:

void FaceFromSuperverts node_t node,
face_t f,
int  base
 

Definition at line 225 of file faces.c.

References c_faceoverflows, f, face_t, node_s::faces, i, MAXEDGES, NewFaceFromFace(), face_s::next, node_t, face_s::numpoints, face_s::split, superverts, and face_s::vertexnums.

Referenced by EmitFaceVertexes(), and FixFaceEdges().

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 }

Here is the call graph for this function:

void FindEdgeVerts vec3_t  v1,
vec3_t  v2
 

Definition at line 327 of file faces.c.

References edge_verts, HASH_SIZE, hashverts, i, num_edge_verts, numvertexes, t, v1, v2, vertexchain, x, x2, y, y1, and y2.

Referenced by FixFaceEdges().

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 }

void FixEdges_r node_t node  ) 
 

Definition at line 534 of file faces.c.

References node_s::children, f, face_t, node_s::faces, FixFaceEdges(), i, face_s::next, node_t, and node_s::planenum.

Referenced by FixTjuncs().

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 }

Here is the call graph for this function:

void FixFaceEdges node_t node,
face_t f
 

Definition at line 466 of file faces.c.

References face_s::badstartvert, c_badstartverts, c_facecollapse, count, dvertexes, edge_dir, edge_start, f, face_t, FaceFromSuperverts(), FindEdgeVerts(), i, face_s::merged, node_t, face_s::numpoints, numsuperverts, p2, point, face_s::split, TestEdge(), vec3_t, vec_t, VectorCopy, VectorNormalize(), VectorSubtract, and face_s::vertexnums.

Referenced by FixEdges_r().

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 }

Here is the call graph for this function:

void FixTjuncs node_t headnode  ) 
 

Definition at line 555 of file faces.c.

References c_badstartverts, c_degenerate, c_facecollapse, c_faceoverflows, c_tjunctions, c_totalverts, c_tryedges, c_uniqueverts, EmitVertexes_r(), FixEdges_r(), hashverts, memset(), node_t, and qprintf().

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 }

Here is the call graph for this function:

void FreeFace face_t f  ) 
 

Definition at line 609 of file faces.c.

References c_faces, f, face_t, FreeMemory(), FreeWinding(), and face_s::w.

00610 {
00611     if (f->w)
00612         FreeWinding (f->w);
00613     FreeMemory(f);
00614     c_faces--;
00615 }

Here is the call graph for this function:

int GetEdge2 int  v1,
int  v2,
face_t f
 

Definition at line 627 of file faces.c.

References c_tryedges, face_s::contents, dedges, edgefaces, Error(), f, face_t, i, numedges, printf(), dedge_t::v, v1, and v2.

Referenced by EmitFace().

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 }

Here is the call graph for this function:

int GetVertexnum vec3_t  in  ) 
 

Definition at line 114 of file faces.c.

References c_totalverts, c_uniqueverts, dvertexes, Error(), fabs(), h(), HashVec(), hashverts, i, in, numvertexes, p, dvertex_t::point, POINT_EPSILON, Q_rint(), vec3_t, and vertexchain.

Referenced by EmitFaceVertexes().

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 }

Here is the call graph for this function:

unsigned HashVec vec3_t  vec  ) 
 

Definition at line 93 of file faces.c.

References Error(), HASH_SIZE, x, and y.

Referenced by GetVertexnum().

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 }

Here is the call graph for this function:

void MakeFaces node_t node  ) 
 

Definition at line 966 of file faces.c.

References c_merge, c_nodefaces, c_subdivide, MakeFaces_r(), node_t, and qprintf().

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 }

Here is the call graph for this function:

void MakeFaces_r node_t node  ) 
 

Definition at line 922 of file faces.c.

References c_nodefaces, node_s::children, node_s::contents, portal_s::face, FaceFromPortal(), node_s::faces, MergeNodeFaces(), face_s::next, portal_s::next, node_t, portal_s::nodes, portal_s::onnode, p, node_s::planenum, portal_t, node_s::portals, s, and SubdivideNodeFaces().

Referenced by MakeFaces().

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 }

Here is the call graph for this function:

void MergeNodeFaces node_t node  ) 
 

Definition at line 723 of file faces.c.

References f1(), f2(), face_t, node_s::faces, mapplanes, face_s::merged, face_s::next, node_t, plane_t::normal, face_s::planenum, node_s::planenum, face_s::split, and TryMerge().

Referenced by MakeFaces_r().

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 }

Here is the call graph for this function:

face_t * NewFaceFromFace face_t f  ) 
 

Definition at line 597 of file faces.c.

References AllocFace(), face_t, face_s::merged, face_s::split, and face_s::w.

Referenced by FaceFromSuperverts(), SubdivideFace(), and TryMerge().

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 }

Here is the call graph for this function:

void SubdivideFace node_t node,
face_t f
 

Definition at line 777 of file faces.c.

References c_subdivide, ClipWindingEpsilon(), DotProduct, Error(), f, face_t, node_s::faces, texinfo_s::flags, i, face_s::merged, NewFaceFromFace(), face_s::next, node_t, winding_t::numpoints, ON_EPSILON, winding_t::p, face_s::split, subdivide_size, SURF_WARP, face_s::texinfo, texinfo, texinfo_t, v, vec3_t, vec_t, texinfo_s::vecs, VectorCopy, VectorNormalize(), face_s::w, and w.

Referenced by SubdivideNodeFaces().

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;
0083