2026-07-13 02:14:11 +01:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Runtime.InteropServices ;
using UnityEngine ;
namespace CultMath.Unity ;
[StructLayout(LayoutKind.Sequential)]
public readonly struct PlanetaryPageInputGpu
{
public PlanetaryPageInputGpu ( Vector4 directionRadius , Vector4 sampling )
{
DirectionRadius = directionRadius ;
Sampling = sampling ;
}
public readonly Vector4 DirectionRadius ;
public readonly Vector4 Sampling ;
}
[StructLayout(LayoutKind.Sequential)]
public readonly struct PlanetaryPageMetadataGpu
{
public PlanetaryPageMetadataGpu ( Vector4 address , Vector4 layout , Vector4 bounds , Vector4 state )
{
Address = address ;
Layout = layout ;
Bounds = bounds ;
State = state ;
}
public readonly Vector4 Address ;
public readonly Vector4 Layout ;
public readonly Vector4 Bounds ;
public readonly Vector4 State ;
}
2026-07-13 02:52:13 +01:00
public readonly struct PlanetaryPageUpload
{
public PlanetaryPageUpload (
PlanetaryPageInputGpu [ ] inputs ,
PlanetaryPageMetadataGpu [ ] metadata ,
int outputSampleCount ,
ulong contentVersion ,
ulong presentationVersion )
{
Inputs = inputs ;
Metadata = metadata ;
OutputSampleCount = outputSampleCount ;
ContentVersion = contentVersion ;
PresentationVersion = presentationVersion ;
}
public PlanetaryPageInputGpu [ ] Inputs { get ; }
public PlanetaryPageMetadataGpu [ ] Metadata { get ; }
public int OutputSampleCount { get ; }
public ulong ContentVersion { get ; }
public ulong PresentationVersion { get ; }
}
2026-07-13 02:14:11 +01:00
public static class PlanetaryPageUploadBuilder
{
public static PlanetaryPageUpload Build (
in PlanetaryResidencySnapshot snapshot ,
int interiorSize ,
int borderSize ,
float radius )
{
if ( ! float . IsFinite ( radius ) | | radius < = 0 ) throw new ArgumentOutOfRangeException ( nameof ( radius ) ) ;
var inputs = new List < PlanetaryPageInputGpu > ( ) ;
var metadata = new PlanetaryPageMetadataGpu [ snapshot . Tiles . Length ] ;
foreach ( var ( resident , pageIndex ) in snapshot . Tiles . Select ( ( resident , index ) = > ( resident , index ) ) )
{
var layout = new PlanetaryPageLayout ( resident . Tile , interiorSize , borderSize ) . Validate ( ) ;
2026-07-13 02:52:13 +01:00
var content = PlanetaryGpuPageBuilder . BuildContent ( layout , radius ) ;
2026-07-13 02:14:11 +01:00
var outputOffset = inputs . Count ;
2026-07-13 02:52:13 +01:00
foreach ( var input in content . Inputs )
2026-07-13 02:14:11 +01:00
{
inputs . Add ( new (
2026-07-13 02:52:13 +01:00
ToUnity ( input . DirectionRadius ) ,
ToUnity ( input . Sampling ) ) ) ;
2026-07-13 02:14:11 +01:00
}
2026-07-13 02:52:13 +01:00
var commonMetadata = PlanetaryGpuPageBuilder . Metadata ( content , outputOffset , resident . Blend ) ;
2026-07-13 02:14:11 +01:00
metadata [ pageIndex ] = new (
2026-07-13 02:52:13 +01:00
ToUnity ( commonMetadata . Address ) ,
ToUnity ( commonMetadata . Layout ) ,
ToUnity ( commonMetadata . Bounds ) ,
ToUnity ( commonMetadata . State ) ) ;
2026-07-13 02:14:11 +01:00
}
return new ( inputs . ToArray ( ) , metadata , inputs . Count , snapshot . ContentVersion , snapshot . PresentationVersion ) ;
}
2026-07-13 02:52:13 +01:00
private static Vector4 ToUnity ( float4 value ) = > new ( value . x , value . y , value . z , value . w ) ;
2026-07-13 02:14:11 +01:00
}