Compare commits

...

10 commits

Author SHA1 Message Date
aloucks
d5e765db61
Merge pull request #548 from gents83/master
Fixing clippy warnings
2022-04-16 13:32:31 -04:00
Mauro Gentile
33fb2fd24f Fixing clippy warnings 2022-04-16 10:52:39 +02:00
maku693
2e76e82cc0 cargo fmt 2022-03-06 19:28:56 -08:00
maku693
11a5346291 Add support for cast using bytemuck crate 2022-03-06 19:28:56 -08:00
aloucks
78c082e944
Merge pull request #539 from CyborgSquirrel/master
Implement IntoMint trait for Vectors, Points, Matrices, and Quaternions
2021-11-26 09:11:33 -05:00
Andrei Jardan
d4d19b9122 Implement IntoMint trait for Vectors, Points, Matrices, and Quaternions
- Updated mint to 0.5.8, so that the IntoMint trait is available
- Implemented IntoMint for Vectors, Points, Matrices, and Quaternions
2021-11-25 13:45:53 +02:00
Shane Pearman
af127633cc Replace use of BaseFloat/Float with BaseNum/Num where possible 2021-08-11 12:07:57 -04:00
Shane Pearman
41fb64cea0 Remove NumCast bound from BaseNum 2021-08-11 12:07:57 -04:00
Dana Jansens
e57b543449
Update links in quaternions.rs (#535)
* Update link to Arcsynthesis tutorial about quaternions

The old link no longer goes to a valid page, and it appears to be malicious.

* Fix links in quaternion.rs

Don't split the line between the [text] and (url) or they don't get turned into a link in docs.rs
2021-07-06 01:43:28 -04:00
Rémi Lauzier
df218547d1 Fix some clippy warnings and some typo 2021-06-16 14:09:50 -04:00
20 changed files with 180 additions and 140 deletions

View file

@ -51,7 +51,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Add `Array::len`
- Re-export `Bounded` and implement for vectors, points, and angles
- Add vector subtraction to `EuclideanSpace`
- Add swizzle functions behinde that `"swizzle"` feature
- Add swizzle functions behind that `"swizzle"` feature
- Add `Matrix4::look_at_dir`
### Changed

View file

@ -22,13 +22,14 @@ swizzle = []
[dependencies]
approx = "0.5"
mint = { version = "0.5", optional = true }
mint = { version = "0.5.8", optional = true }
num-traits = "0.2"
# small_rng used only for benchmarks
rand = { version = "0.8", features = ["small_rng"], optional = true }
serde = { version = "1.0", features = ["serde_derive"], optional = true }
# works only in rust toolchain up to 1.32, disabled indefinitely
#simd = { version = "0.2", optional = true }
bytemuck = { version = "1.0", optional = true }
[dev-dependencies]
serde_json = "1.0"

View file

@ -7,7 +7,7 @@ use std::string::String;
/// Generate the name of the swizzle function and what it returns.
/// NOTE: This function assumes that variables are in ASCII format
#[cfg(feature = "swizzle")]
fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize, upto: usize) -> Option<(String, String)> {
fn gen_swizzle_nth(variables: &str, mut i: usize, upto: usize) -> Option<(String, String)> {
debug_assert!(i > 0); // zeroth permutation is empty
let mut swizzle_impl = String::new();
let mut swizzle = String::new();
@ -22,7 +22,7 @@ fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize, upto: usize) -> Option<
let c = variables.as_bytes()[i % n - 1] as char;
swizzle.push(c);
swizzle_impl.push_str(&format!("self.{}, ", c));
i = i / n;
i /= n;
}
Some((swizzle, swizzle_impl))
}

View file

