diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/GameDraw.cpp | 6 | ||||
-rw-r--r-- | src/geom.zig | 194 |
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; } |