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>
102 lines
4.0 KiB
C++
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);
|
|
}
|