From a0046b6f33b8fc4f5b2b95bf8d8f8bbeb5a17b0e Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 23 Mar 2024 21:15:33 +0300 Subject: [PATCH] Works... almost --- .gitignore | 1 + Cargo.toml | 10 +++ spacecraft2.1.obj | 140 +++++++++++++++++++++++++++++ spacecraft2.2.obj | 77 ++++++++++++++++ spacecraft2.obj | 107 ++++++++++++++++++++++ src/main.rs | 220 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 555 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 spacecraft2.1.obj create mode 100644 spacecraft2.2.obj create mode 100644 spacecraft2.obj create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e2a2e19 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "hello" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.8.5" +glm = "0.2.3" diff --git a/spacecraft2.1.obj b/spacecraft2.1.obj new file mode 100644 index 0000000..11dcbf2 --- /dev/null +++ b/spacecraft2.1.obj @@ -0,0 +1,140 @@ +# Blender 3.6.5 +# www.blender.org +mtllib spacecraft2.1.mtl +o Cube +v -1.000000 0.000000 5.000000 +v -3.000000 0.000000 4.000000 +v -4.000000 0.000000 7.000000 +v -8.000000 0.000000 7.000000 +v -9.000000 0.000000 4.000000 +v -3.000000 0.000000 0.000000 +v -6.000000 0.000000 -7.000000 +v -2.000000 0.000000 -3.000000 +v -7.000000 1.000000 4.000000 +v 0.000000 2.000000 0.000000 +v 0.000000 2.000000 2.000000 +v 0.000000 0.000000 6.000000 +v 0.000000 0.000000 -4.000000 +v -5.000000 0.000000 2.000000 +v 1.000000 0.000000 5.000000 +v 3.000000 0.000000 4.000000 +v 4.000000 0.000000 7.000000 +v 8.000000 0.000000 7.000000 +v 9.000000 0.000000 4.000000 +v 3.000000 0.000000 0.000000 +v 6.000000 0.000000 -7.000000 +v 2.000000 0.000000 -3.000000 +v 7.000000 1.000000 4.000000 +v 5.000000 0.000000 2.000000 +v -7.000000 -1.000000 4.000000 +v 0.000000 -2.000000 0.000000 +v 0.000000 -2.000000 2.000000 +v 7.000000 -1.000000 4.000000 +vn -0.5455 0.8182 -0.1818 +vn -0.4851 0.4851 -0.7276 +vn -0.4439 0.8878 -0.1211 +vn -0.0000 0.9487 0.3162 +vn -0.4423 0.8847 0.1474 +vn 0.2417 0.9670 0.0806 +vn 0.2408 -0.8427 -0.4815 +vn 0.1455 0.5819 0.8001 +vn -0.1414 0.9899 -0.0000 +vn -0.2182 0.8729 -0.4364 +vn 0.4082 -0.8165 -0.4082 +vn -0.4851 0.7276 -0.4851 +vn 0.4099 0.9110 -0.0455 +vn -0.0000 -1.0000 -0.0000 +vn 0.5455 0.8182 -0.1818 +vn 0.4851 0.4851 -0.7276 +vn 0.4439 0.8878 -0.1211 +vn 0.4423 0.8847 0.1474 +vn -0.2417 0.9670 0.0806 +vn -0.2408 -0.8427 -0.4815 +vn -0.1455 0.5819 0.8001 +vn 0.1414 0.9899 -0.0000 +vn 0.2182 0.8729 -0.4364 +vn -0.4082 -0.8165 -0.4082 +vn 0.4851 0.7276 -0.4851 +vn -0.4099 0.9110 -0.0455 +vn -0.5455 -0.8182 -0.1818 +vn -0.4851 -0.4851 -0.7276 +vn -0.4439 -0.8878 -0.1211 +vn -0.0000 -0.9487 0.3162 +vn -0.4423 -0.8847 0.1474 +vn 0.2417 -0.9670 0.0806 +vn 0.2408 0.8427 -0.4815 +vn 0.1455 -0.5819 0.8001 +vn -0.1414 -0.9899 -0.0000 +vn -0.2182 -0.8729 -0.4364 +vn 0.4082 0.8165 -0.4082 +vn -0.4851 -0.7276 -0.4851 +vn 0.4099 -0.9110 -0.0455 +vn 0.5455 -0.8182 -0.1818 +vn 0.4851 -0.4851 -0.7276 +vn 0.4439 -0.8878 -0.1211 +vn 0.4423 -0.8847 0.1474 +vn -0.2417 -0.9670 0.0806 +vn -0.2408 0.8427 -0.4815 +vn -0.1455 -0.5819 0.8001 +vn 0.1414 -0.9899 -0.0000 +vn 0.2182 -0.8729 -0.4364 +vn -0.4082 0.8165 -0.4082 +vn 0.4851 -0.7276 -0.4851 +vn -0.4099 -0.9110 -0.0455 +vt 0.000000 0.000000 +s 0 +usemtl Material +f 6/1/1 10/1/1 8/1/1 +f 10/1/2 14/1/2 9/1/2 +f 5/1/3 9/1/3 7/1/3 +f 3/1/4 9/1/4 4/1/4 +f 4/1/5 9/1/5 5/1/5 +f 2/1/6 9/1/6 3/1/6 +f 1/1/7 2/1/7 11/1/7 +f 9/1/8 2/1/8 11/1/8 +f 9/1/9 11/1/9 10/1/9 +f 8/1/10 10/1/10 13/1/10 +f 1/1/11 11/1/11 12/1/11 +f 10/1/12 6/1/12 14/1/12 +f 7/1/13 9/1/13 14/1/13 +f 7/1/14 14/1/14 5/1/14 +f 20/1/15 22/1/15 10/1/15 +f 10/1/16 23/1/16 24/1/16 +f 19/1/17 21/1/17 23/1/17 +f 17/1/4 18/1/4 23/1/4 +f 18/1/18 19/1/18 23/1/18 +f 16/1/19 17/1/19 23/1/19 +f 15/1/20 11/1/20 16/1/20 +f 23/1/21 11/1/21 16/1/21 +f 23/1/22 10/1/22 11/1/22 +f 22/1/23 13/1/23 10/1/23 +f 15/1/24 12/1/24 11/1/24 +f 10/1/25 24/1/25 20/1/25 +f 21/1/26 24/1/26 23/1/26 +f 21/1/14 19/1/14 24/1/14 +f 6/1/27 8/1/27 26/1/27 +f 26/1/28 25/1/28 14/1/28 +f 5/1/29 7/1/29 25/1/29 +f 3/1/30 4/1/30 25/1/30 +f 4/1/31 5/1/31 25/1/31 +f 2/1/32 3/1/32 25/1/32 +f 1/1/33 27/1/33 2/1/33 +f 25/1/34 27/1/34 2/1/34 +f 25/1/35 26/1/35 27/1/35 +f 8/1/36 13/1/36 26/1/36 +f 1/1/37 12/1/37 27/1/37 +f 26/1/38 14/1/38 6/1/38 +f 7/1/39 14/1/39 25/1/39 +f 20/1/40 26/1/40 22/1/40 +f 26/1/41 24/1/41 28/1/41 +f 19/1/42 28/1/42 21/1/42 +f 17/1/30 28/1/30 18/1/30 +f 18/1/43 28/1/43 19/1/43 +f 16/1/44 28/1/44 17/1/44 +f 15/1/45 16/1/45 27/1/45 +f 28/1/46 16/1/46 27/1/46 +f 28/1/47 27/1/47 26/1/47 +f 22/1/48 26/1/48 13/1/48 +f 15/1/49 27/1/49 12/1/49 +f 26/1/50 20/1/50 24/1/50 +f 21/1/51 28/1/51 24/1/51 diff --git a/spacecraft2.2.obj b/spacecraft2.2.obj new file mode 100644 index 0000000..216dd57 --- /dev/null +++ b/spacecraft2.2.obj @@ -0,0 +1,77 @@ +# Blender 3.6.5 +# www.blender.org +mtllib spacecraft2.2.mtl +o Cube +v -1.000000 0.000000 5.000000 +v -3.000000 0.000000 4.000000 +v -3.000000 0.000000 0.000000 +v -2.000000 0.000000 -3.000000 +v -7.000000 0.000000 4.000000 +v 0.000000 2.000000 0.000000 +v 0.000000 2.000000 2.000000 +v 0.000000 0.000000 6.000000 +v 0.000000 0.000000 -4.000000 +v 1.000000 0.000000 5.000000 +v 3.000000 0.000000 4.000000 +v 3.000000 0.000000 0.000000 +v 2.000000 0.000000 -3.000000 +v 7.000000 0.000000 4.000000 +v 0.000000 -2.000000 0.000000 +v 0.000000 -2.000000 2.000000 +vn -0.5455 0.8182 -0.1818 +vn -0.4851 0.7276 -0.4851 +vn 0.2408 -0.8427 -0.4815 +vn -0.0000 0.7071 0.7071 +vn -0.2747 0.9615 -0.0000 +vn -0.2182 0.8729 -0.4364 +vn 0.4082 -0.8165 -0.4082 +vn 0.5455 0.8182 -0.1818 +vn 0.4851 0.7276 -0.4851 +vn -0.2408 -0.8427 -0.4815 +vn 0.2747 0.9615 -0.0000 +vn 0.2182 0.8729 -0.4364 +vn -0.4082 -0.8165 -0.4082 +vn -0.5455 -0.8182 -0.1818 +vn -0.4851 -0.7276 -0.4851 +vn 0.2408 0.8427 -0.4815 +vn -0.0000 -0.7071 0.7071 +vn -0.2747 -0.9615 -0.0000 +vn -0.2182 -0.8729 -0.4364 +vn 0.4082 0.8165 -0.4082 +vn 0.5455 -0.8182 -0.1818 +vn 0.4851 -0.7276 -0.4851 +vn -0.2408 0.8427 -0.4815 +vn 0.2747 -0.9615 -0.0000 +vn 0.2182 -0.8729 -0.4364 +vn -0.4082 0.8165 -0.4082 +vt 0.000000 0.000000 +s 0 +usemtl Material +f 3/1/1 6/1/1 4/1/1 +f 6/1/2 3/1/2 5/1/2 +f 1/1/3 2/1/3 7/1/3 +f 5/1/4 2/1/4 7/1/4 +f 5/1/5 7/1/5 6/1/5 +f 4/1/6 6/1/6 9/1/6 +f 1/1/7 7/1/7 8/1/7 +f 12/1/8 13/1/8 6/1/8 +f 6/1/9 14/1/9 12/1/9 +f 10/1/10 7/1/10 11/1/10 +f 14/1/4 7/1/4 11/1/4 +f 14/1/11 6/1/11 7/1/11 +f 13/1/12 9/1/12 6/1/12 +f 10/1/13 8/1/13 7/1/13 +f 3/1/14 4/1/14 15/1/14 +f 15/1/15 5/1/15 3/1/15 +f 1/1/16 16/1/16 2/1/16 +f 5/1/17 16/1/17 2/1/17 +f 5/1/18 15/1/18 16/1/18 +f 4/1/19 9/1/19 15/1/19 +f 1/1/20 8/1/20 16/1/20 +f 12/1/21 15/1/21 13/1/21 +f 15/1/22 12/1/22 14/1/22 +f 10/1/23 11/1/23 16/1/23 +f 14/1/17 11/1/17 16/1/17 +f 14/1/24 16/1/24 15/1/24 +f 13/1/25 15/1/25 9/1/25 +f 10/1/26 16/1/26 8/1/26 diff --git a/spacecraft2.obj b/spacecraft2.obj new file mode 100644 index 0000000..ad509cb --- /dev/null +++ b/spacecraft2.obj @@ -0,0 +1,107 @@ +# Blender 3.6.5 +# www.blender.org +mtllib spacecraft2.mtl +o Cube +v -1.000000 0.000000 3.000000 +v -2.000000 0.000000 2.000000 +v -3.000000 0.000000 4.000000 +v -5.000000 0.000000 4.000000 +v -6.000000 0.000000 2.000000 +v -2.000000 0.000000 0.000000 +v -4.000000 0.000000 -6.000000 +v -1.000000 0.000000 -2.000000 +v 1.000000 0.000000 3.000000 +v 2.000000 0.000000 2.000000 +v 3.000000 0.000000 4.000000 +v 5.000000 0.000000 4.000000 +v 6.000000 0.000000 2.000000 +v 4.000000 0.000000 -6.000000 +v 2.000000 0.000000 0.000000 +v 1.000000 0.000000 -2.000000 +v -4.000000 1.000000 2.000000 +v 0.000000 1.000000 0.000000 +v 4.000000 1.000000 2.000000 +v 0.000000 1.000000 1.000000 +v -4.000000 -1.000000 2.000000 +v 0.000000 -1.000000 0.000000 +v 4.000000 -1.000000 2.000000 +v 0.000000 -1.000000 1.000000 +vn -0.0000 0.8944 -0.4472 +vn 0.4364 0.8729 -0.2182 +vn 0.3333 0.6667 -0.6667 +vn -0.3487 0.9300 -0.1162 +vn 0.4444 0.8889 -0.1111 +vn 0.4364 0.8729 0.2182 +vn -0.0000 0.8944 0.4472 +vn -0.4364 0.8729 0.2182 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -0.8944 -0.4472 +vn -0.3015 -0.9045 -0.3015 +vn -0.2182 0.4364 0.8729 +vn -0.4364 0.8729 -0.2182 +vn -0.3333 0.6667 -0.6667 +vn 0.3487 0.9300 -0.1162 +vn -0.4444 0.8889 -0.1111 +vn 0.3015 -0.9045 -0.3015 +vn 0.2182 0.4364 0.8729 +vn 0.4364 -0.8729 -0.2182 +vn 0.3333 -0.6667 -0.6667 +vn -0.3487 -0.9300 -0.1162 +vn 0.4444 -0.8889 -0.1111 +vn 0.4364 -0.8729 0.2182 +vn -0.0000 -0.8944 0.4472 +vn -0.4364 -0.8729 0.2182 +vn -0.0000 -1.0000 -0.0000 +vn -0.3015 0.9045 -0.3015 +vn -0.2182 -0.4364 0.8729 +vn -0.4364 -0.8729 -0.2182 +vn -0.3333 -0.6667 -0.6667 +vn 0.3487 -0.9300 -0.1162 +vn -0.4444 -0.8889 -0.1111 +vn 0.3015 0.9045 -0.3015 +vn 0.2182 -0.4364 0.8729 +vt 0.000000 0.000000 +s 0 +usemtl Material +f 8/1/1 18/1/1 16/1/1 +f 16/1/2 18/1/2 15/1/2 +f 18/1/3 19/1/3 15/1/3 +f 15/1/4 19/1/4 14/1/4 +f 14/1/5 19/1/5 13/1/5 +f 13/1/6 19/1/6 12/1/6 +f 12/1/7 19/1/7 11/1/7 +f 10/1/8 11/1/8 19/1/8 +f 17/1/9 20/1/9 19/1/9 18/1/9 +f 1/1/10 20/1/10 9/1/10 +f 9/1/11 20/1/11 10/1/11 +f 20/1/12 10/1/12 19/1/12 +f 6/1/13 18/1/13 8/1/13 +f 18/1/14 6/1/14 17/1/14 +f 6/1/15 7/1/15 17/1/15 +f 5/1/16 17/1/16 7/1/16 +f 3/1/7 17/1/7 4/1/7 +f 4/1/8 17/1/8 5/1/8 +f 2/1/6 17/1/6 3/1/6 +f 1/1/17 2/1/17 20/1/17 +f 17/1/18 2/1/18 20/1/18 +f 8/1/10 16/1/10 22/1/10 +f 16/1/19 15/1/19 22/1/19 +f 22/1/20 15/1/20 23/1/20 +f 15/1/21 14/1/21 23/1/21 +f 14/1/22 13/1/22 23/1/22 +f 13/1/23 12/1/23 23/1/23 +f 12/1/24 11/1/24 23/1/24 +f 10/1/25 23/1/25 11/1/25 +f 21/1/26 22/1/26 23/1/26 24/1/26 +f 1/1/1 9/1/1 24/1/1 +f 9/1/27 10/1/27 24/1/27 +f 24/1/28 23/1/28 10/1/28 +f 6/1/29 8/1/29 22/1/29 +f 22/1/30 21/1/30 6/1/30 +f 6/1/31 21/1/31 7/1/31 +f 5/1/32 7/1/32 21/1/32 +f 3/1/24 4/1/24 21/1/24 +f 4/1/25 5/1/25 21/1/25 +f 2/1/23 3/1/23 21/1/23 +f 1/1/33 24/1/33 2/1/33 +f 21/1/34 24/1/34 2/1/34 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..7651296 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,220 @@ +use std::fs::File; +use std::{env, io}; +use std::f32::consts::PI; +use std::io::{BufRead, BufReader, BufWriter}; +use std::io::Write; +use rand::Rng; +use glm; +use glm::{dot, ivec2, IVec2, ivec3, to_ivec3, vec2, Vec2, Vec3}; + +#[derive(Copy, Clone, Debug)] +struct ObjVertex { + vertex: usize, + normal: usize, + tex_coord: usize, +} + +#[derive(Copy, Clone, Debug)] +struct ObjFace { + vertices: [ObjVertex; 3], +} + +#[derive(Debug)] +struct ObjMesh { + vertices: Vec, + normals: Vec, + tex_coords: Vec, + faces: Vec, +} + +impl ObjMesh { + fn parse_v2(tokens: &[&str]) -> Vec2 { + assert_eq!(tokens.len(), 2); + let tokens: Vec<_> = tokens.iter().map(|&t| t.parse().unwrap()).collect(); + vec2(tokens[0], tokens[1]) + } + + fn parse_v3(tokens: &[&str]) -> Vec3 { + assert_eq!(tokens.len(), 3); + let tokens: Vec<_> = tokens.iter().map(|&t| t.parse().unwrap()).collect(); + glm::vec3(tokens[0], tokens[1], tokens[2]) + } + + fn parse_fv(desc: &&str) -> ObjVertex { + let tokens: Vec<_> = desc.split('/').map(|s| s.parse::().unwrap() - 1).collect(); + assert_eq!(tokens.len(), 3); + ObjVertex { vertex: tokens[0], tex_coord: tokens[1], normal: tokens[2] } + } + + fn parse_f(tokens: &[&str]) -> ObjFace { + let vertices: Vec<_> = tokens.iter().map(ObjMesh::parse_fv).collect(); + ObjFace { vertices: vertices.as_slice().try_into().unwrap() } + } + + fn read(f: &mut impl BufRead) -> io::Result { + let mut result = ObjMesh { + vertices: Vec::new(), + normals: Vec::new(), + tex_coords: Vec::new(), + faces: Vec::new(), + }; + loop { + let mut line = String::new(); + if f.read_line(&mut line)? == 0 { + break; + } + let tokens: Vec<&str> = line + .trim() + .split('#') + .next() + .unwrap() + .split(' ') + .collect(); + match tokens[0] { + "v" => result.vertices.push(Self::parse_v3(&tokens[1..])), + "vn" => result.normals.push(Self::parse_v3(&tokens[1..])), + "vt" => result.tex_coords.push(Self::parse_v2(&tokens[1..])), + "f" => result.faces.push(Self::parse_f(&tokens[1..])), + _ => (), + } + } + Ok(result) + } +} + +const W: i32 = 800; +const H: i32 = 600; +const SCALE: f32 = 30.0; + +#[derive(Copy, Clone)] +struct Color(u8, u8, u8); + +#[derive(Copy, Clone)] +struct Comparer { + coef: Vec2, + thr: f32, +} + +impl Comparer { + fn new(a: Vec2, b: Vec2) -> Comparer { + let d = b - a; + let ortho = vec2(-d.y, d.x); + Comparer { + coef: ortho, + thr: dot(a, ortho), + } + } + + fn dist(&self, p: Vec2) -> f32 { + dot(p, self.coef) - self.thr + } + + fn test(&self, p: Vec2) -> bool { + self.dist(p) > 0.0 + } +} + +struct Image { + w: i32, + h: i32, + data: Vec, +} + +impl Image { + fn data(&self) -> &[u8] { + self.data.as_slice() + } + + fn put_pixel(&mut self, x: i32, y: i32, color: Color) { + if x < 0 || x >= self.w || y < 0 || y > self.h { + return; + } + let index = 3 * (x + self.w * y) as usize; + self.data[index] = color.0; + self.data[index + 1] = color.1; + self.data[index + 2] = color.2; + } + + fn draw_line(&mut self, a: IVec2, b: IVec2, color: Color) {} + fn draw_tri(&mut self, a: Vec2, b: Vec2, c: Vec2, color: Color) { + let u = Comparer::new(a, b); + let v = Comparer::new(b, c); + let w = Comparer::new(c, a); + for y in 0..self.h { + for x in 0..self.w { + let p = vec2(x as f32, y as f32); + if u.test(p) && v.test(p) && w.test(p) || !u.test(p) && !v.test(p) && !w.test(p) { + self.put_pixel(x, y, color); + } + } + } + } +} + +fn main() -> io::Result<()> { + let args: Vec = env::args().collect(); + let mesh = { + let f = File::open(&args[1])?; + let mut f = BufReader::new(f); + ObjMesh::read(&mut f)? + }; + dbg!(&mesh); + let mut img = Image { + w: W, + h: H, + data: vec![0; (3 * W * H) as usize], + }; + let yaw = PI / 4.0; + let pitch = PI / 6.0; + let roll = 0.0f32; + let m_roll = glm::mat3( + roll.cos(), roll.sin(), 0.0, + -roll.sin(), roll.cos(), 0.0, + 0.0, 0.0, 1.0); + let m_yaw = glm::mat3( + yaw.cos(), 0.0, yaw.sin(), + 0.0, 1.0, 0.0, + -yaw.sin(), 0.0, yaw.cos()); + let m_pitch = glm::mat3( + 1.0, 0.0, 0.0, + 0.0, pitch.cos(), -pitch.sin(), + 0.0, pitch.sin(), pitch.cos()); + let m1 = m_roll * m_pitch * m_yaw; + for f in mesh.faces { + let vs = f.vertices + .map(|v| m1 * mesh.vertices[v.vertex]) + .map(|v| vec2(W as f32 * 0.5 + v.x * SCALE, H as f32 * 0.5 + v.y * SCALE)); + let n = mesh.normals[f.vertices[0].normal]; + if (m1 * mesh.normals[f.vertices[0].normal]).z < 0.0 { + continue; + } + /* + let r: u8 = rand::thread_rng().gen_range(0..255); + let g: u8 = rand::thread_rng().gen_range(0..255); + let b: u8 = rand::thread_rng().gen_range(0..255); + + */ + let color = glm::clamp(to_ivec3(n * 120.0 + 128.0), ivec3(0, 0, 0), ivec3(255, 255, 255)); + img.draw_tri(vs[0], vs[1], vs[2], Color(color.x as u8, color.y as u8, color.z as u8)); + } + /* + for v in mesh.vertices { + img.put_pixel(W / 2 + (v.x * SCALE) as i32, H / 2 + (v.z * SCALE) as i32, Color(255, 255, 255)); + } + + for y in 0..H { + for x in 0..W { + let r = (x * 256 / W).clamp(0, 255) as u8; + let g = (y * 256 / H).clamp(0, 255) as u8; + let b = rand::thread_rng().gen_range(128 - 16..128 + 16); + img.put_pixel(x, y, Color(r, g, b)); + } + } + */ + let f = File::create("1.ppm")?; + let mut f = BufWriter::new(f); + write!(f, "P6\n")?; + write!(f, "{W} {H} 255\n")?; + f.write(img.data()); + Ok(()) +}