void RenderPolyScene::RenderPolyNode(PolyRenderThread *thread, void *node, uint32_t subsectorDepth, sector_t *frontsector) { 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 = PointOnSide(PolyRenderer::Instance()->Viewpoint.Pos, bsp); // Recursively divide front space (toward the viewer). RenderPolyNode(thread, bsp->children[side], subsectorDepth, frontsector); // Possibly divide back space (away from the viewer). side ^= 1; // Don't bother culling on poly objects //if (!CheckBBox(bsp->bbox[side])) // return; node = bsp->children[side]; } subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); RenderPolySubsector(thread, sub, subsectorDepth, frontsector); }
void PolyCull::CullNode(void *node) { 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 = PointOnSide(ViewPos, bsp); // Recursively divide front space (toward the viewer). CullNode(bsp->children[side]); // Possibly divide back space (away from the viewer). side ^= 1; if (!CheckBBox(bsp->bbox[side])) return; node = bsp->children[side]; } // Mark that we need to render this subsector_t *sub = (subsector_t *)((BYTE *)node - 1); MaxCeilingHeight = MAX(MaxCeilingHeight, sub->sector->ceilingplane.Zat0()); MinFloorHeight = MIN(MinFloorHeight, sub->sector->floorplane.Zat0()); PvsSectors.push_back(sub); // Update culling info for further bsp clipping for (uint32_t i = 0; i < sub->numlines; i++) { seg_t *line = &sub->firstline[i]; if ((line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ)) && line->backsector == nullptr) { int sx1, sx2; if (GetSegmentRangeForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), sx1, sx2)) { MarkSegmentCulled(sx1, sx2); } } } }
void PolyCull::CullNode(void *node) { 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 = PointOnSide(PolyRenderer::Instance()->Viewpoint.Pos, bsp); // Recursively divide front space (toward the viewer). CullNode(bsp->children[side]); // Possibly divide back space (away from the viewer). side ^= 1; if (!CheckBBox(bsp->bbox[side])) return; node = bsp->children[side]; } subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); CullSubsector(sub); }
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)); } }