Editor/Roof/ArchVaultGen.cs
using System;
using System.Collections.Generic;
using Sandbox;
namespace Sunless.Architecture;
public static class ArchVaultGen {
public static void Build( ArchMesh canvas, ArchRoofPart roof, ArchKit kit, ArchStyle style ) {
var outline = roof.Outline();
if ( outline.Count < 4 ) {
return;
}
ArchFootprint.Bounds( outline, out var min, out var max );
var alongX = roof.RidgeAlongX;
var runFrom = alongX ? min.x : min.y;
var runTo = alongX ? max.x : max.y;
var acrossFrom = alongX ? min.y : min.x;
var acrossTo = alongX ? max.y : max.x;
var span = acrossTo - acrossFrom;
var rise = MathF.Min( MathF.Max( 8f, roof.VaultRise ), span * 0.48f );
var crown = roof.BaseHeight - MathF.Max( 1f, roof.Thickness );
var spring = crown - rise;
var brush = style.Brush( ArchSurface.Ceiling, roof.Palette );
const int segments = 16;
for ( var index = 0; index < segments; index++ ) {
var from = acrossFrom + span * index / segments;
var to = acrossFrom + span * (index + 1) / segments;
var fromHeight = Height( from, acrossFrom, span, spring, crown );
var toHeight = Height( to, acrossFrom, span, spring, crown );
if ( alongX ) {
canvas.Quad(
new Vector3( runFrom, from, fromHeight ),
new Vector3( runFrom, to, toHeight ),
new Vector3( runTo, to, toHeight ),
new Vector3( runTo, from, fromHeight ), brush );
} else {
canvas.Quad(
new Vector3( from, runFrom, fromHeight ),
new Vector3( to, runFrom, toHeight ),
new Vector3( to, runTo, toHeight ),
new Vector3( from, runTo, fromHeight ), brush );
}
}
}
static float Height( float at, float from, float span, float spring, float crown ) {
var fraction = Math.Clamp( (at - from) / MathF.Max( 1f, span ), 0f, 1f );
return spring + (crown - spring) * MathF.Sin( fraction * MathF.PI );
}
}