Created
July 3, 2025 06:23
-
-
Save peterhellberg/5381e60fb237a163fe84935982e0bfb7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const mem = std.mem; | |
const sin = std.math.sin; | |
const cos = std.math.cos; | |
const signedRemainder = std.zig.c_translation.signedRemainder; | |
pub const object_size = std.zig.c_builtins.__builtin_object_size; | |
pub const memset_chk = std.zig.c_builtins.__builtin___memset_chk; | |
pub const useconds_t = c_uint; | |
pub extern fn printf([*c]const u8, ...) c_int; | |
pub extern fn putchar(c_int) c_int; | |
pub extern fn usleep(useconds_t) c_int; | |
var A: f32 = 0; | |
var B: f32 = 0; | |
var C: f32 = 0; | |
var cubeWidth: f32 = 20; | |
var width: c_int = 160; | |
var height: c_int = 44; | |
var zBuffer: [7040]f32 = mem.zeroes([7040]f32); | |
var buffer: [7040]u8 = mem.zeroes([7040]u8); | |
var backgroundASCIICode: c_int = ' '; | |
var distanceFromCam: f32 = 100; | |
var horizontalOffset: f32 = 0; | |
var K1: f32 = 40; | |
var incrementSpeed: f32 = 0.6; | |
var ooz: f32 = 0; | |
var xp: c_int = 0; | |
var yp: c_int = 0; | |
var idx: c_int = 0; | |
fn calculateX(i: f32, j: f32, k: f32) f32 { | |
return j * sin(A) * sin(B) * cos(C) - k * cos(A) * sin(B) * cos(C) + j * cos(A) * sin(C) + k * sin(A) * sin(C) + i * cos(B) * cos(C); | |
} | |
fn calculateY(i: f32, j: f32, k: f32) f32 { | |
return j * cos(A) * cos(C) + k * sin(A) * cos(C) - j * sin(A) * sin(B) * sin(C) + k * cos(A) * sin(B) * sin(C) - i * cos(B) * sin(C); | |
} | |
fn calculateZ(i: f32, j: f32, k: f32) f32 { | |
return k * cos(A) * cos(B) - j * sin(A) * cos(B) + i * sin(B); | |
} | |
fn calculateForSurface(cubeX: f32, cubeY: f32, cubeZ: f32, ch: c_int) void { | |
const x = calculateX(cubeX, cubeY, cubeZ); | |
const y = calculateY(cubeX, cubeY, cubeZ); | |
const z = calculateZ(cubeX, cubeY, cubeZ) + distanceFromCam; | |
ooz = 1 / z; | |
xp = @intFromFloat((@as(f32, @floatFromInt(@divTrunc(width, 2))) + horizontalOffset) + (((K1 * ooz) * x) * 2)); | |
yp = @intFromFloat(@as(f32, @floatFromInt(@divTrunc(height, 2))) + ((K1 * ooz) * y)); | |
idx = xp + (yp * width); | |
if ((idx >= 0) and (idx < (width * height))) { | |
const i = @as(c_uint, @intCast(idx)); | |
if (ooz > zBuffer[i]) { | |
zBuffer[i] = ooz; | |
buffer[i] = @as(u8, @bitCast(@as(i8, @truncate(ch)))); | |
} | |
} | |
} | |
pub fn main() void { | |
_ = printf("\x1b[2J"); | |
while (true) { | |
_ = memset_chk(@as(?*anyopaque, @ptrCast(@as([*c]u8, @ptrCast(@alignCast(&buffer[0]))))), backgroundASCIICode, @as(c_ulong, @bitCast(@as(c_long, width * height))), object_size(@as(?*const anyopaque, @ptrCast(@as([*c]u8, @ptrCast(@alignCast(&buffer[0]))))), 0)); | |
_ = memset_chk(@as(?*anyopaque, @ptrCast(@as([*c]f32, @ptrCast(@alignCast(&zBuffer[0]))))), 0, @as(c_ulong, @bitCast(@as(c_long, (width * height) * 4))), object_size(@as(?*const anyopaque, @ptrCast(@as([*c]f32, @ptrCast(@alignCast(&zBuffer[0]))))), 0)); | |
cubeWidth = 20; | |
horizontalOffset = -2 * cubeWidth; | |
{ | |
var cubeX: f32 = -cubeWidth; | |
while (cubeX < cubeWidth) : (cubeX += incrementSpeed) { | |
{ | |
var cubeY: f32 = -cubeWidth; | |
while (cubeY < cubeWidth) : (cubeY += incrementSpeed) { | |
calculateForSurface(cubeX, cubeY, -cubeWidth, '@'); | |
calculateForSurface(cubeWidth, cubeY, cubeX, '$'); | |
calculateForSurface(-cubeWidth, cubeY, -cubeX, '~'); | |
calculateForSurface(-cubeX, cubeY, cubeWidth, '#'); | |
calculateForSurface(cubeX, -cubeWidth, -cubeY, ';'); | |
calculateForSurface(cubeX, cubeWidth, cubeY, '+'); | |
} | |
} | |
} | |
} | |
cubeWidth = 10; | |
horizontalOffset = 1 * cubeWidth; | |
{ | |
var cubeX: f32 = -cubeWidth; | |
while (cubeX < cubeWidth) : (cubeX += incrementSpeed) { | |
{ | |
var cubeY: f32 = -cubeWidth; | |
while (cubeY < cubeWidth) : (cubeY += incrementSpeed) { | |
calculateForSurface(cubeX, cubeY, -cubeWidth, '@'); | |
calculateForSurface(cubeWidth, cubeY, cubeX, '$'); | |
calculateForSurface(-cubeWidth, cubeY, -cubeX, '~'); | |
calculateForSurface(-cubeX, cubeY, cubeWidth, '#'); | |
calculateForSurface(cubeX, -cubeWidth, -cubeY, ';'); | |
calculateForSurface(cubeX, cubeWidth, cubeY, '+'); | |
} | |
} | |
} | |
} | |
cubeWidth = 5; | |
horizontalOffset = 8 * cubeWidth; | |
{ | |
var cubeX: f32 = -cubeWidth; | |
while (cubeX < cubeWidth) : (cubeX += incrementSpeed) { | |
{ | |
var cubeY: f32 = -cubeWidth; | |
while (cubeY < cubeWidth) : (cubeY += incrementSpeed) { | |
calculateForSurface(cubeX, cubeY, -cubeWidth, '@'); | |
calculateForSurface(cubeWidth, cubeY, cubeX, '$'); | |
calculateForSurface(-cubeWidth, cubeY, -cubeX, '~'); | |
calculateForSurface(-cubeX, cubeY, cubeWidth, '#'); | |
calculateForSurface(cubeX, -cubeWidth, -cubeY, ';'); | |
calculateForSurface(cubeX, cubeWidth, cubeY, '+'); | |
} | |
} | |
} | |
} | |
_ = printf("\x1b[H"); | |
{ | |
var k: c_int = 0; | |
while (k < (width * height)) : (k += 1) { | |
_ = putchar(if (signedRemainder(k, width) != 0) @as(c_int, @bitCast(@as(c_uint, buffer[@as(c_uint, @intCast(k))]))) else 10); | |
} | |
} | |
A += 0.05; | |
B += 0.03; | |
C += 0.01; | |
_ = usleep(@as(useconds_t, 8000 * 2)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based on https://github.com/servetgulnaroglu/cube.c/blob/master/cube.c
Initially translated using
zig translate-c cube.c > cube.zig
and then manually cleaned up.zig build-exe -O ReleaseSmall -lc cube.zig