Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to using points as vertex coordinates #196

Merged
merged 2 commits into from
Dec 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions core/src/geom.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -15,10 +18,10 @@ pub struct Vertex<P, A> {
}

/// Two-dimensional vertex type.
pub type Vertex2<A, B = Model> = Vertex<Vec2<B>, A>;
pub type Vertex2<A, B = Model> = Vertex<Point2<B>, A>;

/// Three-dimensional vertex type.
pub type Vertex3<A, B = Model> = Vertex<Vec3<B>, A>;
pub type Vertex3<A, B = Model> = Vertex<Point3<B>, A>;

/// Triangle, defined by three vertices.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Expand Down
42 changes: 22 additions & 20 deletions core/src/geom/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -51,16 +51,17 @@ impl<A, B> Mesh<A, B> {
/// # 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]),
Expand Down Expand Up @@ -126,16 +127,16 @@ impl<A> Builder<A> {
}

/// 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<Vs>(&mut self, verts: Vs)
where
Vs: IntoIterator<Item = (Vec3, A)>,
Vs: IntoIterator<Item = (Point3, A)>,
{
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);
}

Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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;

Expand All @@ -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), ()),
],
);
}
Expand All @@ -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();
}
Expand All @@ -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();

Expand Down
83 changes: 65 additions & 18 deletions core/src/math/mat.rs
Original file line number Diff line number Diff line change
@@ -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.
///
Expand Down Expand Up @@ -199,9 +206,16 @@ impl<Src, Dst> Mat3x3<RealToReal<2, Src, Dst>> {
/// ```
#[must_use]
pub fn apply(&self, v: &Vec2<Src>) -> Vec2<Dst> {
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<Src>) -> Point2<Dst> {
let p = [p.x(), p.y(), 1.0].into();
array::from_fn(|i| self.row_vec(i).dot(&p)).into()
}
}

impl<Src, Dst> Mat4x4<RealToReal<3, Src, Dst>> {
Expand All @@ -218,10 +232,17 @@ impl<Src, Dst> Mat4x4<RealToReal<3, Src, Dst>> {
/// ```
#[must_use]
pub fn apply(&self, v: &Vec3<Src>) -> Vec3<Dst> {
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<Src>) -> Point3<Dst> {
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,
Expand Down Expand Up @@ -365,7 +386,7 @@ impl<Src> Mat4x4<RealToProj<Src>> {
/// \ · · M33 / \ 1 /
/// ```
#[must_use]
pub fn apply(&self, v: &Vec3<Src>) -> ProjVec4 {
pub fn apply(&self, v: &Point3<Src>) -> ProjVec4 {
let v = Vector::from([v.x(), v.y(), v.z(), 1.0]);
[
self.row_vec(0).dot(&v),
Expand Down Expand Up @@ -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<ViewToProj> {
let [dx, dy, dz] = (rtf - lbn).0;
let [sx, sy, sz] = (rtf + lbn).0;
Expand Down Expand Up @@ -639,6 +661,7 @@ mod tests {

#[cfg(feature = "fp")]
use crate::math::angle::degs;
use crate::math::point::pt3;

use super::*;

Expand All @@ -652,6 +675,7 @@ mod tests {

mod mat3x3 {
use super::*;
use crate::math::point::pt2;

const MAT: Mat3x3<Map> = Matrix::new([
[0.0, 1.0, 2.0], //
Expand Down Expand Up @@ -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]
Expand All @@ -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]
Expand All @@ -723,6 +749,7 @@ mod tests {

mod mat4x4 {
use super::*;
use crate::math::point::pt3;

const MAT: Mat4x4<Map> = Matrix::new([
[0.0, 1.0, 2.0, 3.0],
Expand Down Expand Up @@ -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")]
Expand All @@ -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")]
Expand All @@ -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")]
Expand All @@ -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]
Expand Down Expand Up @@ -884,26 +931,26 @@ 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);

let lbn = m.apply(&left_bot_near);
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());
}
}
3 changes: 1 addition & 2 deletions core/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions demos/src/bin/crates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -121,7 +121,7 @@ fn floor() -> Mesh<Color3f> {
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);

Expand Down
Loading
Loading