Esempio n. 1
0
void FGLRenderer::SetViewAngle(DAngle viewangle)
{
	mAngles.Yaw = float(270.0-viewangle.Degrees);
	DVector2 v = ViewAngle.ToVector();
	mViewVector.X = v.X;
	mViewVector.Y = v.Y;

	R_SetViewAngle();
}
Esempio n. 2
0
	// Draws any recorded sky boxes and then frees them.
	//
	// The process:
	//   1. Move the camera to coincide with the SkyViewpoint.
	//   2. Clear out the old planes. (They have already been drawn.)
	//   3. Clear a window out of the ClipSegs just large enough for the plane.
	//   4. Pretend the existing vissprites and drawsegs aren't there.
	//   5. Create a drawseg at 0 distance to clip sprites to the visplane. It
	//      doesn't need to be associated with a line in the map, since there
	//      will never be any sprites in front of it.
	//   6. Render the BSP, then planes, then masked stuff.
	//   7. Restore the previous vissprites and drawsegs.
	//   8. Repeat for any other sky boxes.
	//   9. Put the camera back where it was to begin with.
	//
	void RenderPortal::RenderPlanePortals()
	{
		numskyboxes = 0;

		VisiblePlaneList *planes = Thread->PlaneList.get();
		DrawSegmentList *drawseglist = Thread->DrawSegments.get();

		if (!planes->HasPortalPlanes())
			return;

		Thread->Clip3D->EnterSkybox();
		CurrentPortalInSkybox = true;

		int savedextralight = Thread->Viewport->viewpoint.extralight;
		DVector3 savedpos = Thread->Viewport->viewpoint.Pos;
		DRotator savedangles = Thread->Viewport->viewpoint.Angles;
		double savedvisibility = Thread->Light->GetVisibility();
		AActor *savedcamera = Thread->Viewport->viewpoint.camera;
		sector_t *savedsector = Thread->Viewport->viewpoint.sector;

		for (VisiblePlane *pl = planes->PopFirstPortalPlane(); pl != nullptr; pl = planes->PopFirstPortalPlane())
		{
			if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == nullptr)
			{
				pl->Render(Thread, OPAQUE, false, false);
				continue;
			}

			numskyboxes++;

			FSectorPortal *port = pl->portal;
			switch (port->mType)
			{
			case PORTS_SKYVIEWPOINT:
			{
				// Don't let gun flashes brighten the sky box
				AActor *sky = port->mSkybox;
				Thread->Viewport->viewpoint.extralight = 0;
				Thread->Light->SetVisibility(Thread->Viewport.get(), sky->args[0] * 0.25f);

				Thread->Viewport->viewpoint.Pos = sky->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac);
				Thread->Viewport->viewpoint.Angles.Yaw = savedangles.Yaw + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * Thread->Viewport->viewpoint.TicFrac);

				CopyStackedViewParameters();
				break;
			}

			case PORTS_STACKEDSECTORTHING:
			case PORTS_PORTAL:
			case PORTS_LINKEDPORTAL:
				Thread->Viewport->viewpoint.extralight = pl->extralight;
				Thread->Light->SetVisibility(Thread->Viewport.get(), pl->visibility);
				Thread->Viewport->viewpoint.Pos.X = pl->viewpos.X + port->mDisplacement.X;
				Thread->Viewport->viewpoint.Pos.Y = pl->viewpos.Y + port->mDisplacement.Y;
				Thread->Viewport->viewpoint.Pos.Z = pl->viewpos.Z;
				Thread->Viewport->viewpoint.Angles.Yaw = pl->viewangle;
				break;

			case PORTS_HORIZON:
			case PORTS_PLANE:
				// not implemented yet

			default:
				pl->Render(Thread, OPAQUE, false, false);
				numskyboxes--;
				continue;
			}

			SetInSkyBox(port);
			if (port->mPartner > 0) SetInSkyBox(&level.sectorPortals[port->mPartner]);
			Thread->Viewport->viewpoint.camera = nullptr;
			Thread->Viewport->viewpoint.sector = port->mDestination;
			assert(Thread->Viewport->viewpoint.sector != nullptr);
			R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow);
			Thread->OpaquePass->ClearSeenSprites();
			Thread->Clip3D->ClearFakeFloors();

			planes->ClearKeepFakePlanes();
			Thread->ClipSegments->Clear(pl->left, pl->right);
			WindowLeft = pl->left;
			WindowRight = pl->right;

			auto ceilingclip = Thread->OpaquePass->ceilingclip;
			auto floorclip = Thread->OpaquePass->floorclip;
			for (int i = pl->left; i < pl->right; i++)
			{
				if (pl->top[i] == 0x7fff)
				{
					ceilingclip[i] = viewheight;
					floorclip[i] = -1;
				}
				else
				{
					ceilingclip[i] = pl->top[i];
					floorclip[i] = pl->bottom[i];
				}
			}

			drawseglist->PushPortal();
			Thread->SpriteList->PushPortal();
			viewposStack.Push(Thread->Viewport->viewpoint.Pos);
			visplaneStack.Push(pl);

			// Create a drawseg to clip sprites to the sky plane
			DrawSegment *draw_segment = Thread->FrameMemory->NewObject<DrawSegment>();
			draw_segment->CurrentPortalUniq = CurrentPortalUniq;
			draw_segment->siz1 = INT_MAX;
			draw_segment->siz2 = INT_MAX;
			draw_segment->sz1 = 0;
			draw_segment->sz2 = 0;
			draw_segment->x1 = pl->left;
			draw_segment->x2 = pl->right;
			draw_segment->silhouette = SIL_BOTH;
			draw_segment->sprbottomclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left);
			draw_segment->sprtopclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left);
			draw_segment->maskedtexturecol = nullptr;
			draw_segment->swall = nullptr;
			draw_segment->bFogBoundary = false;
			draw_segment->curline = nullptr;
			draw_segment->foggy = false;
			memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));
			memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
			drawseglist->Push(draw_segment);

			Thread->OpaquePass->RenderScene();
			Thread->Clip3D->ResetClip(); // reset clips (floor/ceiling)
			planes->Render();

			ClearInSkyBox(port);
			if (port->mPartner > 0) SetInSkyBox(&level.sectorPortals[port->mPartner]);
		}

		// Draw all the masked textures in a second pass, in the reverse order they
		// were added. This must be done separately from the previous step for the
		// sake of nested skyboxes.
		while (viewposStack.Size() > 0)
		{
			// Masked textures and planes need the view coordinates restored for proper positioning.
			viewposStack.Pop(Thread->Viewport->viewpoint.Pos);
			
			Thread->TranslucentPass->Render();

			VisiblePlane *pl = nullptr;	// quiet, GCC!
			visplaneStack.Pop(pl);
			if (pl->Alpha > 0 && pl->picnum != skyflatnum)
			{
				pl->Render(Thread, pl->Alpha, pl->Additive, true);
			}
			
			Thread->SpriteList->PopPortal();
			drawseglist->PopPortal();
		}

		Thread->Viewport->viewpoint.camera = savedcamera;
		Thread->Viewport->viewpoint.sector = savedsector;
		Thread->Viewport->viewpoint.Pos = savedpos;
		Thread->Light->SetVisibility(Thread->Viewport.get(), savedvisibility);
		Thread->Viewport->viewpoint.extralight = savedextralight;
		Thread->Viewport->viewpoint.Angles = savedangles;
		R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow);

		CurrentPortalInSkybox = false;
		Thread->Clip3D->LeaveSkybox();

		if (Thread->Clip3D->fakeActive) return;

		planes->ClearPortalPlanes();
	}
