Skip to content

Instantly share code, notes, and snippets.

@aaronfinke
Last active October 16, 2022 16:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aaronfinke/ae23f921faa537941c34c9e1eb353af7 to your computer and use it in GitHub Desktop.
Save aaronfinke/ae23f921faa537941c34c9e1eb353af7 to your computer and use it in GitHub Desktop.
spinny cube rust
use std::io::{self, stdin, stdout, Read, Write};
use std::{
thread::{self, sleep},
time::{Duration, Instant},
};
use libm::{sin,cos};
use iter_num_tools::arange;
const cubeWidth: f64 = 15.;
const width: usize = 169;
const height: usize = 48;
const backgroundASCIICode: char = ' ';
const incrementSpeed: f64 = 0.5;
const distanceFromCam: i32 = 60;
const K1: f64 = 40.;
fn main() {
let mut zBuffer: [f64; width * height * 4] = [0.; width * height * 4];
let mut buffer: [char; width * height] = [' '; width * height];
let (mut A, mut B, mut C): (f64, f64, f64) = (0.0, 0.0, 0.0);
print!("\x1b[2J");
io::stdout().flush().unwrap();
let mut sum_dur = Duration::new(0, 0);
let mut avg_dur = Duration::new(0, 0);
let mut counter: u32 = 1;
loop {
let start = Instant::now();
zBuffer = [0.; width * height * 4];
buffer = [backgroundASCIICode; width * height];
for cubeX in arange(-cubeWidth..cubeWidth, incrementSpeed) {
for cubeY in arange(-cubeWidth..cubeWidth, incrementSpeed) {
calculateForSurface(cubeX, cubeY, -cubeWidth, A, B, C, '.', &mut zBuffer, &mut buffer);
calculateForSurface(cubeWidth, cubeY, cubeX, A, B, C, '$', &mut zBuffer, &mut buffer);
calculateForSurface(-cubeWidth, cubeY, -cubeX, A, B, C, '~', &mut zBuffer, &mut buffer);
calculateForSurface(-cubeX, cubeY, cubeWidth, A, B, C, '#', &mut zBuffer, &mut buffer);
calculateForSurface(cubeX, -cubeWidth, -cubeY, A, B, C, ';', &mut zBuffer, &mut buffer);
calculateForSurface(cubeX, cubeWidth, cubeY, A, B, C, '-', &mut zBuffer, &mut buffer);
}
}
let t1 = start.elapsed();
print!("\x1b[H");
for k in 0..(width * height) {
match k % width {
0 => println!(""),
_ => print!("{}",buffer[k]),
};
}
A += 0.05;
B -= 0.05;
C += 0.01;
println!("");
sum_dur = sum_dur.checked_add(t1).unwrap();
avg_dur = sum_dur.div_f64(counter as f64);
println!("\x1b[93;1mAvg Calc Time: {:?} \x1b[0m",avg_dur);
println!("\x1b[93;1mFrame number: {:?} \x1b[0m", counter);
// println!("Time: {:?}",t1);
std::io::stdout().flush().unwrap();
sleep(Duration::from_micros(50000));
counter += 1;
}
}
// Calculations with base library
fn calculateX(i: f64, j: f64, k: f64, A: f64, B: f64, C: f64) -> f64{
return j * A.sin() * B.sin() * C.cos() - k * A.cos() * B.sin() * C.cos() +
j * A.cos() * C.sin() + k * A.sin() * C.sin() + i * B.cos() * C.cos();
}
fn calculateY(i: f64, j: f64, k: f64, A: f64, B: f64, C: f64) -> f64 {
return j * A.cos() * C.cos() + k * A.sin() * C.cos() -
j * A.sin() * B.sin() * C.sin() + k * A.cos() * B.sin() * C.sin() -
i * B.cos() * C.sin();
}
fn calculateZ(i: f64, j: f64, k: f64, A: f64, B: f64, C: f64) -> f64{
return k * A.cos() * B.cos() - j * A.sin() * B.cos() + i * B.sin();
}
//Calculations with libm
// fn calculateX(i: f64, j: f64, k: f64, A: f64, B: f64, C: f64) -> f64{
// 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: f64, j: f64, k: f64, A: f64, B: f64, C: f64) -> f64 {
// 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: f64, j: f64, k: f64, A: f64, B: f64, C: f64) -> f64{
// return k * cos(A) * cos(B) - j * sin(A) * cos(B) + i * sin(B);
// }
fn calculateForSurface(cubeX: f64, cubeY: f64, cubeZ: f64,
A: f64, B: f64, C: f64, ch: char,
zBuffer: &mut [f64; width * height * 4],
buffer: &mut [char; width * height] ) {
let x = calculateX(cubeX, cubeY, cubeZ, A, B, C);
let y = calculateY(cubeX, cubeY, cubeZ, A, B, C);
let z = calculateZ(cubeX, cubeY, cubeZ, A, B, C) + distanceFromCam as f64;
let ooz = 1. / z;
let xp: i32 = ((width / 2) as f64 - 2. * cubeWidth + K1 * ooz * x * 2.) as i32;
let yp: i32 = ((height / 2) as f64 + K1 * ooz * y) as i32;
let idx: i32 = xp + yp * (width as i32);
if idx >= 0 && idx < (width * height) as i32 {
if ooz > zBuffer[idx as usize] {
zBuffer[idx as usize] = ooz;
buffer[idx as usize] = ch;
}
};
}
fn pause() {
let mut stdout = stdout();
stdout.write(b"Press Enter to continue...").unwrap();
stdout.flush().unwrap();
stdin().read(&mut [0]).unwrap();
}
// Base library
// Avg Calc Time: 345.194µs
// Frame number: 1003
// libm
// Avg Calc Time: 8.765695ms
// Frame number: 1000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment