/* ================ CutNodePortals_r ================ */ static void CutNodePortals_r (node_t *node) { plane_t *plane, clipplane; node_t *f, *b, *other_node; portal_t *p, *new_portal, *next_portal; winding_t *w, *frontwinding, *backwinding; int side; // Vic: properly calculate the bounding box CalcNodeBounds (node); // // separate the portals on node into it's children // if (node->contents) return; // at a leaf, no more dividing plane = &mapplanes[node->planenum]; f = node->children[0]; b = node->children[1]; // // create the new portal by taking the full plane winding for the cutting plane // and clipping it by all of the planes from the other portals // w = BaseWindingForPlane (&mapplanes[node->planenum]); side = 0; // shut up compiler warning for (p = node->portals ; p ; p = p->next[side]) { clipplane = mapplanes[p->planenum]; if (p->nodes[0] == node) side = 0; else if (p->nodes[1] == node) { clipplane.dist = -clipplane.dist; VectorNegate (clipplane.normal, clipplane.normal); side = 1; } else Error ("CutNodePortals_r: mislinked portal"); w = ClipWinding (w, &clipplane, true); if (!w) { printf ("WARNING: CutNodePortals_r:new portal was clipped away\n"); break; } } if (w) { // if the plane was not clipped on all sides, there was an error new_portal = AllocPortal (); new_portal->planenum = node->planenum; new_portal->winding = w; AddPortalToNodes (new_portal, f, b); } // partition the portals for (p = node->portals ; p ; p = next_portal) { if (p->nodes[0] == node) side = 0; else if (p->nodes[1] == node) side = 1; else Error ("CutNodePortals_r: mislinked portal"); next_portal = p->next[side]; other_node = p->nodes[!side]; RemovePortalFromNode (p, p->nodes[0]); RemovePortalFromNode (p, p->nodes[1]); // cut the portal into two portals, one on each side of the cut plane DivideWindingEpsilon( p->winding, plane, &frontwinding, &backwinding, ON_EPSILON ); if (!frontwinding) { if (side == 0) AddPortalToNodes (p, b, other_node); else AddPortalToNodes (p, other_node, b); continue; } if (!backwinding) { if (side == 0) AddPortalToNodes (p, f, other_node); else AddPortalToNodes (p, other_node, f); continue; } // the winding is split new_portal = AllocPortal (); *new_portal = *p; new_portal->winding = backwinding; FreeWinding (p->winding); p->winding = frontwinding; if (side == 0) { AddPortalToNodes (p, f, other_node); AddPortalToNodes (new_portal, b, other_node); } else { AddPortalToNodes (p, other_node, f); AddPortalToNodes (new_portal, other_node, b); } } CutNodePortals_r (f); CutNodePortals_r (b); }
/* ================== DivideWinding ================== */ void DivideWinding( winding_t *in, plane_t *split, winding_t **front, winding_t **back ) { DivideWindingEpsilon( in, split, front, back, WINDING_EPSILON ); }