-
-
Save aaronfinke/ae23f921faa537941c34c9e1eb353af7 to your computer and use it in GitHub Desktop.
spinny cube rust
This file contains 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
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