// AJM: MVD // ===================================================================================== // ClipWindingsToBounds // clips all the windings with all the planes (including original face) and outputs // what's left int "out" // ===================================================================================== static void ClipWindingsToBounds(winding_t *windings, int numwindings, plane_t *bounds, int numbounds, plane_t &original_plane, winding_t **out, int &num_out) { hlassert(windings); hlassert(bounds); winding_t out_windings[MAX_PORTALS_ON_LEAF]; num_out = 0; int h, i; *out = NULL; Winding wind; for(h = 0; h < numwindings; h++) { // For each winding... // Create a winding with CWinding wind.initFromPoints(windings[h].points, windings[h].numpoints); // Clip winding to original plane wind.Chop(original_plane.normal, original_plane.dist); for(i = 0; i < numbounds, wind.Valid(); i++) { // For each bound... // Chop the winding to the bounds wind.Chop(bounds[i].normal, bounds[i].dist); } if(wind.Valid()) { // We have a valid winding, copy to array wind.CopyPoints(&out_windings[num_out].points[0], out_windings[num_out].numpoints); num_out++; } } if(!num_out) // Everything was clipped away return; // Otherwise, create out *out = new winding_t[num_out]; memcpy(*out, out_windings, num_out * sizeof(winding_t)); }
// AJM: MVD // ===================================================================================== // GetPortalBounds // This function take a portal and finds its bounds // parallel to the normal of the portal. They will face inwards // ===================================================================================== static void GetPortalBounds(portal_t *p, plane_t **bounds) { int i; vec3_t vec1, vec2; hlassert(p->winding->numpoints >= 3); if(*bounds) delete [] *bounds; *bounds = new plane_t[p->winding->numpoints]; // Loop through each set of points and create a plane boundary for each for(i = 0; i < p->winding->numpoints; i++) { VectorSubtract(p->winding->points[(i + 1) % p->winding->numpoints],p->winding->points[i],vec1); // Create inward normal for this boundary CrossProduct(p->plane.normal, vec1, vec2); VectorNormalize(vec2); VectorCopy(vec2, (*bounds)[i].normal); (*bounds)[i].dist = DotProduct(p->winding->points[i], vec2); } }
// ===================================================================================== // CheckFatal // ===================================================================================== void CheckFatal() { if (fatal) { hlassert(false); exit(1); } }
Winding::Winding(UINT32 numpoints) { hlassert(numpoints >= 3); m_NumPoints = numpoints; m_MaxPoints = (m_NumPoints + 3) & ~3; // groups of 4 m_Points = new vec3_t[m_MaxPoints]; memset(m_Points, 0, sizeof(vec3_t) * m_NumPoints); }
// AJM: MVD // ===================================================================================== // MakeSplitPortalList // This function returns a portal on leaf1 that sucessfully seperates leaf1 // and leaf2 // ===================================================================================== static void MakeSplitPortalList(leaf_t *leaf1, leaf_t *leaf2, portal_t **portals, int *num_portals) { int i, k, l; portal_t *p1; portal_t *t; *num_portals = 0; float check_dist; portal_t p_list[MAX_PORTALS_ON_LEAF]; int c_portal = 0; if(*portals) delete [] *portals; for(i = 0, p1 = leaf1->portals[0]; i < leaf1->numportals; i++, p1++) { hlassert(p1->winding->numpoints >= 3); // Check to make sure all the points on the other leaf are in front of the portal plane for(k = 0, t = leaf2->portals[0]; k < leaf2->numportals; k++, t++) { for(l = 0; l < t->winding->numpoints; l++) { check_dist = DotProduct(t->winding->points[l], p1->plane.normal) - p1->plane.dist; // We make the assumption that all portals face away from their parent leaf if(check_dist < -ON_EPSILON) goto PostLoop; } } PostLoop: // If we didn't check all the leaf2 portals, then this leaf1 portal doesn't work if(k < leaf2->numportals) continue; // If we reach this point, we found a good portal memcpy(&p_list[c_portal++], p1, sizeof(portal_t)); if(c_portal >= MAX_PORTALS_ON_LEAF) Error("c_portal > MAX_PORTALS_ON_LEAF"); } if(!c_portal) return; *num_portals = c_portal; *portals = new portal_t[c_portal]; memcpy(*portals, p_list, c_portal * sizeof(portal_t)); }
static void AddFaceToList(bface_t** head, bface_t* newface) { hlassert(newface); hlassert(newface->w); if (!*head) { *head = newface; return; } else { bface_t* node = *head; while (node->next) { node = node->next; } node->next = newface; newface->next = NULL; } }
void Winding::initFromPoints(vec3_t *points, UINT32 numpoints) { hlassert(numpoints >= 3); Reset(); m_NumPoints = numpoints; m_MaxPoints = (m_NumPoints + 3) & ~3; // groups of 4 m_Points = new vec3_t[m_MaxPoints]; memcpy(m_Points, points, sizeof(vec3_t) * m_NumPoints); }
// AJM: MVD // ===================================================================================== // GetSplitPortal // This function returns a portal on leaf1 that sucessfully seperates leaf1 // and leaf2 // ===================================================================================== static portal_t *GetSplitPortal(leaf_t *leaf1, leaf_t *leaf2) { int i, k, l; portal_t *p1; portal_t *t; float check_dist; for(i = 0, p1 = leaf1->portals[0]; i < leaf1->numportals; i++, p1++) { hlassert(p1->winding->numpoints >= 3); // Check to make sure all the points on the other leaf are in front of the portal plane for(k = 0, t = leaf2->portals[0]; k < leaf2->numportals; k++, t++) { for(l = 0; l < t->winding->numpoints; l++) { check_dist = DotProduct(t->winding->points[l], p1->plane.normal) - p1->plane.dist; // We make the assumption that all portals face away from their parent leaf if(check_dist < -ON_EPSILON) goto PostLoop; } } PostLoop: // If we didn't check all the leaf2 portals, then this leaf1 portal doesn't work if(k < leaf2->numportals) continue; // If we reach this point, we found a good portal return p1; } // Didn't find any return NULL; }
// ===================================================================================== // GetEdge // Don't allow four way edges // ===================================================================================== int GetEdge(const vec3_t p1, const vec3_t p2, face_t* f) { int v1; int v2; dedge_t* edge; int i; hlassert(f->contents); v1 = GetVertex(p1, f->planenum); v2 = GetVertex(p2, f->planenum); for (i = firstmodeledge; i < g_numedges; i++) { edge = &g_dedges[i]; if (v1 == edge->v[1] && v2 == edge->v[0] && !edgefaces[i][1] && edgefaces[i][0]->contents == f->contents #ifdef HLBSP_EDGESHARE_SAMESIDE && edgefaces[i][0]->planenum != (f->planenum ^ 1) && edgefaces[i][0]->contents == f->contents #endif ) { edgefaces[i][1] = f; return -i; } } // emit an edge hlassume(g_numedges < MAX_MAP_EDGES, assume_MAX_MAP_EDGES); edge = &g_dedges[g_numedges]; g_numedges++; edge->v[0] = v1; edge->v[1] = v2; edgefaces[i][0] = f; return i; }
// Returns false if union of brushes is obviously zero static void AddPlaneToUnion(brushhull_t* hull, const int planenum) { bool need_new_face = false; bface_t* new_face_list; bface_t* face; bface_t* next; plane_t* split; Winding* front; Winding* back; new_face_list = NULL; next = NULL; hlassert(hull); if (!hull->faces) { return; } hlassert(hull->faces->w); for (face = hull->faces; face; face = next) { hlassert(face->w); next = face->next; // Duplicate plane, ignore if (face->planenum == planenum) { AddFaceToList(&new_face_list, CopyFace(face)); continue; } split = &g_mapplanes[planenum]; face->w->Clip(split->normal, split->dist, &front, &back); if (front) { delete front; need_new_face = true; if (back) { // Intersected the face delete face->w; face->w = back; AddFaceToList(&new_face_list, CopyFace(face)); } } else { // Completely missed it, back is identical to face->w so it is destroyed if (back) { delete back; AddFaceToList(&new_face_list, CopyFace(face)); } } hlassert(face->w); } FreeFaceList(hull->faces); hull->faces = new_face_list; if (need_new_face && (NumberOfHullFaces(hull) > 2)) { Winding* new_winding = NewWindingFromPlane(hull, planenum); if (new_winding) { bface_t* new_face = (bface_t*)Alloc(sizeof(bface_t)); new_face->planenum = planenum; new_face->w = new_winding; new_face->next = hull->faces; hull->faces = new_face; } } }