BSP
BSP
#Overview
name: BSP
This variable is created as a Console Variable (cvar).
- type:
Exec
- help:
Sorry: Exec commands have no help
It is referenced in 13
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of BSP is to control the visibility and rendering of Binary Space Partitioning (BSP) geometry in Unreal Engine. BSP is a technique used for spatial partitioning and visibility determination, particularly in level design and rendering.
BSP is primarily used in the rendering system of Unreal Engine. Based on the callsites, it’s evident that the Engine’s rendering, editor, and level editing subsystems rely on this variable.
The value of this variable is typically set through the engine’s show flags system. It can be toggled on or off in the editor viewport or through code by modifying the EngineShowFlags.
Several other variables interact with BSP:
- EngineShowFlags.Brushes: Often used in conjunction with BSP for rendering brush geometry.
- EngineShowFlags.BSPTriangles: Controls the rendering of BSP triangles.
Developers should be aware of the following when using this variable:
- BSP visibility affects both editor and game views.
- It impacts performance, especially in complex scenes with many BSP elements.
- In collision views, BSP visibility might be overridden.
Best practices when using this variable include:
- Use it judiciously in performance-critical scenarios.
- Consider its interaction with other show flags, especially in custom rendering or editor tools.
- Be aware of its impact on selection and hit testing in the editor.
- In game builds, ensure that BSP visibility is set correctly for the desired visual output.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/DragTool_BoxSelect.cpp:71
Scope (from outer to inner):
file
function void FDragTool_ActorBoxSelect::StartDrag
Source code excerpt:
FLevelEditorViewportClient::ClearHoverFromObjects();
// Create a list of bsp models to check for intersection with the box
ModelsToCheck.Reset();
// Do not select BSP if its not visible
if( InViewportClient->EngineShowFlags.BSP)
{
UWorld* World = InViewportClient->GetWorld();
check(World);
// Add the persistent level always
ModelsToCheck.Add( World->PersistentLevel->Model );
// Add all streaming level models
for (ULevelStreaming* StreamingLevel : World->GetStreamingLevels())
{
// Only add streaming level models if the level is visible
if (StreamingLevel && StreamingLevel->GetShouldBeVisibleInEditor())
{
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Editor/ActorPositioning.cpp:135
Scope (from outer to inner):
file
function bool IsHitIgnoredRenderingThread
Source code excerpt:
const bool bConsiderInvisibleComponentForPlacement = PrimitiveComponent->bConsiderForActorPlacementWhenHidden;
// Only use this component if it is visible in the specified scene views
const FPrimitiveViewRelevance ViewRelevance = PrimitiveComponent->SceneProxy->GetViewRelevance(&InSceneView);
// BSP is a bit special in that its bDrawRelevance is false even when drawn as wireframe because InSceneView.Family->EngineShowFlags.BSPTriangles is off
const bool bIsRenderedOnScreen = ViewRelevance.bDrawRelevance || (PrimitiveComponent->IsA(UModelComponent::StaticClass()) && InSceneView.Family->EngineShowFlags.BSP);
const bool bIgnoreTranslucentPrimitive = ViewRelevance.HasTranslucency() && !GetDefault<UEditorPerProjectUserSettings>()->bAllowSelectTranslucent;
return (!bIsRenderedOnScreen && !bConsiderInvisibleComponentForPlacement) || bIgnoreTranslucentPrimitive;
}
return false;
}
FActorPositionTraceResult FActorPositioning::TraceWorldForPosition(const UWorld& InWorld, const FSceneView& InSceneView, const FVector& RayStart, const FVector& RayEnd, const TArray<AActor*>* IgnoreActors)
{
TArray<FHitResult> Hits;
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/EditorModeManager.cpp:1596
Scope (from outer to inner):
file
function void FEditorModeTools::DrawHUD
Source code excerpt:
return;
}
// Temporaries.
const bool bShowBrushes = View->Family->EngineShowFlags.Brushes;
const bool bShowBSP = View->Family->EngineShowFlags.BSP;
const bool bShowBuilderBrush = View->Family->EngineShowFlags.BuilderBrush != 0;
UTexture2D* VertexTexture = GetVertexTexture();
const float TextureSizeX = VertexTexture->GetSizeX() * (bLargeVertices ? 1.0f : 0.5f);
const float TextureSizeY = VertexTexture->GetSizeY() * (bLargeVertices ? 1.0f : 0.5f);
GetEditorSelectionSet()->ForEachSelectedObject<AStaticMeshActor>([View, Canvas, VertexTexture, TextureSizeX, TextureSizeY, bIsHitTesting](AStaticMeshActor* Actor)
{
TArray<FVector> Vertices;
FCanvasItemTestbed::bTestState = !FCanvasItemTestbed::bTestState;
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/EditorServer.cpp:5601
Scope (from outer to inner):
file
function bool UEditorEngine::Exec_Editor
Source code excerpt:
}
}
//------------------------------------------------------------------------------------
// BSP
//
else if( FParse::Command( &Str, TEXT("BSP") ) )
{
return CommandIsDeprecated( *CommandTemp, Ar );
}
//------------------------------------------------------------------------------------
// LIGHT
//
else if( FParse::Command( &Str, TEXT("LIGHT") ) )
{
return CommandIsDeprecated( *CommandTemp, Ar );
}
//------------------------------------------------------------------------------------
#Loc: <Workspace>/Engine/Source/Runtime/Core/Public/UObject/UnrealNames.inl:187
Scope: file
Source code excerpt:
REGISTER_NAME(245,GameThread)
REGISTER_NAME(246,RenderThread)
REGISTER_NAME(247,OtherChildren)
REGISTER_NAME(248,Location)
REGISTER_NAME(249,Rotation)
REGISTER_NAME(250,BSP)
REGISTER_NAME(251,EditorSettings)
REGISTER_NAME(252,AudioThread)
REGISTER_NAME(253,ID)
REGISTER_NAME(254,UserDefinedEnum)
REGISTER_NAME(255,Control)
REGISTER_NAME(256,Voice)
REGISTER_NAME(257, Zlib)
REGISTER_NAME(258, Gzip)
REGISTER_NAME(259, LZ4)
REGISTER_NAME(260, Mobile)
REGISTER_NAME(261, Oodle)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/BrushComponent.cpp:315
Scope (from outer to inner):
file
class class FBrushSceneProxy final : public FPrimitiveSceneProxy
function virtual FPrimitiveViewRelevance GetViewRelevance
Source code excerpt:
}
}
if(bNeverShow == false)
{
const bool bBSPVisible = View->Family->EngineShowFlags.BSP;
const bool bBrushesVisible = View->Family->EngineShowFlags.Brushes;
if ( !bVolume ) // EngineShowFlags.Collision does not apply to volumes
{
if( (bBSPVisible && bBrushesVisible) )
{
bVisible = true;
}
}
// See if we should be visible because we are in a 'collision view' and have collision enabled
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/BrushComponent.cpp:530
Scope (from outer to inner):
file
function bool UBrushComponent::IsShown
Source code excerpt:
bool UBrushComponent::IsShown(const FEngineShowFlags& ShowFlags) const
{
if (const AActor* Actor = GetOwner())
{
return (Actor->IsA(AVolume::StaticClass())) ? ShowFlags.Volumes : ShowFlags.BSP;
}
return false;
}
#if WITH_EDITOR
bool UBrushComponent::ComponentIsTouchingSelectionBox(const FBox& InSelBBox, const bool bConsiderOnlyBSP, const bool bMustEncompassEntireComponent) const
{
if (Brush != nullptr && Brush->Polys != nullptr)
{
TArray<FVector> Vertices;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/ModelRender.cpp:303
Scope (from outer to inner):
file
class class FModelSceneProxy final : public FPrimitiveSceneProxy
function virtual void GetDynamicMeshElements
Source code excerpt:
const FSceneView* View = Views[ViewIndex];
bool bShowSelection = GIsEditor && !View->bIsGameView && ViewFamily.EngineShowFlags.Selection;
bool bDynamicBSPTriangles = bShowSelection || IsRichView(ViewFamily);
bool bShowBSPTriangles = ViewFamily.EngineShowFlags.BSPTriangles;
bool bShowBSP = ViewFamily.EngineShowFlags.BSP;
#if WITH_EDITOR
bool bDrawCollision = false;
const bool bInCollisionView = IsCollisionView(View, bDrawCollision);
// draw bsp as dynamic when in collision view mode
if(bInCollisionView)
{
bDynamicBSPTriangles = true;
}
#endif
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/ModelRender.cpp:536
Scope (from outer to inner):
file
class class FModelSceneProxy final : public FPrimitiveSceneProxy
function virtual FPrimitiveViewRelevance GetViewRelevance
Source code excerpt:
}
virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override
{
FPrimitiveViewRelevance Result;
Result.bDrawRelevance = IsShown(View) && View->Family->EngineShowFlags.BSPTriangles && View->Family->EngineShowFlags.BSP;
bool bShowSelectedTriangles = GIsEditor && !View->bIsGameView && View->Family->EngineShowFlags.Selection;
bool bCollisionView = View->Family->EngineShowFlags.CollisionPawn || View->Family->EngineShowFlags.CollisionVisibility;
if (IsRichView(*View->Family) || HasViewDependentDPG() || bCollisionView
|| (bShowSelectedTriangles && HasSelectedSurfaces()))
{
Result.bDynamicRelevance = true;
}
else
{
Result.bStaticRelevance = true;
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/ShowFlags.cpp:654
Scope (from outer to inner):
file
function void EngineShowFlagOverride
Source code excerpt:
DISABLE_ENGINE_SHOWFLAG(TextRender)
DISABLE_ENGINE_SHOWFLAG(Particles)
DISABLE_ENGINE_SHOWFLAG(SkeletalMeshes)
DISABLE_ENGINE_SHOWFLAG(StaticMeshes)
DISABLE_ENGINE_SHOWFLAG(NaniteMeshes)
DISABLE_ENGINE_SHOWFLAG(BSP)
DISABLE_ENGINE_SHOWFLAG(Paper2DSprites)
#undef DISABLE_ENGINE_SHOWFLAG
}
}
#endif
// Force some show flags to be 0 or 1
{
const uint8* Force0Ptr = (const uint8*)&GSystemSettings.GetForce0Mask();
const uint8* Force1Ptr = (const uint8*)&GSystemSettings.GetForce1Mask();
uint8* Ptr = (uint8*)&EngineShowFlags;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:282
Scope: file
Source code excerpt:
/** if this is a game viewport, needed? */
SHOWFLAG_ALWAYS_ACCESSIBLE(Game, SFG_Hidden, NSLOCTEXT("UnrealEd", "GameSF", "Game"))
/** Render objects with colors based on what the actors coloring handlers provides */
SHOWFLAG_FIXED_IN_SHIPPING(0, ActorColoration, SFG_Transient, NSLOCTEXT("UnrealEd", "ActorColorationSF", "Actor Coloration"))
/** Draws BSP brushes (in game or editor textured triangles usually with lightmaps), for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(BSP, SFG_Normal, NSLOCTEXT("UnrealEd", "BSPSF", "BSP"))
/** Collision drawing */
SHOWFLAG_FIXED_IN_SHIPPING(0, Collision, SFG_Normal, NSLOCTEXT("UnrealEd", "CollisionWireFrame", "Collision"))
/** Collision blocking visibility against complex **/
SHOWFLAG_FIXED_IN_SHIPPING(0, CollisionVisibility, SFG_Hidden, NSLOCTEXT("UnrealEd", "CollisionVisibility", "Visibility"))
/** Collision blocking pawn against simple collision **/
SHOWFLAG_FIXED_IN_SHIPPING(0, CollisionPawn, SFG_Hidden, NSLOCTEXT("UnrealEd", "CollisionPawn", "Pawn"))
/** Render LightShafts, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(LightShafts, SFG_LightingFeatures, NSLOCTEXT("UnrealEd", "LightShaftsSF", "Light Shafts"))
/** Render the PostProcess Material */
SHOWFLAG_FIXED_IN_SHIPPING(1, PostProcessMaterial, SFG_PostProcess, NSLOCTEXT("UnrealEd", "PostProcessMaterialSF", "Post Process Material"))
/** Render Sky and Atmospheric lighting, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneHitProxyRendering.cpp:1019
Scope (from outer to inner):
file
function int32 FEditorSelectionMeshProcessor::GetStencilValue
Source code excerpt:
// Reserved values for the stencil buffer that carry specific meaning
enum ESelectionStencilValues : int32
{
NotSelected = 0,
BSP = 1, // The outlines of all BSPs should be merged
COUNT,
};
static constexpr int BitsAvailable = 8; // Stencil buffer is 8-bit
static constexpr int ColorBits = 3; // Can be changed
static constexpr int UniqueIdBits = BitsAvailable - ColorBits;
static constexpr int MaxColor = (1 << ColorBits);
static constexpr int MaxUniqueId = (1 << UniqueIdBits);
auto EncodeSelectionStencilValue = [](int32 ColorIndex, int32 UniqueId) -> int32
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneHitProxyRendering.cpp:1053
Scope (from outer to inner):
file
function int32 FEditorSelectionMeshProcessor::GetStencilValue
Source code excerpt:
int32 StencilValue = ESelectionStencilValues::NotSelected;
if (PrimitiveSceneProxy->GetOwnerName() == NAME_BSP)
{
StencilValue = ESelectionStencilValues::BSP;
}
else if (ExistingStencilValue != nullptr)
{
StencilValue = *ExistingStencilValue;
}
else if (PrimitiveSceneProxy->IsIndividuallySelected())
{
const int Color = 0;
const int UniqueId = ProxyToStencilIndex.Num();
StencilValue = EncodeSelectionStencilValue(Color, UniqueId);
ProxyToStencilIndex.Add(PrimitiveSceneProxy, StencilValue);