MAXEDGES? What MAXEDGES? :)

This commit is contained in:
Bill Currie 2003-09-08 03:00:53 +00:00
parent 89586e0181
commit ca91f7b727
11 changed files with 139 additions and 271 deletions

View File

@ -61,6 +61,7 @@ void CheckWinding (winding_t *w);
winding_t *NewWinding (int points); winding_t *NewWinding (int points);
void FreeWinding (winding_t *w); void FreeWinding (winding_t *w);
winding_t *CopyWinding (winding_t *w); winding_t *CopyWinding (winding_t *w);
winding_t *CopyWindingReverse (winding_t *w);
winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon); winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon);
void DivideWinding (winding_t *in, plane_t *split, winding_t **front, winding_t **back); void DivideWinding (winding_t *in, plane_t *split, winding_t **front, winding_t **back);
@ -84,9 +85,8 @@ typedef struct visfacet_s
// write surfaces // write surfaces
qboolean detail; // is a detail face qboolean detail; // is a detail face
int numpoints; winding_t *points;
vec3_t pts[MAXEDGES]; // FIXME: change to use winding_t int *edges;
int edges[MAXEDGES];
} face_t; } face_t;
typedef struct surface_s typedef struct surface_s

View File

@ -53,21 +53,21 @@ CheckFace (face_t *f)
vec_t d, edgedist; vec_t d, edgedist;
vec3_t dir, edgenormal, facenormal; vec3_t dir, edgenormal, facenormal;
if (f->numpoints < 3) if (f->points->numpoints < 3)
Sys_Error ("CheckFace: %i points", f->numpoints); Sys_Error ("CheckFace: %i points", f->points->numpoints);
VectorCopy (planes[f->planenum].normal, facenormal); VectorCopy (planes[f->planenum].normal, facenormal);
if (f->planeside) if (f->planeside)
VectorNegate (facenormal, facenormal); VectorNegate (facenormal, facenormal);
for (i = 0; i < f->numpoints; i++) { for (i = 0; i < f->points->numpoints; i++) {
p1 = f->pts[i]; p1 = f->points->points[i];
for (j = 0; j < 3; j++) for (j = 0; j < 3; j++)
if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE) if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
Sys_Error ("CheckFace: BUGUS_RANGE: %f", p1[j]); Sys_Error ("CheckFace: BUGUS_RANGE: %f", p1[j]);
j = i + 1 == f->numpoints ? 0 : i + 1; j = i + 1 == f->points->numpoints ? 0 : i + 1;
// check the point is on the face plane // check the point is on the face plane
d = DotProduct (p1, planes[f->planenum].normal) d = DotProduct (p1, planes[f->planenum].normal)
@ -80,7 +80,7 @@ CheckFace (face_t *f)
#endif #endif
// check the edge isn't degenerate // check the edge isn't degenerate
p2 = f->pts[j]; p2 = f->points->points[j];
VectorSubtract (p2, p1, dir); VectorSubtract (p2, p1, dir);
if (VectorLength (dir) < ON_EPSILON) if (VectorLength (dir) < ON_EPSILON)
@ -92,10 +92,10 @@ CheckFace (face_t *f)
edgedist += ON_EPSILON; edgedist += ON_EPSILON;
// all other points must be on front side // all other points must be on front side
for (j = 0; j < f->numpoints; j++) { for (j = 0; j < f->points->numpoints; j++) {
if (j == i) if (j == i)
continue; continue;
d = DotProduct (f->pts[j], edgenormal); d = DotProduct (f->points->points[j], edgenormal);
if (d > edgedist) if (d > edgedist)
Sys_Error ("CheckFace: non-convex"); Sys_Error ("CheckFace: non-convex");
} }
@ -318,27 +318,24 @@ CreateBrushFaces (void)
} }
if (!w) if (!w)
continue; // overcontrained plane continue; // overconstrained plane
// this face is a keeper // this face is a keeper
f = AllocFace (); f = AllocFace ();
f->numpoints = w->numpoints; f->points = w;
if (f->numpoints > MAXEDGES)
Sys_Error ("f->numpoints > MAXEDGES");
for (j = 0; j < w->numpoints; j++) { for (j = 0; j < w->numpoints; j++) {
vec_t *v = f->points->points[j];
VectorSubtract (v, offset, v);
for (k = 0; k < 3; k++) { for (k = 0; k < 3; k++) {
point[k] = w->points[j][k] - offset[k]; r = RINT (v[k]);
r = RINT (point[k]); if (fabs (v[k] - r) < ZERO_EPSILON)
if (fabs (point[k] - r) < ZERO_EPSILON) v[k] = r;
f->pts[j][k] = r;
else
f->pts[j][k] = point[k];
if (f->pts[j][k] < brush_mins[k]) if (v[k] < brush_mins[k])
brush_mins[k] = f->pts[j][k]; brush_mins[k] = v[k];
if (f->pts[j][k] > brush_maxs[k]) if (v[k] > brush_maxs[k])
brush_maxs[k] = f->pts[j][k]; brush_maxs[k] = v[k];
} }
} }
@ -347,7 +344,6 @@ CreateBrushFaces (void)
VectorSubtract (point, offset, point); VectorSubtract (point, offset, point);
plane.dist = DotProduct (plane.normal, point); plane.dist = DotProduct (plane.normal, point);
FreeWinding (w);
f->texturenum = mf->texinfo; f->texturenum = mf->texinfo;
f->planenum = FindPlane (&plane, &f->planeside); f->planenum = FindPlane (&plane, &f->planeside);
f->next = brush_faces; f->next = brush_faces;
@ -588,8 +584,8 @@ ExpandBrush (int hullnum)
// create all the hull points // create all the hull points
for (f = brush_faces; f; f = f->next) for (f = brush_faces; f; f = f->next)
for (i = 0; i < f->numpoints; i++) for (i = 0; i < f->points->numpoints; i++)
AddHullPoint (f->pts[i], hullnum); AddHullPoint (f->points->points[i], hullnum);
// expand all of the planes // expand all of the planes
for (i = 0; i < numbrushfaces; i++) { for (i = 0; i < numbrushfaces; i++) {
@ -619,8 +615,10 @@ ExpandBrush (int hullnum)
// add all of the edge bevels // add all of the edge bevels
for (f = brush_faces; f; f = f->next) for (f = brush_faces; f; f = f->next)
for (i = 0; i < f->numpoints; i++) for (i = 0; i < f->points->numpoints; i++)
AddHullEdge (f->pts[i], f->pts[(i + 1) % f->numpoints], hullnum); AddHullEdge (f->points->points[i],
f->points->points[(i + 1) % f->points->numpoints],
hullnum);
} }
/* /*

View File

@ -73,98 +73,47 @@ NewFaceFromFace (face_t *in)
void void
SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back) SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back)
{ {
face_t *newf, *new2; int i;
int i, j;
int sides[MAXEDGES + 1];
int counts[3]; int counts[3];
plane_t plane;
vec_t dot; vec_t dot;
vec_t dists[MAXEDGES + 1]; winding_t *tmp;
vec_t *p1, *p2;
vec3_t mid;
if (in->numpoints < 0) if (in->points->numpoints < 0)
Sys_Error ("SplitFace: freed face"); Sys_Error ("SplitFace: freed face");
counts[0] = counts[1] = counts[2] = 0; counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point // determine sides for each point
for (i = 0; i < in->numpoints; i++) { for (i = 0; i < in->points->numpoints; i++) {
dot = DotProduct (in->pts[i], split->normal); dot = DotProduct (in->points->points[i], split->normal) - split->dist;
dot -= split->dist;
dists[i] = dot;
if (dot > ON_EPSILON) if (dot > ON_EPSILON)
sides[i] = SIDE_FRONT; counts[SIDE_FRONT]++;
else if (dot < -ON_EPSILON) else if (dot < -ON_EPSILON)
sides[i] = SIDE_BACK; counts[SIDE_BACK]++;
else
sides[i] = SIDE_ON;
counts[sides[i]]++;
} }
sides[i] = sides[0];
dists[i] = dists[0];
if (!counts[0]) { if (!counts[SIDE_FRONT]) {
*front = NULL; *front = NULL;
*back = in; *back = in;
return; return;
} }
if (!counts[1]) { if (!counts[SIDE_BACK]) {
*front = in; *front = in;
*back = NULL; *back = NULL;
return; return;
} }
*back = newf = NewFaceFromFace (in); *back = NewFaceFromFace (in);
*front = new2 = NewFaceFromFace (in); *front = NewFaceFromFace (in);
// distribute the points and generate splits tmp = CopyWinding (in->points);
for (i = 0; i < in->numpoints; i++) { (*front)->points = ClipWinding (tmp, split, 0);
if (newf->numpoints > MAXEDGES || new2->numpoints > MAXEDGES)
Sys_Error ("SplitFace: numpoints > MAXEDGES");
p1 = in->pts[i]; plane.dist = -split->dist;
VectorNegate (split->normal, plane.normal);
(*back)->points = ClipWinding (in->points, &plane, 0);
if (sides[i] == SIDE_ON) { in->points = 0; // freed by ClipWinding
VectorCopy (p1, newf->pts[newf->numpoints]);
newf->numpoints++;
VectorCopy (p1, new2->pts[new2->numpoints]);
new2->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT) {
VectorCopy (p1, new2->pts[new2->numpoints]);
new2->numpoints++;
} else {
VectorCopy (p1, newf->pts[newf->numpoints]);
newf->numpoints++;
}
if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i])
continue;
// generate a split point
p2 = in->pts[(i + 1) % in->numpoints];
dot = dists[i] / (dists[i] - dists[i + 1]);
for (j = 0; j < 3; j++) { // avoid round off error when possible
if (split->normal[j] == 1)
mid[j] = split->dist;
else if (split->normal[j] == -1)
mid[j] = -split->dist;
else
mid[j] = p1[j] + dot * (p2[j] - p1[j]);
}
VectorCopy (mid, newf->pts[newf->numpoints]);
newf->numpoints++;
VectorCopy (mid, new2->pts[new2->numpoints]);
new2->numpoints++;
}
if (newf->numpoints > MAXEDGES || new2->numpoints > MAXEDGES)
Sys_Error ("SplitFace: numpoints > MAXEDGES");
// free the original face now that is is represented by the fragments
FreeFace (in); FreeFace (in);
} }
@ -226,7 +175,7 @@ static void
SaveOutside (qboolean mirror) SaveOutside (qboolean mirror)
{ {
face_t *f, *next, *newf; face_t *f, *next, *newf;
int planenum, i; int planenum;
for (f = outside; f; f = next) { for (f = outside; f; f = next) {
next = f->next; next = f->next;
@ -237,15 +186,11 @@ SaveOutside (qboolean mirror)
if (mirror) { if (mirror) {
newf = NewFaceFromFace (f); newf = NewFaceFromFace (f);
newf->numpoints = f->numpoints; newf->points = CopyWindingReverse (f->points);
newf->planeside = f->planeside ^ 1; // reverse side newf->planeside = f->planeside ^ 1; // reverse side
newf->contents[0] = f->contents[1]; newf->contents[0] = f->contents[1];
newf->contents[1] = f->contents[0]; newf->contents[1] = f->contents[0];
for (i = 0; i < f->numpoints; i++) // add points backwards
{
VectorCopy (f->pts[f->numpoints - 1 - i], newf->pts[i]);
}
validfaces[planenum] = MergeFaceToList (newf, validfaces[planenum] = MergeFaceToList (newf,
validfaces[planenum]); validfaces[planenum]);
} }
@ -331,6 +276,7 @@ CopyFacesToOutside (brush_t *b)
brushfaces++; brushfaces++;
newf = AllocFace (); newf = AllocFace ();
*newf = *f; *newf = *f;
newf->points = CopyWinding (f->points);
newf->next = outside; newf->next = outside;
newf->contents[0] = CONTENTS_EMPTY; newf->contents[0] = CONTENTS_EMPTY;
newf->contents[1] = b->contents; newf->contents[1] = b->contents;

View File

@ -502,7 +502,7 @@ ParseBrush (void)
tx.vecs[i][3] = vecs[i][3]; tx.vecs[i][3] = vecs[i][3];
} }
f = malloc (sizeof (mface_t)); f = calloc (1, sizeof (mface_t));
f->next = b->faces; f->next = b->faces;
b->faces = f; b->faces = f;
f->plane = plane; f->plane = plane;

View File

@ -50,8 +50,9 @@ TryMerge (face_t *f1, face_t *f2)
vec3_t normal, delta, planenormal; vec3_t normal, delta, planenormal;
vec_t dot; vec_t dot;
vec_t *p1, *p2, *p3, *p4, *back; vec_t *p1, *p2, *p3, *p4, *back;
winding_t *f1p, *f2p, *newfp;
if (f1->numpoints == -1 || f2->numpoints == -1) if (!(f1p = f1->points) || !(f2p = f2->points))
return NULL; return NULL;
if (f1->planeside != f2->planeside) if (f1->planeside != f2->planeside)
return NULL; return NULL;
@ -66,12 +67,12 @@ TryMerge (face_t *f1, face_t *f2)
p1 = p2 = NULL; // stop compiler warning p1 = p2 = NULL; // stop compiler warning
j = 0; j = 0;
for (i = 0; i < f1->numpoints; i++) { for (i = 0; i < f1p->numpoints; i++) {
p1 = f1->pts[i]; p1 = f1p->points[i];
p2 = f1->pts[(i + 1) % f1->numpoints]; p2 = f1p->points[(i + 1) % f1p->numpoints];
for (j = 0; j < f2->numpoints; j++) { for (j = 0; j < f2p->numpoints; j++) {
p3 = f2->pts[j]; p3 = f2p->points[j];
p4 = f2->pts[(j + 1) % f2->numpoints]; p4 = f2p->points[(j + 1) % f2p->numpoints];
for (k = 0; k < 3; k++) { for (k = 0; k < 3; k++) {
if (fabs (p1[k] - p4[k]) > EQUAL_EPSILON) if (fabs (p1[k] - p4[k]) > EQUAL_EPSILON)
break; break;
@ -79,15 +80,11 @@ TryMerge (face_t *f1, face_t *f2)
break; break;
} }
if (k == 3) if (k == 3)
break; goto found_edge;
} }
if (j < f2->numpoints)
break;
} }
return NULL; // no matching edges
if (i == f1->numpoints) found_edge:
return NULL; // no matching edges
// check slope of connected lines // check slope of connected lines
// if the slopes are colinear, the point can be removed // if the slopes are colinear, the point can be removed
plane = &planes[f1->planenum]; plane = &planes[f1->planenum];
@ -95,24 +92,24 @@ TryMerge (face_t *f1, face_t *f2)
if (f1->planeside) if (f1->planeside)
VectorNegate (planenormal, planenormal); VectorNegate (planenormal, planenormal);
back = f1->pts[(i + f1->numpoints - 1) % f1->numpoints]; back = f1p->points[(i + f1p->numpoints - 1) % f1p->numpoints];
VectorSubtract (p1, back, delta); VectorSubtract (p1, back, delta);
CrossProduct (planenormal, delta, normal); CrossProduct (planenormal, delta, normal);
_VectorNormalize (normal); _VectorNormalize (normal);
back = f2->pts[(j + 2) % f2->numpoints]; back = f2p->points[(j + 2) % f2p->numpoints];
VectorSubtract (back, p1, delta); VectorSubtract (back, p1, delta);
dot = DotProduct (delta, normal); dot = DotProduct (delta, normal);
if (dot > CONTINUOUS_EPSILON) if (dot > CONTINUOUS_EPSILON)
return NULL; // not a convex polygon return NULL; // not a convex polygon
keep1 = dot < -CONTINUOUS_EPSILON; keep1 = dot < -CONTINUOUS_EPSILON;
back = f1->pts[(i + 2) % f1->numpoints]; back = f1p->points[(i + 2) % f1p->numpoints];
VectorSubtract (back, p2, delta); VectorSubtract (back, p2, delta);
CrossProduct (planenormal, delta, normal); CrossProduct (planenormal, delta, normal);
_VectorNormalize (normal); _VectorNormalize (normal);
back = f2->pts[(j + f2->numpoints - 1) % f2->numpoints]; back = f2p->points[(j + f2p->numpoints - 1) % f2p->numpoints];
VectorSubtract (back, p2, delta); VectorSubtract (back, p2, delta);
dot = DotProduct (delta, normal); dot = DotProduct (delta, normal);
if (dot > CONTINUOUS_EPSILON) if (dot > CONTINUOUS_EPSILON)
@ -120,28 +117,26 @@ TryMerge (face_t *f1, face_t *f2)
keep2 = dot < -CONTINUOUS_EPSILON; keep2 = dot < -CONTINUOUS_EPSILON;
// build the new polygon // build the new polygon
if (f1->numpoints + f2->numpoints > MAXEDGES) {
// Sys_Error ("TryMerge: too many edges!");
return NULL;
}
k = f1p->numpoints + f2p->numpoints - 4 + keep1 + keep2;
newf = NewFaceFromFace (f1); newf = NewFaceFromFace (f1);
newfp = newf->points = NewWinding (k);
// copy first polygon // copy first polygon
for (k = (i + 1) % f1->numpoints; k != i; k = (k + 1) % f1->numpoints) { for (k = (i + 1) % f1p->numpoints; k != i; k = (k + 1) % f1p->numpoints) {
if (k == (i + 1) % f1->numpoints && !keep2) if (k == (i + 1) % f1p->numpoints && !keep2)
continue; continue;
VectorCopy (f1->pts[k], newf->pts[newf->numpoints]); VectorCopy (f1p->points[k], newfp->points[newfp->numpoints]);
newf->numpoints++; newfp->numpoints++;
} }
// copy second polygon // copy second polygon
for (l = (j + 1) % f2->numpoints; l != j; l = (l + 1) % f2->numpoints) { for (l = (j + 1) % f2p->numpoints; l != j; l = (l + 1) % f2p->numpoints) {
if (l == (j + 1) % f2->numpoints && !keep1) if (l == (j + 1) % f2p->numpoints && !keep1)
continue; continue;
VectorCopy (f2->pts[l], newf->pts[newf->numpoints]); VectorCopy (f2p->points[l], newfp->points[newfp->numpoints]);
newf->numpoints++; newfp->numpoints++;
} }
return newf; return newf;
@ -165,7 +160,8 @@ MergeFaceToList (face_t *face, face_t *list)
if (!newf) if (!newf)
continue; continue;
FreeFace (face); FreeFace (face);
f->numpoints = -1; // merged out FreeWinding (f->points); // merged out
f->points = 0;
return MergeFaceToList (newf, list); return MergeFaceToList (newf, list);
} }
@ -182,7 +178,7 @@ FreeMergeListScraps (face_t *merged)
head = NULL; head = NULL;
for (; merged; merged = next) { for (; merged; merged = next) {
next = merged->next; next = merged->next;
if (merged->numpoints == -1) if (!merged->points)
FreeFace (merged); FreeFace (merged);
else { else {
merged->next = head; merged->next = head;

View File

@ -203,7 +203,8 @@ ClearOutFaces (node_t *node)
for (fp = node->markfaces; *fp; fp++) { for (fp = node->markfaces; *fp; fp++) {
// mark all the original faces that are removed // mark all the original faces that are removed
(*fp)->numpoints = 0; FreeWinding ((*fp)->points);
(*fp)->points = 0;
} }
node->faces = NULL; node->faces = NULL;
} }

View File

@ -141,6 +141,22 @@ CopyWinding (winding_t *w)
return c; return c;
} }
winding_t *
CopyWindingReverse (winding_t *w)
{
int i, size;
winding_t *c;
size = (long) ((winding_t *) 0)->points[w->numpoints];
c = malloc (size);
c->numpoints = w->numpoints;
for (i = 0; i < w->numpoints; i++) {
// add points backwards
VectorCopy (w->points[w->numpoints - 1 - i], c->points[i]);
}
return c;
}
void void
CheckWinding (winding_t * w) CheckWinding (winding_t * w)
{ {
@ -355,7 +371,7 @@ NewWinding (int points)
int size; int size;
winding_t *w; winding_t *w;
if (points > MAX_POINTS_ON_WINDING) if (points < 3 || points > MAX_POINTS_ON_WINDING)
Sys_Error ("NewWinding: %i points", points); Sys_Error ("NewWinding: %i points", points);
c_activewindings++; c_activewindings++;

View File

@ -74,8 +74,8 @@ AddFaceToRegionSize (face_t *f)
{ {
int i; int i;
for (i = 0; i < f->numpoints; i++) for (i = 0; i < f->points->numpoints; i++)
AddPointToRegion (f->pts[i]); AddPointToRegion (f->points->points[i]);
} }
static qboolean static qboolean
@ -107,7 +107,7 @@ CanJoinFaces (face_t *f, face_t *f2)
} }
} }
} else { } else {
if (bsp->numsurfedges - firstedge + f2->numpoints if (bsp->numsurfedges - firstedge + f2->points->numpoints
> MAX_EDGES_IN_REGION) > MAX_EDGES_IN_REGION)
return false; // a huge water or sky polygon return false; // a huge water or sky polygon
} }
@ -130,7 +130,7 @@ RecursiveGrowRegion (dface_t *r, face_t *f)
f->outputnumber = bsp->numfaces; f->outputnumber = bsp->numfaces;
// add edges // add edges
for (i = 0; i < f->numpoints; i++) { for (i = 0; i < f->points->numpoints; i++) {
e = f->edges[i]; e = f->edges[i];
if (!edgefaces[abs (e)][0]) if (!edgefaces[abs (e)][0])
continue; // edge has allready been removed continue; // edge has allready been removed
@ -225,7 +225,7 @@ GrowNodeRegion_r (node_t * node)
RecursiveGrowRegion (r, f); RecursiveGrowRegion (r, f);
#endif #endif
r.firstedge = firstedge = bsp->numsurfedges; r.firstedge = firstedge = bsp->numsurfedges;
for (i = 0; i < f->numpoints; i++) { for (i = 0; i < f->points->numpoints; i++) {
if (bsp->numsurfedges == MAX_MAP_SURFEDGES) if (bsp->numsurfedges == MAX_MAP_SURFEDGES)
Sys_Error ("numsurfedges == MAX_MAP_SURFEDGES"); Sys_Error ("numsurfedges == MAX_MAP_SURFEDGES");
BSP_AddSurfEdge (bsp, f->edges[i]); BSP_AddSurfEdge (bsp, f->edges[i]);

View File

@ -53,12 +53,13 @@ FaceSide (face_t *in, plane_t *split)
int frontcount, backcount, i; int frontcount, backcount, i;
vec_t dot; vec_t dot;
vec_t *p; vec_t *p;
winding_t *inp = in->points;
frontcount = backcount = 0; frontcount = backcount = 0;
// axial planes are fast // axial planes are fast
if (split->type < 3) if (split->type < 3)
for (i = 0, p = in->pts[0] + split->type; i < in->numpoints; for (i = 0, p = inp->points[0] + split->type; i < inp->numpoints;
i++, p += 3) { i++, p += 3) {
if (*p > split->dist + ON_EPSILON) { if (*p > split->dist + ON_EPSILON) {
if (backcount) if (backcount)
@ -71,7 +72,7 @@ FaceSide (face_t *in, plane_t *split)
} }
} else } else
// sloping planes take longer // sloping planes take longer
for (i = 0, p = in->pts[0]; i < in->numpoints; i++, p += 3) { for (i = 0, p = inp->points[0]; i < inp->numpoints; i++, p += 3) {
dot = DotProduct (p, split->normal); dot = DotProduct (p, split->normal);
dot -= split->dist; dot -= split->dist;
if (dot > ON_EPSILON) { if (dot > ON_EPSILON) {
@ -334,14 +335,15 @@ CalcSurfaceInfo (surface_t * surf)
} }
for (f = surf->faces; f; f = f->next) { for (f = surf->faces; f; f = f->next) {
winding_t *fp = f->points;
if (f->contents[0] >= 0 || f->contents[1] >= 0) if (f->contents[0] >= 0 || f->contents[1] >= 0)
Sys_Error ("Bad contents"); Sys_Error ("Bad contents");
for (i = 0; i < f->numpoints; i++) for (i = 0; i < fp->numpoints; i++)
for (j = 0; j < 3; j++) { for (j = 0; j < 3; j++) {
if (f->pts[i][j] < surf->mins[j]) if (fp->points[i][j] < surf->mins[j])
surf->mins[j] = f->pts[i][j]; surf->mins[j] = fp->points[i][j];
if (f->pts[i][j] > surf->maxs[j]) if (fp->points[i][j] > surf->maxs[j])
surf->maxs[j] = f->pts[i][j]; surf->maxs[j] = fp->points[i][j];
} }
} }
} }
@ -583,6 +585,7 @@ LinkNodeFaces (surface_t *surface)
nodefaces++; nodefaces++;
new = AllocFace (); new = AllocFace ();
*new = *f; *new = *f;
new->points = CopyWinding (f->points);
f->original = new; f->original = new;
new->next = list; new->next = list;
list = new; list = new;

View File

@ -75,8 +75,8 @@ SubdivideFace (face_t *f, face_t **prevptr)
mins = BOGUS_RANGE; mins = BOGUS_RANGE;
maxs = -BOGUS_RANGE; maxs = -BOGUS_RANGE;
for (i = 0; i < f->numpoints; i++) { for (i = 0; i < f->points->numpoints; i++) {
v = DotProduct (f->pts[i], tex->vecs[axis]); v = DotProduct (f->points->points[i], tex->vecs[axis]);
if (v < mins) if (v < mins)
mins = v; mins = v;
if (v > maxs) if (v > maxs)
@ -146,7 +146,7 @@ GatherNodeFaces_r (node_t *node)
// decision node // decision node
for (f = node->faces; f; f = next) { for (f = node->faces; f; f = next) {
next = f->next; next = f->next;
if (!f->numpoints) { // face was removed outside if (!f->points) { // face was removed outside
FreeFace (f); FreeFace (f);
} else { } else {
f->next = validfaces[f->planenum]; f->next = validfaces[f->planenum];
@ -349,14 +349,15 @@ static void
FindFaceEdges (face_t *face) FindFaceEdges (face_t *face)
{ {
int i; int i;
winding_t *facep = face->points;
face->outputnumber = -1; face->outputnumber = -1;
if (face->numpoints > MAXEDGES) face->edges = malloc (sizeof (int) * facep->numpoints);
Sys_Error ("WriteFace: %i points", face->numpoints);
for (i = 0; i < face->numpoints; i++) for (i = 0; i < facep->numpoints; i++)
face->edges[i] = GetEdge face->edges[i] = GetEdge (facep->points[i],
(face->pts[i], face->pts[(i + 1) % face->numpoints], face); facep->points[(i + 1) % facep->numpoints],
face);
} }
static void static void

View File

@ -30,6 +30,8 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "QF/sys.h" #include "QF/sys.h"
#include "compat.h"
#include "bsp5.h" #include "bsp5.h"
#include "options.h" #include "options.h"
@ -236,118 +238,28 @@ AddFaceEdges (face_t *f)
{ {
int i, j; int i, j;
for (i = 0; i < f->numpoints; i++) { for (i = 0; i < f->points->numpoints; i++) {
j = (i + 1) % f->numpoints; j = (i + 1) % f->points->numpoints;
AddEdge (f->pts[i], f->pts[j]); AddEdge (f->points->points[i], f->points->points[j]);
} }
} }
// a specially allocated face that can hold hundreds of edges if needed
byte superfacebuf[8192];
face_t *superface = (face_t *) superfacebuf;
void FixFaceEdges (face_t * f);
face_t *newlist; face_t *newlist;
static void static void
SplitFaceForTjunc (face_t *f, face_t *original)
{
face_t *new, *chain;
int firstcorner, lastcorner, i;
vec3_t dir, test;
vec_t v;
chain = NULL;
do {
if (f->numpoints <= MAXPOINTS) {
// the face is now small enough without more cutting so copy it
// back to the original
*original = *f;
original->original = chain;
original->next = newlist;
newlist = original;
return;
}
tjuncfaces++;
restart:
// find the last corner
VectorSubtract (f->pts[f->numpoints - 1], f->pts[0], dir);
_VectorNormalize (dir);
for (lastcorner = f->numpoints - 1; lastcorner > 0; lastcorner--) {
VectorSubtract (f->pts[lastcorner - 1], f->pts[lastcorner], test);
_VectorNormalize (test);
v = DotProduct (test, dir);
if (v < 0.9999 || v > 1.00001)
break;
}
// find the first corner
VectorSubtract (f->pts[1], f->pts[0], dir);
_VectorNormalize (dir);
for (firstcorner = 1; firstcorner < f->numpoints - 1; firstcorner++) {
VectorSubtract (f->pts[firstcorner + 1], f->pts[firstcorner],
test);
_VectorNormalize (test);
v = DotProduct (test, dir);
if (v < 0.9999 || v > 1.00001)
break;
}
if (firstcorner + 2 >= MAXPOINTS) {
// rotate the point winding
VectorCopy (f->pts[0], test);
for (i = 1; i < f->numpoints; i++)
VectorCopy (f->pts[i], f->pts[i - 1]);
VectorCopy (test, f->pts[f->numpoints - 1]);
goto restart;
}
// cut off as big a piece as possible, less than MAXPOINTS, and not
// past lastcorner
new = NewFaceFromFace (f);
if (f->original)
Sys_Error ("SplitFaceForTjunc: f->original");
new->original = chain;
chain = new;
new->next = newlist;
newlist = new;
if (f->numpoints - firstcorner <= MAXPOINTS)
new->numpoints = firstcorner + 2;
else if (lastcorner + 2 < MAXPOINTS &&
f->numpoints - lastcorner <= MAXPOINTS)
new->numpoints = lastcorner + 2;
else
new->numpoints = MAXPOINTS;
for (i = 0; i < new->numpoints; i++)
VectorCopy (f->pts[i], new->pts[i]);
for (i = new->numpoints - 1; i < f->numpoints; i++)
VectorCopy (f->pts[i], f->pts[i - (new->numpoints - 2)]);
f->numpoints -= (new->numpoints - 2);
} while (1);
}
void
FixFaceEdges (face_t *f) FixFaceEdges (face_t *f)
{ {
int i, j, k; int i, j, k;
vec_t t1, t2; vec_t t1, t2;
wedge_t *w; wedge_t *w;
winding_t *fp = f->points;
wvert_t *v; wvert_t *v;
*superface = *f;
restart: restart:
for (i = 0; i < superface->numpoints; i++) { for (i = 0; i < fp->numpoints; i++) {
j = (i + 1) % superface->numpoints; j = (i + 1) % fp->numpoints;
w = FindEdge (superface->pts[i], superface->pts[j], &t1, &t2); w = FindEdge (fp->points[i], fp->points[j], &t1, &t2);
for (v = w->head.next; v->t < t1 + T_EPSILON; v = v->next) { for (v = w->head.next; v->t < t1 + T_EPSILON; v = v->next) {
} }
@ -355,25 +267,20 @@ FixFaceEdges (face_t *f)
if (v->t < t2 - T_EPSILON) { if (v->t < t2 - T_EPSILON) {
tjuncs++; tjuncs++;
// insert a new vertex here // insert a new vertex here
for (k = superface->numpoints; k > j; k--) { fp = realloc (fp, field_offset (winding_t,
VectorCopy (superface->pts[k - 1], superface->pts[k]); points[fp->numpoints + 1]));
for (k = fp->numpoints; k > j; k--) {
VectorCopy (fp->points[k - 1], fp->points[k]);
} }
VectorMultAdd (w->origin, v->t, w->dir, superface->pts[j]); VectorMultAdd (w->origin, v->t, w->dir, fp->points[j]);
superface->numpoints++; fp->numpoints++;
goto restart; goto restart;
} }
} }
f->points = fp;
f->next = newlist;
if (superface->numpoints <= MAXPOINTS) { newlist = f;
*f = *superface;
f->next = newlist;
newlist = f;
return;
}
// the face needs to be split into multiple faces because of too many edges
SplitFaceForTjunc (superface, f);
} }
//============================================================================ //============================================================================