void FEdModeLevel::SetLevel( ULevelStreaming* LevelStream ) { if( SelectedLevel != NULL && SelectedLevel != LevelStream ) { // Changed level need to apply PostEditMove to the actors we moved in the last level ApplyPostEditMove(); } SelectedLevel = LevelStream; bIsDirty = false; if( SelectedLevel ) { LevelTransform = SelectedLevel->LevelTransform; ULevel* Level = SelectedLevel->GetLoadedLevel(); // Calculate the Level bounds box LevelBounds = FBox(0); if( Level ) { for( int32 ActorIndex=0; ActorIndex< Level->Actors.Num(); ActorIndex++ ) { AActor* Actor = Level->Actors[ActorIndex]; // Don't include the builder brush or the world settings as they can artificially make the level bounds bigger if( Actor && FActorEditorUtils::IsABuilderBrush(Actor) == false && Level->GetWorldSettings() != Actor ) { LevelBounds += Actor->GetComponentsBoundingBox(); } } } } GEditor->RedrawAllViewports(); }
/** * Minimal initialization constructor. */ FShadowMapPendingTexture(uint32 InSizeX,uint32 InSizeY) : FTextureLayout(4, 4, InSizeX, InSizeY, /* PowerOfTwo */ true, /* AlignByFour */ true) // Min size is 4x4 in case of block compression. , Bounds(FBox(0)) , ShadowmapFlags(SMF_None) , UnallocatedTexels(InSizeX * InSizeY) { }
FBox ALevelBounds::GetComponentsBoundingBox(bool bNonColliding) const { FVector BoundsCenter = RootComponent->GetComponentLocation(); FVector BoundsExtent = RootComponent->ComponentToWorld.GetScale3D() * 0.5f; return FBox(BoundsCenter - BoundsExtent, BoundsCenter + BoundsExtent); }
void UCameraAnim::CalcLocalAABB() { BoundingBox.Init(); if (CameraInterpGroup) { // find move track UInterpTrackMove *MoveTrack = NULL; for (int32 TrackIdx = 0; TrackIdx < CameraInterpGroup->InterpTracks.Num(); ++TrackIdx) { MoveTrack = Cast<UInterpTrackMove>(CameraInterpGroup->InterpTracks[TrackIdx]); if (MoveTrack != NULL) { break; } } if (MoveTrack != NULL) { FVector Zero(0.f), MinBounds, MaxBounds; MoveTrack->PosTrack.CalcBounds(MinBounds, MaxBounds, Zero); BoundingBox = FBox(MinBounds, MaxBounds); } } }
const FBox Turret::boundingBox() const { int3 bbox_size = sprite().bboxSize(); if(m_action == TurretAction::hidden) bbox_size.y = 1; //TODO: when dead&exploded some turrets are hidden return FBox(pos(), pos() + float3(bbox_size)); }
FBox FLevelCollectionModel::EditableWorldArea() { float AxisLength = EditableAxisLength(); return FBox( FVector(-AxisLength, -AxisLength, -AxisLength), FVector(+AxisLength, +AxisLength, +AxisLength) ); }
FBox FKSphereElem::CalcAABB(const FTransform& BoneTM, float Scale) const { FTransform ElemTM = GetTransform(); ElemTM.ScaleTranslation( FVector(Scale) ); ElemTM *= BoneTM; const FVector BoxCenter = ElemTM.GetTranslation(); const FVector BoxExtents(Radius * Scale); return FBox(BoxCenter - BoxExtents, BoxCenter + BoxExtents); }
void ASpacePartioner::Initialize(const float& inExtent, const bool& inDrawDebugInfo) { bInitialized = true; bDrawDebugInfo = inDrawDebugInfo; // The Extent is very similar to the radius of a circle FVector min = FVector(-inExtent, -inExtent, -inExtent); FVector max = FVector(inExtent, inExtent, inExtent); FBox NewBounds = FBox(min, max); OctreeData = new FSimpleOctree(NewBounds.GetCenter(), NewBounds.GetExtent().GetMax()); // const FVector & InOrigin, float InExtent }
void UNavLinkCustomComponent::CalcAndCacheBounds() const { Bounds = FBox(0); Bounds += GetStartPoint(); Bounds += GetEndPoint(); if (bCreateBoxObstacle) { FBox ObstacleBounds = FBox::BuildAABB(ObstacleOffset, ObstacleExtent); Bounds += ObstacleBounds.TransformBy(GetOwner()->GetTransform()); } }
FBox EntitiesEditor::computeOvergroundBox(const FBox &bbox) const { int over_ground = 0; FBox test_box = bbox; test_box.max.y = test_box.min.y + 1.0f; while(over_ground < 16 && m_tile_map.findAny(test_box - float3(0, 1 + over_ground, 0)) == -1) over_ground++; if(over_ground) return FBox(asXZY(bbox.min.xz(), bbox.min.y - over_ground), asXZY(bbox.max.xz(), bbox.min.y)); return FBox::empty(); }
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; } } } }
FBoxSphereBounds UCubiquityMeshComponent::CalcBounds(const FTransform & LocalToWorld) const { //UE_LOG(CubiquityLog, Log, TEXT("UCubiquityMeshComponent::CalcBounds")); /*FBoxSphereBounds NewBounds; NewBounds.Origin = FVector::ZeroVector; NewBounds.BoxExtent = FVector(HALF_WORLD_MAX, HALF_WORLD_MAX, HALF_WORLD_MAX); NewBounds.SphereRadius = FMath::Sqrt(3.0f * FMath::Square(HALF_WORLD_MAX)); return NewBounds;*/ //FVector BoxPoint = FVector(100, 100, 100); /*const FVector UnitV(1, 1, 1); const FBox VeryVeryBig(-UnitV * HALF_WORLD_MAX, UnitV * HALF_WORLD_MAX); return FBoxSphereBounds(VeryVeryBig);*/ return FBoxSphereBounds(FBox(FVector(-128, -128, -128), FVector(128, 128, 128))).TransformBy(LocalToWorld); //TODO check this for each node... }
FBox Door::computeBBox(DoorState state) const { float3 size = (float3)m_sprite.bboxSize(); float maxs = max(size.x, size.z); FBox box; if(classId() == DoorClassId::sliding || state == DoorState::closed) box = FBox(float3(0, 0, 0), state == DoorState::opened_in? float3(0, 0, 0) : size); else if(state == DoorState::closing_in || state == DoorState::opening_in) box = FBox(-maxs + 1, 0, 0, 1, size.y, maxs); else if(state == DoorState::closing_out || state == DoorState::opening_out) box = FBox(0, 0, 0, maxs, size.y, maxs); else if(state == DoorState::opened_out) box = FBox(0, 0, 0, size.z, size.y, size.x); else if(state == DoorState::opened_in) box = FBox(-size.z + 1, 0, 0, 1, size.y, size.x); //TODO: this is still wrong FBox out = rotateY(box, size * 0.5f, dirAngle()); out.min = (float3)(int3)out.min; out.max = (float3)(int3)out.max; DASSERT(classId() == DoorClassId::sliding || !out.empty()); return out; }
void AOctreeSearch::CreateSpacePoints(int32 N, float SizeArg) { Size = SizeArg; FVector s = FVector(SizeArg, SizeArg, SizeArg/10); Particles.SetNum(N); for (int32 i = 0; i < N; i++) { Particles[i].Position = FMath::RandPointInBox(FBox(GetActorLocation() - s, GetActorLocation() + s)); Particles[i].Velocity = 10*FMath::RandRange(25.0, 50.0)*FMath::VRand(); Particles[i].Mass = FMath::RandRange(1.0,5000.0); } Particles[0].Position = FVector::ZeroVector; Particles[0].Velocity = FVector::ZeroVector; Particles[0].Mass = 5000.0; Initialized = true; }
bool FVertexSnappingImpl::SnapDragLocationToNearestVertex( const FVector& BaseLocation, FVector& DragDelta, FLevelEditorViewportClient* ViewportClient ) { int32 MouseX = ViewportClient->Viewport->GetMouseX(); int32 MouseY = ViewportClient->Viewport->GetMouseY(); FVector2D MousePosition = FVector2D( MouseX, MouseY ) ; EAxisList::Type CurrentAxis = ViewportClient->GetCurrentWidgetAxis(); bool bSnapped = false; if( !DragDelta.IsNearlyZero() ) { FVector Direction = DragDelta.GetSafeNormal(); FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( ViewportClient->Viewport, ViewportClient->GetScene(), ViewportClient->EngineShowFlags ) .SetRealtimeUpdate( ViewportClient->IsRealtime() )); FSceneView* View = ViewportClient->CalcSceneView( &ViewFamily ); FVector DesiredUnsnappedLocation = BaseLocation+DragDelta; FBoxSphereBounds SnappingAreaBox( FBox( DesiredUnsnappedLocation-VertexSnappingConstants::MaxSnappingDistance, DesiredUnsnappedLocation+VertexSnappingConstants::MaxSnappingDistance ) ); FBox AllowedSnappingBox = SnappingAreaBox.GetBox(); AllowedSnappingBox += DragDelta; FPlane ActorPlane( DesiredUnsnappedLocation, Direction ); TSet< TWeakObjectPtr<AActor> > NoActorsToIgnore; FVertexSnappingArgs Args ( ActorPlane, DesiredUnsnappedLocation, ViewportClient, View, MousePosition, CurrentAxis, true ); SnapDragDelta( Args, BaseLocation, AllowedSnappingBox, NoActorsToIgnore, DragDelta ); } return bSnapped; }
FBoxSphereBounds UDestructibleComponent::CalcBounds(const FTransform& LocalToWorld) const { #if WITH_APEX if( ApexDestructibleActor == NULL ) { // Fallback if we don't have physics return Super::CalcBounds(LocalToWorld); } const PxBounds3& PBounds = ApexDestructibleActor->getBounds(); return FBoxSphereBounds( FBox( P2UVector(PBounds.minimum), P2UVector(PBounds.maximum) ) ); #else // #if WITH_APEX return Super::CalcBounds(LocalToWorld); #endif // #if WITH_APEX }
void FIndirectLightingCache::UpdateTranslucentVolumeCache(FViewInfo& View, TMap<FIntVector, FBlockUpdateInfo>& BlocksToUpdate, TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate) { extern int32 GUseIndirectLightingCacheInLightingVolume; if (View.State && GUseIndirectLightingCacheInLightingVolume) { FSceneViewState* ViewState = (FSceneViewState*)View.State; for (int32 CascadeIndex = 0; CascadeIndex < ARRAY_COUNT(ViewState->TranslucencyLightingCacheAllocations); CascadeIndex++) { FIndirectLightingCacheAllocation*& Allocation = ViewState->TranslucencyLightingCacheAllocations[CascadeIndex]; const FBoxSphereBounds Bounds(FBox(View.TranslucencyLightingVolumeMin[CascadeIndex], View.TranslucencyLightingVolumeMin[CascadeIndex] + View.TranslucencyLightingVolumeSize[CascadeIndex])); UpdateCacheAllocation(Bounds, GTranslucencyLightingVolumeDim / 4, true, Allocation, BlocksToUpdate, TransitionsOverTimeToUpdate); } } }
bool FVertexSnappingImpl::SnapLocationToNearestVertex( FVector& Location, const FVector2D& MouseLocation, FLevelEditorViewportClient* ViewportClient, FVector& OutVertexNormal, bool bDrawVertexHelpers ) { bool bSnapped = false; // Make a box around the actor which is the area we are allowed to snap in FBox AllowedSnappingBox = FBox( Location-VertexSnappingConstants::MaxSnappingDistance, Location+VertexSnappingConstants::MaxSnappingDistance ); FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( ViewportClient->Viewport, ViewportClient->GetScene(), ViewportClient->EngineShowFlags ) .SetRealtimeUpdate( ViewportClient->IsRealtime() )); FSceneView* View = ViewportClient->CalcSceneView( &ViewFamily ); TArray<FSnapActor> ActorsInBox; TSet<TWeakObjectPtr<AActor> > ActorsToIgnore; // Ignore actors currently being moved ActorsToIgnore.Append( ViewportClient->GetDropPreviewActors() ); GetPossibleSnapActors( AllowedSnappingBox, MouseLocation.IntPoint(), ViewportClient, View, EAxisList::Screen, ActorsToIgnore, ActorsInBox ); FViewportCursorLocation Cursor(View, ViewportClient, MouseLocation.X, MouseLocation.Y ); FPlane ActorPlane( Location, Cursor.GetDirection() ); FVertexSnappingArgs Args ( ActorPlane, Location, ViewportClient, View, Cursor.GetCursorPos(), EAxisList::Screen, bDrawVertexHelpers ); // Snap to the nearest vertex FSnappingVertex ClosestVertex = GetClosestVertex( ActorsInBox, Args ); Location = ClosestVertex.Position; OutVertexNormal = ClosestVertex.Normal; bSnapped = true; return bSnapped; }
bool UNavigationComponent::AsyncGeneratePath(const FVector& FromLocation, const FVector& GoalLocation, TSharedPtr<const FNavigationQueryFilter> QueryFilter) { if (GetWorld()->GetNavigationSystem() == NULL || GetOuter() == NULL || MyNavAgent == NULL || GetNavData() == NULL) { return false; } // Make sure we're trying to path to the closest valid location TO that location rather than the absolute location. // After talking with Steve P., if we need to ever allow pathing WITHOUT projecting to nav-mesh, it will probably be // best to do so using a flag while keeping this as the default behavior. NOTE: If any changes to this behavior // are made, you should search for other places in UNavigationComponent using NavMeshGoalLocation and make sure the // behavior remains consistent. const FNavAgentProperties* NavAgentProps = MyNavAgent->GetNavAgentProperties(); if (NavAgentProps != NULL) { FVector NavMeshGoalLocation; if (ProjectPointToNavigation(GoalLocation, NavMeshGoalLocation) == QuerySuccess) { const EPathFindingMode::Type Mode = bDoHierarchicalPathfinding ? EPathFindingMode::Hierarchical : EPathFindingMode::Regular; AsynPathQueryID = GetWorld()->GetNavigationSystem()->FindPathAsync(*MyNavAgent->GetNavAgentProperties() , FPathFindingQuery(MyNavData, FromLocation, NavMeshGoalLocation, QueryFilter) , FNavPathQueryDelegate::CreateUObject(this, &UNavigationComponent::AsyncGeneratePath_OnCompleteCallback) , Mode); } else { // projecting destination point failed AsynPathQueryID = INVALID_NAVQUERYID; UE_VLOG(GetOwner(), LogNavigation, Warning, TEXT("AI trying to generate path to point off of navmesh")); UE_VLOG_LOCATION(GetOwner(), GoalLocation, 30, FColor::Red, TEXT("Invalid pathing GoalLocation")); if (MyNavData != NULL) { UE_VLOG_BOX(GetOwner(), FBox(GoalLocation-MyNavData->GetDefaultQueryExtent(),GoalLocation+MyNavData->GetDefaultQueryExtent()), FColor::Red, TEXT_EMPTY); } } } else { AsynPathQueryID = INVALID_NAVQUERYID; } return AsynPathQueryID != INVALID_NAVQUERYID; }
/** Calc Bounds */ FBoxSphereBounds UFluidSurfaceComponent::CalcBounds( const FTransform& LocalToWorld ) const { FBoxSphereBounds NewBounds; /*if( BodySetup ) { FBox AggGeomBox = BodySetup->AggGeom.CalcAABB( LocalToWorld ); if( AggGeomBox.IsValid ) { NewBounds = FBoxSphereBounds( AggGeomBox ); } } else*/ { FBox NewBox = FBox( FVector( -( ( FluidXSize * FluidGridSpacing ) / 2.0f ), -( ( FluidYSize * FluidGridSpacing ) / 2.0f ), -10.0f ), FVector( ( FluidXSize * FluidGridSpacing ) / 2.0f, ( FluidYSize * FluidGridSpacing ) / 2.0f, 10.0f ) ); NewBounds = FBoxSphereBounds( NewBox ); NewBounds.Origin = GetComponentLocation( ); } return NewBounds; }
void UEnvQueryGenerator_PathingGrid::FindNodeRefsInPathDistance(const class ARecastNavMesh* NavMesh, const FVector& ContextLocation, float InMaxPathDistance, bool bPathFromContext, TArray<NavNodeRef>& NodeRefs, FBox& NodeRefsBounds) const { FBox MyBounds(0); #if ENVQUERY_CLUSTER_SEARCH const bool bUseBacktracking = !bPathFromContext; NavMesh->GetClustersWithinPathingDistance(ContextLocation, InMaxPathDistance, NodeRefs, bUseBacktracking); for (int32 RefIndex = 0; RefIndex < NodeRefs.Num(); RefIndex++) { FBox ClusterBounds; const bool bSuccess = NavMesh->GetClusterBounds(NodeRefs[RefIndex], ClusterBounds); if (bSuccess) { MyBounds += ClusterBounds; } } #else TSharedPtr<FNavigationQueryFilter> NavFilterInstance = NavigationFilter != NULL ? UNavigationQueryFilter::GetQueryFilter(NavMesh, NavigationFilter)->GetCopy() : NavMesh->GetDefaultQueryFilter()->GetCopy(); NavFilterInstance->SetBacktrackingEnabled(!bPathFromContext); NavMesh->GetPolysWithinPathingDistance(ContextLocation, InMaxPathDistance, NodeRefs, NavFilterInstance); TArray<FVector> PolyVerts; for (int32 RefIndex = 0; RefIndex < NodeRefs.Num(); RefIndex++) { PolyVerts.Reset(); const bool bSuccess = NavMesh->GetPolyVerts(NodeRefs[RefIndex], PolyVerts); if (bSuccess) { MyBounds += FBox(PolyVerts); } } #endif NodeRefsBounds = MyBounds; }
void AAgentSpawnerVolume::Tick(float DeltaSeconds) { Super::Tick(DeltaSeconds); if (m_spawnerActive == false) { return; } int32 numToSpawn = 0; m_timeSinceSpawn += DeltaSeconds; while (m_timeSinceSpawn >= m_spawnDelay) { numToSpawn++; m_timeSinceSpawn -= m_spawnDelay; } if (!m_endlessMode) { numToSpawn = FMath::Min(numToSpawn, m_numAgents - m_numAgentsSpawned); } FBox box = GetComponentsBoundingBox(); ABasicAIAgent *agent = Cast<ABasicAIAgent>(m_agentToSpawn.GetDefaultObject()); int32 agentTeam = agent->m_teamID; UFlockingDataCache *dataCache = UFlockingDataCache::GetCacheChecked(this); for (int32 i = 0; i < numToSpawn; i++) { if (!dataCache->IsTeamAtMaxSize(agentTeam)) { FVector point = FMath::RandPointInBox(FBox(box.Min, box.Max)); point.Z += agent->m_capsuleComponent->GetScaledCapsuleHalfHeight(); GetWorld()->SpawnActor(*m_agentToSpawn, &point, &FRotator::ZeroRotator, FActorSpawnParameters()); } m_numAgentsSpawned++; } }
FBoxSphereBounds UGameplayDebuggingComponent::CalcBounds(const FTransform& LocalToWorld) const { FBox MyBounds; MyBounds.Init(); #if WITH_RECAST if (ShouldReplicateData(EAIDebugDrawDataView::NavMesh)) { MyBounds = NavMeshBounds; } #endif #if USE_EQS_DEBUGGER if (EQSRepData.Num() && ShouldReplicateData(EAIDebugDrawDataView::EQS)) { MyBounds = FBox(FVector(-HALF_WORLD_MAX, -HALF_WORLD_MAX, -HALF_WORLD_MAX), FVector(HALF_WORLD_MAX, HALF_WORLD_MAX, HALF_WORLD_MAX)); } #endif // USE_EQS_DEBUGGER return MyBounds; }
void ASimpleCylinderActor::GenerateMesh() { if (Height <= 0) { MeshComponent->ClearAllMeshSections(); return; } // The number of vertices or polygons wont change at runtime, so we'll just allocate the arrays once if (!bHaveBuffersBeenInitialized) { SetupMeshBuffers(); bHaveBuffersBeenInitialized = true; } FBox BoundingBox = FBox(FVector(-Radius, -Radius, 0), FVector(Radius, Radius, Height)); GenerateCylinder(Vertices, Triangles, Height, Radius, RadialSegmentCount, bCapEnds, bDoubleSided, bSmoothNormals); MeshComponent->ClearAllMeshSections(); MeshComponent->CreateMeshSection(0, Vertices, Triangles, BoundingBox, false, EUpdateFrequency::Infrequent); MeshComponent->SetMaterial(0, Material); }
FBox ALevelBounds::CalculateLevelBounds(ULevel* InLevel) { FBox LevelBounds = FBox(0); if (InLevel) { // Iterate over all level actors for (int32 ActorIndex = 0; ActorIndex < InLevel->Actors.Num() ; ++ActorIndex) { AActor* Actor = InLevel->Actors[ActorIndex]; if (Actor && Actor->IsLevelBoundsRelevant()) { // Sum up components bounding boxes FBox ActorBox = Actor->GetComponentsBoundingBox(true); if (ActorBox.IsValid) { LevelBounds+= ActorBox; } } } } return LevelBounds; }
FBoxSphereBounds UBoxComponent::CalcBounds(const FTransform& LocalToWorld) const { return FBoxSphereBounds( FBox( -BoxExtent, BoxExtent ) ).TransformBy(LocalToWorld); }
FBox FLevelModel::GetLevelBounds() const { return FBox(0); }
FBox FStaticLightingAggregateMesh::GetBounds() const { // Expand the bounds slightly to avoid having to handle geometry that is exactly on the bounding box, // Which happens if you create a new level in Unreal with BSP from the default builder brush. return TrianglePayloads.Num() > 0 ? SceneBounds.ExpandBy(5.0f * Scene.SceneConstants.StaticLightingLevelScale) : FBox(FVector4(0,0,0), FVector4(0,0,0)); }
void FEditorCommonDrawHelper::DrawOldGrid(const FSceneView* View,FPrimitiveDrawInterface* PDI) { ESceneDepthPriorityGroup eDPG = (ESceneDepthPriorityGroup)DepthPriorityGroup; bool bIsPerspective = ( View->ViewMatrices.ProjMatrix.M[3][3] < 1.0f ); // Draw 3D perspective grid if( bIsPerspective) { // @todo: Persp grid should be changed to be adaptive and use same settings as ortho grid, including grid interval! const int32 RangeInCells = NumCells / 2; const int32 MajorLineInterval = NumCells / 8; const int32 NumLines = NumCells + 1; const int32 AxesIndex = NumCells / 2; for( int32 LineIndex = 0; LineIndex < NumLines; ++LineIndex ) { bool bIsMajorLine = ( ( LineIndex - RangeInCells ) % MajorLineInterval ) == 0; FVector A,B; A.X=(PerspectiveGridSize/4.f)*(-1.0+2.0*LineIndex/NumCells); B.X=A.X; A.Y=(PerspectiveGridSize/4.f); B.Y=-(PerspectiveGridSize/4.f); A.Z=0.0; B.Z=0.0; FColor LineColor; float LineThickness = 0.f; if ( LineIndex==AxesIndex ) { LineColor = GridColorAxis; LineThickness = AxesLineThickness; } else if ( bIsMajorLine ) { LineColor = GridColorMajor; } else { LineColor = GridColorMinor; } PDI->DrawLine(A,B,LineColor,eDPG, LineThickness, GridDepthBias); A.Y=A.X; B.Y=B.X; A.X=(PerspectiveGridSize/4.f); B.X=-(PerspectiveGridSize/4.f); PDI->DrawLine(A,B,LineColor,eDPG, LineThickness, GridDepthBias); } } // Draw ortho grid. else { const bool bIsOrthoXY = ( FMath::Abs(View->ViewMatrices.ViewMatrix.M[2][2]) > 0.0f ); const bool bIsOrthoXZ = ( FMath::Abs(View->ViewMatrices.ViewMatrix.M[1][2]) > 0.0f ); const bool bIsOrthoYZ = ( FMath::Abs(View->ViewMatrices.ViewMatrix.M[0][2]) > 0.0f ); FLinearColor AxisColors[3]; GetAxisColors(AxisColors, false); if( bIsOrthoXY ) { FVector StartY( 0.0f, +HALF_WORLD_MAX1, -HALF_WORLD_MAX ); FVector EndY( 0.0f, -HALF_WORLD_MAX1, -HALF_WORLD_MAX ); FVector StartX( +HALF_WORLD_MAX1, 0.0f, -HALF_WORLD_MAX ); FVector EndX( -HALF_WORLD_MAX1, 0.0f, -HALF_WORLD_MAX ); DrawGridSection( GEditor->GetGridSize(), &StartY, &EndY, &StartY.X, &EndY.X, 0, View, PDI); DrawGridSection( GEditor->GetGridSize(), &StartX, &EndX, &StartX.Y, &EndX.Y, 1, View, PDI); DrawOriginAxisLine( &StartY, &EndY, &StartY.X, &EndY.X, View, PDI, AxisColors[1] ); DrawOriginAxisLine( &StartX, &EndX, &StartX.Y, &EndX.Y, View, PDI, AxisColors[0] ); } else if( bIsOrthoXZ ) { FVector StartZ( 0.0f, -HALF_WORLD_MAX, +HALF_WORLD_MAX1 ); FVector EndZ( 0.0f, -HALF_WORLD_MAX, -HALF_WORLD_MAX1 ); FVector StartX( +HALF_WORLD_MAX1, -HALF_WORLD_MAX, 0.0f ); FVector EndX( -HALF_WORLD_MAX1, -HALF_WORLD_MAX, 0.0f ); DrawGridSection( GEditor->GetGridSize(), &StartZ, &EndZ, &StartZ.X, &EndZ.X, 0, View, PDI); DrawGridSection( GEditor->GetGridSize(), &StartX, &EndX, &StartX.Z, &EndX.Z, 2, View, PDI); DrawOriginAxisLine( &StartZ, &EndZ, &StartZ.X, &EndZ.X, View, PDI, AxisColors[2] ); DrawOriginAxisLine( &StartX, &EndX, &StartX.Z, &EndX.Z, View, PDI, AxisColors[0] ); } else if( bIsOrthoYZ ) { FVector StartZ( +HALF_WORLD_MAX, 0.0f, +HALF_WORLD_MAX1 ); FVector EndZ( +HALF_WORLD_MAX, 0.0f, -HALF_WORLD_MAX1 ); FVector StartY( +HALF_WORLD_MAX, +HALF_WORLD_MAX1, 0.0f ); FVector EndY( +HALF_WORLD_MAX, -HALF_WORLD_MAX1, 0.0f ); DrawGridSection( GEditor->GetGridSize(), &StartZ, &EndZ, &StartZ.Y, &EndZ.Y, 1, View, PDI); DrawGridSection( GEditor->GetGridSize(), &StartY, &EndY, &StartY.Z, &EndY.Z, 2, View, PDI); DrawOriginAxisLine( &StartZ, &EndZ, &StartZ.Y, &EndZ.Y, View, PDI, AxisColors[2] ); DrawOriginAxisLine( &StartY, &EndY, &StartY.Z, &EndY.Z, View, PDI, AxisColors[1] ); } if( bDrawKillZ && ( bIsOrthoXZ || bIsOrthoYZ ) && GWorld->GetWorldSettings()->bEnableWorldBoundsChecks ) { float KillZ = GWorld->GetWorldSettings()->KillZ; PDI->DrawLine( FVector(-HALF_WORLD_MAX,0,KillZ), FVector(HALF_WORLD_MAX,0,KillZ), FColor(255,0,0), SDPG_Foreground ); PDI->DrawLine( FVector(0,-HALF_WORLD_MAX,KillZ), FVector(0,HALF_WORLD_MAX,KillZ), FColor(255,0,0), SDPG_Foreground ); } } // Draw orthogonal worldframe. if(bDrawWorldBox) { DrawWireBox(PDI, FBox( FVector(-HALF_WORLD_MAX1,-HALF_WORLD_MAX1,-HALF_WORLD_MAX1),FVector(HALF_WORLD_MAX1,HALF_WORLD_MAX1,HALF_WORLD_MAX1) ), GEngine->C_WorldBox, eDPG ); } }
bool OccluderConfig::update(const FBox &bbox) { //TODO: hiding when close to a door/window FBox test_box(bbox.min.x, bbox.min.y + 1.0f, bbox.min.z, bbox.max.x, 256, bbox.max.z); float3 mid_point = asXZY(test_box.center().xz(), bbox.min.y + 2.0f); bool vis_changed = update(); vector<int> temp; temp.reserve(256); IRect test_rect = (IRect)worldToScreen(bbox); const Grid &grid = m_map.m_grid; grid.findAll(temp, test_rect); vector<int> temp2; temp2.reserve(256); PodArray<int> overlaps(m_map.size()); memset(overlaps.data(), 0, m_map.size() * sizeof(int)); for(int i = 0; i < (int)temp.size(); i++) { const auto &object = grid[temp[i]]; if(object.occluder_id == -1) continue; const OccluderMap::Occluder &occluder = m_map[object.occluder_id]; int order = drawingOrder(object.bbox, bbox); if(order == 1) overlaps[object.occluder_id] = order; } for(int n = 0; n < (int)m_states.size(); n++) { bool is_overlapping = false; const OccluderMap::Occluder &occluder = m_map[n]; if(overlaps[n] == 1) { FBox bbox_around(bbox.min - float3(16, 0, 16), bbox.max + float3(16, 0, 16)); bbox_around.min.y = 0; bbox_around.max.y = Grid::max_height; temp2.clear(); grid.findAll(temp2, bbox_around); FBox local_box = FBox(); for(int i = 0; i < (int)temp2.size(); i++) { const auto &object = grid[temp2[i]]; if(object.occluder_id == n) local_box = local_box.empty()? object.bbox : sum(local_box, object.bbox); } is_overlapping = local_box.min.y > mid_point.y; } if(is_overlapping != m_states[n].is_overlapping) { m_states[n].is_overlapping = is_overlapping; vis_changed = true; } } if(!vis_changed) return false; for(int n= 0; n < (int)m_states.size(); n++) m_states[n].is_visible = !m_states[n].is_overlapping; //TODO: isUnder can be precomputed for(int n = 0; n < (int)m_states.size(); n++) { if(!m_states[n].is_visible) continue; for(int i = 0; i < (int)m_states.size(); i++) if(!m_states[i].is_visible && m_map.isUnder(i, n)) { m_states[n].is_visible = false; break; } } return true; }