Skip to content

Commit

Permalink
add quat wasm methods
Browse files Browse the repository at this point in the history
  • Loading branch information
andykswong committed Mar 14, 2024
1 parent aa2856d commit b132fef
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 20 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
"scripts": {
"prepublishOnly": "npm run build && npm test && npm run docs",
"clean": "rimraf coverage/ docs/ dist/ target/ **/__tests__/**/*.spec.map **/__tests__/**/*.spec.wat",
"build:rust": "cargo rustc -r --target wasm32-unknown-unknown --crate-type cdylib -F jsmath,wasm --no-default-features",
"postbuild:rust": "wasm-opt -Oz -o dist/munum.wasm target/wasm32-unknown-unknown/release/munum.wasm",
"build:wasm": "cargo rustc -r --target wasm32-unknown-unknown --crate-type cdylib -F jsmath,wasm,std --no-default-features",
"postbuild:wasm": "npm run build:wit && npm run build:wasm-opt",
"build:wit": "wasm-tools component embed -o dist/munum.wasm -w root wit/ target/wasm32-unknown-unknown/release/munum.wasm",
"build:wasm-opt": "wasm-opt -Oz -o dist/munum.wasm dist/munum.wasm",
"prebuild": "npm run lint",
"build": "npm run tsc",
"lint": "eslint assembly --ext .ts,.tsx",
Expand Down
11 changes: 2 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
//! Micro Library for 3D Math
#![cfg_attr(not(test), no_std)]
#![no_std]

#[cfg(test)]
extern crate alloc;

#[cfg(feature = "std")]
#[cfg(any(feature = "std", test))]
extern crate std;

mod matrix;
Expand All @@ -25,9 +24,3 @@ pub use quat::{quat, Quaternion};

#[cfg(target_arch = "wasm32")]
mod wasm;

#[cfg(all(target_arch = "wasm32", feature = "wasm", not(test)))]
#[panic_handler]
fn panic(_panic: &core::panic::PanicInfo<'_>) -> ! {
core::arch::wasm32::unreachable()
}
4 changes: 2 additions & 2 deletions src/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ impl<T: Copy + NumAssign, const R: usize, const C: usize> Index<usize> for Matri

#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.0[index / R][index % R]
&self.0[(index / R) % C][index % R]
}
}

impl<T: Copy + NumAssign, const R: usize, const C: usize> IndexMut<usize> for Matrix<T, R, C> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index / R][index % R]
&mut self.0[(index / R) % C][index % R]
}
}

Expand Down
22 changes: 20 additions & 2 deletions src/quat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,14 +377,17 @@ impl<T: Copy + NumAssign> Quaternion<T> {
/// ```
/// # use munum::Quaternion;
/// let mut q = <Quaternion>::from_slice(&[2., 5., 14., 8.]);
/// q.invert();
/// assert!(q.invert());
/// assert_eq!(*q.as_ref(), [-2. / 289., -5. / 289., -14. / 289., 8. / 289.]);
/// ```
pub fn invert(&mut self) {
pub fn invert(&mut self) -> bool {
self.conj();
let len2 = self.sqr_len();
if len2 != T::zero() {
*self /= len2;
true
} else {
false
}
}

Expand Down Expand Up @@ -434,6 +437,21 @@ impl<T: Copy + FloatOps + NumAssign + Signed> Quaternion<T> {
self.0.normalize()
}

/// Returns a normalized version of this vector.
///
/// # Examples
/// ```
/// # use munum::{Quaternion, assert_float_eq};
/// let q = <Quaternion>::from_slice(&[2., 5., 14., 8.]).normalized();
/// assert_float_eq!(q.as_ref(), &[2./17., 5./17., 14./17., 8./17.]);
/// ```
#[inline]
pub fn normalized(&self) -> Self {
let mut q = *self;
q.normalize();
q
}

/// Linear interpolates between 2 unit `Quaternion`s.
///
/// # Examples
Expand Down
9 changes: 9 additions & 0 deletions src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,12 @@ mod jsmath;

#[cfg(feature = "wasm")]
mod vec;

#[cfg(feature = "wasm")]
mod quat;

#[cfg(all(feature = "wasm", not(any(feature = "std", test))))]
#[panic_handler]
fn panic(_panic: &core::panic::PanicInfo<'_>) -> ! {
core::arch::wasm32::unreachable()
}
17 changes: 15 additions & 2 deletions src/wasm/ptr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Matrix;
use crate::{Matrix, Quaternion};
use num::traits::NumAssign;

/// Trait for loading a value from a pointer.
Expand All @@ -15,7 +15,20 @@ impl<T: Copy + NumAssign, const R: usize, const C: usize> Load<Matrix<T, R, C>>
if let Some(&m) = unsafe { self.as_ref() } {
m
} else {
Matrix::<T, R, C>::default()
Matrix::default()
}
}
}

