Пример #1
0
void FTraceInfo::EnterLinePortal(FPathTraverse &pt, intercept_t *in)
{
	line_t *li = in->d.line;
	FLinePortal *port = li->getPortal();

	double frac = in->frac + EQUAL_EPSILON;
	double enterdist = MaxDist * frac;
	DVector3 exit = Start + MaxDist * in->frac * Vec;

	P_TranslatePortalXY(li, Start.X, Start.Y);
	P_TranslatePortalZ(li, Start.Z);
	P_TranslatePortalVXVY(li, Vec.X, Vec.Y);
	P_TranslatePortalZ(li, limitz);

	CurSector = P_PointInSector(Start + enterdist * Vec);
	EnterDist = enterdist;
	inshootthrough = true;
	startfrac = frac;
	Results->unlinked |= (port->mType != PORTT_LINKED);
	pt.PortalRelocate(in, ptflags);

	if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL)
	{
		enterdist = MaxDist * in->frac;
		Results->HitType = TRACE_CrossingPortal;
		Results->HitPos = exit;
		P_TranslatePortalXY(li, exit.X, exit.Y);
		P_TranslatePortalZ(li, exit.Z);
		Results->SrcFromTarget = exit;
		Results->HitVector = Vec;
		TraceCallback(*Results, TraceCallbackData);
	}
}
Пример #2
0
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void GLLineToLinePortal::DrawContents()
{
	// TODO: Handle recursion more intelligently
	if (renderdepth>r_mirror_recursions) 
	{
		ClearScreen();
		return;
	}

	GLRenderer->mClipPortal = this;

	line_t *origin = glport->lines[0]->mOrigin;
	P_TranslatePortalXY(origin, ViewPos.X, ViewPos.Y);
	P_TranslatePortalAngle(origin, ViewAngle);
	P_TranslatePortalZ(origin, ViewPos.Z);
	P_TranslatePortalXY(origin, ViewPath[0].X, ViewPath[0].Y);
	P_TranslatePortalXY(origin, ViewPath[1].X, ViewPath[1].Y);
	if (!r_showviewer && camera != nullptr && P_PointOnLineSidePrecise(ViewPath[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(ViewPath[1], glport->lines[0]->mDestination))
	{
		double distp = (ViewPath[0] - ViewPath[1]).Length();
		if (distp > EQUAL_EPSILON)
		{
			double dist1 = (ViewPos - ViewPath[0]).Length();
			double dist2 = (ViewPos - ViewPath[1]).Length();

			if (dist1 + dist2 < distp + 1)
			{
				camera->renderflags |= RF_INVISIBLE;
			}
		}
	}


	SaveMapSection();

	for (unsigned i = 0; i < lines.Size(); i++)
	{
		line_t *line = lines[i].seg->linedef->getPortalDestination();
		subsector_t *sub;
		if (line->sidedef[0]->Flags & WALLF_POLYOBJ) 
			sub = R_PointInSubsector(line->v1->fixX(), line->v1->fixY());
		else sub = line->frontsector->subsectors[0];
		int mapsection = sub->mapsection;
		currentmapsection[mapsection >> 3] |= 1 << (mapsection & 7);
	}

	GLRenderer->mViewActor = nullptr;
	GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));

	ClearClipper();
	gl_RenderState.SetClipLine(glport->lines[0]->mDestination);
	gl_RenderState.EnableClipLine(true);
	GLRenderer->DrawScene(DM_PORTAL);
	gl_RenderState.EnableClipLine(false);
	RestoreMapSection();
}
Пример #3
0
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
{
	// TODO: Handle recursion more intelligently
	auto &state = mState;
	if (state->renderdepth>r_mirror_recursions)
	{
		return false;
	}
	auto &vp = di->Viewpoint;
	di->mClipPortal = this;

	line_t *origin = glport->lines[0]->mOrigin;
	P_TranslatePortalXY(origin, vp.Pos.X, vp.Pos.Y);
	P_TranslatePortalXY(origin, vp.ActorPos.X, vp.ActorPos.Y);
	P_TranslatePortalAngle(origin, vp.Angles.Yaw);
	P_TranslatePortalZ(origin, vp.Pos.Z);
	P_TranslatePortalXY(origin, vp.Path[0].X, vp.Path[0].Y);
	P_TranslatePortalXY(origin, vp.Path[1].X, vp.Path[1].Y);
	if (!vp.showviewer && vp.camera != nullptr && P_PointOnLineSidePrecise(vp.Path[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(vp.Path[1], glport->lines[0]->mDestination))
	{
		double distp = (vp.Path[0] - vp.Path[1]).Length();
		if (distp > EQUAL_EPSILON)
		{
			double dist1 = (vp.Pos - vp.Path[0]).Length();
			double dist2 = (vp.Pos - vp.Path[1]).Length();

			if (dist1 + dist2 < distp + 1)
			{
				vp.camera->renderflags |= RF_MAYBEINVISIBLE;
			}
		}
	}


	for (unsigned i = 0; i < lines.Size(); i++)
	{
		line_t *line = lines[i].seg->linedef->getPortalDestination();
		subsector_t *sub;
		if (line->sidedef[0]->Flags & WALLF_POLYOBJ)
			sub = di->Level->PointInRenderSubsector(line->v1->fixX(), line->v1->fixY());
		else sub = line->frontsector->subsectors[0];
		di->CurrentMapSections.Set(sub->mapsection);
	}

	vp.ViewActor = nullptr;
	di->SetClipLine(glport->lines[0]->mDestination);
	di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));

	ClearClipper(di, clipper);
	return true;
}
Пример #4
0
void PolyDrawLinePortal::SaveGlobals()
{
	auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
	const auto &viewwindow = PolyRenderer::Instance()->Viewwindow;

	SavedViewpoint = viewpoint;
	SavedInvisibility = viewpoint.camera ? (viewpoint.camera->renderflags & RF_INVISIBLE) == RF_INVISIBLE : false;

	if (Mirror)
	{
		DAngle startang = viewpoint.Angles.Yaw;
		DVector3 startpos = viewpoint.Pos;

		vertex_t *v1 = Mirror->v1;

		// Reflect the current view behind the mirror.
		if (Mirror->Delta().X == 0)
		{ // vertical mirror
			viewpoint.Pos.X = v1->fX() - startpos.X + v1->fX();
		}
		else if (Mirror->Delta().Y == 0)
		{ // horizontal mirror
			viewpoint.Pos.Y = v1->fY() - startpos.Y + v1->fY();
		}
		else
		{ // any mirror
			vertex_t *v2 = Mirror->v2;

			double dx = v2->fX() - v1->fX();
			double dy = v2->fY() - v1->fY();
			double x1 = v1->fX();
			double y1 = v1->fY();
			double x = startpos.X;
			double y = startpos.Y;

			// the above two cases catch len == 0
			double r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy);

			viewpoint.Pos.X = (x1 + r * dx) * 2 - x;
			viewpoint.Pos.Y = (y1 + r * dy) * 2 - y;
		}
		viewpoint.Angles.Yaw = Mirror->Delta().Angle() * 2 - startang;

		if (viewpoint.camera)
			viewpoint.camera->renderflags &= ~RF_INVISIBLE;
	}
	else
	{
		auto src = Portal->mOrigin;
		auto dst = Portal->mDestination;

		P_TranslatePortalXY(src, viewpoint.Pos.X, viewpoint.Pos.Y);
		P_TranslatePortalZ(src, viewpoint.Pos.Z);
		P_TranslatePortalAngle(src, viewpoint.Angles.Yaw);
		P_TranslatePortalXY(src, viewpoint.Path[0].X, viewpoint.Path[0].Y);
		P_TranslatePortalXY(src, viewpoint.Path[1].X, viewpoint.Path[1].Y);

		if (viewpoint.camera && !viewpoint.showviewer)
			viewpoint.camera->renderflags |= RF_INVISIBLE;

		/* What is this code trying to do?
		if (viewpoint.camera)
		{
			viewpoint.camera->renderflags &= ~RF_INVISIBLE;

			if (!viewpoint.showviewer && P_PointOnLineSidePrecise(viewpoint.Path[0], dst) != P_PointOnLineSidePrecise(viewpoint.Path[1], dst))
			{
				double distp = (viewpoint.Path[0] - viewpoint.Path[1]).Length();
				if (distp > EQUAL_EPSILON)
				{
					double dist1 = (viewpoint.Pos - viewpoint.Path[0]).Length();
					double dist2 = (viewpoint.Pos - viewpoint.Path[1]).Length();

					if (dist1 + dist2 < distp + 1)
					{
						viewpoint.camera->renderflags |= RF_INVISIBLE;
					}
				}
			}
		}
		*/
	}

	viewpoint.camera = nullptr;
	viewpoint.sector = viewpoint.ViewLevel->PointInRenderSubsector(viewpoint.Pos)->sector;

	viewpoint.SetViewAngle(viewwindow);
}
Пример #5
0
	void RenderPortal::RenderLinePortal(PortalDrawseg* pds, int depth)
	{
		auto viewport = Thread->Viewport.get();
		auto &viewpoint = viewport->viewpoint;
		
		// [ZZ] check depth. fill portal with black if it's exceeding the visual recursion limit, and continue like nothing happened.
		if (depth >= r_portal_recursions)
		{
			uint8_t color = (uint8_t)BestColor((uint32_t *)GPalette.BaseColors, 0, 0, 0, 0, 255);
			int spacing = viewport->RenderTarget->GetPitch();
			for (int x = pds->x1; x < pds->x2; x++)
			{
				if (x < 0 || x >= viewport->RenderTarget->GetWidth())
					continue;

				int Ytop = pds->ceilingclip[x - pds->x1];
				int Ybottom = pds->floorclip[x - pds->x1];

				if (viewport->RenderTarget->IsBgra())
				{
					uint32_t *dest = (uint32_t*)viewport->RenderTarget->GetBuffer() + x + Ytop * spacing;

					uint32_t c = GPalette.BaseColors[color].d;
					for (int y = Ytop; y <= Ybottom; y++)
					{
						*dest = c;
						dest += spacing;
					}
				}
				else
				{
					uint8_t *dest = viewport->RenderTarget->GetBuffer() + x + Ytop * spacing;

					for (int y = Ytop; y <= Ybottom; y++)
					{
						*dest = color;
						dest += spacing;
					}
				}
			}

			if (r_highlight_portals)
				RenderLinePortalHighlight(pds);

			return;
		}

		DAngle startang = viewpoint.Angles.Yaw;
		DVector3 startpos = viewpoint.Pos;
		DVector3 savedpath[2] = { viewpoint.Path[0], viewpoint.Path[1] };
		ActorRenderFlags savedvisibility = viewpoint.camera ? viewpoint.camera->renderflags & RF_INVISIBLE : ActorRenderFlags::FromInt(0);
		
		viewpoint.camera->renderflags &= ~RF_INVISIBLE;

		CurrentPortalUniq++;

		unsigned int portalsAtStart = WallPortals.Size();

		if (pds->mirror)
		{
			//vertex_t *v1 = ds->curline->v1;
			vertex_t *v1 = pds->src->v1;

			// Reflect the current view behind the mirror.
			if (pds->src->Delta().X == 0)
			{ // vertical mirror
				viewpoint.Pos.X = v1->fX() - startpos.X + v1->fX();
			}
			else if (pds->src->Delta().Y == 0)
			{ // horizontal mirror
				viewpoint.Pos.Y = v1->fY() - startpos.Y + v1->fY();
			}
			else
			{ // any mirror
				vertex_t *v2 = pds->src->v2;

				double dx = v2->fX() - v1->fX();
				double dy = v2->fY() - v1->fY();
				double x1 = v1->fX();
				double y1 = v1->fY();
				double x = startpos.X;
				double y = startpos.Y;

				// the above two cases catch len == 0
				double r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy);

				viewpoint.Pos.X = (x1 + r * dx) * 2 - x;
				viewpoint.Pos.Y = (y1 + r * dy) * 2 - y;
			}
			viewpoint.Angles.Yaw = pds->src->Delta().Angle() * 2 - startang;
		}
		else
		{
			P_TranslatePortalXY(pds->src, viewpoint.Pos.X, viewpoint.Pos.Y);
			P_TranslatePortalZ(pds->src, viewpoint.Pos.Z);
			P_TranslatePortalAngle(pds->src, viewpoint.Angles.Yaw);
			P_TranslatePortalXY(pds->src, viewpoint.Path[0].X, viewpoint.Path[0].Y);
			P_TranslatePortalXY(pds->src, viewpoint.Path[1].X, viewpoint.Path[1].Y);

			if (!viewpoint.showviewer && viewpoint.camera && P_PointOnLineSidePrecise(viewpoint.Path[0], pds->dst) != P_PointOnLineSidePrecise(viewpoint.Path[1], pds->dst))
			{
				double distp = (viewpoint.Path[0] - viewpoint.Path[1]).Length();
				if (distp > EQUAL_EPSILON)
				{
					double dist1 = (viewpoint.Pos - viewpoint.Path[0]).Length();
					double dist2 = (viewpoint.Pos - viewpoint.Path[1]).Length();

					if (dist1 + dist2 < distp + 1)
					{
						viewpoint.camera->renderflags |= RF_INVISIBLE;
					}
				}
			}
		}

		viewpoint.Sin = viewpoint.Angles.Yaw.Sin();
		viewpoint.Cos = viewpoint.Angles.Yaw.Cos();

		viewpoint.TanSin = Thread->Viewport->viewwindow.FocalTangent * viewpoint.Sin;
		viewpoint.TanCos = Thread->Viewport->viewwindow.FocalTangent * viewpoint.Cos;

		CopyStackedViewParameters();

		validcount++;
		PortalDrawseg* prevpds = CurrentPortal;
		CurrentPortal = pds;

		Thread->PlaneList->ClearKeepFakePlanes();
		Thread->ClipSegments->Clear(pds->x1, pds->x2);

		WindowLeft = pds->x1;
		WindowRight = pds->x2;

		// RF_XFLIP should be removed before calling the root function
		int prevmf = MirrorFlags;
		if (pds->mirror)
		{
			if (MirrorFlags & RF_XFLIP)
				MirrorFlags &= ~RF_XFLIP;
			else MirrorFlags |= RF_XFLIP;
		}

		// some portals have height differences, account for this here
		Thread->Clip3D->EnterSkybox(); // push 3D floor height map
		CurrentPortalInSkybox = false; // first portal in a skybox should set this variable to false for proper clipping in skyboxes.

		// first pass, set clipping
		auto ceilingclip = Thread->OpaquePass->ceilingclip;
		auto floorclip = Thread->OpaquePass->floorclip;
		memcpy(ceilingclip + pds->x1, &pds->ceilingclip[0], pds->len * sizeof(*ceilingclip));
		memcpy(floorclip + pds->x1, &pds->floorclip[0], pds->len * sizeof(*floorclip));

		Thread->OpaquePass->RenderScene();
		Thread->Clip3D->ResetClip(); // reset clips (floor/ceiling)
		if (!savedvisibility && viewpoint.camera) viewpoint.camera->renderflags &= ~RF_INVISIBLE;

		Thread->PlaneList->Render();
		RenderPlanePortals();

		double vzp = viewpoint.Pos.Z;

		int prevuniq = CurrentPortalUniq;
		// depth check is in another place right now
		unsigned int portalsAtEnd = WallPortals.Size();
		for (; portalsAtStart < portalsAtEnd; portalsAtStart++)
		{
			RenderLinePortal(WallPortals[portalsAtStart], depth + 1);
		}
		int prevuniq2 = CurrentPortalUniq;
		CurrentPortalUniq = prevuniq;

		if (Thread->MainThread)
			NetUpdate();

		Thread->TranslucentPass->Render();	  //      this is required since with portals there often will be cases when more than 80% of the view is inside a portal.

		if (Thread->MainThread)
			NetUpdate();

		Thread->Clip3D->LeaveSkybox(); // pop 3D floor height map
		CurrentPortalUniq = prevuniq2;

		// draw a red line around a portal if it's being highlighted
		if (r_highlight_portals)
			RenderLinePortalHighlight(pds);

		CurrentPortal = prevpds;
		MirrorFlags = prevmf;
		viewpoint.Angles.Yaw = startang;
		viewpoint.Pos = startpos;
		viewpoint.Path[0] = savedpath[0];
		viewpoint.Path[1] = savedpath[1];
	}