From d1c5055303fa2cb4bb2095c6173460079d1cd34e Mon Sep 17 00:00:00 2001 From: sneeker Date: Thu, 30 Jun 2022 11:37:33 +0000 Subject: [PATCH] feat(examples): add vector maths and an xorshift RNG vec3 operations and a per-thread random stream, the leaf library everything else in the example depends on. --- examples/raytracer/src/math/rng.c | 50 ++++++++++++++++++++++++++++++ examples/raytracer/src/math/vec3.c | 33 ++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 examples/raytracer/src/math/rng.c create mode 100644 examples/raytracer/src/math/vec3.c diff --git a/examples/raytracer/src/math/rng.c b/examples/raytracer/src/math/rng.c new file mode 100644 index 0000000..1939acb --- /dev/null +++ b/examples/raytracer/src/math/rng.c @@ -0,0 +1,50 @@ +#include "rt.h" +#include + +static unsigned long long splitmix(unsigned long long *x) { + unsigned long long z = (*x += 0x9E3779B97F4A7C15ULL); + z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL; + z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL; + return z ^ (z >> 31); +} + +static unsigned long long rotl(unsigned long long x, int k) { + return (x << k) | (x >> (64 - k)); +} + +void rng_seed(rng *r, unsigned long long seed) { + unsigned long long s = seed ? seed : 0x2545F4914F6CDD1DULL; + r->s0 = splitmix(&s); + r->s1 = splitmix(&s); +} + +static unsigned long long rng_next(rng *r) { + unsigned long long s0 = r->s0, s1 = r->s1; + unsigned long long result = s0 + s1; + s1 ^= s0; + r->s0 = rotl(s0, 55) ^ s1 ^ (s1 << 14); + r->s1 = rotl(s1, 36); + return result; +} + +double rng_unit(rng *r) { + /* 53 significant bits, the most a double holds exactly. */ + return (double)(rng_next(r) >> 11) * (1.0 / 9007199254740992.0); +} + +double rng_range(rng *r, double lo, double hi) { return lo + (hi - lo) * rng_unit(r); } + +vec3 rng_in_sphere(rng *r) { + for (int i = 0; i < 64; i++) { + vec3 p = v3(rng_range(r, -1.0, 1.0), rng_range(r, -1.0, 1.0), rng_range(r, -1.0, 1.0)); + if (v3len2(p) < 1.0) return p; + } + return v3(0.0, 0.0, 0.0); +} + +vec3 rng_unit_vector(rng *r) { + double z = rng_range(r, -1.0, 1.0); + double a = rng_range(r, 0.0, 6.283185307179586); + double s = sqrt(1.0 - z * z); + return v3(s * cos(a), s * sin(a), z); +} diff --git a/examples/raytracer/src/math/vec3.c b/examples/raytracer/src/math/vec3.c new file mode 100644 index 0000000..5ac7da3 --- /dev/null +++ b/examples/raytracer/src/math/vec3.c @@ -0,0 +1,33 @@ +#include "rt.h" +#include + +vec3 v3(double x, double y, double z) { + vec3 v = {x, y, z}; + return v; +} + +vec3 v3add(vec3 a, vec3 b) { return v3(a.x + b.x, a.y + b.y, a.z + b.z); } +vec3 v3sub(vec3 a, vec3 b) { return v3(a.x - b.x, a.y - b.y, a.z - b.z); } +vec3 v3mul(vec3 a, vec3 b) { return v3(a.x * b.x, a.y * b.y, a.z * b.z); } +vec3 v3scale(vec3 a, double t) { return v3(a.x * t, a.y * t, a.z * t); } +vec3 v3neg(vec3 a) { return v3(-a.x, -a.y, -a.z); } + +double v3dot(vec3 a, vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } + +vec3 v3cross(vec3 a, vec3 b) { + return v3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); +} + +double v3len2(vec3 a) { return v3dot(a, a); } +double v3len(vec3 a) { return sqrt(v3len2(a)); } + +vec3 v3norm(vec3 a) { + double n = v3len(a); + return n > 0.0 ? v3scale(a, 1.0 / n) : a; +} + +vec3 v3reflect(vec3 v, vec3 n) { return v3sub(v, v3scale(n, 2.0 * v3dot(v, n))); } + +vec3 v3lerp(vec3 a, vec3 b, double t) { + return v3add(v3scale(a, 1.0 - t), v3scale(b, t)); +}