Delete AetheriaMath in favour of CultMath
AetheriaMath predates the CultMath swap and re-implemented helpers CultMath now owns. Callers use CultMath directly: decay (Ship, AetherDrive, Entity), damp (VelocityConversion, FieldTester, FieldDriver), first_order_intercept (TurretController, Combat, GuidedProjectile), quadratic_bezier (FieldDriver) and smootherstep (Ship). Parameter order matches in every case, and those formulas have the same float evaluation order, so behaviour is unchanged. Galaxy's commented-out segment check names distance_to_segment. The other overloads had no callers and are dropped without a CultMath counterpart being needed: the double Damp overloads, FindDistanceToSegment, GetCatmullRomPosition, GetCubicSplinePosition, Smoothstep(x), and the Deg2Rad/Rad2Deg constants. AetherDb census, factions and hardpoint-fit are byte-identical to the pre-cut captures. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
e308c19e4c
commit
55c3fc6a49
12 changed files with 19 additions and 273 deletions
|
|
@ -233,7 +233,7 @@ public class FieldDriver : MonoBehaviour
|
|||
|
||||
if (_grabObject != null)
|
||||
{
|
||||
_tendrilBasePos = AetheriaMath.Damp(_tendrilBasePos.ToCultMath(), _grabObject.position.ToCultMath(), TendrilBaseDamping, Time.deltaTime).ToUnity();
|
||||
_tendrilBasePos = damp(_tendrilBasePos.ToCultMath(), _grabObject.position.ToCultMath(), TendrilBaseDamping, Time.deltaTime).ToUnity();
|
||||
switch (_grabPhase)
|
||||
{
|
||||
case GrabPhase.Extend:
|
||||
|
|
@ -292,7 +292,7 @@ public class FieldDriver : MonoBehaviour
|
|||
for (int i = 1; i <= GIZMO_STEPS; i++)
|
||||
{
|
||||
var l = (float)i / GIZMO_STEPS;
|
||||
var next = AetheriaMath.GetQuadraticSplinePosition(_tendrilBasePos.ToCultMath(), _tendrilBendTarget.ToCultMath(), _tendrilTargetPos.ToCultMath(), l).ToUnity();
|
||||
var next = quadratic_bezier(_tendrilBasePos.ToCultMath(), _tendrilBendTarget.ToCultMath(), _tendrilTargetPos.ToCultMath(), l).ToUnity();
|
||||
Gizmos.DrawLine(previous, next);
|
||||
previous = next;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public class GuidedProjectile : MonoBehaviour
|
|||
var targetPosition = TargetPosition?.Invoke() ?? Target.position;
|
||||
_targetVelocity = lerp(_targetVelocity.ToCultMath(), (targetPosition - _previousTargetPosition).ToCultMath(), saturate(Time.deltaTime * 5)).ToUnity();
|
||||
_previousTargetPosition = targetPosition;
|
||||
targetPosition = AetheriaMath.FirstOrderIntercept(position,float3.zero, TopSpeed, targetPosition.ToCultMath(), _targetVelocity.ToCultMath()).ToUnity();
|
||||
targetPosition = first_order_intercept(position,float3.zero, TopSpeed, targetPosition.ToCultMath(), _targetVelocity.ToCultMath()).ToUnity();
|
||||
|
||||
var diff = targetPosition - transform.position;
|
||||
var targetDist = diff.magnitude;
|
||||
|
|
|
|||
|
|
@ -1,243 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using CultMath;
|
||||
using static CultMath.math;
|
||||
|
||||
public static class AetheriaMath
|
||||
{
|
||||
public const float Deg2Rad = 0.01745329f;
|
||||
public const float Rad2Deg = 57.29578f;
|
||||
|
||||
public static float Decay(float source, float lambda, float dt)
|
||||
{
|
||||
return source * exp(-lambda * dt);
|
||||
}
|
||||
|
||||
public static float3 Decay(float3 source, float lambda, float dt)
|
||||
{
|
||||
return source * exp(-lambda * dt);
|
||||
}
|
||||
|
||||
public static float3 Decay(float3 source, float3 lambda, float dt)
|
||||
{
|
||||
return source * exp(-lambda * dt);
|
||||
}
|
||||
|
||||
public static float Damp(float a, float b, float lambda, float dt)
|
||||
{
|
||||
return lerp(a, b, 1 - exp(-lambda * dt));
|
||||
}
|
||||
|
||||
public static float2 Damp(float2 a, float2 b, float lambda, float dt)
|
||||
{
|
||||
return lerp(a, b, 1 - exp(-lambda * dt));
|
||||
}
|
||||
|
||||
public static float3 Damp(float3 a, float3 b, float lambda, float dt)
|
||||
{
|
||||
return lerp(a, b, 1 - exp(-lambda * dt));
|
||||
}
|
||||
|
||||
public static double Damp(double a, double b, double lambda, double dt)
|
||||
{
|
||||
return lerp(a, b, 1 - exp(-lambda * dt));
|
||||
}
|
||||
|
||||
public static double2 Damp(double2 a, double2 b, double2 lambda, double2 dt)
|
||||
{
|
||||
return lerp(a, b, 1 - exp(-lambda * dt));
|
||||
}
|
||||
|
||||
public static double3 Damp(double3 a, double3 b, double3 lambda, double3 dt)
|
||||
{
|
||||
return lerp(a, b, 1 - exp(-lambda * dt));
|
||||
}
|
||||
|
||||
//first-order intercept using absolute target position
|
||||
public static float3 FirstOrderIntercept
|
||||
(
|
||||
float3 shooterPosition,
|
||||
float3 shooterVelocity,
|
||||
float shotSpeed,
|
||||
float3 targetPosition,
|
||||
float3 targetVelocity
|
||||
) {
|
||||
float3 targetRelativePosition = targetPosition - shooterPosition;
|
||||
float3 targetRelativeVelocity = targetVelocity - shooterVelocity;
|
||||
float t = FirstOrderInterceptTime
|
||||
(
|
||||
shotSpeed,
|
||||
targetRelativePosition,
|
||||
targetRelativeVelocity
|
||||
);
|
||||
return targetPosition + t*targetRelativeVelocity;
|
||||
}
|
||||
|
||||
//first-order intercept using relative target position
|
||||
public static float FirstOrderInterceptTime
|
||||
(
|
||||
float shotSpeed,
|
||||
float3 targetRelativePosition,
|
||||
float3 targetRelativeVelocity
|
||||
) {
|
||||
float velocitySquared = lengthsq(targetRelativeVelocity);
|
||||
if(velocitySquared < 0.001f)
|
||||
return 0f;
|
||||
|
||||
float a = velocitySquared - shotSpeed*shotSpeed;
|
||||
|
||||
//handle similar velocities
|
||||
if (abs(a) < 0.001f)
|
||||
{
|
||||
float t = -lengthsq(targetRelativePosition)/ (2f*dot(targetRelativeVelocity, targetRelativePosition));
|
||||
return max(t, 0f); //don't shoot back in time
|
||||
}
|
||||
|
||||
float b = 2f*dot(targetRelativeVelocity, targetRelativePosition);
|
||||
float c = lengthsq(targetRelativePosition);
|
||||
float determinant = b*b - 4f*a*c;
|
||||
|
||||
if (determinant > 0f) { //determinant > 0; two intercept paths (most common)
|
||||
float t1 = (-b + sqrt(determinant))/(2f*a),
|
||||
t2 = (-b - sqrt(determinant))/(2f*a);
|
||||
if (t1 > 0f) {
|
||||
if (t2 > 0f)
|
||||
return min(t1, t2); //both are positive
|
||||
else
|
||||
return t1; //only t1 is positive
|
||||
} else
|
||||
return max(t2, 0f); //don't shoot back in time
|
||||
} else if (determinant < 0f) //determinant < 0; no intercept path
|
||||
return 0f;
|
||||
else //determinant = 0; one intercept path, pretty much never happens
|
||||
return max(-b/(2f*a), 0f); //don't shoot back in time
|
||||
}
|
||||
|
||||
// http://csharphelper.com/blog/2016/09/find-the-shortest-distance-between-a-point-and-a-line-segment-in-c/
|
||||
// Calculate the distance between
|
||||
// point pt and the segment p1 --> p2.
|
||||
public static float FindDistanceToSegment(
|
||||
float2 pt, float2 p1, float2 p2, out float2 closest)
|
||||
{
|
||||
float dx = p2.x - p1.x;
|
||||
float dy = p2.y - p1.y;
|
||||
if (dx == 0 && dy == 0)
|
||||
{
|
||||
// It's a point not a line segment.
|
||||
closest = p1;
|
||||
dx = pt.x - p1.x;
|
||||
dy = pt.y - p1.y;
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
// Calculate the t that minimizes the distance.
|
||||
float t = ((pt.x - p1.x) * dx + (pt.y - p1.y) * dy) /
|
||||
(dx * dx + dy * dy);
|
||||
|
||||
// See if this represents one of the segment's
|
||||
// end points or a point in the middle.
|
||||
if (t < 0)
|
||||
{
|
||||
closest = float2(p1.x, p1.y);
|
||||
dx = pt.x - p1.x;
|
||||
dy = pt.y - p1.y;
|
||||
}
|
||||
else if (t > 1)
|
||||
{
|
||||
closest = float2(p2.x, p2.y);
|
||||
dx = pt.x - p2.x;
|
||||
dy = pt.y - p2.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
closest = float2(p1.x + t * dx, p1.y + t * dy);
|
||||
dx = pt.x - closest.x;
|
||||
dy = pt.y - closest.y;
|
||||
}
|
||||
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
//Returns a position between 4 float3s with Catmull-Rom spline algorithm
|
||||
//http://www.iquilezles.org/www/articles/minispline/minispline.htm
|
||||
public static float GetCatmullRomPosition(float p0, float p1, float p2, float p3, float t)
|
||||
{
|
||||
//The coefficients of the cubic polynomial (except the 0.5f * which I added later for performance)
|
||||
var a = 2f * p1;
|
||||
var b = p2 - p0;
|
||||
var c = 2f * p0 - 5f * p1 + 4f * p2 - p3;
|
||||
var d = -p0 + 3f * p1 - 3f * p2 + p3;
|
||||
|
||||
//The cubic polynomial: a + b * t + c * t^2 + d * t^3
|
||||
var pos = 0.5f * (a + (b * t) + (c * t * t) + (d * t * t * t));
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
public static float3 GetCatmullRomPosition(float3 p0, float3 p1, float3 p2, float3 p3, float t)
|
||||
{
|
||||
//The coefficients of the cubic polynomial (except the 0.5f * which I added later for performance)
|
||||
var a = 2f * p1;
|
||||
var b = p2 - p0;
|
||||
var c = 2f * p0 - 5f * p1 + 4f * p2 - p3;
|
||||
var d = -p0 + 3f * p1 - 3f * p2 + p3;
|
||||
|
||||
//The cubic polynomial: a + b * t + c * t^2 + d * t^3
|
||||
var pos = 0.5f * (a + (b * t) + (c * t * t) + (d * t * t * t));
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
// https://catlikecoding.com/unity/tutorials/curves-and-splines/
|
||||
public static float GetQuadraticSplinePosition(float p0, float p1, float p2, float t)
|
||||
{
|
||||
t = saturate(t);
|
||||
var oneMinusT = 1f - t;
|
||||
return
|
||||
oneMinusT * oneMinusT * p0 +
|
||||
2f * oneMinusT * t * p1 +
|
||||
t * t * p2;
|
||||
}
|
||||
|
||||
public static float3 GetQuadraticSplinePosition(float3 p0, float3 p1, float3 p2, float t)
|
||||
{
|
||||
t = saturate(t);
|
||||
var oneMinusT = 1f - t;
|
||||
return
|
||||
oneMinusT * oneMinusT * p0 +
|
||||
2f * oneMinusT * t * p1 +
|
||||
t * t * p2;
|
||||
}
|
||||
|
||||
public static float3 GetCubicSplinePosition (float p0, float p1, float p2, float p3, float t) {
|
||||
t = saturate(t);
|
||||
var oneMinusT = 1f - t;
|
||||
return
|
||||
oneMinusT * oneMinusT * oneMinusT * p0 +
|
||||
3f * oneMinusT * oneMinusT * t * p1 +
|
||||
3f * oneMinusT * t * t * p2 +
|
||||
t * t * t * p3;
|
||||
}
|
||||
|
||||
public static float3 GetCubicSplinePosition (float3 p0, float3 p1, float3 p2, float3 p3, float t) {
|
||||
t = saturate(t);
|
||||
var oneMinusT = 1f - t;
|
||||
return
|
||||
oneMinusT * oneMinusT * oneMinusT * p0 +
|
||||
3f * oneMinusT * oneMinusT * t * p1 +
|
||||
3f * oneMinusT * t * t * p2 +
|
||||
t * t * t * p3;
|
||||
}
|
||||
|
||||
public static float Smoothstep(float x)
|
||||
{
|
||||
x = saturate(x);
|
||||
return x * x * (3 - 2 * x);
|
||||
}
|
||||
|
||||
public static float Smootherstep(float x)
|
||||
{
|
||||
x = saturate(x);
|
||||
return x * x * x * (x * (x * 6 - 15) + 10);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 70c5f24f81c803248a4f682e6eb12ef2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -86,7 +86,7 @@ public class CombatState : BaseState
|
|||
var targetHullData = _agent.ItemManager.GetData(target.Hull) as HullData;
|
||||
var targetVelocity = float3(target.Velocity.x, 0, target.Velocity.y);
|
||||
var shipVelocity = float3(_agent.Ship.Velocity.x, 0, _agent.Ship.Velocity.y);
|
||||
var predictedPosition = AetheriaMath.FirstOrderIntercept(
|
||||
var predictedPosition = first_order_intercept(
|
||||
_agent.Ship.Position,
|
||||
float3.zero,
|
||||
testWeapon.Velocity,
|
||||
|
|
|
|||
|
|
@ -99,11 +99,11 @@ public class AetherDrive : Behavior
|
|||
var couplingEfficiency = Evaluate(_data.CouplingEfficiency);
|
||||
var efficiency = float3(saturate(1 - speed / max(rotorSpeed.xy, 1) * sign(_axis.xy)) * couplingEfficiency, 1);
|
||||
|
||||
Thrust = (Rpm - AetheriaMath.Decay(Rpm, _data.CouplingLambda, dt)) * _data.RotorMass * efficiency;
|
||||
Thrust = (Rpm - decay(Rpm, _data.CouplingLambda, dt)) * _data.RotorMass * efficiency;
|
||||
|
||||
var couplingLambda = _data.CouplingLambda * Item.Evaluate(_data.LambdaMultiplier) * max(abs(_axis), Evaluate(_data.PassiveCoupling));
|
||||
var previousRpm = Rpm;
|
||||
Rpm = AetheriaMath.Decay(Rpm, couplingLambda, dt);
|
||||
Rpm = decay(Rpm, couplingLambda, dt);
|
||||
var rpmLoss = previousRpm - Rpm;
|
||||
var force = rpmLoss * _data.RotorMass * efficiency;
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public class TurretController : Behavior, IInitializableBehavior
|
|||
{
|
||||
var targetHullData = Entity.ItemManager.GetData(Entity.Target.Value.Hull) as HullData;
|
||||
var targetVelocity = float3(Entity.Target.Value.Velocity.x, 0, Entity.Target.Value.Velocity.y);
|
||||
var predictedPosition = AetheriaMath.FirstOrderIntercept(
|
||||
var predictedPosition = first_order_intercept(
|
||||
Entity.Position, float3.zero, _shotSpeed,
|
||||
Entity.Target.Value.Position, targetVelocity
|
||||
);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public class VelocityConversion : Behavior
|
|||
|
||||
public override bool Execute(float dt)
|
||||
{
|
||||
Entity.Velocity = AetheriaMath.Damp(Entity.Velocity, Entity.Direction * length(Entity.Velocity), Evaluate(_data.Lambda), dt);
|
||||
Entity.Velocity = damp(Entity.Velocity, Entity.Direction * length(Entity.Velocity), Evaluate(_data.Lambda), dt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -855,7 +855,7 @@ public abstract class Entity
|
|||
|
||||
foreach (var v in VisibilitySources.Keys.ToArray())
|
||||
{
|
||||
VisibilitySources[v] = AetheriaMath.Decay(VisibilitySources[v], ItemManager.GameplaySettings.VisibilityDecay, delta);
|
||||
VisibilitySources[v] = decay(VisibilitySources[v], ItemManager.GameplaySettings.VisibilityDecay, delta);
|
||||
|
||||
if (VisibilitySources[v] < 0.1f) VisibilitySources.Remove(v);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@ public class Galaxy
|
|||
// foreach (var zone in Zones)
|
||||
// {
|
||||
// if(zone != link.Item1 && zone != link.Item2)
|
||||
// if (AetheriaMath.FindDistanceToSegment(zone.Position, link.Item1.Position, link.Item2.Position, out _) < minLineSeparation)
|
||||
// if (distance_to_segment(zone.Position, link.Item1.Position, link.Item2.Position, out _) < minLineSeparation)
|
||||
// links.Remove(link);
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ public class Ship : Entity
|
|||
|
||||
var velocityMagnitude = length(Velocity);
|
||||
if(velocityMagnitude > .01f)
|
||||
Velocity = normalize(Velocity) * AetheriaMath.Decay(velocityMagnitude, HullData.Drag, delta);
|
||||
Velocity = normalize(Velocity) * decay(velocityMagnitude, HullData.Drag, delta);
|
||||
|
||||
Position.xz += Velocity * delta;
|
||||
|
||||
|
|
@ -325,7 +325,7 @@ public class Ship : Entity
|
|||
{
|
||||
var exitLerp = (_wormholeAnimationProgress - ItemManager.GameplaySettings.WormholeExitCurveStart) /
|
||||
(1 - ItemManager.GameplaySettings.WormholeExitCurveStart);
|
||||
exitLerp = AetheriaMath.Smootherstep(exitLerp); // Square the interpolation variable to produce curve with zero slope at start
|
||||
exitLerp = smootherstep(exitLerp); // Square the interpolation variable to produce curve with zero slope at start
|
||||
Position.xz = _wormholePosition + normalize(_wormholeExitVelocity) * exitLerp * ItemManager.GameplaySettings.WormholeExitRadius;
|
||||
Rotation = quaternion.LookRotation(
|
||||
lerp(float3(0, 1, 0), forward, exitLerp),
|
||||
|
|
@ -351,7 +351,7 @@ public class Ship : Entity
|
|||
if (_wormholeAnimationProgress < 1 - ItemManager.GameplaySettings.WormholeExitCurveStart)
|
||||
{
|
||||
var enterLerp = _wormholeAnimationProgress / (1 - ItemManager.GameplaySettings.WormholeExitCurveStart);
|
||||
enterLerp = AetheriaMath.Smootherstep(enterLerp); // Square the interpolation variable to produce curve with zero slope at vertical
|
||||
enterLerp = smootherstep(enterLerp); // Square the interpolation variable to produce curve with zero slope at vertical
|
||||
Position.xz = lerp(_wormholeEntryPosition, _wormholePosition, enterLerp);
|
||||
Rotation = quaternion.LookRotation(
|
||||
lerp(forward, float3(0, -1, 0), enterLerp),
|
||||
|
|
|
|||
|
|
@ -81,21 +81,21 @@ public class FieldTester : MonoBehaviour
|
|||
var turn = _input.Player.Turn.ReadValue<float>();
|
||||
if (_directionalPush)
|
||||
{
|
||||
TestField.Push = AetheriaMath.Damp(TestField.Push, move, _throttleDecay, Time.deltaTime);
|
||||
TestField.FrontTwist = AetheriaMath.Damp(TestField.FrontTwist,
|
||||
TestField.Push = damp(TestField.Push, move, _throttleDecay, Time.deltaTime);
|
||||
TestField.FrontTwist = damp(TestField.FrontTwist,
|
||||
turn,
|
||||
_throttleDecay, Time.deltaTime);
|
||||
TestField.RearTwist = AetheriaMath.Damp(TestField.RearTwist,
|
||||
TestField.RearTwist = damp(TestField.RearTwist,
|
||||
turn,
|
||||
_throttleDecay, Time.deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
TestField.Push = AetheriaMath.Damp(TestField.Push, float2(0,move.y), _throttleDecay, Time.deltaTime);
|
||||
TestField.FrontTwist = AetheriaMath.Damp(TestField.FrontTwist,
|
||||
TestField.Push = damp(TestField.Push, float2(0,move.y), _throttleDecay, Time.deltaTime);
|
||||
TestField.FrontTwist = damp(TestField.FrontTwist,
|
||||
clamp(turn + move.x, -1, 1) * (1+min(move.y,0)),
|
||||
_throttleDecay, Time.deltaTime);
|
||||
TestField.RearTwist = AetheriaMath.Damp(TestField.RearTwist,
|
||||
TestField.RearTwist = damp(TestField.RearTwist,
|
||||
clamp(turn - move.x, -1, 1) * (1+min(-move.y,0)),
|
||||
_throttleDecay, Time.deltaTime);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue