载入中...
搜索中...
未找到
Math.cpp
浏览该文件的文档.
1#include "math/Math.h"
2#include "math/Vec2.h"
3#include "math/Vec3.h"
4#include "math/Mat4.h"
5#include "math/Steering.h"
6
7#include "common/Exception.h"
8
9#include <simplesquirrel/simplesquirrel.hpp>
10
11#include <glm/glm.hpp>
12#include <glm/gtc/matrix_transform.hpp>
13#include <glm/gtc/noise.hpp>
14
15#include <algorithm>
16#include <cctype>
17#include <chrono>
18#include <cmath>
19#include <cstdint>
20#include <sstream>
21#include <string>
22#include <string_view>
23#include <vector>
24
25#ifndef M_PI
26#define M_PI 3.14159265358979323846
27#endif
28
29namespace eve::math {
30namespace {
31
32float clamp01(float t) { return std::clamp(t, 0.f, 1.f); }
33
34float noiseToUnit(float n) {
35 // glm::simplex / perlin is roughly [-1, 1]; map to [0, 1] like LÖVE.
36 return clamp01(n * 0.5f + 0.5f);
37}
38
39float hash11(float p) {
40 p = p - std::floor(p);
41 p *= 0.1031f;
42 p = p - std::floor(p);
43 p *= p + 33.33f;
44 p *= p + p;
45 return p - std::floor(p);
46}
47
48float hash21(float x, float y) {
49 glm::vec3 p3 = glm::fract(glm::vec3(x, y, x) * 0.1031f);
50 p3 += glm::dot(p3, glm::vec3(p3.y + 33.33f, p3.z + 33.33f, p3.x + 33.33f));
51 return glm::fract((p3.x + p3.y) * p3.z);
52}
53
54float hash31(float x, float y, float z) {
55 glm::vec3 p3 = glm::fract(glm::vec3(x, y, z) * 0.1031f);
56 p3 += glm::dot(p3, glm::vec3(p3.y + 33.33f, p3.z + 33.33f, p3.x + 33.33f));
57 return glm::fract((p3.x + p3.y) * p3.z);
58}
59
60bool parseSteeringCoordinate(std::string_view field, float &value) {
61 std::string input(field);
62 std::size_t consumed = 0;
63 try {
64 value = std::stof(input, &consumed);
65 } catch (...) {
66 return false;
67 }
68 while (consumed < input.size() &&
69 std::isspace(static_cast<unsigned char>(input[consumed])) != 0)
70 ++consumed;
71 return consumed == input.size() && std::isfinite(value);
72}
73
74std::vector<steering::Vector2> parseSteeringPoints2(const std::string &text) {
75 std::vector<steering::Vector2> result;
76 std::stringstream input(text);
77 std::string point;
78 while (std::getline(input, point, ',')) {
79 const auto separator = point.find(':');
80 if (separator == std::string::npos || point.find(':', separator + 1) != std::string::npos)
81 continue;
82 steering::Vector2 value;
83 if (parseSteeringCoordinate(std::string_view(point).substr(0, separator), value.x) &&
84 parseSteeringCoordinate(std::string_view(point).substr(separator + 1), value.y))
85 result.push_back(value);
86 }
87 return result;
88}
89
90std::vector<steering::Vector3> parseSteeringPoints3(const std::string &text) {
91 std::vector<steering::Vector3> result;
92 std::stringstream input(text);
93 std::string point;
94 while (std::getline(input, point, ',')) {
95 const auto first = point.find(':');
96 const auto second = first == std::string::npos ? first : point.find(':', first + 1);
97 if (first == std::string::npos || second == std::string::npos ||
98 point.find(':', second + 1) != std::string::npos)
99 continue;
100 steering::Vector3 value;
101 if (parseSteeringCoordinate(std::string_view(point).substr(0, first), value.x) &&
102 parseSteeringCoordinate(
103 std::string_view(point).substr(first + 1, second - first - 1), value.y) &&
104 parseSteeringCoordinate(std::string_view(point).substr(second + 1), value.z))
105 result.push_back(value);
106 }
107 return result;
108}
109
110glm::vec2 voronoiPoint(int ix, int iy) {
111 float hx = hash21(float(ix), float(iy));
112 float hy = hash21(float(ix) + 19.19f, float(iy) + 47.47f);
113 return glm::vec2(float(ix) + hx, float(iy) + hy);
114}
115
116void voronoiF1F2(float x, float y, float &f1, float &f2) {
117 int ix = int(std::floor(x));
118 int iy = int(std::floor(y));
119 f1 = 1e9f;
120 f2 = 1e9f;
121 for (int j = -1; j <= 1; ++j) {
122 for (int i = -1; i <= 1; ++i) {
123 glm::vec2 p = voronoiPoint(ix + i, iy + j);
124 float d = glm::length(glm::vec2(x, y) - p);
125 if (d < f1) {
126 f2 = f1;
127 f1 = d;
128 } else if (d < f2) {
129 f2 = d;
130 }
131 }
132 }
133}
134
135} // namespace
136
138
139Math::Math() : seed_(1), rng_(1) {}
140
141Vec2 *Math::newVec2(float x, float y) { return new Vec2(x, y); }
142Vec3 *Math::newVec3(float x, float y, float z) { return new Vec3(x, y, z); }
143
144Mat4 *Math::newMat4() { return new Mat4(); }
145
146Mat4 *Math::newMat4Translation(float x, float y, float z) {
147 auto *m = new Mat4();
148 m->translate(x, y, z);
149 return m;
150}
151
152Mat4 *Math::newMat4Scale(float sx, float sy, float sz) {
153 auto *m = new Mat4();
154 m->scale(sx, sy, sz);
155 return m;
156}
157
159 auto *m = new Mat4();
160 m->rotateZ(radians);
161 return m;
162}
163
164float Math::clamp(float x, float lo, float hi) const {
165 if (lo > hi) std::swap(lo, hi);
166 return std::clamp(x, lo, hi);
167}
168
169float Math::lerp(float a, float b, float t) const { return a + (b - a) * t; }
170
171float Math::smoothstep(float edge0, float edge1, float x) const {
172 if (edge0 == edge1) return x < edge0 ? 0.f : 1.f;
173 float t = clamp01((x - edge0) / (edge1 - edge0));
174 return t * t * (3.f - 2.f * t);
175}
176
177float Math::remap(float x, float inMin, float inMax, float outMin, float outMax) const {
178 if (inMin == inMax) return outMin;
179 float t = (x - inMin) / (inMax - inMin);
180 return outMin + (outMax - outMin) * t;
181}
182
183float Math::degToRad(float deg) const { return deg * float(M_PI) / 180.f; }
184float Math::radToDeg(float rad) const { return rad * 180.f / float(M_PI); }
185
186float Math::sign(float x) const {
187 if (x > 0.f) return 1.f;
188 if (x < 0.f) return -1.f;
189 return 0.f;
190}
191
192float Math::fract(float x) const { return x - std::floor(x); }
193
194float Math::approach(float current, float target, float maxDelta) const {
195 float d = target - current;
196 if (std::fabs(d) <= maxDelta) return target;
197 return current + sign(d) * maxDelta;
198}
199
200float Math::wrap(float x, float lo, float hi) const {
201 if (lo == hi) return lo;
202 if (lo > hi) std::swap(lo, hi);
203 float range = hi - lo;
204 float t = std::fmod(x - lo, range);
205 if (t < 0.f) t += range;
206 return lo + t;
207}
208
209float Math::pingPong(float t, float length) const {
210 if (length <= 0.f) return 0.f;
211 t = wrap(t, 0.f, length * 2.f);
212 return length - std::fabs(t - length);
213}
214
215Vec2 *Math::steeringSeek2(float x, float y, float targetX, float targetY, float maxSpeed) const {
217 steering::Vector2{targetX, targetY}, maxSpeed);
218 return new Vec2(value.x, value.y);
219}
220
221Vec3 *Math::steeringSeek3(float x, float y, float z, float targetX, float targetY, float targetZ,
222 float maxSpeed) const {
223 const auto value = steering::seek({x, y, z}, {targetX, targetY, targetZ}, maxSpeed);
224 return new Vec3(value.x, value.y, value.z);
225}
226
227Vec2 *Math::steeringFlee2(float x, float y, float targetX, float targetY, float maxSpeed) const {
229 steering::Vector2{targetX, targetY}, maxSpeed);
230 return new Vec2(value.x, value.y);
231}
232
233Vec3 *Math::steeringFlee3(float x, float y, float z, float targetX, float targetY, float targetZ,
234 float maxSpeed) const {
235 const auto value = steering::flee({x, y, z}, {targetX, targetY, targetZ}, maxSpeed);
236 return new Vec3(value.x, value.y, value.z);
237}
238
239Vec2 *Math::steeringArrive2(float x, float y, float targetX, float targetY, float maxSpeed,
240 float slowRadius, float stopRadius) const {
241 const auto value =
243 slowRadius, stopRadius);
244 return new Vec2(value.x, value.y);
245}
246
247Vec3 *Math::steeringArrive3(float x, float y, float z, float targetX, float targetY, float targetZ,
248 float maxSpeed, float slowRadius, float stopRadius) const {
249 const auto value = steering::arrive({x, y, z}, {targetX, targetY, targetZ}, maxSpeed,
250 slowRadius, stopRadius);
251 return new Vec3(value.x, value.y, value.z);
252}
253
254Vec2 *Math::steeringSeparation2(float x, float y, const std::string &neighbors, float radius,
255 float maxAcceleration) const {
256 const auto parsed = parseSteeringPoints2(neighbors);
257 const auto value =
258 steering::separation(steering::Vector2{x, y}, parsed, radius, maxAcceleration);
259 return new Vec2(value.x, value.y);
260}
261
262Vec3 *Math::steeringSeparation3(float x, float y, float z, const std::string &neighbors,
263 float radius, float maxAcceleration) const {
264 const auto parsed = parseSteeringPoints3(neighbors);
265 const auto value = steering::separation({x, y, z}, parsed, radius, maxAcceleration);
266 return new Vec3(value.x, value.y, value.z);
267}
268
269int Math::steeringPathTarget2(float x, float y, const std::string &points, int current,
270 float tolerance) const {
271 const auto parsed = parseSteeringPoints2(points);
272 return steering::pathTarget(steering::Vector2{x, y}, parsed, current, tolerance);
273}
274
275int Math::steeringPathTarget3(float x, float y, float z, const std::string &points, int current,
276 float tolerance) const {
277 const auto parsed = parseSteeringPoints3(points);
278 return steering::pathTarget({x, y, z}, parsed, current, tolerance);
279}
280
281Vec2 *Math::steeringAvoid2(float x, float y, float velocityX, float velocityY, float obstacleX,
282 float obstacleY, float obstacleRadius, float lookAhead,
283 float maxAcceleration) const {
284 const auto value =
285 steering::avoid(steering::Vector2{x, y}, steering::Vector2{velocityX, velocityY},
286 steering::Vector2{obstacleX, obstacleY}, obstacleRadius, lookAhead,
287 maxAcceleration);
288 return new Vec2(value.x, value.y);
289}
290
291Vec3 *Math::steeringAvoid3(float x, float y, float z, float velocityX, float velocityY,
292 float velocityZ, float obstacleX, float obstacleY, float obstacleZ,
293 float obstacleRadius, float lookAhead, float maxAcceleration) const {
294 const auto value = steering::avoid({x, y, z}, {velocityX, velocityY, velocityZ},
295 {obstacleX, obstacleY, obstacleZ}, obstacleRadius, lookAhead,
296 maxAcceleration);
297 return new Vec3(value.x, value.y, value.z);
298}
299
300float Math::inverseLerp(float a, float b, float x) const {
301 if (a == b) return 0.f;
302 return (x - a) / (b - a);
303}
304
305float Math::smootherstep(float edge0, float edge1, float x) const {
306 if (edge0 == edge1) return x < edge0 ? 0.f : 1.f;
307 float t = clamp01((x - edge0) / (edge1 - edge0));
308 return t * t * t * (t * (t * 6.f - 15.f) + 10.f);
309}
310
311float Math::bias(float t, float b) const {
312 t = clamp01(t);
313 if (b <= 0.f) return 0.f;
314 if (b >= 1.f) return 1.f;
315 return t / ((1.f / b - 2.f) * (1.f - t) + 1.f);
316}
317
318float Math::gain(float t, float g) const {
319 t = clamp01(t);
320 if (t < 0.5f) return bias(t * 2.f, g) * 0.5f;
321 return bias(t * 2.f - 1.f, 1.f - g) * 0.5f + 0.5f;
322}
323
324float Math::ease(float t, const std::string &kind) const {
325 t = clamp01(t);
326 if (kind == "linear" || kind.empty()) return t;
327 if (kind == "inQuad") return t * t;
328 if (kind == "outQuad") return 1.f - (1.f - t) * (1.f - t);
329 if (kind == "inOutQuad")
330 return t < 0.5f ? 2.f * t * t : 1.f - std::pow(-2.f * t + 2.f, 2.f) * 0.5f;
331 if (kind == "inCubic") return t * t * t;
332 if (kind == "outCubic") return 1.f - std::pow(1.f - t, 3.f);
333 if (kind == "inOutCubic")
334 return t < 0.5f ? 4.f * t * t * t : 1.f - std::pow(-2.f * t + 2.f, 3.f) * 0.5f;
335 if (kind == "inSine") return 1.f - std::cos(t * float(M_PI) * 0.5f);
336 if (kind == "outSine") return std::sin(t * float(M_PI) * 0.5f);
337 if (kind == "inOutSine") return -(std::cos(float(M_PI) * t) - 1.f) * 0.5f;
338 if (kind == "inExpo") return t <= 0.f ? 0.f : std::pow(2.f, 10.f * t - 10.f);
339 if (kind == "outExpo") return t >= 1.f ? 1.f : 1.f - std::pow(2.f, -10.f * t);
340 if (kind == "inOutExpo") {
341 if (t <= 0.f) return 0.f;
342 if (t >= 1.f) return 1.f;
343 return t < 0.5f ? std::pow(2.f, 20.f * t - 10.f) * 0.5f
344 : (2.f - std::pow(2.f, -20.f * t + 10.f)) * 0.5f;
345 }
346 throw Exception("Math.ease: unknown kind '%s'", kind.c_str());
347}
348
349float Math::step(float edge, float x) const { return x < edge ? 0.f : 1.f; }
350
351float Math::quantize(float x, float stepSize) const {
352 if (stepSize == 0.f) return x;
353 return std::floor(x / stepSize) * stepSize;
354}
355
356float Math::snap(float x, float grid) const {
357 if (grid == 0.f) return x;
358 return std::round(x / grid) * grid;
359}
360
361float Math::length2(float x, float y) const { return std::sqrt(x * x + y * y); }
362float Math::length3(float x, float y, float z) const {
363 return std::sqrt(x * x + y * y + z * z);
364}
365
366float Math::distance2(float x1, float y1, float x2, float y2) const {
367 return length2(x2 - x1, y2 - y1);
368}
369
370float Math::distance3(float x1, float y1, float z1, float x2, float y2, float z2) const {
371 return length3(x2 - x1, y2 - y1, z2 - z1);
372}
373
374float Math::dot2(float x1, float y1, float x2, float y2) const { return x1 * x2 + y1 * y2; }
375float Math::dot3(float x1, float y1, float z1, float x2, float y2, float z2) const {
376 return x1 * x2 + y1 * y2 + z1 * z2;
377}
378
379float Math::cross2(float x1, float y1, float x2, float y2) const { return x1 * y2 - y1 * x2; }
380float Math::angle2(float x, float y) const { return std::atan2(y, x); }
381
382float Math::angleBetween2(float x1, float y1, float x2, float y2) const {
383 return std::atan2(y2, x2) - std::atan2(y1, x1);
384}
385
386float Math::lerpAngle(float a, float b, float t) const {
387 float twoPi = float(M_PI) * 2.f;
388 float diff = std::fmod(b - a + float(M_PI), twoPi);
389 if (diff < 0.f) diff += twoPi;
390 diff -= float(M_PI);
391 return a + diff * t;
392}
393
394float Math::normalize2X(float x, float y) const {
395 float len = length2(x, y);
396 return len > 0.f ? x / len : 0.f;
397}
398float Math::normalize2Y(float x, float y) const {
399 float len = length2(x, y);
400 return len > 0.f ? y / len : 0.f;
401}
402float Math::normalize3X(float x, float y, float z) const {
403 float len = length3(x, y, z);
404 return len > 0.f ? x / len : 0.f;
405}
406float Math::normalize3Y(float x, float y, float z) const {
407 float len = length3(x, y, z);
408 return len > 0.f ? y / len : 0.f;
409}
410float Math::normalize3Z(float x, float y, float z) const {
411 float len = length3(x, y, z);
412 return len > 0.f ? z / len : 0.f;
413}
414
415float Math::rotate2X(float x, float y, float radians) const {
416 float c = std::cos(radians), s = std::sin(radians);
417 return x * c - y * s;
418}
419float Math::rotate2Y(float x, float y, float radians) const {
420 float c = std::cos(radians), s = std::sin(radians);
421 return x * s + y * c;
422}
423
424float Math::polarX(float radius, float radians) const { return radius * std::cos(radians); }
425float Math::polarY(float radius, float radians) const { return radius * std::sin(radians); }
426float Math::cartesianRadius(float x, float y) const { return length2(x, y); }
427float Math::cartesianAngle(float x, float y) const { return angle2(x, y); }
428
429bool Math::pointInCircle(float px, float py, float cx, float cy, float radius) const {
430 if (radius < 0.f) return false;
431 return distance2(px, py, cx, cy) <= radius;
432}
433
434bool Math::pointInRect(float px, float py, float rx, float ry, float rw, float rh) const {
435 return px >= rx && py >= ry && px <= rx + rw && py <= ry + rh;
436}
437
438bool Math::circlesOverlap(float x1, float y1, float r1, float x2, float y2, float r2) const {
439 if (r1 < 0.f || r2 < 0.f) return false;
440 float rr = r1 + r2;
441 float dx = x2 - x1, dy = y2 - y1;
442 return dx * dx + dy * dy <= rr * rr;
443}
444
445bool Math::rectsOverlap(float x1, float y1, float w1, float h1, float x2, float y2, float w2,
446 float h2) const {
447 return x1 <= x2 + w2 && x1 + w1 >= x2 && y1 <= y2 + h2 && y1 + h1 >= y2;
448}
449
450bool Math::circleRectOverlap(float cx, float cy, float radius, float rx, float ry, float rw,
451 float rh) const {
452 if (radius < 0.f) return false;
453 float nearestX = std::clamp(cx, rx, rx + rw);
454 float nearestY = std::clamp(cy, ry, ry + rh);
455 float dx = cx - nearestX, dy = cy - nearestY;
456 return dx * dx + dy * dy <= radius * radius;
457}
458
459bool Math::segmentsIntersect(float ax, float ay, float bx, float by, float cx, float cy, float dx,
460 float dy) const {
461 auto orient = [](float px, float py, float qx, float qy, float rx, float ry) {
462 return (qy - py) * (rx - qx) - (qx - px) * (ry - qy);
463 };
464 auto onSeg = [](float px, float py, float qx, float qy, float rx, float ry) {
465 return std::min(px, rx) <= qx && qx <= std::max(px, rx) && std::min(py, ry) <= qy &&
466 qy <= std::max(py, ry);
467 };
468 float o1 = orient(ax, ay, bx, by, cx, cy);
469 float o2 = orient(ax, ay, bx, by, dx, dy);
470 float o3 = orient(cx, cy, dx, dy, ax, ay);
471 float o4 = orient(cx, cy, dx, dy, bx, by);
472 if (o1 * o2 < 0.f && o3 * o4 < 0.f) return true;
473 constexpr float eps = 1e-6f;
474 if (std::fabs(o1) <= eps && onSeg(ax, ay, cx, cy, bx, by)) return true;
475 if (std::fabs(o2) <= eps && onSeg(ax, ay, dx, dy, bx, by)) return true;
476 if (std::fabs(o3) <= eps && onSeg(cx, cy, ax, ay, dx, dy)) return true;
477 if (std::fabs(o4) <= eps && onSeg(cx, cy, bx, by, dx, dy)) return true;
478 return false;
479}
480
481float Math::raycastCircle2(float ox, float oy, float dx, float dy, float cx, float cy,
482 float radius) const {
483 if (radius < 0.f) return -1.f;
484 float fx = ox - cx, fy = oy - cy;
485 float a = dx * dx + dy * dy;
486 if (a <= 1e-12f) return -1.f;
487 float b = 2.f * (fx * dx + fy * dy);
488 float c = fx * fx + fy * fy - radius * radius;
489 float disc = b * b - 4.f * a * c;
490 if (disc < 0.f) return -1.f;
491 float s = std::sqrt(disc);
492 float t0 = (-b - s) / (2.f * a);
493 float t1 = (-b + s) / (2.f * a);
494 if (t0 >= 0.f) return t0;
495 if (t1 >= 0.f) return t1;
496 return -1.f;
497}
498
499float Math::raycastRect2(float ox, float oy, float dx, float dy, float rx, float ry, float rw,
500 float rh) const {
501 constexpr float inf = 1e30f;
502 float tMin = 0.f;
503 float tMax = inf;
504 auto slab = [&](float o, float d, float minV, float maxV) -> bool {
505 if (std::fabs(d) < 1e-12f) {
506 return o >= minV && o <= maxV;
507 }
508 float inv = 1.f / d;
509 float t1 = (minV - o) * inv;
510 float t2 = (maxV - o) * inv;
511 if (t1 > t2) std::swap(t1, t2);
512 tMin = std::max(tMin, t1);
513 tMax = std::min(tMax, t2);
514 return tMin <= tMax;
515 };
516 if (!slab(ox, dx, rx, rx + rw)) return -1.f;
517 if (!slab(oy, dy, ry, ry + rh)) return -1.f;
518 if (tMax < 0.f) return -1.f;
519 return tMin >= 0.f ? tMin : 0.f;
520}
521
522namespace {
523float closestSegmentT(float px, float py, float ax, float ay, float bx, float by) {
524 float abx = bx - ax, aby = by - ay;
525 float denom = abx * abx + aby * aby;
526 if (denom <= 1e-12f) return 0.f;
527 float t = ((px - ax) * abx + (py - ay) * aby) / denom;
528 return std::clamp(t, 0.f, 1.f);
529}
530float closestSegmentT3(float px, float py, float pz, float ax, float ay, float az, float bx,
531 float by, float bz) {
532 float abx = bx - ax, aby = by - ay, abz = bz - az;
533 float denom = abx * abx + aby * aby + abz * abz;
534 if (denom <= 1e-12f) return 0.f;
535 float t = ((px - ax) * abx + (py - ay) * aby + (pz - az) * abz) / denom;
536 return std::clamp(t, 0.f, 1.f);
537}
538} // namespace
539
540float Math::closestPointOnSegment2X(float px, float py, float ax, float ay, float bx,
541 float by) const {
542 float t = closestSegmentT(px, py, ax, ay, bx, by);
543 return ax + (bx - ax) * t;
544}
545float Math::closestPointOnSegment2Y(float px, float py, float ax, float ay, float bx,
546 float by) const {
547 float t = closestSegmentT(px, py, ax, ay, bx, by);
548 return ay + (by - ay) * t;
549}
550
551bool Math::pointInSphere(float px, float py, float pz, float cx, float cy, float cz,
552 float radius) const {
553 if (radius < 0.f) return false;
554 return distance3(px, py, pz, cx, cy, cz) <= radius;
555}
556
557bool Math::pointInBox(float px, float py, float pz, float minX, float minY, float minZ, float maxX,
558 float maxY, float maxZ) const {
559 return px >= minX && px <= maxX && py >= minY && py <= maxY && pz >= minZ && pz <= maxZ;
560}
561
562bool Math::spheresOverlap(float x1, float y1, float z1, float r1, float x2, float y2, float z2,
563 float r2) const {
564 if (r1 < 0.f || r2 < 0.f) return false;
565 float rr = r1 + r2;
566 float dx = x2 - x1, dy = y2 - y1, dz = z2 - z1;
567 return dx * dx + dy * dy + dz * dz <= rr * rr;
568}
569
570bool Math::boxesOverlap(float minAx, float minAy, float minAz, float maxAx, float maxAy,
571 float maxAz, float minBx, float minBy, float minBz, float maxBx,
572 float maxBy, float maxBz) const {
573 return minAx <= maxBx && maxAx >= minBx && minAy <= maxBy && maxAy >= minBy &&
574 minAz <= maxBz && maxAz >= minBz;
575}
576
577float Math::raycastSphere(float ox, float oy, float oz, float dx, float dy, float dz, float cx,
578 float cy, float cz, float radius) const {
579 if (radius < 0.f) return -1.f;
580 float fx = ox - cx, fy = oy - cy, fz = oz - cz;
581 float a = dx * dx + dy * dy + dz * dz;
582 if (a <= 1e-12f) return -1.f;
583 float b = 2.f * (fx * dx + fy * dy + fz * dz);
584 float c = fx * fx + fy * fy + fz * fz - radius * radius;
585 float disc = b * b - 4.f * a * c;
586 if (disc < 0.f) return -1.f;
587 float s = std::sqrt(disc);
588 float t0 = (-b - s) / (2.f * a);
589 float t1 = (-b + s) / (2.f * a);
590 if (t0 >= 0.f) return t0;
591 if (t1 >= 0.f) return t1;
592 return -1.f;
593}
594
595float Math::raycastBox(float ox, float oy, float oz, float dx, float dy, float dz, float minX,
596 float minY, float minZ, float maxX, float maxY, float maxZ) const {
597 constexpr float inf = 1e30f;
598 float tMin = 0.f;
599 float tMax = inf;
600 auto slab = [&](float o, float d, float minV, float maxV) -> bool {
601 if (std::fabs(d) < 1e-12f) {
602 return o >= minV && o <= maxV;
603 }
604 float inv = 1.f / d;
605 float t1 = (minV - o) * inv;
606 float t2 = (maxV - o) * inv;
607 if (t1 > t2) std::swap(t1, t2);
608 tMin = std::max(tMin, t1);
609 tMax = std::min(tMax, t2);
610 return tMin <= tMax;
611 };
612 if (!slab(ox, dx, minX, maxX)) return -1.f;
613 if (!slab(oy, dy, minY, maxY)) return -1.f;
614 if (!slab(oz, dz, minZ, maxZ)) return -1.f;
615 if (tMax < 0.f) return -1.f;
616 return tMin >= 0.f ? tMin : 0.f;
617}
618
619float Math::raycastPlane(float ox, float oy, float oz, float dx, float dy, float dz, float px,
620 float py, float pz, float nx, float ny, float nz) const {
621 float denom = nx * dx + ny * dy + nz * dz;
622 if (std::fabs(denom) < 1e-12f) return -1.f;
623 float t = (nx * (px - ox) + ny * (py - oy) + nz * (pz - oz)) / denom;
624 return t >= 0.f ? t : -1.f;
625}
626
627float Math::closestPointOnSegment3X(float px, float py, float pz, float ax, float ay, float az,
628 float bx, float by, float bz) const {
629 float t = closestSegmentT3(px, py, pz, ax, ay, az, bx, by, bz);
630 return ax + (bx - ax) * t;
631}
632float Math::closestPointOnSegment3Y(float px, float py, float pz, float ax, float ay, float az,
633 float bx, float by, float bz) const {
634 float t = closestSegmentT3(px, py, pz, ax, ay, az, bx, by, bz);
635 return ay + (by - ay) * t;
636}
637float Math::closestPointOnSegment3Z(float px, float py, float pz, float ax, float ay, float az,
638 float bx, float by, float bz) const {
639 float t = closestSegmentT3(px, py, pz, ax, ay, az, bx, by, bz);
640 return az + (bz - az) * t;
641}
642
643float Math::bilinear(float v00, float v10, float v01, float v11, float u, float v) const {
644 float a = lerp(v00, v10, u);
645 float b = lerp(v01, v11, u);
646 return lerp(a, b, v);
647}
648
649void Math::setRandomSeed(uint32_t seed) {
650 seed_ = seed == 0 ? 1u : seed;
651 rng_.seed(seed_);
652}
653
655 auto us = std::chrono::duration_cast<std::chrono::microseconds>(
656 std::chrono::steady_clock::now().time_since_epoch())
657 .count();
658 setRandomSeed(static_cast<uint32_t>(us) ^ 0xA5A5A5A5u);
659}
660
661uint32_t Math::getRandomSeed() const { return seed_; }
662
664 std::uniform_real_distribution<float> dist(0.f, 1.f);
665 return dist(rng_);
666}
667
668float Math::randomRange(float min, float max) {
669 if (min > max) std::swap(min, max);
670 std::uniform_real_distribution<float> dist(min, max);
671 return dist(rng_);
672}
673
674int Math::randomInt(int min, int maxInclusive) {
675 if (min > maxInclusive) std::swap(min, maxInclusive);
676 std::uniform_int_distribution<int> dist(min, maxInclusive);
677 return dist(rng_);
678}
679
680float Math::randomGaussian(float mean, float stddev) {
681 std::normal_distribution<float> dist(mean, stddev);
682 return dist(rng_);
683}
684
685float Math::hash1(float x) const { return hash11(x); }
686float Math::hash2(float x, float y) const { return hash21(x, y); }
687float Math::hash3(float x, float y, float z) const { return hash31(x, y, z); }
688
689float Math::noise1(float x) const { return noiseToUnit(glm::simplex(glm::vec2(x, 0.f))); }
690float Math::noise2(float x, float y) const { return noiseToUnit(glm::simplex(glm::vec2(x, y))); }
691float Math::noise3(float x, float y, float z) const {
692 return noiseToUnit(glm::simplex(glm::vec3(x, y, z)));
693}
694
695float Math::perlin2(float x, float y) const { return noiseToUnit(glm::perlin(glm::vec2(x, y))); }
696float Math::perlin3(float x, float y, float z) const {
697 return noiseToUnit(glm::perlin(glm::vec3(x, y, z)));
698}
699
700float Math::fbm2(float x, float y, int octaves, float lacunarity, float gain) const {
701 if (octaves < 1) octaves = 1;
702 if (octaves > 16) octaves = 16;
703 float sum = 0.f, amp = 1.f, freq = 1.f, norm = 0.f;
704 for (int i = 0; i < octaves; ++i) {
705 sum += noise2(x * freq, y * freq) * amp;
706 norm += amp;
707 amp *= gain;
708 freq *= lacunarity;
709 }
710 return norm > 0.f ? sum / norm : 0.f;
711}
712
713float Math::fbm3(float x, float y, float z, int octaves, float lacunarity, float gain) const {
714 if (octaves < 1) octaves = 1;
715 if (octaves > 16) octaves = 16;
716 float sum = 0.f, amp = 1.f, freq = 1.f, norm = 0.f;
717 for (int i = 0; i < octaves; ++i) {
718 sum += noise3(x * freq, y * freq, z * freq) * amp;
719 norm += amp;
720 amp *= gain;
721 freq *= lacunarity;
722 }
723 return norm > 0.f ? sum / norm : 0.f;
724}
725
726float Math::ridged2(float x, float y, int octaves, float lacunarity, float gain) const {
727 if (octaves < 1) octaves = 1;
728 if (octaves > 16) octaves = 16;
729 float sum = 0.f, amp = 0.5f, freq = 1.f, prev = 1.f;
730 for (int i = 0; i < octaves; ++i) {
731 float n = noise2(x * freq, y * freq);
732 n = 1.f - std::fabs(n * 2.f - 1.f);
733 n = n * n;
734 sum += n * amp * prev;
735 prev = n;
736 freq *= lacunarity;
737 amp *= gain;
738 }
739 return clamp01(sum);
740}
741
742float Math::ridged3(float x, float y, float z, int octaves, float lacunarity, float gain) const {
743 if (octaves < 1) octaves = 1;
744 if (octaves > 16) octaves = 16;
745 float sum = 0.f, amp = 0.5f, freq = 1.f, prev = 1.f;
746 for (int i = 0; i < octaves; ++i) {
747 float n = noise3(x * freq, y * freq, z * freq);
748 n = 1.f - std::fabs(n * 2.f - 1.f);
749 n = n * n;
750 sum += n * amp * prev;
751 prev = n;
752 freq *= lacunarity;
753 amp *= gain;
754 }
755 return clamp01(sum);
756}
757
758float Math::turbulence2(float x, float y, int octaves, float lacunarity, float gain) const {
759 if (octaves < 1) octaves = 1;
760 if (octaves > 16) octaves = 16;
761 float sum = 0.f, amp = 1.f, freq = 1.f, norm = 0.f;
762 for (int i = 0; i < octaves; ++i) {
763 sum += std::fabs(noise2(x * freq, y * freq) * 2.f - 1.f) * amp;
764 norm += amp;
765 amp *= gain;
766 freq *= lacunarity;
767 }
768 return norm > 0.f ? clamp01(sum / norm) : 0.f;
769}
770
771float Math::voronoi2(float x, float y) const {
772 float f1, f2;
773 voronoiF1F2(x, y, f1, f2);
774 return f1;
775}
776
777float Math::voronoiEdge2(float x, float y) const {
778 float f1, f2;
779 voronoiF1F2(x, y, f1, f2);
780 return f2 - f1;
781}
782
783float Math::warpNoise2(float x, float y, float warpAmp) const {
784 float wx = noise2(x, y) - 0.5f;
785 float wy = noise2(x + 5.2f, y + 1.3f) - 0.5f;
786 return noise2(x + wx * warpAmp, y + wy * warpAmp);
787}
788
789float Math::bezierQuadratic(float t, float p0, float p1, float p2) const {
790 t = clamp01(t);
791 float u = 1.f - t;
792 return u * u * p0 + 2.f * u * t * p1 + t * t * p2;
793}
794
795float Math::bezierCubic(float t, float p0, float p1, float p2, float p3) const {
796 t = clamp01(t);
797 float u = 1.f - t;
798 float uu = u * u;
799 float tt = t * t;
800 return uu * u * p0 + 3.f * uu * t * p1 + 3.f * u * tt * p2 + tt * t * p3;
801}
802
803float Math::bezierQuadratic2X(float t, float x0, float /*y0*/, float x1, float /*y1*/, float x2,
804 float /*y2*/) const {
805 return bezierQuadratic(t, x0, x1, x2);
806}
807
808float Math::bezierQuadratic2Y(float t, float /*x0*/, float y0, float /*x1*/, float y1, float /*x2*/,
809 float y2) const {
810 return bezierQuadratic(t, y0, y1, y2);
811}
812
813float Math::bezierCubic2X(float t, float x0, float /*y0*/, float x1, float /*y1*/, float x2,
814 float /*y2*/, float x3, float /*y3*/) const {
815 return bezierCubic(t, x0, x1, x2, x3);
816}
817
818float Math::bezierCubic2Y(float t, float /*x0*/, float y0, float /*x1*/, float y1, float /*x2*/,
819 float y2, float /*x3*/, float y3) const {
820 return bezierCubic(t, y0, y1, y2, y3);
821}
822
823void Math::expose(ssq::Table &table) {
824 auto cls = table.addClass(name, Math::create, false);
825 expose(cls);
826
827 auto v2 = table.addClass<Vec2>(
828 "Vec2", std::function<Vec2 *()>([]() -> Vec2 * { return nullptr; }), true);
829 v2.addFunc("getX", &Vec2::getX);
830 v2.addFunc("getY", &Vec2::getY);
831 v2.addFunc("setX", &Vec2::setX);
832 v2.addFunc("setY", &Vec2::setY);
833 v2.addFunc("set", &Vec2::set);
834 v2.addFunc("length", &Vec2::length);
835 v2.addFunc("lengthSquared", &Vec2::lengthSquared);
836 v2.addFunc("normalize", &Vec2::normalize);
837 v2.addFunc("normalized", &Vec2::normalized);
838 v2.addFunc("dot", &Vec2::dot);
839 v2.addFunc("cross", &Vec2::cross);
840 v2.addFunc("distanceTo", &Vec2::distanceTo);
841 v2.addFunc("angle", &Vec2::angle);
842 v2.addFunc("add", &Vec2::add);
843 v2.addFunc("sub", &Vec2::sub);
844 v2.addFunc("scale", &Vec2::scale);
845 v2.addFunc("lerpTo", &Vec2::lerpTo);
846 v2.addFunc("clone", &Vec2::clone);
847
848 auto v3 = table.addClass<Vec3>(
849 "Vec3", std::function<Vec3 *()>([]() -> Vec3 * { return nullptr; }), true);
850 v3.addFunc("getX", &Vec3::getX);
851 v3.addFunc("getY", &Vec3::getY);
852 v3.addFunc("getZ", &Vec3::getZ);
853 v3.addFunc("setX", &Vec3::setX);
854 v3.addFunc("setY", &Vec3::setY);
855 v3.addFunc("setZ", &Vec3::setZ);
856 v3.addFunc("set", &Vec3::set);
857 v3.addFunc("length", &Vec3::length);
858 v3.addFunc("lengthSquared", &Vec3::lengthSquared);
859 v3.addFunc("normalize", &Vec3::normalize);
860 v3.addFunc("normalized", &Vec3::normalized);
861 v3.addFunc("dot", &Vec3::dot);
862 v3.addFunc("cross", &Vec3::cross);
863 v3.addFunc("distanceTo", &Vec3::distanceTo);
864 v3.addFunc("add", &Vec3::add);
865 v3.addFunc("sub", &Vec3::sub);
866 v3.addFunc("scale", &Vec3::scale);
867 v3.addFunc("lerpTo", &Vec3::lerpTo);
868 v3.addFunc("clone", &Vec3::clone);
869
870 auto m4 = table.addClass<Mat4>(
871 "Mat4", std::function<Mat4 *()>([]() -> Mat4 * { return nullptr; }), true);
872 m4.addFunc("identity", &Mat4::identity);
873 m4.addFunc("translate", &Mat4::translate);
874 m4.addFunc("rotateX", &Mat4::rotateX);
875 m4.addFunc("rotateY", &Mat4::rotateY);
876 m4.addFunc("rotateZ", &Mat4::rotateZ);
877 m4.addFunc("scale", &Mat4::scale);
878 m4.addFunc("multiply", &Mat4::multiply);
879 m4.addFunc("multiplied", &Mat4::multiplied);
880 m4.addFunc("transformVec3", &Mat4::transformVec3);
881 m4.addFunc("transformPoint2", &Mat4::transformPoint2);
882 m4.addFunc("get", &Mat4::get);
883 m4.addFunc("set", &Mat4::set);
884 m4.addFunc("clone", &Mat4::clone);
885}
886
887void Math::expose(ssq::Class &cls) {
888 cls.addFunc("getName", &Math::getName);
889 cls.addFunc("newVec2", &Math::newVec2);
890 cls.addFunc("newVec3", &Math::newVec3);
891 cls.addFunc("newMat4", &Math::newMat4);
892 cls.addFunc("newMat4Translation", &Math::newMat4Translation);
893 cls.addFunc("newMat4Scale", &Math::newMat4Scale);
894 cls.addFunc("newMat4RotationZ", &Math::newMat4RotationZ);
895
896 cls.addFunc("clamp", &Math::clamp);
897 cls.addFunc("lerp", &Math::lerp);
898 cls.addFunc("smoothstep", &Math::smoothstep);
899 cls.addFunc("remap", &Math::remap);
900 cls.addFunc("degToRad", &Math::degToRad);
901 cls.addFunc("radToDeg", &Math::radToDeg);
902 cls.addFunc("sign", &Math::sign);
903 cls.addFunc("fract", &Math::fract);
904 cls.addFunc("approach", &Math::approach);
905 cls.addFunc("wrap", &Math::wrap);
906 cls.addFunc("pingPong", &Math::pingPong);
907 cls.addFunc("inverseLerp", &Math::inverseLerp);
908 cls.addFunc("smootherstep", &Math::smootherstep);
909 cls.addFunc("bias", &Math::bias);
910 cls.addFunc("gain", &Math::gain);
911 cls.addFunc("ease", &Math::ease);
912 cls.addFunc("step", &Math::step);
913 cls.addFunc("quantize", &Math::quantize);
914 cls.addFunc("snap", &Math::snap);
915
916 cls.addFunc("length2", &Math::length2);
917 cls.addFunc("length3", &Math::length3);
918 cls.addFunc("distance2", &Math::distance2);
919 cls.addFunc("distance3", &Math::distance3);
920 cls.addFunc("dot2", &Math::dot2);
921 cls.addFunc("dot3", &Math::dot3);
922 cls.addFunc("cross2", &Math::cross2);
923 cls.addFunc("angle2", &Math::angle2);
924 cls.addFunc("angleBetween2", &Math::angleBetween2);
925 cls.addFunc("lerpAngle", &Math::lerpAngle);
926 cls.addFunc("normalize2X", &Math::normalize2X);
927 cls.addFunc("normalize2Y", &Math::normalize2Y);
928 cls.addFunc("normalize3X", &Math::normalize3X);
929 cls.addFunc("normalize3Y", &Math::normalize3Y);
930 cls.addFunc("normalize3Z", &Math::normalize3Z);
931 cls.addFunc("steeringSeek2", &Math::steeringSeek2);
932 cls.addFunc("steeringSeek3", &Math::steeringSeek3);
933 cls.addFunc("steeringFlee2", &Math::steeringFlee2);
934 cls.addFunc("steeringFlee3", &Math::steeringFlee3);
935 cls.addFunc("steeringArrive2", &Math::steeringArrive2);
936 cls.addFunc("steeringArrive3", &Math::steeringArrive3);
937 cls.addFunc("steeringSeparation2", &Math::steeringSeparation2);
938 cls.addFunc("steeringSeparation3", &Math::steeringSeparation3);
939 cls.addFunc("steeringPathTarget2", &Math::steeringPathTarget2);
940 cls.addFunc("steeringPathTarget3", &Math::steeringPathTarget3);
941 cls.addFunc("steeringAvoid2", &Math::steeringAvoid2);
942 cls.addFunc("steeringAvoid3", &Math::steeringAvoid3);
943 cls.addFunc("rotate2X", &Math::rotate2X);
944 cls.addFunc("rotate2Y", &Math::rotate2Y);
945 cls.addFunc("polarX", &Math::polarX);
946 cls.addFunc("polarY", &Math::polarY);
947 cls.addFunc("cartesianRadius", &Math::cartesianRadius);
948 cls.addFunc("cartesianAngle", &Math::cartesianAngle);
949 cls.addFunc("pointInCircle", &Math::pointInCircle);
950 cls.addFunc("pointInRect", &Math::pointInRect);
951 cls.addFunc("circlesOverlap", &Math::circlesOverlap);
952 cls.addFunc("rectsOverlap", &Math::rectsOverlap);
953 cls.addFunc("circleRectOverlap", &Math::circleRectOverlap);
954 cls.addFunc("segmentsIntersect", &Math::segmentsIntersect);
955 cls.addFunc("raycastCircle2", &Math::raycastCircle2);
956 cls.addFunc("raycastRect2", &Math::raycastRect2);
957 cls.addFunc("closestPointOnSegment2X", &Math::closestPointOnSegment2X);
958 cls.addFunc("closestPointOnSegment2Y", &Math::closestPointOnSegment2Y);
959 cls.addFunc("pointInSphere", &Math::pointInSphere);
960 cls.addFunc("pointInBox", &Math::pointInBox);
961 cls.addFunc("spheresOverlap", &Math::spheresOverlap);
962 cls.addFunc("boxesOverlap", &Math::boxesOverlap);
963 cls.addFunc("raycastSphere", &Math::raycastSphere);
964 cls.addFunc("raycastBox", &Math::raycastBox);
965 cls.addFunc("raycastPlane", &Math::raycastPlane);
966 cls.addFunc("closestPointOnSegment3X", &Math::closestPointOnSegment3X);
967 cls.addFunc("closestPointOnSegment3Y", &Math::closestPointOnSegment3Y);
968 cls.addFunc("closestPointOnSegment3Z", &Math::closestPointOnSegment3Z);
969 cls.addFunc("bilinear", &Math::bilinear);
970
971 cls.addFunc("setRandomSeed", &Math::setRandomSeed);
972 cls.addFunc("setRandomSeedFromTime", &Math::setRandomSeedFromTime);
973 cls.addFunc("getRandomSeed", &Math::getRandomSeed);
974 cls.addFunc("random", &Math::random);
975 cls.addFunc("randomRange", &Math::randomRange);
976 cls.addFunc("randomInt", &Math::randomInt);
977 cls.addFunc("randomGaussian", &Math::randomGaussian);
978
979 cls.addFunc("hash1", &Math::hash1);
980 cls.addFunc("hash2", &Math::hash2);
981 cls.addFunc("hash3", &Math::hash3);
982
983 cls.addFunc("noise1", &Math::noise1);
984 cls.addFunc("noise2", &Math::noise2);
985 cls.addFunc("noise3", &Math::noise3);
986 cls.addFunc("perlin2", &Math::perlin2);
987 cls.addFunc("perlin3", &Math::perlin3);
988 cls.addFunc("fbm2", &Math::fbm2);
989 cls.addFunc("fbm3", &Math::fbm3);
990 cls.addFunc("ridged2", &Math::ridged2);
991 cls.addFunc("ridged3", &Math::ridged3);
992 cls.addFunc("turbulence2", &Math::turbulence2);
993 cls.addFunc("voronoi2", &Math::voronoi2);
994 cls.addFunc("voronoiEdge2", &Math::voronoiEdge2);
995 cls.addFunc("warpNoise2", &Math::warpNoise2);
996
997 cls.addFunc("bezierQuadratic", &Math::bezierQuadratic);
998 cls.addFunc("bezierCubic", &Math::bezierCubic);
999 cls.addFunc("bezierQuadratic2X", &Math::bezierQuadratic2X);
1000 cls.addFunc("bezierQuadratic2Y", &Math::bezierQuadratic2Y);
1001 cls.addFunc("bezierCubic2X", &Math::bezierCubic2X);
1002 cls.addFunc("bezierCubic2Y", &Math::bezierCubic2Y);
1003}
1004
1005} // namespace eve::math
LogicalId target
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
const std::string & s
float cx
Definition CardTypes.cpp:33
float cy
Definition CardTypes.cpp:34
int bz
Definition CaveMesh.cpp:114
int ax
Definition CaveMesh.cpp:113
int ay
Definition CaveMesh.cpp:113
int bx
Definition CaveMesh.cpp:114
float length
Definition CaveMesh.cpp:94
int az
Definition CaveMesh.cpp:113
int by
Definition CaveMesh.cpp:114
float py
float nx
float nz
float ny
float pz
glm::vec4 p[6]
HSQOBJECT cls
Definition ECS.cpp:21
EvpackChunkInput input
Definition Evpack.cpp:170
tensor::Graph g
Definition GpuGraph.cpp:7
float u
Definition Grass.cpp:233
glm::vec3 n
Definition Grass.cpp:63
float v
std::int32_t second
std::int32_t c
std::int32_t first
std::vector< Colorf > px
std::string text
TokenKind kind
Range range
std::string name
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
#define Module_IMPL(ModuleName, newExpr)
Definition Module.h:26
#define M_PI
float radius
std::uint32_t seed
Definition PointSet.cpp:807
std::shared_ptr< const std::vector< glm::vec2 > > points
float d
float t
const RoadEdge * edge
double current
float dz
float dy
float dx
float bias
float targetX
double oy
double ox
float m[16]
glm::vec3 point
float wx
float qy
float qx
float wy
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
virtual std::string getName() const =0
Returns the name.
Column-major 4x4 matrix wrapping glm::mat4.
Definition Mat4.h:13
Vec3 * transformVec3(const Vec3 *v) const
Definition Mat4.cpp:39
Vec2 * transformPoint2(const Vec2 *v) const
Definition Mat4.cpp:45
void translate(float x, float y, float z)
Post-multiplies a translation.
Definition Mat4.cpp:17
float get(int index) const
Column-major element 0..15.
Definition Mat4.cpp:51
void identity()
Resets to the identity matrix.
Definition Mat4.cpp:15
void scale(float sx, float sy, float sz)
Scales by scalar s. @ownership Caller deletes.
Definition Mat4.cpp:25
void multiply(const Mat4 *other)
Post-multiplies by other (column-vector convention).
Definition Mat4.cpp:29
Mat4 * clone() const
Definition Mat4.cpp:61
void rotateX(float radians)
Post-multiplies a rotation about X (radians).
Definition Mat4.cpp:21
void rotateZ(float radians)
Post-multiplies a rotation about Z (radians).
Definition Mat4.cpp:23
Mat4 * multiplied(const Mat4 *other) const
Definition Mat4.cpp:34
void set(int index, float value)
Sets all components.
Definition Mat4.cpp:56
void rotateY(float radians)
Post-multiplies a rotation about Y (radians).
Definition Mat4.cpp:22
Math module — glm-backed vectors/matrices, noise, bezier, random. Script: math <- eve....
Definition Math.h:23
Vec2 * steeringFlee2(float x, float y, float targetX, float targetY, float maxSpeed) const
Creates a 2D flee velocity. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:227
Vec2 * steeringAvoid2(float x, float y, float velocityX, float velocityY, float obstacleX, float obstacleY, float obstacleRadius, float lookAhead, float maxAcceleration) const
Creates 2D avoidance acceleration. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:281
bool pointInSphere(float px, float py, float pz, float cx, float cy, float cz, float radius) const
True if point is inside or on the sphere.
Definition Math.cpp:551
float bezierQuadratic(float t, float p0, float p1, float p2) const
1D quadratic Bezier at t in [0,1].
Definition Math.cpp:789
Vec3 * steeringFlee3(float x, float y, float z, float targetX, float targetY, float targetZ, float maxSpeed) const
Creates a 3D flee velocity. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:233
bool spheresOverlap(float x1, float y1, float z1, float r1, float x2, float y2, float z2, float r2) const
True if two spheres overlap.
Definition Math.cpp:562
Mat4 * newMat4Scale(float sx, float sy, float sz)
Allocates a scale Mat4. @ownership Caller deletes.
Definition Math.cpp:152
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.
Definition Math.cpp:783
float normalize3X(float x, float y, float z) const
X of the normalized 3D vector (zero-safe).
Definition Math.cpp:402
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
True if two AABBs overlap.
Definition Math.cpp:570
float normalize3Z(float x, float y, float z) const
Z of the normalized 3D vector (zero-safe).
Definition Math.cpp:410
float perlin3(float x, float y, float z) const
Perlin noise in 3D, range [0,1].
Definition Math.cpp:696
float voronoi2(float x, float y) const
Worley / Voronoi F1 distance in [0, ~1.5] (cell size 1). voronoiEdge2 = F2 - F1 (cell borders).
Definition Math.cpp:771
float approach(float current, float target, float maxDelta) const
Moves current toward target by at most maxDelta.
Definition Math.cpp:194
float turbulence2(float x, float y, int octaves=4, float lacunarity=2.f, float gain=0.5f) const
2D turbulence (absolute fBm).
Definition Math.cpp:758
int steeringPathTarget3(float x, float y, float z, const std::string &points, int current, float tolerance) const
Selects a 3D path point from CSV x:y:z points, or -1 for no valid points.
Definition Math.cpp:275
Math()
Initializes RNG and math helpers.
Definition Math.cpp:139
float closestPointOnSegment2Y(float px, float py, float ax, float ay, float bx, float by) const
Y of the closest point on segment AB to P.
Definition Math.cpp:545
Mat4 * newMat4Translation(float x, float y, float z)
Allocates a translation Mat4. @ownership Caller deletes.
Definition Math.cpp:146
float normalize2Y(float x, float y) const
Y of the normalized 2D vector (zero-safe).
Definition Math.cpp:398
Vec2 * steeringSeek2(float x, float y, float targetX, float targetY, float maxSpeed) const
Creates a 2D seek velocity. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:215
float length3(float x, float y, float z) const
3D vector length from components.
Definition Math.cpp:362
float ease(float t, const std::string &kind) const
Easing on [0,1]. kind: "linear"|"inQuad"|"outQuad"|"inOutQuad"|"inCubic"|"outCubic"|"inOutCubic"| "in...
Definition Math.cpp:324
float step(float edge, float x) const
Heaviside step: 0 if x < edge else 1.
Definition Math.cpp:349
float bezierQuadratic2X(float t, float x0, float y0, float x1, float y1, float x2, float y2) const
X of a 2D quadratic Bezier at t.
Definition Math.cpp:803
float angle2(float x, float y) const
Atan2 angle of (x,y) in radians.
Definition Math.cpp:380
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,...
Definition Math.cpp:619
int steeringPathTarget2(float x, float y, const std::string &points, int current, float tolerance) const
Selects a 2D path point from CSV x:y points, or -1 for no valid points.
Definition Math.cpp:269
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
Ray vs AABB; parametric t >= 0 on hit, else -1.
Definition Math.cpp:595
float angleBetween2(float x1, float y1, float x2, float y2) const
Signed angle from first vector to second.
Definition Math.cpp:382
float cartesianAngle(float x, float y) const
Atan2 angle of (x,y).
Definition Math.cpp:427
float normalize3Y(float x, float y, float z) const
Y of the normalized 3D vector (zero-safe).
Definition Math.cpp:406
float closestPointOnSegment2X(float px, float py, float ax, float ay, float bx, float by) const
X of the closest point on segment AB to P.
Definition Math.cpp:540
bool circleRectOverlap(float cx, float cy, float radius, float rx, float ry, float rw, float rh) const
True if circle and axis-aligned rect overlap.
Definition Math.cpp:450
float smootherstep(float edge0, float edge1, float x) const
Ken Perlin smootherstep between edge0 and edge1.
Definition Math.cpp:305
float closestPointOnSegment3Y(float px, float py, float pz, float ax, float ay, float az, float bx, float by, float bz) const
Y of the closest point on segment AB to P.
Definition Math.cpp:632
float random()
Uniform float in [0, 1).
Definition Math.cpp:663
float fract(float x) const
Fractional part of x.
Definition Math.cpp:192
float noise1(float x) const
Value noise in 1D, range [0,1].
Definition Math.cpp:689
Mat4 * newMat4()
Allocates an identity Mat4. @ownership Caller deletes.
Definition Math.cpp:144
Vec2 * steeringSeparation2(float x, float y, const std::string &neighbors, float radius, float maxAcceleration) const
Creates 2D separation acceleration from CSV. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:254
float smoothstep(float edge0, float edge1, float x) const
Hermite smoothstep between edge0 and edge1.
Definition Math.cpp:171
float degToRad(float deg) const
Degrees to radians.
Definition Math.cpp:183
float randomRange(float min, float max)
Uniform float in [min, max).
Definition Math.cpp:668
bool rectsOverlap(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) const
True if two axis-aligned rects overlap.
Definition Math.cpp:445
float normalize2X(float x, float y) const
X of the normalized 2D vector (zero-safe).
Definition Math.cpp:394
Vec3 * steeringSeparation3(float x, float y, float z, const std::string &neighbors, float radius, float maxAcceleration) const
Creates 3D separation acceleration from CSV. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:262
Vec3 * steeringSeek3(float x, float y, float z, float targetX, float targetY, float targetZ, float maxSpeed) const
Creates a 3D seek velocity. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:221
Vec3 * steeringArrive3(float x, float y, float z, float targetX, float targetY, float targetZ, float maxSpeed, float slowRadius, float stopRadius) const
Creates a 3D arrive velocity. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:247
float snap(float x, float grid) const
Snaps x to the nearest grid multiple.
Definition Math.cpp:356
float polarX(float radius, float radians) const
X of polar (radius, radians).
Definition Math.cpp:424
float rotate2X(float x, float y, float radians) const
Rotate (x,y) by radians around origin.
Definition Math.cpp:415
float wrap(float x, float lo, float hi) const
Wraps x into [lo, hi).
Definition Math.cpp:200
float voronoiEdge2(float x, float y) const
2D Worley F2-F1 edge distance.
Definition Math.cpp:777
float sign(float x) const
Sign of x (-1, 0, or 1).
Definition Math.cpp:186
float cross2(float x1, float y1, float x2, float y2) const
2D cross product (scalar z-component).
Definition Math.cpp:379
float clamp(float x, float lo, float hi) const
Clamps x into [lo, hi].
Definition Math.cpp:164
float closestPointOnSegment3X(float px, float py, float pz, float ax, float ay, float az, float bx, float by, float bz) const
X of the closest point on segment AB to P.
Definition Math.cpp:627
float rotate2Y(float x, float y, float radians) const
Y after rotating (x,y) by radians about the origin.
Definition Math.cpp:419
float closestPointOnSegment3Z(float px, float py, float pz, float ax, float ay, float az, float bx, float by, float bz) const
Z of the closest point on segment AB to P.
Definition Math.cpp:637
float bezierCubic2Y(float t, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) const
Y of a 2D cubic Bezier at t.
Definition Math.cpp:818
float noise3(float x, float y, float z) const
Value noise in 3D, range [0,1].
Definition Math.cpp:691
float perlin2(float x, float y) const
Perlin noise in 2D, range [0,1].
Definition Math.cpp:695
bool pointInCircle(float px, float py, float cx, float cy, float radius) const
True if point is inside or on the circle.
Definition Math.cpp:429
float hash2(float x, float y) const
Deterministic 2D hash mapped to [0,1].
Definition Math.cpp:686
float bezierQuadratic2Y(float t, float x0, float y0, float x1, float y1, float x2, float y2) const
Y of a 2D quadratic Bezier at t.
Definition Math.cpp:808
float dot3(float x1, float y1, float z1, float x2, float y2, float z2) const
3D dot product of two vectors.
Definition Math.cpp:375
float noise2(float x, float y) const
Value noise in 2D, range [0,1].
Definition Math.cpp:690
Vec3 * steeringAvoid3(float x, float y, float z, float velocityX, float velocityY, float velocityZ, float obstacleX, float obstacleY, float obstacleZ, float obstacleRadius, float lookAhead, float maxAcceleration) const
Creates 3D avoidance acceleration. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:291
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.
Definition Math.cpp:557
void setRandomSeedFromTime()
Seeds the RNG from the system clock.
Definition Math.cpp:654
Vec3 * newVec3(float x=0.f, float y=0.f, float z=0.f)
Allocates a Vec3. @ownership Caller deletes.
Definition Math.cpp:142
float ridged3(float x, float y, float z, int octaves=4, float lacunarity=2.f, float gain=0.5f) const
3D ridged multifractal noise.
Definition Math.cpp:742
uint32_t getRandomSeed() const
Current RNG seed value.
Definition Math.cpp:661
float bezierCubic(float t, float p0, float p1, float p2, float p3) const
1D cubic Bezier at t in [0,1].
Definition Math.cpp:795
float gain(float t, float g) const
Schlick gain shaping of t in [0,1].
Definition Math.cpp:318
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].
Definition Math.cpp:643
float ridged2(float x, float y, int octaves=4, float lacunarity=2.f, float gain=0.5f) const
2D ridged multifractal noise.
Definition Math.cpp:726
float cartesianRadius(float x, float y) const
Length of (x,y).
Definition Math.cpp:426
float pingPong(float t, float length) const
Triangle-wave ping-pong of t over [0, length].
Definition Math.cpp:209
float hash1(float x) const
Deterministic 1D hash mapped to [0,1].
Definition Math.cpp:685
float distance2(float x1, float y1, float x2, float y2) const
2D distance between two points.
Definition Math.cpp:366
float bias(float t, float b) const
Schlick bias/gain — shape [0,1] distributions (procgen falloff).
Definition Math.cpp:311
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.
Definition Math.cpp:499
float distance3(float x1, float y1, float z1, float x2, float y2, float z2) const
3D distance between two points.
Definition Math.cpp:370
void setRandomSeed(uint32_t seed)
Sets the module RNG seed.
Definition Math.cpp:649
float length2(float x, float y) const
2D vector length from components.
Definition Math.cpp:361
float radToDeg(float rad) const
Radians to degrees.
Definition Math.cpp:184
float inverseLerp(float a, float b, float x) const
Linear interpolation between a and b by t.
Definition Math.cpp:300
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).
Definition Math.cpp:459
float remap(float x, float inMin, float inMax, float outMin, float outMax) const
Maps x from [inMin,inMax] into [outMin,outMax].
Definition Math.cpp:177
Mat4 * newMat4RotationZ(float radians)
Allocates a Z-rotation Mat4 (radians). @ownership Caller deletes.
Definition Math.cpp:158
Vec2 * newVec2(float x=0.f, float y=0.f)
Allocates a Vec2. @ownership Caller deletes.
Definition Math.cpp:141
float randomGaussian(float mean, float stddev)
Box-Muller Gaussian (mean, stddev).
Definition Math.cpp:680
float lerpAngle(float a, float b, float t) const
Shortest-path angle interpolation.
Definition Math.cpp:386
Vec2 * steeringArrive2(float x, float y, float targetX, float targetY, float maxSpeed, float slowRadius, float stopRadius) const
Creates a 2D arrive velocity. @ownership owned @lifetime Caller deletes the result.
Definition Math.cpp:239
float bezierCubic2X(float t, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) const
X of a 2D cubic Bezier at t.
Definition Math.cpp:813
float fbm3(float x, float y, float z, int octaves=4, float lacunarity=2.f, float gain=0.5f) const
3D fractal Brownian motion.
Definition Math.cpp:713
float dot2(float x1, float y1, float x2, float y2) const
2D dot product of two vectors.
Definition Math.cpp:374
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...
Definition Math.cpp:481
float polarY(float radius, float radians) const
Y of polar (radius, radians).
Definition Math.cpp:425
bool pointInRect(float px, float py, float rx, float ry, float rw, float rh) const
True if point is inside or on the axis-aligned rect.
Definition Math.cpp:434
float lerp(float a, float b, float t) const
Linear interpolation between a and b by t.
Definition Math.cpp:169
float quantize(float x, float stepSize) const
Quantizes x to multiples of stepSize.
Definition Math.cpp:351
bool circlesOverlap(float x1, float y1, float r1, float x2, float y2, float r2) const
True if two circles overlap.
Definition Math.cpp:438
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....
Definition Math.cpp:700
float raycastSphere(float ox, float oy, float oz, float dx, float dy, float dz, float cx, float cy, float cz, float radius) const
Ray vs sphere; parametric t >= 0 on hit, else -1.
Definition Math.cpp:577
int randomInt(int min, int maxInclusive)
Uniform inclusive integer in [min, maxInclusive].
Definition Math.cpp:674
float hash3(float x, float y, float z) const
Deterministic 3D hash mapped to [0,1].
Definition Math.cpp:687
2D float vector (script-facing math module value).
Definition Vec2.h:10
Vec2 * sub(const Vec2 *other) const
Definition Vec2.cpp:47
Vec2 * normalized() const
Definition Vec2.cpp:17
float cross(const Vec2 *other) const
Cross product with other.
Definition Vec2.cpp:28
float dot(const Vec2 *other) const
Atan2 angle in radians.
Definition Vec2.cpp:23
Vec2 * scale(float s) const
Definition Vec2.cpp:52
float angle() const
Atan2 angle in radians.
Definition Vec2.cpp:40
float distanceTo(const Vec2 *other) const
Euclidean distance to other.
Definition Vec2.cpp:33
void setX(float x)
Sets the X component.
Definition Vec2.h:21
float length() const
Magnitude (and squared magnitude).
Definition Vec2.h:31
void setY(float y)
Sets the Y component.
Definition Vec2.h:23
float lengthSquared() const
Squared Euclidean magnitude.
Definition Vec2.h:33
float getY() const
Y component.
Definition Vec2.h:19
float getX() const
Component accessors.
Definition Vec2.h:17
Vec2 * clone() const
Copies this vector.
Definition Vec2.cpp:59
void set(float x, float y)
Sets both components.
Definition Vec2.h:25
Vec2 * add(const Vec2 *other) const
Arithmetic helpers returning new (caller-owned) vectors.
Definition Vec2.cpp:42
void normalize()
Normalizes in place / returns a normalized copy.
Definition Vec2.cpp:9
Vec2 * lerpTo(const Vec2 *other, float t) const
Linear interpolation to other at t in [0,1].
Definition Vec2.cpp:54
3D float vector (script-facing math module value).
Definition Vec3.h:10
Vec3 * normalized() const
Definition Vec3.cpp:18
float getY() const
Y component.
Definition Vec3.h:19
Vec3 * cross(const Vec3 *other) const
Definition Vec3.cpp:29
Vec3 * clone() const
Copies this vector.
Definition Vec3.cpp:61
Vec3 * sub(const Vec3 *other) const
Definition Vec3.cpp:48
float getZ() const
Z component.
Definition Vec3.h:21
void setX(float x)
Sets the X component.
Definition Vec3.h:23
Vec3 * lerpTo(const Vec3 *other, float t) const
Linear interpolation to other at t in [0,1].
Definition Vec3.cpp:55
float length() const
Magnitude (and squared magnitude).
Definition Vec3.h:36
Vec3 * scale(float s) const
Definition Vec3.cpp:53
Vec3 * add(const Vec3 *other) const
Arithmetic helpers returning new (caller-owned) vectors.
Definition Vec3.cpp:43
void setY(float y)
Sets the Y component.
Definition Vec3.h:25
float dot(const Vec3 *other) const
Dot/cross product and distance.
Definition Vec3.cpp:24
float distanceTo(const Vec3 *other) const
Euclidean distance to other.
Definition Vec3.cpp:35
float lengthSquared() const
Squared Euclidean magnitude.
Definition Vec3.h:38
void normalize()
Normalizes in place / returns a normalized copy.
Definition Vec3.cpp:9
void setZ(float z)
Sets the Z component.
Definition Vec3.h:27
float getX() const
Component accessors.
Definition Vec3.h:17
void set(float x, float y, float z)
Sets all three components.
Definition Vec3.h:29
Vector2 arrive(Vector2 position, Vector2 target, float maxSpeed, float slowRadius, float stopRadius)
Slows toward target inside slowRadius and stops inside stopRadius.
Definition Steering.cpp:161
Vector2 seek(Vector2 position, Vector2 target, float maxSpeed)
Returns a velocity of at most maxSpeed directed from position to target.
Definition Steering.cpp:149
Vector2 avoid(Vector2 position, Vector2 velocity, Vector2 obstacle, float obstacleRadius, float lookAhead, float maxAcceleration)
Computes avoidance acceleration away from a predicted obstacle overlap.
Definition Steering.cpp:185
Vector2 separation(Vector2 position, std::span< const Vector2 > neighbors, float radius, float maxAcceleration)
Computes bounded separation acceleration from a borrowed neighbor snapshot.
Definition Steering.cpp:169
Vector2 flee(Vector2 position, Vector2 target, float maxSpeed)
Returns a velocity of at most maxSpeed directed away from target.
Definition Steering.cpp:155
int pathTarget(Vector2 position, std::span< const Vector2 > points, int current, float tolerance)
Selects the current path point, advancing across points within tolerance.
Definition Steering.cpp:177
Stateless steering vector algorithms shared by 2D and 3D callers.
Definition Steering.h:17
bool consumed
Definition Graphics.cpp:184