void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, const FMaterialRenderProxy* MaterialProxy, const FDeferredDecalProxy& DecalProxy, const float FadeAlphaValue=1.0f)
	{
		const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();

		FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(View.GetFeatureLevel()), View, true, ESceneRenderTargetsMode::SetTextures);

		FTransform ComponentTrans = DecalProxy.ComponentTrans;

		FMatrix WorldToComponent = ComponentTrans.ToInverseMatrixWithScale();

		// Set the transform from screen space to light space.
		if(ScreenToDecal.IsBound())
		{
			const FMatrix ScreenToDecalValue = 
				FMatrix(
					FPlane(1,0,0,0),
					FPlane(0,1,0,0),
					FPlane(0,0,View.ViewMatrices.ProjMatrix.M[2][2],1),
					FPlane(0,0,View.ViewMatrices.ProjMatrix.M[3][2],0)
				) * View.InvViewProjectionMatrix * WorldToComponent;

			SetShaderValue(RHICmdList, ShaderRHI, ScreenToDecal, ScreenToDecalValue);
		}

		// Set the transform from light space to world space
		if(DecalToWorld.IsBound())
		{
			const FMatrix DecalToWorldValue = ComponentTrans.ToMatrixWithScale();
			
			SetShaderValue(RHICmdList, ShaderRHI, DecalToWorld, DecalToWorldValue);
		}

		SetShaderValue(RHICmdList, ShaderRHI, FadeAlpha, FadeAlphaValue);
		SetShaderValue(RHICmdList, ShaderRHI, WorldToDecal, WorldToComponent);
	}
FMatrix OSVRHMDDescription::GetProjectionMatrix(EEye Eye) const
{
	// @TODO: a proper stereo projection matrix should be calculated

	const float ProjectionCenterOffset = 0.151976421f;
	const float PassProjectionOffset = (Eye == LEFT_EYE) ? ProjectionCenterOffset : -ProjectionCenterOffset;

#if 1
	const float HalfFov = FMath::DegreesToRadians(GetFov(Eye).X) / 2.f;
	const float InWidth = GetDisplaySize(Eye).X;
	const float InHeight = GetDisplaySize(Eye).Y;
	const float XS = 1.0f / tan(HalfFov);
	const float YS = InWidth / tan(HalfFov) / InHeight;
#else
	const float HalfFov = 2.19686294f / 2.f;
	const float InWidth = 640.f;
	const float InHeight = 480.f;
	const float XS = 1.0f / tan(HalfFov);
	const float YS = InWidth / tan(HalfFov) / InHeight;
#endif

	const float InNearZ = GNearClippingPlane;
	return FMatrix(
			   FPlane(XS, 0.0f, 0.0f, 0.0f),
			   FPlane(0.0f, YS, 0.0f, 0.0f),
			   FPlane(0.0f, 0.0f, 0.0f, 1.0f),
			   FPlane(0.0f, 0.0f, InNearZ, 0.0f))

		   *
		   FTranslationMatrix(FVector(PassProjectionOffset, 0, 0));
}
示例#3
0
void FSceneView::UpdateViewMatrix()
{
	FVector StereoViewLocation = ViewLocation;
	if (GEngine->IsStereoscopic3D() && StereoPass != eSSP_FULL)
	{
		GEngine->StereoRenderingDevice->CalculateStereoViewOffset(StereoPass, ViewRotation, WorldToMetersScale, StereoViewLocation);
		ViewLocation = StereoViewLocation;
	}

	ViewMatrices.ViewOrigin = StereoViewLocation;

	ViewMatrices.ViewMatrix = FTranslationMatrix(-StereoViewLocation);
	ViewMatrices.ViewMatrix = ViewMatrices.ViewMatrix * FInverseRotationMatrix(ViewRotation);
	ViewMatrices.ViewMatrix = ViewMatrices.ViewMatrix * FMatrix(
		FPlane(0,	0,	1,	0),
		FPlane(1,	0,	0,	0),
		FPlane(0,	1,	0,	0),
		FPlane(0,	0,	0,	1));
 
	ViewMatrices.PreViewTranslation = -ViewMatrices.ViewOrigin;
	FMatrix TranslatedViewMatrix = FTranslationMatrix(-ViewMatrices.PreViewTranslation) * ViewMatrices.ViewMatrix;
	
	// Compute a transform from view origin centered world-space to clip space.
	ViewMatrices.TranslatedViewProjectionMatrix = TranslatedViewMatrix * ViewMatrices.ProjMatrix;
	ViewMatrices.InvTranslatedViewProjectionMatrix = ViewMatrices.TranslatedViewProjectionMatrix.Inverse();

	ViewProjectionMatrix = ViewMatrices.GetViewProjMatrix();
	InvViewMatrix = ViewMatrices.GetInvViewMatrix();
	InvViewProjectionMatrix = ViewMatrices.GetInvViewProjMatrix();

}
void FScene::UpdateSceneCaptureContents(USceneCaptureComponent2D* CaptureComponent)
{
	check(CaptureComponent);

	if (CaptureComponent->TextureTarget)
	{
		const FTransform& Transform = CaptureComponent->GetComponentToWorld();
		FMatrix ViewMatrix = Transform.ToInverseMatrixWithScale();
		FVector ViewLocation = Transform.GetTranslation();
		// swap axis st. x=z,y=x,z=y (unreal coord space) so that z is up
		ViewMatrix = ViewMatrix * FMatrix(
			FPlane(0,	0,	1,	0),
			FPlane(1,	0,	0,	0),
			FPlane(0,	1,	0,	0),
			FPlane(0,	0,	0,	1));
		const float FOV = CaptureComponent->FOVAngle * (float)PI / 360.0f;
		const bool bUseSceneColorTexture = CaptureComponent->CaptureSource == SCS_SceneColorHDR;
		FSceneRenderer* SceneRenderer = CreateSceneRenderer(CaptureComponent, CaptureComponent->TextureTarget, ViewMatrix , ViewLocation, FOV, CaptureComponent->MaxViewDistanceOverride, bUseSceneColorTexture, &CaptureComponent->PostProcessSettings, CaptureComponent->PostProcessBlendWeight);

		FTextureRenderTargetResource* TextureRenderTarget = CaptureComponent->TextureTarget->GameThread_GetRenderTargetResource();
		const FName OwnerName = CaptureComponent->GetOwner() ? CaptureComponent->GetOwner()->GetFName() : NAME_None;

		ENQUEUE_UNIQUE_RENDER_COMMAND_FOURPARAMETER( 
			CaptureCommand,
			FSceneRenderer*, SceneRenderer, SceneRenderer,
			FTextureRenderTargetResource*, TextureRenderTarget, TextureRenderTarget,
			FName, OwnerName, OwnerName,
			bool, bUseSceneColorTexture, bUseSceneColorTexture,
		{
			UpdateSceneCaptureContent_RenderThread(RHICmdList, SceneRenderer, TextureRenderTarget, OwnerName, FResolveParams(), bUseSceneColorTexture);
		});
	}
FSlateD3DRenderer::FSlateD3DRenderer( const ISlateStyle& InStyle )
{

	ViewMatrix = FMatrix(	FPlane(1,	0,	0,	0),
							FPlane(0,	1,	0,	0),
							FPlane(0,	0,	1,  0),
							FPlane(0,	0,	0,	1));

}
FSlateOpenGLRenderer::FSlateOpenGLRenderer( const ISlateStyle& InStyle )
:	Style( InStyle )
{

	ViewMatrix = FMatrix(	FPlane(1,	0,	0,	0),
							FPlane(0,	1,	0,	0),
							FPlane(0,	0,	1,  0),
							FPlane(0,	0,	0,	1));

}
示例#7
0
FMatrix FCanvas::CalcBaseTransform2D(uint32 ViewSizeX, uint32 ViewSizeY)
{
	return AdjustProjectionMatrixForRHI(
		FTranslationMatrix(FVector(-GPixelCenterOffset,-GPixelCenterOffset,0)) *
		FMatrix(
			FPlane(	1.0f / (ViewSizeX / 2.0f),	0.0,										0.0f,	0.0f	),
			FPlane(	0.0f,						-1.0f / (ViewSizeY / 2.0f),					0.0f,	0.0f	),
			FPlane(	0.0f,						0.0f,										1.0f,	0.0f	),
			FPlane(	-1.0f,						1.0f,										0.0f,	1.0f	)
			)
		);
}
FSceneView* FJavascriptUMGViewportClient::CalcSceneView(FSceneViewFamily* ViewFamily)
{
	FSceneViewInitOptions ViewInitOptions;

	const FVector& ViewLocation = GetViewLocation();
	const FRotator& ViewRotation = GetViewRotation();

	const FIntPoint ViewportSizeXY = Viewport->GetSizeXY();

	FIntRect ViewRect = FIntRect(0, 0, ViewportSizeXY.X, ViewportSizeXY.Y);
	ViewInitOptions.SetViewRectangle(ViewRect);

	ViewInitOptions.ViewOrigin = ViewLocation;

	ViewInitOptions.ViewRotationMatrix = FInverseRotationMatrix(ViewRotation);
	ViewInitOptions.ViewRotationMatrix = ViewInitOptions.ViewRotationMatrix * FMatrix(
		FPlane(0, 0, 1, 0),
		FPlane(1, 0, 0, 0),
		FPlane(0, 1, 0, 0),
		FPlane(0, 0, 0, 1));

	//@TODO: Should probably be locally configurable (or just made into a FMinimalViewInfo property)
	const EAspectRatioAxisConstraint AspectRatioAxisConstraint = GetDefault<ULocalPlayer>()->AspectRatioAxisConstraint;

	FMinimalViewInfo::CalculateProjectionMatrixGivenView(ViewInfo, AspectRatioAxisConstraint, Viewport, /*inout*/ ViewInitOptions);

	ViewInitOptions.ViewFamily = ViewFamily;
	ViewInitOptions.SceneViewStateInterface = ViewState.GetReference();
	ViewInitOptions.ViewElementDrawer = this;

	ViewInitOptions.BackgroundColor = GetBackgroundColor();

	//ViewInitOptions.EditorViewBitflag = 0, // send the bit for this view - each actor will check it's visibility bits against this

	// for ortho views to steal perspective view origin
	//ViewInitOptions.OverrideLODViewOrigin = FVector::ZeroVector;
	//ViewInitOptions.bUseFauxOrthoViewPos = true;

	//ViewInitOptions.CursorPos = CurrentMousePos;

	FSceneView* View = new FSceneView(ViewInitOptions);

	ViewFamily->Views.Add(View);

	View->StartFinalPostprocessSettings(ViewLocation);

	//OverridePostProcessSettings(*View);

	View->EndFinalPostprocessSettings(ViewInitOptions);

	return View;
}
	void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, const FMaterialRenderProxy* MaterialProxy, const FDeferredDecalProxy& DecalProxy, const float FadeAlphaValue=1.0f)
	{
		const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();

		FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(View.GetFeatureLevel()), View, View.ViewUniformBuffer, true, ESceneRenderTargetsMode::SetTextures);

		FTransform ComponentTrans = DecalProxy.ComponentTrans;

		FMatrix WorldToComponent = ComponentTrans.ToInverseMatrixWithScale();

		// Set the transform from screen space to light space.
		if(SvPositionToDecal.IsBound())
		{
			FVector2D InvViewSize = FVector2D(1.0f / View.ViewRect.Width(), 1.0f / View.ViewRect.Height());

			// setup a matrix to transform float4(SvPosition.xyz,1) directly to Decal (quality, performance as we don't need to convert or use interpolator)

			//	new_xy = (xy - ViewRectMin.xy) * ViewSizeAndInvSize.zw * float2(2,-2) + float2(-1, 1);

			//  transformed into one MAD:  new_xy = xy * ViewSizeAndInvSize.zw * float2(2,-2)      +       (-ViewRectMin.xy) * ViewSizeAndInvSize.zw * float2(2,-2) + float2(-1, 1);

			float Mx = 2.0f * InvViewSize.X;
			float My = -2.0f * InvViewSize.Y;
			float Ax = -1.0f - 2.0f * View.ViewRect.Min.X * InvViewSize.X;
			float Ay = 1.0f + 2.0f * View.ViewRect.Min.Y * InvViewSize.Y;

			// todo: we could use InvTranslatedViewProjectionMatrix and TranslatedWorldToComponent for better quality
			const FMatrix SvPositionToDecalValue = 
				FMatrix(
					FPlane(Mx,  0,   0,  0),
					FPlane( 0, My,   0,  0),
					FPlane( 0,  0,   1,  0),
					FPlane(Ax, Ay,   0,  1)
				) * View.InvViewProjectionMatrix * WorldToComponent;

			SetShaderValue(RHICmdList, ShaderRHI, SvPositionToDecal, SvPositionToDecalValue);
		}

		// Set the transform from light space to world space
		if(DecalToWorld.IsBound())
		{
			const FMatrix DecalToWorldValue = ComponentTrans.ToMatrixWithScale();
			
			SetShaderValue(RHICmdList, ShaderRHI, DecalToWorld, DecalToWorldValue);
		}

		SetShaderValue(RHICmdList, ShaderRHI, WorldToDecal, WorldToComponent);

		float LifetimeAlpha = FMath::Clamp(View.Family->CurrentWorldTime * -DecalProxy.InvFadeDuration + DecalProxy.FadeStartDelayNormalized, 0.0f, 1.0f);
		SetShaderValue(RHICmdList, ShaderRHI, DecalParams, FVector2D(FadeAlphaValue, LifetimeAlpha));
	}
