Ejemplo n.º 1
0
void PolyCull::MarkSegmentCulled(angle_t startAngle, angle_t endAngle)
{
	if (startAngle > endAngle)
	{
		MarkSegmentCulled(startAngle, ANGLE_MAX);
		MarkSegmentCulled(0, endAngle);
		return;
	}

	int count = (int)SolidSegments.size();
	int cur = 0;
	while (cur < count)
	{
		if (SolidSegments[cur].Start <= startAngle && SolidSegments[cur].End >= endAngle) // Already fully marked
		{
			return;
		}
		else if (SolidSegments[cur].End >= startAngle && SolidSegments[cur].Start <= endAngle) // Merge segments
		{
			// Find last segment
			int merge = cur;
			while (merge + 1 != count && SolidSegments[merge + 1].Start <= endAngle)
				merge++;

			// Apply new merged range
			SolidSegments[cur].Start = MIN(SolidSegments[cur].Start, startAngle);
			SolidSegments[cur].End = MAX(SolidSegments[merge].End, endAngle);

			// Remove additional segments we merged with
			if (merge > cur)
				SolidSegments.erase(SolidSegments.begin() + (cur + 1), SolidSegments.begin() + (merge + 1));

			return;
		}
		else if (SolidSegments[cur].Start > startAngle) // Insert new segment
		{
			SolidSegments.insert(SolidSegments.begin() + cur, { startAngle, endAngle });
			return;
		}
		cur++;
	}
	SolidSegments.push_back({ startAngle, endAngle });

#if 0
	count = (int)SolidSegments.size();
	for (int i = 1; i < count; i++)
	{
		if (SolidSegments[i - 1].Start >= SolidSegments[i].Start ||
			SolidSegments[i - 1].End >= SolidSegments[i].Start ||
			SolidSegments[i - 1].End + 1 == SolidSegments[i].Start ||
			SolidSegments[i].Start > SolidSegments[i].End)
		{
			I_FatalError("MarkSegmentCulled is broken!");
		}
	}
#endif
}
Ejemplo n.º 2
0
void PolyCull::InvertSegments()
{
	TempInvertSolidSegments.swap(SolidSegments);
	ClearSolidSegments();
	angle_t cur = 0;
	for (const auto &segment : TempInvertSolidSegments)
	{
		if (cur < segment.Start)
			MarkSegmentCulled(cur, segment.Start - 1);
		cur = segment.End + 1;
	}
	if (cur < ANGLE_MAX)
		MarkSegmentCulled(cur, ANGLE_MAX);
}
Ejemplo n.º 3
0
void PolyCull::CullSubsector(subsector_t *sub)
{
	// Check if subsector is clipped entirely by the portal clip plane
	bool visible = false;
	for (uint32_t i = 0; i < sub->numlines; i++)
	{
		seg_t *line = &sub->firstline[i];
		if (PortalClipPlane.A * line->v1->fX() + PortalClipPlane.B * line->v1->fY() + PortalClipPlane.D > 0.0)
		{
			visible = true;
			break;
		}
	}
	if (!visible)
		return;

	// Update sky heights for the scene
	if (!FirstSkyHeight)
	{
		MaxCeilingHeight = MAX(MaxCeilingHeight, sub->sector->ceilingplane.Zat0());
		MinFloorHeight = MIN(MinFloorHeight, sub->sector->floorplane.Zat0());
	}
	else
	{
		MaxCeilingHeight = sub->sector->ceilingplane.Zat0();
		MinFloorHeight = sub->sector->floorplane.Zat0();
		FirstSkyHeight = false;
	}

	// Mark that we need to render this
	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)
		{
			// Skip lines not facing viewer
			DVector2 pt1 = line->v1->fPos() - PolyRenderer::Instance()->Viewpoint.Pos;
			DVector2 pt2 = line->v2->fPos() - PolyRenderer::Instance()->Viewpoint.Pos;
			if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0)
				continue;

			// Skip line if entirely behind portal clipping plane
			if ((PortalClipPlane.A * line->v1->fX() + PortalClipPlane.B * line->v1->fY() + PortalClipPlane.D <= 0.0) ||
				(PortalClipPlane.A * line->v2->fX() + PortalClipPlane.B * line->v2->fY() + PortalClipPlane.D <= 0.0))
			{
				continue;
			}

			angle_t angle1, angle2;
			if (GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2))
			{
				MarkSegmentCulled(angle1, angle2);
			}
		}
	}
}
Ejemplo n.º 4
0
void PolyCull::MarkViewFrustum()
{
	// Clips things outside the viewing frustum.
	auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
	auto &viewwindow = PolyRenderer::Instance()->Viewwindow;
	double tilt = fabs(viewpoint.Angles.Pitch.Degrees);
	if (tilt > 46.0) // If the pitch is larger than this you can look all around
		return;

	double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(viewwindow.WidescreenRatio) / 90.0;
	angle_t a1 = DAngle(floatangle).BAMs();
	if (a1 < ANGLE_180)
	{
		MarkSegmentCulled(AngleToPseudo(viewpoint.Angles.Yaw.BAMs() + a1), AngleToPseudo(viewpoint.Angles.Yaw.BAMs() - a1));
	}
}
Ejemplo n.º 5
0
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);
            }
        }
    }
}
Ejemplo n.º 6
0
void PolyCull::CullSubsector(subsector_t *sub)
{
	// Check if subsector is clipped entirely by the portal clip plane
	bool visible = false;
	for (uint32_t i = 0; i < sub->numlines; i++)
	{
		seg_t *line = &sub->firstline[i];
		if (PortalClipPlane.A * line->v1->fX() + PortalClipPlane.B * line->v1->fY() + PortalClipPlane.D > 0.0)
		{
			visible = true;
			break;
		}
	}
	if (!visible)
		return;

	// Update sky heights for the scene
	if (!FirstSkyHeight)
	{
		MaxCeilingHeight = MAX(MaxCeilingHeight, sub->sector->ceilingplane.Zat0());
		MinFloorHeight = MIN(MinFloorHeight, sub->sector->floorplane.Zat0());
	}
	else
	{
		MaxCeilingHeight = sub->sector->ceilingplane.Zat0();
		MinFloorHeight = sub->sector->floorplane.Zat0();
		FirstSkyHeight = false;
	}

	uint32_t subsectorDepth = (uint32_t)PvsSectors.size();

	// Mark that we need to render this
	PvsSectors.push_back(sub);
	PvsLineStart.push_back(NextPvsLineStart);

	DVector3 viewpos = PolyRenderer::Instance()->Viewpoint.Pos;

	// Update culling info for further bsp clipping
	for (uint32_t i = 0; i < sub->numlines; i++)
	{
		seg_t *line = &sub->firstline[i];

		// Skip lines not facing viewer
		DVector2 pt1 = line->v1->fPos() - viewpos;
		DVector2 pt2 = line->v2->fPos() - viewpos;
		if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0)
		{
			PvsLineVisible[NextPvsLineStart++] = false;
			continue;
		}

		// Skip line if entirely behind portal clipping plane
		if ((PortalClipPlane.A * line->v1->fX() + PortalClipPlane.B * line->v1->fY() + PortalClipPlane.D <= 0.0) ||
			(PortalClipPlane.A * line->v2->fX() + PortalClipPlane.B * line->v2->fY() + PortalClipPlane.D <= 0.0))
		{
			PvsLineVisible[NextPvsLineStart++] = false;
			continue;
		}

		angle_t angle1, angle2;
		bool lineVisible = GetAnglesForLine(line->v1->fX(), line->v1->fY(), line->v2->fX(), line->v2->fY(), angle1, angle2);
		if (lineVisible && line->backsector == nullptr)
		{
			MarkSegmentCulled(angle1, angle2);
		}

		// Mark if this line was visible
		PvsLineVisible[NextPvsLineStart++] = lineVisible;
	}

	if (!SectorSeen[sub->sector->Index()])
	{
		SectorSeen[sub->sector->Index()] = true;
		SeenSectors.push_back(sub->sector);
	}

	SubsectorDepths[sub->Index()] = subsectorDepth;
}