This repository has been archived on 2026-10-29. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
CultMath/unity/Runtime/PlanetaryPageUpload.cs

95 lines
3.1 KiB
C#

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;
}
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; }
}
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();
var content = PlanetaryGpuPageBuilder.BuildContent(layout, radius);
var outputOffset = inputs.Count;
foreach (var input in content.Inputs)
{
inputs.Add(new(
ToUnity(input.DirectionRadius),
ToUnity(input.Sampling)));
}
var commonMetadata = PlanetaryGpuPageBuilder.Metadata(content, outputOffset, resident.Blend);
metadata[pageIndex] = new(
ToUnity(commonMetadata.Address),
ToUnity(commonMetadata.Layout),
ToUnity(commonMetadata.Bounds),
ToUnity(commonMetadata.State));
}
return new(inputs.ToArray(), metadata, inputs.Count, snapshot.ContentVersion, snapshot.PresentationVersion);
}
private static Vector4 ToUnity(float4 value) => new(value.x, value.y, value.z, value.w);
}