void AddHullEdge (expand_t *ex, vec3_t p1, vec3_t p2) { int pt1, pt2; int i; int a, b, c, d, e; vec3_t edgevec, planeorg, planevec; plane_t plane; vec_t l; pt1 = AddHullPoint (ex, p1); pt2 = AddHullPoint (ex, p2); // now use the rounded values p1 = ex->hull_points[pt1]; p2 = ex->hull_points[pt2]; for (i=0 ; i<ex->num_hull_edges ; i++) if ( (ex->hull_edges[i][0] == pt1 && ex->hull_edges[i][1] == pt2) || (ex->hull_edges[i][0] == pt2 && ex->hull_edges[i][1] == pt1) ) return; // allread added if (ex->num_hull_edges == MAX_HULL_EDGES) Error ("MAX_HULL_EDGES"); ex->hull_edges[i][0] = pt1; ex->hull_edges[i][1] = pt2; ex->num_hull_edges++; VectorSubtract (p1, p2, edgevec); VectorNormalize (edgevec); for (a=0 ; a<3 ; a++) { b = (a+1)%3; c = (a+2)%3; for (d=0 ; d<=1 ; d++) for (e=0 ; e<=1 ; e++) { VectorCopy (p1, plane.iorigin); plane.iorigin[b] += hull_size[ex->hullnum][d][b]; plane.iorigin[c] += hull_size[ex->hullnum][e][c]; VectorCopy (vec3_origin, planevec); planevec[a] = 1; plane.inormal[0] = planevec[1]*edgevec[2] - planevec[2]*edgevec[1]; plane.inormal[1] = planevec[2]*edgevec[0] - planevec[0]*edgevec[2]; plane.inormal[2] = planevec[0]*edgevec[1] - planevec[1]*edgevec[0]; if (!plane.inormal[0] && !plane.inormal[1] && !plane.inormal[2]) continue; // degenerate TestAddPlane (ex, &plane); } } }
/* ============ AddHullEdge Creates all of the hull planes around the given edge, if not done allready ============= */ void AddHullEdge (vec3_t p1, vec3_t p2, int hullnum) { int pt1, pt2; int i; int a, b, c, d, e; vec3_t edgevec, planeorg, planevec; plane_t plane; vec_t length; pt1 = AddHullPoint (p1, hullnum); pt2 = AddHullPoint (p2, hullnum); for (i=0 ; i<num_hull_edges ; i++) if ((hull_edges[i][0] == pt1 && hull_edges[i][1] == pt2) || (hull_edges[i][0] == pt2 && hull_edges[i][1] == pt1)) return; // already added if (num_hull_edges == MAX_HULL_EDGES) Error ("AddHullEdge: MAX_HULL_EDGES"); hull_edges[num_hull_edges][0] = pt1; hull_edges[num_hull_edges][1] = pt2; num_hull_edges++; VectorSubtract(p1, p2, edgevec); VectorNormalize(edgevec); for (a=0 ; a<3 ; a++) { b = (a+1)%3; c = (a+2)%3; planevec[a] = 1; planevec[b] = 0; planevec[c] = 0; CrossProduct(planevec, edgevec, plane.normal); length = VectorNormalize(plane.normal); /* If this edge is almost parallel to the hull edge, skip it. */ if (length < ANGLE_EPSILON) continue; for (d = 0 ; d < 2 ; d++) { for (e = 0 ; e < 2 ; e++) { VectorCopy(p1, planeorg); planeorg[b] -= hullinfo.hullsizes[hullnum][d^1][b]; planeorg[c] -= hullinfo.hullsizes[hullnum][e^1][c]; plane.dist = DotProduct(planeorg, plane.normal); TestAddPlane(&plane); } } } }
/* ============ AddHullEdge Creates all of the hull planes around the given edge, if not done allready ============= */ void AddHullEdge (vec3_t p1, vec3_t p2, int hullnum) { int pt1, pt2; int i; int a, b, c, d, e; vec3_t edgevec, planeorg, planevec; plane_t plane; vec_t l; pt1 = AddHullPoint (p1, hullnum); pt2 = AddHullPoint (p2, hullnum); for (i=0 ; i<num_hull_edges ; i++) if ( (hull_edges[i][0] == pt1 && hull_edges[i][1] == pt2) || (hull_edges[i][0] == pt2 && hull_edges[i][1] == pt1) ) return; // allread added if (num_hull_edges == MAX_HULL_EDGES) Error ("MAX_HULL_EDGES"); hull_edges[i][0] = pt1; hull_edges[i][1] = pt2; num_hull_edges++; VectorSubtract (p1, p2, edgevec); VectorNormalize (edgevec); for (a=0 ; a<3 ; a++) { b = (a+1)%3; c = (a+2)%3; for (d=0 ; d<=1 ; d++) for (e=0 ; e<=1 ; e++) { VectorCopy (p1, planeorg); planeorg[b] += hull_size[hullnum][d][b]; planeorg[c] += hull_size[hullnum][e][c]; VectorCopy (vec3_origin, planevec); planevec[a] = 1; CrossProduct (planevec, edgevec, plane.normal); l = VectorLength (plane.normal); if (l < 1-ANGLEEPSILON || l > 1+ANGLEEPSILON) continue; plane.dist = DotProduct (planeorg, plane.normal); TestAddPlane (&plane); } } }
/* ============ ExpandBrush ============= */ void ExpandBrush (int hullindex) { int i, x, s; vec3_t corner; face_t *f; plane_t plane, *p; num_hull_points = 0; num_hull_edges = 0; // create all the hull points for (f=brush_faces ; f ; f=f->next) for (i=0 ; i<f->numpoints ; i++) AddHullPoint (f->pts[i], hullindex); // expand all of the planes for (i=0 ; i<numbrushfaces ; i++) { p = &faces[i].plane; VectorCopy (vec3_origin, corner); for (x=0 ; x<3 ; x++) { if (p->normal[x] > 0) corner[x] = ExpandSize (hullindex, 1, x); else if (p->normal[x] < 0) corner[x] = ExpandSize (hullindex, 0, x); } p->dist += DotProduct (corner, p->normal); } // add any axis planes not contained in the brush to bevel off corners for (x=0 ; x<3 ; x++) for (s=-1 ; s<=1 ; s+=2) { // add the plane VectorCopy (vec3_origin, plane.normal); plane.normal[x] = s; if (s == -1) plane.dist = -brush_mins[x] - ExpandSize (hullindex, 0, x); else plane.dist = brush_maxs[x] + ExpandSize (hullindex, 1, x); AddBrushPlane (&plane, hullnum); } // add all of the edge bevels for (f=brush_faces ; f ; f=f->next) for (i=0 ; i<f->numpoints ; i++) AddHullEdge (f->pts[i], f->pts[(i+1)%f->numpoints], hullindex); }
/* ============ ExpandBrush ============= */ void ExpandBrush (brush_t *b, int hullnum) { int i, x, s; int corner; bface_t *brush_faces, *f, *nf; plane_t *p, plane; int iorigin[3], inormal[3]; expand_t ex; brushhull_t *h; qboolean axial; brush_faces = b->hulls[0].faces; h = &b->hulls[hullnum]; ex.b = b; ex.hullnum = hullnum; ex.num_hull_points = 0; ex.num_hull_edges = 0; // expand all of the planes axial = true; for (f=brush_faces ; f ; f=f->next) { p = f->plane; if (p->type > PLANE_Z) axial = false; // not an xyz axial plane VectorCopy (p->iorigin, iorigin); VectorCopy (p->inormal, inormal); for (x=0 ; x<3 ; x++) { if (p->normal[x] > 0) corner = hull_size[hullnum][1][x]; else if (p->normal[x] < 0) corner = - hull_size[hullnum][0][x]; else corner = 0; iorigin[x] += p->normal[x]*corner; } nf = malloc(sizeof(*nf)); memset (nf, 0, sizeof(*nf)); nf->planenum = FindIntPlane (inormal, iorigin); nf->plane = &mapplanes[nf->planenum]; nf->next = h->faces; nf->contents = CONTENTS_EMPTY; h->faces = nf; nf->texinfo = 0; // all clip hulls have same texture } // if this was an axial brush, we are done if (axial) return; #if 1 // add any axis planes not contained in the brush to bevel off corners for (x=0 ; x<3 ; x++) for (s=-1 ; s<=1 ; s+=2) { // add the plane VectorCopy (vec3_origin, plane.inormal); plane.inormal[x] = s; if (s == -1) { VectorAdd (b->hulls[0].mins, hull_size[hullnum][0], plane.iorigin); } else { VectorAdd (b->hulls[0].maxs, hull_size[hullnum][1], plane.iorigin); } AddBrushPlane (&ex, &plane); } #endif #if 0 // create all the hull points for (f=brush_faces ; f ; f=f->next) for (i=0 ; i<f->w->numpoints ; i++) AddHullPoint (&ex, f->w->p[i]); // add all of the edge bevels for (f=brush_faces ; f ; f=f->next) for (i=0 ; i<f->w->numpoints ; i++) AddHullEdge (&ex, f->w->p[i], f->w->p[(i+1)%f->w->numpoints]); #endif }
/* ============ ExpandBrush ============= */ void ExpandBrush (int hullnum) { int i, x, s; vec3_t corner; winding_t *w; plane_t plane; int j, k, numwindings; vec_t r; winding_t **windings; plane_t clipplane, faceplane; mface_t *mf; vec3_t point; vec3_t mins, maxs; if (!numbrushfaces) return; num_hull_points = 0; num_hull_edges = 0; ClearBounds( mins, maxs ); // generate windings and bounds data numwindings = 0; windings = calloc(numbrushfaces, sizeof(*windings)); for (i = 0;i < numbrushfaces;i++) { mf = &faces[i]; windings[i] = NULL; faceplane = mf->plane; w = BaseWindingForPlane (&faceplane); for (j = 0;j < numbrushfaces && w;j++) { clipplane = faces[j].plane; if( j == i ) continue; // flip the plane, because we want to keep the back side VectorNegate(clipplane.normal, clipplane.normal); clipplane.dist *= -1; w = ClipWindingEpsilon (w, &clipplane, ON_EPSILON, true); } if (!w) continue; // overcontrained plane for (j = 0;j < w->numpoints;j++) { for (k = 0;k < 3;k++) { point[k] = w->points[j][k]; r = Q_rint( point[k] ); if ( fabs( point[k] - r ) < ZERO_EPSILON) w->points[j][k] = r; else w->points[j][k] = point[k]; // check for incomplete brushes if( w->points[j][k] >= BOGUS_RANGE || w->points[j][k] <= -BOGUS_RANGE ) return; } AddPointToBounds( w->points[j], mins, maxs ); } windings[i] = w; } // add all of the corner offsets for (i = 0;i < numwindings;i++) { w = windings[i]; for (j = 0;j < w->numpoints;j++) AddHullPoint(w->points[j], hullnum); } // expand the face planes for (i = 0;i < numbrushfaces;i++) { mf = &faces[i]; for (x=0 ; x<3 ; x++) { if (mf->plane.normal[x] > 0) corner[x] = -hullinfo.hullsizes[hullnum][0][x]; else if (mf->plane.normal[x] < 0) corner[x] = -hullinfo.hullsizes[hullnum][1][x]; } mf->plane.dist += DotProduct (corner, mf->plane.normal); } // add any axis planes not contained in the brush to bevel off corners for (x=0 ; x<3 ; x++) for (s=-1 ; s<=1 ; s+=2) { // add the plane VectorClear (plane.normal); plane.normal[x] = s; if (s == -1) plane.dist = -mins[x] + hullinfo.hullsizes[hullnum][1][x]; else plane.dist = maxs[x] + -hullinfo.hullsizes[hullnum][0][x]; AddBrushPlane (&plane); } // add all of the edge bevels for (i = 0;i < numwindings;i++) { w = windings[i]; for (j = 0;j < w->numpoints;j++) AddHullEdge(w->points[j], w->points[(j+1)%w->numpoints], hullnum); } // free the windings as we no longer need them for (i = 0;i < numwindings;i++) if (windings[i]) FreeWinding(windings[i]); free(windings); }
/* ============ AddHullEdge Creates all of the hull planes around the given edge, if not done allready ============= */ void AddHullEdge (vec3_t p1, vec3_t p2, int hullnum) { int pt1, pt2; int i; int a, b, c, d, e; vec3_t edgevec, planeorg, planevec; plane_t plane; vec_t l; pt1 = AddHullPoint (p1, hullnum); pt2 = AddHullPoint (p2, hullnum); for (i=0 ; i<num_hull_edges ; i++) if ( (hull_edges[i][0] == pt1 && hull_edges[i][1] == pt2) || (hull_edges[i][0] == pt2 && hull_edges[i][1] == pt1) ) return; // allread added if (num_hull_edges == MAX_HULL_EDGES) Message (MSGERR, "MAX_HULL_EDGES (%d) exceeded", MAX_HULL_EDGES); hull_edges[i][0] = pt1; hull_edges[i][1] = pt2; num_hull_edges++; VectorSubtract (p1, p2, edgevec); VectorNormalize (edgevec); for (a=0 ; a<3 ; a++) { VectorCopy (vec3_origin, planevec); planevec[a] = 1; CrossProduct (planevec, edgevec, plane.normal); l = VectorLength (plane.normal); if (options.OldExpand) { if (l < 1-ANGLEEPSILON || l > 1+ANGLEEPSILON) continue; } else { // If this edge is almost parallel to the hull edge, skip it if (l < ANGLEEPSILON) continue; VectorScale (plane.normal, 1 / l, plane.normal); } b = (a+1)%3; c = (a+2)%3; for (d=0 ; d<=1 ; d++) for (e=0 ; e<=1 ; e++) { VectorCopy (p1, planeorg); planeorg[b] += ExpandSize (hullnum, d, b); planeorg[c] += ExpandSize (hullnum, e, c); plane.dist = DotProduct (planeorg, plane.normal); TestAddPlane (&plane); } } }