diff --git a/core/src/geom.rs b/core/src/geom.rs index 9ed027e4..4c0a759d 100644 --- a/core/src/geom.rs +++ b/core/src/geom.rs @@ -1,7 +1,10 @@ //! Basic geometric primitives. -use crate::math::vec::{Vec2, Vec3}; -use crate::render::Model; +use crate::{ + math::point::{Point2, Point3}, + math::vec::{Vec2, Vec3}, + render::Model, +}; pub use mesh::Mesh; @@ -15,10 +18,10 @@ pub struct Vertex { } /// Two-dimensional vertex type. -pub type Vertex2 = Vertex, A>; +pub type Vertex2 = Vertex, A>; /// Three-dimensional vertex type. -pub type Vertex3 = Vertex, A>; +pub type Vertex3 = Vertex, A>; /// Triangle, defined by three vertices. #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/core/src/geom/mesh.rs b/core/src/geom/mesh.rs index 7064940b..9082de1d 100644 --- a/core/src/geom/mesh.rs +++ b/core/src/geom/mesh.rs @@ -9,8 +9,8 @@ use alloc::{vec, vec::Vec}; use crate::math::{ mat::{Mat4x4, RealToReal}, + point::Point3, space::Linear, - vec::Vec3, }; use crate::render::Model; @@ -51,16 +51,17 @@ impl Mesh { /// # Examples /// ``` /// # use retrofire_core::geom::{Tri, Mesh, vertex}; - /// # use retrofire_core::math::vec3; + /// # use retrofire_core::math::point::pt3; /// let verts = [ - /// vec3(0.0, 0.0, 0.0), - /// vec3(1.0, 0.0, 0.0), - /// vec3(0.0, 1.0, 0.0), - /// vec3(0.0, 0.0, 1.0) + /// pt3(0.0, 0.0, 0.0), + /// pt3(1.0, 0.0, 0.0), + /// pt3(0.0, 1.0, 0.0), + /// pt3(0.0, 0.0, 1.0) /// ] /// .map(|v| vertex(v, ())); /// /// let faces = [ + /// // Indices point to the verts array /// Tri([0, 1, 2]), /// Tri([0, 1, 3]), /// Tri([0, 2, 3]), @@ -126,16 +127,16 @@ impl Builder { } /// Appends a vertex with the given position and attribute. - pub fn push_vert(&mut self, pos: Vec3, attrib: A) { + pub fn push_vert(&mut self, pos: Point3, attrib: A) { self.mesh.verts.push(vertex(pos.to(), attrib)); } /// Appends all the vertices yielded by the given iterator. pub fn push_verts(&mut self, verts: Vs) where - Vs: IntoIterator, + Vs: IntoIterator, { - let vs = verts.into_iter().map(|(v, a)| vertex(v.to(), a)); + let vs = verts.into_iter().map(|(p, a)| vertex(p.to(), a)); self.mesh.verts.extend(vs); } @@ -164,7 +165,7 @@ impl Builder<()> { .mesh .verts .into_iter() - .map(|v| vertex(tf.apply(&v.pos), v.attrib)) + .map(|v| vertex(tf.apply_pt(&v.pos), v.attrib)) .collect(), }; mesh.into_builder() @@ -254,6 +255,7 @@ mod tests { use core::f32::consts::FRAC_1_SQRT_2; use crate::geom::vertex; + use crate::math::point::pt3; use crate::math::vec3; use crate::prelude::splat; @@ -265,9 +267,9 @@ mod tests { let _: Mesh<()> = Mesh::new( [Tri([0, 1, 2]), Tri([1, 2, 3])], [ - vertex(vec3(0.0, 0.0, 0.0), ()), - vertex(vec3(1.0, 1.0, 1.0), ()), - vertex(vec3(2.0, 2.0, 2.0), ()), + vertex(pt3(0.0, 0.0, 0.0), ()), + vertex(pt3(1.0, 1.0, 1.0), ()), + vertex(pt3(2.0, 2.0, 2.0), ()), ], ); } @@ -278,9 +280,9 @@ mod tests { let mut b = Mesh::builder(); b.push_faces([[0, 1, 2], [1, 2, 3]]); b.push_verts([ - (vec3(0.0, 0.0, 0.0), ()), - (vec3(1.0, 1.0, 1.0), ()), - (vec3(2.0, 2.0, 2.0), ()), + (pt3(0.0, 0.0, 0.0), ()), + (pt3(1.0, 1.0, 1.0), ()), + (pt3(2.0, 2.0, 2.0), ()), ]); _ = b.build(); } @@ -292,10 +294,10 @@ mod tests { let mut b = Mesh::builder(); b.push_faces([[0, 2, 1], [0, 1, 3], [0, 3, 2]]); b.push_verts([ - (vec3(0.0, 0.0, 0.0), ()), - (vec3(1.0, 0.0, 0.0), ()), - (vec3(0.0, 1.0, 0.0), ()), - (vec3(0.0, 0.0, 1.0), ()), + (pt3(0.0, 0.0, 0.0), ()), + (pt3(1.0, 0.0, 0.0), ()), + (pt3(0.0, 1.0, 0.0), ()), + (pt3(0.0, 0.0, 1.0), ()), ]); let b = b.with_vertex_normals(); diff --git a/core/src/math/mat.rs b/core/src/math/mat.rs index 9a19e2e4..ea9ce48b 100644 --- a/core/src/math/mat.rs +++ b/core/src/math/mat.rs @@ -1,16 +1,23 @@ #![allow(clippy::needless_range_loop)] //! Matrices and linear transforms. +//! +//! TODO Docs -use core::array; -use core::fmt::{self, Debug, Formatter}; -use core::marker::PhantomData; -use core::ops::Range; +use core::{ + array, + fmt::{self, Debug, Formatter}, + marker::PhantomData, + ops::Range, +}; use crate::render::{NdcToScreen, ViewToProj}; -use super::space::{Linear, Proj4, Real}; -use super::vec::{ProjVec4, Vec2, Vec2u, Vec3, Vector}; +use super::{ + point::{Point2, Point3}, + space::{Linear, Proj4, Real}, + vec::{ProjVec4, Vec2, Vec2u, Vec3, Vector}, +}; /// A linear transform from one space (or basis) to another. /// @@ -199,9 +206,16 @@ impl Mat3x3> { /// ``` #[must_use] pub fn apply(&self, v: &Vec2) -> Vec2 { - let v = [v.x(), v.y(), 1.0].into(); + let v = [v.x(), v.y(), 1.0].into(); // TODO w=0.0 array::from_fn(|i| self.row_vec(i).dot(&v)).into() } + + // TODO Add trait to overload apply or similar + #[must_use] + pub fn apply_pt(&self, p: &Point2) -> Point2 { + let p = [p.x(), p.y(), 1.0].into(); + array::from_fn(|i| self.row_vec(i).dot(&p)).into() + } } impl Mat4x4> { @@ -218,10 +232,17 @@ impl Mat4x4> { /// ``` #[must_use] pub fn apply(&self, v: &Vec3) -> Vec3 { - let v = [v.x(), v.y(), v.z(), 1.0].into(); + let v = [v.x(), v.y(), v.z(), 1.0].into(); // TODO w=0.0 array::from_fn(|i| self.row_vec(i).dot(&v)).into() } + // TODO Add trait to overload apply or similar + #[must_use] + pub fn apply_pt(&self, p: &Point3) -> Point3 { + let p = [p.x(), p.y(), p.z(), 1.0].into(); + array::from_fn(|i| self.row_vec(i).dot(&p)).into() + } + /// Returns the determinant of `self`. /// /// Given a matrix M, @@ -365,7 +386,7 @@ impl Mat4x4> { /// \ · · M33 / \ 1 / /// ``` #[must_use] - pub fn apply(&self, v: &Vec3) -> ProjVec4 { + pub fn apply(&self, v: &Point3) -> ProjVec4 { let v = Vector::from([v.x(), v.y(), v.z(), 1.0]); [ self.row_vec(0).dot(&v), @@ -602,6 +623,7 @@ pub fn perspective( /// # Parameters /// * `lbn`: The left-bottom-near corner of the projection box. /// * `rtf`: The right-bottom-far corner of the projection box. +// TODO Change to take points pub fn orthographic(lbn: Vec3, rtf: Vec3) -> Mat4x4 { let [dx, dy, dz] = (rtf - lbn).0; let [sx, sy, sz] = (rtf + lbn).0; @@ -639,6 +661,7 @@ mod tests { #[cfg(feature = "fp")] use crate::math::angle::degs; + use crate::math::point::pt3; use super::*; @@ -652,6 +675,7 @@ mod tests { mod mat3x3 { use super::*; + use crate::math::point::pt2; const MAT: Mat3x3 = Matrix::new([ [0.0, 1.0, 2.0], // @@ -696,6 +720,7 @@ mod tests { [0.0, 0.0, 1.0], ]); assert_eq!(m.apply(&vec2(1.0, 2.0)), vec2(2.0, -6.0)); + assert_eq!(m.apply_pt(&pt2(2.0, -1.0)), pt2(4.0, 3.0)); } #[test] @@ -706,6 +731,7 @@ mod tests { [0.0, 0.0, 1.0], ]); assert_eq!(m.apply(&vec2(1.0, 2.0)), vec2(3.0, -1.0)); + assert_eq!(m.apply_pt(&pt2(2.0, -1.0)), pt2(4.0, -4.0)); } #[test] @@ -723,6 +749,7 @@ mod tests { mod mat4x4 { use super::*; + use crate::math::point::pt3; const MAT: Mat4x4 = Matrix::new([ [0.0, 1.0, 2.0, 3.0], @@ -753,17 +780,25 @@ mod tests { } #[test] - fn scaling_vec3() { + fn scaling() { let m = scale(vec3(1.0, -2.0, 3.0)); + let v = vec3(0.0, 4.0, -3.0); assert_eq!(m.apply(&v), vec3(0.0, -8.0, -9.0)); + + let p = pt3(4.0, 0.0, -3.0); + assert_eq!(m.apply_pt(&p), pt3(4.0, 0.0, -9.0)); } #[test] - fn translation_vec3() { + fn translation() { let m = translate(vec3(1.0, 2.0, 3.0)); + let v = vec3(0.0, 5.0, -3.0); assert_eq!(m.apply(&v), vec3(1.0, 7.0, 0.0)); + + let p = pt3(3.0, 5.0, 0.0); + assert_eq!(m.apply_pt(&p), pt3(4.0, 7.0, 3.0)); } #[cfg(feature = "fp")] @@ -775,6 +810,10 @@ mod tests { m.apply(&vec3(0.0, 0.0, 1.0)), vec3(0.0, 1.0, 0.0) ); + assert_approx_eq!( + m.apply_pt(&pt3(0.0, -2.0, 0.0)), + pt3(0.0, 0.0, 2.0) + ); } #[cfg(feature = "fp")] @@ -786,6 +825,10 @@ mod tests { m.apply(&vec3(1.0, 0.0, 0.0)), vec3(0.0, 0.0, 1.0) ); + assert_approx_eq!( + m.apply_pt(&pt3(0.0, 0.0, -2.0)), + pt3(2.0, 0.0, 0.0) + ); } #[cfg(feature = "fp")] @@ -797,6 +840,10 @@ mod tests { m.apply(&vec3(0.0, 1.0, 0.0)), vec3(1.0, 0.0, 0.0) ); + assert_approx_eq!( + m.apply_pt(&pt3(-2.0, 0.0, 0.0)), + pt3(0.0, 2.0, 0.0) + ); } #[test] @@ -884,19 +931,19 @@ mod tests { #[test] fn orthographic_box_maps_to_unit_cube() { - let lbn = vec3(-20.0, 0.0, 0.01); - let rtf = vec3(100.0, 50.0, 100.0); + let lbn = pt3(-20.0, 0.0, 0.01); + let rtf = pt3(100.0, 50.0, 100.0); - let m = orthographic(lbn, rtf); + let m = orthographic(lbn.to_vec(), rtf.to_vec()); assert_approx_eq!(m.apply(&lbn.to()), [-1.0, -1.0, -1.0, 1.0].into()); - assert_approx_eq!(m.apply(&rtf.to()), splat(1.0)); + assert_approx_eq!(m.apply(&rtf.to()), [1.0, 1.0, 1.0, 1.0].into()); } #[test] fn perspective_frustum_maps_to_unit_cube() { - let left_bot_near = vec3(-0.125, -0.0625, 0.1); - let right_top_far = vec3(125.0, 62.5, 100.0); + let left_bot_near = pt3(-0.125, -0.0625, 0.1); + let right_top_far = pt3(125.0, 62.5, 100.0); let m = perspective(0.8, 2.0, 0.1..100.0); @@ -904,6 +951,6 @@ mod tests { assert_approx_eq!(lbn / lbn.w(), [-1.0, -1.0, -1.0, 1.0].into()); let rtf = m.apply(&right_top_far); - assert_approx_eq!(rtf / rtf.w(), splat(1.0)); + assert_approx_eq!(rtf / rtf.w(), [1.0, 1.0, 1.0, 1.0].into()); } } diff --git a/core/src/render.rs b/core/src/render.rs index 305fbd64..7f57582a 100644 --- a/core/src/render.rs +++ b/core/src/render.rs @@ -16,10 +16,9 @@ use crate::math::{ Lerp, }; -use crate::render::raster::ScreenVec; use clip::{view_frustum, Clip, ClipVert}; use ctx::{Context, DepthSort, FaceCull}; -use raster::tri_fill; +use raster::{tri_fill, ScreenVec}; use shader::{FragmentShader, VertexShader}; use stats::Stats; use target::Target; diff --git a/demos/src/bin/crates.rs b/demos/src/bin/crates.rs index 7a27cafe..fce3e483 100644 --- a/demos/src/bin/crates.rs +++ b/demos/src/bin/crates.rs @@ -3,7 +3,7 @@ use core::ops::ControlFlow::*; use re::prelude::*; use re::geom::Vertex3; -use re::math::color::gray; +use re::math::{color::gray, point::pt3}; use re::render::{ batch::Batch, cam::{Camera, FirstPerson}, @@ -121,7 +121,7 @@ fn floor() -> Mesh { for i in -size..=size { let even_odd = ((i & 1) ^ (j & 1)) == 1; - let pos = vec3(i as f32, -1.0, j as f32); + let pos = pt3(i as f32, -1.0, j as f32); let col = if even_odd { gray(0.2) } else { gray(0.9) }; bld.push_vert(pos, col); diff --git a/demos/src/bin/solids.rs b/demos/src/bin/solids.rs index ea58a87f..14ea9058 100644 --- a/demos/src/bin/solids.rs +++ b/demos/src/bin/solids.rs @@ -6,7 +6,8 @@ use re::prelude::*; use re::geom::Vertex3; use re::math::{ - color::gray, mat::RealToReal, spline::smootherstep, vec::ProjVec4, + color::gray, mat::RealToReal, point::pt2, spline::smootherstep, + vec::ProjVec4, }; use re::render::{batch::Batch, cam::Camera, ModelToProj, ModelToWorld}; @@ -157,11 +158,11 @@ fn objects(res: u32) -> [Mesh; 13] { fn lathe(secs: u32) -> Mesh { Lathe::new( vec![ - vertex(vec2(0.75, -0.5), vec2(1.0, 1.0)), - vertex(vec2(0.55, -0.25), vec2(1.0, 0.5)), - vertex(vec2(0.5, 0.0), vec2(1.0, 0.0)), - vertex(vec2(0.55, 0.25), vec2(1.0, -0.5)), - vertex(vec2(0.75, 0.5), vec2(1.0, 1.0)), + vertex(pt2(0.75, -0.5), vec2(1.0, 1.0)), + vertex(pt2(0.55, -0.25), vec2(1.0, 0.5)), + vertex(pt2(0.5, 0.0), vec2(1.0, 0.0)), + vertex(pt2(0.55, 0.25), vec2(1.0, -0.5)), + vertex(pt2(0.75, 0.5), vec2(1.0, 1.0)), ], secs, ) diff --git a/demos/src/bin/sprites.rs b/demos/src/bin/sprites.rs index 9ad8d116..f446b209 100644 --- a/demos/src/bin/sprites.rs +++ b/demos/src/bin/sprites.rs @@ -20,10 +20,11 @@ fn main() { ]; let count = 10000; let rng = Xorshift64::default(); + // TODO Points in unit ball and other distribs let verts: Vec>> = UnitBall .samples(rng) .take(count) - .flat_map(|pos| verts.map(|v| vertex(pos.to(), v))) + .flat_map(|pos| verts.map(|v| vertex(pos.to().to_pt(), v))) .collect(); let tris: Vec<_> = (0..count) @@ -40,7 +41,7 @@ fn main() { |v: Vertex3>, (mv, proj): (&Mat4x4, &Mat4x4)| { let vertex_pos = 0.008 * vec3(v.attrib.x(), v.attrib.y(), 0.0); - let view_pos = mv.apply(&v.pos) + vertex_pos; + let view_pos = mv.apply_pt(&v.pos) + vertex_pos; vertex(proj.apply(&view_pos), v.attrib) }, |frag: Frag>| { diff --git a/demos/src/bin/square.rs b/demos/src/bin/square.rs index abb5dcbe..2f44cb32 100644 --- a/demos/src/bin/square.rs +++ b/demos/src/bin/square.rs @@ -2,16 +2,20 @@ use std::ops::ControlFlow::*; use re::prelude::*; -use re::geom::Vertex3; -use re::render::{ctx::Context, render, tex::SamplerClamp, ModelToProj}; +use re::{ + geom::Vertex3, + math::point::pt3, + render::{ctx::Context, render, tex::SamplerClamp, ModelToProj}, +}; + use re_front::minifb::Window; fn main() { let verts: [Vertex3; 4] = [ - vertex(vec3(-1.0, -1.0, 0.0), uv(0.0, 0.0)), - vertex(vec3(-1.0, 1.0, 0.0), uv(0.0, 1.0)), - vertex(vec3(1.0, -1.0, 0.0), uv(1.0, 0.0)), - vertex(vec3(1.0, 1.0, 0.0), uv(1.0, 1.0)), + vertex(pt3(-1.0, -1.0, 0.0), uv(0.0, 0.0)), + vertex(pt3(-1.0, 1.0, 0.0), uv(0.0, 1.0)), + vertex(pt3(1.0, -1.0, 0.0), uv(1.0, 0.0)), + vertex(pt3(1.0, 1.0, 0.0), uv(1.0, 1.0)), ]; let mut win = Window::builder() diff --git a/demos/wasm/src/triangle.rs b/demos/wasm/src/triangle.rs index 3d857521..c8d62fe8 100644 --- a/demos/wasm/src/triangle.rs +++ b/demos/wasm/src/triangle.rs @@ -6,13 +6,13 @@ use re::geom::{vertex, Tri, Vertex3}; use re::math::{ color::{rgba, Color4f}, mat::{perspective, rotate_z, translate, viewport}, + point::pt3, rads, vec2, vec3, }; use re::render::{raster::Frag, render, shader::Shader, ModelToView}; use re::util::Dims; -use re_front::dims::SVGA_800_600; -use re_front::wasm::Window; +use re_front::{dims::SVGA_800_600, wasm::Window}; // Entry point from JS #[wasm_bindgen(start)] @@ -25,9 +25,9 @@ pub fn start() { win.ctx.color_clear = Some(rgba(0, 0, 0, 0x80)); let vs = [ - vertex(vec3(-2.0, 1.0, 0.0), rgba(1.0, 0.2, 0.1, 0.9)), - vertex(vec3(2.0, 2.0, 0.0), rgba(0.2, 0.9, 0.1, 0.8)), - vertex(vec3(0.0, -2.0, 0.0), rgba(0.3, 0.4, 1.0, 1.0)), + vertex(pt3(-2.0, 1.0, 0.0), rgba(1.0, 0.2, 0.1, 0.9)), + vertex(pt3(2.0, 2.0, 0.0), rgba(0.2, 0.9, 0.1, 0.8)), + vertex(pt3(0.0, -2.0, 0.0), rgba(0.3, 0.4, 1.0, 1.0)), ]; let proj = perspective(1.0, 4.0 / 3.0, 0.1..1000.0); diff --git a/geom/src/io.rs b/geom/src/io.rs index f16b52d0..0488dc26 100644 --- a/geom/src/io.rs +++ b/geom/src/io.rs @@ -37,11 +37,11 @@ //! f 1 2 3 4 5 //! ``` -use alloc::string::String; -use alloc::vec; -use core::fmt; -use core::num::{ParseFloatError, ParseIntError}; - +use alloc::{string::String, vec}; +use core::{ + fmt, + num::{ParseFloatError, ParseIntError}, +}; #[cfg(feature = "std")] use std::{ error, @@ -51,7 +51,10 @@ use std::{ }; use re::geom::{mesh::Builder, vertex, Mesh, Normal3, Tri}; -use re::math::vec::{vec3, Vec3, Vector}; +use re::math::{ + point::Point3, + vec::{vec3, Vec3, Vector}, +}; use re::render::{ tex::{uv, TexCoord}, Model, @@ -143,7 +146,7 @@ pub fn parse_obj(src: impl IntoIterator) -> Result> { match item.as_bytes() { [b'#', ..] => continue, // Skip comment - b"v" => verts.push(parse_vector(tokens)?), + b"v" => verts.push(parse_point(tokens)?), b"vt" => tcrds.push(parse_texcoord(tokens)?), b"vn" => norms.push(parse_normal(tokens)?), @@ -204,9 +207,8 @@ fn parse_texcoord<'a>( Ok(uv(u, v)) } -fn parse_vector<'a>( - i: &mut impl Iterator, -) -> Result> { +fn parse_vector<'a>(i: &mut impl Iterator) -> Result> +{ let x = next(i)?.parse()?; let y = next(i)?.parse()?; let z = next(i)?.parse()?; @@ -217,6 +219,12 @@ fn parse_normal<'a>(i: &mut impl Iterator) -> Result { parse_vector(i).map(Vector::to) } +fn parse_point<'a>( + i: &mut impl Iterator, +) -> Result> { + parse_vector(i).map(Vector::to_pt) +} + fn parse_index(s: &str) -> Result { // OBJ has one-based indices Ok(s.parse::()? - 1) @@ -291,8 +299,7 @@ impl From for Error { #[cfg(test)] mod tests { - use re::geom::Tri; - use re::math::vec3; + use re::{geom::Tri, math::point::pt3}; use super::*; @@ -312,7 +319,7 @@ v 1.0 2.0 0.0"; let mesh = parse_obj(input).unwrap().build(); assert_eq!(mesh.faces, vec![Tri([0, 1, 3]), Tri([3, 0, 2])]); - assert_eq!(mesh.verts[3].pos, vec3(1.0, 2.0, 0.0)); + assert_eq!(mesh.verts[3].pos, pt3(1.0, 2.0, 0.0)); } #[test] diff --git a/geom/src/solids.rs b/geom/src/solids.rs index 8f8d14fc..592639dc 100644 --- a/geom/src/solids.rs +++ b/geom/src/solids.rs @@ -1,9 +1,7 @@ //! Mesh approximations of various geometric shapes. -use core::array::from_fn; -use core::ops::Range; - use alloc::{vec, vec::Vec}; +use core::{array::from_fn, ops::Range}; use re::geom::{ mesh::Builder, vertex, Mesh, Normal2, Normal3, Vertex, Vertex2, @@ -11,8 +9,9 @@ use re::geom::{ use re::math::{ angle::{degs, polar, turns, Angle}, mat::rotate_y, + point::{pt2, pt3, Point3}, vary::Vary, - vec::{splat, vec2, vec3, Vec3}, + vec::{vec2, vec3, Vec3}, }; use re::render::tex::{uv, TexCoord}; @@ -49,9 +48,9 @@ pub struct Tetrahedron; #[derive(Copy, Clone, Debug)] pub struct Box { /// The left bottom near corner of the box. - pub left_bot_near: Vec3, + pub left_bot_near: Point3, /// The right top far corner of the box. - pub right_top_far: Vec3, + pub right_top_far: Point3, } /// Regular octahedron. @@ -164,12 +163,12 @@ impl Tetrahedron { use re::math::float::f32; let sqrt = f32::sqrt; let coords = [ - vec3(0.0, 1.0, 0.0), - vec3(sqrt(8.0 / 9.0), -1.0 / 3.0, 0.0), - vec3(-sqrt(2.0 / 9.0), -1.0 / 3.0, sqrt(2.0 / 3.0)), - vec3(-sqrt(2.0 / 9.0), -1.0 / 3.0, -sqrt(2.0 / 3.0)), + pt3(0.0, 1.0, 0.0), + pt3(sqrt(8.0 / 9.0), -1.0 / 3.0, 0.0), + pt3(-sqrt(2.0 / 9.0), -1.0 / 3.0, sqrt(2.0 / 3.0)), + pt3(-sqrt(2.0 / 9.0), -1.0 / 3.0, -sqrt(2.0 / 3.0)), ]; - let norms = [-coords[3], -coords[1], -coords[2], -coords[0]]; + let norms = [3, 1, 2, 0].map(|i| -coords[i].to_vec()); let mut b = Mesh::builder(); @@ -240,9 +239,10 @@ impl Box { /// Returns a cube centered on the origin, with the given side length. pub fn cube(side_len: f32) -> Self { + let l = 0.5 * side_len; Self { - left_bot_near: splat(-0.5 * side_len), - right_top_far: splat(0.5 * side_len), + left_bot_near: pt3(-l, -l, -l), + right_top_far: pt3(l, l, l), } } @@ -252,8 +252,8 @@ impl Box { b.push_faces(Self::FACES); for (pos_i, [norm_i, _uv_i]) in Self::VERTS { let pos = from_fn(|i| { - self.left_bot_near[i] - .lerp(&self.right_top_far[i], Self::COORDS[pos_i][i]) + self.left_bot_near.0[i] + .lerp(&self.right_top_far.0[i], Self::COORDS[pos_i][i]) }); b.push_vert(pos.into(), Self::NORMS[norm_i]); } @@ -262,13 +262,13 @@ impl Box { } impl Octahedron { - const COORDS: [Vec3; 6] = [ - vec3(-1.0, 0.0, 0.0), - vec3(0.0, -1.0, 0.0), - vec3(0.0, 0.0, -1.0), - vec3(0.0, 1.0, 0.0), - vec3(0.0, 0.0, 1.0), - vec3(1.0, 0.0, 0.0), + const COORDS: [Point3; 6] = [ + pt3(-1.0, 0.0, 0.0), + pt3(0.0, -1.0, 0.0), + pt3(0.0, 0.0, -1.0), + pt3(0.0, 1.0, 0.0), + pt3(0.0, 0.0, 1.0), + pt3(1.0, 0.0, 0.0), ]; const NORMS: [Normal3; 8] = [ vec3(-1.0, -1.0, -1.0), @@ -379,7 +379,7 @@ impl Dodecahedron { b.push_face(i5, i5 + 2, i5 + 3); b.push_face(i5, i5 + 3, i5 + 4); for &j in face { - b.push_vert(Self::COORDS[j].normalize(), n); + b.push_vert(Self::COORDS[j].normalize().to_pt(), n); } } b.build() @@ -424,7 +424,7 @@ impl Icosahedron { let n = Self::NORMALS[i].normalize(); b.push_face(3 * i, 3 * i + 1, 3 * i + 2); for vi in *vs { - b.push_vert(Self::COORDS[vi].normalize(), n); + b.push_vert(Self::COORDS[vi].normalize().to_pt(), n); } } b.build() @@ -463,12 +463,12 @@ impl Lathe { // Create vertices for Vertex { pos, attrib: n } in &pts { - let mut pos = start.apply(&vec3(pos.x(), pos.y(), 0.0)); + let mut pos = start.apply_pt(&pt3(pos.x(), pos.y(), 0.0)); let mut norm = start.apply(&vec3(n.x(), n.y(), 0.0)).normalize(); for _ in 0..=secs { b.push_vert(pos, norm); - pos = rot.apply(&pos); + pos = rot.apply_pt(&pos); norm = rot.apply(&norm); } } @@ -523,7 +523,7 @@ impl Sphere { let pts = degs(-90.0) .vary_to(degs(90.0), segments) .map(|alt| polar(radius, alt).to_cart()) - .map(|pos| vertex(pos, pos)) + .map(|pos| vertex(pos.to_pt(), pos)) .collect(); Lathe::new(pts, sectors).build() @@ -536,7 +536,7 @@ impl Torus { let pts = turns(0.0) .vary_to(turns(1.0), self.minor_sectors) .map(|alt| polar(self.minor_radius, alt).to_cart()) - .map(|v| vertex(vec2(self.major_radius, 0.0) + v, v)) + .map(|v| vertex(pt2(self.major_radius, 0.0) + v, v)) .collect(); Lathe::new(pts, self.major_sectors).build() @@ -560,8 +560,8 @@ impl Cylinder { impl Cone { /// Builds the conical mesh. pub fn build(self) -> Mesh { - let base_pt = vec2(self.base_radius, -1.0); - let apex_pt = vec2(self.apex_radius, 1.0); + let base_pt = pt2(self.base_radius, -1.0); + let apex_pt = pt2(self.apex_radius, 1.0); let n = apex_pt - base_pt; let n = vec2(n.y(), -n.x()); let pts = vec![vertex(base_pt, n), vertex(apex_pt, n)]; @@ -580,14 +580,14 @@ impl Capsule { let bottom_pts: Vec<_> = degs(-90.0) .vary_to(degs(0.0), cap_segments) .map(|alt| polar(radius, alt).to_cart()) - .map(|v| vertex(vec2(0.0, -1.0) + v, v)) + .map(|v| vertex(pt2(0.0, -1.0) + v, v)) .collect(); // Top hemisphere let top_pts = bottom_pts .iter() .map(|Vertex { pos, attrib: n }| { - vertex(vec2(pos.x(), -pos.y()), vec2(n.x(), -n.y())) + vertex(pt2(pos.x(), -pos.y()), vec2(n.x(), -n.y())) }) .rev();