3d rendering hawd

This commit is contained in:
Mikkel Troels Kongsted 2026-03-25 14:11:06 +01:00
parent f81b0811a8
commit 766c704633
5 changed files with 104 additions and 15 deletions

View File

@ -1,6 +1,6 @@
use sdl3::pixels::Color; use sdl3::pixels::Color;
use crate::engine::math::{V2, V3}; use crate::engine::math::{Vertex, V2, V3};
use std::{marker::PhantomData, time::Duration}; use std::{marker::PhantomData, time::Duration};
use super::error::Error; use super::error::Error;
@ -19,6 +19,7 @@ pub trait Renderer {
fn point(&mut self, pos: V2, color: Color); fn point(&mut self, pos: V2, color: Color);
fn draw_line(&mut self, from: V2, to: V2, color: Color); fn draw_line(&mut self, from: V2, to: V2, color: Color);
fn draw_cube(&mut self, pos: V3, size: V3, outline_colors: Color, fill_color: Color); fn draw_cube(&mut self, pos: V3, size: V3, outline_colors: Color, fill_color: Color);
fn draw_triangle(&mut self, triangle: Vertex, color: Color);
} }
pub enum Event { pub enum Event {

View File

@ -35,14 +35,31 @@ impl MulAssign<f64> for V3 {
} }
impl V3 { impl V3 {
pub fn as_2d(&self) -> V2 { pub fn project(&self) -> V2 {
V2(self.0 / self.2, self.1 / self.2) V2(self.0 / self.2, self.1 / self.2)
} }
pub fn delta(&self, v: V3) -> V3 {
V3(v.0 - self.0, v.1 - self.1, v.2 - self.2)
}
} }
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub struct Vertex(pub V3, pub V3, pub V3); pub struct Vertex(pub V3, pub V3, pub V3);
impl Vertex {
pub fn normal_vector(&self) -> V3 {
let vector_a = self.1.delta(self.0);
let vector_b = self.1.delta(self.2);
V3(
vector_a.1 * vector_b.2 - vector_a.2 * vector_b.1,
vector_a.2 * vector_b.0 - vector_a.0 * vector_b.2,
vector_a.0 * vector_b.1 - vector_a.1 * vector_b.0,
)
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

View File

@ -4,7 +4,8 @@ use sdl3::{
event::Event, event::Event,
keyboard::Keycode, keyboard::Keycode,
pixels::{Color, PixelFormat}, pixels::{Color, PixelFormat},
render::{Canvas, FRect}, rect::Point,
render::{Canvas, FPoint, FRect},
video::Window, video::Window,
Sdl, VideoSubsystem, Sdl, VideoSubsystem,
}; };
@ -12,12 +13,12 @@ use sdl3::{
use crate::engine::{ use crate::engine::{
error::Error, error::Error,
game, game,
math::{V2, V3}, math::{Vertex, V2, V3},
Object, Object,
}; };
static WIDTH: f64 = 1280.0; pub static WIDTH: f64 = 1280.0;
static HEIGHT: f64 = 720.0; pub static HEIGHT: f64 = 720.0;
pub struct SdlIo { pub struct SdlIo {
sdl_context: Sdl, sdl_context: Sdl,
@ -111,24 +112,90 @@ impl game::Renderer for SdlIo {
} }
fn draw_line(&mut self, from: V2, to: V2, color: Color) { fn draw_line(&mut self, from: V2, to: V2, color: Color) {
todo!() self.canvas.set_draw_color(color);
self.canvas
.draw_line(
FPoint::new(from.0 as f32, from.1 as f32),
FPoint::new(to.0 as f32, to.1 as f32),
)
.unwrap();
}
fn draw_triangle(&mut self, triangle: Vertex, color: Color) {
self.draw_line(
self.world_to_screen(triangle.0.project()),
self.world_to_screen(triangle.1.project()),
color,
);
self.draw_line(
self.world_to_screen(triangle.1.project()),
self.world_to_screen(triangle.2.project()),
color,
);
self.draw_line(
self.world_to_screen(triangle.2.project()),
self.world_to_screen(triangle.0.project()),
color,
);
} }
fn draw_cube(&mut self, pos: V3, size: V3, outline_color: Color, fill_color: Color) { fn draw_cube(&mut self, pos: V3, size: V3, outline_color: Color, fill_color: Color) {
let V3(x, y, z) = pos; let V3(x, y, z) = pos;
let V3(w, h, d) = size; let V3(w, h, mut d) = size;
d /= 200.0;
let points = [ let points = [
pos, pos,
V3(x + w, y, z), V3(x + w, y, z),
V3(x, y + h, z), V3(x, y + h, z),
V3(x + w, y + h, z), V3(x + w, y + h, z),
V3(x, y, z + d / 100.0), V3(x, y, z + d),
V3(x + w, y, z + d / 100.0), V3(x + w, y, z + d),
V3(x, y + h, z + d / 100.0), V3(x, y + h, z + d),
V3(x + w, y + h, z + d / 100.0), V3(x + w, y + h, z + d),
]; ];
let vertices = [
// south
Vertex(points[0], points[2], points[3]),
Vertex(points[0], points[3], points[1]),
// east
Vertex(points[1], points[3], points[7]),
Vertex(points[1], points[7], points[5]),
// north
Vertex(points[5], points[7], points[6]),
Vertex(points[5], points[6], points[4]),
// west
Vertex(points[4], points[6], points[2]),
Vertex(points[4], points[2], points[0]),
// top
Vertex(points[2], points[6], points[7]),
Vertex(points[2], points[7], points[3]),
// bottom
Vertex(points[5], points[4], points[0]),
Vertex(points[5], points[0], points[1]),
];
println!("current triangles");
for vertex in vertices {
let normal_vector = vertex.normal_vector();
// self.draw_triangle(vertex, outline_color);
println!("{}", normal_vector.2);
if normal_vector.2 > 0.0 {
self.draw_triangle(
Vertex(
vertex.0,
vertex.1,
V3(vertex.2 .0, vertex.2 .1, vertex.2 .2),
),
outline_color,
);
}
}
for point in points { for point in points {
self.point(point.as_2d(), outline_color); self.point(point.project(), outline_color);
} }
} }
} }

View File

@ -41,6 +41,10 @@ impl Shape {
} }
} }
pub fn points<'a>(&'a self) -> impl Iterator<Item = V3> + 'a {
self.vertices.iter().cloned()
}
pub fn vertices<'a>(&'a self) -> impl Iterator<Item = Vertex> + 'a { pub fn vertices<'a>(&'a self) -> impl Iterator<Item = Vertex> + 'a {
let verts: &[V3] = &self.vertices; let verts: &[V3] = &self.vertices;
self.fragments self.fragments

View File

@ -36,8 +36,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut game = engine::Game::<engine::SdlIo, Object>::new()?; let mut game = engine::Game::<engine::SdlIo, Object>::new()?;
let player = Object::Player { let player = Object::Player {
pos: V3(-50.0, -50.0, 0.0), pos: V3(200.0, 100.0, 0.0),
vel: V3(0.0, 0.0, 1.0), vel: V3(0.0, 0.0, 0.1),
}; };
game.spawn(player); game.spawn(player);