void gl_RenderBSPNode (void *node) { if (numnodes == 0) { DoSubsector (subsectors); return; } while (!((size_t)node & 1)) // Keep going until found a subsector { node_t *bsp = (node_t *)node; // Decide which side the view point is on. int side = R_PointOnSide(viewx, viewy, bsp); // Recursively divide front space (toward the viewer). gl_RenderBSPNode (bsp->children[side]); // Possibly divide back space (away from the viewer). side ^= 1; if (!clipper.CheckBox(bsp->bbox[side])) { return; } node = bsp->children[side]; } DoSubsector ((subsector_t *)((BYTE *)node - 1)); }
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) { int nodenum = numnodes-1; while (!(nodenum & NF_SUBSECTOR)) nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)]; return &subsectors[nodenum & ~NF_SUBSECTOR]; }
void R_RenderBSPNode (int bspnum) { node_t *bsp; int side; if (bspnum & NF_SUBSECTOR) { if (bspnum == -1) R_Subsector (0); else R_Subsector (bspnum&(~NF_SUBSECTOR)); return; } bsp = &nodes[bspnum]; #ifdef __NeXT__ RD_DrawNodeLine (bsp); #endif // // decide which side the view point is on // side = R_PointOnSide (viewx, viewy, bsp); R_RenderBSPNode (bsp->children[side]); // recursively divide front space if (R_CheckBBox (bsp->bbox[side^1])) // possibly divide back space R_RenderBSPNode (bsp->children[side^1]); }
// // RenderBSPNode // Renders all subsectors below a given node, // traversing subtree recursively. // Just call with BSP root. void R_RenderBSPNode (int bspnum) { node_t* bsp; int side; // Found a subsector? if (bspnum & NF_SUBSECTOR) { if (bspnum == -1) R_Subsector (0); else R_Subsector (bspnum&(~NF_SUBSECTOR)); return; } bsp = &nodes[bspnum]; // Decide which side the view point is on. side = R_PointOnSide (viewx, viewy, bsp); // Recursively divide front space. R_RenderBSPNode (bsp->children[side]); // Possibly divide back space. if (R_CheckBBox (bsp->bbox[side^1])) R_RenderBSPNode (bsp->children[side^1]); }
// // RenderBSPNode // Renders all subsectors below a given node, // traversing subtree recursively. // Just call with BSP root. void R_RenderBSPNode(int bspnum, vector<BspNodeInfo>& nodeInfo, vector<SegInfo>& segInfo, int parentIdx, bool nodeFront) { node_t* bsp; int side; // Found a subsector? if (bspnum & NF_SUBSECTOR) { int subsectorNum = (bspnum == -1) ? 0 : bspnum&(~NF_SUBSECTOR); R_Subsector(subsectorNum, segInfo, parentIdx); return; } bsp = &nodes[bspnum]; int curIdx = nodeInfo.size(); nodeInfo.emplace_back(); { BspNodeInfo& curNodeInfo = nodeInfo.back(); //Ref could be invalid after recursion below. curNodeInfo.node = *bsp; curNodeInfo.parent = parentIdx; curNodeInfo.frontChild = curNodeInfo.backChild = -1; curNodeInfo.twoSide = false; } if (parentIdx != -1) { BspNodeInfo& parent = nodeInfo[parentIdx]; if (nodeFront) { parent.frontChild = curIdx; } else { parent.backChild = curIdx; } } // Decide which side the view point is on. side = R_PointOnSide(viewx, viewy, bsp); // Recursively divide front space. R_RenderBSPNode(bsp->children[side], nodeInfo, segInfo, curIdx, true); // Possibly divide back space. if (R_CheckBBox(bsp->bbox[side ^ 1])) { R_RenderBSPNode(bsp->children[side ^ 1], nodeInfo, segInfo, curIdx, false); nodeInfo[curIdx].twoSide = true; } }
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) { int nodenum = numnodes-1; // special case for trivial maps (single subsector, no nodes) if (numnodes == 0) return subsectors; while (!(nodenum & NF_SUBSECTOR)) nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)]; return &subsectors[nodenum & ~NF_SUBSECTOR]; }
// // R_PointInSubsector // subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) { int nodenum; // single subsector is a special case if (!numnodes) return subsectors; nodenum = numnodes - 1; while (!(nodenum & NF_SUBSECTOR)) nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)]; return &subsectors[nodenum & ~NF_SUBSECTOR]; }
void R_RenderBSPNode(int bspnum) { while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? { const node_t *bsp = &nodes[bspnum]; // Decide which side the view point is on. int side = R_PointOnSide(viewx, viewy, bsp); // Recursively divide front space. R_RenderBSPNode(bsp->children[side]); // Possibly divide back space. if (!R_CheckBBox(bsp->bbox[side^1])) return; bspnum = bsp->children[side^1]; } R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); }
void R_RenderBSPNode(int bspnum) { while (!(bspnum & NF_SUBSECTOR)) { const node_t *bsp = &nodes[bspnum]; int side = R_PointOnSide(viewx, viewy, bsp); R_RenderBSPNode(bsp->children[side]); if (!R_CheckBBox(bsp->bbox[side ^ 1])) return; bspnum = bsp->children[side ^ 1]; } R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); }
void CollectNode(void *node, TArray<FCoverageVertex> &shape) { static TArray<FCoverageLine> lists[2]; const double COVERAGE_EPSILON = 6.; // same epsilon as the node builder if (!((size_t)node & 1)) // Keep going until found a subsector { node_t *bsp = (node_t *)node; int centerside = R_PointOnSide(center.x, center.y, bsp); lists[0].Clear(); lists[1].Clear(); for(unsigned i=0;i<shape.Size(); i++) { FCoverageVertex *v1 = &shape[i]; FCoverageVertex *v2 = &shape[(i+1) % shape.Size()]; FCoverageLine vl = {{*v1, *v2}}; double dist_v1 = PartitionDistance(v1, bsp); double dist_v2 = PartitionDistance(v2, bsp); if(dist_v1 <= COVERAGE_EPSILON) { if (dist_v2 <= COVERAGE_EPSILON) { lists[centerside].Push(vl); } else { int side = PointOnSide(v2, bsp); lists[side].Push(vl); } } else if (dist_v2 <= COVERAGE_EPSILON) { int side = PointOnSide(v1, bsp); lists[side].Push(vl); } else { int side1 = PointOnSide(v1, bsp); int side2 = PointOnSide(v2, bsp); if(side1 != side2) { // if the partition line crosses this seg, we must split it. FCoverageVertex vert; if (GetIntersection(v1, v2, bsp, &vert)) { lists[0].Push(vl); lists[1].Push(vl); lists[side1].Last().v[1] = vert; lists[side2].Last().v[0] = vert; } else { // should never happen lists[side1].Push(vl); } } else { // both points on the same side. lists[side1].Push(vl); } } } if (lists[1].Size() == 0) { CollectNode(bsp->children[0], shape); } else if (lists[0].Size() == 0) { CollectNode(bsp->children[1], shape); } else { // copy the static arrays into local ones TArray<FCoverageVertex> locallists[2]; for(int l=0;l<2;l++) { for (unsigned i=0;i<lists[l].Size(); i++) { locallists[l].Push(lists[l][i].v[0]); unsigned i1= (i+1)%lists[l].Size(); if (lists[l][i1].v[0] != lists[l][i].v[1]) { locallists[l].Push(lists[l][i].v[1]); } } } CollectNode(bsp->children[0], locallists[0]); CollectNode(bsp->children[1], locallists[1]); } } else { // we reached a subsector so we can link the node with this subsector subsector_t *sub = (subsector_t *)((BYTE *)node - 1); collect.Push(int(sub-subsectors)); } }
int PointOnSide(FCoverageVertex *vt, node_t *node) { return R_PointOnSide(vt->x, vt->y, node); }