impl<T: Copy + NumAssign> Load<Quaternion<T>>
for *const Quaternion<T>
{
#[inline]
fn load(&self) -> Quaternion<T> {
if let Some(&q) = unsafe { self.as_ref() } {
q
} else {
Quaternion::default()
}
}
}
176 changes: 176 additions & 0 deletions src/wasm/quat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
use super::ptr::Load;
use crate::{Quaternion, Vec3};
use alloc::boxed::Box;

#[export_name = concat!("munum:wasm/quat#create")]
pub extern "C" fn quat_create(x: f64, y: f64, z: f64, w: f64) -> *const Quaternion<f64> {
Box::into_raw(Box::new(Quaternion::new(x, y, z, w)))
}

#[export_name = concat!("munum:wasm/quat#from-unit-vecs")]
pub extern "C" fn quat_from_unit_vecs(
from: *const Vec3<f64>,
to: *const Vec3<f64>,
) -> *const Quaternion<f64> {
Box::into_raw(Box::new(Quaternion::from_unit_vecs(from.load(), to.load())))
}

#[export_name = concat!("munum:wasm/quat#from-axis-angle")]
pub extern "C" fn quat_from_axis_angle(
axis: *const Vec3<f64>,
angle: f64,
) -> *const Quaternion<f64> {
Box::into_raw(Box::new(Quaternion::from_axis_angle(axis.load(), angle)))
}

#[export_name = concat!("munum:wasm/quat#from-angle-x")]
pub extern "C" fn quat_from_angle_x(angle: f64) -> *const Quaternion<f64> {
Box::into_raw(Box::new(Quaternion::from_angle_x(angle)))
}

#[export_name = concat!("munum:wasm/quat#from-angle-y")]
pub extern "C" fn quat_from_angle_y(angle: f64) -> *const Quaternion<f64> {
Box::into_raw(Box::new(Quaternion::from_angle_y(angle)))
}

#[export_name = concat!("munum:wasm/quat#from-angle-z")]
pub extern "C" fn quat_from_angle_z(angle: f64) -> *const Quaternion<f64> {
Box::into_raw(Box::new(Quaternion::from_angle_z(angle)))
}

#[export_name = concat!("munum:wasm/quat#free")]
pub extern "C" fn quat_free(ptr: *mut Quaternion<f64>) {
drop(unsafe { Box::from_raw(ptr) })
}

#[export_name = "munum:wasm/quat#set"]
pub extern "C" fn quat_set(
out: *mut Quaternion<f64>,
x: f64,
y: f64,
z: f64,
w: f64,
) -> *const Quaternion<f64> {
if let Some(q) = unsafe { out.as_mut() } {
q[0] = x;
q[1] = y;
q[2] = z;
q[3] = w;
}
out
}

#[export_name = concat!("munum:wasm/quat#get")]
pub extern "C" fn quat_get(ptr: *const Quaternion<f64>) -> *const Quaternion<f64> {
ptr
}

#[export_name = concat!("munum:wasm/quat#copy")]
pub extern "C" fn quat_copy(
dst: *mut Quaternion<f64>,
src: *const Quaternion<f64>,
) -> *const Quaternion<f64> {
if let Some(o) = unsafe { dst.as_mut() } {
*o = src.load();
}
dst
}

#[export_name = concat!("munum:wasm/quat#mul")]
pub extern "C" fn quat_mul(
out: *mut Quaternion<f64>,
a: *const Quaternion<f64>,
b: *const Quaternion<f64>,
) -> *const Quaternion<f64> {
if let Some(o) = unsafe { out.as_mut() } {
*o = a.load() * b.load();
}
out
}

#[export_name = concat!("munum:wasm/quat#rotate-vec3")]
pub extern "C" fn quat_rotate_vec3(
out: *mut Vec3<f64>,
q: *const Quaternion<f64>,
v: *const Vec3<f64>,
) -> *const Vec3<f64> {
if let Some(o) = unsafe { out.as_mut() } {
*o = q.load().rotate_vec3(v.load())
}
out
}

#[export_name = concat!("munum:wasm/quat#norm")]
pub extern "C" fn quat_norm(
out: *mut Quaternion<f64>,
q: *const Quaternion<f64>,
) -> *const Quaternion<f64> {
if let Some(o) = unsafe { out.as_mut() } {
*o = q.load();
o.normalize();
}
out
}

#[export_name = concat!("munum:wasm/quat#dot")]
pub extern "C" fn quat_dot(a: *const Quaternion<f64>, b: *const Quaternion<f64>) -> f64 {
a.load().dot(b.load())
}

#[export_name = concat!("munum:wasm/quat#sqr-len")]
pub extern "C" fn quat_sqr_len(q: *const Quaternion<f64>) -> f64 {
q.load().sqr_len()
}

#[export_name = concat!("munum:wasm/quat#len")]
pub extern "C" fn quat_len(q: *const Quaternion<f64>) -> f64 {
q.load().len()
}

#[export_name = concat!("munum:wasm/quat#conj")]
pub extern "C" fn quat_conj(
out: *mut Quaternion<f64>,
q: *const Quaternion<f64>,
) -> *const Quaternion<f64> {
if let Some(o) = unsafe { out.as_mut() } {
*o = q.load();
o.conj();
}
out
}

#[export_name = concat!("munum:wasm/quat#invert")]
pub extern "C" fn quat_invert(out: *mut Quaternion<f64>, q: *const Quaternion<f64>) -> bool {
if let Some(o) = unsafe { out.as_mut() } {
*o = q.load();
o.invert()
} else {
false
}
}

#[export_name = concat!("munum:wasm/quat#lerp")]
pub extern "C" fn quat_lerp(
out: *mut Quaternion<f64>,
a: *const Quaternion<f64>,
b: *const Quaternion<f64>,
t: f64,
) -> *const Quaternion<f64> {
if let Some(o) = unsafe { out.as_mut() } {
*o = a.load().lerp(b.load(), t);
}
out
}

#[export_name = concat!("munum:wasm/quat#slerp")]
pub extern "C" fn quat_slerp(
out: *mut Quaternion<f64>,
a: *const Quaternion<f64>,
b: *const Quaternion<f64>,
t: f64,
) -> *const Quaternion<f64> {
if let Some(o) = unsafe { out.as_mut() } {
*o = a.load().slerp(b.load(), t);
}
out
}
23 changes: 22 additions & 1 deletion src/wasm/vec.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
use super::ptr::Load;
use crate::{Mat2, Mat3, Mat4, Vec2, Vec3, Vec4};
use alloc::boxed::Box;
use paste::paste;

macro_rules! export_vec {
($name:ident, $vec_type:ty, $mat_type:ty, $t:ty) => {
paste! {
#[export_name = concat!("munum:wasm/", stringify!($name), "#free")]
pub extern "C" fn [<$name _free>](ptr: *mut $vec_type) {
drop(unsafe { Box::from_raw(ptr) })
}

#[export_name = concat!("munum:wasm/", stringify!($name), "#get")]
pub extern "C" fn [<$name _get>](ptr: *const $t) -> *const $t {
pub extern "C" fn [<$name _get>](ptr: *const $vec_type) -> *const $vec_type {
ptr
}

Expand Down Expand Up @@ -105,6 +111,11 @@ export_vec!(vec2, Vec2<f64>, Mat2<f64>, f64);
export_vec!(vec3, Vec3<f64>, Mat3<f64>, f64);
export_vec!(vec4, Vec4<f64>, Mat4<f64>, f64);

#[export_name = "munum:wasm/vec2#create"]
pub extern "C" fn vec2_create(x: f64, y: f64) -> *const Vec2<f64> {
Box::into_raw(Box::new(Vec2::new([[x, y]])))
}

#[export_name = "munum:wasm/vec2#set"]
pub extern "C" fn vec2_set(out: *mut Vec2<f64>, x: f64, y: f64) -> *const Vec2<f64> {
if let Some(v) = unsafe { out.as_mut() } {
Expand All @@ -114,6 +125,11 @@ pub extern "C" fn vec2_set(out: *mut Vec2<f64>, x: f64, y: f64) -> *const Vec2<f
out
}

#[export_name = "munum:wasm/vec3#create"]
pub extern "C" fn vec3_create(x: f64, y: f64, z: f64) -> *const Vec3<f64> {
Box::into_raw(Box::new(Vec3::new([[x, y, z]])))
}

#[export_name = "munum:wasm/vec3#set"]
pub extern "C" fn vec3_set(out: *mut Vec3<f64>, x: f64, y: f64, z: f64) -> *const Vec3<f64> {
if let Some(v) = unsafe { out.as_mut() } {
Expand All @@ -124,6 +140,11 @@ pub extern "C" fn vec3_set(out: *mut Vec3<f64>, x: f64, y: f64, z: f64) -> *cons
out
}

#[export_name = "munum:wasm/vec4#create"]
pub extern "C" fn vec4_create(x: f64, y: f64, z: f64, w: f64) -> *const Vec4<f64> {
Box::into_raw(Box::new(Vec4::new([[x, y, z, w]])))
}

#[export_name = "munum:wasm/vec4#set"]
pub extern "C" fn vec4_set(
out: *mut Vec4<f64>,
Expand Down
4 changes: 2 additions & 2 deletions wit/world.wit
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package munum/wasm;
package munum:wasm;

interface vec2 {
type pvec2 = u32;
Expand Down Expand Up @@ -90,7 +90,7 @@ interface quat {
sqr-len: func(a: pquat) -> f64;
len: func(a: pquat) -> f64;
conj: func(out: pquat, a: pquat) -> pquat;
invert: func(out: pquat, a: pquat) -> pquat;
invert: func(out: pquat, a: pquat) -> bool;
lerp: func(out: pquat, a: pquat, b: pquat, t: f64) -> pquat;
slerp: func(out: pquat, a: pquat, b: pquat, t: f64) -> pquat;
}
Expand Down

0 comments on commit b132fef

Please sign in to comment.