diff --git a/src/main.rs b/src/main.rs index 6e3e220..62c682f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,10 @@ mod consts { pub const SCREEN_WIDTH: usize = 1920; pub const SCREEN_HEIGHT: usize = 1080; pub const STRIDE: u32 = SCREEN_WIDTH as u32; + pub const FPS: u32 = 30; + pub const FRAME_LENGTH: f64 = 1.0 / FPS as f64; + pub const UPS: u32 = FPS; // TODO: Change + pub const UPDATE_LENGTH: f64 = 1.0 / UPS as f64; } use points::*; @@ -16,9 +20,9 @@ use render::*; use scene::*; use consts::*; -use core::f64; use std::{num::NonZeroU32, u32}; +use core::f64; use std::{num::NonZeroU32, thread, time::{Duration, Instant}, u32}; -use softbuffer::{Buffer, Context, Rect, Surface}; +use softbuffer::{Context, Rect, Surface}; use winit::{self, event_loop::EventLoop, window::Window}; fn main() { @@ -49,23 +53,37 @@ fn main() { let mut scene = vec![Object { vertices: vec![ - Point3D(0.0, f64::MAX / 2.0, 0.0), - Point3D(f64::MAX / 2.0, -f64::MAX / 2.0, 0.0), - Point3D(-f64::MAX / 2.0, -f64::MAX / 2.0, 0.0), + Point3D{x: 0.0, y: f64::MAX / 2.0, z: 0.0}, + Point3D{x: f64::MAX / 2.0, y: -f64::MAX / 2.0, z: 0.0}, + Point3D{x: -f64::MAX / 2.0, y: -f64::MAX / 2.0, z: 0.0}, ], edges: vec![ - (Point3D(0.0, f64::MAX / 2.0, 0.0), Point3D(f64::MAX / 2.0, -f64::MAX / 2.0, 0.0)), - (Point3D(f64::MAX / 2.0, -f64::MAX / 2.0, 0.0), Point3D(-f64::MAX / 2.0, -f64::MAX / 2.0, 0.0)), - (Point3D(-f64::MAX / 2.0, -f64::MAX / 2.0, 0.0), Point3D(0.0, f64::MAX / 2.0, 0.0)) + (Point3D{x: 0.0, y: f64::MAX / 2.0, z: 0.0}, Point3D{x: f64::MAX / 2.0, y: -f64::MAX / 2.0, z: 0.0}), + (Point3D{x: f64::MAX / 2.0, y: -f64::MAX / 2.0, z: 0.0}, Point3D{x: -f64::MAX / 2.0, y: -f64::MAX / 2.0, z: 0.0}), + (Point3D{x: -f64::MAX / 2.0, y: -f64::MAX / 2.0, z: 0.0}, Point3D{x: 0.0, y: f64::MAX / 2.0, z: 0.0}) ], + faces: vec![ + (Point3D{x: 0.0, y: f64::MAX / 2.0, z: 0.0}, + Point3D{x: f64::MAX / 2.0, y: -f64::MAX / 2.0, z: 0.0}, + Point3D{x: -f64::MAX / 2.0, y: -f64::MAX / 2.0, z: 0.0}) + ] }]; loop { let mut sbuffer = surface.buffer_mut().expect("Couldn't create buffer"); - // set_scene(t, &mut scene); + + let now = Instant::now(); + render(t, &scene, &mut *sbuffer); t += 1; + let elapsed = now.elapsed(); + let remaining = if Duration::from_secs_f64(UPDATE_LENGTH) > elapsed { Duration::from_secs_f64(UPDATE_LENGTH) - elapsed } else { + eprintln!("fps < {FPS}"); + Duration::ZERO + }; + thread::sleep(remaining); + sbuffer .present_with_damage(&[Rect { x: 0, diff --git a/src/points.rs b/src/points.rs index 68a1d83..c76463f 100644 --- a/src/points.rs +++ b/src/points.rs @@ -1,7 +1,11 @@ use crate::consts::*; #[derive(Debug, Clone, Copy)] -pub struct Point2D(pub f64, pub f64); +pub struct Point2D { + pub x: f64, + pub y: f64 +} + impl Point2D { pub fn to_canvas_coordinates(&self) -> Point3D { todo!(); @@ -12,19 +16,21 @@ impl Point2D { // Pythagorean formula // TODO: use hypot function f64::sqrt( - (f64::powf(p2.0.max(p1.0) - p1.0.min(p2.0), 2.0) - + f64::powf(p2.1.max(p1.1) - p1.1.min(p2.1), 2.0)) as f64, + (f64::powf(p2.x.max(p1.x) - p1.x.min(p2.x), 2.0) + + f64::powf(p2.y.max(p1.y) - p1.y.min(p2.y), 2.0)) as f64, ) } } #[derive(Debug, Clone, Copy)] -pub struct Point3D(pub f64, pub f64, pub f64); +pub struct Point3D { + pub x: f64, pub y: f64, pub z: f64 +} impl Point3D { pub fn to_screen_coordinates(&self) -> Point2D { - let Point3D(x, y, z) = *self; + let Point3D {x, y, z} = *self; - if self.2 == 0.0 { + if z == 0.0 { // Normalize to the interval [0, 1] let x = (x / f64::MAX + 1.0) / 2.0; let y = (-y / f64::MAX + 1.0) / 2.0; @@ -32,10 +38,10 @@ impl Point3D { assert!(x <= 1.0 && y <= 1.0 && z <= 1.0); - Point2D( - x * (SCREEN_WIDTH - 1) as f64, // Scale to the interval [0, SCREEN_WIDTH) - y * (SCREEN_HEIGHT - 1) as f64, // Scale to the interval [0, SCREEN_HEIGHT) - ) + Point2D { + x: x * (SCREEN_WIDTH - 1) as f64, // Scale to the interval [0, SCREEN_WIDTH) + y: y * (SCREEN_HEIGHT - 1) as f64, // Scale to the interval [0, SCREEN_HEIGHT) + } } else { let x = x / z; let y = y / z; @@ -47,10 +53,10 @@ impl Point3D { assert!(x <= 1.0 && y <= 1.0 && z <= 1.0); - Point2D( - x * (SCREEN_WIDTH - 1) as f64, - y * (SCREEN_HEIGHT - 1) as f64, - ) + Point2D { + x: x * (SCREEN_WIDTH - 1) as f64, + y: y * (SCREEN_HEIGHT - 1) as f64, + } } } @@ -58,7 +64,7 @@ impl Point3D { let p1 = self; // Pythagorean formula f64::sqrt( - f64::powf(p2.0 - p1.0, 2.0) + f64::powf(p2.1 - p1.1, 2.0) + f64::powf(p2.2 - p1.2, 2.0) // Fix to use max and min + f64::powf(p2.x - p1.x, 2.0) + f64::powf(p2.y - p1.y, 2.0) + f64::powf(p2.z - p1.z, 2.0) // Fix to use max and min ) } } diff --git a/src/render.rs b/src/render.rs index 85006b1..1512764 100644 --- a/src/render.rs +++ b/src/render.rs @@ -28,11 +28,11 @@ pub fn render(t: u128, scene: &Scene, buf: &mut [u32]) { for obj in scene { for vertex in &obj.vertices { let vertex = vertex.to_screen_coordinates(); - let x = vertex.0; - let y = vertex.1; + let x = vertex.x; + let y = vertex.y; - for i in -10..10 { - for j in -10..10 { + for i in -10..=10 { + for j in -10..=10 { let x = x + i as f64; let y = y + j as f64; *index_buffer(buf, x, y) = to_rgb((255, 255, 255)); @@ -44,18 +44,17 @@ pub fn render(t: u128, scene: &Scene, buf: &mut [u32]) { let start = edge.0.to_screen_coordinates(); let end = edge.1.to_screen_coordinates(); - if (end.0 - start.0).abs() == 0.0 { // Vertical line case - m is undefined - for y in (start.1.min(end.1) as u32)..(end.1.max(start.1) + 1.0) as u32 { - *index_buffer(buf, end.0, y as f64) = to_rgb((255, 255, 255)); + if (end.x - start.x).abs() == 0.0 { // Vertical line case - m is undefined + for y in (start.y.min(end.y) as u32)..(end.y.max(start.y) + 1.0) as u32 { + *index_buffer(buf, end.x, y as f64) = to_rgb((255, 255, 255)); } continue } - let m = (end.1 - start.1) / (end.0 - start.0); // m = rise/run - let c = start.1 as f64 - m * start.0 as f64; // c = y - mx + let m = (end.y - start.y) / (end.x - start.x); // m = rise/run + let c = start.y as f64 - m * start.x as f64; // c = y - mx - dbg!(start, end, "==="); - for x in (start.0.min(end.0) as usize)..(end.0.max(start.0) as usize) { + for x in (start.x.min(end.x) as usize)..=(end.x.max(start.x) as usize) { let x = x as f64; let y = m * x + c; // y = mx + c *index_buffer(buf, x, y) = to_rgb((255, 255, 255)); diff --git a/src/scene.rs b/src/scene.rs index 2c61468..50a52b2 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -7,12 +7,20 @@ pub struct Object { // Every vertex in edges must have a corresponding vertex in vertices pub vertices: Vec, pub edges: Vec<(Point3D, Point3D)>, + pub faces: Vec<(Point3D, Point3D, Point3D)>, } pub type Scene = Vec; pub fn set_scene(t: u128, scene: &mut Scene) { for obj in scene { - obj.vertices[0] = Point3D(f64::MAX / 2.0, f64::MAX / 2.0, 1.0_f64.max(t as f64 / 100.0)); + for vertex in obj.vertices.iter_mut() { + vertex.z += 1.0; + } + + for edge in obj.edges.iter_mut() { + edge.0.z += 1.0; + edge.1.z += 1.0; + } } }