sandpypi/Sand.ChunkPrototype/PrototypeSparseSandAdapter.Runtime.Thermal.cs

84 lines
3.2 KiB
C#

using Sand.Core;
namespace Sand.ChunkPrototype;
public sealed partial class PrototypeSparseSandAdapter
{
private void ApplyHeatEmission(int x, int y, float amount)
{
AdjustTemperatureAt(x, y, amount * 0.08f);
AdjustTemperatureAt(x - 1, y, amount * 0.02f);
AdjustTemperatureAt(x + 1, y, amount * 0.02f);
AdjustTemperatureAt(x, y - 1, amount * 0.02f);
AdjustTemperatureAt(x, y + 1, amount * 0.02f);
}
private void ApplyTemperatureDiffusion(int x, int y, PrototypeParticle particle)
{
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
{
return;
}
var localTemperature = page.GetTemperature(localX, localY);
var airDelta = localTemperature - _ambientTemperature;
if (MathF.Abs(airDelta) > 0.5f)
{
var minTransfer = Math.Min(airDelta * -0.5f, airDelta * 0.5f);
var maxTransfer = Math.Max(airDelta * -0.5f, airDelta * 0.5f);
var transfer = Math.Clamp(
airDelta * 0.05f * particle.AmbientCoolingMultiplier / MathF.Max(0.1f, particle.Conductivity <= 0f ? 1f : particle.Conductivity),
minTransfer,
maxTransfer);
page.SetTemperature(localX, localY, localTemperature - transfer);
localTemperature -= transfer;
}
DiffuseBetween(x, y, x + 1, y, particle, localTemperature);
DiffuseBetween(x, y, x, y + 1, particle, localTemperature);
}
private void AdjustTemperatureAt(int x, int y, float delta)
{
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
{
return;
}
page.SetTemperature(localX, localY, page.GetTemperature(localX, localY) + delta);
}
private void DiffuseBetween(int x, int y, int nx, int ny, PrototypeParticle particle, float localTemperature)
{
if (!TryGetCellPage(x, y, out _, out var sourcePage, out var sourceLocalX, out var sourceLocalY) ||
!TryGetCellPage(nx, ny, out _, out var targetPage, out var targetLocalX, out var targetLocalY))
{
return;
}
var neighborParticle = targetPage[targetLocalX, targetLocalY];
if (neighborParticle.TypeId == 0)
{
return;
}
var neighborTemperature = targetPage.GetTemperature(targetLocalX, targetLocalY);
var delta = localTemperature - neighborTemperature;
if (MathF.Abs(delta) <= 0.5f)
{
return;
}
var sourceConductivity = MathF.Max(particle.Conductivity, 0.1f);
var targetConductivity = MathF.Max(neighborParticle.Conductivity, 0.1f);
var minTransfer = Math.Min(delta * -0.5f, delta * 0.5f);
var maxTransfer = Math.Max(delta * -0.5f, delta * 0.5f);
var transfer = Math.Clamp(
delta * ((sourceConductivity + targetConductivity) * 0.5f) * 0.1f * particle.NeighborHeatTransferMultiplier,
minTransfer,
maxTransfer);
sourcePage.SetTemperature(sourceLocalX, sourceLocalY, localTemperature - transfer);
targetPage.SetTemperature(targetLocalX, targetLocalY, neighborTemperature + transfer);
}
}