void ULevelThumbnailRenderer::GetView(ULevel* Level, FSceneViewFamily* ViewFamily, int32 X, int32 Y, uint32 SizeX, uint32 SizeY) const 
{
	check(ViewFamily);

	FIntRect ViewRect(
		FMath::Max<int32>(X,0),
		FMath::Max<int32>(Y,0),
		FMath::Max<int32>(X+SizeX,0),
		FMath::Max<int32>(Y+SizeY,0));

	FBox LevelBox(0);

	if (Level->LevelBoundsActor.IsValid())
	{
		LevelBox = Level->LevelBoundsActor.Get()->GetComponentsBoundingBox();
	}
	else
	{
		LevelBox = ALevelBounds::CalculateLevelBounds(Level);
	}

	if (ViewRect.Width() > 0 && ViewRect.Height() > 0)
	{
		FSceneViewInitOptions ViewInitOptions;

		ViewInitOptions.SetViewRectangle(ViewRect);
		ViewInitOptions.ViewFamily = ViewFamily;

		const FVector ViewPoint = LevelBox.GetCenter();
		ViewInitOptions.ViewMatrix = FMatrix(
			FPlane(1,				0,				0,		0),
			FPlane(0,				-1,				0,		0),
			FPlane(0,				0,				-1,		0),
			FPlane(-ViewPoint.X,	ViewPoint.Y,	0,		1));

		const float ZOffset = WORLD_MAX;
		ViewInitOptions.ProjectionMatrix =  FReversedZOrthoMatrix(
			LevelBox.GetSize().X/2.f,
			LevelBox.GetSize().Y/2.f,
			0.5f / ZOffset,
			ZOffset
			);

		FSceneView* NewView = new FSceneView(ViewInitOptions);

		ViewFamily->Views.Add(NewView);
	}
}
static FMatrix CreateProjectionMatrixD3D( uint32 Width, uint32 Height )
{
	// Create ortho projection matrix
	const float Left = 0.0f;//0.5f
	const float Right = Left+Width;
	const float Top = 0.0f;//0.5f
	const float Bottom = Top+Height;
	const float ZNear = 0;
	const float ZFar = 1;

	return	FMatrix( FPlane(2.0f/(Right-Left),			0,							0,					0 ),
					 FPlane(0,							2.0f/(Top-Bottom),			0,					0 ),
					 FPlane(0,							0,							1/(ZNear-ZFar),		0 ),
					 FPlane((Left+Right)/(Left-Right),	(Top+Bottom)/(Bottom-Top),	ZNear/(ZNear-ZFar), 1 ) );

}
示例#12
0
FSceneNode* URender11::CreateMasterFrame( UViewport* Viewport, FVector Location, FRotator Rotation, FScreenBounds* Bounds )
{
    // Set base info.
    FSceneNode* Frame = new(GSceneMem)FSceneNode;
    Frame->Viewport = Viewport;
    Frame->X = Viewport->SizeX;
    Frame->Y = Viewport->SizeY;
    Frame->XB = 0;
    Frame->YB = 0;
    Frame->Level = Viewport->Actor->GetLevel();
    Frame->Parent = NULL;
    Frame->Sibling = NULL;
    Frame->Child = NULL;
    Frame->iSurf = INDEX_NONE;
    Frame->Recursion = 0;
    Frame->Mirror = 1.0;
    Frame->Recursion = 0;
    Frame->NearClip = FPlane(0, 0, 0, 0);
    Frame->Draw[0] = NULL;
    Frame->Draw[1] = NULL;
    Frame->Draw[2] = NULL;
    Frame->Sprite = NULL;
    Frame->Span = new(GSceneMem)FSpanBuffer;
    Frame->Span->AllocIndexForScreen(Viewport->SizeX, Viewport->SizeY, &GSceneMem);
    
    // Compute coords.
    Frame->ComputeRenderCoords(Location, Rotation);

    // Compute zone.
    Frame->ZoneNumber = Viewport->Actor->GetLevel()->Model->PointRegion(Viewport->Actor->GetLevel()->GetLevelInfo(), Frame->Coords.Origin).ZoneNumber;

    return Frame;
}
示例#13
0
/**
 * Builds the permuted planes for SIMD fast clipping
 */
