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
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ lto = "thin"
opt-level = 1
split-debuginfo = "unpacked"


[[bench]]
name = "fill"
harness = false
Expand All @@ -85,3 +84,7 @@ harness = false
[[bench]]
name = "isect"
harness = false

[[bench]]
name = "vec"
harness = false
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ for custom allocators is planned in order to make `alloc` optional as well.
* Type-tagged affine and linear transforms and projections
* Perspective-correct texture mapping
* Triangle mesh data structure and a library of shapes
* Point, directional, and spotlight support
* Cubic Bézier, Hermite, Catmull–Rom, and B-splines
* Simple random number generation and distributions
* Simple text rendering with bitmap fonts
Expand All @@ -68,8 +69,7 @@ for custom allocators is planned in order to make `alloc` optional as well.
## In progress

* Different camera types
* Builtin light source support
* Spherical etc UV mapping
* Spherical etc. UV mapping
* Procedural noise generation
* Terminal frontend with ncurses
* Cube mapping and skyboxes
Expand Down
32 changes: 32 additions & 0 deletions benches/vec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! Triangle clipping benchmarks.

use divan::Bencher;
use divan::counter::ItemsCount;
use retrofire_core::{
math::rand::{DefaultRng, Distrib},
math::{Vec3, splat},
};

#[divan::bench]
fn normalize_exact(b: Bencher) {
let rng = &mut DefaultRng::default();
let vecs = splat(-1e6)..splat(1e6);

b.with_inputs(|| vecs.sample(rng))
.input_counter(|_| ItemsCount::new(1u32))
.bench_local_values(|v: Vec3| v.normalize());
}

#[divan::bench]
fn normalize_approx(b: Bencher) {
let rng = &mut DefaultRng::default();
let vecs = splat(-1e6)..splat(1e6);

b.with_inputs(|| vecs.sample(rng))
.input_counter(|_| ItemsCount::new(1u32))
.bench_local_values(|v: Vec3| v.normalize_approx());
}

fn main() {
divan::main()
}
4 changes: 2 additions & 2 deletions core/examples/hello_tri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn main() {
// Interpolate vertex colors in linear color space
vertex(mvp.apply(&v.pos), v.attrib.to_linear())
},
|frag: Frag<Color3f<_>>| frag.var.to_srgb().to_color4(),
|frag: Frag<Color3f<_>>, _| frag.var.to_srgb().to_color4(),
);
#[cfg(not(feature = "fp"))]
let shader = shader::new(
Expand All @@ -24,7 +24,7 @@ fn main() {
// Interpolate vertex colors in normal sRGB color space
vertex(mvp.apply(&v.pos), v.attrib)
},
|frag: Frag<Color3f<_>>| frag.var.to_color4(),
|frag: Frag<Color3f<_>>, _| frag.var.to_color4(),
);

let dims @ (w, h) = (640, 480);
Expand Down
39 changes: 24 additions & 15 deletions core/src/geom/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use core::{
};

use crate::{
math::{Linear, Mat4, Point3},
math::{Linear, Mat4, Point3, degs},
render::Model,
};

Expand Down Expand Up @@ -35,6 +35,13 @@ pub struct Builder<Attrib = (), Basis = Model> {
pub mesh: Mesh<Attrib, Basis>,
}

#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Weight {
Equal,
Area,
Angle,
}

