Skip to content
Open
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
4 changes: 2 additions & 2 deletions core/src/geom/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,15 @@ impl<A> Builder<A> {
/// This is an eager operation, that is, only vertices *currently* added
/// to the builder are transformed. The attribute type of the result is
/// `Normal3`; the vertex type it accepts is changed accordingly.
pub fn with_vertex_normals(self) -> Builder<Normal3> {
pub fn with_vertex_normals(self) -> Builder<Normal3<Model>> {
let Mesh { verts, faces } = self.mesh;

// Compute weighted face normals...
let face_normals = faces.iter().map(|tri| {
// TODO If n-gonal faces are supported some day, the cross
// product is not proportional to area anymore
let [a, b, c] = tri.map(|i| verts[i].pos).0;
(b - a).cross(&(c - a)).to()
(b - a).cross(&(c - a))
});
// ...initialize vertex normals to zero...
let mut verts: Vec<_> = verts
Expand Down
17 changes: 8 additions & 9 deletions core/src/geom/prim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ pub struct Sphere<B = ()>(pub Point3<B>, pub f32);

/// A surface normal in 3D.
// TODO Use distinct type rather than alias
pub type Normal3 = Vec3;
pub type Normal3<B> = Vec3<B>;

/// A surface normal in 2D.
pub type Normal2 = Vec2;

Expand Down Expand Up @@ -248,10 +249,9 @@ impl<A, B> Tri<Vertex3<A, B>> {
/// ]);
/// assert_approx_eq!(tri.normal(), vec3(0.0, FRAC_1_SQRT_2, -FRAC_1_SQRT_2));
/// ```
pub fn normal(&self) -> Normal3 {
pub fn normal(&self) -> Normal3<B> {
let [t, u] = self.tangents();
// TODO add basis parameter to normals
t.cross(&u).normalize_or_zero().to()
t.cross(&u).normalize_or_zero()
}

/// Returns the plane that `self` lies on.
Expand Down Expand Up @@ -372,7 +372,7 @@ impl<B> Plane3<B> {
///
/// ```
pub fn from_points(a: Point3<B>, b: Point3<B>, c: Point3<B>) -> Self {
let n = (b - a).cross(&(c - a)).to();
let n = (b - a).cross(&(c - a));
Self::from_point_and_normal(a, n)
}

Expand All @@ -392,10 +392,9 @@ impl<B> Plane3<B> {
/// assert_eq!(p.offset(), 3.0);
///
/// ```
pub fn from_point_and_normal(pt: Point3<B>, n: Normal3) -> Self {
pub fn from_point_and_normal(pt: Point3<B>, n: Normal3<B>) -> Self {
let n = n.normalize();
let d = dot(&pt.0, &n.0);
Plane::new(n.x(), n.y(), n.z(), d)
Plane::new(n.x(), n.y(), n.z(), dot(&pt.0, &n.0))
}

/// Returns the normal vector of `self`.
Expand All @@ -409,7 +408,7 @@ impl<B> Plane3<B> {
/// assert_eq!(<Plane3>::XY.normal(), Vec3::Z);
/// assert_eq!(<Plane3>::YZ.normal(), Vec3::X);
#[inline]
pub fn normal(&self) -> Normal3 {
pub fn normal(&self) -> Normal3<B> {
let [a, b, c, _] = self.0.0;
let n = vec3(a, b, c);
debug_assert!(n.len_sqr().approx_eq(&1.0));
Expand Down
2 changes: 1 addition & 1 deletion core/src/render/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub fn ray<'a, B>(o: Point3<B>, dir: Vec3<B>) -> DbgBatch<B> {
pub fn face_normal<A, B: Debug + Default>(
tri: Tri<Vertex3<A, B>>,
) -> DbgBatch<B> {
ray(tri.centroid(), tri.normal().to())
ray(tri.centroid(), tri.normal())
}

/// Draws a visualization of an affine basis.
Expand Down
2 changes: 1 addition & 1 deletion core/src/render/tex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub const fn uv(u: f32, v: f32) -> TexCoord {
/// 1 +------+------+------+
///
/// ```
pub fn cube_map(pos: Vec3, dir: Normal3) -> TexCoord {
pub fn cube_map(pos: Vec3, dir: Normal3<()>) -> TexCoord {
// -1.0..1.0 -> 0.0..1.0
let [x, y, z] = (0.5 * pos + splat(0.5))
.clamp(&splat(0.0), &splat(1.0))
Expand Down
6 changes: 3 additions & 3 deletions demos/src/bin/crates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ fn main() {
},
);
let crate_shader = shader::new(
|v: Vertex3<(Normal3, TexCoord)>, mvp: &ProjMat3<_>| {
|v: Vertex3<(Normal3<_>, TexCoord)>, mvp: &ProjMat3<_>| {
vertex(mvp.apply(&v.pos), v.attrib)
},
|frag: Frag<(Normal3, TexCoord)>| {
|frag: Frag<(Normal3<_>, TexCoord)>| {
let (n, uv) = frag.var;
let kd = lerp(n.dot(&light_dir).max(0.0), 0.4, 1.0);
let col = SamplerClamp.sample(&tex, uv);
Expand Down Expand Up @@ -137,7 +137,7 @@ fn main() {
.expect("should run");
}

fn crates() -> Vec<Obj<(Normal3, TexCoord)>> {
fn crates() -> Vec<Obj<(Normal3<Model>, TexCoord)>> {
let obj = Obj::new(Cube { side_len: 2.0 }.build());

let mut res = vec![];
Expand Down
2 changes: 1 addition & 1 deletion demos/src/bin/curses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn main() {
|v: Vertex3<_>, mvp: &ProjMat3<Model>| {
vertex(mvp.apply(&v.pos), v.attrib)
},
|frag: Frag<Normal3>| {
|frag: Frag<Normal3<Model>>| {
let [x, y, z] = (frag.var / 2.0 + splat(0.5)).0;
rgb(x, y, z).to_color4()
},
Expand Down
39 changes: 23 additions & 16 deletions demos/src/bin/solids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use re::prelude::*;
use re::core::{
geom::Polyline,
math::{ProjMat3, ProjVec3, color::gray},
render::cam::Fov,
render::{Model, ModelToWorld, shader},
render::cam::{Fov, Transform},
render::{Model, ModelToWorld, View, shader},
};
use re::front::{Frame, minifb::Window};
use re::geom::{io::read_obj, solids::*};
Expand Down Expand Up @@ -63,15 +63,17 @@ fn main() {
.perspective(Fov::Equiv35mm(28.0), 0.1..1000.0)
.viewport(pt2(10, h - 10)..pt2(w - 10, 10));

type VertexIn = Vertex3<Normal3>;
type VertexIn = Vertex3<Normal3<Model>>;
type VertexOut = Vertex<ProjVec3, Color3f>;
type Uniform<'a> = (&'a ProjMat3<Model>, &'a Mat4);

fn vtx_shader(v: VertexIn, (mvp, spin): Uniform) -> VertexOut {
type NormalMat = Mat3<Model, View, 3>;
type Uniform<'a> = (&'a ProjMat3<Model>, &'a NormalMat);

fn vtx_shader(v: VertexIn, (mvp, n): Uniform) -> VertexOut {
// Transform vertex normal
let norm = spin.apply(&v.attrib);
let norm = n.apply(&v.attrib);
// Calculate diffuse shading
let diffuse = (norm.z() + 0.2).max(0.2) * 0.8;
let diffuse = (-norm.z() + 0.2).max(0.2) * 0.8;
// Visualize normal by mapping to RGB values
let [r, g, b] = (0.45 * (v.attrib + splat(1.1))).0;
let col = diffuse * rgb(r, g, b);
Expand Down Expand Up @@ -108,12 +110,17 @@ fn main() {
.to::<ModelToWorld>()
.then(&cam.world_to_project());

let normal: NormalMat = spin
.to()
.linear()
.then(&cam.transform.world_to_view().linear());

let object = &objects[carousel.idx % objects.len()];

Batch {
prims: object.faces.clone(),
verts: object.verts.clone(),
uniform: (&model_view_project, &spin),
uniform: (&model_view_project, &normal),
shader: shader,
viewport: cam.viewport,
target: frame.buf,
Expand All @@ -127,7 +134,7 @@ fn main() {

// Creates the 14 objects exhibited.
#[rustfmt::skip]
fn objects_n(res: u32) -> [Mesh<Normal3>; 14] {
fn objects_n(res: u32) -> [Mesh<Normal3<Model>>; 14] {
let segments = res;
let sectors = 2 * res;

Expand Down Expand Up @@ -160,7 +167,7 @@ fn objects_n(res: u32) -> [Mesh<Normal3>; 14] {
}

// Creates a Lathe mesh.
fn lathe(secs: u32) -> Mesh<Normal3> {
fn lathe(secs: u32) -> Mesh<Normal3<Model>> {
let pts = [
(pt2(0.75, -0.5), vec2(1.0, 1.0)),
(pt2(0.55, -0.25), vec2(1.0, 0.5)),
Expand All @@ -176,10 +183,10 @@ fn lathe(secs: u32) -> Mesh<Normal3> {
}

// Loads the Utah teapot model.
fn teapot() -> Mesh<Normal3> {
fn teapot() -> Mesh<Normal3<Model>> {
static TEAPOT: &[u8] = include_bytes!("../../assets/teapot.obj");
read_obj(TEAPOT)
.unwrap()
.expect("valid .obj, included in binary")
.transform(
&scale(splat(0.4))
.then(&translate(-0.5 * Vec3::Y))
Expand All @@ -189,20 +196,20 @@ fn teapot() -> Mesh<Normal3> {
}

// Loads the Stanford bunny model.
fn bunny() -> Mesh<Normal3> {
fn bunny() -> Mesh<Normal3<Model>> {
static BUNNY: &[u8] = include_bytes!("../../assets/bunny.obj");
read_obj::<()>(BUNNY)
.unwrap()
.expect("valid .obj, included in binary")
.transform(&scale(splat(0.12)).then(&translate(-Vec3::Y)).to())
.with_vertex_normals()
.build()
}

// Loads the Stanford dragon model.
fn dragon() -> Mesh<Normal3> {
fn dragon() -> Mesh<Normal3<Model>> {
static DRAGON: &[u8] = include_bytes!("../../assets/dragon.obj");
read_obj::<()>(DRAGON)
.unwrap()
.expect("valid .obj, included in binary")
.with_vertex_normals()
.transform(
&scale(splat(0.18))
Expand Down
16 changes: 9 additions & 7 deletions geom/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub enum Error {
pub struct Obj {
faces: Vec<Tri<Indices>>,
coords: Vec<Point3<Model>>,
norms: Vec<Normal3>,
norms: Vec<Normal3<Model>>,
texcs: Vec<TexCoord>,
}

Expand Down Expand Up @@ -235,7 +235,7 @@ impl TryFrom<Obj> for Builder<()> {
o.try_into_with(|_| Some(()))
}
}
impl TryFrom<Obj> for Builder<Normal3> {
impl TryFrom<Obj> for Builder<Normal3<Model>> {
type Error = Error;

fn try_from(o: Obj) -> Result<Self> {
Expand All @@ -255,7 +255,7 @@ impl TryFrom<Obj> for Builder<TexCoord> {
o.try_into_with(|i| i.uv.map(|ti| o.texcs[ti]))
}
}
impl TryFrom<Obj> for Builder<(Normal3, TexCoord)> {
impl TryFrom<Obj> for Builder<(Normal3<Model>, TexCoord)> {
type Error = Error;

fn try_from(o: Obj) -> Result<Self> {
Expand Down Expand Up @@ -335,8 +335,10 @@ fn parse_vector<'a>(
Ok(vec3(x, y, z))
}

fn parse_normal<'a>(i: &mut impl Iterator<Item = &'a str>) -> Result<Normal3> {
Ok(parse_vector(i)?.to())
fn parse_normal<'a>(
i: &mut impl Iterator<Item = &'a str>,
) -> Result<Normal3<Model>> {
Ok(parse_vector(i)?)
}

fn parse_point<'a>(
Expand Down Expand Up @@ -506,7 +508,7 @@ v 0.0 -2.0 0.0
v 1.0 2.0 3.0
vn 0.0 0.0 -1.0";

let m: Mesh<Normal3> = parse_obj(input).unwrap().build();
let m: Mesh<Normal3<_>> = parse_obj(input).unwrap().build();

assert_eq!(m.faces.len(), 2);
assert_eq!(m.verts.len(), 5);
Expand Down Expand Up @@ -585,7 +587,7 @@ v 0.0 -2.0 0.0
vt 0.0 -1.0
vn 0.0 0.0 1.0";

let m = &parse_obj::<(Normal3, TexCoord)>(input)
let m = &parse_obj::<(Normal3<_>, TexCoord)>(input)
.unwrap()
.build();
assert_eq!(m.faces.len(), 2);
Expand Down
7 changes: 4 additions & 3 deletions geom/src/solids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use retrofire_core::math::{Lerp, Vec3};
pub use lathe::*;

pub use platonic::*;
use retrofire_core::render::Model;

pub trait Build<A>: Sized {
fn build(self) -> Mesh<A>;
Expand All @@ -24,8 +25,8 @@ pub trait Build<A>: Sized {

pub struct Icosphere(pub f32, pub u8);

impl Build<Normal3> for Icosphere {
fn build(self) -> Mesh<Normal3> {
impl Build<Normal3<Model>> for Icosphere {
fn build(self) -> Mesh<Normal3<Model>> {
#[derive(Default)]
struct Tessellator {
coords: Vec<Vec3>,
Expand Down Expand Up @@ -70,7 +71,7 @@ impl Build<Normal3> for Icosphere {
}

let verts = recurser.coords.iter().map(|&p| {
vertex((p.normalize() * self.0).to().to_pt(), p.normalize())
vertex((p.normalize() * self.0).to().to_pt(), p.normalize().to())
});

Mesh::new(recurser.faces, verts)
Expand Down
Loading
Loading