void FConvexVolume::Init(void)
{
	int32 NumToAdd = Planes.Num() / 4;
	int32 NumRemaining = Planes.Num() % 4;
	// Presize the array
	PermutedPlanes.Empty(NumToAdd * 4 + (NumRemaining ? 4 : 0));
	// For each set of four planes
	for (int32 Count = 0, Offset = 0; Count < NumToAdd; Count++, Offset += 4)
	{
		// Add them in SSE ready form
		new(PermutedPlanes)FPlane(Planes[Offset + 0].X,Planes[Offset + 1].X,Planes[Offset + 2].X,Planes[Offset + 3].X);
		new(PermutedPlanes)FPlane(Planes[Offset + 0].Y,Planes[Offset + 1].Y,Planes[Offset + 2].Y,Planes[Offset + 3].Y);
		new(PermutedPlanes)FPlane(Planes[Offset + 0].Z,Planes[Offset + 1].Z,Planes[Offset + 2].Z,Planes[Offset + 3].Z);
		new(PermutedPlanes)FPlane(Planes[Offset + 0].W,Planes[Offset + 1].W,Planes[Offset + 2].W,Planes[Offset + 3].W);
	}
	// Pad the last set so we have an even 4 planes of vert data
	if (NumRemaining)
	{
		FPlane Last1, Last2, Last3, Last4;
		// Read the last set of verts
		switch (NumRemaining)
		{
			case 3:
			{
				Last1 = Planes[NumToAdd * 4 + 0];
				Last2 = Planes[NumToAdd * 4 + 1];
				Last3 = Planes[NumToAdd * 4 + 2];
				Last4 = Last1;
				break;
			}
			case 2:
			{
				Last1 = Planes[NumToAdd * 4 + 0];
				Last2 = Planes[NumToAdd * 4 + 1];
				Last3 = Last4 = Last1;
				break;
			}
			case 1:
			{
				Last1 = Planes[NumToAdd * 4 + 0];
				Last2 = Last3 = Last4 = Last1;
				break;
			}
			default:
			{
				Last1 = FPlane(0, 0, 0, 0);
				Last2 = Last3 = Last4 = Last1;
				break;
			}
		}
		// Add them in SIMD ready form
		new(PermutedPlanes)FPlane(Last1.X,Last2.X,Last3.X,Last4.X);
		new(PermutedPlanes)FPlane(Last1.Y,Last2.Y,Last3.Y,Last4.Y);
		new(PermutedPlanes)FPlane(Last1.Z,Last2.Z,Last3.Z,Last4.Z);
		new(PermutedPlanes)FPlane(Last1.W,Last2.W,Last3.W,Last4.W);
	}
}
示例#14
0
FMatrix FSimpleHMD::GetStereoProjectionMatrix(const enum EStereoscopicPass StereoPassType, const float FOV) const
{
	const float ProjectionCenterOffset = 0.151976421f;
	const float PassProjectionOffset = (StereoPassType == eSSP_LEFT_EYE) ? ProjectionCenterOffset : -ProjectionCenterOffset;

	const float HalfFov = 2.19686294f / 2.f;
	const float InWidth = 640.f;
	const float InHeight = 480.f;
	const float XS = 1.0f / tan(HalfFov);
	const float YS = InWidth / tan(HalfFov) / InHeight;

	const float InNearZ = GNearClippingPlane;
	return FMatrix(
		FPlane(XS,                      0.0f,								    0.0f,							0.0f),
		FPlane(0.0f,					YS,	                                    0.0f,							0.0f),
		FPlane(0.0f,	                0.0f,								    0.0f,							1.0f),
		FPlane(0.0f,					0.0f,								    InNearZ,						0.0f))

		* FTranslationMatrix(FVector(PassProjectionOffset,0,0));
}
示例#15
0
FMatrix FCanvas::CalcViewMatrix(uint32 ViewSizeX, uint32 ViewSizeY, float fFOV)
{
	// convert FOV to randians
	float FOVRad = fFOV * (float)PI / 360.0f;
	// move camera back enough so that the canvas items being rendered are at the same screen extents as regular canvas 2d rendering	
	FTranslationMatrix CamOffsetMat(-FVector(0,0,-FMath::Tan(FOVRad)*ViewSizeX/2));
	// adjust so that canvas items render as if they start at [0,0] upper left corner of screen 
	// and extend to the lower right corner [ViewSizeX,ViewSizeY]. 
	FMatrix OrientCanvasMat(
		FPlane(	1.0f,				0.0f,				0.0f,	0.0f	),
		FPlane(	0.0f,				-1.0f,				0.0f,	0.0f	),
		FPlane(	0.0f,				0.0f,				1.0f,	0.0f	),
		FPlane(	ViewSizeX * -0.5f,	ViewSizeY * 0.5f,	0.0f, 1.0f		)
		);
	return 
		// also apply screen offset to align to pixel centers
		FTranslationMatrix(FVector(-GPixelCenterOffset,-GPixelCenterOffset,0)) * 
		OrientCanvasMat * 
		CamOffsetMat;
}
static FMatrix CreateProjectionMatrix( uint32 Width, uint32 Height )
{
	
	float PixelOffset = GPixelCenterOffset;

	// Create ortho projection matrix
	const float Left = PixelOffset;
	const float Right = Left+Width;
	const float Top = PixelOffset;
	const float Bottom = Top+Height;
	const float ZNear = -100.0f;
	const float ZFar = 100.0f;
	return AdjustProjectionMatrixForRHI(
		FMatrix(
			FPlane(2.0f/(Right-Left),			0,							0,					0 ),
			FPlane(0,							2.0f/(Top-Bottom),			0,					0 ),
			FPlane(0,							0,							1/(ZNear-ZFar),		0 ),
			FPlane((Left+Right)/(Left-Right),	(Top+Bottom)/(Bottom-Top),	ZNear/(ZNear-ZFar), 1 )
			)
		);
}
void UBerserkCameraComponent::UpdateCameraBounds(const APlayerController* playerController)
{
	auto const* const localPlayer = Cast<ULocalPlayer>(playerController->Player);
	if (localPlayer == nullptr || localPlayer->ViewportClient == nullptr) return;

	FVector2D currentViewportSize;
	localPlayer->ViewportClient->GetViewportSize(currentViewportSize);

	// calc frustum edge direction, from bottom left corner
	if (CameraMovementBounds.GetSize() == FVector::ZeroVector || currentViewportSize != CameraMovementViewportSize)
	{
		// calc frustum edge direction, from bottom left corner
		const FVector frustumRay2dDir = FVector(1, 1, 0).GetSafeNormal();
		const FVector frustumRay2dRight = FVector::CrossProduct(frustumRay2dDir, FVector::UpVector);
		const FQuat rotQuat(frustumRay2dRight, FMath::DegreesToRadians(90.0f - playerController->PlayerCameraManager->GetFOVAngle() * 0.5f));
		const FVector frustumRayDir = rotQuat.RotateVector(frustumRay2dDir);

		// collect 3 world bounds' points and matching frustum rays (bottom left, top left, bottom right)
		auto const* const gameState = GetWorld()->GetGameState<ABerserkGameState>();
		if (gameState)
		{
			const auto worldBounds = gameState->WorldBounds;

			if (worldBounds.GetSize() != FVector::ZeroVector)
			{
				const FVector worldBoundPoints[] = {
					FVector(worldBounds.Min.X, worldBounds.Min.Y, worldBounds.Max.Z),
					FVector(worldBounds.Min.X, worldBounds.Max.Y, worldBounds.Max.Z),
					FVector(worldBounds.Max.X, worldBounds.Min.Y, worldBounds.Max.Z)
				};
				const FVector frustumRays[] = {
					FVector(frustumRayDir.X, frustumRayDir.Y, frustumRayDir.Z),
					FVector(frustumRayDir.X, -frustumRayDir.Y, frustumRayDir.Z),
					FVector(-frustumRayDir.X, frustumRayDir.Y, frustumRayDir.Z)
				};

				// get camera plane for intersections
				const auto cameraPlane = FPlane(playerController->GetFocalLocation(), FVector::UpVector);

				// get matching points on camera plane
				const FVector cameraPlanePoints[3] = {
					FProjectionUtils::IntersectRayWithPlane(worldBoundPoints[0], frustumRays[0], cameraPlane) * MiniMapBoundsLimit,
					FProjectionUtils::IntersectRayWithPlane(worldBoundPoints[1], frustumRays[1], cameraPlane) * MiniMapBoundsLimit,
					FProjectionUtils::IntersectRayWithPlane(worldBoundPoints[2], frustumRays[2], cameraPlane) * MiniMapBoundsLimit
				};

				// create new bounds
				CameraMovementBounds = FBox(cameraPlanePoints, 3);
				CameraMovementViewportSize = currentViewportSize;
			}
		}
	}
}
示例#18
0
FMatrix FSteamVRHMD::GetStereoProjectionMatrix(const enum EStereoscopicPass StereoPassType, const float FOV) const
{
	check(IsStereoEnabled());

	vr::Hmd_Eye HmdEye = (StereoPassType == eSSP_LEFT_EYE) ? vr::Eye_Left : vr::Eye_Right;
	float Left, Right, Top, Bottom;

	VRSystem->GetProjectionRaw(HmdEye, &Right, &Left, &Top, &Bottom);
	Bottom *= -1.0f;
	Top *= -1.0f;
	Right *= -1.0f;
	Left *= -1.0f;

	float ZNear = GNearClippingPlane;

	float SumRL = (Right + Left);
	float SumTB = (Top + Bottom);
	float InvRL = (1.0f / (Right - Left));
	float InvTB = (1.0f / (Top - Bottom));

#if 1
	FMatrix Mat = FMatrix(
		FPlane((2.0f * InvRL), 0.0f, 0.0f, 0.0f),
		FPlane(0.0f, (2.0f * InvTB), 0.0f, 0.0f),
		FPlane((SumRL * InvRL), (SumTB * InvTB), 0.0f, 1.0f),
		FPlane(0.0f, 0.0f, ZNear, 0.0f)
		);
#else
	vr::HmdMatrix44_t SteamMat = VRSystem->GetProjectionMatrix(HmdEye, ZNear, 10000.0f, vr::API_DirectX);
	FMatrix Mat = ToFMatrix(SteamMat);

	Mat.M[3][3] = 0.0f;
	Mat.M[2][3] = 1.0f;
	Mat.M[2][2] = 0.0f;
	Mat.M[3][2] = ZNear;
#endif

	return Mat;

}
示例#19
0
/**  
 * Transforms a point from the view's world-space into the view's screen-space.  
 * Divides the resulting X, Y, Z by W before returning. 
 */