//
// Inherent impls
//
Expand Down Expand Up @@ -205,27 +212,29 @@ impl<A> Builder<A> {
pub fn with_vertex_normals(self) -> Builder<Normal3> {
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()
});
// ...initialize vertex normals to zero...
// Initialize vertex normals to zero...
let mut verts: Vec<_> = verts
.iter()
.into_iter()
.map(|v| vertex(v.pos, Normal3::zero()))
.collect();
// ...accumulate normals...
for (&Tri(vs), n) in zip(&faces, face_normals) {
for i in vs {
verts[i].attrib += n;
}
for tri in &faces {
let [i, j, k] = tri.0;
let [ab, ac] = tri.map(|i| verts[i]).tangents();
let bc = ac - ab;
let n = ab.cross(&ac).to().normalize_approx();
let a_a = ab.angle(&ac);
let a_b = (-ab).angle(&bc);
let a_c = degs(180.0) - a_a - a_b;

// Angle unit does not matter, the normals get normalized anyway
verts[i].attrib += n; //a_a.to_rads() * n;
verts[j].attrib += n; //a_b.to_rads() * n;
verts[k].attrib += n; //a_c.to_rads() * n;
}
// ...and normalize to unit length.
for v in &mut verts {
v.attrib = v.attrib.normalize();
v.attrib = v.attrib.normalize_or_zero();
}

// No need to sanity check again
Expand Down
1 change: 1 addition & 0 deletions core/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub fn lerp<T: Lerp>(t: f32, from: T, to: T) -> T {
/// ```
#[inline]
pub fn inv_lerp(t: f32, min: f32, max: f32) -> f32 {
debug_assert!(!min.approx_eq(&max));
(t - min) / (max - min)
}

Expand Down
9 changes: 7 additions & 2 deletions core/src/math/angle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use core::{
ops::{AddAssign, DivAssign, MulAssign, SubAssign},
};

use crate::math::{Affine, ApproxEq, Linear, Vector, vary::ZDiv};
use super::{Affine, ApproxEq, Linear, Vector, vary::ZDiv};
#[cfg(feature = "fp")]
use crate::math::{Vec2, Vec3, float::f32, vec2, vec3};
use super::{Vec2, Vec3, float::f32, vec2, vec3};

//
// Types
Expand Down Expand Up @@ -77,6 +77,7 @@ pub const fn turns(a: f32) -> Angle {
/// # Panics
/// If `x` is outside the range [-1.0, 1.0].
#[cfg(feature = "fp")]
#[inline]
pub fn asin(x: f32) -> Angle {
assert!(-1.0 <= x && x <= 1.0);
Angle(f32::asin(x))
Expand All @@ -96,6 +97,7 @@ pub fn asin(x: f32) -> Angle {
/// # Panics
/// If `x` is outside the range [-1.0, 1.0].
#[cfg(feature = "fp")]
#[inline]
pub fn acos(x: f32) -> Angle {
Angle(f32::acos(x))
}
Expand All @@ -113,11 +115,13 @@ pub fn acos(x: f32) -> Angle {
/// assert_eq!(atan2(-3.0, 0.0), degs(-90.0));
/// ```
#[cfg(feature = "fp")]
#[inline]
pub fn atan2(y: f32, x: f32) -> Angle {
Angle(f32::atan2(y, x))
}

/// Returns a polar coordinate vector with azimuth `az` and radius `r`.
#[inline]
pub const fn polar<B>(r: f32, az: Angle) -> PolarVec<B> {
Vector::new([r, az.to_rads()])
}
Expand All @@ -126,6 +130,7 @@ pub const fn polar<B>(r: f32, az: Angle) -> PolarVec<B> {
/// altitude `alt`, and radius `r`.
///
/// An altitude of +90° corresponds to straight up and -90° to straight down.
#[inline]
pub const fn spherical<B>(r: f32, az: Angle, alt: Angle) -> SphericalVec<B> {
Vector::new([r, az.to_rads(), alt.to_rads()])
}
Expand Down
23 changes: 15 additions & 8 deletions core/src/math/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ pub mod mm {
}

pub mod fallback {
use crate::math::float::fast_recip_sqrt;

/// Returns the largest integer less than or equal to `x`.
#[inline]
pub fn floor(x: f32) -> f32 {
Expand All @@ -119,21 +121,26 @@ pub mod fallback {
/// Returns the approximate reciprocal of the square root of `x`.
#[inline]
pub fn recip_sqrt(x: f32) -> f32 {
if x < 0.0 {
return f32::NAN;
}
// https://en.wikipedia.org/wiki/Fast_inverse_square_root
let y = f32::from_bits(0x5f37_5a86 - (x.to_bits() >> 1));
// Two rounds of Newton's method
let y = y * (1.5 - 0.5 * x * y * y);
y * (1.5 - 0.5 * x * y * y)
fast_recip_sqrt(x)
}
#[inline]
pub fn sqrt(x: f32) -> f32 {
1.0 / recip_sqrt(x)
}
}

/// Returns a fast approximation of the reciprocal square root of a number.
#[inline]
pub fn fast_recip_sqrt(x: f32) -> f32 {
// https://en.wikipedia.org/wiki/Fast_inverse_square_root
const MAGIC: u32 = 0x5f37_5a86;
let mut y = f32::from_bits(MAGIC.saturating_sub(x.to_bits() >> 1));
// A round of Newton's method
y = y * (1.5 - 0.5 * x * y * y);
//y = y * (1.5 - 0.5 * x * y * y);
y
}

#[cfg(feature = "std")]
#[allow(non_camel_case_types)]
pub type f32 = core::primitive::f32;
Expand Down
Loading
Loading