fix phweedee wendewing

This commit is contained in:
sfja 2026-04-08 14:42:58 +02:00
parent e831c07ac1
commit f9af4ffe28
6 changed files with 40 additions and 129 deletions

View File

@ -11,11 +11,13 @@ impl V3 {
Self(v, v, v) Self(v, v, v)
} }
/// See https://en.wikipedia.org/wiki/3D_projection#Mathematical_formula
/// for details on the implementation.
pub fn project_2d(&self, camera_pos: V3) -> V2 { pub fn project_2d(&self, camera_pos: V3) -> V2 {
// V2(self.0 / self.2, self.1 / self.2) let a = *self;
let c = camera_pos; let c = camera_pos;
let d = *self - c; let d = a - c;
let e = V3(0.0, 0.0, 0.0) - c; let e = (camera_pos + V3(0.0, 0.0, 1.0)) - c;
V2(e.2 / d.2 * d.0 + e.0, e.2 / d.2 * d.1 + e.1) V2(e.2 / d.2 * d.0 + e.0, e.2 / d.2 * d.1 + e.1)
} }
@ -32,7 +34,7 @@ impl V3 {
} }
pub fn len(&self) -> f64 { pub fn len(&self) -> f64 {
f64::sqrt(self.0.powi(2) + self.1.powi(2) + self.2.powi(2)) (self.0.powi(2) + self.1.powi(2) + self.2.powi(2)).sqrt()
} }
pub fn unit(&self) -> Self { pub fn unit(&self) -> Self {
@ -51,6 +53,10 @@ impl V3 {
pub fn distance(&self, rhs: Self) -> f64 { pub fn distance(&self, rhs: Self) -> f64 {
(*self - rhs).len() (*self - rhs).len()
} }
pub fn angle(&self, rhs: Self) -> f64 {
(self.dot(rhs) / (self.len() * rhs.len())).acos()
}
} }
impl Add for V3 { impl Add for V3 {

View File

@ -3,7 +3,6 @@
mod error; mod error;
mod game; mod game;
mod math; mod math;
mod r3d;
mod scene; mod scene;
mod sdl_io; mod sdl_io;
mod shapes; mod shapes;
@ -11,7 +10,6 @@ mod shapes;
pub use error::*; pub use error::*;
pub use game::*; pub use game::*;
pub use math::*; pub use math::*;
pub use r3d::*;
pub use scene::*; pub use scene::*;
pub use sdl_io::*; pub use sdl_io::*;
pub use shapes::*; pub use shapes::*;

View File

@ -1,81 +0,0 @@
use crate::engine::{game::Renderer, Color, Shape, Triangle2, Triangle3, V2, V3};
pub struct R3d<'r, R: Renderer> {
r: &'r mut R,
triangle_buffer: Vec<Triangle2>,
camera_pos: V3,
}
impl<'r, R: Renderer> R3d<'r, R> {
pub fn new(r: &'r mut R, camera_pos: V3) -> Self {
Self {
r,
triangle_buffer: Vec::new(),
camera_pos,
}
}
pub fn draw_line(&mut self, from: V3, to: V3, color: Color) {
self.r.draw_line(
from.project_2d(self.camera_pos),
to.project_2d(self.camera_pos),
color,
);
}
pub fn draw_triangle(&mut self, triangle: Triangle3, color: Color) {
let triangle = triangle
.translate(self.camera_pos)
.project_2d(self.camera_pos);
self.r.draw_line(triangle.0, triangle.1, color);
self.r.draw_line(triangle.1, triangle.2, color);
self.r.draw_line(triangle.2, triangle.0, color);
}
pub fn draw_shape(&mut self, pos: V3, shape: &Shape, outline_color: Color, fill_color: Color) {
self.triangle_buffer.clear();
self.triangle_buffer.extend(
shape
.faces()
.map(|tri| tri.translate(pos).project_2d(self.camera_pos)),
);
self.r.draw_triangles(&self.triangle_buffer, fill_color);
for face in shape.faces() {
if face.normal().dot(face.0 - self.camera_pos + pos) >= 0.0 {
continue;
}
// let pxyz = face.middle() + face.normal();
// self.draw_line(
// face.middle() + pos,
// face.middle() + (face.1 - face.0).unit() * 0.02 + pos,
// Color::HEX(0xffaa00),
// );
// self.draw_line(
// face.middle() + pos,
// face.middle() + (face.2 - face.1).unit() * 0.02 + pos,
// Color::HEX(0x00ffaa),
// );
// self.draw_line(
// face.middle() + pos,
// face.middle() + (face.0 - face.2).unit() * 0.02 + pos,
// Color::HEX(0xaa00ff),
// );
// self.draw_line(face.middle() + pos, pxyz + pos, Color::HEX(0xffffff));
// self.draw_triangle(face.translate(pos - CAMERA_POS), outline_color);
self.r.draw_line(
(face.0 + pos).project_2d(self.camera_pos),
(face.1 + pos).project_2d(self.camera_pos),
outline_color,
);
self.r.draw_line(
(face.2 + pos).project_2d(self.camera_pos),
(face.0 + pos).project_2d(self.camera_pos),
outline_color,
);
}
}
}

View File

@ -1,72 +1,60 @@
use std::f64::consts::PI;
use crate::engine::{Color, Renderer, Shape, Triangle3, V3}; use crate::engine::{Color, Renderer, Shape, Triangle3, V3};
pub struct DrawnTriangle {
triangle: Triangle3,
outline_color: Color,
fill_color: Color,
}
pub struct Scene { pub struct Scene {
objects: Vec<DrawnTriangle>, tris: Vec<(Triangle3, V3, Color, Color)>,
} }
impl Scene { impl Scene {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self { tris: Vec::new() }
objects: Vec::new(),
}
} }
pub fn render<R: Renderer>(&mut self, r: &mut R, camera_pos: V3, camera_rot: V3) { pub fn render<R: Renderer>(&mut self, r: &mut R, camera_pos: V3) {
let mut indices_with_scores = self let mut indices_with_scores = self
.objects .tris
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, object)| { .map(|(i, (tri, ..))| {
let mut point_scores = object.triangle.points().map(|p| p.distance(camera_pos)); let mut p_scores = [tri.0, tri.1, tri.2].map(|p| (camera_pos - p).len());
point_scores.sort_by(|a, b| a.total_cmp(b));
(i, point_scores[0]) p_scores.sort_by(|a, b| a.total_cmp(b));
let score = p_scores[0] * p_scores[1];
(i, score)
}) })
.rev() .rev()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
indices_with_scores.sort_by(|a, b| b.1.total_cmp(&a.1)); indices_with_scores.sort_by(|a, b| b.1.total_cmp(&a.1));
for (i, _) in indices_with_scores { 'render_tri_loop: for (i, _) in indices_with_scores {
let object = &self.objects[i]; let (tri3, normal, outline_color, fill_color) = &self.tris[i];
let tri3 = object
.triangle
.translate(camera_pos * -1.0)
.rotate(camera_rot);
// check if behind camera for v in [tri3.0, tri3.1, tri3.2] {
// TODO: doesn't take camera_pos or camera_rot into accout if v.2 < camera_pos.2 {
if !(tri3.0 .2 >= 0.0 && tri3.1 .2 >= 0.0 && tri3.2 .2 >= 0.0) { continue 'render_tri_loop;
}
}
if normal.dot(camera_pos - tri3.0) < 0.0 {
continue; continue;
} }
if tri3.normal().dot(tri3.0 - camera_pos) >= 0.0 { let tri2 = tri3.project_2d(camera_pos);
continue;
}
let tri2 = tri3 r.draw_triangle(tri2.clone(), *fill_color);
.translate(V3(0.0, 0.0, -1.0)) r.draw_line(tri2.0, tri2.1, *outline_color);
.project_2d(V3(0.0, 0.0, -1.0)); r.draw_line(tri2.0, tri2.2, *outline_color);
r.draw_triangle(tri2.clone(), object.fill_color);
r.draw_line(tri2.0, tri2.1, object.outline_color);
r.draw_line(tri2.0, tri2.2, object.outline_color);
} }
} }
pub fn draw_shape(&mut self, pos: V3, shape: &Shape, outline_color: Color, fill_color: Color) { pub fn draw_shape(&mut self, pos: V3, shape: &Shape, outline_color: Color, fill_color: Color) {
for triangle in shape.faces() { for triangle in shape.faces() {
self.objects.push(DrawnTriangle { let tri = triangle.translate(pos);
triangle: triangle.translate(pos), let normal = tri.normal();
outline_color, self.tris.push((tri, normal, outline_color, fill_color))
fill_color,
})
} }
} }
} }

View File

@ -231,7 +231,7 @@ impl<R: Renderer> engine::Game<R> for Game {
for object in &self.objects { for object in &self.objects {
object.render(&mut scene); object.render(&mut scene);
} }
scene.render(r, self.camera_pos, V3(0.0, 0.0, 0.0)); scene.render(r, self.camera_pos);
} }
fn event(&mut self, event: engine::Event) { fn event(&mut self, event: engine::Event) {

View File

@ -220,7 +220,7 @@ impl MotionDevice {
} }
fn main() { fn main() {
let mut reader = csv::Reader::from_path("assets/inputs_moving.csv").unwrap(); let mut reader = csv::Reader::from_path("assets/inputs_still.csv").unwrap();
let mut measurements = Vec::<Measurement>::new(); let mut measurements = Vec::<Measurement>::new();
for entry in reader.deserialize::<Measurement>() { for entry in reader.deserialize::<Measurement>() {
let entry: Measurement = entry.unwrap(); let entry: Measurement = entry.unwrap();