/* ============== SplitNodePortals Move or split the portals that bound node so that the node's children have portals instead of node. ============== */ void SplitNodePortals (node_t *node) { portal_t *p, *next_portal, *new_portal; node_t *f, *b, *other_node; int side = 0; plane_t *plane; winding_t *frontwinding, *backwinding; plane = &mapplanes[node->planenum]; f = node->children[0]; b = node->children[1]; 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 // ClipWindingEpsilon (p->winding, plane->normal, plane->dist, SPLIT_WINDING_EPSILON, &frontwinding, &backwinding); if (frontwinding && WindingIsTiny(frontwinding)) { FreeWinding (frontwinding); frontwinding = NULL; c_tinyportals++; } if (backwinding && WindingIsTiny(backwinding)) { FreeWinding (backwinding); backwinding = NULL; c_tinyportals++; } if (!frontwinding && !backwinding) { // tiny windings on both sides continue; } if (!frontwinding) { FreeWinding (backwinding); if (side == 0) AddPortalToNodes (p, b, other_node); else AddPortalToNodes (p, other_node, b); continue; } if (!backwinding) { FreeWinding (frontwinding); 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); } } node->portals = NULL; }
void MakeNodePortal(node_t *node) { portal_t *new_portal, *p; winding_t *w; vec3_t normal; float dist = 0; // TTimo: init int side = 0; w = BaseWindingForNode(node); // clip the portal by all the other portals in the node for(p = node->portals; p && w; p = p->next[side]) { if(p->nodes[0] == node) { side = 0; VectorCopy(p->plane.normal, normal); dist = p->plane.dist; } //end if else if(p->nodes[1] == node) { side = 1; VectorSubtract(vec3_origin, p->plane.normal, normal); dist = -p->plane.dist; } //end else if else { Error("MakeNodePortal: mislinked portal"); } //end else ChopWindingInPlace(&w, normal, dist, 0.1); } //end for if(!w) { return; } //end if if(WindingIsTiny(w)) { c_tinyportals++; FreeWinding(w); return; } //end if #ifdef DEBUG /* //NOTE: don't use this winding ok check // all the invalid windings only have a degenerate edge if (WindingError(w)) { Log_Print("MakeNodePortal: %s\n", WindingErrorString()); FreeWinding(w); return; } //end if*/ #endif //DEBUG new_portal = AllocPortal(); new_portal->plane = mapplanes[node->planenum]; #ifdef ME new_portal->planenum = node->planenum; #endif //ME new_portal->onnode = node; new_portal->winding = w; AddPortalToNodes(new_portal, node->children[0], node->children[1]); } //end of the function MakeNodePortal
//=========================================================================== // Move or split the portals that bound node so that the node's // children have portals instead of node. // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void SplitNodePortals(node_t *node) { portal_t *p, *next_portal, *new_portal; node_t *f, *b, *other_node; int side = 0; // TTimo: init plane_t *plane; winding_t *frontwinding, *backwinding; plane = &mapplanes[node->planenum]; f = node->children[0]; b = node->children[1]; 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("SplitNodePortals: 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 // ClipWindingEpsilon(p->winding, plane->normal, plane->dist, SPLIT_WINDING_EPSILON, &frontwinding, &backwinding); if(frontwinding && WindingIsTiny(frontwinding)) { FreeWinding(frontwinding); frontwinding = NULL; c_tinyportals++; } //end if if(backwinding && WindingIsTiny(backwinding)) { FreeWinding(backwinding); backwinding = NULL; c_tinyportals++; } //end if #ifdef DEBUG /* //NOTE: don't use this winding ok check // all the invalid windings only have a degenerate edge if (frontwinding && WindingError(frontwinding)) { Log_Print("SplitNodePortals: front %s\n", WindingErrorString()); FreeWinding(frontwinding); frontwinding = NULL; } //end if if (backwinding && WindingError(backwinding)) { Log_Print("SplitNodePortals: back %s\n", WindingErrorString()); FreeWinding(backwinding); backwinding = NULL; } //end if*/ #endif //DEBUG if(!frontwinding && !backwinding) // tiny windings on both sides { continue; } if(!frontwinding) { FreeWinding(backwinding); if(side == 0) { AddPortalToNodes(p, b, other_node); } else { AddPortalToNodes(p, other_node, b); } continue; } if(!backwinding) { FreeWinding(frontwinding); 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); } //end if else { AddPortalToNodes(p, other_node, f); AddPortalToNodes(new_portal, other_node, b); } //end else } node->portals = NULL; } //end of the function SplitNodePortals
void MakeHeadnodePortals(tree_t *tree) { vec3_t bounds[2]; int i, j, n; portal_t *p, *portals[6]; plane_t bplanes[6], *pl; node_t *node; node = tree->headnode; // pad with some space so there will never be null volume leaves for(i = 0 ; i < 3 ; i++) { bounds[0][i] = tree->mins[i] - SIDESPACE; bounds[1][i] = tree->maxs[i] + SIDESPACE; } tree->outside_node.planenum = PLANENUM_LEAF; tree->outside_node.brushlist = NULL; tree->outside_node.portals = NULL; tree->outside_node.contents = 0; for(i = 0 ; i < 3 ; i++) for(j = 0 ; j < 2 ; j++) { n = j * 3 + i; p = AllocPortal(); portals[n] = p; pl = &bplanes[n]; memset(pl, 0, sizeof(*pl)); if(j) { pl->normal[i] = -1; pl->dist = -bounds[j][i]; } else { pl->normal[i] = 1; pl->dist = bounds[j][i]; } p->plane = *pl; p->winding = BaseWindingForPlane(pl->normal, pl->dist); AddPortalToNodes(p, node, &tree->outside_node); } // clip the basewindings by all the other planes for(i = 0 ; i < 6 ; i++) { for(j = 0 ; j < 6 ; j++) { if(j == i) { continue; } ChopWindingInPlace(&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON); } //end for } //end for } //end of the function MakeHeadNodePortals
/* ============== SplitNodePortals Move or split the portals that bound node so that the node's children have portals instead of node. ============== */ static void SplitNodePortals( node_t *node ) { uPortal_t *p, *next_portal, *new_portal; node_t *f, *b, *other_node; int side; idPlane *plane; idWinding *frontwinding, *backwinding; plane = &dmapGlobals.mapPlanes[node->planenum]; f = node->children[0]; b = node->children[1]; for( p = node->portals ; p ; p = next_portal ) { if( p->nodes[0] == node ) { side = 0; } else if( p->nodes[1] == node ) { side = 1; } else { common->Error( "SplitNodePortals: mislinked portal" ); side = 0; // quiet a compiler warning } 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 // p->winding->Split( *plane, SPLIT_WINDING_EPSILON, &frontwinding, &backwinding ); if( frontwinding && frontwinding->IsTiny() ) { delete frontwinding; frontwinding = NULL; c_tinyportals++; } if( backwinding && backwinding->IsTiny() ) { delete backwinding; backwinding = NULL; c_tinyportals++; } if( !frontwinding && !backwinding ) { // tiny windings on both sides continue; } if( !frontwinding ) { delete backwinding; if( side == 0 ) { AddPortalToNodes( p, b, other_node ); } else { AddPortalToNodes( p, other_node, b ); } continue; } if( !backwinding ) { delete frontwinding; 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; delete 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 ); } } node->portals = NULL; }
/* ================== MakeNodePortal create the new portal by taking the full plane winding for the cutting plane and clipping it by all of parents of this node ================== */ void MakeNodePortal (node_t *node) { portal_t *new_portal, *p; winding_t *w; vec3_t normal; float dist; int side; w = BaseWindingForNode (node); // clip the portal by all the other portals in the node for (p = node->portals ; p && w; p = p->next[side]) { if (p->nodes[0] == node) { side = 0; VectorCopy (p->plane.normal, normal); dist = p->plane.dist; } else if (p->nodes[1] == node) { side = 1; VectorSubtract (vec3_origin, p->plane.normal, normal); dist = -p->plane.dist; } else Error ("CutNodePortals_r: mislinked portal"); ChopWindingInPlace (&w, normal, dist, CLIP_EPSILON); } if (!w) { return; } /* ydnar: adding this here to fix degenerate windings */ #if 0 if( FixWinding( w ) == qfalse ) { c_badportals++; FreeWinding( w ); return; } #endif if (WindingIsTiny (w)) { c_tinyportals++; FreeWinding (w); return; } new_portal = AllocPortal (); new_portal->plane = mapplanes[node->planenum]; new_portal->onnode = node; new_portal->winding = w; new_portal->compileFlags = node->compileFlags; AddPortalToNodes (new_portal, node->children[0], node->children[1]); }
static void MakeHeadnodePortals( tree_t *tree ) { idBounds bounds; int i, j, n; uPortal_t *p, *portals[6]; idPlane bplanes[6], *pl; node_t *node; node = tree->headnode; tree->outside_node.planenum = PLANENUM_LEAF; tree->outside_node.brushlist = NULL; tree->outside_node.portals = NULL; tree->outside_node.opaque = false; // if no nodes, don't go any farther if( node->planenum == PLANENUM_LEAF ) { return; } // pad with some space so there will never be null volume leafs for( i = 0; i < 3; i++ ) { bounds[0][i] = tree->bounds[0][i] - SIDESPACE; bounds[1][i] = tree->bounds[1][i] + SIDESPACE; if( bounds[0][i] >= bounds[1][i] ) { common->Error( "Backwards tree volume" ); } } for( i = 0; i < 3; i++ ) { for( j = 0; j < 2; j++ ) { n = j * 3 + i; p = AllocPortal(); portals[n] = p; pl = &bplanes[n]; memset( pl, 0, sizeof( *pl ) ); if( j ) { ( *pl ) [i] = -1; ( *pl ) [3] = bounds[j][i]; } else { ( *pl ) [i] = 1; ( *pl ) [3] = -bounds[j][i]; } p->plane = *pl; p->winding = new idWinding( *pl ); AddPortalToNodes( p, node, &tree->outside_node ); } } // clip the basewindings by all the other planes for( i = 0; i < 6; i++ ) { for( j = 0; j < 6; j++ ) { if( j == i ) { continue; } portals[i]->winding = portals[i]->winding->Clip( bplanes[j], ON_EPSILON ); } } }
/* ================ 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); }