Files
VoxelForge/Source/VoxelForge/Private/VoxelStrateDefinition.cpp
T
Fr0zkaandClaude Opus 5.5 fc9227f9e0 fix(unreal): U1 -- Unreal compiles again on L61; CoreGeometry asset section; versioned layout-unit upgrade
Windows MSVC catch-up after abyss L15-L61 (no Unreal there): 64-bit clipmap
shift (C4334), qualified VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel, UHT
metadata and duplicate-signature fixes. Optional CoreGeometry section on
UVoxelStrateDefinition (native caves, lattice, profiled heightfields, named
stamps, rooms/tunnels; off/empty by default), resolved after passage planning.
VoxelForgeAssetVersion 2 converts strate height/transition/gap to metres on
load (exact, 0 m change on the owner's 5 assets; packages never saved).
Gates pass (SurfaceWorld, FloatingIslands, Core-off, M2, W1/W8/W16).
KNOWN REGRESSION vs L14 (2026-10-20, same command, same PC): full set 3.9 ->
5.37 s, worker-seconds 15.8 -> 30, LOD0 1.11 -> 1.69 s, ring 0.50 -> 0.80 s;
not yet attributed (Core L15-L61 vs Unreal side).
Report: Standalone/Research/WorldAssemblerM3/Unreal1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 12:12:08 +01:00

102 lines
4.0 KiB
C++

// Serialized strate-definition migrations.
#include "VoxelStrateDefinition.h"
#include "VoxelForgeAssetVersion.h"
#include "Serialization/CustomVersion.h"
#include "VoxelPassageGeometry.h"
namespace
{
constexpr int32 GVoxelForgeStrateGentleSlopeDegreesVersion = VoxelForgeAssetVersion::TunnelFloorSlopeDegrees;
FCustomVersionRegistration GVoxelForgeStrateSerializationRegistration(
VoxelForgeAssetVersion::GUID,
VoxelForgeAssetVersion::MetreAuthoringV1,
TEXT("VoxelForgeStrateSerialization"));
float LegacyGradientToDegrees(float LegacyGradient)
{
if (!VoxelMath::IsFinite(LegacyGradient) || LegacyGradient <= 0.0f)
{
return 0.0f;
}
if (LegacyGradient >= 4096.0f)
{
return VoxelPassageGeometry::TunnelFloorGentleSlopeMaximumDegrees;
}
// Invert the old gradient without atan/tan. The same deterministic sine/cosine helper
// used by generation makes this migration independent of the host CRT.
float LowDegrees = 0.0f;
float HighDegrees = VoxelPassageGeometry::TunnelFloorGentleSlopeMaximumDegrees;
for (int32 Iteration = 0; Iteration < 32; ++Iteration)
{
const float MidDegrees = (LowDegrees + HighDegrees) * 0.5f;
float SinValue = 0.0f;
float CosValue = 0.0f;
VoxelMath::DetSinCos(
SinValue, CosValue, MidDegrees * (PI / 180.0f));
const float MidGradient = FMath::Min(
FMath::Abs(SinValue) / FMath::Max(FMath::Abs(CosValue), 1.0e-3f),
4096.0f);
if (MidGradient < LegacyGradient)
{
LowDegrees = MidDegrees;
}
else
{
HighDegrees = MidDegrees;
}
}
return FMath::Clamp(
(LowDegrees + HighDegrees) * 0.5f,
0.0f,
VoxelPassageGeometry::TunnelFloorGentleSlopeMaximumDegrees);
}
}
void UVoxelStrateDefinition::Serialize(FArchive& Ar)
{
Ar.UsingCustomVersion(VoxelForgeAssetVersion::GUID);
Super::Serialize(Ar);
if (Ar.IsLoading() && Ar.CustomVer(VoxelForgeAssetVersion::GUID)
< VoxelForgeAssetVersion::MetreAuthoringV1)
{
// A stand-alone strate has no owning settings object during Serialize. Convert using the
// current 8 m layout default here; UVoxelSettings corrects referenced old strates using
// their saved effective width during its own load upgrade.
// Une strate seule n'a pas ses reglages proprietaires ici; UVoxelSettings corrige ensuite
// les references avec leur largeur physique sauvegardee.
constexpr double LegacyDefaultLayoutChunkMeters = 8.0;
StrateHeightMeters = static_cast<double>(FMath::Max(1, StrateHeightInChunks))
* LegacyDefaultLayoutChunkMeters;
TransitionWidthMeters = static_cast<double>(FMath::Max(0, TransitionBlendChunks))
* LegacyDefaultLayoutChunkMeters;
UE_LOG(LogTemp, Display,
TEXT("[VoxelForgeAssetUpgrade] type=Strate asset=%s height_chunks=%d height_m=%.6f transition_chunks=%d transition_m=%.6f fallback_layout_chunk_m=%.6f"),
*GetPathName(), StrateHeightInChunks, StrateHeightMeters,
TransitionBlendChunks, TransitionWidthMeters, LegacyDefaultLayoutChunkMeters);
}
}
void UVoxelStrateDefinition::PostLoad()
{
Super::PostLoad();
// The field remains reflected solely so old packages deserialize without shifting the
// following members. Tunnel geometry owns the floor now, so every serialized legacy value
// is normalized to the ignored compatibility default before any runtime copy is made.
GenerationParams.bTunnelFloorEnabled = true;
if (GetLinkerCustomVersion(VoxelForgeAssetVersion::GUID)
>= GVoxelForgeStrateGentleSlopeDegreesVersion)
{
return;
}
const float LegacyGradient = GenerationParams.TunnelFloorGentleSlopeThreshold;
GenerationParams.TunnelFloorGentleSlopeThreshold =
LegacyGradientToDegrees(LegacyGradient);
}