FPlane FSceneView::Project(const FVector& WorldPoint) const
{
	FPlane Result = WorldToScreen(WorldPoint);

	if (Result.W == 0)
	{
		Result.W = KINDA_SMALL_NUMBER;
	}

	const float RHW = 1.0f / Result.W;

	return FPlane(Result.X * RHW,Result.Y * RHW,Result.Z * RHW,Result.W);
}
	void SetParameters(const FSceneView& View, const FMaterialRenderProxy* MaterialProxy, const FDeferredDecalProxy& DecalProxy)
	{
		const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();

		FMaterialShader::SetParameters(ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(GRHIFeatureLevel), View, true, ESceneRenderTargetsMode::SetTextures);

		FTransform ComponentTrans = DecalProxy.ComponentTrans;

		// 1,1,1 requires no scale
		//			ComponentTrans = ComponentTrans.GetScaled(GDefaultDecalSize);

		FMatrix WorldToComponent = ComponentTrans.ToMatrixWithScale().Inverse();

		// Set the transform from screen space to light space.
		if(ScreenToDecal.IsBound())
		{
			const FMatrix ScreenToDecalValue = 
				FMatrix(
					FPlane(1,0,0,0),
					FPlane(0,1,0,0),
					FPlane(0,0,View.ViewMatrices.ProjMatrix.M[2][2],1),
					FPlane(0,0,View.ViewMatrices.ProjMatrix.M[3][2],0)
				) * View.InvViewProjectionMatrix * WorldToComponent;

			SetShaderValue(ShaderRHI, ScreenToDecal, ScreenToDecalValue);
		}

		// Set the transform from light space to world space (only for normals)
		if(DecalToWorld.IsBound())
		{
			const FMatrix DecalToWorldValue = ComponentTrans.ToMatrixNoScale();
			
			// 1,1,1 requires no scale
			//			DecalToWorldValue = DecalToWorldValue.GetScaled(GDefaultDecalSize);

			SetShaderValue(ShaderRHI, DecalToWorld, DecalToWorldValue);
		}
	}
