static Winding* NewWindingFromPlane(const brushhull_t* const hull, const int planenum) { Winding* winding; Winding* front; Winding* back; bface_t* face; plane_t* plane; plane = &g_mapplanes[planenum]; winding = new Winding(plane->normal, plane->dist); for (face = hull->faces; face; face = face->next) { plane = &g_mapplanes[face->planenum]; winding->Clip(plane->normal, plane->dist, &front, &back); delete winding; if (front) { delete front; } if (back) { winding = back; } else { Developer(DEVELOPER_LEVEL_ERROR, "NewFaceFromPlane returning NULL"); return NULL; } } return winding; }
// ===================================================================================== // GetAlternateOrigin // ===================================================================================== void GetAlternateOrigin (const vec3_t pos, const vec3_t normal, const patch_t *patch, vec3_t &origin) { const dplane_t *faceplane; const vec_t *faceplaneoffset; const vec_t *facenormal; dplane_t clipplane; Winding w; faceplane = getPlaneFromFaceNumber (patch->faceNumber); faceplaneoffset = g_face_offset[patch->faceNumber]; facenormal = faceplane->normal; VectorCopy (normal, clipplane.normal); clipplane.dist = DotProduct (pos, clipplane.normal); w = *patch->winding; if (w.WindingOnPlaneSide (clipplane.normal, clipplane.dist) != SIDE_CROSS) { VectorCopy (patch->origin, origin); } else { w.Clip (clipplane, false); if (w.m_NumPoints == 0) { VectorCopy (patch->origin, origin); } else { vec3_t center; bool found; vec3_t bestpoint; vec_t bestdist = -1.0; vec3_t point; vec_t dist; vec3_t v; w.getCenter (center); found = false; VectorMA (center, PATCH_HUNT_OFFSET, facenormal, point); if (HuntForWorld (point, faceplaneoffset, faceplane, 2, 1.0, PATCH_HUNT_OFFSET)) { VectorSubtract (point, center, v); dist = VectorLength (v); if (!found || dist < bestdist) { found = true; VectorCopy (point, bestpoint); bestdist = dist; } } if (!found) { for (int i = 0; i < w.m_NumPoints; i++) { const vec_t *p1; const vec_t *p2; p1 = w.m_Points[i]; p2 = w.m_Points[(i + 1) % w.m_NumPoints]; VectorAdd (p1, p2, point); VectorAdd (point, center, point); VectorScale (point, 1.0/3.0, point); VectorMA (point, PATCH_HUNT_OFFSET, facenormal, point); if (HuntForWorld (point, faceplaneoffset, faceplane, 1, 0.0, PATCH_HUNT_OFFSET)) { VectorSubtract (point, center, v); dist = VectorLength (v); if (!found || dist < bestdist) { found = true; VectorCopy (point, bestpoint); bestdist = dist; } } } } if (found) { VectorCopy (bestpoint, origin); } else { VectorCopy (patch->origin, origin); } } } }
// ===================================================================================== // snap_to_winding_noedge // first snaps the point into the winding // then moves the point towards the inside for at most certain distance until: // either 1) the point is not close to any of the edges // or 2) the point can not be moved any more // returns the maximal distance that the point can be kept away from all the edges // in most of the cases, the maximal distance = width; in other cases, the maximal distance < width // ===================================================================================== vec_t snap_to_winding_noedge(const Winding& w, const dplane_t& plane, vec_t* const point, vec_t width, vec_t maxmove) { int pass; int numplanes; dplane_t *planes; int x; vec3_t v; vec_t newwidth; vec_t bestwidth; vec3_t bestpoint; snap_to_winding (w, plane, point); planes = (dplane_t *)malloc (w.m_NumPoints * sizeof (dplane_t)); hlassume (planes != NULL, assume_NoMemory); numplanes = 0; for (x = 0; x < w.m_NumPoints; x++) { VectorSubtract (w.m_Points[(x + 1) % w.m_NumPoints], w.m_Points[x], v); CrossProduct (v, plane.normal, planes[numplanes].normal); if (!VectorNormalize (planes[numplanes].normal)) { continue; } planes[numplanes].dist = DotProduct (w.m_Points[x], planes[numplanes].normal); numplanes++; } bestwidth = 0; VectorCopy (point, bestpoint); newwidth = width; for (pass = 0; pass < 5; pass++) // apply binary search method for 5 iterations to find the maximal distance that the point can be kept away from all the edges { bool failed; vec3_t newpoint; Winding *newwinding; failed = true; newwinding = new Winding (w); for (x = 0; x < numplanes && newwinding->m_NumPoints > 0; x++) { dplane_t clipplane = planes[x]; clipplane.dist += newwidth; newwinding->Clip (clipplane, false); } if (newwinding->m_NumPoints > 0) { VectorCopy (point, newpoint); snap_to_winding (*newwinding, plane, newpoint); VectorSubtract (newpoint, point, v); if (VectorLength (v) <= maxmove + ON_EPSILON) { failed = false; } } delete newwinding; if (!failed) { bestwidth = newwidth; VectorCopy (newpoint, bestpoint); if (pass == 0) { break; } newwidth += width * pow (0.5, pass + 1); } else { newwidth -= width * pow (0.5, pass + 1); } } free (planes); VectorCopy (bestpoint, point); return bestwidth; }