#include "qbsp.h"
#include "l_mem.h"
Include dependency graph for faces.c:

Go to the source code of this file.
|
|
Definition at line 82 of file faces.c. Referenced by FindEdgeVerts(), and HashVec(). |
|
|
|
|
|
|
|
|
|
|
|
Definition at line 40 of file faces.c. Referenced by Brush_MoveVertex_old1(), CM_ComparePoints(), and GetVertexnum(). |
|
|
|
|
|
|
|
|
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:

|
||||||||||||
|
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:

|
|
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:

|
||||||||||||
|
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:

|
||||||||||||||||
|
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:

|
||||||||||||
|
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 }
|
|
|
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:

|
||||||||||||
|
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:

|
|
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:

|
|
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:

|
||||||||||||||||
|
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:

|
|
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:

|
|
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:

|
|
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:

|
|
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:

|
|
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:

|
|
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:

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