wip(assembler): round S9 -- collision look-ahead: ground ring ready on arrival up to 40 m/s and 50 m/s falls
voxel.StreamingCollisionLookahead (default on) predicts the support tile 350 ms ahead along full 3D velocity and prioritises its 9-tile collision ring. Owner plan, BuildHost actor: 40 m/s arrival-ready 25/74 -> 74/74 (CVar-off control 15/74); 6/12/25 m/s stay 100%; -Z 50 m/s 93/93. Spawn unchanged (~7.7 s). Critical LOD0 path at 40 m/s: generation 67 ms p50, RMC body update 38 ms p50. LOD8 cost counted (native horizon 48 ms of 60), optimisation deferred. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
8440adc742
commit
e7586a1256
7 files changed
+507
-70
No files matched your search
@@ -197,6 +197,12 @@ namespace
|
||||
GVoxelForgeStreamingDynamicNearReserve,
|
||||
TEXT("Keep the authored near-worker reserve while moving or before the walkable ring is ready; default 1 releases idle slots after that gate, 0 restores the legacy fixed reserve."));
|
||||
|
||||
int32 GVoxelForgeStreamingCollisionLookahead = 1;
|
||||
FAutoConsoleVariableRef CVarVoxelForgeStreamingCollisionLookahead(
|
||||
TEXT("voxel.StreamingCollisionLookahead"),
|
||||
GVoxelForgeStreamingCollisionLookahead,
|
||||
TEXT("Request up to two collision rings ahead along player velocity; 0 disables predictive ring admission."));
|
||||
|
||||
int32 GVoxelForgeStreamingLegacyPendingResultCap = 0;
|
||||
FAutoConsoleVariableRef CVarVoxelForgeStreamingLegacyPendingResultCap(
|
||||
TEXT("voxel.StreamingLegacyPendingResultCap"),
|
||||
@@ -2056,6 +2062,7 @@ void AVoxelWorld::BeginPlay()
|
||||
int32 CommandLineSampleStacks = GVoxelForgeSampleStacks;
|
||||
int32 CommandLineCollisionGate = GVoxelForgeCollisionGate;
|
||||
int32 CommandLineCoreRegionConcurrentAdmission = GVoxelForgeCoreRegionConcurrentAdmission;
|
||||
int32 CommandLineStreamingCollisionLookahead = GVoxelForgeStreamingCollisionLookahead;
|
||||
int32 CommandLineStreamingResultBacklogCap = GVoxelForgeStreamingResultBacklogCap;
|
||||
int32 CommandLineStep1GenerationCap = GVoxelForgeStep1GenerationCap;
|
||||
int32 CommandLineStep1ExitAfterFrames = GVoxelForgeStep1ExitAfterFrames;
|
||||
@@ -2134,6 +2141,12 @@ void AVoxelWorld::BeginPlay()
|
||||
GVoxelForgeStreamingDynamicNearReserve);
|
||||
FParse::Value(FCommandLine::Get(), TEXT("voxel.StreamingLegacyPendingResultCap="),
|
||||
GVoxelForgeStreamingLegacyPendingResultCap);
|
||||
if (FParse::Value(FCommandLine::Get(), TEXT("voxel.StreamingCollisionLookahead="),
|
||||
CommandLineStreamingCollisionLookahead))
|
||||
{
|
||||
GVoxelForgeStreamingCollisionLookahead =
|
||||
CommandLineStreamingCollisionLookahead != 0 ? 1 : 0;
|
||||
}
|
||||
if (FParse::Value(FCommandLine::Get(), TEXT("voxel.CoreRegionConcurrentAdmission="),
|
||||
CommandLineCoreRegionConcurrentAdmission))
|
||||
{
|
||||
@@ -6896,8 +6909,8 @@ void AVoxelWorld::Tick(float DeltaTime)
|
||||
AdvanceHeadlessCollisionGateStressTest(PlayerLastPos, PlayerHeading, PlayerPawn);
|
||||
AdvanceHeadlessDigMotionTest(PlayerLastPos, PlayerPawn);
|
||||
PeakObservedPawnSpeedCmPerSecond = FMath::Max(
|
||||
PeakObservedPawnSpeedCmPerSecond, PlayerHeading.Size2D());
|
||||
StartupTraceSpeedCmPerSecond = PlayerHeading.Size2D();
|
||||
PeakObservedPawnSpeedCmPerSecond, PlayerHeading.Size());
|
||||
StartupTraceSpeedCmPerSecond = PlayerHeading.Size();
|
||||
UpdatePawnCollisionGate(PlayerPawn, PlayerLastPos, DeltaTime);
|
||||
RecordHeadlessDigMotionFrame(PlayerPawn, PlayerLastPos, DeltaTime);
|
||||
ObserveHeadlessStrateCrossingTest(PlayerLastPos, PlayerPawn);
|
||||
@@ -10253,6 +10266,52 @@ void AVoxelWorld::BuildDesiredTransitionIndex()
|
||||
}
|
||||
}
|
||||
|
||||
FIntVector AVoxelWorld::GetStreamingHeadingStep(const FVector& PlayerHeading,
|
||||
const APawn* PlayerPawn) const
|
||||
{
|
||||
FVector Heading = GetActorTransform().InverseTransformVectorNoScale(PlayerHeading);
|
||||
if (Heading.IsNearlyZero() && IsValid(PlayerPawn))
|
||||
{
|
||||
Heading = GetActorTransform().InverseTransformVectorNoScale(
|
||||
PlayerPawn->GetActorForwardVector());
|
||||
}
|
||||
|
||||
const float AbsX = FMath::Abs(Heading.X);
|
||||
const float AbsY = FMath::Abs(Heading.Y);
|
||||
const float AbsZ = FMath::Abs(Heading.Z);
|
||||
if (AbsX <= KINDA_SMALL_NUMBER && AbsY <= KINDA_SMALL_NUMBER
|
||||
&& AbsZ <= KINDA_SMALL_NUMBER)
|
||||
{
|
||||
return FIntVector::ZeroValue;
|
||||
}
|
||||
if (AbsX >= AbsY && AbsX >= AbsZ)
|
||||
{
|
||||
return FIntVector(Heading.X >= 0.0f ? 1 : -1, 0, 0);
|
||||
}
|
||||
if (AbsY >= AbsZ)
|
||||
{
|
||||
return FIntVector(0, Heading.Y >= 0.0f ? 1 : -1, 0);
|
||||
}
|
||||
return FIntVector(0, 0, Heading.Z >= 0.0f ? 1 : -1);
|
||||
}
|
||||
|
||||
int32 AVoxelWorld::GetStreamingCollisionLookaheadTiles(
|
||||
const FVector& PlayerHeading, const FIntVector& HeadingStep) const
|
||||
{
|
||||
if (GVoxelForgeStreamingCollisionLookahead == 0
|
||||
|| HeadingStep == FIntVector::ZeroValue || PlayerHeading.Size() < 50.0f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Aim 350 ms ahead, round up to a whole level-0 tile, and cap the lead at two tiles.
|
||||
// Viser 350 ms d'avance, arrondir au tile L0 superieur et limiter l'avance a deux tiles.
|
||||
const float TileWidthCm = static_cast<float>(CHUNK_SIZE) * GetActiveVoxelSizeCm();
|
||||
const int32 RequestedTiles = FMath::CeilToInt(
|
||||
PlayerHeading.Size() * 0.35f / FMath::Max(TileWidthCm, 1.0f));
|
||||
return FMath::Clamp(RequestedTiles, 1, 2);
|
||||
}
|
||||
|
||||
void AVoxelWorld::BuildCoreDesiredTiles(const FIntVector& Center, const FVector& PlayerPosition,
|
||||
APawn* PlayerPawn, const FVector& PlayerHeading,
|
||||
TArray<FVoxelTileKey>& OutLeavers)
|
||||
@@ -10279,6 +10338,12 @@ void AVoxelWorld::BuildCoreDesiredTiles(const FIntVector& Center, const FVector&
|
||||
{CameraVoxels.X, CameraVoxels.Y, CameraVoxels.Z});
|
||||
}
|
||||
|
||||
const FIntVector LookaheadHeadingStep = GetStreamingHeadingStep(PlayerHeading, PlayerPawn);
|
||||
const int32 LookaheadTiles = GetStreamingCollisionLookaheadTiles(
|
||||
PlayerHeading, LookaheadHeadingStep);
|
||||
int32 LookaheadCollisionTilesAdded = 0;
|
||||
int32 LookaheadDesiredTilesMissing = 0;
|
||||
|
||||
TArray<FVoxelTileKey> CandidateKeys;
|
||||
TSet<FVoxelTileKey> CandidateSet;
|
||||
TSet<FVoxelTileKey> BaseVisualTiles;
|
||||
@@ -10357,6 +10422,49 @@ void AVoxelWorld::BuildCoreDesiredTiles(const FIntVector& Center, const FVector&
|
||||
CollisionAnchorTiles.Add(Key);
|
||||
}
|
||||
|
||||
const FVoxelTileKey PlayerTile(GetTileCoordAtLocalCm(WorldToLocalCm(PlayerPosition)), 0);
|
||||
FVoxelTileKey OccupiedTile = PlayerTile;
|
||||
FVoxelTileKey SupportTile;
|
||||
if (GetPlayerSupportTile(PlayerPawn, PlayerPosition, SupportTile))
|
||||
{
|
||||
OccupiedTile = SupportTile;
|
||||
}
|
||||
|
||||
// Reserve the future 3x3 collision rings inside the existing LOD0 clipmap.
|
||||
// Reserver les prochains anneaux 3x3 dans le clipmap LOD0 deja present.
|
||||
for (int32 Ahead = 1; Ahead <= LookaheadTiles; ++Ahead)
|
||||
{
|
||||
const FIntVector AheadCenter = OccupiedTile.Coord + LookaheadHeadingStep * Ahead;
|
||||
for (int32 Dy = -1; Dy <= 1; ++Dy)
|
||||
for (int32 Dx = -1; Dx <= 1; ++Dx)
|
||||
{
|
||||
const FVoxelTileKey Key(AheadCenter + FIntVector(Dx, Dy, 0), 0);
|
||||
if (!CandidateSet.Contains(Key))
|
||||
{
|
||||
++LookaheadDesiredTilesMissing;
|
||||
continue;
|
||||
}
|
||||
if (!CollisionDesiredTiles.Contains(Key))
|
||||
{
|
||||
CollisionDesiredTiles.Add(Key);
|
||||
++LookaheadCollisionTilesAdded;
|
||||
}
|
||||
if (!BaseVisualTiles.Contains(Key)) CollisionAnchorTiles.Add(Key);
|
||||
}
|
||||
}
|
||||
if (LookaheadTiles > 0 && VoxelForgeStartupTrace::IsActive())
|
||||
{
|
||||
VoxelForgeStartupTrace::RecordEvent(TEXT("collision_lookahead"), FString::Printf(
|
||||
TEXT("\"center\":[%d,%d,%d],\"walkable_center\":[%d,%d,%d],"
|
||||
"\"heading_step\":[%d,%d,%d],\"speed_cm_s\":%s,"
|
||||
"\"lookahead_tiles\":%d,\"collision_tiles_added\":%d,\"desired_tiles_missing\":%d"),
|
||||
Center.X, Center.Y, Center.Z, OccupiedTile.Coord.X, OccupiedTile.Coord.Y,
|
||||
OccupiedTile.Coord.Z,
|
||||
LookaheadHeadingStep.X, LookaheadHeadingStep.Y, LookaheadHeadingStep.Z,
|
||||
*FString::SanitizeFloat(PlayerHeading.Size()), LookaheadTiles,
|
||||
LookaheadCollisionTilesAdded, LookaheadDesiredTilesMissing));
|
||||
}
|
||||
|
||||
for (const FVoxelTileKey& Key : CollisionAnchorTiles)
|
||||
{
|
||||
if (!BaseVisualTiles.Contains(Key) && !FullVisualAnchorTiles.Contains(Key))
|
||||
@@ -10391,13 +10499,6 @@ void AVoxelWorld::BuildCoreDesiredTiles(const FIntVector& Center, const FVector&
|
||||
}
|
||||
CancelObsoleteTileWork();
|
||||
|
||||
const FVoxelTileKey PlayerTile(GetTileCoordAtLocalCm(WorldToLocalCm(PlayerPosition)), 0);
|
||||
FVoxelTileKey OccupiedTile = PlayerTile;
|
||||
FVoxelTileKey SupportTile;
|
||||
if (GetPlayerSupportTile(PlayerPawn, PlayerPosition, SupportTile))
|
||||
{
|
||||
OccupiedTile = SupportTile;
|
||||
}
|
||||
auto AddCriticalTile = [this](const FVoxelTileKey& Key)
|
||||
{
|
||||
if (IsDesired(Key) && !CriticalDesiredTiles.Contains(Key))
|
||||
@@ -10415,22 +10516,7 @@ void AVoxelWorld::BuildCoreDesiredTiles(const FIntVector& Center, const FVector&
|
||||
}
|
||||
AddCriticalTile(OccupiedTile);
|
||||
|
||||
FVector Heading = GetActorTransform().InverseTransformVectorNoScale(PlayerHeading);
|
||||
if (Heading.IsNearlyZero() && IsValid(PlayerPawn))
|
||||
{
|
||||
Heading = GetActorTransform().InverseTransformVectorNoScale(
|
||||
PlayerPawn->GetActorForwardVector());
|
||||
}
|
||||
FIntVector HeadingStep = FIntVector::ZeroValue;
|
||||
const float AbsX = FMath::Abs(Heading.X);
|
||||
const float AbsY = FMath::Abs(Heading.Y);
|
||||
const float AbsZ = FMath::Abs(Heading.Z);
|
||||
if (AbsX > KINDA_SMALL_NUMBER || AbsY > KINDA_SMALL_NUMBER || AbsZ > KINDA_SMALL_NUMBER)
|
||||
{
|
||||
if (AbsX >= AbsY && AbsX >= AbsZ) HeadingStep.X = Heading.X >= 0.0f ? 1 : -1;
|
||||
else if (AbsY >= AbsZ) HeadingStep.Y = Heading.Y >= 0.0f ? 1 : -1;
|
||||
else HeadingStep.Z = Heading.Z >= 0.0f ? 1 : -1;
|
||||
}
|
||||
const FIntVector HeadingStep = LookaheadHeadingStep;
|
||||
if (HeadingStep != FIntVector::ZeroValue)
|
||||
{
|
||||
FVoxelTileKey NextTile = OccupiedTile;
|
||||
@@ -10443,9 +10529,19 @@ void AVoxelWorld::BuildCoreDesiredTiles(const FIntVector& Center, const FVector&
|
||||
for (int32 Dy = -1; Dy <= 1; ++Dy)
|
||||
for (int32 Dx = -1; Dx <= 1; ++Dx)
|
||||
{
|
||||
const FVoxelTileKey WalkableKey(PlayerTile.Coord + FIntVector(Dx, Dy, 0), 0);
|
||||
const FVoxelTileKey WalkableKey(OccupiedTile.Coord + FIntVector(Dx, Dy, 0), 0);
|
||||
if (CollisionDesiredTiles.Contains(WalkableKey)) AddCriticalTile(WalkableKey);
|
||||
}
|
||||
for (int32 Ahead = 1; Ahead <= LookaheadTiles; ++Ahead)
|
||||
{
|
||||
const FIntVector AheadCenter = OccupiedTile.Coord + HeadingStep * Ahead;
|
||||
for (int32 Dy = -1; Dy <= 1; ++Dy)
|
||||
for (int32 Dx = -1; Dx <= 1; ++Dx)
|
||||
{
|
||||
const FVoxelTileKey WalkableKey(AheadCenter + FIntVector(Dx, Dy, 0), 0);
|
||||
if (CollisionDesiredTiles.Contains(WalkableKey)) AddCriticalTile(WalkableKey);
|
||||
}
|
||||
}
|
||||
for (int32 Index = CriticalDesiredTiles.Num() - 1; Index >= 0; --Index)
|
||||
{
|
||||
const int32 ExistingIndex = DesiredSorted.Find(CriticalDesiredTiles[Index]);
|
||||
@@ -10710,6 +10806,11 @@ void AVoxelWorld::BuildDesiredTiles(const FIntVector& Center, const FVector& Pla
|
||||
++DesiredEpoch;
|
||||
DesiredEpochStartCycles = FPlatformTime::Cycles64();
|
||||
DesiredEpochCenterChunk = Center;
|
||||
const FIntVector LookaheadHeadingStep = GetStreamingHeadingStep(PlayerHeading, PlayerPawn);
|
||||
const int32 LookaheadTiles = GetStreamingCollisionLookaheadTiles(
|
||||
PlayerHeading, LookaheadHeadingStep);
|
||||
int32 LookaheadCollisionTilesAdded = 0;
|
||||
int32 LookaheadDesiredTilesMissing = 0;
|
||||
|
||||
const int32 R = Settings ? FMath::Max(1, Settings->ClipRadius) : 6;
|
||||
const int32 MaxLevel = Settings ? FMath::Clamp(Settings->MaxClipLevel, 0, 8) : 4;
|
||||
@@ -10791,6 +10892,49 @@ void AVoxelWorld::BuildDesiredTiles(const FIntVector& Center, const FVector& Pla
|
||||
CollisionDesiredTiles.Add(Key);
|
||||
}
|
||||
|
||||
const FVoxelTileKey PlayerTile(
|
||||
WorldToChunkCoord(WorldToLocalCm(PlayerPosition)), 0);
|
||||
FVoxelTileKey OccupiedTile = PlayerTile;
|
||||
FVoxelTileKey SupportTile;
|
||||
if (GetPlayerSupportTile(PlayerPawn, PlayerPosition, SupportTile))
|
||||
{
|
||||
OccupiedTile = SupportTile;
|
||||
}
|
||||
|
||||
// Reserve predictive collision inside the current clipmap so those tiles cook before arrival.
|
||||
// Reserver la collision predictive dans le clipmap courant pour cuire avant l'arrivee.
|
||||
for (int32 Ahead = 1; Ahead <= LookaheadTiles; ++Ahead)
|
||||
{
|
||||
const FIntVector AheadCenter = OccupiedTile.Coord + LookaheadHeadingStep * Ahead;
|
||||
for (int32 Dy = -1; Dy <= 1; ++Dy)
|
||||
for (int32 Dx = -1; Dx <= 1; ++Dx)
|
||||
{
|
||||
const FVoxelTileKey Key(AheadCenter + FIntVector(Dx, Dy, 0), 0);
|
||||
if (!IsDesired(Key))
|
||||
{
|
||||
++LookaheadDesiredTilesMissing;
|
||||
continue;
|
||||
}
|
||||
if (!CollisionDesiredTiles.Contains(Key))
|
||||
{
|
||||
CollisionDesiredTiles.Add(Key);
|
||||
++LookaheadCollisionTilesAdded;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (LookaheadTiles > 0 && VoxelForgeStartupTrace::IsActive())
|
||||
{
|
||||
VoxelForgeStartupTrace::RecordEvent(TEXT("collision_lookahead"), FString::Printf(
|
||||
TEXT("\"center\":[%d,%d,%d],\"walkable_center\":[%d,%d,%d],"
|
||||
"\"heading_step\":[%d,%d,%d],\"speed_cm_s\":%s,"
|
||||
"\"lookahead_tiles\":%d,\"collision_tiles_added\":%d,\"desired_tiles_missing\":%d"),
|
||||
Center.X, Center.Y, Center.Z, OccupiedTile.Coord.X, OccupiedTile.Coord.Y,
|
||||
OccupiedTile.Coord.Z,
|
||||
LookaheadHeadingStep.X, LookaheadHeadingStep.Y, LookaheadHeadingStep.Z,
|
||||
*FString::SanitizeFloat(PlayerHeading.Size()), LookaheadTiles,
|
||||
LookaheadCollisionTilesAdded, LookaheadDesiredTilesMissing));
|
||||
}
|
||||
|
||||
if (GVoxelForgeProfileTileGeneration != 0)
|
||||
{
|
||||
int32 RenderLOD0Count = 0;
|
||||
@@ -10860,15 +11004,6 @@ void AVoxelWorld::BuildDesiredTiles(const FIntVector& Center, const FVector& Pla
|
||||
// one that can catch a falling pawn — followed by the adjacent tile in the dominant movement
|
||||
// direction. Keep the actor-centre tile as a fallback for capsule/offset edge cases. Only keys
|
||||
// in the current desired set are promoted, so this never expands the streaming footprint.
|
||||
const FVoxelTileKey PlayerTile(
|
||||
WorldToChunkCoord(WorldToLocalCm(PlayerPosition)), 0);
|
||||
FVoxelTileKey OccupiedTile = PlayerTile;
|
||||
FVoxelTileKey SupportTile;
|
||||
if (GetPlayerSupportTile(PlayerPawn, PlayerPosition, SupportTile))
|
||||
{
|
||||
OccupiedTile = SupportTile;
|
||||
}
|
||||
|
||||
auto AddCriticalTile = [this](const FVoxelTileKey& Key)
|
||||
{
|
||||
if (IsDesired(Key) && !CriticalDesiredTiles.Contains(Key))
|
||||
@@ -10889,31 +11024,7 @@ void AVoxelWorld::BuildDesiredTiles(const FIntVector& Center, const FVector& Pla
|
||||
}
|
||||
AddCriticalTile(OccupiedTile);
|
||||
|
||||
FVector Heading = PlayerHeading;
|
||||
if (Heading.IsNearlyZero() && IsValid(PlayerPawn))
|
||||
{
|
||||
Heading = PlayerPawn->GetActorForwardVector();
|
||||
}
|
||||
Heading = GetActorTransform().InverseTransformVectorNoScale(Heading);
|
||||
const float AbsX = FMath::Abs(Heading.X);
|
||||
const float AbsY = FMath::Abs(Heading.Y);
|
||||
const float AbsZ = FMath::Abs(Heading.Z);
|
||||
FIntVector HeadingStep = FIntVector::ZeroValue;
|
||||
if (AbsX > KINDA_SMALL_NUMBER || AbsY > KINDA_SMALL_NUMBER || AbsZ > KINDA_SMALL_NUMBER)
|
||||
{
|
||||
if (AbsX >= AbsY && AbsX >= AbsZ)
|
||||
{
|
||||
HeadingStep.X = Heading.X >= 0.0f ? 1 : -1;
|
||||
}
|
||||
else if (AbsY >= AbsZ)
|
||||
{
|
||||
HeadingStep.Y = Heading.Y >= 0.0f ? 1 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
HeadingStep.Z = Heading.Z >= 0.0f ? 1 : -1;
|
||||
}
|
||||
}
|
||||
const FIntVector HeadingStep = LookaheadHeadingStep;
|
||||
if (HeadingStep != FIntVector::ZeroValue)
|
||||
{
|
||||
FVoxelTileKey NextTile = OccupiedTile;
|
||||
@@ -10926,9 +11037,19 @@ void AVoxelWorld::BuildDesiredTiles(const FIntVector& Center, const FVector& Pla
|
||||
for (int32 Dy = -1; Dy <= 1; ++Dy)
|
||||
for (int32 Dx = -1; Dx <= 1; ++Dx)
|
||||
{
|
||||
const FVoxelTileKey WalkableKey(PlayerTile.Coord + FIntVector(Dx, Dy, 0), 0);
|
||||
const FVoxelTileKey WalkableKey(OccupiedTile.Coord + FIntVector(Dx, Dy, 0), 0);
|
||||
if (CollisionDesiredTiles.Contains(WalkableKey)) AddCriticalTile(WalkableKey);
|
||||
}
|
||||
for (int32 Ahead = 1; Ahead <= LookaheadTiles; ++Ahead)
|
||||
{
|
||||
const FIntVector AheadCenter = OccupiedTile.Coord + HeadingStep * Ahead;
|
||||
for (int32 Dy = -1; Dy <= 1; ++Dy)
|
||||
for (int32 Dx = -1; Dx <= 1; ++Dx)
|
||||
{
|
||||
const FVoxelTileKey WalkableKey(AheadCenter + FIntVector(Dx, Dy, 0), 0);
|
||||
if (CollisionDesiredTiles.Contains(WalkableKey)) AddCriticalTile(WalkableKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert in reverse so CriticalDesiredTiles[0] remains the occupied floor, [1] the heading
|
||||
// tile, and all ordinary distance-sorted work follows both.
|
||||
@@ -11378,7 +11499,7 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
? LastStreamingSchedulerSampleSeconds : StreamingUpdateStartSeconds;
|
||||
const double IntervalSeconds = FMath::Max(0.0, Now - IntervalStart);
|
||||
const double BusySeconds = FPlatformTime::ToSeconds64(WorkerCyclesDelta);
|
||||
const double SpeedCmPerSecond = PlayerHeading.Size2D();
|
||||
const double SpeedCmPerSecond = PlayerHeading.Size();
|
||||
VoxelForgeStartupTrace::RecordEvent(TEXT("scheduler_skip"), FString::Printf(
|
||||
TEXT("\"frame\":%llu,\"reason\":\"%s\",\"desired_count\":%d,"
|
||||
"\"desired_missing\":%d,\"desired_missing_by_lod\":%s,"
|
||||
@@ -11589,7 +11710,7 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
bGateCenterChanged ? WalkableCenter.Y - PreviousGateCenter.Y : 0,
|
||||
bGateCenterChanged ? WalkableCenter.Z - PreviousGateCenter.Z : 0,
|
||||
bGateCenterChanged ? 1 : 0, bWalkableRingReadyForReserve ? 1 : 0,
|
||||
WalkableRingReadyCount, *FString::SanitizeFloat(PlayerHeading.Size2D()), DesiredEpoch));
|
||||
WalkableRingReadyCount, *FString::SanitizeFloat(PlayerHeading.Size()), DesiredEpoch));
|
||||
bHasLastWalkableGateSample = true;
|
||||
LastWalkableGateCenter = WalkableCenter;
|
||||
bLastWalkableGateReady = bWalkableRingReadyForReserve;
|
||||
@@ -11600,7 +11721,7 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
RecordSchedulerSkip(TEXT("core_region_compile_pending"));
|
||||
return;
|
||||
}
|
||||
const bool bPawnMoving = PlayerHeading.Size2D() >= 50.0f;
|
||||
const bool bPawnMoving = PlayerHeading.Size() >= 50.0f;
|
||||
EffectiveNearTaskReserve = GVoxelForgeStreamingDynamicNearReserve == 0
|
||||
? AuthoredNearTaskReserve
|
||||
: ((bPawnMoving || !bWalkableRingReadyForReserve) ? AuthoredNearTaskReserve : 0);
|
||||
@@ -12219,7 +12340,7 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
CenterChunk.X, CenterChunk.Y, CenterChunk.Z,
|
||||
*FString::SanitizeFloat(LocalPawn.X), *FString::SanitizeFloat(LocalPawn.Y),
|
||||
*FString::SanitizeFloat(LocalPawn.Z),
|
||||
*FString::SanitizeFloat(PlayerHeading.Size2D()),
|
||||
*FString::SanitizeFloat(PlayerHeading.Size()),
|
||||
bWalkableRingReadyForReserve ? 1 : 0,
|
||||
*DesiredCounts, *ResidentCounts, *PendingCounts,
|
||||
GetActiveGenerationTaskCount(), GetGenerationAdmissionCount(), MaxTasks, NearTaskReserve,
|
||||
|
||||
@@ -702,6 +702,10 @@ private:
|
||||
void BuildCoreDesiredTiles(const FIntVector& Center, const FVector& PlayerPosition,
|
||||
APawn* PlayerPawn, const FVector& PlayerHeading,
|
||||
TArray<FVoxelTileKey>& OutLeavers);
|
||||
FIntVector GetStreamingHeadingStep(const FVector& PlayerHeading,
|
||||
const APawn* PlayerPawn) const;
|
||||
int32 GetStreamingCollisionLookaheadTiles(const FVector& PlayerHeading,
|
||||
const FIntVector& HeadingStep) const;
|
||||
void StartPendingCoreRegionCompile();
|
||||
void LoadCoreTile(const FVoxelTileKey& Tile, EVoxelTileWorkPriority WorkPriority);
|
||||
void EnqueueStreamingResult(FChunkResult&& Result);
|
||||
|
||||
@@ -17490,6 +17490,24 @@ bool RunCoreWorldActorIntegrationTest(const FExploreArguments& Arguments, FStrin
|
||||
float WalkSpeedCmPerSecond = 600.0f;
|
||||
FParse::Value(FCommandLine::Get(), TEXT("voxel.TestMoveSpeedCmPerSecond="),
|
||||
WalkSpeedCmPerSecond);
|
||||
FString WalkDirectionText(TEXT("0,1,0"));
|
||||
const FString DirectionKey(TEXT("voxel.TestMoveDirection="));
|
||||
const FString CommandLineText(FCommandLine::Get());
|
||||
const int32 DirectionKeyIndex = CommandLineText.Find(
|
||||
DirectionKey, ESearchCase::IgnoreCase, ESearchDir::FromStart);
|
||||
if (DirectionKeyIndex != INDEX_NONE)
|
||||
{
|
||||
WalkDirectionText = CommandLineText.Mid(DirectionKeyIndex + DirectionKey.Len());
|
||||
const int32 DirectionEnd = WalkDirectionText.Find(
|
||||
TEXT(" "), ESearchCase::CaseSensitive, ESearchDir::FromStart);
|
||||
if (DirectionEnd != INDEX_NONE)
|
||||
{
|
||||
WalkDirectionText.LeftInline(DirectionEnd, EAllowShrinking::No);
|
||||
}
|
||||
WalkDirectionText.TrimStartAndEndInline();
|
||||
WalkDirectionText.RemoveFromStart(TEXT("\""));
|
||||
WalkDirectionText.RemoveFromEnd(TEXT("\""));
|
||||
}
|
||||
TArray<double> SpawnTickMilliseconds;
|
||||
TArray<double> WalkTickMilliseconds;
|
||||
TArray<TPair<double, double>> TickSamples;
|
||||
@@ -17569,11 +17587,11 @@ bool RunCoreWorldActorIntegrationTest(const FExploreArguments& Arguments, FStrin
|
||||
return false;
|
||||
}
|
||||
UE_LOG(LogTemp, Display,
|
||||
TEXT("[VoxelForgeCoreWorldStreamTrace] pass complete=1 recipe=%s voxel_cm=%.3f walk_speed_cm_s=%.0f walk_direction=+Y"),
|
||||
TEXT("[VoxelForgeCoreWorldStreamTrace] pass complete=1 recipe=%s voxel_cm=%.3f walk_speed_cm_s=%.0f walk_direction=%s"),
|
||||
Arguments.CoreHybridMesherVersion == 2 ? TEXT("WorldAssemblerHybridV2")
|
||||
: (Arguments.CoreHybridMesherVersion == 1 ? TEXT("WorldAssemblerHybridV1")
|
||||
: TEXT("MarchingCubesV1")),
|
||||
Arguments.CoreVoxelSizeCm, WalkSpeedCmPerSecond);
|
||||
Arguments.CoreVoxelSizeCm, WalkSpeedCmPerSecond, *WalkDirectionText);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user