void FRendererModule::GPUBenchmark(FSynthBenchmarkResults& InOut, float WorkScale)
{
	check(IsInGameThread());

	FSceneViewInitOptions ViewInitOptions;
	FIntRect ViewRect(0, 0, 1, 1);

	FBox LevelBox(FVector(-WORLD_MAX), FVector(+WORLD_MAX));
	ViewInitOptions.SetViewRectangle(ViewRect);

	// Initialize Projection Matrix and ViewMatrix since FSceneView initialization is doing some math on them.
	// Otherwise it trips NaN checks.
	const FVector ViewPoint = LevelBox.GetCenter();
	ViewInitOptions.ViewOrigin = FVector(ViewPoint.X, ViewPoint.Y, 0.0f);
	ViewInitOptions.ViewRotationMatrix = FMatrix(
		FPlane(1, 0, 0, 0),
		FPlane(0, -1, 0, 0),
		FPlane(0, 0, -1, 0),
		FPlane(0, 0, 0, 1));

	const float ZOffset = WORLD_MAX;
	ViewInitOptions.ProjectionMatrix = FReversedZOrthoMatrix(
		LevelBox.GetSize().X / 2.f,
		LevelBox.GetSize().Y / 2.f,
		0.5f / ZOffset,
		ZOffset
		);

	FSceneView DummyView(ViewInitOptions);

	ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER(
	  RendererGPUBenchmarkCommand,
	  FSceneView, DummyView, DummyView,
	  float, WorkScale, WorkScale,
	  FSynthBenchmarkResults&, InOut, InOut,
	{
		RendererGPUBenchmark(RHICmdList, InOut, DummyView, WorkScale);
	});
示例#22
0
int32 FPoly::Split( const FVector &InNormal, const FVector &InBase )
{
    // Split it.
    FPoly Front, Back;
    Front.Init();
    Back.Init();
    switch( SplitWithPlaneFast( FPlane(InBase,InNormal), &Front, &Back ))
    {
    case SP_Back:
        return 0;
    case SP_Split:
        *this = Front;
        return Vertices.Num();
    default:
        return Vertices.Num();
    }
}
//
// ClipNode - return the node containing a specified location from a number of coplanar nodes.
//
int32 ClipNode(const UModel& Model, int32 iNode, const FVector& HitLocation)
{
	while (iNode != INDEX_NONE)
	{
		const FBspNode& Node = Model.Nodes[iNode];
		int32 NumVertices = Node.NumVertices;

		// Only consider this node if it has some vertices.
		if (NumVertices > 0)
		{
			int32 iVertPool = Node.iVertPool;

			FVector PrevPt = Model.Points[Model.Verts[iVertPool + NumVertices - 1].pVertex];
			FVector Normal = Model.Surfs[Node.iSurf].Plane;
			float PrevDot = 0.f;

			for (int32 i = 0; i<NumVertices; i++)
			{
				FVector Pt = Model.Points[Model.Verts[iVertPool + i].pVertex];
				float Dot = FPlane(Pt, Normal ^ (Pt - PrevPt)).PlaneDot(HitLocation);
				// Check for sign change
				if ((Dot < 0.f && PrevDot > 0.f) || (Dot > 0.f && PrevDot < 0.f))
				{
					goto TryNextNode;
				}
				PrevPt = Pt;
				PrevDot = Dot;
			}

			return iNode;
		}

	TryNextNode:;
		iNode = Node.iPlane;
	}
	return INDEX_NONE;
}
示例#24
0
void USwFMOD::RenderAudioGeometry( FSceneNode* Frame )
{
	guard(USwFMOD::RenderAudioGeometry);
	FMOD_RESULT result;

	if( !GRenderDevice || !Geometry || !StatRender )
		return;

	static TArray<FMOD_VECTOR> poly;
	static FPlane linecolor = FPlane(1,0,0,1);

	int polys;
	SWF_FMOD_RCALL( Geometry->getNumPolygons(&polys) );
	for( int i=0; i<polys; ++i )
	{
		int tris;
		SWF_FMOD_RCALL( Geometry->getPolygonNumVertices(i,&tris) );

		if( poly.Num() < tris )
			poly.Insert(0,tris-poly.Num());

		for( int j=0; j<tris; ++j )
		{
			SWF_FMOD_RCALL( Geometry->getPolygonVertex(i,j,&poly(j)) );
			if( j != 0 )
			{
				// TODO :: offset by normal to prevent z-artifacts
				GRenderDevice->Draw3DLine( Frame, linecolor, 0, ToUEVector(poly(j-1)), ToUEVector(poly(j)) );
			}
		}

		// TODO :: render normal
		// TODO :: don't render distant ones
	}

	unguard;
}
void UInfiniteSystemComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

    // If disabled or we are not attached to a parent component, return.
    if (!bIsActive || !AttachParent || !GetWorld()) return;

    FVector CamLoc;
    FRotator CamRot;
    FVector PawnLoc;
    FVector NewLoc;

#if WITH_EDITOR
    if (GIsEditor)
    {
        if (!UpdateInEditor) return;

        TArray<FVector> viewLocations = GetWorld()->ViewLocationsRenderedLastFrame;
        if (viewLocations.Num() != 0)
        {
            CamLoc = viewLocations[0];
        }

        //FEditorViewportClient* client = (FEditorViewportClient*)GEditor->GetActiveViewport()->GetClient();
        //CamLoc = client->GetViewLocation();
        //CamRot = client->GetViewRotation();

        if (FollowMethod == LookAtLocation || FollowMethod == FollowCamera)
        {
            NewLoc = CamLoc;
            NewLoc = NewLoc.GridSnap(GridSnapSize);
            NewLoc.Z = AttachParent->GetComponentLocation().Z;
            AttachParent->SetWorldLocation(NewLoc);
        }
        else
        {
            AttachParent->SetRelativeLocation(FVector(0, 0, 0)); //Reset location
        }

        if (ScaleByDistance && FMath::Abs(CamLoc.Z - AttachParent->GetComponentLocation().Z) > ScaleStartDistance)
        {
            float DistScale = FMath::Abs(CamLoc.Z - AttachParent->GetComponentLocation().Z) / ScaleDistanceFactor;
            DistScale = FMath::Clamp(DistScale, ScaleMin, ScaleMax);
            AttachParent->SetRelativeScale3D(FVector(DistScale, DistScale, 1)); //Scale only on x & y axis
        }
        else if (!ScaleByDistance)
        {
            AttachParent->SetRelativeScale3D(FVector(1, 1, 1)); //Reset scale
        }
        return;
    }
#endif

    if (GetWorld()->WorldType == EWorldType::Game || GetWorld()->WorldType == EWorldType::PIE)
    {
        if (!GEngine || !GEngine->GetFirstLocalPlayerController(GetWorld())) return;

        GEngine->GetFirstLocalPlayerController(GetWorld())->PlayerCameraManager->GetCameraViewPoint(CamLoc, CamRot);

        if (GEngine->GetFirstLocalPlayerController(GetWorld())->GetPawn()) //null check
        {
            PawnLoc = GEngine->GetFirstLocalPlayerController(GetWorld())->GetPawn()->GetActorLocation();
        }
        else
        {
            PawnLoc = AttachParent->GetComponentLocation();
        }
    }

    switch (FollowMethod)
    {
    case LookAtLocation:
        if (!FMath::SegmentPlaneIntersection(CamLoc, CamLoc + CamRot.Vector() * MaxLookAtDistance, FPlane(AttachParent->GetComponentLocation(), FVector(0, 0, 1)), NewLoc))
        {
            NewLoc = CamLoc + CamRot.Vector() * MaxLookAtDistance;
        }
        break;
    case FollowCamera:
        NewLoc = CamLoc;
        break;
    case FollowPawn:
        NewLoc = PawnLoc;
        break;
    default:
        break;
    };

    //UE_LOG(LogTemp, Warning, TEXT("Camera Z Distance from Plane: %f"), FMath::Abs(CamLoc.Z - AttachParent->GetComponentLocation().Z));

    if (ScaleByDistance && FMath::Abs(CamLoc.Z - AttachParent->GetComponentLocation().Z) > ScaleStartDistance)
    {
        float DistScale = FMath::Abs(CamLoc.Z - AttachParent->GetComponentLocation().Z) / ScaleDistanceFactor;
        DistScale = FMath::Clamp(DistScale, ScaleMin, ScaleMax);
        AttachParent->SetRelativeScale3D(FVector(DistScale, DistScale, 1)); //Scale only on x & y axis
    }

    if (FollowMethod == Stationary) return;

    NewLoc = NewLoc.GridSnap(GridSnapSize);
    NewLoc.Z = AttachParent->GetComponentLocation().Z;
    AttachParent->SetWorldLocation(NewLoc);
}
void UWorldThumbnailRenderer::GetView(UWorld* World, FSceneViewFamily* ViewFamily, int32 X, int32 Y, uint32 SizeX, uint32 SizeY) const 
{
	check(ViewFamily);
	check(World);
	check(World->PersistentLevel);

	FIntRect ViewRect(
		FMath::Max<int32>(X, 0),
		FMath::Max<int32>(Y, 0),
		FMath::Max<int32>(X + SizeX, 0),
		FMath::Max<int32>(Y + SizeY, 0));

	if (ViewRect.Width() > 0 && ViewRect.Height() > 0)
	{
		FBox WorldBox(0);
		TArray<ULevel*> LevelsToRender = World->GetLevels();
		for ( auto* Level : LevelsToRender )
		{
			if (Level && Level->bIsVisible)
			{
				ALevelBounds* LevelBounds = Level->LevelBoundsActor.Get();
				if (!LevelBounds)
				{
					// Ensure a Level Bounds Actor exists for future renders
					FActorSpawnParameters SpawnParameters;
					SpawnParameters.OverrideLevel = Level;
					LevelBounds = World->SpawnActor<ALevelBounds>(SpawnParameters);
					LevelBounds->UpdateLevelBoundsImmediately();
					Level->LevelBoundsActor = LevelBounds;
				}

				if (!LevelBounds->IsUsingDefaultBounds())
				{
					WorldBox += LevelBounds->GetComponentsBoundingBox();
				}
			}
		}

		UWorldThumbnailInfo* ThumbnailInfo = Cast<UWorldThumbnailInfo>(World->ThumbnailInfo);
		if (!ThumbnailInfo)
		{
			ThumbnailInfo = UWorldThumbnailInfo::StaticClass()->GetDefaultObject<UWorldThumbnailInfo>();
		}

		const FVector Origin = WorldBox.GetCenter();
		FMatrix ViewMatrix = FTranslationMatrix(-Origin);
		FMatrix ProjectionMatrix;
		float FOVScreenSize = 0; // Screen size taking FOV into account
		if (ThumbnailInfo->CameraMode == ECameraProjectionMode::Perspective)
		{
			const float FOVDegrees = 30.f;
			const float HalfFOVRadians = FMath::DegreesToRadians<float>(FOVDegrees) * 0.5f;
			const float WorldRadius = WorldBox.GetSize().Size() / 2.f;
			float TargetDistance = WorldRadius / FMath::Tan(HalfFOVRadians);

			if (ensure(ThumbnailInfo))
			{
				if (TargetDistance + ThumbnailInfo->OrbitZoom < 0)
				{
					ThumbnailInfo->OrbitZoom = -TargetDistance;
				}
			}

			float OrbitPitch = GlobalOrbitPitchOffset + ThumbnailInfo->OrbitPitch;
			float OrbitYaw = GlobalOrbitYawOffset + ThumbnailInfo->OrbitYaw;
			float OrbitZoom = TargetDistance + ThumbnailInfo->OrbitZoom;

			// Ensure a minimum camera distance to prevent problems with really small objects
			const float MinCameraDistance = 48;
			OrbitZoom = FMath::Max<float>(MinCameraDistance, OrbitZoom);

			const FRotator RotationOffsetToViewCenter(0.f, 90.f, 0.f);
			ViewMatrix = ViewMatrix *
				FRotationMatrix(FRotator(0, OrbitYaw, 0)) *
				FRotationMatrix(FRotator(0, 0, OrbitPitch)) *
				FTranslationMatrix(FVector(0, OrbitZoom, 0)) *
				FInverseRotationMatrix(RotationOffsetToViewCenter);

			ViewMatrix = ViewMatrix * FMatrix(
				FPlane(0, 0, 1, 0),
				FPlane(1, 0, 0, 0),
				FPlane(0, 1, 0, 0),
				FPlane(0, 0, 0, 1));

			const float NearPlane = 1.0f;
			ProjectionMatrix = FReversedZPerspectiveMatrix(
				HalfFOVRadians,
				1.0f,
				1.0f,
				NearPlane
				);

			FOVScreenSize = SizeX / FMath::Tan(FOVDegrees);
		}
		else if (ThumbnailInfo->CameraMode == ECameraProjectionMode::Orthographic)
		{
			FVector2D WorldSizeMin2D;
			FVector2D WorldSizeMax2D;
			switch (ThumbnailInfo->OrthoDirection)
			{
				case EOrthoThumbnailDirection::Top:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(1, 0, 0, 0),
						FPlane(0, -1, 0, 0),
						FPlane(0, 0, -1, 0),
						FPlane(0, 0, Origin.Z, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.X,WorldBox.Min.Y);
					WorldSizeMax2D = FVector2D(WorldBox.Max.X,WorldBox.Max.Y);
					break;
				case EOrthoThumbnailDirection::Bottom:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(1, 0, 0, 0),
						FPlane(0, -1, 0, 0),
						FPlane(0, 0, 1, 0),
						FPlane(0, 0, Origin.Z, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.X, WorldBox.Min.Y);
					WorldSizeMax2D = FVector2D(WorldBox.Max.X, WorldBox.Max.Y);
					break;
				case EOrthoThumbnailDirection::Front:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(1, 0, 0, 0),
						FPlane(0, 0, -1, 0),
						FPlane(0, 1, 0, 0),
						FPlane(0, 0, Origin.Y, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.X, WorldBox.Min.Z);
					WorldSizeMax2D = FVector2D(WorldBox.Max.X, WorldBox.Max.Z);
					break;
				case EOrthoThumbnailDirection::Back:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(-1, 0, 0, 0),
						FPlane(0, 0, 1, 0),
						FPlane(0, 1, 0, 0),
						FPlane(0, 0, Origin.Y, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.X, WorldBox.Min.Z);
					WorldSizeMax2D = FVector2D(WorldBox.Max.X, WorldBox.Max.Z);
					break;
				case EOrthoThumbnailDirection::Left:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(0, 0, -1, 0),
						FPlane(-1, 0, 0, 0),
						FPlane(0, 1, 0, 0),
						FPlane(0, 0, Origin.X, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.Y, WorldBox.Min.Z);
					WorldSizeMax2D = FVector2D(WorldBox.Max.Y, WorldBox.Max.Z);
					break;
				case EOrthoThumbnailDirection::Right:
					ViewMatrix = ViewMatrix * FMatrix(
						FPlane(0, 0, 1, 0),
						FPlane(1, 0, 0, 0),
						FPlane(0, 1, 0, 0),
						FPlane(0, 0, Origin.X, 1));
					WorldSizeMin2D = FVector2D(WorldBox.Min.Y, WorldBox.Min.Z);
					WorldSizeMax2D = FVector2D(WorldBox.Max.Y, WorldBox.Max.Z);
					break;
				default:
					// Unknown OrthoDirection
					ensureMsgf(false, TEXT("Unknown thumbnail OrthoDirection"));
					break;
			}

			FVector2D WorldSize2D = (WorldSizeMax2D - WorldSizeMin2D);
			WorldSize2D.X = FMath::Abs(WorldSize2D.X);
			WorldSize2D.Y = FMath::Abs(WorldSize2D.Y);
			const bool bUseXAxis = (WorldSize2D.X / WorldSize2D.Y) > 1.f;
			const float WorldAxisSize = bUseXAxis ? WorldSize2D.X : WorldSize2D.Y;
			const uint32 ViewportAxisSize = bUseXAxis ? SizeX : SizeY;
			const float OrthoZoom = WorldAxisSize / ViewportAxisSize / 2.f;
			const float OrthoWidth = FMath::Max(1.f, SizeX * OrthoZoom);
			const float OrthoHeight = FMath::Max(1.f, SizeY * OrthoZoom);

			const float ZOffset = HALF_WORLD_MAX;
			ProjectionMatrix = FReversedZOrthoMatrix(
				OrthoWidth,
				OrthoHeight,
				0.5f / ZOffset,
				ZOffset
				);

			FOVScreenSize = SizeX;
		}
		else
		{
			// Unknown CameraMode
			ensureMsgf(false, TEXT("Unknown thumbnail CameraMode"));
		}

		FSceneViewInitOptions ViewInitOptions;
		ViewInitOptions.ViewFamily = ViewFamily;
		ViewInitOptions.SetViewRectangle(ViewRect);
		ViewInitOptions.BackgroundColor = FLinearColor::Black;
		ViewInitOptions.ViewMatrix = ViewMatrix;
		ViewInitOptions.ProjectionMatrix = ProjectionMatrix;

		FSceneView* NewView = new FSceneView(ViewInitOptions);

		ViewFamily->Views.Add(NewView);

		// Tell the texture streaming system about this thumbnail view, so the textures will stream in as needed
		// NOTE: Sizes may not actually be in screen space depending on how the thumbnail ends up stretched by the UI.  Not a big deal though.
		// NOTE: Textures still take a little time to stream if the view has not been re-rendered recently, so they may briefly appear blurry while mips are prepared
		// NOTE: Content Browser only renders thumbnails for loaded assets, and only when the mouse is over the panel. They'll be frozen in their last state while the mouse cursor is not over the panel.  This is for performance reasons
		IStreamingManager::Get().AddViewInformation(Origin, SizeX, FOVScreenSize);
	}
}
示例#27
0
void AStrategyHUD::DrawMiniMap()
{
	const AStrategyPlayerController* const PC = Cast<AStrategyPlayerController>(PlayerOwner);
	AStrategyGameState const* const MyGameState = GetWorld()->GetGameState<AStrategyGameState>();

	// @todo, clean this up
	if (PC && MyGameState && MyGameState->MiniMapCamera.IsValid())
	{
		const float BaseRotation = 270;
		UTexture* MiniMapTexture = Cast<UTexture>(MyGameState->MiniMapCamera->GetCaptureComponent2D()->TextureTarget);
		const float MapWidth = (MyGameState->MiniMapCamera->MiniMapWidth - MiniMapMargin) * UIScale;
		const float MapHeight = (MyGameState->MiniMapCamera->MiniMapHeight - MiniMapMargin) * UIScale;
		const FVector WorldCenter = MyGameState->WorldBounds.GetCenter();
		const FVector WorldExtent = MyGameState->WorldBounds.GetExtent();
		const FRotator RotOrg = MyGameState->MiniMapCamera->GetCaptureComponent2D()->GetComponentRotation();
		const FRotationMatrix RotationMatrix(FRotator(0,BaseRotation-RotOrg.Roll,0));
		const FVector2D Offset(MiniMapMargin * UIScale + (MapWidth/2.0f), Canvas->ClipY - (MapHeight/2.0f) - MiniMapMargin * UIScale );

		if (MiniMapTexture)
		{
			FCanvasTileItem MapTileItem( FVector2D( 0.0f, 0.0f), FVector2D( 0.0f, 0.0f ), FLinearColor::White );
			MapTileItem.Texture = MiniMapTexture->Resource;
			MapTileItem.Size = FVector2D( MapWidth, MapHeight );
			MapTileItem.BlendMode = SE_BLEND_Opaque;
			Canvas->DrawItem( MapTileItem, FVector2D( MiniMapMargin * UIScale, Canvas->ClipY - MapHeight - MiniMapMargin * UIScale ) );
		}
		FCanvasTileItem TileItem( FVector2D( 0.0f, 0.0f), FVector2D( 0.0f, 0.0f ), FLinearColor::White );
		TileItem.Size = FVector2D( 6 * UIScale, 6 * UIScale );
		for (FConstPawnIterator Iterator = GetWorld()->GetPawnIterator(); Iterator; ++Iterator)
		{
			AStrategyChar* TestChar = Cast<AStrategyChar>(*Iterator);
			if (TestChar != NULL && TestChar->GetHealth() > 0 )
			{
				AStrategyAIController* AIController = Cast<AStrategyAIController>(TestChar->Controller);
				if (AIController != NULL && AIController->IsLogicEnabled())
				{
					FLinearColor DrawColor;
					if (PC != NULL && TestChar->GetTeamNum() == PC->GetTeamNum())
					{
						DrawColor = FColor( 49, 137, 253, 255);
					} 
					else
					{
						DrawColor = FColor( 242, 114, 16, 255);
					}
					const FVector CenterRelativeLocation = RotationMatrix.TransformPosition(TestChar->GetActorLocation() - WorldCenter);
					const FVector2D MiniMapPoint = FVector2D(CenterRelativeLocation.X / WorldExtent.X, CenterRelativeLocation.Y / WorldExtent.Y);
					TileItem.SetColor( DrawColor );
					Canvas->DrawItem( TileItem, FVector2D( Offset.X + MiniMapPoint.X * (MapWidth/2.0f), Offset.Y + MiniMapPoint.Y * (MapHeight/2.0f) ) );
				}
			}
		}


		ULocalPlayer* MyPlayer =  Cast<ULocalPlayer>(PC->Player);
		FVector2D ScreenCorners[4] = { FVector2D(0, 0), FVector2D(Canvas->ClipX, 0), FVector2D(Canvas->ClipX, Canvas->ClipY), FVector2D(0, Canvas->ClipY) };
		const FPlane GroundPlane = FPlane(FVector(0, 0, MyGameState->WorldBounds.Max.Z), FVector::UpVector);
		for (int32 i = 0; i < 4; i++)
		{
			FVector RayOrigin, RayDirection;
			FStrategyHelpers::DeprojectScreenToWorld(ScreenCorners[i], MyPlayer, RayOrigin, RayDirection);
			const FVector GroundPoint = FStrategyHelpers::IntersectRayWithPlane(RayOrigin, RayDirection, GroundPlane);
			const FVector CenterRelativeLocation = RotationMatrix.TransformPosition(GroundPoint - WorldCenter);
			MiniMapPoints[i] = FVector2D(CenterRelativeLocation.X / WorldExtent.X, CenterRelativeLocation.Y / WorldExtent.Y);
		}
	} 
}
示例#28
0
//
// Find the best splitting polygon within a pool of polygons, and return its
// index (into the PolyList array).
//
static FPoly *FindBestSplit
(
	int32					NumPolys,
	FPoly**				PolyList,
	FBSPOps::EBspOptimization	Opt,
	int32					Balance,
	int32					InPortalBias
)
{
	check(NumPolys>0);

	// No need to test if only one poly.
	if( NumPolys==1 )
		return PolyList[0];

	FPoly   *Poly, *Best=NULL;
	float   Score, BestScore;
	int32     i, Index, j, Inc;
	int32     Splits, Front, Back, Coplanar, AllSemiSolids;

	//PortalBias -- added by Legend on 4/12/2000
	float	PortalBias = InPortalBias / 100.0f;
	Balance &= 0xFF;								// keep only the low byte to recover "Balance"
	//UE_LOG(LogBSPOps, Log, TEXT("Balance=%d PortalBias=%f"), Balance, PortalBias );

	if		(Opt==FBSPOps::BSP_Optimal)  Inc = 1;					// Test lots of nodes.
	else if (Opt==FBSPOps::BSP_Good)		Inc = FMath::Max(1,NumPolys/20);	// Test 20 nodes.
	else /* BSP_Lame */			Inc = FMath::Max(1,NumPolys/4);	// Test 4 nodes.

	// See if there are any non-semisolid polygons here.
	for( i=0; i<NumPolys; i++ )
		if( !(PolyList[i]->PolyFlags & PF_AddLast) )
			break;
	AllSemiSolids = (i>=NumPolys);

	// Search through all polygons in the pool and find:
	// A. The number of splits each poly would make.
	// B. The number of front and back nodes the polygon would create.
	// C. Number of coplanars.
	BestScore = 0;
	for( i=0; i<NumPolys; i+=Inc )
	{
		Splits = Front = Back = Coplanar = 0;
		Index = i-1;
		do
		{
			Index++;
			Poly = PolyList[Index];
		} while( Index<(i+Inc) && Index<NumPolys 
			&& ( (Poly->PolyFlags & PF_AddLast) && !(Poly->PolyFlags & PF_Portal) )
			&& !AllSemiSolids );
		if( Index>=i+Inc || Index>=NumPolys )
			continue;

		for( j=0; j<NumPolys; j+=Inc ) if( j != Index )
		{
			FPoly *OtherPoly = PolyList[j];
			switch( OtherPoly->SplitWithPlaneFast( FPlane( Poly->Vertices[0], Poly->Normal), NULL, NULL ) )
			{
				case SP_Coplanar:
					Coplanar++;
					break;

				case SP_Front:
					Front++;
					break;

				case SP_Back:
					Back++;
					break;

				case SP_Split:
					// Disfavor splitting polys that are zone portals.
					if( !(OtherPoly->PolyFlags & PF_Portal) )
						Splits++;
					else
						Splits += 16;
					break;
			}
		}
		// added by Legend 1/31/1999
		// Score optimization: minimize cuts vs. balance tree (as specified in BSP Rebuilder dialog)
		Score = ( 100.0 - float(Balance) ) * Splits + float(Balance) * FMath::Abs( Front - Back );
		if( Poly->PolyFlags & PF_Portal )
		{
			// PortalBias -- added by Legend on 4/12/2000
			//
			// PortalBias enables level designers to control the effect of Portals on the BSP.
			// This effect can range from 0.0 (ignore portals), to 1.0 (portals cut everything).
			//
			// In builds prior to this (since the 221 build dating back to 1/31/1999) the bias
			// has been 1.0 causing the portals to cut the BSP in ways that will potentially
			// degrade level performance, and increase the BSP complexity.
			// 
			// By setting the bias to a value between 0.3 and 0.7 the positive effects of 
			// the portals are preserved without giving them unreasonable priority in the BSP.
			//
			// Portals should be weighted high enough in the BSP to separate major parts of the
			// level from each other (pushing entire rooms down the branches of the BSP), but
			// should not be so high that portals cut through adjacent geometry in a way that
			// increases complexity of the room being (typically, accidentally) cut.
			//
			Score -= ( 100.0 - float(Balance) ) * Splits * PortalBias; // ignore PortalBias of the split polys -- bias toward portal selection for cutting planes!
		}
		//UE_LOG(LogBSPOps, Log,  "  %4d: Score = %f (Front = %4d, Back = %4d, Splits = %4d, Flags = %08X)", Index, Score, Front, Back, Splits, Poly->PolyFlags ); //LEC

		if( Score<BestScore || !Best )
		{
			Best      = Poly;
			BestScore = Score;
		}
	}
	check(Best);
	return Best;
}
示例#29
0
// Add an editor polygon to the Bsp, and also stick a reference to it
// in the editor polygon's BspNodes list. If the editor polygon has more sides
// than the Bsp will allow, split it up into several sub-polygons.
//
// Returns: Index to newly-created node of Bsp.  If several nodes were created because
// of split polys, returns the parent (highest one up in the Bsp).
int32	FBSPOps::bspAddNode( UModel* Model, int32 iParent, ENodePlace NodePlace, uint32 NodeFlags, FPoly* EdPoly )
{
	if( NodePlace == NODE_Plane )
	{
		// Make sure coplanars are added at the end of the coplanar list so that 
		// we don't insert NF_IsNew nodes with non NF_IsNew coplanar children.
		while( Model->Nodes[iParent].iPlane != INDEX_NONE )
		{
			iParent = Model->Nodes[iParent].iPlane;
		}
	}
	FBspSurf* Surf = NULL;
	if( EdPoly->iLink == Model->Surfs.Num() )
	{
		int32 NewIndex = Model->Surfs.AddZeroed();
		Surf = &Model->Surfs[NewIndex];

		// This node has a new polygon being added by bspBrushCSG; must set its properties here.
		Surf->pBase     	= bspAddPoint  (Model,&EdPoly->Base,1);
		Surf->vNormal   	= bspAddVector (Model,&EdPoly->Normal,1);
		Surf->vTextureU 	= bspAddVector (Model,&EdPoly->TextureU,0);
		Surf->vTextureV 	= bspAddVector (Model,&EdPoly->TextureV,0);
		Surf->Material  	= EdPoly->Material;
		Surf->Actor			= NULL;

		Surf->PolyFlags 	= EdPoly->PolyFlags & ~PF_NoAddToBSP;
		Surf->LightMapScale= EdPoly->LightMapScale;

		// Find the LightmassPrimitiveSettings in the UModel...
		int32 FoundLightmassIndex = INDEX_NONE;
		if (Model->LightmassSettings.Find(EdPoly->LightmassSettings, FoundLightmassIndex) == false)
		{
			FoundLightmassIndex = Model->LightmassSettings.Add(EdPoly->LightmassSettings);
		}
		Surf->iLightmassIndex = FoundLightmassIndex;

		Surf->Actor	 		= EdPoly->Actor;
		Surf->iBrushPoly	= EdPoly->iBrushPoly;

		Surf->Plane			= FPlane(EdPoly->Vertices[0],EdPoly->Normal);
	}
	else
	{
		check(EdPoly->iLink!=INDEX_NONE);
		check(EdPoly->iLink<Model->Surfs.Num());
		Surf = &Model->Surfs[EdPoly->iLink];
	}

	// Set NodeFlags.
	if( Surf->PolyFlags & PF_NotSolid              ) NodeFlags |= NF_NotCsg;
	if( Surf->PolyFlags & (PF_Invisible|PF_Portal) ) NodeFlags |= NF_NotVisBlocking;

	if( EdPoly->Vertices.Num() > FBspNode::MAX_NODE_VERTICES )
	{
		// Split up into two coplanar sub-polygons (one with MAX_NODE_VERTICES vertices and
		// one with all the remaining vertices) and recursively add them.

		// EdPoly1 is just the first MAX_NODE_VERTICES from EdPoly.
		FMemMark Mark(FMemStack::Get());
		FPoly *EdPoly1 = new FPoly;
		*EdPoly1 = *EdPoly;
		EdPoly1->Vertices.RemoveAt(FBspNode::MAX_NODE_VERTICES,EdPoly->Vertices.Num() - FBspNode::MAX_NODE_VERTICES);

		// EdPoly2 is the first vertex from EdPoly, and the last EdPoly->Vertices.Num() - MAX_NODE_VERTICES + 1.
		FPoly *EdPoly2 = new FPoly;
		*EdPoly2 = *EdPoly;
		EdPoly2->Vertices.RemoveAt(1,FBspNode::MAX_NODE_VERTICES - 2);

		int32 iNode = bspAddNode( Model, iParent, NodePlace, NodeFlags, EdPoly1 ); // Add this poly first.
		bspAddNode( Model, iNode,   NODE_Plane, NodeFlags, EdPoly2 ); // Then add other (may be bigger).

		delete EdPoly1;
		delete EdPoly2;

		Mark.Pop();
		return iNode; // Return coplanar "parent" node (not coplanar child)
	}
	else
	{
		// Add node.
		if( NodePlace!=NODE_Root )
		{
			Model->Nodes.ModifyItem( iParent );
		}
		int32 iNode			 = Model->Nodes.AddZeroed();
		FBspNode& Node       = Model->Nodes[iNode];

		// Tell transaction tracking system that parent is about to be modified.
		FBspNode* Parent=NULL;
		if( NodePlace!=NODE_Root )
			Parent = &Model->Nodes[iParent];

		// Set node properties.
		Node.iSurf       	 = EdPoly->iLink;
		Node.NodeFlags   	 = NodeFlags;
		Node.iCollisionBound = INDEX_NONE;
		Node.Plane           = FPlane( EdPoly->Vertices[0], EdPoly->Normal );
		Node.iVertPool       = Model->Verts.AddUninitialized(EdPoly->Vertices.Num());
		Node.iFront		     = INDEX_NONE;
		Node.iBack		     = INDEX_NONE;
		Node.iPlane		     = INDEX_NONE;
		if( NodePlace==NODE_Root )
		{
			Node.iLeaf[0]	 = INDEX_NONE;
			Node.iLeaf[1] 	 = INDEX_NONE;
			Node.iZone[0]	 = 0;
			Node.iZone[1]	 = 0;
		}
		else if( NodePlace==NODE_Front || NodePlace==NODE_Back )
		{
			int32 ZoneFront=NodePlace==NODE_Front;
			Node.iLeaf[0]	 = Parent->iLeaf[ZoneFront];
			Node.iLeaf[1] 	 = Parent->iLeaf[ZoneFront];
			Node.iZone[0]	 = Parent->iZone[ZoneFront];
			Node.iZone[1]	 = Parent->iZone[ZoneFront];
		}
		else
		{
			int32 IsFlipped    = (Node.Plane|Parent->Plane)<0.0;
			Node.iLeaf[0]    = Parent->iLeaf[IsFlipped  ];
			Node.iLeaf[1]    = Parent->iLeaf[1-IsFlipped];
			Node.iZone[0]    = Parent->iZone[IsFlipped  ];
			Node.iZone[1]    = Parent->iZone[1-IsFlipped];
		}

		// Link parent to this node.
		if     ( NodePlace==NODE_Front ) Parent->iFront = iNode;
		else if( NodePlace==NODE_Back  ) Parent->iBack  = iNode;
		else if( NodePlace==NODE_Plane ) Parent->iPlane = iNode;

		// Add all points to point table, merging nearly-overlapping polygon points
		// with other points in the poly to prevent criscrossing vertices from
		// being generated.

		// Must maintain Node->NumVertices on the fly so that bspAddPoint is always
		// called with the Bsp in a clean state.
		Node.NumVertices = 0;
		FVert* VertPool	 = &Model->Verts[ Node.iVertPool ];
		for( uint8 i=0; i<EdPoly->Vertices.Num(); i++ )
		{
			int32 pVertex = bspAddPoint(Model,&EdPoly->Vertices[i],0);
			if( Node.NumVertices==0 || VertPool[Node.NumVertices-1].pVertex!=pVertex )
			{
				VertPool[Node.NumVertices].iSide   = INDEX_NONE;
				VertPool[Node.NumVertices].pVertex = pVertex;
				Node.NumVertices++;
			}
		}
		if( Node.NumVertices>=2 && VertPool[0].pVertex==VertPool[Node.NumVertices-1].pVertex )
		{
			Node.NumVertices--;
		}
		if( Node.NumVertices < 3 )
		{
			GErrors++;
// 			UE_LOG(LogBSPOps, Warning, TEXT("bspAddNode: Infinitesimal polygon %i (%i)"), Node.NumVertices, EdPoly->Vertices.Num() );
			Node.NumVertices = 0;
		}

		return iNode;
	}
}
示例#30
0
void ABrush::CheckForErrors()
{
	Super::CheckForErrors();

	if( !BrushComponent )
	{
		FFormatNamedArguments Arguments;
		Arguments.Add(TEXT("ActorName"), FText::FromString(GetName()));
		FMessageLog("MapCheck").Warning()
			->AddToken(FUObjectToken::Create(this))
			->AddToken(FTextToken::Create(FText::Format(LOCTEXT( "MapCheck_Message_BrushComponentNull", "{ActorName} : Brush has NULL BrushComponent property - please delete" ), Arguments) ))
			->AddToken(FMapErrorToken::Create(FMapErrors::BrushComponentNull));
	}
	else
	{		
		ABrush* MyBrush = Cast<ABrush>( Brush );
		// NOTE : don't report NULL texture references on the builder brush - it doesn't matter there
		if( MyBrush && !FActorEditorUtils::IsABuilderBrush(MyBrush) && !IsBrushShape() )
		{
			// A brush without any polygons in it isn't useful.  Should be deleted.
			if( Brush->Polys->Element.Num() == 0 )
			{
				FFormatNamedArguments Arguments;
				Arguments.Add(TEXT("ActorName"), FText::FromString(GetName()));
				FMessageLog("MapCheck").Warning()
					->AddToken(FUObjectToken::Create(this))
					->AddToken(FTextToken::Create(FText::Format(LOCTEXT( "MapCheck_Message_BrushZeroPolygons", "{ActorName} : Brush has zero polygons - please delete" ), Arguments) ))
					->AddToken(FMapErrorToken::Create(FMapErrors::BrushZeroPolygons));
			}

			// Check for non-coplanar polygons.
			for( int32 x = 0 ; x < Brush->Polys->Element.Num() ; ++x )
			{
				FPoly* Poly = &(Brush->Polys->Element[x]);
				bool	Coplanar = 1;

				for(int32 VertexIndex = 0;VertexIndex < Poly->Vertices.Num();VertexIndex++)
				{
					if(FMath::Abs(FPlane(Poly->Vertices[0],Poly->Normal).PlaneDot(Poly->Vertices[VertexIndex])) > THRESH_POINT_ON_PLANE)
					{
						FFormatNamedArguments Arguments;
						Arguments.Add(TEXT("ActorName"), FText::FromString(GetName()));
						FMessageLog("MapCheck").Warning()
							->AddToken(FUObjectToken::Create(this))
							->AddToken(FTextToken::Create(FText::Format(LOCTEXT( "MapCheck_Message_NonCoPlanarPolys", "{ActorName} : Brush has non-coplanar polygons" ), Arguments) ))
							->AddToken(FMapErrorToken::Create(FMapErrors::NonCoPlanarPolys));
						Coplanar = 0;
						break;
					}
				}

				if(!Coplanar)
				{
					break;
				}
			}

			// check for planar brushes which might mess up collision
			if(Brush->Bounds.BoxExtent.Z < SMALL_NUMBER || Brush->Bounds.BoxExtent.Y < SMALL_NUMBER || Brush->Bounds.BoxExtent.X < SMALL_NUMBER)
			{
				FFormatNamedArguments Arguments;
				Arguments.Add(TEXT("ActorName"), FText::FromString(GetName()));
				FMessageLog("MapCheck").Warning()
					->AddToken(FUObjectToken::Create(this))
					->AddToken(FTextToken::Create(FText::Format(LOCTEXT( "MapCheck_Message_PlanarBrush", "{ActorName} : Brush is planar" ), Arguments) ))
					->AddToken(FMapErrorToken::Create(FMapErrors::PlanarBrush));
			}
		}
	}
}