Esempio n. 3
0
void R_DrawPortals ()
{
	static TArray<size_t> interestingStack;
	static TArray<ptrdiff_t> drawsegStack;
	static TArray<ptrdiff_t> visspriteStack;
	static TArray<DVector3> viewposStack;
	static TArray<visplane_t *> visplaneStack;

	numskyboxes = 0;

	if (visplanes[MAXVISPLANES] == NULL)
		return;

	R_3D_EnterSkybox();
	CurrentPortalInSkybox = true;

	int savedextralight = extralight;
	DVector3 savedpos = ViewPos;
	DAngle savedangle = ViewAngle;
	ptrdiff_t savedvissprite_p = vissprite_p - vissprites;
	ptrdiff_t savedds_p = ds_p - drawsegs;
	ptrdiff_t savedlastopening = lastopening;
	size_t savedinteresting = FirstInterestingDrawseg;
	double savedvisibility = R_GetVisibility();
	AActor *savedcamera = camera;
	sector_t *savedsector = viewsector;

	int i;
	visplane_t *pl;

	for (pl = visplanes[MAXVISPLANES]; pl != NULL; pl = visplanes[MAXVISPLANES])
	{
		// Pop the visplane off the list now so that if this skybox adds more
		// skyboxes to the list, they will be drawn instead of skipped (because
		// new skyboxes go to the beginning of the list instead of the end).
		visplanes[MAXVISPLANES] = pl->next;
		pl->next = NULL;

		if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == NULL)
		{
			R_DrawSinglePlane (pl, OPAQUE, false, false);
			*freehead = pl;
			freehead = &pl->next;
			continue;
		}

		numskyboxes++;

		FSectorPortal *port = pl->portal;
		switch (port->mType)
		{
		case PORTS_SKYVIEWPOINT:
		{
			// Don't let gun flashes brighten the sky box
			ASkyViewpoint *sky = barrier_cast<ASkyViewpoint*>(port->mSkybox);
			extralight = 0;
			R_SetVisibility(sky->args[0] * 0.25f);

			ViewPos = sky->InterpolatedPosition(r_TicFracF);
			ViewAngle = savedangle + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * r_TicFracF);

			R_CopyStackedViewParameters();
			break;
		}

		case PORTS_STACKEDSECTORTHING:
		case PORTS_PORTAL:
		case PORTS_LINKEDPORTAL:
			extralight = pl->extralight;
			R_SetVisibility (pl->visibility);
			ViewPos.X = pl->viewpos.X + port->mDisplacement.X;
			ViewPos.Y = pl->viewpos.Y + port->mDisplacement.Y;
			ViewPos.Z = pl->viewpos.Z;
			ViewAngle = pl->viewangle;
			break;

		case PORTS_HORIZON:
		case PORTS_PLANE:
			// not implemented yet

		default:
			R_DrawSinglePlane(pl, OPAQUE, false, false);
			*freehead = pl;
			freehead = &pl->next;
			numskyboxes--;
			continue;
		}

		port->mFlags |= PORTSF_INSKYBOX;
		if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags |= PORTSF_INSKYBOX;
		camera = NULL;
		viewsector = port->mDestination;
		assert(viewsector != NULL);
		R_SetViewAngle ();
		validcount++;	// Make sure we see all sprites

		R_ClearPlanes (false);
		R_ClearClipSegs (pl->left, pl->right);
		WindowLeft = pl->left;
		WindowRight = pl->right;

		for (i = pl->left; i < pl->right; i++)
		{
			if (pl->top[i] == 0x7fff)
			{
				ceilingclip[i] = viewheight;
				floorclip[i] = -1;
			}
			else
			{
				ceilingclip[i] = pl->top[i];
				floorclip[i] = pl->bottom[i];
			}
		}

		// Create a drawseg to clip sprites to the sky plane
		R_CheckDrawSegs ();
		ds_p->CurrentPortalUniq = CurrentPortalUniq;
		ds_p->siz1 = INT_MAX;
		ds_p->siz2 = INT_MAX;
		ds_p->sz1 = 0;
		ds_p->sz2 = 0;
		ds_p->x1 = pl->left;
		ds_p->x2 = pl->right;
		ds_p->silhouette = SIL_BOTH;
		ds_p->sprbottomclip = R_NewOpening (pl->right - pl->left);
		ds_p->sprtopclip = R_NewOpening (pl->right - pl->left);
		ds_p->maskedtexturecol = ds_p->swall = -1;
		ds_p->bFogBoundary = false;
		ds_p->curline = NULL;
		ds_p->fake = 0;
		memcpy (openings + ds_p->sprbottomclip, floorclip + pl->left, (pl->right - pl->left)*sizeof(short));
		memcpy (openings + ds_p->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left)*sizeof(short));

		firstvissprite = vissprite_p;
		firstdrawseg = ds_p++;
		FirstInterestingDrawseg = InterestingDrawsegs.Size();

		interestingStack.Push (FirstInterestingDrawseg);
		ptrdiff_t diffnum = firstdrawseg - drawsegs;
		drawsegStack.Push (diffnum);
		diffnum = firstvissprite - vissprites;
		visspriteStack.Push (diffnum);
		viewposStack.Push(ViewPos);
		visplaneStack.Push (pl);

		InSubsector = NULL;
		R_RenderBSPNode (nodes + numnodes - 1);
		R_3D_ResetClip(); // reset clips (floor/ceiling)
		R_DrawPlanes ();

		port->mFlags &= ~PORTSF_INSKYBOX;
		if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags &= ~PORTSF_INSKYBOX;
	}

	// Draw all the masked textures in a second pass, in the reverse order they
	// were added. This must be done separately from the previous step for the
	// sake of nested skyboxes.
	while (interestingStack.Pop (FirstInterestingDrawseg))
	{
		ptrdiff_t pd = 0;

		drawsegStack.Pop (pd);
		firstdrawseg = drawsegs + pd;
		visspriteStack.Pop (pd);
		firstvissprite = vissprites + pd;

		// Masked textures and planes need the view coordinates restored for proper positioning.
		viewposStack.Pop(ViewPos);

		R_DrawMasked ();

		ds_p = firstdrawseg;
		vissprite_p = firstvissprite;

		visplaneStack.Pop (pl);
		if (pl->Alpha > 0 && pl->picnum != skyflatnum)
		{
			R_DrawSinglePlane (pl, pl->Alpha, pl->Additive, true);
		}
		*freehead = pl;
		freehead = &pl->next;
	}
	firstvissprite = vissprites;
	vissprite_p = vissprites + savedvissprite_p;
	firstdrawseg = drawsegs;
	ds_p = drawsegs + savedds_p;
	InterestingDrawsegs.Resize ((unsigned int)FirstInterestingDrawseg);
	FirstInterestingDrawseg = savedinteresting;

	lastopening = savedlastopening;

	camera = savedcamera;
	viewsector = savedsector;
	ViewPos = savedpos;
	R_SetVisibility(savedvisibility);
	extralight = savedextralight;
	ViewAngle = savedangle;
	R_SetViewAngle ();

	CurrentPortalInSkybox = false;
	R_3D_LeaveSkybox();

	if(fakeActive) return;

	for (*freehead = visplanes[MAXVISPLANES], visplanes[MAXVISPLANES] = NULL; *freehead; )
		freehead = &(*freehead)->next;
}