bool PolyCull::IsSegmentCulled(angle_t startAngle, angle_t endAngle) const { if (startAngle > endAngle) { return IsSegmentCulled(startAngle, ANGLE_MAX) && IsSegmentCulled(0, endAngle); } for (const auto &segment : SolidSegments) { if (startAngle >= segment.Start && endAngle <= segment.End) return true; else if (endAngle < segment.Start) return false; } return false; }
bool PolyCull::CheckBBox(float *bspcoord) { // Occlusion test using solid segments: static const uint8_t checkcoord[12][4] = { { 3,0,2,1 }, { 3,0,2,0 }, { 3,1,2,0 }, { 0 }, { 2,0,2,1 }, { 0,0,0,0 }, { 3,1,3,0 }, { 0 }, { 2,0,3,1 }, { 2,1,3,1 }, { 2,1,3,0 } }; // Find the corners of the box that define the edges from current viewpoint. const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; int boxpos = (viewpoint.Pos.X <= bspcoord[BOXLEFT] ? 0 : viewpoint.Pos.X < bspcoord[BOXRIGHT] ? 1 : 2) + (viewpoint.Pos.Y >= bspcoord[BOXTOP] ? 0 : viewpoint.Pos.Y > bspcoord[BOXBOTTOM] ? 4 : 8); if (boxpos == 5) return true; const uint8_t *check = checkcoord[boxpos]; angle_t angle1 = PointToPseudoAngle(bspcoord[check[0]], bspcoord[check[1]]); angle_t angle2 = PointToPseudoAngle(bspcoord[check[2]], bspcoord[check[3]]); return !IsSegmentCulled(angle2, angle1); }
bool PolyCull::CheckBBox(float *bspcoord) { // Start using a quick frustum AABB test: AxisAlignedBoundingBox aabb(Vec3f(bspcoord[BOXLEFT], bspcoord[BOXBOTTOM], (float)ViewPos.Z - 1000.0f), Vec3f(bspcoord[BOXRIGHT], bspcoord[BOXTOP], (float)ViewPos.Z + 1000.0f)); auto result = IntersectionTest::frustum_aabb(frustumPlanes, aabb); if (result == IntersectionTest::outside) return false; // Occlusion test using solid segments: static const int lines[4][4] = { { BOXLEFT, BOXBOTTOM, BOXRIGHT, BOXBOTTOM }, { BOXRIGHT, BOXBOTTOM, BOXRIGHT, BOXTOP }, { BOXRIGHT, BOXTOP, BOXLEFT, BOXTOP }, { BOXLEFT, BOXTOP, BOXLEFT, BOXBOTTOM } }; bool foundline = false; int minsx1, maxsx2; for (int i = 0; i < 4; i++) { int j = i < 3 ? i + 1 : 0; float x1 = bspcoord[lines[i][0]]; float y1 = bspcoord[lines[i][1]]; float x2 = bspcoord[lines[i][2]]; float y2 = bspcoord[lines[i][3]]; int sx1, sx2; if (GetSegmentRangeForLine(x1, y1, x2, y2, sx1, sx2)) { if (foundline) { minsx1 = MIN(minsx1, sx1); maxsx2 = MAX(maxsx2, sx2); } else { minsx1 = sx1; maxsx2 = sx2; foundline = true; } } } if (!foundline) return false; return !IsSegmentCulled(minsx1, maxsx2); }
bool PolyCull::GetAnglesForLine(double x1, double y1, double x2, double y2, angle_t &angle1, angle_t &angle2) const { angle2 = PointToPseudoAngle(x1, y1); angle1 = PointToPseudoAngle(x2, y2); return !IsSegmentCulled(angle1, angle2); }