@ -30,7 +30,7 @@ use rand::{
use structure::*;
use approx;
use num::BaseFloat;
use num::{BaseFloat, BaseNum};
/// An angle, in radians.
///
@ -138,38 +138,38 @@ macro_rules! impl_angle {
}
}
impl_operator!(<S: BaseFloat> Add<$Angle<S> > for $Angle<S> {
impl_operator!(<S: BaseNum> Add<$Angle<S> > for $Angle<S> {
fn add(lhs, rhs) -> $Angle<S> { $Angle(lhs.0 + rhs.0) }
});
impl_operator!(<S: BaseFloat> Sub<$Angle<S> > for $Angle<S> {
impl_operator!(<S: BaseNum> Sub<$Angle<S> > for $Angle<S> {
fn sub(lhs, rhs) -> $Angle<S> { $Angle(lhs.0 - rhs.0) }
});
impl_operator!(<S: BaseFloat> Div<$Angle<S> > for $Angle<S> {
impl_operator!(<S: BaseNum> Div<$Angle<S> > for $Angle<S> {
fn div(lhs, rhs) -> S { lhs.0 / rhs.0 }
});
impl_operator!(<S: BaseFloat> Rem<$Angle<S> > for $Angle<S> {
impl_operator!(<S: BaseNum> Rem<$Angle<S> > for $Angle<S> {
fn rem(lhs, rhs) -> $Angle<S> { $Angle(lhs.0 % rhs.0) }
});
impl_assignment_operator!(<S: BaseFloat> AddAssign<$Angle<S> > for $Angle<S> {
impl_assignment_operator!(<S: BaseNum> AddAssign<$Angle<S> > for $Angle<S> {
fn add_assign(&mut self, other) { self.0 += other.0; }
});
impl_assignment_operator!(<S: BaseFloat> SubAssign<$Angle<S> > for $Angle<S> {
impl_assignment_operator!(<S: BaseNum> SubAssign<$Angle<S> > for $Angle<S> {
fn sub_assign(&mut self, other) { self.0 -= other.0; }
});
impl_assignment_operator!(<S: BaseFloat> RemAssign<$Angle<S> > for $Angle<S> {
impl_assignment_operator!(<S: BaseNum> RemAssign<$Angle<S> > for $Angle<S> {
fn rem_assign(&mut self, other) { self.0 %= other.0; }
});
impl_operator!(<S: BaseFloat> Mul<S> for $Angle<S> {
impl_operator!(<S: BaseNum> Mul<S> for $Angle<S> {
fn mul(lhs, scalar) -> $Angle<S> { $Angle(lhs.0 * scalar) }
});
impl_operator!(<S: BaseFloat> Div<S> for $Angle<S> {
impl_operator!(<S: BaseNum> Div<S> for $Angle<S> {
fn div(lhs, scalar) -> $Angle<S> { $Angle(lhs.0 / scalar) }
});
impl_assignment_operator!(<S: BaseFloat> MulAssign<S> for $Angle<S> {
impl_assignment_operator!(<S: BaseNum> MulAssign<S> for $Angle<S> {
fn mul_assign(&mut self, scalar) { self.0 *= scalar; }
});
impl_assignment_operator!(<S: BaseFloat> DivAssign<S> for $Angle<S> {
impl_assignment_operator!(<S: BaseNum> DivAssign<S> for $Angle<S> {
fn div_assign(&mut self, scalar) { self.0 /= scalar; }
});

View file

@ -20,7 +20,7 @@
//! let uniforms = uniform! {
//! point: Into::<[_; 2]>::into(point),
//! matrix: Into::<[[_; 4]; 4]>::into(matrix),
//! // Yuck!! (ノಥ益ಥ)ノ ┻━┻
//! // Yuck!! (ノಥ益ಥ)ノ ┻━┻)
//! };
//! # }
//! ` ` `

View file

@ -224,3 +224,6 @@ impl<S: Clone, A: Angle + Into<S>> From<Euler<A>> for MintEuler<S> {
MintEuler::from([v.x.into(), v.y.into(), v.z.into()])
}
}
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Euler);

View file

@ -55,6 +55,9 @@
#[macro_use]
extern crate approx;
#[cfg(feature = "bytemuck")]
extern crate bytemuck;
#[cfg(feature = "mint")]
pub extern crate mint;

View file

@ -24,7 +24,10 @@ macro_rules! default_fn {
#[cfg(not(feature = "simd"))]
macro_rules! default_fn {
{ $($tt:tt)* } => { fn $( $tt )* };
{ $($tt:tt)* } => {
#[inline]
fn $( $tt )*
};
}
/// Generates a binary operator implementation for the permutations of by-ref and by-val
@ -35,7 +38,6 @@ macro_rules! impl_operator {
}) => {
impl<$S: $Constraint> $Op for $Lhs {
type Output = $Output;
#[inline]
default_fn!($op(self) -> $Output {
let $x = self; $body
});
@ -43,7 +45,6 @@ macro_rules! impl_operator {
impl<'a, $S: $Constraint> $Op for &'a $Lhs {
type Output = $Output;
#[inline]
default_fn!($op(self) -> $Output {
let $x = self; $body
});
@ -55,7 +56,6 @@ macro_rules! impl_operator {
}) => {
impl<$S: $Constraint> $Op<$Rhs> for $Lhs {
type Output = $Output;
#[inline]
default_fn!($op(self, other: $Rhs) -> $Output {
let ($lhs, $rhs) = (self, other); $body
});
@ -63,7 +63,6 @@ macro_rules! impl_operator {
impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs {
type Output = $Output;
#[inline]
default_fn!($op(self, other: $Rhs) -> $Output {
let ($lhs, $rhs) = (self, other); $body
});
@ -75,7 +74,6 @@ macro_rules! impl_operator {
}) => {
impl<$S: $Constraint> $Op<$Rhs> for $Lhs {
type Output = $Output;
#[inline]
default_fn!( $op(self, other: $Rhs) -> $Output {
let ($lhs, $rhs) = (self, other); $body
});
@ -83,7 +81,6 @@ macro_rules! impl_operator {
impl<'a, $S: $Constraint> $Op<&'a $Rhs> for $Lhs {
type Output = $Output;
#[inline]
default_fn!( $op(self, other: &'a $Rhs) -> $Output {
let ($lhs, $rhs) = (self, other); $body
});
@ -91,7 +88,6 @@ macro_rules! impl_operator {
impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs {
type Output = $Output;
#[inline]
default_fn!( $op(self, other: $Rhs) -> $Output {
let ($lhs, $rhs) = (self, other); $body
});
@ -99,7 +95,6 @@ macro_rules! impl_operator {
impl<'a, 'b, $S: $Constraint> $Op<&'a $Rhs> for &'b $Lhs {
type Output = $Output;
#[inline]
default_fn!( $op(self, other: &'a $Rhs) -> $Output {
let ($lhs, $rhs) = (self, other); $body
});
@ -111,7 +106,6 @@ macro_rules! impl_operator {
}) => {
impl $Op<$Rhs<$S>> for $Lhs {
type Output = $Output;
#[inline]
default_fn!( $op(self, other: $Rhs<$S>) -> $Output {
let ($lhs, $rhs) = (self, other); $body
});
@ -119,7 +113,6 @@ macro_rules! impl_operator {
impl<'a> $Op<&'a $Rhs<$S>> for $Lhs {
type Output = $Output;
#[inline]
default_fn!( $op(self, other: &'a $Rhs<$S>) -> $Output {
let ($lhs, $rhs) = (self, other); $body
});
@ -132,7 +125,6 @@ macro_rules! impl_assignment_operator {
fn $op:ident(&mut $lhs:ident, $rhs:ident) $body:block
}) => {
impl<$S: $Constraint + $Op<$S>> $Op<$Rhs> for $Lhs {
#[inline]
default_fn!( $op(&mut $lhs, $rhs: $Rhs) $body );
}
};
@ -218,7 +210,7 @@ macro_rules! impl_tuple_conversions {
impl<$S> From<$Tuple> for $ArrayN<$S> {
#[inline]
fn from(v: $Tuple) -> $ArrayN<$S> {
match v { ($($field),+,) => $ArrayN { $($field: $field),+ } }
match v { ($($field),+,) => $ArrayN { $($field),+ } }
}
}
@ -373,7 +365,20 @@ macro_rules! impl_mint_conversions {
$ArrayN { $( $field: v.$field, )+ }
}
}
impl<S: Clone> mint::IntoMint for $ArrayN<S> {
type MintType = mint::$Mint<S>;
}
}
}
/// Generate implementation required to cast using `bytemuck`
#[cfg(feature = "bytemuck")]
macro_rules! impl_bytemuck_cast {
($ArrayN:ident) => {
unsafe impl<S: bytemuck::Pod> bytemuck::Pod for $ArrayN<S> {}
unsafe impl<S: bytemuck::Zeroable> bytemuck::Zeroable for $ArrayN<S> {}
};
}
include!(concat!(env!("OUT_DIR"), "/swizzle_operator_macro.rs"));

View file

@ -30,7 +30,7 @@ use structure::*;
use angle::Rad;
use approx;
use euler::Euler;
use num::BaseFloat;
use num::{BaseFloat, BaseNum};
use point::{Point2, Point3};
use quaternion::Quaternion;
use transform::{Transform, Transform2, Transform3};
@ -563,8 +563,8 @@ impl<S: BaseFloat> VectorSpace for Matrix4<S> {
}
impl<S: BaseFloat> Matrix for Matrix2<S> {
type Column = Vector2<S>;
type Row = Vector2<S>;
type Column = Vector2<S>;
type Transpose = Matrix2<S>;
#[inline]
@ -661,8 +661,8 @@ impl<S: BaseFloat> SquareMatrix for Matrix2<S> {
}
impl<S: BaseFloat> Matrix for Matrix3<S> {
type Column = Vector3<S>;
type Row = Vector3<S>;
type Column = Vector3<S>;
type Transpose = Matrix3<S>;
#[inline]
@ -776,8 +776,8 @@ impl<S: BaseFloat> SquareMatrix for Matrix3<S> {
}
impl<S: BaseFloat> Matrix for Matrix4<S> {
type Column = Vector4<S>;
type Row = Vector4<S>;
type Column = Vector4<S>;
type Transpose = Matrix4<S>;
#[inline]
@ -1092,13 +1092,13 @@ impl<S: BaseFloat> Transform<Point2<S>> for Matrix3<S> {
Matrix3::from(Matrix2::look_at(dir, up))
}
fn look_at_lh(eye: Point2<S>, center: Point2<S>, up: Vector2<S>) -> Matrix3<S> {
let dir = center - eye;
fn look_at_rh(eye: Point2<S>, center: Point2<S>, up: Vector2<S>) -> Matrix3<S> {
let dir = eye - center;
Matrix3::from(Matrix2::look_at(dir, up))
}
fn look_at_rh(eye: Point2<S>, center: Point2<S>, up: Vector2<S>) -> Matrix3<S> {
let dir = eye - center;
fn look_at_lh(eye: Point2<S>, center: Point2<S>, up: Vector2<S>) -> Matrix3<S> {
let dir = center - eye;
Matrix3::from(Matrix2::look_at(dir, up))
}
@ -1125,16 +1125,16 @@ impl<S: BaseFloat> Transform<Point3<S>> for Matrix3<S> {
Matrix3::look_to_lh(dir, up)
}
fn look_at_lh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix3<S> {
let dir = center - eye;
Matrix3::look_to_lh(dir, up)
}
fn look_at_rh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix3<S> {
let dir = center - eye;
Matrix3::look_to_rh(dir, up)
}
fn look_at_lh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix3<S> {
let dir = center - eye;
Matrix3::look_to_lh(dir, up)
}
fn transform_vector(&self, vec: Vector3<S>) -> Vector3<S> {
self * vec
}
@ -1157,14 +1157,14 @@ impl<S: BaseFloat> Transform<Point3<S>> for Matrix4<S> {
Matrix4::look_at_rh(eye, center, up)
}
fn look_at_lh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
Matrix4::look_at_lh(eye, center, up)
}
fn look_at_rh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
Matrix4::look_at_rh(eye, center, up)
}
fn look_at_lh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
Matrix4::look_at_lh(eye, center, up)
}
fn transform_vector(&self, vec: Vector3<S>) -> Vector3<S> {
(self * vec.extend(S::zero())).truncate()
}
@ -1559,6 +1559,9 @@ macro_rules! mint_conversions {
}
}
impl<S: Clone> mint::IntoMint for $MatrixN<S> {
type MintType = mint::$MintN<S>;
}
}
}
@ -1569,7 +1572,14 @@ mint_conversions!(Matrix3 { x, y, z }, ColumnMatrix3);
#[cfg(feature = "mint")]
mint_conversions!(Matrix4 { x, y, z, w }, ColumnMatrix4);
impl<S: BaseFloat> From<Matrix2<S>> for Matrix3<S> {
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Matrix2);
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Matrix3);
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Matrix4);
impl<S: BaseNum> From<Matrix2<S>> for Matrix3<S> {
/// Clone the elements of a 2-dimensional matrix into the top-left corner
/// of a 3-dimensional identity matrix.
fn from(m: Matrix2<S>) -> Matrix3<S> {
@ -1582,7 +1592,7 @@ impl<S: BaseFloat> From<Matrix2<S>> for Matrix3<S> {
}
}
impl<S: BaseFloat> From<Matrix2<S>> for Matrix4<S> {
impl<S: BaseNum> From<Matrix2<S>> for Matrix4<S> {
/// Clone the elements of a 2-dimensional matrix into the top-left corner
/// of a 4-dimensional identity matrix.
fn from(m: Matrix2<S>) -> Matrix4<S> {
@ -1596,7 +1606,7 @@ impl<S: BaseFloat> From<Matrix2<S>> for Matrix4<S> {
}
}
impl<S: BaseFloat> From<Matrix3<S>> for Matrix4<S> {
impl<S: BaseNum> From<Matrix3<S>> for Matrix4<S> {
/// Clone the elements of a 3-dimensional matrix into the top-left corner
/// of a 4-dimensional identity matrix.
fn from(m: Matrix3<S>) -> Matrix4<S> {
@ -1678,7 +1688,7 @@ impl<S: fmt::Debug> fmt::Debug for Matrix4<S> {
impl<S> Distribution<Matrix2<S>> for Standard
where
Standard: Distribution<Vector2<S>>,
S: BaseFloat,
S: BaseNum,
{
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Matrix2<S> {
@ -1693,7 +1703,7 @@ where
impl<S> Distribution<Matrix3<S>> for Standard
where
Standard: Distribution<Vector3<S>>,
S: BaseFloat,
S: BaseNum,
{
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Matrix3<S> {
@ -1709,7 +1719,7 @@ where
impl<S> Distribution<Matrix4<S>> for Standard
where
Standard: Distribution<Vector4<S>>,
S: BaseFloat,
S: BaseNum,
{
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Matrix4<S> {

View file

@ -18,7 +18,7 @@ use approx;
use std::fmt;
use std::ops::*;
use num_traits::{Float, Num, NumCast};
use num_traits::{Float, Num};
/// Base numeric types with partial ordering
pub trait BaseNum:
@ -26,7 +26,6 @@ pub trait BaseNum:
+ Clone
+ fmt::Debug
+ Num
+ NumCast
+ PartialOrd
+ AddAssign
+ SubAssign
@ -41,7 +40,6 @@ impl<T> BaseNum for T where
+ Clone
+ fmt::Debug
+ Num
+ NumCast
+ PartialOrd
+ AddAssign
+ SubAssign

View file

@ -83,7 +83,7 @@ macro_rules! impl_point {
/// Construct a new point, using the provided values.
#[inline]
pub const fn new($($field: S),+) -> $PointN<S> {
$PointN { $($field: $field),+ }
$PointN { $($field),+ }
}
/// Perform the given operation on each field in the point, returning a new point
@ -154,7 +154,7 @@ macro_rules! impl_point {
}
}
impl<S: BaseFloat> MetricSpace for $PointN<S> {
impl<S: BaseNum> MetricSpace for $PointN<S> {
type Metric = S;
#[inline]
@ -368,6 +368,13 @@ impl_mint_conversions!(Point2 { x, y }, Point2);
#[cfg(feature = "mint")]
impl_mint_conversions!(Point3 { x, y, z }, Point3);
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Point1);
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Point2);
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Point3);
impl<S: fmt::Debug> fmt::Debug for Point1<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Point1 ")?;
@ -405,7 +412,7 @@ mod tests {
#[test]
fn test_index_mut() {
let mut p = POINT2;
*&mut p[0] = 0;
p[0] = 0;
assert_eq!(p, [0, 2].into());
}
@ -518,7 +525,7 @@ mod tests {
#[test]
fn test_index_mut() {
let mut p = POINT3;
*&mut p[1] = 0;
p[1] = 0;
assert_eq!(p, [1, 0, 3].into());
}

View file

@ -29,7 +29,7 @@ use angle::Rad;
use approx;
use euler::Euler;
use matrix::{Matrix3, Matrix4};
use num::BaseFloat;
use num::{BaseFloat, BaseNum};
use point::Point3;
use quaternion;
use rotation::{Basis3, Rotation, Rotation3};
@ -72,10 +72,8 @@ impl<S: BaseFloat> Quaternion<S> {
///
/// Return the closest rotation that turns `src` vector into `dst`.
///
/// - [Related StackOverflow question]
/// (http://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another)
/// - [Ogre implementation for normalized vectors]
/// (https://bitbucket.org/sinbad/ogre/src/9db75e3ba05c/OgreMain/include/OgreVector3.h?fileviewer=file-view-default#cl-651)
/// - [Related StackOverflow question](http://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another)
/// - [Ogre implementation for normalized vectors](https://bitbucket.org/sinbad/ogre/src/9db75e3ba05c/OgreMain/include/OgreVector3.h?fileviewer=file-view-default#cl-651)
pub fn from_arc(
src: Vector3<S>,
dst: Vector3<S>,
@ -132,10 +130,8 @@ impl<S: BaseFloat> Quaternion<S> {
/// more advisable to use `nlerp` when you know your rotations are going
/// to be small.
///
/// - [Understanding Slerp, Then Not Using It]
/// (http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/)
/// - [Arcsynthesis OpenGL tutorial]
/// (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html)
/// - [Understanding Slerp, Then Not Using It](http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/)
/// - [Arcsynthesis OpenGL tutorial](https://www.roiatalla.com/public/arcsynthesis/html/Positioning/Tut08%20Interpolation.html)
pub fn slerp(self, mut other: Quaternion<S>, amount: S) -> Quaternion<S> {
let mut dot = self.dot(other);
let dot_threshold: S = cast(0.9995f64).unwrap();
@ -242,7 +238,6 @@ impl<S: NumCast + Copy> Quaternion<S> {
}
impl<S: BaseFloat> InnerSpace for Quaternion<S> {
#[inline]
default_fn!( dot(self, other: Quaternion<S>) -> S {
self.s * other.s + self.v.dot(other.v)
} );
@ -414,7 +409,7 @@ impl<S: BaseFloat> approx::UlpsEq for Quaternion<S> {
}
}
impl<S: BaseFloat> From<Quaternion<S>> for Matrix3<S> {
impl<S: BaseNum> From<Quaternion<S>> for Matrix3<S> {
/// Convert the quaternion to a 3 x 3 rotation matrix.
fn from(quat: Quaternion<S>) -> Matrix3<S> {
let x2 = quat.v.x + quat.v.x;
@ -442,7 +437,7 @@ impl<S: BaseFloat> From<Quaternion<S>> for Matrix3<S> {
}
}
impl<S: BaseFloat> From<Quaternion<S>> for Matrix4<S> {
impl<S: BaseNum> From<Quaternion<S>> for Matrix4<S> {
/// Convert the quaternion to a 4 x 4 rotation matrix.
fn from(quat: Quaternion<S>) -> Matrix4<S> {
let x2 = quat.v.x + quat.v.x;
@ -538,7 +533,7 @@ impl<S: BaseFloat> Rotation3 for Quaternion<S> {
}
}
impl<S: BaseFloat> From<Quaternion<S>> for [S; 4] {
impl<S: BaseNum> From<Quaternion<S>> for [S; 4] {
#[inline]
fn from(v: Quaternion<S>) -> Self {
let (xi, yj, zk, w) = v.into();
@ -546,42 +541,42 @@ impl<S: BaseFloat> From<Quaternion<S>> for [S; 4] {
}
}
impl<S: BaseFloat> AsRef<[S; 4]> for Quaternion<S> {
impl<S: BaseNum> AsRef<[S; 4]> for Quaternion<S> {
#[inline]
fn as_ref(&self) -> &[S; 4] {
unsafe { &*(self as *const quaternion::Quaternion<S> as *const [S; 4]) }
}
}
impl<S: BaseFloat> AsMut<[S; 4]> for Quaternion<S> {
impl<S: BaseNum> AsMut<[S; 4]> for Quaternion<S> {
#[inline]
fn as_mut(&mut self) -> &mut [S; 4] {
unsafe { &mut *(self as *mut quaternion::Quaternion<S> as *mut [S; 4]) }
}
}
impl<S: BaseFloat> From<[S; 4]> for Quaternion<S> {
impl<S: BaseNum> From<[S; 4]> for Quaternion<S> {
#[inline]
fn from(v: [S; 4]) -> Quaternion<S> {
Quaternion::new(v[3], v[0], v[1], v[2])
}
}
impl<'a, S: BaseFloat> From<&'a [S; 4]> for &'a Quaternion<S> {
impl<'a, S: BaseNum> From<&'a [S; 4]> for &'a Quaternion<S> {
#[inline]
fn from(v: &'a [S; 4]) -> &'a Quaternion<S> {
unsafe { &*(v as *const [S; 4] as *const quaternion::Quaternion<S>) }
}
}
impl<'a, S: BaseFloat> From<&'a mut [S; 4]> for &'a mut Quaternion<S> {
impl<'a, S: BaseNum> From<&'a mut [S; 4]> for &'a mut Quaternion<S> {
#[inline]
fn from(v: &'a mut [S; 4]) -> &'a mut Quaternion<S> {
unsafe { &mut *(v as *mut [S; 4] as *mut quaternion::Quaternion<S>) }
}
}
impl<S: BaseFloat> From<Quaternion<S>> for (S, S, S, S) {
impl<S: BaseNum> From<Quaternion<S>> for (S, S, S, S) {
#[inline]
fn from(v: Quaternion<S>) -> Self {
let Quaternion {
@ -592,21 +587,21 @@ impl<S: BaseFloat> From<Quaternion<S>> for (S, S, S, S) {
}
}
impl<S: BaseFloat> AsRef<(S, S, S, S)> for Quaternion<S> {
impl<S: BaseNum> AsRef<(S, S, S, S)> for Quaternion<S> {
#[inline]
fn as_ref(&self) -> &(S, S, S, S) {
unsafe { &*(self as *const quaternion::Quaternion<S> as *const (S, S, S, S)) }
}
}
impl<S: BaseFloat> AsMut<(S, S, S, S)> for Quaternion<S> {
impl<S: BaseNum> AsMut<(S, S, S, S)> for Quaternion<S> {
#[inline]
fn as_mut(&mut self) -> &mut (S, S, S, S) {
unsafe { &mut *(self as *mut quaternion::Quaternion<S> as *mut (S, S, S, S)) }
}
}
impl<S: BaseFloat> From<(S, S, S, S)> for Quaternion<S> {
impl<S: BaseNum> From<(S, S, S, S)> for Quaternion<S> {
#[inline]
fn from(v: (S, S, S, S)) -> Quaternion<S> {
let (xi, yj, zk, w) = v;
@ -614,14 +609,14 @@ impl<S: BaseFloat> From<(S, S, S, S)> for Quaternion<S> {
}
}
impl<'a, S: BaseFloat> From<&'a (S, S, S, S)> for &'a Quaternion<S> {
impl<'a, S: BaseNum> From<&'a (S, S, S, S)> for &'a Quaternion<S> {
#[inline]
fn from(v: &'a (S, S, S, S)) -> &'a Quaternion<S> {
unsafe { &*(v as *const (S, S, S, S) as *const quaternion::Quaternion<S>) }
}
}
impl<'a, S: BaseFloat> From<&'a mut (S, S, S, S)> for &'a mut Quaternion<S> {
impl<'a, S: BaseNum> From<&'a mut (S, S, S, S)> for &'a mut Quaternion<S> {
#[inline]
fn from(v: &'a mut (S, S, S, S)) -> &'a mut Quaternion<S> {
unsafe { &mut *(v as *mut (S, S, S, S) as *mut quaternion::Quaternion<S>) }
@ -630,7 +625,7 @@ impl<'a, S: BaseFloat> From<&'a mut (S, S, S, S)> for &'a mut Quaternion<S> {
macro_rules! index_operators {
($S:ident, $Output:ty, $I:ty) => {
impl<$S: BaseFloat> Index<$I> for Quaternion<$S> {
impl<$S: BaseNum> Index<$I> for Quaternion<$S> {
type Output = $Output;
#[inline]
@ -640,7 +635,7 @@ macro_rules! index_operators {
}
}
impl<$S: BaseFloat> IndexMut<$I> for Quaternion<$S> {
impl<$S: BaseNum> IndexMut<$I> for Quaternion<$S> {
#[inline]
fn index_mut<'a>(&'a mut self, i: $I) -> &'a mut $Output {
let v: &mut [$S; 4] = self.as_mut();
@ -661,7 +656,7 @@ impl<S> Distribution<Quaternion<S>> for Standard
where
Standard: Distribution<S>,
Standard: Distribution<Vector3<S>>,
S: BaseFloat,
S: BaseNum,
{
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Quaternion<S> {
@ -689,6 +684,14 @@ impl<S: Clone> From<Quaternion<S>> for mint::Quaternion<S> {
}
}
#[cfg(feature = "mint")]
impl<S: Clone> mint::IntoMint for Quaternion<S> {
type MintType = mint::Quaternion<S>;
}
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Quaternion);
#[cfg(test)]
mod tests {
use quaternion::*;

View file

@ -26,7 +26,7 @@ impl From<Simdf32x4> for Quaternion<f32> {
#[inline]
fn from(f: Simdf32x4) -> Self {
unsafe {
let mut ret: Self = mem::uninitialized();
let mut ret: Self = mem::MaybeUninit();
{
let ret_mut: &mut [f32; 4] = ret.as_mut();
f.store(ret_mut.as_mut(), 0 as usize);

View file

@ -23,7 +23,7 @@ use angle::Rad;
use approx;
use euler::Euler;
use matrix::{Matrix2, Matrix3};
use num::BaseFloat;
use num::{BaseFloat, BaseNum};
use point::{Point2, Point3};
use quaternion::Quaternion;
use vector::{Vector2, Vector3};
@ -36,7 +36,7 @@ where
Self: approx::AbsDiffEq<Epsilon = <<Self as Rotation>::Space as EuclideanSpace>::Scalar>,
Self: approx::RelativeEq<Epsilon = <<Self as Rotation>::Space as EuclideanSpace>::Scalar>,
Self: approx::UlpsEq<Epsilon = <<Self as Rotation>::Space as EuclideanSpace>::Scalar>,
<Self::Space as EuclideanSpace>::Scalar: BaseFloat,
<Self::Space as EuclideanSpace>::Scalar: BaseNum,
Self: iter::Product<Self>,
{
type Space: EuclideanSpace;
@ -149,7 +149,7 @@ pub trait Rotation3:
/// let unit_y = rot.rotate_vector(unit_x);
///
/// // Since sin(π/2) may not be exactly zero due to rounding errors, we can
/// // use approx's assert_ulps_eq!() feature to show that it is close enough.
/// // use approx assert_ulps_eq!() feature to show that it is close enough.
/// // assert_ulps_eq!(&unit_y, &Vector2::unit_y()); // TODO: Figure out how to use this
///
/// // This is exactly equivalent to using the raw matrix itself:
@ -319,7 +319,7 @@ impl<S: BaseFloat> Basis3<S> {
#[inline]
pub fn from_quaternion(quaternion: &Quaternion<S>) -> Basis3<S> {
Basis3 {
mat: quaternion.clone().into(),
mat: (*quaternion).into(),
}
}
}

View file

@ -25,7 +25,7 @@ use approx;
use angle::Rad;
use num::{BaseFloat, BaseNum};
pub use num_traits::{Bounded, One, Zero};
pub use num_traits::{Bounded, Num, NumCast, One, Zero};
/// An array containing elements of type `Element`
pub trait Array
@ -388,7 +388,7 @@ where
/// ```
#[inline]
fn midpoint(self, other: Self) -> Self {
self + (other - self) / cast(2).unwrap()
self + (other - self) / (Self::Scalar::one() + Self::Scalar::one())
}
/// Returns the average position of all points in the slice.
@ -406,7 +406,10 @@ where
/// let centroid = Point2::centroid(&triangle);
/// ```
#[inline]
fn centroid(points: &[Self]) -> Self {
fn centroid(points: &[Self]) -> Self
where
Self::Scalar: NumCast,
{
let total_displacement = points
.iter()
.fold(Self::Diff::zero(), |acc, p| acc + p.to_vec());
@ -441,7 +444,7 @@ where
/// see `SquareMatrix`.
pub trait Matrix: VectorSpace
where
Self::Scalar: Float,
Self::Scalar: Num,
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
Self: Index<usize, Output = <Self as Matrix>::Column>,
@ -493,7 +496,7 @@ where
/// A column-major major matrix where the rows and column vectors are of the same dimensions.
pub trait SquareMatrix
where
Self::Scalar: Float,
Self::Scalar: Num,
Self: One,
Self: iter::Product<Self>,
@ -580,10 +583,10 @@ where
fn is_symmetric(&self) -> bool;
}
/// Angles and their associated trigonometric functions.
/// Angles, and their associated trigonometric functions.
///
/// Typed angles allow for the writing of self-documenting code that makes it
/// clear when semantic violations have occured - for example, adding degrees to
/// clear when semantic violations have occurred - for example, adding degrees to
/// radians, or adding a number to an angle.
///
pub trait Angle
@ -609,7 +612,7 @@ where
{
type Unitless: BaseFloat;
/// Return the angle, normalized to the range `[0, full_turn)`.
/// Return the angle, normalized to the range `[0, full_turn]`.
#[inline]
fn normalize(self) -> Self {
let rem = self % Self::full_turn();
@ -620,7 +623,7 @@ where
}
}
/// Return the angle, normalized to the range `[-turn_div_2, turn_div_2)`.
/// Return the angle, normalized to the range `[-turn_div_2, turn_div_2]`.
#[inline]
fn normalize_signed(self) -> Self {
let rem = self.normalize();

View file

@ -123,8 +123,8 @@ where
}
#[inline]
fn look_at_lh(eye: P, center: P, up: P::Diff) -> Decomposed<P::Diff, R> {
let rot = R::look_at(center - eye, up);
fn look_at_rh(eye: P, center: P, up: P::Diff) -> Decomposed<P::Diff, R> {
let rot = R::look_at(eye - center, up);
let disp = rot.rotate_vector(P::origin() - eye);
Decomposed {
scale: P::Scalar::one(),
@ -134,8 +134,8 @@ where
}
#[inline]
fn look_at_rh(eye: P, center: P, up: P::Diff) -> Decomposed<P::Diff, R> {
let rot = R::look_at(eye - center, up);
fn look_at_lh(eye: P, center: P, up: P::Diff) -> Decomposed<P::Diff, R> {
let rot = R::look_at(center - eye, up);
let disp = rot.rotate_vector(P::origin() - eye);
Decomposed {
scale: P::Scalar::one(),
@ -366,7 +366,7 @@ mod serde_de {
where
D: serde::de::Deserializer<'a>,
{
const FIELDS: &'static [&'static str] = &["scale", "rot", "disp"];
const FIELDS: &[&str] = &["scale", "rot", "disp"];
deserializer.deserialize_struct("Decomposed", FIELDS, DecomposedVisitor(PhantomData))
}
}
@ -422,11 +422,7 @@ mod serde_de {
None => return Err(serde::de::Error::missing_field("disp")),
};
Ok(Decomposed {
scale: scale,
rot: rot,
disp: disp,
})
Ok(Decomposed { scale, rot, disp })
}
}
}

View file

@ -96,7 +96,7 @@ macro_rules! impl_vector {
/// Construct a new vector, using the provided values.
#[inline]
pub const fn new($($field: S),+) -> $VectorN<S> {
$VectorN { $($field: $field),+ }
$VectorN { $($field),+ }
}
/// Perform the given operation on each field in the vector, returning a new point
@ -209,7 +209,6 @@ macro_rules! impl_vector {
impl<S: Neg<Output = S>> Neg for $VectorN<S> {
type Output = $VectorN<S>;
#[inline]
default_fn!( neg(self) -> $VectorN<S> { $VectorN::new($(-self.$field),+) } );
}
@ -254,7 +253,7 @@ macro_rules! impl_vector {
#[cfg(feature = "rand")]
impl<S> Distribution<$VectorN<S>> for Standard
where Standard: Distribution<S>,
S: BaseFloat {
S: BaseNum {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $VectorN<S> {
$VectorN { $($field: rng.gen()),+ }
@ -309,30 +308,30 @@ macro_rules! impl_vector {
});
impl<S: BaseNum> ElementWise for $VectorN<S> {
#[inline] default_fn!( add_element_wise(self, rhs: $VectorN<S>) -> $VectorN<S> { $VectorN::new($(self.$field + rhs.$field),+) } );
#[inline] default_fn!( sub_element_wise(self, rhs: $VectorN<S>) -> $VectorN<S> { $VectorN::new($(self.$field - rhs.$field),+) } );
#[inline] default_fn!( mul_element_wise(self, rhs: $VectorN<S>) -> $VectorN<S> { $VectorN::new($(self.$field * rhs.$field),+) } );
#[inline] default_fn!( div_element_wise(self, rhs: $VectorN<S>) -> $VectorN<S> { $VectorN::new($(self.$field / rhs.$field),+) } );
default_fn!( add_element_wise(self, rhs: $VectorN<S>) -> $VectorN<S> { $VectorN::new($(self.$field + rhs.$field),+) } );
default_fn!( sub_element_wise(self, rhs: $VectorN<S>) -> $VectorN<S> { $VectorN::new($(self.$field - rhs.$field),+) } );
default_fn!( mul_element_wise(self, rhs: $VectorN<S>) -> $VectorN<S> { $VectorN::new($(self.$field * rhs.$field),+) } );
default_fn!( div_element_wise(self, rhs: $VectorN<S>) -> $VectorN<S> { $VectorN::new($(self.$field / rhs.$field),+) } );
#[inline] fn rem_element_wise(self, rhs: $VectorN<S>) -> $VectorN<S> { $VectorN::new($(self.$field % rhs.$field),+) }
#[inline] default_fn!( add_assign_element_wise(&mut self, rhs: $VectorN<S>) { $(self.$field += rhs.$field);+ } );
#[inline] default_fn!( sub_assign_element_wise(&mut self, rhs: $VectorN<S>) { $(self.$field -= rhs.$field);+ } );
#[inline] default_fn!( mul_assign_element_wise(&mut self, rhs: $VectorN<S>) { $(self.$field *= rhs.$field);+ } );
#[inline] default_fn!( div_assign_element_wise(&mut self, rhs: $VectorN<S>) { $(self.$field /= rhs.$field);+ } );
default_fn!( add_assign_element_wise(&mut self, rhs: $VectorN<S>) { $(self.$field += rhs.$field);+ } );
default_fn!( sub_assign_element_wise(&mut self, rhs: $VectorN<S>) { $(self.$field -= rhs.$field);+ } );
default_fn!( mul_assign_element_wise(&mut self, rhs: $VectorN<S>) { $(self.$field *= rhs.$field);+ } );
default_fn!( div_assign_element_wise(&mut self, rhs: $VectorN<S>) { $(self.$field /= rhs.$field);+ } );
#[inline] fn rem_assign_element_wise(&mut self, rhs: $VectorN<S>) { $(self.$field %= rhs.$field);+ }
}
impl<S: BaseNum> ElementWise<S> for $VectorN<S> {
#[inline] default_fn!( add_element_wise(self, rhs: S) -> $VectorN<S> { $VectorN::new($(self.$field + rhs),+) } );
#[inline] default_fn!( sub_element_wise(self, rhs: S) -> $VectorN<S> { $VectorN::new($(self.$field - rhs),+) } );
#[inline] default_fn!( mul_element_wise(self, rhs: S) -> $VectorN<S> { $VectorN::new($(self.$field * rhs),+) } );
#[inline] default_fn!( div_element_wise(self, rhs: S) -> $VectorN<S> { $VectorN::new($(self.$field / rhs),+) } );
default_fn!( add_element_wise(self, rhs: S) -> $VectorN<S> { $VectorN::new($(self.$field + rhs),+) } );
default_fn!( sub_element_wise(self, rhs: S) -> $VectorN<S> { $VectorN::new($(self.$field - rhs),+) } );
default_fn!( mul_element_wise(self, rhs: S) -> $VectorN<S> { $VectorN::new($(self.$field * rhs),+) } );
default_fn!( div_element_wise(self, rhs: S) -> $VectorN<S> { $VectorN::new($(self.$field / rhs),+) } );
#[inline] fn rem_element_wise(self, rhs: S) -> $VectorN<S> { $VectorN::new($(self.$field % rhs),+) }
#[inline] default_fn!( add_assign_element_wise(&mut self, rhs: S) { $(self.$field += rhs);+ } );
#[inline] default_fn!( sub_assign_element_wise(&mut self, rhs: S) { $(self.$field -= rhs);+ } );
#[inline] default_fn!( mul_assign_element_wise(&mut self, rhs: S) { $(self.$field *= rhs);+ } );
#[inline] default_fn!( div_assign_element_wise(&mut self, rhs: S) { $(self.$field /= rhs);+ } );
default_fn!( add_assign_element_wise(&mut self, rhs: S) { $(self.$field += rhs);+ } );
default_fn!( sub_assign_element_wise(&mut self, rhs: S) { $(self.$field -= rhs);+ } );
default_fn!( mul_assign_element_wise(&mut self, rhs: S) { $(self.$field *= rhs);+ } );
default_fn!( div_assign_element_wise(&mut self, rhs: S) { $(self.$field /= rhs);+ } );
#[inline] fn rem_assign_element_wise(&mut self, rhs: S) { $(self.$field %= rhs);+ }
}
@ -520,7 +519,7 @@ impl<S: BaseNum> Vector4<S> {
#[inline]
pub fn dot<V: InnerSpace>(a: V, b: V) -> V::Scalar
where
V::Scalar: BaseFloat,
V::Scalar: BaseNum,
{
V::dot(a, b)
}
@ -597,6 +596,18 @@ impl<S: fmt::Debug> fmt::Debug for Vector4<S> {
}
}
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Vector1);
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Vector2);
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Vector3);
#[cfg(feature = "bytemuck")]
impl_bytemuck_cast!(Vector4);
#[cfg(feature = "mint")]
impl_mint_conversions!(Vector2 { x, y }, Vector2);
#[cfg(feature = "mint")]
@ -620,7 +631,7 @@ mod tests {
#[test]
fn test_index_mut() {
let mut v = VECTOR2;
*&mut v[0] = 0;
v[0] = 0;
assert_eq!(v, [0, 2].into());
}
@ -741,7 +752,7 @@ mod tests {
#[test]
fn test_index_mut() {
let mut v = VECTOR3;
*&mut v[1] = 0;
v[1] = 0;
assert_eq!(v, [1, 0, 3].into());
}
@ -868,7 +879,7 @@ mod tests {
#[test]
fn test_index_mut() {
let mut v = VECTOR4;
*&mut v[2] = 0;
v[2] = 0;
assert_eq!(v, [1, 2, 0, 4].into());
}

View file

@ -28,7 +28,7 @@ impl From<Simdf32x4> for Vector4<f32> {
#[inline]
fn from(f: Simdf32x4) -> Self {
unsafe {
let mut ret: Self = mem::uninitialized();
let mut ret: Self = mem::MaybeUninit();
{
let ret_mut: &mut [f32; 4] = ret.as_mut();
f.store(ret_mut.as_mut(), 0 as usize);
@ -244,7 +244,7 @@ impl From<Simdi32x4> for Vector4<i32> {
#[inline]
fn from(f: Simdi32x4) -> Self {
unsafe {
let mut ret: Self = mem::uninitialized();
let mut ret: Self = mem::MaybeUninit();
{
let ret_mut: &mut [i32; 4] = ret.as_mut();
f.store(ret_mut.as_mut(), 0 as usize);
@ -324,7 +324,7 @@ impl From<Simdu32x4> for Vector4<u32> {
#[inline]
fn from(f: Simdu32x4) -> Self {
unsafe {
let mut ret: Self = mem::uninitialized();
let mut ret: Self = mem::MaybeUninit();
{
let ret_mut: &mut [u32; 4] = ret.as_mut();
f.store(ret_mut.as_mut(), 0 as usize);

View file

@ -220,7 +220,7 @@ mod from {
use cgmath::*;
fn check_with_euler(x: Rad<f32>, y: Rad<f32>, z: Rad<f32>) {
let matrix3 = Matrix3::from(Euler { x: x, y: y, z: z });
let matrix3 = Matrix3::from(Euler { x, y, z });
let quaternion = Quaternion::from(matrix3);
let quaternion_matrix3 = Matrix3::from(quaternion);
assert_ulps_eq!(matrix3, quaternion_matrix3);
@ -265,7 +265,7 @@ mod arc {
#[test]
fn test_same() {
let v = Vector3::unit_x();
let q = Quaternion::from_arc(v, v, None);
let q = Quaternion::from_arc(v.clone(), v, None);
assert_eq!(q, Quaternion::new(1.0, 0.0, 0.0, 0.0));
}

View file

@ -122,7 +122,7 @@ fn test_look_at_lh() {
assert_ulps_eq!(t, Matrix4::<f64>::look_at_lh(eye, center, up));
assert_ulps_eq!(&t.transform_point(point), &view_point);
// Decomposed::look_at is inconsistent and deprecated, but verify that the behvaior
// Decomposed::look_at is inconsistent and deprecated, but verify that the behavior
// remains the same until removed.
#[allow(deprecated)]
let t: Decomposed<Vector3<f64>, Quaternion<f64>> = Transform::look_at(eye, center, up);