mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-22 06:45:13 +00:00
Convert to use glam
for math types (#149)
* [spirv-std] Remove math types * Temp implementation of copysign https://github.com/EmbarkStudios/rust-gpu/issues/148 * Convert shader to use glam * Rustfmt * Fix wgpu-example-shader to use glam * [spirv-std] Disable clippy::use_self * Upgrade to latest glam branch * Use latest glam fork * Remove incorrect assert_uninit After discussions with @khyperia * Update lockfile * Update to latest glam fork with fixes * Use real copysign intrinsic * Disable clippy on example-shader for now Tracked in https://github.com/EmbarkStudios/rust-gpu/issues/186
This commit is contained in:
parent
b47ff73b44
commit
98eb8d369c
5
.github/workflows/clippy.sh
vendored
5
.github/workflows/clippy.sh
vendored
@ -34,7 +34,10 @@ clippy rustc_codegen_spirv
|
||||
clippy spirv-builder
|
||||
|
||||
# Examples
|
||||
clippy examples/example-runner
|
||||
|
||||
# disabled due to https://github.com/EmbarkStudios/rust-gpu/issues/186
|
||||
#clippy examples/example-runner
|
||||
|
||||
clippy examples/wgpu-example-runner
|
||||
|
||||
clippy_no_features examples/example-runner-cpu
|
||||
|
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -605,15 +605,16 @@ name = "example-runner-cpu"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"example-shader",
|
||||
"glam",
|
||||
"minifb",
|
||||
"rayon",
|
||||
"spirv-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "example-shader"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"spirv-std",
|
||||
]
|
||||
|
||||
@ -933,6 +934,11 @@ dependencies = [
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.9.5"
|
||||
source = "git+https://github.com/EmbarkStudios/glam-rs?rev=262e4e1b86e54dbd7772a9c1f342abd30a438282#262e4e1b86e54dbd7772a9c1f342abd30a438282"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
@ -2930,6 +2936,7 @@ dependencies = [
|
||||
name = "wgpu-example-shader"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"spirv-std",
|
||||
]
|
||||
|
||||
|
@ -12,3 +12,7 @@ members = [
|
||||
"spirv-tools",
|
||||
"spirv-tools-sys",
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
# https://github.com/bitshifter/glam-rs/pull/85
|
||||
glam = { git = "https://github.com/EmbarkStudios/glam-rs", rev = "262e4e1b86e54dbd7772a9c1f342abd30a438282" }
|
||||
|
@ -9,8 +9,7 @@ license = "MIT OR Apache-2.0"
|
||||
minifb = "0.19.1"
|
||||
# bring in the shader as natively compiled code
|
||||
example-shader = { path = "../example-shader" }
|
||||
# for math types, likely get from glam directly later instead
|
||||
spirv-std = { path = "../../spirv-std" }
|
||||
glam = { version = "0.9", default_features = false }
|
||||
|
||||
# for parallelism, not really needed though
|
||||
rayon = "1.5"
|
||||
|
@ -1,6 +1,6 @@
|
||||
use glam::{vec2, Vec4};
|
||||
use minifb::{Key, Window, WindowOptions};
|
||||
use rayon::prelude::*;
|
||||
use spirv_std::{vec2, Vec4};
|
||||
use std::time::Instant;
|
||||
|
||||
fn color_u32_from_vec4(v: Vec4) -> u32 {
|
||||
|
@ -10,3 +10,4 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
spirv-std = { path = "../../spirv-std" }
|
||||
glam = { version = "0.9", default_features = false }
|
@ -6,26 +6,39 @@
|
||||
#![register_attr(spirv)]
|
||||
|
||||
use core::f32::consts::PI;
|
||||
use spirv_std::{Input, Mat4, MathExt, Output, Vec2, Vec3, Vec4};
|
||||
use glam::{const_vec3, Mat4, Vec2, Vec3, Vec4};
|
||||
use spirv_std::{Input, MathExt, Output};
|
||||
|
||||
const DEPOLARIZATION_FACTOR: f32 = 0.035;
|
||||
const LUMINANCE: f32 = 1.0;
|
||||
const MIE_COEFFICIENT: f32 = 0.005;
|
||||
const MIE_DIRECTIONAL_G: f32 = 0.8;
|
||||
const MIE_K_COEFFICIENT: Vec3 = Vec3::new(0.686, 0.678, 0.666);
|
||||
const MIE_K_COEFFICIENT: Vec3 = const_vec3!([0.686, 0.678, 0.666]);
|
||||
const MIE_V: f32 = 4.0;
|
||||
const MIE_ZENITH_LENGTH: f32 = 1.25e3;
|
||||
const NUM_MOLECULES: f32 = 2.542e25f32;
|
||||
const PRIMARIES: Vec3 = Vec3::new(6.8e-7f32, 5.5e-7f32, 4.5e-7f32);
|
||||
const PRIMARIES: Vec3 = const_vec3!([6.8e-7f32, 5.5e-7f32, 4.5e-7f32]);
|
||||
const RAYLEIGH: f32 = 1.0;
|
||||
const RAYLEIGH_ZENITH_LENGTH: f32 = 8.4e3;
|
||||
const REFRACTIVE_INDEX: f32 = 1.0003;
|
||||
const SUN_ANGULAR_DIAMETER_DEGREES: f32 = 0.0093333;
|
||||
const SUN_INTENSITY_FACTOR: f32 = 1000.0;
|
||||
const SUN_INTENSITY_FALLOFF_STEEPNESS: f32 = 1.5;
|
||||
const TONEMAP_WEIGHTING: Vec3 = Vec3::splat(9.50);
|
||||
const TONEMAP_WEIGHTING: Vec3 = const_vec3!([9.50; 3]);
|
||||
const TURBIDITY: f32 = 2.0;
|
||||
|
||||
// TODO: add this to glam? Rust std has it on f32/f64
|
||||
fn pow(v: Vec3, power: f32) -> Vec3 {
|
||||
let v: [f32; 3] = v.into();
|
||||
Vec3::new(v[0].pow(power), v[1].pow(power), v[2].pow(power))
|
||||
}
|
||||
|
||||
// TODO: add this to glam? Rust std has it on f32/f64
|
||||
fn exp(v: Vec3) -> Vec3 {
|
||||
let v: [f32; 3] = v.into();
|
||||
Vec3::new(v[0].exp(), v[1].exp(), v[2].exp())
|
||||
}
|
||||
|
||||
/// Based on: https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/
|
||||
fn acos_approx(v: f32) -> f32 {
|
||||
let x = v.abs();
|
||||
@ -51,12 +64,12 @@ fn total_rayleigh(lambda: Vec3) -> Vec3 {
|
||||
(8.0 * PI.pow(3.0)
|
||||
* (REFRACTIVE_INDEX.pow(2.0) - 1.0).pow(2.0)
|
||||
* (6.0 + 3.0 * DEPOLARIZATION_FACTOR))
|
||||
/ (3.0 * NUM_MOLECULES * lambda.pow(4.0) * (6.0 - 7.0 * DEPOLARIZATION_FACTOR))
|
||||
/ (3.0 * NUM_MOLECULES * pow(lambda, 4.0) * (6.0 - 7.0 * DEPOLARIZATION_FACTOR))
|
||||
}
|
||||
|
||||
fn total_mie(lambda: Vec3, k: Vec3, t: f32) -> Vec3 {
|
||||
let c = 0.2 * t * 10e-18;
|
||||
0.434 * c * PI * ((2.0 * PI) / lambda).pow(MIE_V - 2.0) * k
|
||||
0.434 * c * PI * pow((2.0 * PI) / lambda, MIE_V - 2.0) * k
|
||||
}
|
||||
|
||||
fn rayleigh_phase(cos_theta: f32) -> f32 {
|
||||
@ -78,19 +91,19 @@ fn sun_intensity(zenith_angle_cos: f32) -> f32 {
|
||||
}
|
||||
|
||||
fn uncharted2_tonemap(w: Vec3) -> Vec3 {
|
||||
const A: Vec3 = Vec3::splat(0.15); // Shoulder strength
|
||||
const B: Vec3 = Vec3::splat(0.50); // Linear strength
|
||||
const C: Vec3 = Vec3::splat(0.10); // Linear angle
|
||||
const D: Vec3 = Vec3::splat(0.20); // Toe strength
|
||||
const E: Vec3 = Vec3::splat(0.02); // Toe numerator
|
||||
const F: Vec3 = Vec3::splat(0.30); // Toe denominator
|
||||
const A: Vec3 = const_vec3!([0.15; 3]); // Shoulder strength
|
||||
const B: Vec3 = const_vec3!([0.50; 3]); // Linear strength
|
||||
const C: Vec3 = const_vec3!([0.10; 3]); // Linear angle
|
||||
const D: Vec3 = const_vec3!([0.20; 3]); // Toe strength
|
||||
const E: Vec3 = const_vec3!([0.02; 3]); // Toe numerator
|
||||
const F: Vec3 = const_vec3!([0.30; 3]); // Toe denominator
|
||||
|
||||
((w * (A * w + C * B) + D * E) / (w * (A * w + B) + D * F)) - E / F
|
||||
}
|
||||
|
||||
fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 {
|
||||
let up = Vec3::new(0.0, 1.0, 0.0);
|
||||
let sunfade = 1.0 - (1.0 - (sun_position.1 / 450000.0).exp()).saturate();
|
||||
let sunfade = 1.0 - (1.0 - (sun_position.y() / 450000.0).exp()).saturate();
|
||||
let rayleigh_coefficient = RAYLEIGH - (1.0 * (1.0 - sunfade));
|
||||
let beta_r = total_rayleigh(PRIMARIES) * rayleigh_coefficient;
|
||||
|
||||
@ -105,7 +118,7 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 {
|
||||
let s_m = MIE_ZENITH_LENGTH / denom;
|
||||
|
||||
// Combined extinction factor
|
||||
let fex = (-(beta_r * s_r + beta_m * s_m)).exp();
|
||||
let fex = exp(-(beta_r * s_r + beta_m * s_m));
|
||||
|
||||
// In-scattering
|
||||
let sun_direction = sun_position.normalize();
|
||||
@ -114,11 +127,16 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 {
|
||||
|
||||
let beta_m_theta = beta_m * henyey_greenstein_phase(cos_theta, MIE_DIRECTIONAL_G);
|
||||
let sun_e = sun_intensity(sun_direction.dot(up));
|
||||
let mut lin =
|
||||
(sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * (Vec3::splat(1.0) - fex))
|
||||
.pow(1.5);
|
||||
let mut lin = pow(
|
||||
sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * (Vec3::splat(1.0) - fex),
|
||||
1.5,
|
||||
);
|
||||
|
||||
lin *= Vec3::splat(1.0).lerp(
|
||||
(sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * fex).pow(0.5),
|
||||
pow(
|
||||
sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * fex,
|
||||
0.5,
|
||||
),
|
||||
((1.0 - up.dot(sun_direction)).pow(5.0)).saturate(),
|
||||
);
|
||||
|
||||
@ -140,50 +158,24 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 {
|
||||
let curr = uncharted2_tonemap(((2.0 / LUMINANCE.pow(4.0)).log2()) * tex_color);
|
||||
let color = curr * white_scale;
|
||||
|
||||
color.pow(1.0 / (1.2 + (1.2 * sunfade)))
|
||||
}
|
||||
|
||||
pub fn main_fs_test(screen_pos: Vec2) -> Vec4 {
|
||||
// hard-code information because we can't bind buffers at the moment
|
||||
let eye_pos = Vec3(0.0, 0.0997, 0.2);
|
||||
let sun_pos = Vec3::new(0.0, 75.0, -1000.0);
|
||||
let clip_to_world = Mat4 {
|
||||
x_axis: Vec4(-0.5522849, 0.0, 0.0, 0.0),
|
||||
y_axis: Vec4(0.0, 0.4096309, -0.061444636, 0.0),
|
||||
z_axis: Vec4(0.0, 99.99999, 199.99998, 999.99994),
|
||||
w_axis: Vec4(0.0, -0.14834046, -0.98893654, 0.0),
|
||||
};
|
||||
|
||||
let cs_pos = Vec4(screen_pos.0, -screen_pos.1, 1.0, 1.0);
|
||||
let ws_pos = {
|
||||
let p = clip_to_world.mul_vec4(cs_pos);
|
||||
p.truncate() / p.3
|
||||
};
|
||||
let dir = (ws_pos - eye_pos).normalize();
|
||||
|
||||
// evaluate Preetham sky model
|
||||
let color = sky(dir, sun_pos);
|
||||
|
||||
// let color = dir;
|
||||
|
||||
color.extend(1.0)
|
||||
pow(color, 1.0 / (1.2 + (1.2 * sunfade)))
|
||||
}
|
||||
|
||||
pub fn fs(screen_pos: Vec2) -> Vec4 {
|
||||
// hard-code information because we can't bind buffers at the moment
|
||||
let eye_pos = Vec3(0.0, 0.0997, 0.2);
|
||||
let eye_pos = Vec3::new(0.0, 0.0997, 0.2);
|
||||
let sun_pos = Vec3::new(0.0, 75.0, -1000.0);
|
||||
let clip_to_world = Mat4 {
|
||||
x_axis: Vec4(-0.5522849, 0.0, 0.0, 0.0),
|
||||
y_axis: Vec4(0.0, 0.4096309, -0.061444636, 0.0),
|
||||
z_axis: Vec4(0.0, 99.99999, 199.99998, 999.99994),
|
||||
w_axis: Vec4(0.0, -0.14834046, -0.98893654, 0.0),
|
||||
};
|
||||
let clip_to_world = Mat4::from_cols(
|
||||
Vec4::new(-0.5522849, 0.0, 0.0, 0.0),
|
||||
Vec4::new(0.0, 0.4096309, -0.061444636, 0.0),
|
||||
Vec4::new(0.0, 99.99999, 199.99998, 999.99994),
|
||||
Vec4::new(0.0, -0.14834046, -0.98893654, 0.0),
|
||||
);
|
||||
|
||||
let cs_pos = Vec4(screen_pos.0, -screen_pos.1, 1.0, 1.0);
|
||||
let cs_pos = Vec4::new(screen_pos.x(), -screen_pos.y(), 1.0, 1.0);
|
||||
let ws_pos = {
|
||||
let p = clip_to_world.mul_vec4(cs_pos);
|
||||
p.truncate() / p.3
|
||||
p.truncate() / p.w()
|
||||
};
|
||||
let dir = (ws_pos - eye_pos).normalize();
|
||||
|
||||
@ -197,7 +189,7 @@ pub fn fs(screen_pos: Vec2) -> Vec4 {
|
||||
#[spirv(fragment)]
|
||||
pub fn main_fs(input: Input<Vec4>, mut output: Output<Vec4>) {
|
||||
let v = input.load();
|
||||
let color = fs(Vec2::new(v.0, v.1));
|
||||
let color = fs(Vec2::new(v.x(), v.y()));
|
||||
output.store(color)
|
||||
}
|
||||
|
||||
|
@ -10,3 +10,4 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
spirv-std = { path = "../../spirv-std" }
|
||||
glam = { version = "0.9", default_features = false }
|
@ -3,7 +3,8 @@
|
||||
#![feature(register_attr)]
|
||||
#![register_attr(spirv)]
|
||||
|
||||
use spirv_std::{Input, Output, Vec4};
|
||||
use glam::Vec4;
|
||||
use spirv_std::{Input, Output};
|
||||
|
||||
#[allow(unused_attributes)]
|
||||
#[spirv(fragment)]
|
||||
|
@ -11,7 +11,6 @@ use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_mir::interpret::Scalar;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::abi::{self, AddressSpace, HasDataLayout, LayoutOf, Primitive, Size};
|
||||
use std::ops::Range;
|
||||
|
||||
impl<'tcx> CodegenCx<'tcx> {
|
||||
pub fn constant_u8(&self, val: u8) -> SpirvValue {
|
||||
@ -405,7 +404,6 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
"create_const_alloc must consume all bytes of an Allocation after an unsized struct"
|
||||
);
|
||||
}
|
||||
Self::assert_uninit(alloc, base, *offset, occupied_spaces);
|
||||
self.constant_composite(ty, values)
|
||||
}
|
||||
SpirvType::Opaque { name } => self.tcx.sess.fatal(&format!(
|
||||
@ -508,21 +506,4 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
*offset += Size::from_bytes(len);
|
||||
Pointer::new_with_tag(alloc_id, Size::from_bytes(inner_offset), ())
|
||||
}
|
||||
|
||||
fn assert_uninit(
|
||||
alloc: &Allocation,
|
||||
start: Size,
|
||||
end: Size,
|
||||
occupied_ranges: Vec<Range<Size>>,
|
||||
) {
|
||||
// Range<Size> doesn't impl Iterator, so manually do it.
|
||||
let mut index = start;
|
||||
while index < end {
|
||||
assert_eq!(
|
||||
occupied_ranges.iter().any(|range| range.contains(&index)),
|
||||
alloc.init_mask().get(index)
|
||||
);
|
||||
index += Size::from_bytes(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
clippy::enum_glob_use,
|
||||
clippy::pub_enum_variant_names,
|
||||
clippy::mem_forget,
|
||||
clippy::use_self,
|
||||
clippy::filter_map_next,
|
||||
clippy::needless_continue,
|
||||
clippy::needless_borrow,
|
||||
@ -37,9 +36,8 @@
|
||||
nonstandard_style
|
||||
)]
|
||||
|
||||
pub mod math;
|
||||
pub use crate::math::MathExt;
|
||||
pub use crate::math::*;
|
||||
mod math_ext;
|
||||
pub use math_ext::MathExt;
|
||||
|
||||
macro_rules! pointer_addrspace_write {
|
||||
(false) => {};
|
||||
|
@ -1,242 +0,0 @@
|
||||
use super::{Vec2, Vec4};
|
||||
use core::ops::{Add, Mul, Sub};
|
||||
|
||||
/// Creates a `Mat2` from two column vectors.
|
||||
#[inline]
|
||||
pub fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
|
||||
Mat2::from_cols(x_axis, y_axis)
|
||||
}
|
||||
|
||||
/// A 2x2 column major matrix.
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
|
||||
pub struct Mat2(pub Vec4);
|
||||
|
||||
impl Default for Mat2 {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl Mat2 {
|
||||
/// Creates a 2x2 matrix with all elements set to `0.0`.
|
||||
#[inline]
|
||||
pub const fn zero() -> Self {
|
||||
Self(Vec4::zero())
|
||||
}
|
||||
|
||||
/// Creates a 2x2 identity matrix.
|
||||
#[inline]
|
||||
pub const fn identity() -> Self {
|
||||
Self(Vec4::new(1.0, 0.0, 0.0, 1.0))
|
||||
}
|
||||
|
||||
/// Creates a 2x2 matrix from two column vectors.
|
||||
#[inline]
|
||||
pub fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
|
||||
Self(Vec4::new(x_axis.x(), x_axis.y(), y_axis.x(), y_axis.y()))
|
||||
}
|
||||
|
||||
/// Creates a 2x2 matrix from a `[f32; 4]` stored in column major order. If
|
||||
/// your data is stored in row major you will need to `transpose` the
|
||||
/// returned matrix.
|
||||
#[inline]
|
||||
pub fn from_cols_array(m: &[f32; 4]) -> Self {
|
||||
Self(Vec4::new(m[0], m[1], m[2], m[3]))
|
||||
}
|
||||
|
||||
/// Creates a `[f32; 4]` storing data in column major order.
|
||||
/// If you require data in row major order `transpose` the matrix first.
|
||||
#[inline]
|
||||
pub fn to_cols_array(&self) -> [f32; 4] {
|
||||
self.0.into()
|
||||
}
|
||||
|
||||
/// Creates a 2x2 matrix from a `[[f32; 2]; 2]` stored in column major
|
||||
/// order. If your data is in row major order you will need to `transpose`
|
||||
/// the returned matrix.
|
||||
#[inline]
|
||||
pub fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
|
||||
Self(Vec4::new(m[0][0], m[0][1], m[1][0], m[1][1]))
|
||||
}
|
||||
|
||||
/// Creates a `[[f32; 2]; 2]` storing data in column major order.
|
||||
/// If you require data in row major order `transpose` the matrix first.
|
||||
#[inline]
|
||||
pub fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
|
||||
let (x0, y0, x1, y1) = self.0.into();
|
||||
[[x0, y0], [x1, y1]]
|
||||
}
|
||||
|
||||
/// Creates a 2x2 matrix containing the given non-uniform `scale`.
|
||||
#[inline]
|
||||
pub fn from_scale(scale: Vec2) -> Self {
|
||||
let (x, y) = scale.into();
|
||||
Self(Vec4::new(x, 0.0, 0.0, y))
|
||||
}
|
||||
|
||||
/// Sets the first column, the `x` axis.
|
||||
#[inline]
|
||||
pub fn set_x_axis(&mut self, x: Vec2) {
|
||||
(self.0).0 = x.x();
|
||||
(self.0).1 = x.y();
|
||||
}
|
||||
|
||||
/// Sets the second column, the `y` axis.
|
||||
#[inline]
|
||||
pub fn set_y_axis(&mut self, y: Vec2) {
|
||||
(self.0).2 = y.x();
|
||||
(self.0).3 = y.y();
|
||||
}
|
||||
|
||||
/// Returns the first column, the `x` axis.
|
||||
#[inline]
|
||||
pub fn x_axis(&self) -> Vec2 {
|
||||
let (x, y, _, _) = self.0.into();
|
||||
Vec2::new(x, y)
|
||||
}
|
||||
|
||||
/// Returns the second column, the `y` axis.
|
||||
#[inline]
|
||||
pub fn y_axis(&self) -> Vec2 {
|
||||
let (_, _, x, y) = self.0.into();
|
||||
Vec2::new(x, y)
|
||||
}
|
||||
|
||||
// #[inline]
|
||||
// pub(crate) fn col(&self, index: usize) -> Vec2 {
|
||||
// match index {
|
||||
// 0 => self.x_axis(),
|
||||
// 1 => self.y_axis(),
|
||||
// _ => panic!(
|
||||
// "index out of bounds: the len is 2 but the index is {}",
|
||||
// index
|
||||
// ),
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[inline]
|
||||
// pub(crate) fn col_mut(&mut self, index: usize) -> &mut Vec2 {
|
||||
// match index {
|
||||
// 0 => unsafe { &mut *(self.0.as_mut().as_mut_ptr() as *mut Vec2) },
|
||||
// 1 => unsafe { &mut *(self.0.as_mut()[2..].as_mut_ptr() as *mut Vec2) },
|
||||
// _ => panic!(
|
||||
// "index out of bounds: the len is 2 but the index is {}",
|
||||
// index
|
||||
// ),
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Returns the transpose of `self`.
|
||||
#[inline]
|
||||
pub fn transpose(&self) -> Self {
|
||||
let (m00, m01, m10, m11) = self.0.into();
|
||||
Self(Vec4::new(m00, m10, m01, m11))
|
||||
}
|
||||
|
||||
/// Returns the determinant of `self`.
|
||||
#[inline]
|
||||
pub fn determinant(&self) -> f32 {
|
||||
let (a, b, c, d) = self.0.into();
|
||||
a * d - b * c
|
||||
}
|
||||
|
||||
/// Returns the inverse of `self`.
|
||||
///
|
||||
/// If the matrix is not invertible the returned matrix will be invalid.
|
||||
#[inline]
|
||||
pub fn inverse(&self) -> Self {
|
||||
let (a, b, c, d) = self.0.into();
|
||||
let det = a * d - b * c;
|
||||
let tmp = Vec4::new(1.0, -1.0, -1.0, 1.0) / det;
|
||||
Self(Vec4::new(d, b, c, a) * tmp)
|
||||
}
|
||||
|
||||
/// Transforms a `Vec2`.
|
||||
#[inline]
|
||||
pub fn mul_vec2(&self, other: Vec2) -> Vec2 {
|
||||
// TODO: SSE2
|
||||
let other = Vec4::new(other.x(), other.x(), other.y(), other.y());
|
||||
let tmp = self.0 * other;
|
||||
let (x0, y0, x1, y1) = tmp.into();
|
||||
Vec2::new(x0 + x1, y0 + y1)
|
||||
}
|
||||
|
||||
/// Multiplies two 2x2 matrices.
|
||||
#[inline]
|
||||
pub fn mul_mat2(&self, other: &Self) -> Self {
|
||||
// TODO: SSE2
|
||||
let (x0, y0, x1, y1) = other.0.into();
|
||||
Self::from_cols(
|
||||
self.mul_vec2(Vec2::new(x0, y0)),
|
||||
self.mul_vec2(Vec2::new(x1, y1)),
|
||||
)
|
||||
}
|
||||
|
||||
/// Adds two 2x2 matrices.
|
||||
#[inline]
|
||||
pub fn add_mat2(&self, other: &Self) -> Self {
|
||||
Self(self.0 + other.0)
|
||||
}
|
||||
|
||||
/// Subtracts two 2x2 matrices.
|
||||
#[inline]
|
||||
pub fn sub_mat2(&self, other: &Self) -> Self {
|
||||
Self(self.0 - other.0)
|
||||
}
|
||||
|
||||
/// Multiplies a 2x2 matrix by a scalar.
|
||||
#[inline]
|
||||
pub fn mul_scalar(&self, other: f32) -> Self {
|
||||
let s = Vec4::splat(other);
|
||||
Self(self.0 * s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Mat2> for Mat2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
self.add_mat2(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Mat2> for Mat2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self.sub_mat2(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Mat2> for Mat2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self.mul_mat2(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec2> for Mat2 {
|
||||
type Output = Vec2;
|
||||
#[inline]
|
||||
fn mul(self, other: Vec2) -> Vec2 {
|
||||
self.mul_vec2(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Mat2> for f32 {
|
||||
type Output = Mat2;
|
||||
#[inline]
|
||||
fn mul(self, other: Mat2) -> Mat2 {
|
||||
other.mul_scalar(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Mat2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: f32) -> Self {
|
||||
self.mul_scalar(other)
|
||||
}
|
||||
}
|
@ -1,320 +0,0 @@
|
||||
use super::Vec3;
|
||||
use core::ops::{Add, Mul, Sub};
|
||||
|
||||
/// Creates a `Mat3` from three column vectors.
|
||||
#[inline]
|
||||
pub fn mat3(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Mat3 {
|
||||
Mat3 {
|
||||
x_axis,
|
||||
y_axis,
|
||||
z_axis,
|
||||
}
|
||||
}
|
||||
|
||||
/// A 3x3 column major matrix.
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
|
||||
pub struct Mat3 {
|
||||
pub x_axis: Vec3,
|
||||
pub y_axis: Vec3,
|
||||
pub z_axis: Vec3,
|
||||
}
|
||||
|
||||
impl Default for Mat3 {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl Mat3 {
|
||||
/// Creates a 3x3 matrix with all elements set to `0.0`.
|
||||
#[inline]
|
||||
pub const fn zero() -> Self {
|
||||
Self {
|
||||
x_axis: Vec3::zero(),
|
||||
y_axis: Vec3::zero(),
|
||||
z_axis: Vec3::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a 3x3 identity matrix.
|
||||
#[inline]
|
||||
pub const fn identity() -> Self {
|
||||
Self {
|
||||
x_axis: Vec3::new(1.0, 0.0, 0.0),
|
||||
y_axis: Vec3::new(0.0, 1.0, 0.0),
|
||||
z_axis: Vec3::new(0.0, 0.0, 1.0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a 3x3 matrix from three column vectors.
|
||||
#[inline]
|
||||
pub fn from_cols(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
|
||||
Self {
|
||||
x_axis,
|
||||
y_axis,
|
||||
z_axis,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a 3x3 matrix from a `[f32; 9]` stored in column major order.
|
||||
/// If your data is stored in row major you will need to `transpose` the
|
||||
/// returned matrix.
|
||||
#[inline]
|
||||
pub fn from_cols_array(m: &[f32; 9]) -> Self {
|
||||
Self {
|
||||
x_axis: Vec3::new(m[0], m[1], m[2]),
|
||||
y_axis: Vec3::new(m[3], m[4], m[5]),
|
||||
z_axis: Vec3::new(m[6], m[7], m[8]),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `[f32; 9]` storing data in column major order.
|
||||
/// If you require data in row major order `transpose` the matrix first.
|
||||
#[inline]
|
||||
pub fn to_cols_array(&self) -> [f32; 9] {
|
||||
let (m00, m01, m02) = self.x_axis.into();
|
||||
let (m10, m11, m12) = self.y_axis.into();
|
||||
let (m20, m21, m22) = self.z_axis.into();
|
||||
[m00, m01, m02, m10, m11, m12, m20, m21, m22]
|
||||
}
|
||||
|
||||
/// Creates a 3x3 matrix from a `[[f32; 3]; 3]` stored in column major order.
|
||||
/// If your data is in row major order you will need to `transpose` the
|
||||
/// returned matrix.
|
||||
#[inline]
|
||||
pub fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
|
||||
Self {
|
||||
x_axis: m[0].into(),
|
||||
y_axis: m[1].into(),
|
||||
z_axis: m[2].into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `[[f32; 3]; 3]` storing data in column major order.
|
||||
/// If you require data in row major order `transpose` the matrix first.
|
||||
#[inline]
|
||||
pub fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
|
||||
[self.x_axis.into(), self.y_axis.into(), self.z_axis.into()]
|
||||
}
|
||||
|
||||
/// Creates a 3x3 non-uniform scale matrix.
|
||||
#[inline]
|
||||
pub fn from_scale(scale: Vec3) -> Self {
|
||||
// TODO: should have a affine 2D scale and a 3d scale?
|
||||
// Do not panic as long as any component is non-zero
|
||||
let (x, y, z) = scale.into();
|
||||
Self {
|
||||
x_axis: Vec3::new(x, 0.0, 0.0),
|
||||
y_axis: Vec3::new(0.0, y, 0.0),
|
||||
z_axis: Vec3::new(0.0, 0.0, z),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the first column, the `x` axis.
|
||||
#[inline]
|
||||
pub fn set_x_axis(&mut self, x: Vec3) {
|
||||
self.x_axis = x;
|
||||
}
|
||||
|
||||
/// Sets the second column, the `y` axis.
|
||||
#[inline]
|
||||
pub fn set_y_axis(&mut self, y: Vec3) {
|
||||
self.y_axis = y;
|
||||
}
|
||||
|
||||
/// Sets the third column, the `z` axis.
|
||||
#[inline]
|
||||
pub fn set_z_axis(&mut self, z: Vec3) {
|
||||
self.z_axis = z;
|
||||
}
|
||||
|
||||
/// Returns the first column, the `x` axis.
|
||||
#[inline]
|
||||
pub fn x_axis(&self) -> Vec3 {
|
||||
self.x_axis
|
||||
}
|
||||
|
||||
/// Returns the second column, the `y` axis.
|
||||
#[inline]
|
||||
pub fn y_axis(&self) -> Vec3 {
|
||||
self.y_axis
|
||||
}
|
||||
|
||||
/// Returns the third column, the `z` axis.
|
||||
#[inline]
|
||||
pub fn z_axis(&self) -> Vec3 {
|
||||
self.z_axis
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the first column, the `x` axis.
|
||||
#[inline]
|
||||
pub fn x_axis_mut(&mut self) -> &mut Vec3 {
|
||||
&mut self.x_axis
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the second column, the `y` axis.
|
||||
#[inline]
|
||||
pub fn y_axis_mut(&mut self) -> &mut Vec3 {
|
||||
&mut self.y_axis
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the third column, the `z` axis.
|
||||
#[inline]
|
||||
pub fn z_axis_mut(&mut self) -> &mut Vec3 {
|
||||
&mut self.z_axis
|
||||
}
|
||||
|
||||
// #[inline]
|
||||
// pub(crate) fn col(&self, index: usize) -> Vec3 {
|
||||
// match index {
|
||||
// 0 => self.x_axis,
|
||||
// 1 => self.y_axis,
|
||||
// 2 => self.z_axis,
|
||||
// _ => panic!(
|
||||
// "index out of bounds: the len is 3 but the index is {}",
|
||||
// index
|
||||
// ),
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[inline]
|
||||
// pub(crate) fn col_mut(&mut self, index: usize) -> &mut Vec3 {
|
||||
// match index {
|
||||
// 0 => &mut self.x_axis,
|
||||
// 1 => &mut self.y_axis,
|
||||
// 2 => &mut self.z_axis,
|
||||
// _ => panic!(
|
||||
// "index out of bounds: the len is 3 but the index is {}",
|
||||
// index
|
||||
// ),
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Returns the transpose of `self`.
|
||||
#[inline]
|
||||
pub fn transpose(&self) -> Self {
|
||||
Self {
|
||||
x_axis: Vec3::new(self.x_axis.0, self.y_axis.0, self.z_axis.0),
|
||||
y_axis: Vec3::new(self.x_axis.1, self.y_axis.1, self.z_axis.1),
|
||||
z_axis: Vec3::new(self.x_axis.2, self.y_axis.2, self.z_axis.2),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the determinant of `self`.
|
||||
#[inline]
|
||||
pub fn determinant(&self) -> f32 {
|
||||
self.z_axis.dot(self.x_axis.cross(self.y_axis))
|
||||
}
|
||||
|
||||
/// Returns the inverse of `self`.
|
||||
///
|
||||
/// If the matrix is not invertible the returned matrix will be invalid.
|
||||
pub fn inverse(&self) -> Self {
|
||||
let tmp0 = self.y_axis.cross(self.z_axis);
|
||||
let tmp1 = self.z_axis.cross(self.x_axis);
|
||||
let tmp2 = self.x_axis.cross(self.y_axis);
|
||||
let det = self.z_axis.dot_as_vec3(tmp2);
|
||||
let inv_det = det.recip();
|
||||
// TODO: Work out if it's possible to get rid of the transpose
|
||||
Self::from_cols(tmp0 * inv_det, tmp1 * inv_det, tmp2 * inv_det).transpose()
|
||||
}
|
||||
|
||||
/// Multiplies two 3x3 matrices.
|
||||
#[inline]
|
||||
pub fn mul_mat3(&self, other: &Self) -> Self {
|
||||
Self {
|
||||
x_axis: self.mul_vec3(other.x_axis),
|
||||
y_axis: self.mul_vec3(other.y_axis),
|
||||
z_axis: self.mul_vec3(other.z_axis),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds two 3x3 matrices.
|
||||
#[inline]
|
||||
pub fn add_mat3(&self, other: &Self) -> Self {
|
||||
Self {
|
||||
x_axis: self.x_axis + other.x_axis,
|
||||
y_axis: self.y_axis + other.y_axis,
|
||||
z_axis: self.z_axis + other.z_axis,
|
||||
}
|
||||
}
|
||||
|
||||
/// Subtracts two 3x3 matrices.
|
||||
#[inline]
|
||||
pub fn sub_mat3(&self, other: &Self) -> Self {
|
||||
Self {
|
||||
x_axis: self.x_axis - other.x_axis,
|
||||
y_axis: self.y_axis - other.y_axis,
|
||||
z_axis: self.z_axis - other.z_axis,
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a `Vec3`.
|
||||
#[inline]
|
||||
pub fn mul_vec3(&self, other: Vec3) -> Vec3 {
|
||||
let mut res = self.x_axis * Vec3::splat(other.x());
|
||||
res = self.y_axis.mul_add(Vec3::splat(other.y()), res);
|
||||
res = self.z_axis.mul_add(Vec3::splat(other.z()), res);
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Multiplies a 3x3 matrix by a scalar.
|
||||
pub fn mul_scalar(&self, other: f32) -> Self {
|
||||
let s = Vec3::splat(other);
|
||||
Self {
|
||||
x_axis: self.x_axis * s,
|
||||
y_axis: self.y_axis * s,
|
||||
z_axis: self.z_axis * s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Mat3> for Mat3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
self.add_mat3(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Mat3> for Mat3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self.sub_mat3(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Mat3> for Mat3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self.mul_mat3(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec3> for Mat3 {
|
||||
type Output = Vec3;
|
||||
#[inline]
|
||||
fn mul(self, other: Vec3) -> Vec3 {
|
||||
self.mul_vec3(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Mat3> for f32 {
|
||||
type Output = Mat3;
|
||||
#[inline]
|
||||
fn mul(self, other: Mat3) -> Mat3 {
|
||||
other.mul_scalar(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Mat3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: f32) -> Self {
|
||||
self.mul_scalar(other)
|
||||
}
|
||||
}
|
@ -1,464 +0,0 @@
|
||||
use super::{Vec3, Vec4};
|
||||
use core::ops::{Add, Mul, Sub};
|
||||
|
||||
/// Creates a `Mat4` from four column vectors.
|
||||
#[inline]
|
||||
pub fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
|
||||
Mat4 {
|
||||
x_axis,
|
||||
y_axis,
|
||||
z_axis,
|
||||
w_axis,
|
||||
}
|
||||
}
|
||||
|
||||
/// A 4x4 column major matrix.
|
||||
///
|
||||
/// This type is 16 byte aligned.
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
|
||||
pub struct Mat4 {
|
||||
pub x_axis: Vec4,
|
||||
pub y_axis: Vec4,
|
||||
pub z_axis: Vec4,
|
||||
pub w_axis: Vec4,
|
||||
}
|
||||
|
||||
impl Default for Mat4 {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl Mat4 {
|
||||
/// Creates a 4x4 matrix with all elements set to `0.0`.
|
||||
#[inline]
|
||||
pub const fn zero() -> Self {
|
||||
Self {
|
||||
x_axis: Vec4::zero(),
|
||||
y_axis: Vec4::zero(),
|
||||
z_axis: Vec4::zero(),
|
||||
w_axis: Vec4::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a 4x4 identity matrix.
|
||||
#[inline]
|
||||
pub const fn identity() -> Self {
|
||||
Self {
|
||||
x_axis: Vec4::new(1.0, 0.0, 0.0, 0.0),
|
||||
y_axis: Vec4::new(0.0, 1.0, 0.0, 0.0),
|
||||
z_axis: Vec4::new(0.0, 0.0, 1.0, 0.0),
|
||||
w_axis: Vec4::new(0.0, 0.0, 0.0, 1.0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a 4x4 matrix from four column vectors.
|
||||
#[inline]
|
||||
pub fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
|
||||
Self {
|
||||
x_axis,
|
||||
y_axis,
|
||||
z_axis,
|
||||
w_axis,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a 4x4 matrix from a `[f32; 16]` stored in column major order.
|
||||
/// If your data is stored in row major you will need to `transpose` the
|
||||
/// returned matrix.
|
||||
#[inline]
|
||||
pub fn from_cols_array(m: &[f32; 16]) -> Self {
|
||||
Self {
|
||||
x_axis: Vec4::new(m[0], m[1], m[2], m[3]),
|
||||
y_axis: Vec4::new(m[4], m[5], m[6], m[7]),
|
||||
z_axis: Vec4::new(m[8], m[9], m[10], m[11]),
|
||||
w_axis: Vec4::new(m[12], m[13], m[14], m[15]),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `[f32; 16]` storing data in column major order.
|
||||
/// If you require data in row major order `transpose` the matrix first.
|
||||
#[inline]
|
||||
pub fn to_cols_array(&self) -> [f32; 16] {
|
||||
*self.as_ref()
|
||||
}
|
||||
|
||||
/// Creates a 4x4 matrix from a `[[f32; 4]; 4]` stored in column major
|
||||
/// order. If your data is in row major order you will need to `transpose`
|
||||
/// the returned matrix.
|
||||
#[inline]
|
||||
pub fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
|
||||
Self {
|
||||
x_axis: m[0].into(),
|
||||
y_axis: m[1].into(),
|
||||
z_axis: m[2].into(),
|
||||
w_axis: m[3].into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `[[f32; 4]; 4]` storing data in column major order.
|
||||
/// If you require data in row major order `transpose` the matrix first.
|
||||
#[inline]
|
||||
pub fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
|
||||
[
|
||||
self.x_axis.into(),
|
||||
self.y_axis.into(),
|
||||
self.z_axis.into(),
|
||||
self.w_axis.into(),
|
||||
]
|
||||
}
|
||||
|
||||
/// Creates a 4x4 homogeneous transformation matrix from the given `translation`.
|
||||
#[inline]
|
||||
pub fn from_translation(translation: Vec3) -> Self {
|
||||
Self {
|
||||
x_axis: Vec4::unit_x(),
|
||||
y_axis: Vec4::unit_y(),
|
||||
z_axis: Vec4::unit_z(),
|
||||
w_axis: translation.extend(1.0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a 4x4 homogeneous transformation matrix containing the given
|
||||
/// non-uniform `scale`.
|
||||
#[inline]
|
||||
pub fn from_scale(scale: Vec3) -> Self {
|
||||
// Do not panic as long as any component is non-zero
|
||||
let (x, y, z) = scale.into();
|
||||
Self {
|
||||
x_axis: Vec4::new(x, 0.0, 0.0, 0.0),
|
||||
y_axis: Vec4::new(0.0, y, 0.0, 0.0),
|
||||
z_axis: Vec4::new(0.0, 0.0, z, 0.0),
|
||||
w_axis: Vec4::unit_w(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the first column, the `x` axis.
|
||||
#[inline]
|
||||
pub fn set_x_axis(&mut self, x: Vec4) {
|
||||
self.x_axis = x;
|
||||
}
|
||||
|
||||
/// Sets the second column, the `y` axis.
|
||||
#[inline]
|
||||
pub fn set_y_axis(&mut self, y: Vec4) {
|
||||
self.y_axis = y;
|
||||
}
|
||||
|
||||
/// Sets the third column, the `z` axis.
|
||||
#[inline]
|
||||
pub fn set_z_axis(&mut self, z: Vec4) {
|
||||
self.z_axis = z;
|
||||
}
|
||||
|
||||
/// Sets the fourth column, the `w` axis.
|
||||
#[inline]
|
||||
pub fn set_w_axis(&mut self, w: Vec4) {
|
||||
self.w_axis = w;
|
||||
}
|
||||
|
||||
/// Returns the first column, the `x` axis.
|
||||
#[inline]
|
||||
pub fn x_axis(&self) -> Vec4 {
|
||||
self.x_axis
|
||||
}
|
||||
|
||||
/// Returns the second column, the `y` axis.
|
||||
#[inline]
|
||||
pub fn y_axis(&self) -> Vec4 {
|
||||
self.y_axis
|
||||
}
|
||||
|
||||
/// Returns the third column, the `z` axis.
|
||||
#[inline]
|
||||
pub fn z_axis(&self) -> Vec4 {
|
||||
self.z_axis
|
||||
}
|
||||
|
||||
/// Returns the fourth column, the `w` axis.
|
||||
#[inline]
|
||||
pub fn w_axis(&self) -> Vec4 {
|
||||
self.w_axis
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the first column, the `x` axis.
|
||||
#[inline]
|
||||
pub fn x_axis_mut(&mut self) -> &mut Vec4 {
|
||||
&mut self.x_axis
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the second column, the `y` axis.
|
||||
#[inline]
|
||||
pub fn y_axis_mut(&mut self) -> &mut Vec4 {
|
||||
&mut self.y_axis
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the third column, the `z` axis.
|
||||
#[inline]
|
||||
pub fn z_axis_mut(&mut self) -> &mut Vec4 {
|
||||
&mut self.z_axis
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the fourth column, the `w` axis.
|
||||
#[inline]
|
||||
pub fn w_axis_mut(&mut self) -> &mut Vec4 {
|
||||
&mut self.w_axis
|
||||
}
|
||||
|
||||
// #[inline]
|
||||
// pub(crate) fn col(&self, index: usize) -> Vec4 {
|
||||
// match index {
|
||||
// 0 => self.x_axis,
|
||||
// 1 => self.y_axis,
|
||||
// 2 => self.z_axis,
|
||||
// 3 => self.w_axis,
|
||||
// _ => panic!(
|
||||
// "index out of bounds: the len is 4 but the index is {}",
|
||||
// index
|
||||
// ),
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[inline]
|
||||
// pub(crate) fn col_mut(&mut self, index: usize) -> &mut Vec4 {
|
||||
// match index {
|
||||
// 0 => &mut self.x_axis,
|
||||
// 1 => &mut self.y_axis,
|
||||
// 2 => &mut self.z_axis,
|
||||
// 3 => &mut self.w_axis,
|
||||
// _ => panic!(
|
||||
// "index out of bounds: the len is 4 but the index is {}",
|
||||
// index
|
||||
// ),
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Returns the transpose of `self`.
|
||||
#[inline]
|
||||
pub fn transpose(&self) -> Self {
|
||||
let (m00, m01, m02, m03) = self.x_axis.into();
|
||||
let (m10, m11, m12, m13) = self.y_axis.into();
|
||||
let (m20, m21, m22, m23) = self.z_axis.into();
|
||||
let (m30, m31, m32, m33) = self.w_axis.into();
|
||||
|
||||
Self {
|
||||
x_axis: Vec4::new(m00, m10, m20, m30),
|
||||
y_axis: Vec4::new(m01, m11, m21, m31),
|
||||
z_axis: Vec4::new(m02, m12, m22, m32),
|
||||
w_axis: Vec4::new(m03, m13, m23, m33),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the determinant of `self`.
|
||||
#[inline]
|
||||
pub fn determinant(&self) -> f32 {
|
||||
let (m00, m01, m02, m03) = self.x_axis.into();
|
||||
let (m10, m11, m12, m13) = self.y_axis.into();
|
||||
let (m20, m21, m22, m23) = self.z_axis.into();
|
||||
let (m30, m31, m32, m33) = self.w_axis.into();
|
||||
|
||||
let a2323 = m22 * m33 - m23 * m32;
|
||||
let a1323 = m21 * m33 - m23 * m31;
|
||||
let a1223 = m21 * m32 - m22 * m31;
|
||||
let a0323 = m20 * m33 - m23 * m30;
|
||||
let a0223 = m20 * m32 - m22 * m30;
|
||||
let a0123 = m20 * m31 - m21 * m30;
|
||||
|
||||
m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
|
||||
- m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
|
||||
+ m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
|
||||
- m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
|
||||
}
|
||||
|
||||
/// Returns the inverse of `self`.
|
||||
///
|
||||
/// If the matrix is not invertible the returned matrix will be invalid.
|
||||
pub fn inverse(&self) -> Self {
|
||||
let (m00, m01, m02, m03) = self.x_axis.into();
|
||||
let (m10, m11, m12, m13) = self.y_axis.into();
|
||||
let (m20, m21, m22, m23) = self.z_axis.into();
|
||||
let (m30, m31, m32, m33) = self.w_axis.into();
|
||||
|
||||
let coef00 = m22 * m33 - m32 * m23;
|
||||
let coef02 = m12 * m33 - m32 * m13;
|
||||
let coef03 = m12 * m23 - m22 * m13;
|
||||
|
||||
let coef04 = m21 * m33 - m31 * m23;
|
||||
let coef06 = m11 * m33 - m31 * m13;
|
||||
let coef07 = m11 * m23 - m21 * m13;
|
||||
|
||||
let coef08 = m21 * m32 - m31 * m22;
|
||||
let coef10 = m11 * m32 - m31 * m12;
|
||||
let coef11 = m11 * m22 - m21 * m12;
|
||||
|
||||
let coef12 = m20 * m33 - m30 * m23;
|
||||
let coef14 = m10 * m33 - m30 * m13;
|
||||
let coef15 = m10 * m23 - m20 * m13;
|
||||
|
||||
let coef16 = m20 * m32 - m30 * m22;
|
||||
let coef18 = m10 * m32 - m30 * m12;
|
||||
let coef19 = m10 * m22 - m20 * m12;
|
||||
|
||||
let coef20 = m20 * m31 - m30 * m21;
|
||||
let coef22 = m10 * m31 - m30 * m11;
|
||||
let coef23 = m10 * m21 - m20 * m11;
|
||||
|
||||
let fac0 = Vec4::new(coef00, coef00, coef02, coef03);
|
||||
let fac1 = Vec4::new(coef04, coef04, coef06, coef07);
|
||||
let fac2 = Vec4::new(coef08, coef08, coef10, coef11);
|
||||
let fac3 = Vec4::new(coef12, coef12, coef14, coef15);
|
||||
let fac4 = Vec4::new(coef16, coef16, coef18, coef19);
|
||||
let fac5 = Vec4::new(coef20, coef20, coef22, coef23);
|
||||
|
||||
let vec0 = Vec4::new(m10, m00, m00, m00);
|
||||
let vec1 = Vec4::new(m11, m01, m01, m01);
|
||||
let vec2 = Vec4::new(m12, m02, m02, m02);
|
||||
let vec3 = Vec4::new(m13, m03, m03, m03);
|
||||
|
||||
let inv0 = vec1 * fac0 - vec2 * fac1 + vec3 * fac2;
|
||||
let inv1 = vec0 * fac0 - vec2 * fac3 + vec3 * fac4;
|
||||
let inv2 = vec0 * fac1 - vec1 * fac3 + vec3 * fac5;
|
||||
let inv3 = vec0 * fac2 - vec1 * fac4 + vec2 * fac5;
|
||||
|
||||
let sign_a = Vec4::new(1.0, -1.0, 1.0, -1.0);
|
||||
let sign_b = Vec4::new(-1.0, 1.0, -1.0, 1.0);
|
||||
|
||||
let inverse = Self {
|
||||
x_axis: inv0 * sign_a,
|
||||
y_axis: inv1 * sign_b,
|
||||
z_axis: inv2 * sign_a,
|
||||
w_axis: inv3 * sign_b,
|
||||
};
|
||||
|
||||
let col0 = Vec4::new(
|
||||
inverse.x_axis.x(),
|
||||
inverse.y_axis.x(),
|
||||
inverse.z_axis.x(),
|
||||
inverse.w_axis.x(),
|
||||
);
|
||||
|
||||
let dot0 = self.x_axis * col0;
|
||||
let dot1 = dot0.x() + dot0.y() + dot0.z() + dot0.w();
|
||||
|
||||
let rcp_det = 1.0 / dot1;
|
||||
inverse * rcp_det
|
||||
}
|
||||
|
||||
/// Transforms a 4D vector.
|
||||
#[inline]
|
||||
pub fn mul_vec4(&self, other: Vec4) -> Vec4 {
|
||||
let mut res = self.x_axis * other.dup_x();
|
||||
res = self.y_axis.mul_add(other.dup_y(), res);
|
||||
res = self.z_axis.mul_add(other.dup_z(), res);
|
||||
res = self.w_axis.mul_add(other.dup_w(), res);
|
||||
res
|
||||
}
|
||||
|
||||
/// Multiplies two 4x4 matrices.
|
||||
#[inline]
|
||||
pub fn mul_mat4(&self, other: &Self) -> Self {
|
||||
Self {
|
||||
x_axis: self.mul_vec4(other.x_axis),
|
||||
y_axis: self.mul_vec4(other.y_axis),
|
||||
z_axis: self.mul_vec4(other.z_axis),
|
||||
w_axis: self.mul_vec4(other.w_axis),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds two 4x4 matrices.
|
||||
#[inline]
|
||||
pub fn add_mat4(&self, other: &Self) -> Self {
|
||||
Self {
|
||||
x_axis: self.x_axis + other.x_axis,
|
||||
y_axis: self.y_axis + other.y_axis,
|
||||
z_axis: self.z_axis + other.z_axis,
|
||||
w_axis: self.w_axis + other.w_axis,
|
||||
}
|
||||
}
|
||||
|
||||
/// Subtracts two 4x4 matrices.
|
||||
#[inline]
|
||||
pub fn sub_mat4(&self, other: &Self) -> Self {
|
||||
Self {
|
||||
x_axis: self.x_axis - other.x_axis,
|
||||
y_axis: self.y_axis - other.y_axis,
|
||||
z_axis: self.z_axis - other.z_axis,
|
||||
w_axis: self.w_axis - other.w_axis,
|
||||
}
|
||||
}
|
||||
|
||||
/// Multiplies this matrix by a scalar value.
|
||||
#[inline]
|
||||
pub fn mul_scalar(&self, other: f32) -> Self {
|
||||
let s = Vec4::splat(other);
|
||||
Self {
|
||||
x_axis: self.x_axis * s,
|
||||
y_axis: self.y_axis * s,
|
||||
z_axis: self.z_axis * s,
|
||||
w_axis: self.w_axis * s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[f32; 16]> for Mat4 {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[f32; 16] {
|
||||
unsafe { &*(self as *const Self as *const [f32; 16]) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<[f32; 16]> for Mat4 {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [f32; 16] {
|
||||
unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Mat4> for Mat4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
self.add_mat4(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Mat4> for Mat4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self.sub_mat4(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Mat4> for Mat4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self.mul_mat4(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec4> for Mat4 {
|
||||
type Output = Vec4;
|
||||
#[inline]
|
||||
fn mul(self, other: Vec4) -> Vec4 {
|
||||
self.mul_vec4(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Mat4> for f32 {
|
||||
type Output = Mat4;
|
||||
#[inline]
|
||||
fn mul(self, other: Mat4) -> Mat4 {
|
||||
other.mul_scalar(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Mat4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: f32) -> Self {
|
||||
self.mul_scalar(other)
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
//! This math library is heavily borrowed from [glam](https://github.com/bitshifter/glam-rs)
|
||||
//! In the future we hope to be able to use it directly!
|
||||
|
||||
pub mod mat2;
|
||||
pub mod mat3;
|
||||
pub mod mat4;
|
||||
pub mod vec2;
|
||||
pub mod vec3;
|
||||
pub mod vec4;
|
||||
pub use mat2::*;
|
||||
pub use mat3::*;
|
||||
pub use mat4::*;
|
||||
pub use vec2::*;
|
||||
pub use vec3::*;
|
||||
pub use vec4::*;
|
||||
|
||||
pub trait MathExt {
|
||||
fn pow(self, factor: Self) -> Self;
|
||||
fn sqrt(self) -> Self;
|
||||
fn log2(self) -> Self;
|
||||
fn abs(self) -> Self;
|
||||
fn cos(self) -> Self;
|
||||
fn round(self) -> Self;
|
||||
fn floor(self) -> Self;
|
||||
fn ceil(self) -> Self;
|
||||
fn exp(self) -> Self;
|
||||
fn saturate(self) -> Self;
|
||||
}
|
||||
|
||||
#[allow(clippy::use_self)]
|
||||
impl MathExt for f32 {
|
||||
fn pow(self, factor: Self) -> Self {
|
||||
unsafe { core::intrinsics::powf32(self, factor) }
|
||||
}
|
||||
|
||||
fn sqrt(self) -> Self {
|
||||
unsafe { core::intrinsics::sqrtf32(self) }
|
||||
}
|
||||
|
||||
fn log2(self) -> Self {
|
||||
unsafe { core::intrinsics::log2f32(self) }
|
||||
}
|
||||
|
||||
fn abs(self) -> Self {
|
||||
unsafe { core::intrinsics::fabsf32(self) }
|
||||
}
|
||||
|
||||
fn cos(self) -> Self {
|
||||
unsafe { core::intrinsics::cosf32(self) }
|
||||
}
|
||||
|
||||
fn round(self) -> Self {
|
||||
unsafe { core::intrinsics::roundf32(self) }
|
||||
}
|
||||
|
||||
fn floor(self) -> Self {
|
||||
unsafe { core::intrinsics::floorf32(self) }
|
||||
}
|
||||
|
||||
fn ceil(self) -> Self {
|
||||
unsafe { core::intrinsics::ceilf32(self) }
|
||||
}
|
||||
|
||||
fn exp(self) -> Self {
|
||||
unsafe { core::intrinsics::expf32(self) }
|
||||
}
|
||||
|
||||
fn saturate(self) -> Self {
|
||||
self.max(0.0).min(1.0)
|
||||
}
|
||||
}
|
@ -1,409 +0,0 @@
|
||||
use super::Vec3;
|
||||
use crate::math::MathExt;
|
||||
use core::{f32, ops::*};
|
||||
|
||||
/// A 2-dimensional vector.
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Default)]
|
||||
#[repr(simd)]
|
||||
pub struct Vec2(pub f32, pub f32);
|
||||
|
||||
/// Creates a `Vec2`.
|
||||
#[inline]
|
||||
pub fn vec2(x: f32, y: f32) -> Vec2 {
|
||||
Vec2(x, y)
|
||||
}
|
||||
|
||||
impl Vec2 {
|
||||
#[deprecated(since = "0.9.5", note = "please use `Vec2::recip` instead")]
|
||||
#[inline(always)]
|
||||
pub fn reciprocal(self) -> Self {
|
||||
self.recip()
|
||||
}
|
||||
|
||||
/// Returns a `Vec2` containing the reciprocal `1.0/n` of each element of `self`.
|
||||
#[inline]
|
||||
pub fn recip(self) -> Self {
|
||||
Self(self.0.recip(), self.1.recip())
|
||||
}
|
||||
|
||||
/// Performs a linear interpolation between `self` and `other` based on
|
||||
/// the value `s`.
|
||||
///
|
||||
/// When `s` is `0.0`, the result will be equal to `self`. When `s`
|
||||
/// is `1.0`, the result will be equal to `other`.
|
||||
#[inline]
|
||||
pub fn lerp(self, other: Self, s: f32) -> Self {
|
||||
self + ((other - self) * s)
|
||||
}
|
||||
|
||||
/// Creates a new `Vec2`.
|
||||
#[inline]
|
||||
pub fn new(x: f32, y: f32) -> Self {
|
||||
Self(x, y)
|
||||
}
|
||||
|
||||
/// Creates a `Vec2` with all elements set to `0.0`.
|
||||
#[inline]
|
||||
pub fn zero() -> Self {
|
||||
Self::splat(0.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec2` with all elements set to `1.0`.
|
||||
#[inline]
|
||||
pub fn one() -> Self {
|
||||
Self::splat(1.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec2` with values `[x: 1.0, y: 0.0]`.
|
||||
#[inline]
|
||||
pub fn unit_x() -> Self {
|
||||
Self::new(1.0, 0.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec2` with values `[x: 0.0, y: 1.0]`.
|
||||
#[inline]
|
||||
pub fn unit_y() -> Self {
|
||||
Self::new(0.0, 1.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec2` with all elements set to `v`.
|
||||
#[inline]
|
||||
pub fn splat(v: f32) -> Self {
|
||||
Self(v, v)
|
||||
}
|
||||
|
||||
/// Creates a `Vec3` from `self` and the given `z` value.
|
||||
#[inline]
|
||||
pub fn extend(self, z: f32) -> Vec3 {
|
||||
Vec3::new(self.0, self.1, z)
|
||||
}
|
||||
|
||||
/// Returns element `x`.
|
||||
#[inline]
|
||||
pub fn x(self) -> f32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns element `y`.
|
||||
#[inline]
|
||||
pub fn y(self) -> f32 {
|
||||
self.1
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to element `x`.
|
||||
#[inline]
|
||||
pub fn x_mut(&mut self) -> &mut f32 {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to element `y`.
|
||||
#[inline]
|
||||
pub fn y_mut(&mut self) -> &mut f32 {
|
||||
&mut self.1
|
||||
}
|
||||
|
||||
/// Sets element `x`.
|
||||
#[inline]
|
||||
pub fn set_x(&mut self, x: f32) {
|
||||
self.0 = x;
|
||||
}
|
||||
|
||||
/// Sets element `y`.
|
||||
#[inline]
|
||||
pub fn set_y(&mut self, y: f32) {
|
||||
self.1 = y;
|
||||
}
|
||||
|
||||
/// Computes the dot product of `self` and `other`.
|
||||
#[inline]
|
||||
pub fn dot(self, other: Self) -> f32 {
|
||||
(self.0 * other.0) + (self.1 * other.1)
|
||||
}
|
||||
|
||||
/// Computes the length of `self`.
|
||||
#[inline]
|
||||
pub fn length(self) -> f32 {
|
||||
self.dot(self).sqrt()
|
||||
}
|
||||
|
||||
/// Computes the squared length of `self`.
|
||||
///
|
||||
/// This is generally faster than `Vec2::length()` as it avoids a square
|
||||
/// root operation.
|
||||
#[inline]
|
||||
pub fn length_squared(self) -> f32 {
|
||||
self.dot(self)
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.9.5", note = "please use `Vec2::length_recip` instead")]
|
||||
#[inline(always)]
|
||||
pub fn length_reciprocal(self) -> f32 {
|
||||
self.length_recip()
|
||||
}
|
||||
|
||||
/// Computes `1.0 / Vec2::length()`.
|
||||
///
|
||||
/// For valid results, `self` must _not_ be of length zero.
|
||||
#[inline]
|
||||
pub fn length_recip(self) -> f32 {
|
||||
self.length().recip()
|
||||
}
|
||||
|
||||
/// Returns `self` normalized to length 1.0.
|
||||
///
|
||||
/// For valid results, `self` must _not_ be of length zero.
|
||||
#[inline]
|
||||
pub fn normalize(self) -> Self {
|
||||
self * self.length_recip()
|
||||
}
|
||||
|
||||
/// Returns the vertical minimum of `self` and `other`.
|
||||
///
|
||||
/// In other words, this computes
|
||||
/// `[x: min(x1, x2), y: min(y1, y2)]`,
|
||||
/// taking the minimum of each element individually.
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
Self(self.0.min(other.0), self.1.min(other.1))
|
||||
}
|
||||
|
||||
/// Returns the vertical maximum of `self` and `other`.
|
||||
///
|
||||
/// In other words, this computes
|
||||
/// `[x: max(x1, x2), y: max(y1, y2)]`,
|
||||
/// taking the maximum of each element individually.
|
||||
#[inline]
|
||||
pub fn max(self, other: Self) -> Self {
|
||||
Self(self.0.max(other.0), self.1.max(other.1))
|
||||
}
|
||||
|
||||
/// Returns the horizontal minimum of `self`'s elements.
|
||||
///
|
||||
/// In other words, this computes `min(x, y)`.
|
||||
#[inline]
|
||||
pub fn min_element(self) -> f32 {
|
||||
self.0.min(self.1)
|
||||
}
|
||||
|
||||
/// Returns the horizontal maximum of `self`'s elements.
|
||||
///
|
||||
/// In other words, this computes `max(x, y)`.
|
||||
#[inline]
|
||||
pub fn max_element(self) -> f32 {
|
||||
self.0.max(self.1)
|
||||
}
|
||||
|
||||
/// Creates a `Vec2` from the first two values in `slice`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `slice` is less than two elements long.
|
||||
#[inline]
|
||||
pub fn from_slice_unaligned(slice: &[f32]) -> Self {
|
||||
Self(slice[0], slice[1])
|
||||
}
|
||||
|
||||
/// Writes the elements of `self` to the first two elements in `slice`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `slice` is less than two elements long.
|
||||
#[inline]
|
||||
pub fn write_to_slice_unaligned(self, slice: &mut [f32]) {
|
||||
slice[0] = self.0;
|
||||
slice[1] = self.1;
|
||||
}
|
||||
|
||||
/// Returns a `Vec2` containing the absolute value of each element of `self`.
|
||||
#[inline]
|
||||
pub fn abs(self) -> Self {
|
||||
Self(self.0.abs(), self.1.abs())
|
||||
}
|
||||
|
||||
/// Returns a `Vec2` containing the nearest integer to a number for each element of `self`.
|
||||
/// Round half-way cases away from 0.0.
|
||||
#[inline]
|
||||
pub fn round(self) -> Self {
|
||||
Self(self.0.round(), self.1.round())
|
||||
}
|
||||
|
||||
/// Returns a `Vec2` containing the largest integer less than or equal to a number for each
|
||||
/// element of `self`.
|
||||
#[inline]
|
||||
pub fn floor(self) -> Self {
|
||||
Self(self.0.floor(), self.1.floor())
|
||||
}
|
||||
|
||||
/// Returns a `Vec2` containing this vector raised to the power of `power`
|
||||
#[inline]
|
||||
pub fn pow(self, power: f32) -> Self {
|
||||
Self(self.0.pow(power), self.1.pow(power))
|
||||
}
|
||||
|
||||
/// Returns a `Vec2` containing this vector exp'd
|
||||
#[inline]
|
||||
pub fn exp(self) -> Self {
|
||||
Self(self.0.exp(), self.1.exp())
|
||||
}
|
||||
|
||||
/// Returns a `Vec2` containing the smallest integer greater than or equal to a number for each
|
||||
/// element of `self`.
|
||||
#[inline]
|
||||
pub fn ceil(self) -> Self {
|
||||
Self(self.0.ceil(), self.1.ceil())
|
||||
}
|
||||
|
||||
/// The perpendicular dot product of the vector and `other`.
|
||||
#[inline]
|
||||
pub fn perp_dot(self, other: Self) -> f32 {
|
||||
(self.0 * other.1) - (self.1 * other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Vec2> for Vec2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, other: Self) -> Self {
|
||||
Self(self.0 / other.0, self.1 / other.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<Vec2> for Vec2 {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: Self) {
|
||||
self.0 /= other.0;
|
||||
self.1 /= other.1;
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f32> for Vec2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, other: f32) -> Self {
|
||||
Self(self.0 / other, self.1 / other)
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<f32> for Vec2 {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: f32) {
|
||||
self.0 /= other;
|
||||
self.1 /= other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Vec2> for f32 {
|
||||
type Output = Vec2;
|
||||
#[inline]
|
||||
fn div(self, other: Vec2) -> Vec2 {
|
||||
Vec2(self / other.0, self / other.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec2> for Vec2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: Self) -> Self {
|
||||
Self(self.0 * other.0, self.1 * other.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<Vec2> for Vec2 {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
self.0 *= other.0;
|
||||
self.1 *= other.1;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Vec2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: f32) -> Self {
|
||||
Self(self.0 * other, self.1 * other)
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<f32> for Vec2 {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, other: f32) {
|
||||
self.0 *= other;
|
||||
self.1 *= other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec2> for f32 {
|
||||
type Output = Vec2;
|
||||
#[inline]
|
||||
fn mul(self, other: Vec2) -> Vec2 {
|
||||
Vec2(self * other.0, self * other.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Vec2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self(self.0 + other.0, self.1 + other.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Vec2 {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.0 += other.0;
|
||||
self.1 += other.1;
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Vec2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn sub(self, other: Self) -> Self {
|
||||
Self(self.0 - other.0, self.1 - other.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Vec2 {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.0 -= other.0;
|
||||
self.1 -= other.1;
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Vec2 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn neg(self) -> Self {
|
||||
Self(-self.0, -self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32)> for Vec2 {
|
||||
#[inline]
|
||||
fn from(t: (f32, f32)) -> Self {
|
||||
Self(t.0, t.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec2> for (f32, f32) {
|
||||
#[inline]
|
||||
fn from(v: Vec2) -> Self {
|
||||
(v.0, v.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 2]> for Vec2 {
|
||||
#[inline]
|
||||
fn from(a: [f32; 2]) -> Self {
|
||||
Self(a[0], a[1])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec2> for [f32; 2] {
|
||||
#[inline]
|
||||
fn from(v: Vec2) -> Self {
|
||||
[v.0, v.1]
|
||||
}
|
||||
}
|
@ -1,510 +0,0 @@
|
||||
use super::{Vec2, Vec4};
|
||||
use crate::math::MathExt;
|
||||
use core::ops::*;
|
||||
|
||||
/// A 3-dimensional vector without SIMD support.
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Default)]
|
||||
#[repr(simd)]
|
||||
pub struct Vec3(pub f32, pub f32, pub f32);
|
||||
|
||||
/// Creates a `Vec3`.
|
||||
#[inline]
|
||||
pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
|
||||
Vec3::new(x, y, z)
|
||||
}
|
||||
|
||||
impl Vec3 {
|
||||
/// Creates a new `Vec3`.
|
||||
#[inline]
|
||||
pub const fn new(x: f32, y: f32, z: f32) -> Self {
|
||||
Self(x, y, z)
|
||||
}
|
||||
|
||||
/// Creates a `Vec3` with all elements set to `0.0`.
|
||||
#[inline]
|
||||
pub const fn zero() -> Self {
|
||||
Self::splat(0.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec3` with all elements set to `1.0`.
|
||||
#[inline]
|
||||
pub const fn one() -> Self {
|
||||
Self::splat(1.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec3` with values `[x: 1.0, y: 0.0, z: 0.0]`.
|
||||
#[inline]
|
||||
pub const fn unit_x() -> Self {
|
||||
Self::new(1.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec3` with values `[x: 0.0, y: 1.0, z: 0.0]`.
|
||||
#[inline]
|
||||
pub const fn unit_y() -> Self {
|
||||
Self::new(0.0, 1.0, 0.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec3` with values `[x: 0.0, y: 0.0, z: 1.0]`.
|
||||
#[inline]
|
||||
pub const fn unit_z() -> Self {
|
||||
Self::new(0.0, 0.0, 1.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec3` with all elements set to `v`.
|
||||
#[inline]
|
||||
pub const fn splat(v: f32) -> Self {
|
||||
Self(v, v, v)
|
||||
}
|
||||
|
||||
/// Creates a `Vec4` from `self` and the given `w` value.
|
||||
#[inline]
|
||||
pub fn extend(self, w: f32) -> Vec4 {
|
||||
Vec4::new(self.0, self.1, self.2, w)
|
||||
}
|
||||
|
||||
/// Creates a `Vec2` from the first three elements of `self`,
|
||||
/// removing `z`.
|
||||
#[inline]
|
||||
pub fn truncate(self) -> Vec2 {
|
||||
Vec2::new(self.0, self.1)
|
||||
}
|
||||
|
||||
/// Returns element `x`.
|
||||
#[inline]
|
||||
pub fn x(self) -> f32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns element `y`.
|
||||
#[inline]
|
||||
pub fn y(self) -> f32 {
|
||||
self.1
|
||||
}
|
||||
|
||||
/// Returns element `z`.
|
||||
#[inline]
|
||||
pub fn z(self) -> f32 {
|
||||
self.2
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to element `x`.
|
||||
#[inline]
|
||||
pub fn x_mut(&mut self) -> &mut f32 {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to element `y`.
|
||||
#[inline]
|
||||
pub fn y_mut(&mut self) -> &mut f32 {
|
||||
&mut self.1
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to element `z`.
|
||||
#[inline]
|
||||
pub fn z_mut(&mut self) -> &mut f32 {
|
||||
&mut self.2
|
||||
}
|
||||
|
||||
/// Sets element `x`.
|
||||
#[inline]
|
||||
pub fn set_x(&mut self, x: f32) {
|
||||
self.0 = x;
|
||||
}
|
||||
|
||||
/// Sets element `y`.
|
||||
#[inline]
|
||||
pub fn set_y(&mut self, y: f32) {
|
||||
self.1 = y;
|
||||
}
|
||||
|
||||
/// Sets element `z`.
|
||||
#[inline]
|
||||
pub fn set_z(&mut self, z: f32) {
|
||||
self.2 = z;
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` with all elements set to the value of element `x`.
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn dup_x(self) -> Self {
|
||||
Self(self.0, self.0, self.0)
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` with all elements set to the value of element `y`.
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn dup_y(self) -> Self {
|
||||
Self(self.1, self.1, self.1)
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` with all elements set to the value of element `z`.
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn dup_z(self) -> Self {
|
||||
Self(self.2, self.2, self.2)
|
||||
}
|
||||
|
||||
/// Computes the dot product of `self` and `other`.
|
||||
#[inline]
|
||||
pub fn dot(self, other: Self) -> f32 {
|
||||
(self.0 * other.0) + (self.1 * other.1) + (self.2 * other.2)
|
||||
}
|
||||
|
||||
/// Returns Vec3 dot in all lanes of Vec3
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn dot_as_vec3(self, other: Self) -> Self {
|
||||
let dot = self.dot(other);
|
||||
Self::new(dot, dot, dot)
|
||||
}
|
||||
|
||||
/// Computes the cross product of `self` and `other`.
|
||||
#[inline]
|
||||
pub fn cross(self, other: Self) -> Self {
|
||||
Self(
|
||||
self.1 * other.2 - other.1 * self.2,
|
||||
self.2 * other.0 - other.2 * self.0,
|
||||
self.0 * other.1 - other.0 * self.1,
|
||||
)
|
||||
}
|
||||
|
||||
/// Computes the length of `self`.
|
||||
#[inline]
|
||||
pub fn length(self) -> f32 {
|
||||
self.dot(self).sqrt()
|
||||
}
|
||||
|
||||
/// Computes the squared length of `self`.
|
||||
///
|
||||
/// This is generally faster than `Vec3::length()` as it avoids a square
|
||||
/// root operation.
|
||||
#[inline]
|
||||
pub fn length_squared(self) -> f32 {
|
||||
self.dot(self)
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.9.5", note = "please use `Vec3::length_recip` instead")]
|
||||
#[inline(always)]
|
||||
pub fn length_reciprocal(self) -> f32 {
|
||||
self.length_recip()
|
||||
}
|
||||
|
||||
/// Computes `1.0 / Vec3::length()`.
|
||||
///
|
||||
/// For valid results, `self` must _not_ be of length zero.
|
||||
#[inline]
|
||||
pub fn length_recip(self) -> f32 {
|
||||
self.length().recip()
|
||||
}
|
||||
|
||||
/// Returns `self` normalized to length 1.0.
|
||||
///
|
||||
/// For valid results, `self` must _not_ be of length zero.
|
||||
#[inline]
|
||||
pub fn normalize(self) -> Self {
|
||||
self * self.length_recip()
|
||||
}
|
||||
|
||||
/// Returns the vertical minimum of `self` and `other`.
|
||||
///
|
||||
/// In other words, this computes
|
||||
/// `[x: min(x1, x2), y: min(y1, y2), z: min(z1, z2)]`,
|
||||
/// taking the minimum of each element individually.
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
Self(
|
||||
self.0.min(other.0),
|
||||
self.1.min(other.1),
|
||||
self.2.min(other.2),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the vertical maximum of `self` and `other`.
|
||||
///
|
||||
/// In other words, this computes
|
||||
/// `[x: max(x1, x2), y: max(y1, y2), z: max(z1, z2)]`,
|
||||
/// taking the maximum of each element individually.
|
||||
#[inline]
|
||||
pub fn max(self, other: Self) -> Self {
|
||||
Self(
|
||||
self.0.max(other.0),
|
||||
self.1.max(other.1),
|
||||
self.2.max(other.2),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the horizontal minimum of `self`'s elements.
|
||||
///
|
||||
/// In other words, this computes `min(x, y, z)`.
|
||||
#[inline]
|
||||
pub fn min_element(self) -> f32 {
|
||||
self.0.min(self.1.min(self.2))
|
||||
}
|
||||
|
||||
/// Returns the horizontal maximum of `self`'s elements.
|
||||
///
|
||||
/// In other words, this computes `max(x, y, z)`.
|
||||
#[inline]
|
||||
pub fn max_element(self) -> f32 {
|
||||
self.0.max(self.1.max(self.2))
|
||||
}
|
||||
|
||||
/// Creates a `Vec3` from the first three values in `slice`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `slice` is less than three elements long.
|
||||
#[inline]
|
||||
pub fn from_slice_unaligned(slice: &[f32]) -> Self {
|
||||
Self::new(slice[0], slice[1], slice[2])
|
||||
}
|
||||
|
||||
/// Writes the elements of `self` to the first three elements in `slice`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `slice` is less than three elements long.
|
||||
#[inline]
|
||||
pub fn write_to_slice_unaligned(self, slice: &mut [f32]) {
|
||||
slice[0] = self.0;
|
||||
slice[1] = self.1;
|
||||
slice[2] = self.2;
|
||||
}
|
||||
|
||||
/// Per element multiplication/addition of the three inputs: b + (self * a)
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn mul_add(self, a: Self, b: Self) -> Self {
|
||||
Self(
|
||||
(self.0 * a.0) + b.0,
|
||||
(self.1 * a.1) + b.1,
|
||||
(self.2 * a.2) + b.2,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` containing the absolute value of each element of `self`.
|
||||
#[inline]
|
||||
pub fn abs(self) -> Self {
|
||||
Self(self.0.abs(), self.1.abs(), self.2.abs())
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` containing the nearest integer to a number for each element of `self`.
|
||||
/// Round half-way cases away from 0.0.
|
||||
#[inline]
|
||||
pub fn round(self) -> Self {
|
||||
Self(self.0.round(), self.1.round(), self.2.round())
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` containing the largest integer less than or equal to a number for each
|
||||
/// element of `self`.
|
||||
#[inline]
|
||||
pub fn floor(self) -> Self {
|
||||
Self(self.0.floor(), self.1.floor(), self.2.floor())
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` containing this vector raised to the power of `power`
|
||||
#[inline]
|
||||
pub fn pow(self, power: f32) -> Self {
|
||||
Self(self.0.pow(power), self.1.pow(power), self.2.pow(power))
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` containing this vector exp'd
|
||||
#[inline]
|
||||
pub fn exp(self) -> Self {
|
||||
Self(self.0.exp(), self.1.exp(), self.2.exp())
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` containing the smallest integer greater than or equal to a number for each
|
||||
/// element of `self`.
|
||||
#[inline]
|
||||
pub fn ceil(self) -> Self {
|
||||
Self(self.0.ceil(), self.1.ceil(), self.2.ceil())
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.9.5", note = "please use `Vec3::recip` instead")]
|
||||
#[inline(always)]
|
||||
pub fn reciprocal(self) -> Self {
|
||||
self.recip()
|
||||
}
|
||||
|
||||
/// Returns a `Vec3` containing the reciprocal `1.0/n` of each element of `self`.
|
||||
#[inline]
|
||||
pub fn recip(self) -> Self {
|
||||
Self(self.0.recip(), self.1.recip(), self.2.recip())
|
||||
}
|
||||
|
||||
/// Performs a linear interpolation between `self` and `other` based on
|
||||
/// the value `s`.
|
||||
///
|
||||
/// When `s` is `0.0`, the result will be equal to `self`. When `s`
|
||||
/// is `1.0`, the result will be equal to `other`.
|
||||
#[inline]
|
||||
pub fn lerp(self, other: Self, s: f32) -> Self {
|
||||
self + ((other - self) * s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Vec3> for Vec3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, other: Self) -> Self {
|
||||
Self(self.0 / other.0, self.1 / other.1, self.2 / other.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<Vec3> for Vec3 {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: Self) {
|
||||
self.0 /= other.0;
|
||||
self.1 /= other.1;
|
||||
self.2 /= other.2;
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f32> for Vec3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, other: f32) -> Self {
|
||||
Self(self.0 / other, self.1 / other, self.2 / other)
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<f32> for Vec3 {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: f32) {
|
||||
self.0 /= other;
|
||||
self.1 /= other;
|
||||
self.2 /= other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Vec3> for f32 {
|
||||
type Output = Vec3;
|
||||
#[inline]
|
||||
fn div(self, other: Vec3) -> Vec3 {
|
||||
Vec3(self / other.0, self / other.1, self / other.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec3> for Vec3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: Self) -> Self {
|
||||
Self(self.0 * other.0, self.1 * other.1, self.2 * other.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<Vec3> for Vec3 {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
self.0 *= other.0;
|
||||
self.1 *= other.1;
|
||||
self.2 *= other.2;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Vec3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: f32) -> Self {
|
||||
Self(self.0 * other, self.1 * other, self.2 * other)
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<f32> for Vec3 {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, other: f32) {
|
||||
self.0 *= other;
|
||||
self.1 *= other;
|
||||
self.2 *= other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec3> for f32 {
|
||||
type Output = Vec3;
|
||||
#[inline]
|
||||
fn mul(self, other: Vec3) -> Vec3 {
|
||||
Vec3(self * other.0, self * other.1, self * other.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Vec3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self(self.0 + other.0, self.1 + other.1, self.2 + other.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Vec3 {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.0 += other.0;
|
||||
self.1 += other.1;
|
||||
self.2 += other.2;
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Vec3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn sub(self, other: Self) -> Self {
|
||||
Self(self.0 - other.0, self.1 - other.1, self.2 - other.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Vec3 {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.0 -= other.0;
|
||||
self.1 -= other.1;
|
||||
self.2 -= other.2;
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Vec3 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn neg(self) -> Self {
|
||||
Self(-self.0, -self.1, -self.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32, f32)> for Vec3 {
|
||||
#[inline]
|
||||
fn from(t: (f32, f32, f32)) -> Self {
|
||||
Self::new(t.0, t.1, t.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec3> for (f32, f32, f32) {
|
||||
#[inline]
|
||||
fn from(v: Vec3) -> Self {
|
||||
(v.0, v.1, v.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 3]> for Vec3 {
|
||||
#[inline]
|
||||
fn from(a: [f32; 3]) -> Self {
|
||||
Self::new(a[0], a[1], a[2])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec3> for [f32; 3] {
|
||||
#[inline]
|
||||
fn from(v: Vec3) -> Self {
|
||||
[v.0, v.1, v.2]
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vec3_private() {
|
||||
assert_eq!(
|
||||
vec3(1.0, 1.0, 1.0).mul_add(vec3(0.5, 2.0, -4.0), vec3(-1.0, -1.0, -1.0)),
|
||||
vec3(-0.5, 1.0, -5.0)
|
||||
);
|
||||
assert_eq!(vec3(1.0, 2.0, 3.0).dup_x(), vec3(1.0, 1.0, 1.0));
|
||||
assert_eq!(vec3(1.0, 2.0, 3.0).dup_y(), vec3(2.0, 2.0, 2.0));
|
||||
assert_eq!(vec3(1.0, 2.0, 3.0).dup_z(), vec3(3.0, 3.0, 3.0));
|
||||
}
|
@ -1,619 +0,0 @@
|
||||
use crate::math::{MathExt, Vec3};
|
||||
use core::{f32, ops::*};
|
||||
|
||||
/// A 4-dimensional vector.
|
||||
///
|
||||
/// A 4-dimensional vector.
|
||||
///
|
||||
/// This type is 16 byte aligned unless the `scalar-math` feature is enabed.
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Default)]
|
||||
// if compiling with simd enabled assume alignment needs to match the simd type
|
||||
#[repr(simd)]
|
||||
pub struct Vec4(pub f32, pub f32, pub f32, pub f32);
|
||||
|
||||
/// Creates a `Vec4`.
|
||||
#[inline]
|
||||
pub fn vec4(x: f32, y: f32, z: f32, w: f32) -> Vec4 {
|
||||
Vec4::new(x, y, z, w)
|
||||
}
|
||||
|
||||
impl Vec4 {
|
||||
/// Creates a new `Vec4`.
|
||||
#[inline]
|
||||
pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
|
||||
Self(x, y, z, w)
|
||||
}
|
||||
|
||||
/// Creates a `Vec4` with all elements set to `0.0`.
|
||||
#[inline]
|
||||
pub const fn zero() -> Self {
|
||||
Self::splat(0.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec4` with all elements set to `1.0`.
|
||||
#[inline]
|
||||
pub const fn one() -> Self {
|
||||
Self::splat(1.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec4` with values `[x: 1.0, y: 0.0, z: 0.0, w: 0.0]`.
|
||||
#[inline]
|
||||
pub const fn unit_x() -> Self {
|
||||
Self::new(1.0, 0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec4` with values `[x: 0.0, y: 1.0, z: 0.0, w: 0.0]`.
|
||||
#[inline]
|
||||
pub const fn unit_y() -> Self {
|
||||
Self::new(0.0, 1.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec4` with values `[x: 0.0, y: 0.0, z: 1.0, w: 0.0]`.
|
||||
#[inline]
|
||||
pub const fn unit_z() -> Self {
|
||||
Self::new(0.0, 0.0, 1.0, 0.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec4` with values `[x: 0.0, y: 0.0, z: 0.0, w: 1.0]`.
|
||||
#[inline]
|
||||
pub const fn unit_w() -> Self {
|
||||
Self::new(0.0, 0.0, 0.0, 1.0)
|
||||
}
|
||||
|
||||
/// Creates a `Vec4` with all elements set to `v`.
|
||||
#[inline]
|
||||
pub const fn splat(v: f32) -> Self {
|
||||
Self(v, v, v, v)
|
||||
}
|
||||
|
||||
/// Creates a `Vec3` from the first three elements of `self`,
|
||||
/// removing `w`.
|
||||
#[inline]
|
||||
pub fn truncate(self) -> Vec3 {
|
||||
Vec3::new(self.0, self.1, self.2)
|
||||
}
|
||||
|
||||
/// Returns element `x`.
|
||||
#[inline]
|
||||
pub fn x(self) -> f32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns element `y`.
|
||||
#[inline]
|
||||
pub fn y(self) -> f32 {
|
||||
self.1
|
||||
}
|
||||
|
||||
/// Returns element `z`.
|
||||
#[inline]
|
||||
pub fn z(self) -> f32 {
|
||||
self.2
|
||||
}
|
||||
|
||||
/// Returns element `w`.
|
||||
#[inline]
|
||||
pub fn w(self) -> f32 {
|
||||
self.3
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to element `x`.
|
||||
#[inline]
|
||||
pub fn x_mut(&mut self) -> &mut f32 {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to element `y`.
|
||||
#[inline]
|
||||
pub fn y_mut(&mut self) -> &mut f32 {
|
||||
&mut self.1
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to element `z`.
|
||||
#[inline]
|
||||
pub fn z_mut(&mut self) -> &mut f32 {
|
||||
&mut self.2
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to element `w`.
|
||||
#[inline]
|
||||
pub fn w_mut(&mut self) -> &mut f32 {
|
||||
&mut self.3
|
||||
}
|
||||
|
||||
/// Sets element `x`.
|
||||
#[inline]
|
||||
pub fn set_x(&mut self, x: f32) {
|
||||
self.0 = x;
|
||||
}
|
||||
|
||||
/// Sets element `y`.
|
||||
#[inline]
|
||||
pub fn set_y(&mut self, y: f32) {
|
||||
self.1 = y;
|
||||
}
|
||||
|
||||
/// Sets element `z`.
|
||||
#[inline]
|
||||
pub fn set_z(&mut self, z: f32) {
|
||||
self.2 = z;
|
||||
}
|
||||
|
||||
/// Sets element `w`.
|
||||
#[inline]
|
||||
pub fn set_w(&mut self, w: f32) {
|
||||
self.3 = w;
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` with all elements set to the value of element `x`.
|
||||
#[inline]
|
||||
pub fn dup_x(self) -> Self {
|
||||
Self(self.0, self.0, self.0, self.0)
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` with all elements set to the value of element `y`.
|
||||
#[inline]
|
||||
pub fn dup_y(self) -> Self {
|
||||
Self(self.1, self.1, self.1, self.1)
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` with all elements set to the value of element `z`.
|
||||
#[inline]
|
||||
pub fn dup_z(self) -> Self {
|
||||
Self(self.2, self.2, self.2, self.2)
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` with all elements set to the value of element `w`.
|
||||
#[inline]
|
||||
pub fn dup_w(self) -> Self {
|
||||
Self(self.3, self.3, self.3, self.3)
|
||||
}
|
||||
|
||||
/// Computes the 4D dot product of `self` and `other`.
|
||||
#[inline]
|
||||
pub fn dot(self, other: Self) -> f32 {
|
||||
(self.0 * other.0) + (self.1 * other.1) + (self.2 * other.2) + (self.3 * other.3)
|
||||
}
|
||||
|
||||
/// Computes the 4D length of `self`.
|
||||
#[inline]
|
||||
pub fn length(self) -> f32 {
|
||||
self.dot(self).sqrt()
|
||||
}
|
||||
|
||||
/// Computes the squared 4D length of `self`.
|
||||
///
|
||||
/// This is generally faster than `Vec4::length()` as it avoids a square
|
||||
/// root operation.
|
||||
#[inline]
|
||||
pub fn length_squared(self) -> f32 {
|
||||
self.dot(self)
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.9.5", note = "please use `Vec4::length_recip` instead")]
|
||||
#[inline(always)]
|
||||
pub fn length_reciprocal(self) -> f32 {
|
||||
self.length_recip()
|
||||
}
|
||||
|
||||
/// Computes `1.0 / Vec4::length()`.
|
||||
///
|
||||
/// For valid results, `self` must _not_ be of length zero.
|
||||
#[inline]
|
||||
pub fn length_recip(self) -> f32 {
|
||||
self.length().recip()
|
||||
}
|
||||
|
||||
/// Returns `self` normalized to length 1.0.
|
||||
///
|
||||
/// For valid results, `self` must _not_ be of length zero.
|
||||
#[inline]
|
||||
pub fn normalize(self) -> Self {
|
||||
self * self.length_recip()
|
||||
}
|
||||
|
||||
/// Returns the vertical minimum of `self` and `other`.
|
||||
///
|
||||
/// In other words, this computes
|
||||
/// `[x: min(x1, x2), y: min(y1, y2), z: min(z1, z2), w: min(w1, w2)]`,
|
||||
/// taking the minimum of each element individually.
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
Self(
|
||||
self.0.min(other.0),
|
||||
self.1.min(other.1),
|
||||
self.2.min(other.2),
|
||||
self.3.min(other.3),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the vertical maximum of `self` and `other`.
|
||||
///
|
||||
/// In other words, this computes
|
||||
/// `[x: max(x1, x2), y: max(y1, y2), z: max(z1, z2), w: max(w1, w2)]`,
|
||||
/// taking the maximum of each element individually.
|
||||
#[inline]
|
||||
pub fn max(self, other: Self) -> Self {
|
||||
Self(
|
||||
self.0.max(other.0),
|
||||
self.1.max(other.1),
|
||||
self.2.max(other.2),
|
||||
self.3.max(other.3),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the horizontal minimum of `self`'s elements.
|
||||
///
|
||||
/// In other words, this computes `min(x, y, z, w)`.
|
||||
#[inline]
|
||||
pub fn min_element(self) -> f32 {
|
||||
self.0.min(self.1.min(self.2.min(self.3)))
|
||||
}
|
||||
|
||||
/// Returns the horizontal maximum of `self`'s elements.
|
||||
///
|
||||
/// In other words, this computes `max(x, y, z, w)`.
|
||||
#[inline]
|
||||
pub fn max_element(self) -> f32 {
|
||||
self.0.max(self.1.max(self.2.min(self.3)))
|
||||
}
|
||||
|
||||
/// Creates a `Vec4` from the first four values in `slice`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `slice` is less than four elements long.
|
||||
#[inline]
|
||||
pub fn from_slice_unaligned(slice: &[f32]) -> Self {
|
||||
Self(slice[0], slice[1], slice[2], slice[3])
|
||||
}
|
||||
|
||||
/// Writes the elements of `self` to the first four elements in `slice`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `slice` is less than four elements long.
|
||||
#[inline]
|
||||
pub fn write_to_slice_unaligned(self, slice: &mut [f32]) {
|
||||
slice[0] = self.0;
|
||||
slice[1] = self.1;
|
||||
slice[2] = self.2;
|
||||
slice[3] = self.3;
|
||||
}
|
||||
|
||||
/// Per element multiplication/addition of the three inputs: b + (self * a)
|
||||
#[inline]
|
||||
pub fn mul_add(self, a: Self, b: Self) -> Self {
|
||||
Self(
|
||||
(self.0 * a.0) + b.0,
|
||||
(self.1 * a.1) + b.1,
|
||||
(self.2 * a.2) + b.2,
|
||||
(self.3 * a.3) + b.3,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` containing the absolute value of each element of `self`.
|
||||
#[inline]
|
||||
pub fn abs(self) -> Self {
|
||||
Self(self.0.abs(), self.1.abs(), self.2.abs(), self.3.abs())
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` containing the nearest integer to a number for each element of `self`.
|
||||
/// Round half-way cases away from 0.0.
|
||||
#[inline]
|
||||
pub fn round(self) -> Self {
|
||||
Self(
|
||||
self.0.round(),
|
||||
self.1.round(),
|
||||
self.2.round(),
|
||||
self.3.round(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` containing the largest integer less than or equal to a number for each
|
||||
/// element of `self`.
|
||||
#[inline]
|
||||
pub fn floor(self) -> Self {
|
||||
Self(
|
||||
self.0.floor(),
|
||||
self.1.floor(),
|
||||
self.2.floor(),
|
||||
self.3.floor(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` containing this vector raised to the power of `power`
|
||||
#[inline]
|
||||
pub fn pow(self, power: f32) -> Self {
|
||||
Self(
|
||||
self.0.pow(power),
|
||||
self.1.pow(power),
|
||||
self.2.pow(power),
|
||||
self.3.pow(power),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` containing this vector exp'd
|
||||
#[inline]
|
||||
pub fn exp(self) -> Self {
|
||||
Self(self.0.exp(), self.1.exp(), self.2.exp(), self.3.exp())
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` containing the smallest integer greater than or equal to a number for each
|
||||
/// element of `self`.
|
||||
#[inline]
|
||||
pub fn ceil(self) -> Self {
|
||||
Self(self.0.ceil(), self.1.ceil(), self.2.ceil(), self.3.ceil())
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.9.5", note = "please use `Vec4::recip` instead")]
|
||||
#[inline(always)]
|
||||
pub fn reciprocal(self) -> Self {
|
||||
self.recip()
|
||||
}
|
||||
|
||||
/// Returns a `Vec4` containing the reciprocal `1.0/n` of each element of `self`.
|
||||
#[inline]
|
||||
pub fn recip(self) -> Self {
|
||||
// TODO: Optimize
|
||||
Self::one() / self
|
||||
}
|
||||
|
||||
/// Performs a linear interpolation between `self` and `other` based on
|
||||
/// the value `s`.
|
||||
///
|
||||
/// When `s` is `0.0`, the result will be equal to `self`. When `s`
|
||||
/// is `1.0`, the result will be equal to `other`.
|
||||
#[inline]
|
||||
pub fn lerp(self, other: Self, s: f32) -> Self {
|
||||
self + ((other - self) * s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Vec4> for Vec4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, other: Self) -> Self {
|
||||
{
|
||||
Self(
|
||||
self.0 / other.0,
|
||||
self.1 / other.1,
|
||||
self.2 / other.2,
|
||||
self.3 / other.3,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<Vec4> for Vec4 {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: Self) {
|
||||
{
|
||||
self.0 /= other.0;
|
||||
self.1 /= other.1;
|
||||
self.2 /= other.2;
|
||||
self.3 /= other.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f32> for Vec4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, other: f32) -> Self {
|
||||
{
|
||||
Self(
|
||||
self.0 / other,
|
||||
self.1 / other,
|
||||
self.2 / other,
|
||||
self.3 / other,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<f32> for Vec4 {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: f32) {
|
||||
{
|
||||
self.0 /= other;
|
||||
self.1 /= other;
|
||||
self.2 /= other;
|
||||
self.3 /= other;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Vec4> for f32 {
|
||||
type Output = Vec4;
|
||||
#[inline]
|
||||
fn div(self, other: Vec4) -> Vec4 {
|
||||
{
|
||||
Vec4(
|
||||
self / other.0,
|
||||
self / other.1,
|
||||
self / other.2,
|
||||
self / other.3,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec4> for Vec4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: Self) -> Self {
|
||||
{
|
||||
Self(
|
||||
self.0 * other.0,
|
||||
self.1 * other.1,
|
||||
self.2 * other.2,
|
||||
self.3 * other.3,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<Vec4> for Vec4 {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
{
|
||||
self.0 *= other.0;
|
||||
self.1 *= other.1;
|
||||
self.2 *= other.2;
|
||||
self.3 *= other.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Vec4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, other: f32) -> Self {
|
||||
{
|
||||
Self(
|
||||
self.0 * other,
|
||||
self.1 * other,
|
||||
self.2 * other,
|
||||
self.3 * other,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<f32> for Vec4 {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, other: f32) {
|
||||
{
|
||||
self.0 *= other;
|
||||
self.1 *= other;
|
||||
self.2 *= other;
|
||||
self.3 *= other;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Vec4> for f32 {
|
||||
type Output = Vec4;
|
||||
#[inline]
|
||||
fn mul(self, other: Vec4) -> Vec4 {
|
||||
{
|
||||
Vec4(
|
||||
self * other.0,
|
||||
self * other.1,
|
||||
self * other.2,
|
||||
self * other.3,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Vec4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
{
|
||||
Self(
|
||||
self.0 + other.0,
|
||||
self.1 + other.1,
|
||||
self.2 + other.2,
|
||||
self.3 + other.3,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Vec4 {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
{
|
||||
self.0 += other.0;
|
||||
self.1 += other.1;
|
||||
self.2 += other.2;
|
||||
self.3 += other.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Vec4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn sub(self, other: Self) -> Self {
|
||||
{
|
||||
Self(
|
||||
self.0 - other.0,
|
||||
self.1 - other.1,
|
||||
self.2 - other.2,
|
||||
self.3 - other.3,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Vec4 {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
{
|
||||
self.0 -= other.0;
|
||||
self.1 -= other.1;
|
||||
self.2 -= other.2;
|
||||
self.3 -= other.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Vec4 {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn neg(self) -> Self {
|
||||
{
|
||||
Self(-self.0, -self.1, -self.2, -self.3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32, f32, f32)> for Vec4 {
|
||||
#[inline]
|
||||
fn from(t: (f32, f32, f32, f32)) -> Self {
|
||||
Self::new(t.0, t.1, t.2, t.3)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec4> for (f32, f32, f32, f32) {
|
||||
#[inline]
|
||||
fn from(v: Vec4) -> Self {
|
||||
{
|
||||
(v.0, v.1, v.2, v.3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 4]> for Vec4 {
|
||||
#[inline]
|
||||
fn from(a: [f32; 4]) -> Self {
|
||||
{
|
||||
Self(a[0], a[1], a[2], a[3])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec4> for [f32; 4] {
|
||||
#[inline]
|
||||
fn from(v: Vec4) -> Self {
|
||||
{
|
||||
[v.0, v.1, v.2, v.3]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vec4_private() {
|
||||
assert_eq!(
|
||||
vec4(1.0, 1.0, 1.0, 1.0).mul_add(vec4(0.5, 2.0, -4.0, 0.0), vec4(-1.0, -1.0, -1.0, -1.0)),
|
||||
vec4(-0.5, 1.0, -5.0, -1.0)
|
||||
);
|
||||
assert_eq!(vec4(1.0, 2.0, 3.0, 4.0).dup_x(), vec4(1.0, 1.0, 1.0, 1.0));
|
||||
assert_eq!(vec4(1.0, 2.0, 3.0, 4.0).dup_y(), vec4(2.0, 2.0, 2.0, 2.0));
|
||||
assert_eq!(vec4(1.0, 2.0, 3.0, 4.0).dup_z(), vec4(3.0, 3.0, 3.0, 3.0));
|
||||
assert_eq!(vec4(1.0, 2.0, 4.0, 4.0).dup_w(), vec4(4.0, 4.0, 4.0, 4.0));
|
||||
}
|
85
spirv-std/src/math_ext.rs
Normal file
85
spirv-std/src/math_ext.rs
Normal file
@ -0,0 +1,85 @@
|
||||
pub trait MathExt {
|
||||
fn pow(self, factor: Self) -> Self;
|
||||
fn sqrt(self) -> Self;
|
||||
fn log2(self) -> Self;
|
||||
fn abs(self) -> Self;
|
||||
fn cos(self) -> Self;
|
||||
fn sin(self) -> Self;
|
||||
fn sin_cos(self) -> (f32, f32);
|
||||
fn round(self) -> Self;
|
||||
fn floor(self) -> Self;
|
||||
fn ceil(self) -> Self;
|
||||
fn exp(self) -> Self;
|
||||
fn saturate(self) -> Self;
|
||||
|
||||
fn signum(self) -> Self;
|
||||
fn copysign(self, sign: Self) -> Self;
|
||||
|
||||
// TODO: implement but need new intrinsic in core?
|
||||
//fn tan(self) -> Self;
|
||||
}
|
||||
|
||||
impl MathExt for f32 {
|
||||
fn pow(self, factor: f32) -> f32 {
|
||||
unsafe { core::intrinsics::powf32(self, factor) }
|
||||
}
|
||||
|
||||
fn sqrt(self) -> f32 {
|
||||
unsafe { core::intrinsics::sqrtf32(self) }
|
||||
}
|
||||
|
||||
fn log2(self) -> f32 {
|
||||
unsafe { core::intrinsics::log2f32(self) }
|
||||
}
|
||||
|
||||
fn abs(self) -> f32 {
|
||||
unsafe { core::intrinsics::fabsf32(self) }
|
||||
}
|
||||
|
||||
fn cos(self) -> f32 {
|
||||
unsafe { core::intrinsics::cosf32(self) }
|
||||
}
|
||||
|
||||
fn sin(self) -> f32 {
|
||||
unsafe { core::intrinsics::sinf32(self) }
|
||||
}
|
||||
|
||||
// TODO: implement but need new intrinsic in core?
|
||||
//fn tan(self) -> f32 {
|
||||
|
||||
fn sin_cos(self) -> (f32, f32) {
|
||||
(self.sin(), self.cos())
|
||||
}
|
||||
|
||||
fn round(self) -> f32 {
|
||||
unsafe { core::intrinsics::roundf32(self) }
|
||||
}
|
||||
|
||||
fn floor(self) -> f32 {
|
||||
unsafe { core::intrinsics::floorf32(self) }
|
||||
}
|
||||
|
||||
fn ceil(self) -> f32 {
|
||||
unsafe { core::intrinsics::ceilf32(self) }
|
||||
}
|
||||
|
||||
fn exp(self) -> f32 {
|
||||
unsafe { core::intrinsics::expf32(self) }
|
||||
}
|
||||
|
||||
fn saturate(self) -> f32 {
|
||||
self.max(0.0).min(1.0)
|
||||
}
|
||||
|
||||
fn signum(self) -> f32 {
|
||||
if self.is_nan() {
|
||||
Self::NAN
|
||||
} else {
|
||||
1.0_f32.copysign(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn copysign(self, sign: f32) -> f32 {
|
||||
unsafe { core::intrinsics::copysignf32(self, sign) }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user