summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/GameDraw.cpp6
-rw-r--r--src/geom.zig194
2 files changed, 43 insertions, 157 deletions
diff --git a/src/GameDraw.cpp b/src/GameDraw.cpp
index f59bb69..12ac309 100644
--- a/src/GameDraw.cpp
+++ b/src/GameDraw.cpp
@@ -437,10 +437,10 @@ void Game::DrawGLScene(void)
 			glDisable(GL_CLIP_PLANE0);
 		glPopMatrix();
 
-		GLfloat frustum[6][4];
-		GLfloat projection[16];
+		alignas(16) GLfloat frustum[6][4];
+		alignas(16) GLfloat projection[16];
 		glGetFloatv(GL_PROJECTION_MATRIX, projection);
-		GLfloat model_view[16];
+		alignas(16) GLfloat model_view[16];
 		glGetFloatv(GL_MODELVIEW_MATRIX, model_view);
 		setFrustum(frustum, projection, model_view);
 
diff --git a/src/geom.zig b/src/geom.zig
index af6bd21..80cf1db 100644
--- a/src/geom.zig
+++ b/src/geom.zig
@@ -53,20 +53,20 @@ export fn crossProduct(u: XYZ, v: XYZ) XYZ {
     };
 }
 
-inline fn splat(x: f32) @Vector(3, f32) {
+inline fn splat(comptime n: comptime_int, x: anytype) @Vector(n, @TypeOf(x)) {
     return @splat(x);
 }
 
 export fn normalize(v: XYZ) XYZ {
     const u: @Vector(3, f32) = @bitCast(v);
     const d = norm(u);
-    return if (d == 0) v else @bitCast(u / splat(d));
+    return if (d == 0) v else @bitCast(u / splat(3, d));
 }
 
 export fn reflect(v: XYZ, n: XYZ) XYZ {
     const u: @Vector(3, f32) = @bitCast(v);
     const m: @Vector(3, f32) = @bitCast(n);
-    return @bitCast(u - m * splat(dot(u, m) * 2));
+    return @bitCast(u - m * splat(3, dot(u, m) * 2));
 }
 
 fn rotate2d(i: *f32, j: *f32, a: f32) void {
@@ -92,174 +92,60 @@ export fn segmentIntersectsSphere(a: XYZ, b: XYZ, i: XYZ, r: f32) bool {
     const q: @Vector(3, f32) = @bitCast(b);
     const c: @Vector(3, f32) = @bitCast(i);
 
-    if (@reduce(.Or, @max(p, q) < c - splat(r))) return false;
-    if (@reduce(.Or, @min(p, q) > c + splat(r))) return false;
+    if (@reduce(.Or, @max(p, q) < c - splat(3, r))) return false;
+    if (@reduce(.Or, @min(p, q) > c + splat(3, r))) return false;
     // https://en.wikipedia.org/wiki/Line–sphere_intersection
     const d = q - p; // line's direction
-    const u = d / splat(norm(d)); // unit vector
+    const u = d / splat(3, norm(d)); // unit vector
     return sqr(dot(u, (p - c))) >= @reduce(.Add, sqr(p - c)) - sqr(r);
 }
 
-export fn setFrustum(frustum: [*][4]f32, p: [*]const f32,
-                     mv: [*] const f32) void {
-    const clip = [16]f32{
-        mv[0] * p[0] + mv[1] * p[4] + mv[2] * p[8] + mv[3] * p[12],
-        mv[0] * p[1] + mv[1] * p[5] + mv[2] * p[9] + mv[3] * p[13],
-        mv[0] * p[2] + mv[1] * p[6] + mv[2] * p[10] + mv[3] * p[14],
-        mv[0] * p[3] + mv[1] * p[7] + mv[2] * p[11] + mv[3] * p[15],
-        mv[4] * p[0] + mv[5] * p[4] + mv[6] * p[8] + mv[7] * p[12],
-        mv[4] * p[1] + mv[5] * p[5] + mv[6] * p[9] + mv[7] * p[13],
-        mv[4] * p[2] + mv[5] * p[6] + mv[6] * p[10] + mv[7] * p[14],
-        mv[4] * p[3] + mv[5] * p[7] + mv[6] * p[11] + mv[7] * p[15],
-        mv[8] * p[0] + mv[9] * p[4] + mv[10] * p[8] + mv[11] * p[12],
-        mv[8] * p[1] + mv[9] * p[5] + mv[10] * p[9] + mv[11] * p[13],
-        mv[8] * p[2] + mv[9] * p[6] + mv[10] * p[10] + mv[11] * p[14],
-        mv[8] * p[3] + mv[9] * p[7] + mv[10] * p[11] + mv[11] * p[15],
-        mv[12] * p[0] + mv[13] * p[4] + mv[14] * p[8] + mv[15] * p[12],
-        mv[12] * p[1] + mv[13] * p[5] + mv[14] * p[9] + mv[15] * p[13],
-        mv[12] * p[2] + mv[13] * p[6] + mv[14] * p[10] + mv[15] * p[14],
-        mv[12] * p[3] + mv[13] * p[7] + mv[14] * p[11] + mv[15] * p[15],
-    };
-
-    // Right plane
-    frustum[0][0] = clip[3] - clip[0];
-    frustum[0][1] = clip[7] - clip[4];
-    frustum[0][2] = clip[11] - clip[8];
-    frustum[0][3] = clip[15] - clip[12];
-
-    // Left plane
-    frustum[1][0] = clip[3] + clip[0];
-    frustum[1][1] = clip[7] + clip[4];
-    frustum[1][2] = clip[11] + clip[8];
-    frustum[1][3] = clip[15] + clip[12];
-
-    // Bottom plane
-    frustum[2][0] = clip[3] + clip[1];
-    frustum[2][1] = clip[7] + clip[5];
-    frustum[2][2] = clip[11] + clip[9];
-    frustum[2][3] = clip[15] + clip[13];
-
-    // Top plane
-    frustum[3][0] = clip[3] - clip[1];
-    frustum[3][1] = clip[7] - clip[5];
-    frustum[3][2] = clip[11] - clip[9];
-    frustum[3][3] = clip[15] - clip[13];
-
-    // Far plane
-    frustum[4][0] = clip[3] - clip[2];
-    frustum[4][1] = clip[7] - clip[6];
-    frustum[4][2] = clip[11] - clip[10];
-    frustum[4][3] = clip[15] - clip[14];
-
-    // Near plane
-    frustum[5][0] = clip[3] + clip[2];
-    frustum[5][1] = clip[7] + clip[6];
-    frustum[5][2] = clip[11] + clip[10];
-    frustum[5][3] = clip[15] + clip[14];
-
-    // normalize the right plane
-    var t: f32 = undefined;
-    t = @sqrt(frustum[0][0]*frustum[0][0]
-        + frustum[0][1]*frustum[0][1]
-        + frustum[0][2]*frustum[0][2]);
-    frustum[0][0] /= t;
-    frustum[0][1] /= t;
-    frustum[0][2] /= t;
-    frustum[0][3] /= t;
-
-    // calculate left plane
-    frustum[1][0] = clip[3] + clip[0];
-    frustum[1][1] = clip[7] + clip[4];
-    frustum[1][2] = clip[11] + clip[ 8];
-    frustum[1][3] = clip[15] + clip[12];
-
-    // normalize the left plane
-    t = @sqrt(frustum[1][0]*frustum[1][0]
-        + frustum[1][1]*frustum[1][1]
-        + frustum[1][2]*frustum[1][2]);
-    frustum[1][0] /= t;
-    frustum[1][1] /= t;
-    frustum[1][2] /= t;
-    frustum[1][3] /= t;
-
-    // calculate the bottom plane
-    frustum[2][0] = clip[3] + clip[1];
-    frustum[2][1] = clip[7] + clip[5];
-    frustum[2][2] = clip[11] + clip[9];
-    frustum[2][3] = clip[15] + clip[13];
-
-    // normalize the bottom plane
-    t = @sqrt(frustum[2][0]*frustum[2][0]
-        + frustum[2][1]*frustum[2][1]
-        + frustum[2][2]*frustum[2][2]);
-    frustum[2][0] /= t;
-    frustum[2][1] /= t;
-    frustum[2][2] /= t;
-    frustum[2][3] /= t;
-
-    // calculate the top plane
-    frustum[3][0] = clip[3] - clip[1];
-    frustum[3][1] = clip[7] - clip[5];
-    frustum[3][2] = clip[11] - clip[9];
-    frustum[3][3] = clip[15] - clip[13];
-
-    // normalize the top plane
-    t = @sqrt(frustum[3][0]*frustum[3][0]
-        + frustum[3][1]*frustum[3][1]
-        + frustum[3][2]*frustum[3][2]);
-    frustum[3][0] /= t;
-    frustum[3][1] /= t;
-    frustum[3][2] /= t;
-    frustum[3][3] /= t;
-
-    // calculate the far plane
-    frustum[4][0] = clip[3] - clip[2];
-    frustum[4][1] = clip[7] - clip[6];
-    frustum[4][2] = clip[11] - clip[10];
-    frustum[4][3] = clip[15] - clip[14];
-
-    // normalize the far plane
-    t = @sqrt(frustum[4][0]*frustum[4][0]
-        + frustum[4][1]*frustum[4][1]
-        + frustum[4][2]*frustum[4][2]);
-    frustum[4][0] /= t;
-    frustum[4][1] /= t;
-    frustum[4][2] /= t;
-    frustum[4][3] /= t;
-
-    // calculate the near plane
-    frustum[5][0] = clip[3] + clip[2];
-    frustum[5][1] = clip[7] + clip[6];
-    frustum[5][2] = clip[11] + clip[10];
-    frustum[5][3] = clip[15] + clip[14];
+fn transpose(comptime n: comptime_int, m: [n]@Vector(n, f32)) @TypeOf(m) {
+    const flat: @Vector(sqr(n), f32) = @bitCast(m);
+    return @bitCast(@shuffle(f32, flat, undefined, blk: {
+        var v: @Vector(sqr(n), i32) = undefined;
+        for (0..n) |i| {
+            for (0..n) |j|
+                v[i * n + j] = @intCast(j * n + i);
+        }
+        break :blk v;
+    }));
+}
 
-    // normalize the near plane
-    t = @sqrt(frustum[5][0]*frustum[5][0]
-        + frustum[5][1]*frustum[5][1]
-        + frustum[5][2]*frustum[5][2]);
-    frustum[5][0] /= t;
-    frustum[5][1] /= t;
-    frustum[5][2] /= t;
-    frustum[5][3] /= t;
+export fn setFrustum(frustum: *[6]@Vector(4, f32),
+                     p: *const [4]@Vector(4, f32),
+                     mv: *const [4]@Vector(4, f32)) void {
+    var mvp: [4]@Vector(4, f32) = undefined;
+    for (&mvp, transpose(4, p.*)) |*u, p_col| {
+        for (mv, 0..4) |mv_row, i|
+            u[i] = dot(p_col, mv_row);
+    } // matrix multiplication
+
+    frustum.* = .{
+        mvp[3] - mvp[0], mvp[3] + mvp[0], // right & left planes
+        mvp[3] - mvp[1], mvp[3] + mvp[1], // bottom & top planes
+        mvp[3] - mvp[2], mvp[3] + mvp[2], // far & near planes
+    };
+    for (frustum) |*plane| // normalize
+        plane.* /= @splat(norm(plane.* * @Vector(4, f32){ 1, 1, 1, 0 }));
 }
 
-export fn cubeInFrustum(frustum: [*][4]f32,
+export fn cubeInFrustum(frustum: *const [6]@Vector(4, f32),
                         x: f32, y: f32, z: f32, size: f32) bool {
     const delta = [_]f32{ -size, size };
-    loop: for (0..6) |i| {
+    loop: for (frustum) |*plane| {
         for (delta) |dx| for (delta) |dy| for (delta) |dz|
-            if (frustum[i][0] * (x + dx) + frustum[i][1] * (y + dy)
-                + frustum[i][2] * (z + dz) + frustum[i][3] > 0) continue :loop;
+            if (dot(plane.*, @Vector(4, f32){ x + dx, y + dy, z + dz, 1 }) > 0)
+                continue :loop;
         return false;
     }
     return true;
 }
 
-export fn sphereInFrustum(frustum: [*][4]f32,
+export fn sphereInFrustum(frustum: *const [6]@Vector(4, f32),
                           x: f32, y: f32, z: f32, r: f32) bool {
-    for (0..6) |i|
-        if (frustum[i][0] * x + frustum[i][1] * y
-            + frustum[i][2] * z + frustum[i][3] <= -r)
+    for (frustum) |*plane|
+        if (dot(plane.*, @Vector(4, f32){ x, y, z, 1 }) <= -r)
             return false;
     return true;
 }