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)
}
/// See https://en.wikipedia.org/wiki/3D_projection#Mathematical_formula
/// for details on the implementation.
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 d = *self - c;
let e = V3(0.0, 0.0, 0.0) - c;
let d = a - 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)
}
@ -32,7 +34,7 @@ impl V3 {
}
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 {
@ -51,6 +53,10 @@ impl V3 {
pub fn distance(&self, rhs: Self) -> f64 {
(*self - rhs).len()
}
pub fn angle(&self, rhs: Self) -> f64 {
(self.dot(rhs) / (self.len() * rhs.len())).acos()
}
}
impl Add for V3 {

View File

@ -3,7 +3,6 @@
mod error;
mod game;
mod math;
mod r3d;
mod scene;
mod sdl_io;
mod shapes;
@ -11,7 +10,6 @@ mod shapes;
pub use error::*;
pub use game::*;
pub use math::*;
pub use r3d::*;
pub use scene::*;
pub use sdl_io::*;
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};
pub struct DrawnTriangle {
triangle: Triangle3,
outline_color: Color,
fill_color: Color,
}
pub struct Scene {
objects: Vec<DrawnTriangle>,
tris: Vec<(Triangle3, V3, Color, Color)>,
}
impl Scene {
pub fn new() -> Self {
Self {
objects: Vec::new(),
}
Self { tris: 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
.objects
.tris
.iter()
.enumerate()
.map(|(i, object)| {
let mut point_scores = object.triangle.points().map(|p| p.distance(camera_pos));
point_scores.sort_by(|a, b| a.total_cmp(b));
.map(|(i, (tri, ..))| {
let mut p_scores = [tri.0, tri.1, tri.2].map(|p| (camera_pos - p).len());
(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()
.collect::<Vec<_>>();
indices_with_scores.sort_by(|a, b| b.1.total_cmp(&a.1));
for (i, _) in indices_with_scores {
let object = &self.objects[i];
let tri3 = object
.triangle
.translate(camera_pos * -1.0)
.rotate(camera_rot);
'render_tri_loop: for (i, _) in indices_with_scores {
let (tri3, normal, outline_color, fill_color) = &self.tris[i];
// check if behind camera
// TODO: doesn't take camera_pos or camera_rot into accout
if !(tri3.0 .2 >= 0.0 && tri3.1 .2 >= 0.0 && tri3.2 .2 >= 0.0) {
for v in [tri3.0, tri3.1, tri3.2] {
if v.2 < camera_pos.2 {
continue 'render_tri_loop;
}
}
if normal.dot(camera_pos - tri3.0) < 0.0 {
continue;
}
if tri3.normal().dot(tri3.0 - camera_pos) >= 0.0 {
continue;
}
let tri2 = tri3.project_2d(camera_pos);
let tri2 = tri3
.translate(V3(0.0, 0.0, -1.0))
.project_2d(V3(0.0, 0.0, -1.0));
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);
r.draw_triangle(tri2.clone(), *fill_color);
r.draw_line(tri2.0, tri2.1, *outline_color);
r.draw_line(tri2.0, tri2.2, *outline_color);
}
}
pub fn draw_shape(&mut self, pos: V3, shape: &Shape, outline_color: Color, fill_color: Color) {
for triangle in shape.faces() {
self.objects.push(DrawnTriangle {
triangle: triangle.translate(pos),
outline_color,
fill_color,
})
let tri = triangle.translate(pos);
let normal = tri.normal();
self.tris.push((tri, normal, outline_color, fill_color))
}
}
}

View File

@ -231,7 +231,7 @@ impl<R: Renderer> engine::Game<R> for Game {
for object in &self.objects {
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) {

View File

@ -220,7 +220,7 @@ impl MotionDevice {
}
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();
for entry in reader.deserialize::<Measurement>() {
let entry: Measurement = entry.unwrap();