8#include <simplesquirrel/simplesquirrel.hpp>
11#include <glm/gtc/matrix_transform.hpp>
12#include <glm/gtc/noise.hpp>
21#define M_PI 3.14159265358979323846
27float clamp01(
float t) {
return std::clamp(t, 0.f, 1.f); }
29float noiseToUnit(
float n) {
31 return clamp01(
n * 0.5f + 0.5f);
34float hash11(
float p) {
35 p =
p - std::floor(
p);
37 p =
p - std::floor(
p);
40 return p - std::floor(
p);
43float hash21(
float x,
float y) {
44 glm::vec3 p3 = glm::fract(glm::vec3(
x,
y,
x) * 0.1031f);
45 p3 += glm::dot(p3, glm::vec3(p3.y + 33.33f, p3.z + 33.33f, p3.x + 33.33f));
46 return glm::fract((p3.x + p3.y) * p3.z);
49float hash31(
float x,
float y,
float z) {
50 glm::vec3 p3 = glm::fract(glm::vec3(
x,
y,
z) * 0.1031f);
51 p3 += glm::dot(p3, glm::vec3(p3.y + 33.33f, p3.z + 33.33f, p3.x + 33.33f));
52 return glm::fract((p3.x + p3.y) * p3.z);
55glm::vec2 voronoiPoint(
int ix,
int iy) {
56 float hx = hash21(
float(ix),
float(iy));
57 float hy = hash21(
float(ix) + 19.19f,
float(iy) + 47.47f);
58 return glm::vec2(
float(ix) + hx,
float(iy) + hy);
61void voronoiF1F2(
float x,
float y,
float &f1,
float &f2) {
62 int ix = int(std::floor(
x));
63 int iy = int(std::floor(
y));
66 for (
int j = -1; j <= 1; ++j) {
67 for (
int i = -1; i <= 1; ++i) {
68 glm::vec2
p = voronoiPoint(ix + i, iy + j);
69 float d = glm::length(glm::vec2(
x,
y) -
p);
93 m->translate(
x,
y,
z);
104 auto *
m =
new Mat4();
110 if (lo > hi) std::swap(lo, hi);
111 return std::clamp(
x, lo, hi);
117 if (edge0 == edge1)
return x < edge0 ? 0.f : 1.f;
118 float t = clamp01((
x - edge0) / (edge1 - edge0));
119 return t * t * (3.f - 2.f * t);
122float Math::remap(
float x,
float inMin,
float inMax,
float outMin,
float outMax)
const {
123 if (inMin == inMax)
return outMin;
124 float t = (
x - inMin) / (inMax - inMin);
125 return outMin + (outMax - outMin) * t;
132 if (
x > 0.f)
return 1.f;
133 if (
x < 0.f)
return -1.f;
140 float d = target - current;
141 if (std::fabs(
d) <= maxDelta)
return target;
142 return current +
sign(
d) * maxDelta;
146 if (lo == hi)
return lo;
147 if (lo > hi) std::swap(lo, hi);
148 float range = hi - lo;
149 float t = std::fmod(
x - lo, range);
150 if (t < 0.f) t += range;
155 if (length <= 0.f)
return 0.f;
156 t =
wrap(t, 0.f, length * 2.f);
157 return length - std::fabs(t - length);
161 if (
a ==
b)
return 0.f;
162 return (
x -
a) / (
b -
a);
166 if (edge0 == edge1)
return x < edge0 ? 0.f : 1.f;
167 float t = clamp01((
x - edge0) / (edge1 - edge0));
168 return t * t * t * (t * (t * 6.f - 15.f) + 10.f);
173 if (
b <= 0.f)
return 0.f;
174 if (
b >= 1.f)
return 1.f;
175 return t / ((1.f /
b - 2.f) * (1.f - t) + 1.f);
180 if (t < 0.5f)
return bias(t * 2.f, g) * 0.5f;
181 return bias(t * 2.f - 1.f, 1.f - g) * 0.5f + 0.5f;
186 if (
kind ==
"linear" ||
kind.empty())
return t;
187 if (
kind ==
"inQuad")
return t * t;
188 if (
kind ==
"outQuad")
return 1.f - (1.f - t) * (1.f - t);
189 if (
kind ==
"inOutQuad")
190 return t < 0.5f ? 2.f * t * t : 1.f - std::pow(-2.f * t + 2.f, 2.f) * 0.5f;
191 if (
kind ==
"inCubic")
return t * t * t;
192 if (
kind ==
"outCubic")
return 1.f - std::pow(1.f - t, 3.f);
193 if (
kind ==
"inOutCubic")
194 return t < 0.5f ? 4.f * t * t * t : 1.f - std::pow(-2.f * t + 2.f, 3.f) * 0.5f;
195 if (
kind ==
"inSine")
return 1.f - std::cos(t *
float(
M_PI) * 0.5f);
196 if (
kind ==
"outSine")
return std::sin(t *
float(
M_PI) * 0.5f);
197 if (
kind ==
"inOutSine")
return -(std::cos(
float(
M_PI) * t) - 1.f) * 0.5f;
198 if (
kind ==
"inExpo")
return t <= 0.f ? 0.f : std::pow(2.f, 10.f * t - 10.f);
199 if (
kind ==
"outExpo")
return t >= 1.f ? 1.f : 1.f - std::pow(2.f, -10.f * t);
200 if (
kind ==
"inOutExpo") {
201 if (t <= 0.f)
return 0.f;
202 if (t >= 1.f)
return 1.f;
203 return t < 0.5f ? std::pow(2.f, 20.f * t - 10.f) * 0.5f
204 : (2.f - std::pow(2.f, -20.f * t + 10.f)) * 0.5f;
206 throw Exception(
"Math.ease: unknown kind '%s'",
kind.c_str());
209float Math::step(
float edge,
float x)
const {
return x < edge ? 0.f : 1.f; }
212 if (stepSize == 0.f)
return x;
213 return std::floor(
x / stepSize) * stepSize;
217 if (grid == 0.f)
return x;
218 return std::round(
x / grid) * grid;
223 return std::sqrt(
x *
x +
y *
y +
z *
z);
227 return length2(x2 - x1, y2 - y1);
230float Math::distance3(
float x1,
float y1,
float z1,
float x2,
float y2,
float z2)
const {
231 return length3(x2 - x1, y2 - y1, z2 - z1);
234float Math::dot2(
float x1,
float y1,
float x2,
float y2)
const {
return x1 * x2 + y1 * y2; }
235float Math::dot3(
float x1,
float y1,
float z1,
float x2,
float y2,
float z2)
const {
236 return x1 * x2 + y1 * y2 + z1 * z2;
239float Math::cross2(
float x1,
float y1,
float x2,
float y2)
const {
return x1 * y2 - y1 * x2; }
243 return std::atan2(y2, x2) - std::atan2(y1, x1);
247 float twoPi = float(
M_PI) * 2.f;
248 float diff = std::fmod(
b -
a +
float(
M_PI), twoPi);
249 if (diff < 0.f) diff += twoPi;
256 return len > 0.f ?
x / len : 0.f;
260 return len > 0.f ?
y / len : 0.f;
264 return len > 0.f ?
x / len : 0.f;
268 return len > 0.f ?
y / len : 0.f;
272 return len > 0.f ?
z / len : 0.f;
276 float c = std::cos(radians),
s = std::sin(radians);
277 return x *
c -
y *
s;
280 float c = std::cos(radians),
s = std::sin(radians);
281 return x *
s +
y *
c;
284float Math::polarX(
float radius,
float radians)
const {
return radius * std::cos(radians); }
285float Math::polarY(
float radius,
float radians)
const {
return radius * std::sin(radians); }
290 if (radius < 0.f)
return false;
295 return px >= rx && py >= ry &&
px <= rx + rw && py <= ry + rh;
299 if (r1 < 0.f || r2 < 0.f)
return false;
301 float dx = x2 - x1, dy = y2 - y1;
302 return dx * dx + dy * dy <= rr * rr;
307 return x1 <= x2 + w2 && x1 + w1 >= x2 && y1 <= y2 + h2 && y1 + h1 >= y2;
312 if (radius < 0.f)
return false;
313 float nearestX = std::clamp(
cx, rx, rx + rw);
314 float nearestY = std::clamp(
cy, ry, ry + rh);
315 float dx =
cx - nearestX, dy =
cy - nearestY;
316 return dx * dx + dy * dy <= radius * radius;
321 auto orient = [](
float px,
float py,
float qx,
float qy,
float rx,
float ry) {
322 return (qy - py) * (rx - qx) - (qx -
px) * (ry - qy);
324 auto onSeg = [](
float px,
float py,
float qx,
float qy,
float rx,
float ry) {
325 return std::min(
px, rx) <= qx && qx <= std::max(
px, rx) && std::min(py, ry) <= qy &&
326 qy <= std::max(py, ry);
328 float o1 = orient(ax, ay, bx, by,
cx,
cy);
329 float o2 = orient(ax, ay, bx, by, dx, dy);
330 float o3 = orient(
cx,
cy, dx, dy, ax, ay);
331 float o4 = orient(
cx,
cy, dx, dy, bx, by);
332 if (o1 * o2 < 0.f && o3 * o4 < 0.f)
return true;
333 constexpr float eps = 1e-6f;
334 if (std::fabs(o1) <= eps && onSeg(ax, ay,
cx,
cy, bx, by))
return true;
335 if (std::fabs(o2) <= eps && onSeg(ax, ay, dx, dy, bx, by))
return true;
336 if (std::fabs(o3) <= eps && onSeg(
cx,
cy, ax, ay, dx, dy))
return true;
337 if (std::fabs(o4) <= eps && onSeg(
cx,
cy, bx, by, dx, dy))
return true;
342 float radius)
const {
343 if (radius < 0.f)
return -1.f;
344 float fx = ox -
cx, fy = oy -
cy;
345 float a = dx * dx + dy * dy;
346 if (
a <= 1e-12f)
return -1.f;
347 float b = 2.f * (fx * dx + fy * dy);
348 float c = fx * fx + fy * fy - radius * radius;
349 float disc =
b *
b - 4.f *
a *
c;
350 if (disc < 0.f)
return -1.f;
351 float s = std::sqrt(disc);
352 float t0 = (-
b -
s) / (2.f *
a);
353 float t1 = (-
b +
s) / (2.f *
a);
354 if (t0 >= 0.f)
return t0;
355 if (t1 >= 0.f)
return t1;
361 constexpr float inf = 1e30f;
364 auto slab = [&](
float o,
float d,
float minV,
float maxV) ->
bool {
365 if (std::fabs(
d) < 1e-12f) {
366 return o >= minV && o <= maxV;
369 float t1 = (minV - o) * inv;
370 float t2 = (maxV - o) * inv;
371 if (t1 > t2) std::swap(t1, t2);
372 tMin = std::max(tMin, t1);
373 tMax = std::min(tMax, t2);
376 if (!slab(ox, dx, rx, rx + rw))
return -1.f;
377 if (!slab(oy, dy, ry, ry + rh))
return -1.f;
378 if (tMax < 0.f)
return -1.f;
379 return tMin >= 0.f ? tMin : 0.f;
383float closestSegmentT(
float px,
float py,
float ax,
float ay,
float bx,
float by) {
384 float abx = bx - ax, aby = by - ay;
385 float denom = abx * abx + aby * aby;
386 if (denom <= 1e-12f)
return 0.f;
387 float t = ((
px - ax) * abx + (py - ay) * aby) / denom;
388 return std::clamp(t, 0.f, 1.f);
390float closestSegmentT3(
float px,
float py,
float pz,
float ax,
float ay,
float az,
float bx,
391 float by,
float bz) {
392 float abx = bx - ax, aby = by - ay, abz = bz - az;
393 float denom = abx * abx + aby * aby + abz * abz;
394 if (denom <= 1e-12f)
return 0.f;
395 float t = ((
px - ax) * abx + (py - ay) * aby + (pz - az) * abz) / denom;
396 return std::clamp(t, 0.f, 1.f);
402 float t = closestSegmentT(
px, py, ax, ay, bx, by);
403 return ax + (bx - ax) * t;
407 float t = closestSegmentT(
px, py, ax, ay, bx, by);
408 return ay + (by - ay) * t;
412 float radius)
const {
413 if (radius < 0.f)
return false;
418 float maxY,
float maxZ)
const {
419 return px >= minX && px <= maxX && py >= minY && py <= maxY && pz >= minZ && pz <= maxZ;
424 if (r1 < 0.f || r2 < 0.f)
return false;
426 float dx = x2 - x1, dy = y2 - y1, dz = z2 - z1;
427 return dx * dx + dy * dy + dz * dz <= rr * rr;
431 float maxAz,
float minBx,
float minBy,
float minBz,
float maxBx,
432 float maxBy,
float maxBz)
const {
433 return minAx <= maxBx && maxAx >= minBx && minAy <= maxBy && maxAy >= minBy &&
434 minAz <= maxBz && maxAz >= minBz;
438 float cy,
float cz,
float radius)
const {
439 if (radius < 0.f)
return -1.f;
440 float fx = ox -
cx, fy = oy -
cy, fz = oz - cz;
441 float a = dx * dx + dy * dy + dz * dz;
442 if (
a <= 1e-12f)
return -1.f;
443 float b = 2.f * (fx * dx + fy * dy + fz * dz);
444 float c = fx * fx + fy * fy + fz * fz - radius * radius;
445 float disc =
b *
b - 4.f *
a *
c;
446 if (disc < 0.f)
return -1.f;
447 float s = std::sqrt(disc);
448 float t0 = (-
b -
s) / (2.f *
a);
449 float t1 = (-
b +
s) / (2.f *
a);
450 if (t0 >= 0.f)
return t0;
451 if (t1 >= 0.f)
return t1;
455float Math::raycastBox(
float ox,
float oy,
float oz,
float dx,
float dy,
float dz,
float minX,
456 float minY,
float minZ,
float maxX,
float maxY,
float maxZ)
const {
457 constexpr float inf = 1e30f;
460 auto slab = [&](
float o,
float d,
float minV,
float maxV) ->
bool {
461 if (std::fabs(
d) < 1e-12f) {
462 return o >= minV && o <= maxV;
465 float t1 = (minV - o) * inv;
466 float t2 = (maxV - o) * inv;
467 if (t1 > t2) std::swap(t1, t2);
468 tMin = std::max(tMin, t1);
469 tMax = std::min(tMax, t2);
472 if (!slab(ox, dx, minX, maxX))
return -1.f;
473 if (!slab(oy, dy, minY, maxY))
return -1.f;
474 if (!slab(oz, dz, minZ, maxZ))
return -1.f;
475 if (tMax < 0.f)
return -1.f;
476 return tMin >= 0.f ? tMin : 0.f;
480 float py,
float pz,
float nx,
float ny,
float nz)
const {
481 float denom = nx * dx + ny * dy + nz * dz;
482 if (std::fabs(denom) < 1e-12f)
return -1.f;
483 float t = (nx * (
px - ox) + ny * (py - oy) + nz * (pz - oz)) / denom;
484 return t >= 0.f ? t : -1.f;
488 float bx,
float by,
float bz)
const {
489 float t = closestSegmentT3(
px, py, pz, ax, ay, az, bx, by, bz);
490 return ax + (bx - ax) * t;
493 float bx,
float by,
float bz)
const {
494 float t = closestSegmentT3(
px, py, pz, ax, ay, az, bx, by, bz);
495 return ay + (by - ay) * t;
498 float bx,
float by,
float bz)
const {
499 float t = closestSegmentT3(
px, py, pz, ax, ay, az, bx, by, bz);
500 return az + (bz - az) * t;
504 float a =
lerp(v00, v10,
u);
505 float b =
lerp(v01, v11,
u);
515 auto us = std::chrono::duration_cast<std::chrono::microseconds>(
516 std::chrono::steady_clock::now().time_since_epoch())
524 std::uniform_real_distribution<float> dist(0.f, 1.f);
529 if (min > max) std::swap(min, max);
530 std::uniform_real_distribution<float> dist(min, max);
535 if (min > maxInclusive) std::swap(min, maxInclusive);
536 std::uniform_int_distribution<int> dist(min, maxInclusive);
541 std::normal_distribution<float> dist(mean, stddev);
549float Math::noise1(
float x)
const {
return noiseToUnit(glm::simplex(glm::vec2(
x, 0.f))); }
550float Math::noise2(
float x,
float y)
const {
return noiseToUnit(glm::simplex(glm::vec2(
x,
y))); }
552 return noiseToUnit(glm::simplex(glm::vec3(
x,
y,
z)));
555float Math::perlin2(
float x,
float y)
const {
return noiseToUnit(glm::perlin(glm::vec2(
x,
y))); }
557 return noiseToUnit(glm::perlin(glm::vec3(
x,
y,
z)));
560float Math::fbm2(
float x,
float y,
int octaves,
float lacunarity,
float gain)
const {
561 if (octaves < 1) octaves = 1;
562 if (octaves > 16) octaves = 16;
563 float sum = 0.f, amp = 1.f, freq = 1.f, norm = 0.f;
564 for (
int i = 0; i < octaves; ++i) {
565 sum +=
noise2(
x * freq,
y * freq) * amp;
570 return norm > 0.f ? sum / norm : 0.f;
573float Math::fbm3(
float x,
float y,
float z,
int octaves,
float lacunarity,
float gain)
const {
574 if (octaves < 1) octaves = 1;
575 if (octaves > 16) octaves = 16;
576 float sum = 0.f, amp = 1.f, freq = 1.f, norm = 0.f;
577 for (
int i = 0; i < octaves; ++i) {
578 sum +=
noise3(
x * freq,
y * freq,
z * freq) * amp;
583 return norm > 0.f ? sum / norm : 0.f;
586float Math::ridged2(
float x,
float y,
int octaves,
float lacunarity,
float gain)
const {
587 if (octaves < 1) octaves = 1;
588 if (octaves > 16) octaves = 16;
589 float sum = 0.f, amp = 0.5f, freq = 1.f, prev = 1.f;
590 for (
int i = 0; i < octaves; ++i) {
592 n = 1.f - std::fabs(
n * 2.f - 1.f);
594 sum +=
n * amp * prev;
602float Math::ridged3(
float x,
float y,
float z,
int octaves,
float lacunarity,
float gain)
const {
603 if (octaves < 1) octaves = 1;
604 if (octaves > 16) octaves = 16;
605 float sum = 0.f, amp = 0.5f, freq = 1.f, prev = 1.f;
606 for (
int i = 0; i < octaves; ++i) {
607 float n =
noise3(
x * freq,
y * freq,
z * freq);
608 n = 1.f - std::fabs(
n * 2.f - 1.f);
610 sum +=
n * amp * prev;
619 if (octaves < 1) octaves = 1;
620 if (octaves > 16) octaves = 16;
621 float sum = 0.f, amp = 1.f, freq = 1.f, norm = 0.f;
622 for (
int i = 0; i < octaves; ++i) {
623 sum += std::fabs(
noise2(
x * freq,
y * freq) * 2.f - 1.f) * amp;
628 return norm > 0.f ? clamp01(sum / norm) : 0.f;
633 voronoiF1F2(
x,
y, f1, f2);
639 voronoiF1F2(
x,
y, f1, f2);
645 float wy =
noise2(
x + 5.2f,
y + 1.3f) - 0.5f;
646 return noise2(
x + wx * warpAmp,
y + wy * warpAmp);
652 return u *
u * p0 + 2.f *
u * t * p1 + t * t * p2;
660 return uu *
u * p0 + 3.f * uu * t * p1 + 3.f *
u * tt * p2 + tt * t * p3;
674 float ,
float x3,
float )
const {
679 float y2,
float ,
float y3)
const {
683void Math::expose(ssq::Table &table) {
684 auto cls = table.addClass(
name, Math::create,
false);
687 auto v2 = table.addClass<
Vec2>(
688 "Vec2", std::function<Vec2 *()>([]() ->
Vec2 * {
return nullptr; }),
true);
708 auto v3 = table.addClass<Vec3>(
709 "Vec3", std::function<Vec3 *()>([]() -> Vec3 * {
return nullptr; }),
true);
730 auto m4 = table.addClass<Mat4>(
731 "Mat4", std::function<Mat4 *()>([]() -> Mat4 * {
return nullptr; }),
true);
747void Math::expose(ssq::Class &
cls) {
#define Module_IMPL(ModuleName, newExpr)
virtual std::string getName() const =0
Column-major 4x4 matrix wrapping glm::mat4.
Vec3 * transformVec3(const Vec3 *v) const
Vec2 * transformPoint2(const Vec2 *v) const
void translate(float x, float y, float z)
float get(int index) const
Column-major element 0..15.
void scale(float sx, float sy, float sz)
void multiply(const Mat4 *other)
void rotateX(float radians)
void rotateZ(float radians)
Mat4 * multiplied(const Mat4 *other) const
void set(int index, float value)
void rotateY(float radians)
Math module — glm-backed vectors/matrices, noise, bezier, random. Script: math <- eve....
bool pointInSphere(float px, float py, float pz, float cx, float cy, float cz, float radius) const
float bezierQuadratic(float t, float p0, float p1, float p2) const
bool spheresOverlap(float x1, float y1, float z1, float r1, float x2, float y2, float z2, float r2) const
Mat4 * newMat4Scale(float sx, float sy, float sz)
float warpNoise2(float x, float y, float warpAmp=1.f) const
Domain warp: sample noise at (x,y) + warpAmp * (noise-0.5). Useful for organic terrain / caves.
float normalize3X(float x, float y, float z) const
bool boxesOverlap(float minAx, float minAy, float minAz, float maxAx, float maxAy, float maxAz, float minBx, float minBy, float minBz, float maxBx, float maxBy, float maxBz) const
float normalize3Z(float x, float y, float z) const
float perlin3(float x, float y, float z) const
float voronoi2(float x, float y) const
Worley / Voronoi F1 distance in [0, ~1.5] (cell size 1). voronoiEdge2 = F2 - F1 (cell borders).
float approach(float current, float target, float maxDelta) const
float turbulence2(float x, float y, int octaves=4, float lacunarity=2.f, float gain=0.5f) const
float closestPointOnSegment2Y(float px, float py, float ax, float ay, float bx, float by) const
Mat4 * newMat4Translation(float x, float y, float z)
float normalize2Y(float x, float y) const
float length3(float x, float y, float z) const
float ease(float t, const std::string &kind) const
Easing on [0,1]. kind: "linear"|"inQuad"|"outQuad"|"inOutQuad"|"inCubic"|"outCubic"|"inOutCubic"| "in...
float step(float edge, float x) const
float bezierQuadratic2X(float t, float x0, float y0, float x1, float y1, float x2, float y2) const
float angle2(float x, float y) const
float raycastPlane(float ox, float oy, float oz, float dx, float dy, float dz, float px, float py, float pz, float nx, float ny, float nz) const
Ray vs infinite plane through (px,py,pz) with normal (nx,ny,nz). Returns parametric t,...
float raycastBox(float ox, float oy, float oz, float dx, float dy, float dz, float minX, float minY, float minZ, float maxX, float maxY, float maxZ) const
float angleBetween2(float x1, float y1, float x2, float y2) const
float cartesianAngle(float x, float y) const
float normalize3Y(float x, float y, float z) const
float closestPointOnSegment2X(float px, float py, float ax, float ay, float bx, float by) const
bool circleRectOverlap(float cx, float cy, float radius, float rx, float ry, float rw, float rh) const
float smootherstep(float edge0, float edge1, float x) const
float closestPointOnSegment3Y(float px, float py, float pz, float ax, float ay, float az, float bx, float by, float bz) const
float fract(float x) const
float noise1(float x) const
float smoothstep(float edge0, float edge1, float x) const
float degToRad(float deg) const
float randomRange(float min, float max)
bool rectsOverlap(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) const
float normalize2X(float x, float y) const
float snap(float x, float grid) const
float polarX(float radius, float radians) const
float rotate2X(float x, float y, float radians) const
Rotate (x,y) by radians around origin.
float wrap(float x, float lo, float hi) const
float voronoiEdge2(float x, float y) const
float sign(float x) const
float cross2(float x1, float y1, float x2, float y2) const
float clamp(float x, float lo, float hi) const
float closestPointOnSegment3X(float px, float py, float pz, float ax, float ay, float az, float bx, float by, float bz) const
float rotate2Y(float x, float y, float radians) const
float closestPointOnSegment3Z(float px, float py, float pz, float ax, float ay, float az, float bx, float by, float bz) const
float bezierCubic2Y(float t, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) const
float noise3(float x, float y, float z) const
float perlin2(float x, float y) const
bool pointInCircle(float px, float py, float cx, float cy, float radius) const
float hash2(float x, float y) const
float bezierQuadratic2Y(float t, float x0, float y0, float x1, float y1, float x2, float y2) const
float dot3(float x1, float y1, float z1, float x2, float y2, float z2) const
float noise2(float x, float y) const
bool pointInBox(float px, float py, float pz, float minX, float minY, float minZ, float maxX, float maxY, float maxZ) const
Inclusive AABB test against [min,max] on each axis.
void setRandomSeedFromTime()
Vec3 * newVec3(float x=0.f, float y=0.f, float z=0.f)
float ridged3(float x, float y, float z, int octaves=4, float lacunarity=2.f, float gain=0.5f) const
uint32_t getRandomSeed() const
float bezierCubic(float t, float p0, float p1, float p2, float p3) const
float gain(float t, float g) const
float bilinear(float v00, float v10, float v01, float v11, float u, float v) const
Bilinear sample of 4 corners (v00,v10,v01,v11) with u,v in [0,1].
float ridged2(float x, float y, int octaves=4, float lacunarity=2.f, float gain=0.5f) const
float cartesianRadius(float x, float y) const
float pingPong(float t, float length) const
float hash1(float x) const
float distance2(float x1, float y1, float x2, float y2) const
float bias(float t, float b) const
Schlick bias/gain — shape [0,1] distributions (procgen falloff).
float raycastRect2(float ox, float oy, float dx, float dy, float rx, float ry, float rw, float rh) const
Ray vs axis-aligned rect (x,y,w,h). Returns parametric t >= 0, else -1.
float distance3(float x1, float y1, float z1, float x2, float y2, float z2) const
void setRandomSeed(uint32_t seed)
float length2(float x, float y) const
float radToDeg(float rad) const
float inverseLerp(float a, float b, float x) const
Inverse of lerp: t such that lerp(a,b,t) ≈ x.
bool segmentsIntersect(float ax, float ay, float bx, float by, float cx, float cy, float dx, float dy) const
True if segments AB and CD intersect (including endpoints).
float remap(float x, float inMin, float inMax, float outMin, float outMax) const
Mat4 * newMat4RotationZ(float radians)
Vec2 * newVec2(float x=0.f, float y=0.f)
float randomGaussian(float mean, float stddev)
Box-Muller Gaussian (mean, stddev).
float lerpAngle(float a, float b, float t) const
float bezierCubic2X(float t, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) const
float fbm3(float x, float y, float z, int octaves=4, float lacunarity=2.f, float gain=0.5f) const
float dot2(float x1, float y1, float x2, float y2) const
float raycastCircle2(float ox, float oy, float dx, float dy, float cx, float cy, float radius) const
Ray vs circle. Hit point = (ox,oy) + t*(dx,dy). Returns t >= 0 on hit, else -1. Direction need not be...
float polarY(float radius, float radians) const
bool pointInRect(float px, float py, float rx, float ry, float rw, float rh) const
float lerp(float a, float b, float t) const
float quantize(float x, float stepSize) const
bool circlesOverlap(float x1, float y1, float r1, float x2, float y2, float r2) const
float fbm2(float x, float y, int octaves=4, float lacunarity=2.f, float gain=0.5f) const
Fractal Brownian Motion / ridged / turbulence. octaves >= 1; lacunarity ~2; gain/persistence ~0....
float raycastSphere(float ox, float oy, float oz, float dx, float dy, float dz, float cx, float cy, float cz, float radius) const
int randomInt(int min, int maxInclusive)
float hash3(float x, float y, float z) const
2D float vector (script-facing math module value).
Vec2 * sub(const Vec2 *other) const
Vec2 * normalized() const
float cross(const Vec2 *other) const
float dot(const Vec2 *other) const
Dot/cross product, distance, angle (radians).
Vec2 * scale(float s) const
float distanceTo(const Vec2 *other) const
float length() const
Magnitude (and squared magnitude).
float lengthSquared() const
float getX() const
Component accessors.
Vec2 * clone() const
Copies this vector.
void set(float x, float y)
Sets both components.
Vec2 * add(const Vec2 *other) const
Arithmetic helpers returning new (caller-owned) vectors.
void normalize()
Normalizes in place / returns a normalized copy.
Vec2 * lerpTo(const Vec2 *other, float t) const
Linear interpolation to other at t in [0,1].
3D float vector (script-facing math module value).
Vec3 * normalized() const
Vec3 * cross(const Vec3 *other) const
Vec3 * clone() const
Copies this vector.
Vec3 * sub(const Vec3 *other) const
Vec3 * lerpTo(const Vec3 *other, float t) const
Linear interpolation to other at t in [0,1].
float length() const
Magnitude (and squared magnitude).
Vec3 * scale(float s) const
Vec3 * add(const Vec3 *other) const
Arithmetic helpers returning new (caller-owned) vectors.
float dot(const Vec3 *other) const
Dot/cross product and distance.
float distanceTo(const Vec3 *other) const
float lengthSquared() const
void normalize()
Normalizes in place / returns a normalized copy.
float getX() const
Component accessors.
void set(float x, float y, float z)
Sets all three components.