Skip to content

Commit 8bcbdbf

Browse files
committed
Add basis parameter to Normal3
1 parent 898dbe7 commit 8bcbdbf

File tree

11 files changed

+90
-81
lines changed

11 files changed

+90
-81
lines changed

core/src/geom/mesh.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,15 +202,15 @@ impl<A> Builder<A> {
202202
/// This is an eager operation, that is, only vertices *currently* added
203203
/// to the builder are transformed. The attribute type of the result is
204204
/// `Normal3`; the vertex type it accepts is changed accordingly.
205-
pub fn with_vertex_normals(self) -> Builder<Normal3> {
205+
pub fn with_vertex_normals(self) -> Builder<Normal3<Model>> {
206206
let Mesh { verts, faces } = self.mesh;
207207

208208
// Compute weighted face normals...
209209
let face_normals = faces.iter().map(|tri| {
210210
// TODO If n-gonal faces are supported some day, the cross
211211
// product is not proportional to area anymore
212212
let [a, b, c] = tri.map(|i| verts[i].pos).0;
213-
(b - a).cross(&(c - a)).to()
213+
(b - a).cross(&(c - a))
214214
});
215215
// ...initialize vertex normals to zero...
216216
let mut verts: Vec<_> = verts

core/src/geom/prim.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ pub struct Sphere<B = ()>(pub Point3<B>, pub f32);
6666

6767
/// A surface normal in 3D.
6868
// TODO Use distinct type rather than alias
69-
pub type Normal3 = Vec3;
69+
pub type Normal3<B> = Vec3<B>;
70+
7071
/// A surface normal in 2D.
7172
pub type Normal2 = Vec2;
7273

@@ -248,10 +249,9 @@ impl<A, B> Tri<Vertex3<A, B>> {
248249
/// ]);
249250
/// assert_approx_eq!(tri.normal(), vec3(0.0, FRAC_1_SQRT_2, -FRAC_1_SQRT_2));
250251
/// ```
251-
pub fn normal(&self) -> Normal3 {
252+
pub fn normal(&self) -> Normal3<B> {
252253
let [t, u] = self.tangents();
253-
// TODO add basis parameter to normals
254-
t.cross(&u).normalize_or_zero().to()
254+
t.cross(&u).normalize_or_zero()
255255
}
256256

257257
/// Returns the plane that `self` lies on.
@@ -372,7 +372,7 @@ impl<B> Plane3<B> {
372372
///
373373
/// ```
374374
pub fn from_points(a: Point3<B>, b: Point3<B>, c: Point3<B>) -> Self {
375-
let n = (b - a).cross(&(c - a)).to();
375+
let n = (b - a).cross(&(c - a));
376376
Self::from_point_and_normal(a, n)
377377
}
378378

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

401400
/// Returns the normal vector of `self`.
@@ -409,7 +408,7 @@ impl<B> Plane3<B> {
409408
/// assert_eq!(<Plane3>::XY.normal(), Vec3::Z);
410409
/// assert_eq!(<Plane3>::YZ.normal(), Vec3::X);
411410
#[inline]
412-
pub fn normal(&self) -> Normal3 {
411+
pub fn normal(&self) -> Normal3<B> {
413412
let [a, b, c, _] = self.0.0;
414413
let n = vec3(a, b, c);
415414
debug_assert!(n.len_sqr().approx_eq(&1.0));

core/src/render/debug.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub fn ray<'a, B>(o: Point3<B>, dir: Vec3<B>) -> DbgBatch<B> {
9090
pub fn face_normal<A, B: Debug + Default>(
9191
tri: Tri<Vertex3<A, B>>,
9292
) -> DbgBatch<B> {
93-
ray(tri.centroid(), tri.normal().to())
93+
ray(tri.centroid(), tri.normal())
9494
}
9595

9696
/// Draws a visualization of an affine basis.

core/src/render/tex.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub const fn uv(u: f32, v: f32) -> TexCoord {
8080
/// 1 +------+------+------+
8181
///
8282
/// ```
83-
pub fn cube_map(pos: Vec3, dir: Normal3) -> TexCoord {
83+
pub fn cube_map(pos: Vec3, dir: Normal3<()>) -> TexCoord {
8484
// -1.0..1.0 -> 0.0..1.0
8585
let [x, y, z] = (0.5 * pos + splat(0.5))
8686
.clamp(&splat(0.0), &splat(1.0))

demos/src/bin/crates.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ fn main() {
3636
},
3737
);
3838
let crate_shader = shader::new(
39-
|v: Vertex3<(Normal3, TexCoord)>, mvp: &ProjMat3<_>| {
39+
|v: Vertex3<(Normal3<_>, TexCoord)>, mvp: &ProjMat3<_>| {
4040
vertex(mvp.apply(&v.pos), v.attrib)
4141
},
42-
|frag: Frag<(Normal3, TexCoord)>| {
42+
|frag: Frag<(Normal3<_>, TexCoord)>| {
4343
let (n, uv) = frag.var;
4444
let kd = lerp(n.dot(&light_dir).max(0.0), 0.4, 1.0);
4545
let col = SamplerClamp.sample(&tex, uv);
@@ -137,7 +137,7 @@ fn main() {
137137
.expect("should run");
138138
}
139139

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

143143
let mut res = vec![];

demos/src/bin/curses.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn main() {
5050
|v: Vertex3<_>, mvp: &ProjMat3<Model>| {
5151
vertex(mvp.apply(&v.pos), v.attrib)
5252
},
53-
|frag: Frag<Normal3>| {
53+
|frag: Frag<Normal3<Model>>| {
5454
let [x, y, z] = (frag.var / 2.0 + splat(0.5)).0;
5555
rgb(x, y, z).to_color4()
5656
},

demos/src/bin/solids.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use re::prelude::*;
77
use re::core::{
88
geom::Polyline,
99
math::{ProjMat3, ProjVec3, color::gray},
10-
render::cam::Fov,
11-
render::{Model, ModelToWorld, shader},
10+
render::cam::{Fov, Transform},
11+
render::{Model, ModelToWorld, View, shader},
1212
};
1313
use re::front::{Frame, minifb::Window};
1414
use re::geom::{io::read_obj, solids::*};
@@ -63,15 +63,17 @@ fn main() {
6363
.perspective(Fov::Equiv35mm(28.0), 0.1..1000.0)
6464
.viewport(pt2(10, h - 10)..pt2(w - 10, 10));
6565

66-
type VertexIn = Vertex3<Normal3>;
66+
type VertexIn = Vertex3<Normal3<Model>>;
6767
type VertexOut = Vertex<ProjVec3, Color3f>;
68-
type Uniform<'a> = (&'a ProjMat3<Model>, &'a Mat4);
6968

70-
fn vtx_shader(v: VertexIn, (mvp, spin): Uniform) -> VertexOut {
69+
type NormalMat = Mat3<Model, View, 3>;
70+
type Uniform<'a> = (&'a ProjMat3<Model>, &'a NormalMat);
71+
72+
fn vtx_shader(v: VertexIn, (mvp, n): Uniform) -> VertexOut {
7173
// Transform vertex normal
72-
let norm = spin.apply(&v.attrib);
74+
let norm = n.apply(&v.attrib);
7375
// Calculate diffuse shading
74-
let diffuse = (norm.z() + 0.2).max(0.2) * 0.8;
76+
let diffuse = (-norm.z() + 0.2).max(0.2) * 0.8;
7577
// Visualize normal by mapping to RGB values
7678
let [r, g, b] = (0.45 * (v.attrib + splat(1.1))).0;
7779
let col = diffuse * rgb(r, g, b);
@@ -108,12 +110,17 @@ fn main() {
108110
.to::<ModelToWorld>()
109111
.then(&cam.world_to_project());
110112

113+
let normal: NormalMat = spin
114+
.to()
115+
.linear()
116+
.then(&cam.transform.world_to_view().linear());
117+
111118
let object = &objects[carousel.idx % objects.len()];
112119

113120
Batch {
114121
prims: object.faces.clone(),
115122
verts: object.verts.clone(),
116-
uniform: (&model_view_project, &spin),
123+
uniform: (&model_view_project, &normal),
117124
shader: shader,
118125
viewport: cam.viewport,
119126
target: frame.buf,
@@ -127,7 +134,7 @@ fn main() {
127134

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

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

162169
// Creates a Lathe mesh.
163-
fn lathe(secs: u32) -> Mesh<Normal3> {
170+
fn lathe(secs: u32) -> Mesh<Normal3<Model>> {
164171
let pts = [
165172
(pt2(0.75, -0.5), vec2(1.0, 1.0)),
166173
(pt2(0.55, -0.25), vec2(1.0, 0.5)),
@@ -176,10 +183,10 @@ fn lathe(secs: u32) -> Mesh<Normal3> {
176183
}
177184

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

191198
// Loads the Stanford bunny model.
192-
fn bunny() -> Mesh<Normal3> {
199+
fn bunny() -> Mesh<Normal3<Model>> {
193200
static BUNNY: &[u8] = include_bytes!("../../assets/bunny.obj");
194201
read_obj::<()>(BUNNY)
195-
.unwrap()
202+
.expect("valid .obj, included in binary")
196203
.transform(&scale(splat(0.12)).then(&translate(-Vec3::Y)).to())
197204
.with_vertex_normals()
198205
.build()
199206
}
200207

201208
// Loads the Stanford dragon model.
202-
fn dragon() -> Mesh<Normal3> {
209+
fn dragon() -> Mesh<Normal3<Model>> {
203210
static DRAGON: &[u8] = include_bytes!("../../assets/dragon.obj");
204211
read_obj::<()>(DRAGON)
205-
.unwrap()
212+
.expect("valid .obj, included in binary")
206213
.with_vertex_normals()
207214
.transform(
208215
&scale(splat(0.18))

geom/src/io.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ pub enum Error {
7979
pub struct Obj {
8080
faces: Vec<Tri<Indices>>,
8181
coords: Vec<Point3<Model>>,
82-
norms: Vec<Normal3>,
82+
norms: Vec<Normal3<Model>>,
8383
texcs: Vec<TexCoord>,
8484
}
8585

@@ -235,7 +235,7 @@ impl TryFrom<Obj> for Builder<()> {
235235
o.try_into_with(|_| Some(()))
236236
}
237237
}
238-
impl TryFrom<Obj> for Builder<Normal3> {
238+
impl TryFrom<Obj> for Builder<Normal3<Model>> {
239239
type Error = Error;
240240

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

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

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

342344
fn parse_point<'a>(
@@ -506,7 +508,7 @@ v 0.0 -2.0 0.0
506508
v 1.0 2.0 3.0
507509
vn 0.0 0.0 -1.0";
508510

509-
let m: Mesh<Normal3> = parse_obj(input).unwrap().build();
511+
let m: Mesh<Normal3<_>> = parse_obj(input).unwrap().build();
510512

511513
assert_eq!(m.faces.len(), 2);
512514
assert_eq!(m.verts.len(), 5);
@@ -585,7 +587,7 @@ v 0.0 -2.0 0.0
585587
vt 0.0 -1.0
586588
vn 0.0 0.0 1.0";
587589

588-
let m = &parse_obj::<(Normal3, TexCoord)>(input)
590+
let m = &parse_obj::<(Normal3<_>, TexCoord)>(input)
589591
.unwrap()
590592
.build();
591593
assert_eq!(m.faces.len(), 2);

geom/src/solids.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use retrofire_core::math::{Lerp, Vec3};
1313
pub use lathe::*;
1414

1515
pub use platonic::*;
16+
use retrofire_core::render::Model;
1617

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

2526
pub struct Icosphere(pub f32, pub u8);
2627

27-
impl Build<Normal3> for Icosphere {
28-
fn build(self) -> Mesh<Normal3> {
28+
impl Build<Normal3<Model>> for Icosphere {
29+
fn build(self) -> Mesh<Normal3<Model>> {
2930
#[derive(Default)]
3031
struct Tessellator {
3132
coords: Vec<Vec3>,
@@ -70,7 +71,7 @@ impl Build<Normal3> for Icosphere {
7071
}
7172

7273
let verts = recurser.coords.iter().map(|&p| {
73-
vertex((p.normalize() * self.0).to().to_pt(), p.normalize())
74+
vertex((p.normalize() * self.0).to().to_pt(), p.normalize().to())
7475
});
7576

7677
Mesh::new(recurser.faces, verts)

0 commit comments

Comments
 (0)