Skip to content

Instantly share code, notes, and snippets.

@peterhellberg
Created July 3, 2025 06:23
Show Gist options
  • Save peterhellberg/5381e60fb237a163fe84935982e0bfb7 to your computer and use it in GitHub Desktop.
Save peterhellberg/5381e60fb237a163fe84935982e0bfb7 to your computer and use it in GitHub Desktop.
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));
}
}
@peterhellberg
Copy link
Author

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

Screenshot from 2025-07-03 08-24-06

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment