Axiom
Axiom is combat / camera / HUD math: clamp, lerp, easing, noise, CFrame look-at. Every public function returns a concrete type (number, boolean, Vector3, CFrame, Color3, …) — never any, never nil on the math path.
Header: #include <clpp/libs/axiom.clh>. Runtime: CluauppLibs.Axiom. --!native. MathUtils is the same module (legacy name).
A .axiom file lists groups so generated out/ copies only those functions via Axiom.Select.
Use when: HUD bars, camera bob, projectile arcs, local juice (easing, bezier, value-noise).
Do not use when: economy rolls or loot — Keep owns persisted RNG. Networked motion is Flare + Echo, not a client lerp.
Example
Section titled “Example”#include <clpp/libs/axiom.clh>
void init() { double alpha = Axiom.Clamp(0.4, 0, 1); // 0.4 Vector3 p = Axiom.LerpVector3(Vector3::zero, Vector3::one, alpha); double ease = Axiom.Smoothstep(0, 1, alpha); // 0.352}Schema (HudMath.axiom)
Section titled “Schema (HudMath.axiom)”opt name = HudMathgroup Scalargroup Lerpgroup EasingThat emits Axiom.Select({ "Scalar", "Lerp", "Easing" }). Unknown group names error.
Groups: Scalar Lerp Vector CFrame Easing Bezier Geometry Trig Probability Noise Color.
Aliases always present on the full module: LerpVector = LerpVector3, Random = RandomRange, AngleDiff = DeltaAngle.
API — Scalar
Section titled “API — Scalar”Returns: double — value forced into [min, max].
When: HP, alpha, ammo, slider thumbs.
Formula: clamp(x, a, b) = min(max(x, a), b)
Axiom.Clamp(12, 0, 10); // 10Axiom.Clamp(-1, 0, 10); // 0Axiom.Clamp(3, 0, 10); // 3Returns: double — value remapped from [inMin, inMax] to [outMin, outMax]. If inMax == inMin, returns outMin.
When: health → bar fill, studs → UI pixels.
Formula: out = outMin + (outMax - outMin) * (value - inMin) / (inMax - inMin)
Axiom.Map(50, 0, 100, 0, 1); // 0.5Returns: double in [min, max). Range 0 returns min.
When: angles, cyclic indices, carousel slots.
Formula: wrap(x) = min + ((x - min) mod (max - min)) with negative mods corrected.
Axiom.Wrap(370, 0, 360); // 10Returns: 1, -1, or 0.
When: knockback direction, facing.
Formula: sign(x) = 1 if x>0, -1 if x<0, else 0
Axiom.Sign(-8); // -1Axiom.Sign(0); // 0Returns: double rounded half-up. Optional digits is decimal places.
When: display numbers before Mint, grid placement.
Formula: round(x, p) = floor(x * 10^p + 0.5) / 10^p
Axiom.Round(1.55); // 2Axiom.Round(1.234, 2); // 1.23Returns: double snapped to step. step == 0 returns value.
When: building grids, UI pixel snap.
Formula: snap(x, s) = floor(x/s + 0.5) * s
Axiom.Snap(13, 5); // 15PingPong
Section titled “PingPong”Returns: double bouncing between 0 and length.
When: idle bob, patrol that turns around without extra state.
Formula: triangle wave: length - | (t/length mod 2)*length - length |
Axiom.PingPong(0.25, 1); // 0.5Axiom.PingPong(1.25, 1); // 0.5Saturate
Section titled “Saturate”Returns: double in [0, 1].
When: alpha, blend weights.
Formula: saturate(x) = clamp(x, 0, 1)
Axiom.Saturate(1.4); // 1Returns: fractional part in [0, 1) for positives.
When: tiling noise, looping 0–1 timers.
Formula: fract(x) = x - floor(x)
Axiom.Fract(3.25); // 0.25InvLerp
Section titled “InvLerp”Returns: double — how far value sits between from and to. Equal endpoints return 0.
When: progress bars, inverse of Lerp.
Formula: invLerp(a, b, v) = (v - a) / (b - a)
Axiom.InvLerp(10, 20, 15); // 0.5Approach
Section titled “Approach”Returns: current moved toward target by at most maxDelta.
When: frame-rate independent chase without overshoot (camera follow, heat).
Formula: approach = current + clamp(target - current, -maxDelta, maxDelta)
Axiom.Approach(0, 10, 3); // 3Axiom.Approach(9, 10, 3); // 10IsFinite
Section titled “IsFinite”Returns: bool — not NaN and not ±inf.
When: guard before writing a number to Keep or a remote.
Axiom.IsFinite(1.0/0.0); // falseAbs / Min / Max / Pow / Sqrt / Cbrt / Hypot / Log / Exp
Section titled “Abs / Min / Max / Pow / Sqrt / Cbrt / Hypot / Log / Exp”Returns: double.
When: same cases as math.*, but typed and --!native.
Formulas: |x|, min, max, a^b, √x, ∛x (sign-preserving), √(a²+b²), ln(x), e^x.
Axiom.Hypot(3, 4); // 5Axiom.Cbrt(-8); // -2Axiom.Pow(2, 10); // 1024Smoothstep
Section titled “Smoothstep”Returns: double in [0, 1] with zero derivative at the edges.
When: camera ease-in-out, fog, HUD fades. Prefer this over raw lerp for motion that should not pop.
Formula: t = saturate((x-edge0)/(edge1-edge0)); t²(3-2t) Hermite.
Axiom.Smoothstep(0, 1, 0.5); // 0.5Axiom.Smoothstep(0, 1, 0.25); // 0.15625Smootherstep
Section titled “Smootherstep”Returns: double in [0, 1] — Ken Perlin’s 5th-order smoothstep (zero 1st and 2nd derivatives at edges).
When: longer camera blends where Smoothstep still feels linear in the middle.
Formula: t³(t(6t - 15) + 10) with the same saturated t.
Axiom.Smootherstep(0, 1, 0.5); // 0.5Gcd / Lcm
Section titled “Gcd / Lcm”Returns: double (Euclid). Lcm is 0 if gcd is 0.
When: grid snapping of two cell sizes, repeating VFX periods.
Formulas: Euclidean algorithm; lcm(a,b) = |a b| / gcd(a,b).
Axiom.Gcd(12, 8); // 4Axiom.Lcm(12, 8); // 24IsEven / IsOdd
Section titled “IsEven / IsOdd”Returns: bool (value % 2 == 0 / != 0).
When: checkerboard tiles, alternating lanes.
Axiom.IsEven(4); // trueAxiom.IsOdd(4); // falseFactorial
Section titled “Factorial”Returns: double — floor(n)! (1 for n < 2).
When: combo tables, small n only (overflows fast).
Formula: n! = 1·2·…·n
Axiom.Factorial(5); // 120Returns: double.
When: UI scale rungs without a lookup table (0–49 cycle).
Formula: Scale(value, n) = value * ((n mod 50) + 1) / 50
Axiom.Scale(100, 0); // 2 — (0 % 50)+1 = 1 → 100 * 1/50Axiom.Scale(100, 49); // 100 — (49 % 50)+1 = 50 → 100 * 50/50API — Lerp
Section titled “API — Lerp”Returns: double.
When: any blend that may overshoot (alpha not clamped).
Formula: lerp(a, b, t) = a + (b - a) t
Axiom.Lerp(0, 10, 0.25); // 2.5Axiom.Lerp(0, 10, 2); // 20LerpClamped
Section titled “LerpClamped”Returns: double — same with t saturated to [0, 1].
When: health bars, doors — never go past the end.
Axiom.LerpClamped(0, 10, 2); // 10LerpVector2 / LerpVector3 / LerpVector / LerpColor3 / LerpCFrame / LerpUDim2
Section titled “LerpVector2 / LerpVector3 / LerpVector / LerpColor3 / LerpCFrame / LerpUDim2”Returns: the matching Roblox type (LerpVector is LerpVector3).
When: positions, colors, poses, GUI boxes. Use the typed name — do not jam everything through Lerp.
Formula: component (or CFrame) lerp: (1-t) a + t b.
Axiom.LerpVector3(Vector3::zero, Vector3::one, 0.5); // (0.5, 0.5, 0.5)LerpAngle
Section titled “LerpAngle”Returns: double radians, shortest-arc.
When: yaw, turret turn, spin UI. Never lerp degrees with plain Lerp across 359→1.
Formula: from + DeltaAngle(from, to) * alpha
Axiom.LerpAngle(0, 3.14159, 0.5);Inverse
Section titled “Inverse”Returns: double — alias of InvLerp.
When: same as InvLerp; older MathUtils name.
API — Vector / CFrame
Section titled “API — Vector / CFrame”Project
Section titled “Project”Returns: Vector3 — a onto b. Degenerate b → Vector3.zero.
When: move along a rail, slide on a wall tangent.
Formula: proj_b a = â_b (a · â_b)
Axiom.Project(Vector3::xAxis * 2, Vector3::xAxis); // (2, 0, 0)Reject
Section titled “Reject”Returns: Vector3 — a - Project(a, b) (component orthogonal to b).
When: keep motion after removing the floor normal.
Reflect
Section titled “Reflect”Returns: Vector3.
When: bullets, dashes off walls. normal should be unit.
Formula: R = I - 2 (I · N) N
Axiom.Reflect(Vector3::zAxis, Vector3::yAxis);Returns: double radians between two vectors.
When: cone checks, facing.
Formula: acos(clamp(â · ˆb, -1, 1))
Distance / Distance2
Section titled “Distance / Distance2”Returns: double (Vector3 / Vector2 magnitude of b - a).
When: aggro range, pickup radius. Prefer this over subtracting then .Magnitude in HUD code you want --!native.
Axiom.Distance(Vector3::zero, Vector3::one); // sqrt(3)Orthonormal
Section titled “Orthonormal”Returns: CFrame at origin looking along forward, up default Y.
When: build a basis for a beam or camera without shearing.
Returns: Vector3 spherical lerp (direction + blended magnitude). Near-parallel falls back to linear.
When: rotating a facing vector. For poses use SlerpCFrame.
Formula: sin/cos of θ t on the great circle; θ = acos(â · ˆb).
SlerpCFrame
Section titled “SlerpCFrame”Returns: CFrame — Roblox a:Lerp(b, t) (quaternion lerp).
When: camera cut blends, door hinges.
LookAt
Section titled “LookAt”Returns: CFrame.lookAt(from, look).
When: NPC head, billboard, turret. Pair with Flat if you must stay Y-up on slopes.
Returns: CFrame at the same position, look flattened to XZ (Y-up). Degenerate look → -Z.
When: character facing on hills so they do not tilt into the ground.
API — Easing
Section titled “API — Easing”All easings take t in any range, clamp it to [0, 1], and return double in [0, 1] (Back/Elastic/Bounce may overshoot inside that after the clamp of input). Penner / easings.net formulas.
When: Tween-like HUD without TweenService. In* starts slow, Out* ends slow, InOut* both. Linear is clamp(t,0,1).
| Call | Formula (after t = clamp(t,0,1)) |
|---|---|
InSine | 1 - cos(t π / 2) |
OutSine | sin(t π / 2) |
InOutSine | -(cos(π t) - 1) / 2 |
InQuad | t² |
OutQuad | 1 - (1-t)² |
InCubic | t³ |
OutCubic | 1 - (1-t)³ |
InQuart | t⁴ |
InQuint | t⁵ |
InExpo | 0 if t=0 else 2^(10t-10) |
OutExpo | 1 if t=1 else 1 - 2^(-10t) |
InCirc | 1 - √(1-t²) |
OutCirc | √(1-(t-1)²) |
InBack | 2.70158 t³ - 1.70158 t² |
InElastic | -2^(10t-10) sin((10t-10.75) 2π/3) (0/1 at ends) |
OutBounce | piecewise 7.5625 t² (d=2.75) |
InBounce | 1 - OutBounce(1-t) |
Linear | t |
InOut* splits at 0.5 and scales the In/Out piece. Out* of power easings is 1 - (1-t)^n.
Axiom.OutQuad(0.5); // 0.75Axiom.InOutSine(0.5); // 0.5Axiom.Linear(2); // 1API — Bezier / motion juice
Section titled “API — Bezier / motion juice”CubicBezier
Section titled “CubicBezier”Returns: Vector3 on the cubic Bézier.
When: missile arcs, camera tracks with two handles.
Formula: (1-t)³ P0 + 3(1-t)² t P1 + 3(1-t) t² P2 + t³ P3
Axiom.CubicBezier(0, p0, p1, p2, p3); // p0Axiom.CubicBezier(1, p0, p1, p2, p3); // p3QuadraticBezier
Section titled “QuadraticBezier”Returns: Vector3.
When: one-handle jumps.
Formula: (1-t)² P0 + 2(1-t)t P1 + t² P2
Hover / Float
Section titled “Hover / Float”Returns: CFrame.lookAt(anchor + (0, bob, 0), look).
When: pickup gems, shop items. Hover uses sin(elapsed * 1.6) * 0.22; Float uses sin(elapsed * 1.1) * 0.18.
Formula: bob = sin(ω t) · A
FloatSpin
Section titled “FloatSpin”Returns: CFrame — Float bob plus yaw 50° * elapsed.
When: coins in the air.
API — Geometry
Section titled “API — Geometry”AabbContains
Section titled “AabbContains”Returns: bool — point inside inclusive AABB [min, max].
When: zone checks, hitboxes that are boxes.
Axiom.AabbContains(Vector3::zero, Vector3::one * -1, Vector3::one); // trueSphereContains
Section titled “SphereContains”Returns: bool — \|p - c\| ≤ r.
When: explosion radius, pickup.
RayPlane
Section titled “RayPlane”Returns: Vector3 hit point. Parallel or behind the ray → Vector3.zero (never nil).
When: mouse-to-ground, water plane. Test Magnitude or a sentinel if zero origin is a valid hit.
Formula: t = ((point - origin) · N) / (dir · N); hit = origin + dir t if t ≥ 0.
Barycentric
Section titled “Barycentric”Returns: Vector3(u, v, w) with u + v + w = 1 (u at a, v at b, w at c). Degenerate triangle → (1, 0, 0).
When: triangle hit interpolation (color, UV, height). Point is inside if all of u,v,w ≥ 0.
Formula: v = (d11 d20 - d01 d21) / denom, w = (d00 d21 - d01 d20) / denom, u = 1 - v - w.
ClosestPointOnSegment
Section titled “ClosestPointOnSegment”Returns: Vector3 on segment a–b closest to p.
When: rope IK, rail grind, NPC stay-on-path.
Formula: t = clamp((p-a)·(b-a) / \|b-a\|², 0, 1); a + (b-a) t
API — Trig
Section titled “API — Trig”Deg / Rad
Section titled “Deg / Rad”Returns: double. deg = rad * 180/π, rad = deg * π/180.
When: converting Tween/UI degrees to CFrame.Angles.
Axiom.Deg(Axiom.Rad(90)); // 90DeltaAngle / AngleDiff
Section titled “DeltaAngle / AngleDiff”Returns: double shortest signed delta in radians, range (-π, π].
When: turn-to-face. AngleDiff is the same function.
Formula: ((to - from + π) mod 2π) - π
DeltaAngleDegrees
Section titled “DeltaAngleDegrees”Returns: signed degrees in (-180, 180].
When: the same, if your data is already degrees.
NormalizeAngle
Section titled “NormalizeAngle”Returns: radians wrapped to [-π, π).
When: storing facing so it does not grow forever.
Sin / Cos / Tan / Asin / Acos / Atan2
Section titled “Sin / Cos / Tan / Asin / Acos / Atan2”Returns: double — math.* wrappers, radians in / out.
When: call Axiom so .axiom tree-shake still includes trig with Scalar/Easing.
Axiom.Atan2(1, 0); // π/2API — Probability / Noise / Color
Section titled “API — Probability / Noise / Color”RandomRange / Random
Section titled “RandomRange / Random”Returns: double in [min, max) (Luau math.random).
When: VFX jitter, camera shake. Not loot or coins.
Formula: min + (max-min) * U(0,1)
Weighted
Section titled “Weighted”Returns: int 1-based index. Empty list → 0. Non-positive total → 1.
When: weighted emotes, local juice tables — still not economy.
Axiom.Weighted({ 1, 3, 0 }); // 1 or 2, never 3Gaussian
Section titled “Gaussian”Returns: double ~ N(mean or 0, std or 1). Box–Muller.
When: recoil spread, damage juice (display). Not DataStore rolls.
Formula: √(-2 ln U) cos(2π V) * std + mean
Average / Sum
Section titled “Average / Sum”Returns: double. Empty average is 0, empty sum is 0.
When: DPS meters, ping smoothing.
Axiom.Average({ 2, 4, 6 }); // 4Axiom.Sum({ 2, 4, 6 }); // 12HashU32
Section titled “HashU32”Returns: double in 0 .. 2³²-1 (integer-valued).
When: stable id from a number (chunk keys). Deterministic.
Value1 / Value2 / Value3
Section titled “Value1 / Value2 / Value3”Returns: double in [0, 1) from HashU32 / 2³².
When: cheap value-noise for grass sway, not cryptography.
Axiom.Value1(10); // same every sessionAxiom.Value2(chunkX, chunkZ);FromHSV
Section titled “FromHSV”Returns: Color3 (h,s,v in [0,1]).
When: rainbow strokes, team hues.
Contrast
Section titled “Contrast”Returns: Color3 pushed away from 0.5 gray, then clamped.
When: hit flash, accessibility contrast kick.
Formula: clamp((c - 0.5) * amount + 0.5, 0, 1) per channel.
LerpHSV
Section titled “LerpHSV”Returns: Color3 — hue takes the short arc, S/V lerp linearly.
When: health green→red without crossing the rainbow.
MathUtils
Section titled “MathUtils”Same runtime as Axiom. Header aliases: Lerp, Map, Clamp, Round, Snap, Sign, Wrap, Saturate, Inverse, AngleDiff, LerpAngle, Random, Weighted, LerpVector. Prefer Axiom. in new code.