Esempio n. 1
0
//----------------------------------------------------------------------//
// DEBUG
//----------------------------------------------------------------------//
FString UAISense_Sight::GetDebugLegend() const
{
	static const FColor SightColor = GetDebugSightRangeColor(); 
	static const FColor LoseSightColor = GetDebugLoseSightColor();

	return FString::Printf(TEXT("{%s} Sight, {%s} Lose Sight,"), *SightColor.ToString(), *LoseSightColor.ToString());
}
Esempio n. 2
0
void FTileRenderer::DrawTile(FRHICommandListImmediate& RHICmdList, const class FSceneView& View, const FMaterialRenderProxy* MaterialRenderProxy, bool bNeedsToSwitchVerticalAxis, float X, float Y, float SizeX, float SizeY, float U, float V, float SizeU, float SizeV, bool bIsHitTesting, const FHitProxyId HitProxyId, const FColor InVertexColor)
{
	FMaterialTileVertex DestVertex[4];

	// create verts
	if (bNeedsToSwitchVerticalAxis)
	{
		DestVertex[0].Initialize(X + SizeX, View.ViewRect.Height() - (Y + SizeY), U + SizeU, V + SizeV);
		DestVertex[1].Initialize(X, View.ViewRect.Height() - (Y + SizeY), U, V + SizeV);
		DestVertex[2].Initialize(X + SizeX, View.ViewRect.Height() - Y, U + SizeU, V);
		DestVertex[3].Initialize(X, View.ViewRect.Height() - Y, U, V);		
	}
	else
	{
		DestVertex[0].Initialize(X + SizeX, Y, U + SizeU, V);
		DestVertex[1].Initialize(X, Y, U, V);
		DestVertex[2].Initialize(X + SizeX, Y + SizeY, U + SizeU, V + SizeV);
		DestVertex[3].Initialize(X, Y + SizeY, U, V + SizeV);
	}

	DestVertex[0].Color = InVertexColor.DWColor();
	DestVertex[1].Color = InVertexColor.DWColor();
	DestVertex[2].Color = InVertexColor.DWColor();
	DestVertex[3].Color = InVertexColor.DWColor();

	// update the FMeshBatch
	FMeshBatch& Mesh = GTileMesh.MeshElement;
	Mesh.UseDynamicData = true;
	Mesh.DynamicVertexData = DestVertex;
	Mesh.MaterialRenderProxy = MaterialRenderProxy;

	GetRendererModule().DrawTileMesh(RHICmdList, View, Mesh, bIsHitTesting, HitProxyId);
}
Esempio n. 3
0
void UPaperTerrainComponent::PostLoad()
{
	Super::PostLoad();

	const int32 PaperVer = GetLinkerCustomVersion(FPaperCustomVersion::GUID);

	if (PaperVer < FPaperCustomVersion::FixVertexColorSpace)
	{
		const FColor SRGBColor = TerrainColor.ToFColor(/*bSRGB=*/ true);
		TerrainColor = SRGBColor.ReinterpretAsLinear();
	}
}
Esempio n. 4
0
FColor HSB::hsbFromRgb(const FColor& rgb) {
    const auto brightness = max(
        max(RGB::red(rgb), RGB::green(rgb)), RGB::blue(rgb));
    auto hue = 0.0f, saturation = 0.0f;

    if (not near(brightness, 0.0)) {
        const auto darkest = min(
            min(RGB::red(rgb), RGB::green(rgb)), RGB::blue(rgb));
        const auto range = brightness - darkest;
        saturation = range / brightness;

        if (not near(saturation, 0.0)) {
            const float r = (brightness - RGB::red(rgb)) / range;
            const float g = (brightness - RGB::green(rgb)) / range;
            const float b = (brightness - RGB::blue(rgb)) / range;

            if (near(RGB::red(rgb), brightness))
                hue = b - g;
            else if (near(RGB::green(rgb), brightness))
                hue = 2.0f + r - b;
            else
                hue = 4.0f + g - r;

            hue /= 6.0f;

            if (hue < 0)
                hue += 1.0f;
        }
    }
    return FColor(hue, saturation, brightness, rgb.alpha());
}
	bool ParseTag(FColor& OutColor)
	{
		FString TagString;

		EStringParserToken Token = ReadToken();
		for (; Token != EStringParserToken::EndOfString && Token != EStringParserToken::CloseTag; Token = ReadToken())
		{
			if (Token == EStringParserToken::RegularChar)
			{
				TagString.AppendChar(DataString[DataIndex]);
			}
			
			DataIndex++;
		}

		bool bResult = false;
		if (Token == EStringParserToken::CloseTag)
		{
			const FString TagColorLower = TagString.ToLower();
			const bool bIsColorName = GColorList.IsValidColorName(*TagColorLower);
			
			if (bIsColorName)
			{
				OutColor = GColorList.GetFColorByName(*TagColorLower);
				bResult = true;
			}
			else
			{
				bResult = OutColor.InitFromString(TagString);
			}
		}

		return bResult;
	}
Esempio n. 6
0
void BatchRenderer::DrawSolidTriangle3D(
	const Vec3D& a, const Vec3D& b, const Vec3D& c,
	const FColor& color
	)
{
	const U4 rgbaColor = color.ToRGBA32();

	SetBatchState( this, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

	const UINT iBaseVertex = self->batchedVertices.Num();
	Vertex & v0 = self->batchedVertices.Add();
	Vertex & v1 = self->batchedVertices.Add();
	Vertex & v2 = self->batchedVertices.Add();

	v0.xyz.x 	= a.x;
	v0.xyz.y 	= a.y;
	v0.xyz.z 	= a.z;
	v0.rgba.asU32 	= rgbaColor;

	v1.xyz.x 	= b.x;
	v1.xyz.y 	= b.y;
	v1.xyz.z 	= b.z;
	v1.rgba.asU32 	= rgbaColor;

	v2.xyz.x 	= c.x;
	v2.xyz.y 	= c.y;
	v2.xyz.z 	= c.z;
	v2.rgba.asU32 	= rgbaColor;

	self->batchedIndices.Add( iBaseVertex + 0 );
	self->batchedIndices.Add( iBaseVertex + 1 );
	self->batchedIndices.Add( iBaseVertex + 2 );
}
		uint32 ParseTag( FString& OutData )
		{
			FString TagString;
			int32 OryginalIndex = Index;
			uint8 token = ReadToken();
			while (token != EndOfString && token != CloseTag)
			{
				if (token == RegularChar)
				{
					TagString.AppendChar(DataString[Index++]);
				}
				token = ReadToken();
			}

			int OutTag = ErrorTag;

			if (token != CloseTag)
			{
				Index = OryginalIndex;
				OutData = FString::Printf( TEXT("{%s"), *TagString);
				OutData.AppendChar(DataString[Index-1]);
				return OutTag;
			}

			if (GColorList.IsValidColorName(*TagString.ToLower()))
			{
				OutTag = DefinedColor;
				OutData = TagString;
			}
			else
			{
				FColor Color;
				if (Color.InitFromString(TagString))
				{
					OutTag = OtherColor;
					OutData = TagString;
				}
				else
				{
					OutTag = ErrorTag;
					OutData = FString::Printf( TEXT("{%s"), *TagString);
					OutData.AppendChar(DataString[Index-1]);
				}
			}
			//Index++;
			return OutTag;
		}
void FD3DGPUProfiler::PushEvent(const TCHAR* Name, FColor Color)
{
#if WITH_DX_PERF
	D3DPERF_BeginEvent(Color.DWColor(), Name);
#endif

	FGPUProfiler::PushEvent(Name, Color);
}
void FColorStructCustomization::OnSetColorFromColorPicker( FLinearColor NewColor )
{
	FString ColorString;
	if( bIsLinearColor )
	{
		ColorString = NewColor.ToString();
	}
	else
	{
		// Handled by the color picker
		const bool bSRGB = false;
		FColor NewFColor = NewColor.ToFColor(bSRGB);
		ColorString = NewFColor.ToString();
	}

	StructPropertyHandle->SetValueFromFormattedString( ColorString, bIsInteractive ? EPropertyValueSetFlags::InteractiveChange : 0 );
}
void FColorStructCustomization::CreateColorPicker( bool bUseAlpha, bool bOnlyRefreshOnOk )
{
	int32 NumObjects = StructPropertyHandle->GetNumOuterObjects();

	SavedPreColorPickerColors.Empty();
	TArray<FString> PerObjectValues;
	StructPropertyHandle->GetPerObjectValues( PerObjectValues );

	for( int32 ObjectIndex = 0; ObjectIndex < NumObjects; ++ObjectIndex )
	{
		if( bIsLinearColor )
		{
			FLinearColor Color;
			Color.InitFromString( PerObjectValues[ObjectIndex] );
			SavedPreColorPickerColors.Add( Color );	
		}
		else
		{
			FColor Color;
			Color.InitFromString( PerObjectValues[ObjectIndex] );
			SavedPreColorPickerColors.Add( Color.ReinterpretAsLinear() );
		}
	}

	FLinearColor InitialColor;
	GetColorAsLinear(InitialColor);

	// This needs to be meta data.  Other colors could benefit from this
	const bool bRefreshOnlyOnOk = StructPropertyHandle->GetProperty()->GetOwnerClass()->IsChildOf(UMaterialExpressionConstant3Vector::StaticClass());

	FColorPickerArgs PickerArgs;
	PickerArgs.bUseAlpha = !bIgnoreAlpha;
	PickerArgs.bOnlyRefreshOnMouseUp = false;
	PickerArgs.bOnlyRefreshOnOk = bRefreshOnlyOnOk;
	PickerArgs.DisplayGamma = TAttribute<float>::Create( TAttribute<float>::FGetter::CreateUObject(GEngine, &UEngine::GetDisplayGamma) );
	PickerArgs.OnColorCommitted = FOnLinearColorValueChanged::CreateSP( this, &FColorStructCustomization::OnSetColorFromColorPicker );
	PickerArgs.OnColorPickerCancelled = FOnColorPickerCancelled::CreateSP( this, &FColorStructCustomization::OnColorPickerCancelled );
	PickerArgs.OnInteractivePickBegin = FSimpleDelegate::CreateSP( this, &FColorStructCustomization::OnColorPickerInteractiveBegin );
	PickerArgs.OnInteractivePickEnd = FSimpleDelegate::CreateSP( this, &FColorStructCustomization::OnColorPickerInteractiveEnd );
	PickerArgs.InitialColorOverride = InitialColor;
	PickerArgs.ParentWidget = ColorPickerParentWidget;

	OpenColorPicker(PickerArgs);
}
Esempio n. 11
0
// from http://www.cs.rit.edu/~ncs/color/t_convert.html
FColor HSB::hsbToRgb(const FColor& hsb) {
    auto h = hue(hsb), s = saturation(hsb), b = brightness(hsb);
    float red, green, blue;
    if (s == 0) {
        // achromatic (grey)
        red = green = blue = b;
    } else {
        h *= 6;			// sector 0 to 5
        int i = floor(h);
        auto f = h - i;			// factorial part of h
        auto p = b * (1 - s);
        auto q = b * (1 - s * f);
        auto t = b * (1 - s * (1 - f));

        switch(i) {
            case 0:
                red = b;
                green = t;
                blue = p;
                break;

            case 1:
                red = q;
                green = b;
                blue = p;
                break;

            case 2:
                red = p;
                green = b;
                blue = t;
                break;

            case 3:
                red = p;
                green = q;
                blue = b;
                break;

            case 4:
                red = t;
                green = p;
                blue = b;
                break;

            case 5:
            default:
                red = b;
                green = p;
                blue = q;
                break;
        }
    }

    return FColor(red, green, blue, hsb.alpha());
}
TSharedRef<SColorPicker> FColorStructCustomization::CreateInlineColorPicker()
{
	int32 NumObjects = StructPropertyHandle->GetNumOuterObjects();

	SavedPreColorPickerColors.Empty();
	TArray<FString> PerObjectValues;
	StructPropertyHandle->GetPerObjectValues( PerObjectValues );

	for( int32 ObjectIndex = 0; ObjectIndex < NumObjects; ++ObjectIndex )
	{
		if( bIsLinearColor )
		{
			FLinearColor Color;
			Color.InitFromString( PerObjectValues[ObjectIndex] );
			SavedPreColorPickerColors.Add( Color );	
		}
		else
		{
			FColor Color;
			Color.InitFromString( PerObjectValues[ObjectIndex] );
			SavedPreColorPickerColors.Add( Color.ReinterpretAsLinear() );
		}
	}

	FLinearColor InitialColor;
	GetColorAsLinear(InitialColor);

	// This needs to be meta data.  Other colors could benefit from this
	const bool bRefreshOnlyOnOk = StructPropertyHandle->GetProperty()->GetOwnerClass()->IsChildOf(UMaterialExpressionConstant3Vector::StaticClass());
	
	return SNew(SColorPicker)
		.Visibility(this, &FColorStructCustomization::GetInlineColorPickerVisibility)
		.DisplayInlineVersion(true)
		.OnlyRefreshOnMouseUp(false)
		.OnlyRefreshOnOk(bRefreshOnlyOnOk)
		.DisplayGamma(TAttribute<float>::Create( TAttribute<float>::FGetter::CreateUObject(GEngine, &UEngine::GetDisplayGamma) ))
		.OnColorCommitted(FOnLinearColorValueChanged::CreateSP( this, &FColorStructCustomization::OnSetColorFromColorPicker ))
		.OnColorPickerCancelled(FOnColorPickerCancelled::CreateSP( this, &FColorStructCustomization::OnColorPickerCancelled ))
		.OnInteractivePickBegin(FSimpleDelegate::CreateSP( this, &FColorStructCustomization::OnColorPickerInteractiveBegin ))
		.OnInteractivePickEnd(FSimpleDelegate::CreateSP( this, &FColorStructCustomization::OnColorPickerInteractiveEnd ))
		.TargetColorAttribute(InitialColor);
}
Esempio n. 13
0
void BatchRenderer::DrawSprite(
	const Matrix4& cameraWorldMatrix,
	const Vec3D& spriteOrigin,
	const FLOAT spriteSizeX, const FLOAT spriteSizeY,
	const FColor& color
)
{
	const Vec3D spriteX = cameraWorldMatrix[0].ToVec3() * spriteSizeX;
	const Vec3D spriteY = cameraWorldMatrix[1].ToVec3() * spriteSizeY;

	const U4 rgbaColor = color.ToRGBA32();

	SetBatchState( this, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

	const UINT iBaseVertex = self->batchedVertices.Num();

	Vertex & v0 = self->batchedVertices.Add();
	Vertex & v1 = self->batchedVertices.Add();
	Vertex & v2 = self->batchedVertices.Add();
	Vertex & v3 = self->batchedVertices.Add();

	
	v0.xyz		= spriteOrigin - spriteX - spriteY;	// bottom left
	v0.uv.x 	= 0.0f;
	v0.uv.y 	= 1.0f;
	v0.rgba.asU32 	= rgbaColor;

	v1.xyz		= spriteOrigin - spriteX + spriteY;	// top left
	v1.uv.x 	= 0.0f;
	v1.uv.y 	= 0.0f;
	v1.rgba.asU32 	= rgbaColor;

	v2.xyz		= spriteOrigin + spriteX + spriteY;	// top right
	v2.uv.x 	= 1.0f;
	v2.uv.y 	= 0.0f;
	v2.rgba.asU32 	= rgbaColor;

	v3.xyz		= spriteOrigin + spriteX - spriteY;	// bottom right
	v3.uv.x 	= 1.0f;
	v3.uv.y 	= 1.0f;
	v3.rgba.asU32 	= rgbaColor;

	// indices:
	// 0,	1,	2,
	// 0,	2,	3,

	self->batchedIndices.Add( iBaseVertex + 0 );
	self->batchedIndices.Add( iBaseVertex + 1 );
	self->batchedIndices.Add( iBaseVertex + 2 );

	self->batchedIndices.Add( iBaseVertex + 0 );
	self->batchedIndices.Add( iBaseVertex + 2 );
	self->batchedIndices.Add( iBaseVertex + 3 );
}
void UPaperSpriteComponent::PostLoad()
{
	Super::PostLoad();

	const int32 PaperVer = GetLinkerCustomVersion(FPaperCustomVersion::GUID);

	if (PaperVer < FPaperCustomVersion::ConvertPaperSpriteComponentToBeMeshComponent)
	{
		if (MaterialOverride_DEPRECATED != nullptr)
		{
			SetMaterial(0, MaterialOverride_DEPRECATED);
		}
	}

	if (PaperVer < FPaperCustomVersion::FixVertexColorSpace)
	{
		const FColor SRGBColor = SpriteColor.ToFColor(/*bSRGB=*/ true);
		SpriteColor = SRGBColor.ReinterpretAsLinear();
	}
}
void DrawDebugPoint(const UWorld* InWorld, FVector const& Position, float Size, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority)
{
	// no debug line drawing on dedicated server
	if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
	{
		// this means foreground lines can't be persistent 
		ULineBatchComponent* const LineBatcher = GetDebugLineBatcher( InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground) );
		if(LineBatcher != NULL)
		{
			LineBatcher->DrawPoint(Position, Color.ReinterpretAsLinear(), Size, DepthPriority, LifeTime);
		}
	}
}
void FColorStructCustomization::OnColorPickerCancelled( FLinearColor OriginalColor )
{
	TArray<FString> PerObjectColors;

	for( int32 ColorIndex = 0; ColorIndex < SavedPreColorPickerColors.Num(); ++ColorIndex )
	{
		if( bIsLinearColor )
		{
			PerObjectColors.Add( SavedPreColorPickerColors[ColorIndex].ToString() );
		}
		else
		{
			const bool bSRGB = false;
			FColor Color = SavedPreColorPickerColors[ColorIndex].ToFColor( bSRGB );
			PerObjectColors.Add( Color.ToString() );
		}
	}

	StructPropertyHandle->SetPerObjectValues( PerObjectColors );

	PerObjectColors.Empty();
}
Esempio n. 17
0
void BatchRenderer::DrawTriangle3D(
	const Vec3D& a, const Vec3D& b, const Vec3D& c,
	const FColor& color
)
{
#if 0
	DrawLine3D( a, b, color, color );
	DrawLine3D( b, c, color, color );
	DrawLine3D( c, a, color, color );
#else
	SetBatchState( this, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP );

	Vertex & v0 = self->batchedVertices.Add();
	Vertex & v1 = self->batchedVertices.Add();
	Vertex & v2 = self->batchedVertices.Add();
	Vertex & v3 = self->batchedVertices.Add();

	v0.xyz.x 	= a.x;
	v0.xyz.y 	= a.y;
	v0.xyz.z 	= a.z;
	v0.rgba.asU32 	= color.ToRGBA32();

	v1.xyz.x 	= b.x;
	v1.xyz.y 	= b.y;
	v1.xyz.z 	= b.z;
	v1.rgba.asU32 	= color.ToRGBA32();

	v2.xyz.x 	= c.x;
	v2.xyz.y 	= c.y;
	v2.xyz.z 	= c.z;
	v2.rgba.asU32 	= color.ToRGBA32();

	v3.xyz.x 	= a.x;
	v3.xyz.y 	= a.y;
	v3.xyz.z 	= a.z;
	v3.rgba.asU32 	= color.ToRGBA32();
#endif
}
Esempio n. 18
0
	void Window::drawWindow(Renderer2D &out, IRect rect, FColor color, int outline) {
		FColor lighter(color.rgb() * 1.2f, color.a);
		FColor darker(color.rgb() * 0.8f, color.a);
		int aoutline = fwk::abs(outline);

		if(outline) {
			int2 hsize(rect.width(), aoutline);
			int2 vsize(aoutline, rect.height());

			FColor col1 = outline < 0? darker : lighter;
			out.addFilledRect(IRect(rect.min, rect.min + hsize), col1);
			out.addFilledRect(IRect(rect.min, rect.min + vsize), col1);

			int2 p1(rect.min.x, rect.max.y - aoutline);
			int2 p2(rect.max.x - aoutline, rect.min.y);
			FColor col2 = outline < 0? lighter : darker;
			out.addFilledRect(IRect(p1, p1 + hsize), col2);
			out.addFilledRect(IRect(p2, p2 + vsize), col2);
		}

		int2 off(aoutline, aoutline);
		out.addFilledRect(inset(rect, off, off), color);
	}
void FSequencerFolderNode::SetFolderColor()
{
	InitialFolderColor = MovieSceneFolder.GetFolderColor();
	bFolderPickerWasCancelled = false;

	FColorPickerArgs PickerArgs;
	PickerArgs.bUseAlpha = false;
	PickerArgs.DisplayGamma = TAttribute<float>::Create( TAttribute<float>::FGetter::CreateUObject(GEngine, &UEngine::GetDisplayGamma) );
	PickerArgs.InitialColorOverride = InitialFolderColor.ReinterpretAsLinear();
	PickerArgs.OnColorCommitted = FOnLinearColorValueChanged::CreateSP( this, &FSequencerFolderNode::OnColorPickerPicked);
	PickerArgs.OnColorPickerWindowClosed = FOnWindowClosed::CreateSP( this, &FSequencerFolderNode::OnColorPickerClosed);
	PickerArgs.OnColorPickerCancelled  = FOnColorPickerCancelled::CreateSP( this, &FSequencerFolderNode::OnColorPickerCancelled );

	OpenColorPicker(PickerArgs);
}
Esempio n. 20
0
FTetrisBlockSet *FTetrisGameController::GenerateBlockSet(){
	bool texture = scene->GetTexture();
	unsigned int textureid = scene->GetTextureId();
	FTetrisBlockSet::BLOCKOPTIONS option = FTetrisBlockSet::I;
	FColor *color = new FColor(0, 0, 0, 1);
	int myoption = rand();
	switch(myoption % 7){
		case 0:
			option = FTetrisBlockSet::I;
			color->SetR(1);
			break;
		case 1:
			option = FTetrisBlockSet::J;
			color->SetG(1);
			break;
		case 2:
			option = FTetrisBlockSet::L;
			color->SetB(1);
			break;
		case 3:
			option = FTetrisBlockSet::O;
			color->SetR(1);
			color->SetB(1);
			break;
		case 4:
			option = FTetrisBlockSet::T;
			color->SetB(1);
			color->SetG(1);
			break;
		case 5:
			option = FTetrisBlockSet::S;
			color->SetR(1);
			color->SetG(1);
			break;
		case 6:
			option = FTetrisBlockSet::Z;
			color->SetR(1);
			color->SetG(1);
			color->SetB(1);
			break;
	}
	FTetrisBlockSet *blockset = new FTetrisBlockSet(0, 0, option, field->GetBoxWidth(), field->GetBoxHeight(), field->GetCubeWidth(), field->GetCubeHeight(), color, false, texture, textureid, false);
	return blockset;
}
void AGameplayDebuggingHUDComponent::PrintString(FPrintContext& Context, const FColor& InColor, const FString& InString )
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	PrintString(Context, FString::Printf(TEXT("{%s}%s"), *InColor.ToString(), *InString));
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
TArray<FColor> USceneCapturer::SaveAtlas(FString Folder, const TArray<FColor>& SurfaceData)
{
	SCOPE_CYCLE_COUNTER( STAT_SPSavePNG );
	
    TArray<FColor> SphericalAtlas;
    SphericalAtlas.AddZeroed(SphericalAtlasWidth * SphericalAtlasHeight);

    const FVector2D slicePlaneDim = FVector2D(
        2.0f * FMath::Tan(FMath::DegreesToRadians(sliceHFov) / 2.0f),
        2.0f * FMath::Tan(FMath::DegreesToRadians(sliceVFov) / 2.0f));

    //For each direction,
    //    Find corresponding slice
    //    Calculate intersection of slice plane
    //    Calculate intersection UVs by projecting onto plane tangents
    //    Supersample that UV coordinate from the unprojected atlas
    {
        SCOPE_CYCLE_COUNTER(STAT_SPSampleSpherical);
        // Dump out how long the process took
        const FDateTime SamplingStartTime = FDateTime::UtcNow();
        UE_LOG(LogStereoPanorama, Log, TEXT("Sampling atlas..."));

        for (int32 y = 0; y < SphericalAtlasHeight; y++)
        {
            for (int32 x = 0; x < SphericalAtlasWidth; x++)
            {
                FLinearColor samplePixelAccum = FLinearColor(0, 0, 0, 0);

                //TODO: ikrimae: Seems that bilinear filtering sans supersampling is good enough. Supersampling sans bilerp seems best.
                //               After more tests, come back to optimize by folding supersampling in and remove this outer sampling loop.
                const auto& ssPattern = g_ssPatterns[SSMethod];

                for (int32 SampleCount = 0; SampleCount < ssPattern.numSamples; SampleCount++)
                {
                    const float sampleU = ((float)x + ssPattern.ssOffsets[SampleCount].X) / SphericalAtlasWidth;
                    const float sampleV = ((float)y + ssPattern.ssOffsets[SampleCount].Y) / SphericalAtlasHeight;

                    const float sampleTheta = sampleU * 360.0f;
                    const float samplePhi = sampleV * 180.0f;

                    const FVector sampleDir = FVector(
                        FMath::Sin(FMath::DegreesToRadians(samplePhi)) * FMath::Cos(FMath::DegreesToRadians(sampleTheta)),
                        FMath::Sin(FMath::DegreesToRadians(samplePhi)) * FMath::Sin(FMath::DegreesToRadians(sampleTheta)),
                        FMath::Cos(FMath::DegreesToRadians(samplePhi)));


                    //TODO: ikrimae: ugh, ugly.
                    const int32 sliceXIndex = FMath::TruncToInt(FRotator::ClampAxis(sampleTheta + hAngIncrement / 2.0f) / hAngIncrement);
                    int32 sliceYIndex = 0;

                    //Slice Selection = slice with max{sampleDir dot  sliceNormal }
                    {
                        float largestCosAngle = 0;
                        for (int VerticalStep = 0; VerticalStep < NumberOfVerticalSteps; VerticalStep++)
                        {
                            const FVector2D sliceCenterThetaPhi = FVector2D(
                                hAngIncrement * sliceXIndex,
                                vAngIncrement * VerticalStep);

                            //TODO: ikrimae: There has got to be a faster way. Rethink reparametrization later
                            const FVector sliceDir = FVector(
                                FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)) * FMath::Cos(FMath::DegreesToRadians(sliceCenterThetaPhi.X)),
                                FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)) * FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.X)),
                                FMath::Cos(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)));

                            const float cosAngle = sampleDir | sliceDir;

                            if (cosAngle > largestCosAngle)
                            {
                                largestCosAngle = cosAngle;
                                sliceYIndex = VerticalStep;
                            }
                        }
                    }


                    const FVector2D sliceCenterThetaPhi = FVector2D(
                        hAngIncrement * sliceXIndex,
                        vAngIncrement * sliceYIndex);

                    //TODO: ikrimae: Reparameterize with an inverse mapping (e.g. project from slice pixels onto final u,v coordinates.
                    //               Should make code simpler and faster b/c reduces to handful of sin/cos calcs per slice. 
                    //               Supersampling will be more difficult though.

                    const FVector sliceDir = FVector(
                        FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)) * FMath::Cos(FMath::DegreesToRadians(sliceCenterThetaPhi.X)),
                        FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)) * FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.X)),
                        FMath::Cos(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)));

                    const FPlane slicePlane = FPlane(sliceDir, -sliceDir);

                    //Tangents from partial derivatives of sphere equation
                    const FVector slicePlanePhiTangent = FVector(
                        FMath::Cos(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)) * FMath::Cos(FMath::DegreesToRadians(sliceCenterThetaPhi.X)),
                        FMath::Cos(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)) * FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.X)),
                        -FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.Y))).GetSafeNormal();

                    //Should be reconstructed to get around discontinuity of theta tangent at nodal points
                    const FVector slicePlaneThetaTangent = (sliceDir ^ slicePlanePhiTangent).GetSafeNormal();
                    //const FVector slicePlaneThetaTangent = FVector(
                    //    -FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)) * FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.X)),
                    //    FMath::Sin(FMath::DegreesToRadians(sliceCenterThetaPhi.Y)) * FMath::Cos(FMath::DegreesToRadians(sliceCenterThetaPhi.X)),
                    //    0).SafeNormal();

                    check(!slicePlaneThetaTangent.IsZero() && !slicePlanePhiTangent.IsZero());

                    const double t = (double)-slicePlane.W / (sampleDir | sliceDir);
                    const FVector sliceIntersection = FVector(t * sampleDir.X, t * sampleDir.Y, t * sampleDir.Z);

                    //Calculate scalar projection of sliceIntersection onto tangent vectors. a dot b / |b| = a dot b when tangent vectors are normalized
                    //Then reparameterize to U,V of the sliceplane based on slice plane dimensions
                    const float sliceU = (sliceIntersection | slicePlaneThetaTangent) / slicePlaneDim.X;
                    const float sliceV = (sliceIntersection | slicePlanePhiTangent) / slicePlaneDim.Y;

                    check(sliceU >= -(0.5f + KINDA_SMALL_NUMBER) &&
                        sliceU <= (0.5f + KINDA_SMALL_NUMBER));

                    check(sliceV >= -(0.5f + KINDA_SMALL_NUMBER) &&
                        sliceV <= (0.5f + KINDA_SMALL_NUMBER));

                    //TODO: ikrimae: Supersample/bilinear filter
                    const int32 slicePixelX = FMath::TruncToInt(dbgMatchCaptureSliceFovToAtlasSliceFov ? sliceU * StripWidth : sliceU * CaptureWidth);
                    const int32 slicePixelY = FMath::TruncToInt(dbgMatchCaptureSliceFovToAtlasSliceFov ? sliceV * StripHeight : sliceV * CaptureHeight);

                    FLinearColor slicePixelSample;

                    if (bEnableBilerp)
                    {
                        //TODO: ikrimae: Clean up later; too tired now
                        const int32 sliceCenterPixelX = (sliceXIndex + 0.5f) * StripWidth;
                        const int32 sliceCenterPixelY = (sliceYIndex + 0.5f) * StripHeight;

                        const FIntPoint atlasSampleTL(sliceCenterPixelX + FMath::Clamp(slicePixelX    , -StripWidth/2, StripWidth/2), sliceCenterPixelY + FMath::Clamp(slicePixelY    , -StripHeight/2, StripHeight/2));
                        const FIntPoint atlasSampleTR(sliceCenterPixelX + FMath::Clamp(slicePixelX + 1, -StripWidth/2, StripWidth/2), sliceCenterPixelY + FMath::Clamp(slicePixelY    , -StripHeight/2, StripHeight/2));
                        const FIntPoint atlasSampleBL(sliceCenterPixelX + FMath::Clamp(slicePixelX    , -StripWidth/2, StripWidth/2), sliceCenterPixelY + FMath::Clamp(slicePixelY + 1, -StripHeight/2, StripHeight/2));
                        const FIntPoint atlasSampleBR(sliceCenterPixelX + FMath::Clamp(slicePixelX + 1, -StripWidth/2, StripWidth/2), sliceCenterPixelY + FMath::Clamp(slicePixelY + 1, -StripHeight/2, StripHeight/2));

                        const FColor pixelColorTL = SurfaceData[atlasSampleTL.Y * UnprojectedAtlasWidth + atlasSampleTL.X];
                        const FColor pixelColorTR = SurfaceData[atlasSampleTR.Y * UnprojectedAtlasWidth + atlasSampleTR.X];
                        const FColor pixelColorBL = SurfaceData[atlasSampleBL.Y * UnprojectedAtlasWidth + atlasSampleBL.X];
                        const FColor pixelColorBR = SurfaceData[atlasSampleBR.Y * UnprojectedAtlasWidth + atlasSampleBR.X];

                        const float fracX = FMath::Frac(dbgMatchCaptureSliceFovToAtlasSliceFov ? sliceU * StripWidth : sliceU * CaptureWidth);
                        const float fracY = FMath::Frac(dbgMatchCaptureSliceFovToAtlasSliceFov ? sliceV * StripHeight : sliceV * CaptureHeight);

                        //Reinterpret as linear (a.k.a dont apply srgb inversion)
                        slicePixelSample = FMath::BiLerp(
                            pixelColorTL.ReinterpretAsLinear(), pixelColorTR.ReinterpretAsLinear(),
                            pixelColorBL.ReinterpretAsLinear(), pixelColorBR.ReinterpretAsLinear(),
                            fracX, fracY);
                    }
                    else
                    {
                        const int32 sliceCenterPixelX = (sliceXIndex + 0.5f) * StripWidth;
                        const int32 sliceCenterPixelY = (sliceYIndex + 0.5f) * StripHeight;

                        const int32 atlasSampleX = sliceCenterPixelX + slicePixelX;
                        const int32 atlasSampleY = sliceCenterPixelY + slicePixelY;


                        slicePixelSample = SurfaceData[atlasSampleY * UnprojectedAtlasWidth + atlasSampleX].ReinterpretAsLinear();
                    }

                    samplePixelAccum += slicePixelSample;

                    ////Output color map of projections
                    //const FColor debugEquiColors[12] = {
                    //    FColor(205, 180, 76),
                    //    FColor(190, 88, 202),
                    //    FColor(127, 185, 194),
                    //    FColor(90, 54, 47),
                    //    FColor(197, 88, 53),
                    //    FColor(197, 75, 124),
                    //    FColor(130, 208, 72),
                    //    FColor(136, 211, 153),
                    //    FColor(126, 130, 207),
                    //    FColor(83, 107, 59),
                    //    FColor(200, 160, 157),
                    //    FColor(80, 66, 106)
                    //};

                    //samplePixelAccum = ssPattern.numSamples * debugEquiColors[sliceYIndex * 4 + sliceXIndex];
                }

                SphericalAtlas[y * SphericalAtlasWidth + x] = (samplePixelAccum / ssPattern.numSamples).Quantize();

                // Force alpha value
                if (bForceAlpha)
                {
                    SphericalAtlas[y * SphericalAtlasWidth + x].A = 255;
                }
            }
        }

        //Blit the first column into the last column to make the stereo image seamless at theta=360
        for (int32 y = 0; y < SphericalAtlasHeight; y++)
        {
            SphericalAtlas[y * SphericalAtlasWidth + (SphericalAtlasWidth - 1)] = SphericalAtlas[y * SphericalAtlasWidth + 0];
        }

        const FTimespan SamplingDuration = FDateTime::UtcNow() - SamplingStartTime;
        UE_LOG(LogStereoPanorama, Log, TEXT("...done! Duration: %g seconds"), SamplingDuration.GetTotalSeconds());
    }
	
	// Generate name
	FString FrameString = FString::Printf( TEXT( "%s_%05d.png" ), *Folder, CurrentFrameCount );
    FString AtlasName =  OutputDir / Timestamp / FrameString;
    
	UE_LOG( LogStereoPanorama, Log, TEXT( "Writing atlas: %s" ), *AtlasName );

	// Write out PNG
    //TODO: ikrimae: Use threads to write out the images for performance
	IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper( EImageFormat::PNG );
    ImageWrapper->SetRaw(SphericalAtlas.GetData(), SphericalAtlas.GetAllocatedSize(), SphericalAtlasWidth, SphericalAtlasHeight, ERGBFormat::BGRA, 8);
	const TArray<uint8>& PNGData = ImageWrapper->GetCompressed(100);
	FFileHelper::SaveArrayToFile( PNGData, *AtlasName );

    if (FStereoPanoramaManager::GenerateDebugImages->GetInt() != 0)
    {
        FString FrameStringUnprojected = FString::Printf(TEXT("%s_%05d_Unprojected.png"), *Folder, CurrentFrameCount);
        FString AtlasNameUnprojected = OutputDir / Timestamp / FrameStringUnprojected;

        ImageWrapper->SetRaw(SurfaceData.GetData(), SurfaceData.GetAllocatedSize(), UnprojectedAtlasWidth, UnprojectedAtlasHeight, ERGBFormat::BGRA, 8);
        const TArray<uint8>& PNGDataUnprojected = ImageWrapper->GetCompressed(100);
        FFileHelper::SaveArrayToFile(PNGData, *AtlasNameUnprojected);
    }
	ImageWrapper.Reset();

	UE_LOG( LogStereoPanorama, Log, TEXT( " ... done!" ), *AtlasName );

    return SphericalAtlas;
}
		void ParseString(const FString& StringToParse)
		{
			Index = 0;
			DataString = StringToParse;
			Strings.Add(StringNode());
			if (Index >= DataString.Len())
				return;

			uint8 Token = ReadToken();
			while (Token != EndOfString)
			{
				switch (Token)
				{
				case RegularChar:
					Strings[Strings.Num()-1].String.AppendChar( DataString[Index++] );
					break;
				case NewLine:
					Strings.Add(StringNode());
					Strings[Strings.Num()-1].bNewLine = true;
					Strings[Strings.Num()-1].Color = Strings[Strings.Num()-2].Color;
					break;
				case EndOfString:
					break;
				case Tab:
					{
						const FString TabString(TEXT("     "));
						Strings[Strings.Num()-1].String.Append(TabString);
						static bool sbTest = false;
						if (sbTest)
						{
						Index++;
						}
						break;
					}
				case OpenTag:
					{
						FString OutData;
						switch (ParseTag(OutData))
						{
						case DefinedColor:
							{
								int32 i = Strings.Add(StringNode());
								Strings[i].Color = GColorList.GetFColorByName(*OutData.ToLower());
							}
							break;
						case OtherColor:
							{
								FColor NewColor; 
								if (NewColor.InitFromString( OutData ))
								{
									int32 i = Strings.Add(StringNode());
									Strings[i].Color = NewColor;
									break;
								}
							}
						default:
							Strings[Strings.Num()-1].String += OutData;
							break;
						}
					}
					break;
				}
				Token = ReadToken();
			}
		}
Esempio n. 24
0
FORCEINLINE R8G8B8A8 FColor_to_RGBA32( const FColor& theColor )
{
	R8G8B8A8	rgba;
	rgba.asU32 	= theColor.ToRGBA32();
	return rgba;
}