Merge branch 'main' into schema-types-metadata
This commit is contained in:
commit
27f36dc425
@ -32,7 +32,7 @@ fn segment_ease(c: &mut Criterion) {
|
||||
|
||||
fn curve_position(c: &mut Criterion) {
|
||||
/// A helper function that benchmarks calling [`CubicCurve::position()`] over a generic [`VectorSpace`].
|
||||
fn bench_curve<M: Measurement, P: VectorSpace>(
|
||||
fn bench_curve<M: Measurement, P: VectorSpace<Scalar = f32>>(
|
||||
group: &mut BenchmarkGroup<M>,
|
||||
name: &str,
|
||||
curve: CubicCurve<P>,
|
||||
|
@ -55,7 +55,7 @@ pub struct CubicKeyframeCurve<T> {
|
||||
|
||||
impl<V> Curve<V> for CubicKeyframeCurve<V>
|
||||
where
|
||||
V: VectorSpace,
|
||||
V: VectorSpace<Scalar = f32>,
|
||||
{
|
||||
#[inline]
|
||||
fn domain(&self) -> Interval {
|
||||
@ -179,7 +179,7 @@ pub struct WideLinearKeyframeCurve<T> {
|
||||
|
||||
impl<T> IterableCurve<T> for WideLinearKeyframeCurve<T>
|
||||
where
|
||||
T: VectorSpace,
|
||||
T: VectorSpace<Scalar = f32>,
|
||||
{
|
||||
#[inline]
|
||||
fn domain(&self) -> Interval {
|
||||
@ -289,7 +289,7 @@ pub struct WideCubicKeyframeCurve<T> {
|
||||
|
||||
impl<T> IterableCurve<T> for WideCubicKeyframeCurve<T>
|
||||
where
|
||||
T: VectorSpace,
|
||||
T: VectorSpace<Scalar = f32>,
|
||||
{
|
||||
#[inline]
|
||||
fn domain(&self) -> Interval {
|
||||
@ -406,7 +406,7 @@ fn cubic_spline_interpolation<T>(
|
||||
step_duration: f32,
|
||||
) -> T
|
||||
where
|
||||
T: VectorSpace,
|
||||
T: VectorSpace<Scalar = f32>,
|
||||
{
|
||||
let coeffs = (vec4(2.0, 1.0, -2.0, 1.0) * lerp + vec4(-3.0, -2.0, 3.0, -1.0)) * lerp;
|
||||
value_start * (coeffs.x * lerp + 1.0)
|
||||
@ -415,7 +415,7 @@ where
|
||||
+ tangent_in_end * step_duration * lerp * coeffs.w
|
||||
}
|
||||
|
||||
fn cubic_spline_interpolate_slices<'a, T: VectorSpace>(
|
||||
fn cubic_spline_interpolate_slices<'a, T: VectorSpace<Scalar = f32>>(
|
||||
width: usize,
|
||||
first: &'a [T],
|
||||
second: &'a [T],
|
||||
|
@ -262,6 +262,7 @@ macro_rules! impl_componentwise_vector_space {
|
||||
}
|
||||
|
||||
impl bevy_math::VectorSpace for $ty {
|
||||
type Scalar = f32;
|
||||
const ZERO: Self = Self {
|
||||
$($element: 0.0,)+
|
||||
};
|
||||
|
@ -358,7 +358,10 @@ mod tests {
|
||||
// Next allocated entity should be a further generation on the same index
|
||||
let entity = world.spawn_empty().id();
|
||||
assert_eq!(entity.index(), dead_ref.index());
|
||||
assert!(entity.generation() > dead_ref.generation());
|
||||
assert!(entity
|
||||
.generation()
|
||||
.cmp_approx(&dead_ref.generation())
|
||||
.is_gt());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -373,7 +376,10 @@ mod tests {
|
||||
// Next allocated entity should be a further generation on the same index
|
||||
let entity = world.spawn_empty().id();
|
||||
assert_eq!(entity.index(), dead_ref.index());
|
||||
assert!(entity.generation() > dead_ref.generation());
|
||||
assert!(entity
|
||||
.generation()
|
||||
.cmp_approx(&dead_ref.generation())
|
||||
.is_gt());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -185,29 +185,6 @@ impl SparseSetIndex for EntityRow {
|
||||
///
|
||||
/// This should be treated as a opaque identifier, and its internal representation may be subject to change.
|
||||
///
|
||||
/// # Ordering
|
||||
///
|
||||
/// [`EntityGeneration`] implements [`Ord`].
|
||||
/// Generations that are later will be [`Greater`](core::cmp::Ordering::Greater) than earlier ones.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::entity::EntityGeneration;
|
||||
/// assert!(EntityGeneration::FIRST < EntityGeneration::FIRST.after_versions(400));
|
||||
/// let (aliased, did_alias) = EntityGeneration::FIRST.after_versions(400).after_versions_and_could_alias(u32::MAX);
|
||||
/// assert!(did_alias);
|
||||
/// assert!(EntityGeneration::FIRST < aliased);
|
||||
/// ```
|
||||
///
|
||||
/// Ordering will be incorrect for distant generations:
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::entity::EntityGeneration;
|
||||
/// // This ordering is wrong!
|
||||
/// assert!(EntityGeneration::FIRST > EntityGeneration::FIRST.after_versions(400 + (1u32 << 31)));
|
||||
/// ```
|
||||
///
|
||||
/// This strange behavior needed to account for aliasing.
|
||||
///
|
||||
/// # Aliasing
|
||||
///
|
||||
/// Internally [`EntityGeneration`] wraps a `u32`, so it can't represent *every* possible generation.
|
||||
@ -235,6 +212,9 @@ impl EntityGeneration {
|
||||
/// Represents the first generation of an [`EntityRow`].
|
||||
pub const FIRST: Self = Self(0);
|
||||
|
||||
/// Non-wrapping difference between two generations after which a signed interpretation becomes negative.
|
||||
const DIFF_MAX: u32 = 1u32 << 31;
|
||||
|
||||
/// Gets some bits that represent this value.
|
||||
/// The bits are opaque and should not be regarded as meaningful.
|
||||
#[inline(always)]
|
||||
@ -266,18 +246,48 @@ impl EntityGeneration {
|
||||
let raw = self.0.overflowing_add(versions);
|
||||
(Self(raw.0), raw.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for EntityGeneration {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for EntityGeneration {
|
||||
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
||||
let diff = self.0.wrapping_sub(other.0);
|
||||
(1u32 << 31).cmp(&diff)
|
||||
/// Compares two generations.
|
||||
///
|
||||
/// Generations that are later will be [`Greater`](core::cmp::Ordering::Greater) than earlier ones.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::entity::EntityGeneration;
|
||||
/// # use core::cmp::Ordering;
|
||||
/// let later_generation = EntityGeneration::FIRST.after_versions(400);
|
||||
/// assert_eq!(EntityGeneration::FIRST.cmp_approx(&later_generation), Ordering::Less);
|
||||
///
|
||||
/// let (aliased, did_alias) = EntityGeneration::FIRST.after_versions(400).after_versions_and_could_alias(u32::MAX);
|
||||
/// assert!(did_alias);
|
||||
/// assert_eq!(EntityGeneration::FIRST.cmp_approx(&aliased), Ordering::Less);
|
||||
/// ```
|
||||
///
|
||||
/// Ordering will be incorrect and [non-transitive](https://en.wikipedia.org/wiki/Transitive_relation)
|
||||
/// for distant generations:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use bevy_ecs::entity::EntityGeneration;
|
||||
/// # use core::cmp::Ordering;
|
||||
/// let later_generation = EntityGeneration::FIRST.after_versions(3u32 << 31);
|
||||
/// let much_later_generation = later_generation.after_versions(3u32 << 31);
|
||||
///
|
||||
/// // while these orderings are correct and pass assertions...
|
||||
/// assert_eq!(EntityGeneration::FIRST.cmp_approx(&later_generation), Ordering::Less);
|
||||
/// assert_eq!(later_generation.cmp_approx(&much_later_generation), Ordering::Less);
|
||||
///
|
||||
/// // ... this ordering is not and the assertion fails!
|
||||
/// assert_eq!(EntityGeneration::FIRST.cmp_approx(&much_later_generation), Ordering::Less);
|
||||
/// ```
|
||||
///
|
||||
/// Because of this, `EntityGeneration` does not implement `Ord`/`PartialOrd`.
|
||||
#[inline]
|
||||
pub const fn cmp_approx(&self, other: &Self) -> core::cmp::Ordering {
|
||||
use core::cmp::Ordering;
|
||||
match self.0.wrapping_sub(other.0) {
|
||||
0 => Ordering::Equal,
|
||||
1..Self::DIFF_MAX => Ordering::Greater,
|
||||
_ => Ordering::Less,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1422,7 +1432,10 @@ mod tests {
|
||||
// The very next entity allocated should be a further generation on the same index
|
||||
let next_entity = entities.alloc();
|
||||
assert_eq!(next_entity.index(), entity.index());
|
||||
assert!(next_entity.generation() > entity.generation().after_versions(GENERATIONS));
|
||||
assert!(next_entity
|
||||
.generation()
|
||||
.cmp_approx(&entity.generation().after_versions(GENERATIONS))
|
||||
.is_gt());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1609,6 +1622,24 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn entity_generation_is_approximately_ordered() {
|
||||
use core::cmp::Ordering;
|
||||
|
||||
let old = EntityGeneration::FIRST;
|
||||
let middle = old.after_versions(1);
|
||||
let younger_before_ord_wrap = middle.after_versions(EntityGeneration::DIFF_MAX);
|
||||
let younger_after_ord_wrap = younger_before_ord_wrap.after_versions(1);
|
||||
|
||||
assert_eq!(middle.cmp_approx(&old), Ordering::Greater);
|
||||
assert_eq!(middle.cmp_approx(&middle), Ordering::Equal);
|
||||
assert_eq!(middle.cmp_approx(&younger_before_ord_wrap), Ordering::Less);
|
||||
assert_eq!(
|
||||
middle.cmp_approx(&younger_after_ord_wrap),
|
||||
Ordering::Greater
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn entity_debug() {
|
||||
let entity = Entity::from_raw(EntityRow::new(NonMaxU32::new(42).unwrap()));
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! This module contains abstract mathematical traits shared by types used in `bevy_math`.
|
||||
|
||||
use crate::{ops, Dir2, Dir3, Dir3A, Quat, Rot2, Vec2, Vec3, Vec3A, Vec4};
|
||||
use crate::{ops, DVec2, DVec3, DVec4, Dir2, Dir3, Dir3A, Quat, Rot2, Vec2, Vec3, Vec3A, Vec4};
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
ops::{Add, Div, Mul, Neg, Sub},
|
||||
@ -9,7 +9,7 @@ use variadics_please::all_tuples_enumerated;
|
||||
|
||||
/// A type that supports the mathematical operations of a real vector space, irrespective of dimension.
|
||||
/// In particular, this means that the implementing type supports:
|
||||
/// - Scalar multiplication and division on the right by elements of `f32`
|
||||
/// - Scalar multiplication and division on the right by elements of `Self::Scalar`
|
||||
/// - Negation
|
||||
/// - Addition and subtraction
|
||||
/// - Zero
|
||||
@ -19,16 +19,16 @@ use variadics_please::all_tuples_enumerated;
|
||||
/// - (Commutativity of addition) For all `u, v: Self`, `u + v == v + u`.
|
||||
/// - (Additive identity) For all `v: Self`, `v + Self::ZERO == v`.
|
||||
/// - (Additive inverse) For all `v: Self`, `v - v == v + (-v) == Self::ZERO`.
|
||||
/// - (Compatibility of multiplication) For all `a, b: f32`, `v: Self`, `v * (a * b) == (v * a) * b`.
|
||||
/// - (Compatibility of multiplication) For all `a, b: Self::Scalar`, `v: Self`, `v * (a * b) == (v * a) * b`.
|
||||
/// - (Multiplicative identity) For all `v: Self`, `v * 1.0 == v`.
|
||||
/// - (Distributivity for vector addition) For all `a: f32`, `u, v: Self`, `(u + v) * a == u * a + v * a`.
|
||||
/// - (Distributivity for scalar addition) For all `a, b: f32`, `v: Self`, `v * (a + b) == v * a + v * b`.
|
||||
/// - (Distributivity for vector addition) For all `a: Self::Scalar`, `u, v: Self`, `(u + v) * a == u * a + v * a`.
|
||||
/// - (Distributivity for scalar addition) For all `a, b: Self::Scalar`, `v: Self`, `v * (a + b) == v * a + v * b`.
|
||||
///
|
||||
/// Note that, because implementing types use floating point arithmetic, they are not required to actually
|
||||
/// implement `PartialEq` or `Eq`.
|
||||
pub trait VectorSpace:
|
||||
Mul<f32, Output = Self>
|
||||
+ Div<f32, Output = Self>
|
||||
Mul<Self::Scalar, Output = Self>
|
||||
+ Div<Self::Scalar, Output = Self>
|
||||
+ Add<Self, Output = Self>
|
||||
+ Sub<Self, Output = Self>
|
||||
+ Neg<Output = Self>
|
||||
@ -37,6 +37,9 @@ pub trait VectorSpace:
|
||||
+ Clone
|
||||
+ Copy
|
||||
{
|
||||
/// The scalar type of this vector space.
|
||||
type Scalar: ScalarField;
|
||||
|
||||
/// The zero vector, which is the identity of addition for the vector space type.
|
||||
const ZERO: Self;
|
||||
|
||||
@ -47,29 +50,99 @@ pub trait VectorSpace:
|
||||
/// Note that the value of `t` is not clamped by this function, so extrapolating outside
|
||||
/// of the interval `[0,1]` is allowed.
|
||||
#[inline]
|
||||
fn lerp(self, rhs: Self, t: f32) -> Self {
|
||||
self * (1. - t) + rhs * t
|
||||
fn lerp(self, rhs: Self, t: Self::Scalar) -> Self {
|
||||
self * (Self::Scalar::ONE - t) + rhs * t
|
||||
}
|
||||
}
|
||||
|
||||
impl VectorSpace for Vec4 {
|
||||
type Scalar = f32;
|
||||
const ZERO: Self = Vec4::ZERO;
|
||||
}
|
||||
|
||||
impl VectorSpace for Vec3 {
|
||||
type Scalar = f32;
|
||||
const ZERO: Self = Vec3::ZERO;
|
||||
}
|
||||
|
||||
impl VectorSpace for Vec3A {
|
||||
type Scalar = f32;
|
||||
const ZERO: Self = Vec3A::ZERO;
|
||||
}
|
||||
|
||||
impl VectorSpace for Vec2 {
|
||||
type Scalar = f32;
|
||||
const ZERO: Self = Vec2::ZERO;
|
||||
}
|
||||
|
||||
impl VectorSpace for f32 {
|
||||
impl VectorSpace for DVec4 {
|
||||
type Scalar = f64;
|
||||
const ZERO: Self = DVec4::ZERO;
|
||||
}
|
||||
|
||||
impl VectorSpace for DVec3 {
|
||||
type Scalar = f64;
|
||||
const ZERO: Self = DVec3::ZERO;
|
||||
}
|
||||
|
||||
impl VectorSpace for DVec2 {
|
||||
type Scalar = f64;
|
||||
const ZERO: Self = DVec2::ZERO;
|
||||
}
|
||||
|
||||
// Every scalar field is a 1-dimensional vector space over itself.
|
||||
impl<T: ScalarField> VectorSpace for T {
|
||||
type Scalar = Self;
|
||||
const ZERO: Self = Self::ZERO;
|
||||
}
|
||||
|
||||
/// A type that supports the operations of a scalar field. An implementation should support:
|
||||
/// - Addition and subtraction
|
||||
/// - Multiplication and division
|
||||
/// - Negation
|
||||
/// - Zero (additive identity)
|
||||
/// - One (multiplicative identity)
|
||||
///
|
||||
/// Within the limitations of floating point arithmetic, all the following are required to hold:
|
||||
/// - (Associativity of addition) For all `u, v, w: Self`, `(u + v) + w == u + (v + w)`.
|
||||
/// - (Commutativity of addition) For all `u, v: Self`, `u + v == v + u`.
|
||||
/// - (Additive identity) For all `v: Self`, `v + Self::ZERO == v`.
|
||||
/// - (Additive inverse) For all `v: Self`, `v - v == v + (-v) == Self::ZERO`.
|
||||
/// - (Associativity of multiplication) For all `u, v, w: Self`, `(u * v) * w == u * (v * w)`.
|
||||
/// - (Commutativity of multiplication) For all `u, v: Self`, `u * v == v * u`.
|
||||
/// - (Multiplicative identity) For all `v: Self`, `v * Self::ONE == v`.
|
||||
/// - (Multiplicative inverse) For all `v: Self`, `v / v == v * v.inverse() == Self::ONE`.
|
||||
/// - (Distributivity over addition) For all `a, b: Self`, `u, v: Self`, `(u + v) * a == u * a + v * a`.
|
||||
pub trait ScalarField:
|
||||
Mul<Self, Output = Self>
|
||||
+ Div<Self, Output = Self>
|
||||
+ Add<Self, Output = Self>
|
||||
+ Sub<Self, Output = Self>
|
||||
+ Neg<Output = Self>
|
||||
+ Default
|
||||
+ Debug
|
||||
+ Clone
|
||||
+ Copy
|
||||
{
|
||||
/// The additive identity.
|
||||
const ZERO: Self;
|
||||
/// The multiplicative identity.
|
||||
const ONE: Self;
|
||||
|
||||
/// The multiplicative inverse of this element. This is equivalent to `1.0 / self`.
|
||||
fn recip(self) -> Self {
|
||||
Self::ONE / self
|
||||
}
|
||||
}
|
||||
|
||||
impl ScalarField for f32 {
|
||||
const ZERO: Self = 0.0;
|
||||
const ONE: Self = 1.0;
|
||||
}
|
||||
|
||||
impl ScalarField for f64 {
|
||||
const ZERO: Self = 0.0;
|
||||
const ONE: Self = 1.0;
|
||||
}
|
||||
|
||||
/// A type consisting of formal sums of elements from `V` and `W`. That is,
|
||||
@ -84,24 +157,24 @@ impl VectorSpace for f32 {
|
||||
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
|
||||
pub struct Sum<V, W>(pub V, pub W);
|
||||
|
||||
impl<V, W> Mul<f32> for Sum<V, W>
|
||||
impl<F: ScalarField, V, W> Mul<F> for Sum<V, W>
|
||||
where
|
||||
V: VectorSpace,
|
||||
W: VectorSpace,
|
||||
V: VectorSpace<Scalar = F>,
|
||||
W: VectorSpace<Scalar = F>,
|
||||
{
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
fn mul(self, rhs: F) -> Self::Output {
|
||||
Sum(self.0 * rhs, self.1 * rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, W> Div<f32> for Sum<V, W>
|
||||
impl<F: ScalarField, V, W> Div<F> for Sum<V, W>
|
||||
where
|
||||
V: VectorSpace,
|
||||
W: VectorSpace,
|
||||
V: VectorSpace<Scalar = F>,
|
||||
W: VectorSpace<Scalar = F>,
|
||||
{
|
||||
type Output = Self;
|
||||
fn div(self, rhs: f32) -> Self::Output {
|
||||
fn div(self, rhs: F) -> Self::Output {
|
||||
Sum(self.0 / rhs, self.1 / rhs)
|
||||
}
|
||||
}
|
||||
@ -149,11 +222,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, W> VectorSpace for Sum<V, W>
|
||||
impl<F: ScalarField, V, W> VectorSpace for Sum<V, W>
|
||||
where
|
||||
V: VectorSpace,
|
||||
W: VectorSpace,
|
||||
V: VectorSpace<Scalar = F>,
|
||||
W: VectorSpace<Scalar = F>,
|
||||
{
|
||||
type Scalar = F;
|
||||
const ZERO: Self = Sum(V::ZERO, W::ZERO);
|
||||
}
|
||||
|
||||
@ -162,32 +236,32 @@ where
|
||||
/// relationships hold, within the limitations of floating point arithmetic:
|
||||
/// - (Nonnegativity) For all `v: Self`, `v.norm() >= 0.0`.
|
||||
/// - (Positive definiteness) For all `v: Self`, `v.norm() == 0.0` implies `v == Self::ZERO`.
|
||||
/// - (Absolute homogeneity) For all `c: f32`, `v: Self`, `(v * c).norm() == v.norm() * c.abs()`.
|
||||
/// - (Absolute homogeneity) For all `c: Self::Scalar`, `v: Self`, `(v * c).norm() == v.norm() * c.abs()`.
|
||||
/// - (Triangle inequality) For all `v, w: Self`, `(v + w).norm() <= v.norm() + w.norm()`.
|
||||
///
|
||||
/// Note that, because implementing types use floating point arithmetic, they are not required to actually
|
||||
/// implement `PartialEq` or `Eq`.
|
||||
pub trait NormedVectorSpace: VectorSpace {
|
||||
/// The size of this element. The return value should always be nonnegative.
|
||||
fn norm(self) -> f32;
|
||||
fn norm(self) -> Self::Scalar;
|
||||
|
||||
/// The squared norm of this element. Computing this is often faster than computing
|
||||
/// [`NormedVectorSpace::norm`].
|
||||
#[inline]
|
||||
fn norm_squared(self) -> f32 {
|
||||
fn norm_squared(self) -> Self::Scalar {
|
||||
self.norm() * self.norm()
|
||||
}
|
||||
|
||||
/// The distance between this element and another, as determined by the norm.
|
||||
#[inline]
|
||||
fn distance(self, rhs: Self) -> f32 {
|
||||
fn distance(self, rhs: Self) -> Self::Scalar {
|
||||
(rhs - self).norm()
|
||||
}
|
||||
|
||||
/// The squared distance between this element and another, as determined by the norm. Note that
|
||||
/// this is often faster to compute in practice than [`NormedVectorSpace::distance`].
|
||||
#[inline]
|
||||
fn distance_squared(self, rhs: Self) -> f32 {
|
||||
fn distance_squared(self, rhs: Self) -> Self::Scalar {
|
||||
(rhs - self).norm_squared()
|
||||
}
|
||||
}
|
||||
@ -245,10 +319,55 @@ impl NormedVectorSpace for f32 {
|
||||
fn norm(self) -> f32 {
|
||||
ops::abs(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl NormedVectorSpace for DVec4 {
|
||||
#[inline]
|
||||
fn norm(self) -> f64 {
|
||||
self.length()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn norm_squared(self) -> f32 {
|
||||
self * self
|
||||
fn norm_squared(self) -> f64 {
|
||||
self.length_squared()
|
||||
}
|
||||
}
|
||||
|
||||
impl NormedVectorSpace for DVec3 {
|
||||
#[inline]
|
||||
fn norm(self) -> f64 {
|
||||
self.length()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn norm_squared(self) -> f64 {
|
||||
self.length_squared()
|
||||
}
|
||||
}
|
||||
|
||||
impl NormedVectorSpace for DVec2 {
|
||||
#[inline]
|
||||
fn norm(self) -> f64 {
|
||||
self.length()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn norm_squared(self) -> f64 {
|
||||
self.length_squared()
|
||||
}
|
||||
}
|
||||
|
||||
impl NormedVectorSpace for f64 {
|
||||
#[inline]
|
||||
#[cfg(feature = "std")]
|
||||
fn norm(self) -> f64 {
|
||||
f64::abs(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(all(any(feature = "libm", feature = "nostd-libm"), not(feature = "std")))]
|
||||
fn norm(self) -> f64 {
|
||||
libm::fabs(self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,7 +472,7 @@ pub trait StableInterpolate: Clone {
|
||||
// VectorSpace type, but the "natural from the semantics" part is less clear in general.
|
||||
impl<V> StableInterpolate for V
|
||||
where
|
||||
V: NormedVectorSpace,
|
||||
V: NormedVectorSpace<Scalar = f32>,
|
||||
{
|
||||
#[inline]
|
||||
fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
|
||||
@ -462,10 +581,13 @@ impl<V: VectorSpace> HasTangent for V {
|
||||
type Tangent = V;
|
||||
}
|
||||
|
||||
impl<M, N> HasTangent for (M, N)
|
||||
impl<F, U, V, M, N> HasTangent for (M, N)
|
||||
where
|
||||
M: HasTangent,
|
||||
N: HasTangent,
|
||||
F: ScalarField,
|
||||
U: VectorSpace<Scalar = F>,
|
||||
V: VectorSpace<Scalar = F>,
|
||||
M: HasTangent<Tangent = U>,
|
||||
N: HasTangent<Tangent = V>,
|
||||
{
|
||||
type Tangent = Sum<M::Tangent, N::Tangent>;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use super::{CubicCurve, RationalCurve};
|
||||
|
||||
// -- CubicSegment
|
||||
|
||||
impl<P: VectorSpace> Curve<P> for CubicSegment<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> Curve<P> for CubicSegment<P> {
|
||||
#[inline]
|
||||
fn domain(&self) -> Interval {
|
||||
Interval::UNIT
|
||||
@ -22,7 +22,7 @@ impl<P: VectorSpace> Curve<P> for CubicSegment<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: VectorSpace> SampleDerivative<P> for CubicSegment<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> SampleDerivative<P> for CubicSegment<P> {
|
||||
#[inline]
|
||||
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<P> {
|
||||
WithDerivative {
|
||||
@ -32,7 +32,7 @@ impl<P: VectorSpace> SampleDerivative<P> for CubicSegment<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: VectorSpace> SampleTwoDerivatives<P> for CubicSegment<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> SampleTwoDerivatives<P> for CubicSegment<P> {
|
||||
#[inline]
|
||||
fn sample_with_two_derivatives_unchecked(&self, t: f32) -> WithTwoDerivatives<P> {
|
||||
WithTwoDerivatives {
|
||||
@ -46,7 +46,7 @@ impl<P: VectorSpace> SampleTwoDerivatives<P> for CubicSegment<P> {
|
||||
// -- CubicCurve
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> Curve<P> for CubicCurve<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> Curve<P> for CubicCurve<P> {
|
||||
#[inline]
|
||||
fn domain(&self) -> Interval {
|
||||
// The non-emptiness invariant guarantees that this succeeds.
|
||||
@ -61,7 +61,7 @@ impl<P: VectorSpace> Curve<P> for CubicCurve<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> SampleDerivative<P> for CubicCurve<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> SampleDerivative<P> for CubicCurve<P> {
|
||||
#[inline]
|
||||
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<P> {
|
||||
WithDerivative {
|
||||
@ -72,7 +72,7 @@ impl<P: VectorSpace> SampleDerivative<P> for CubicCurve<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> SampleTwoDerivatives<P> for CubicCurve<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> SampleTwoDerivatives<P> for CubicCurve<P> {
|
||||
#[inline]
|
||||
fn sample_with_two_derivatives_unchecked(&self, t: f32) -> WithTwoDerivatives<P> {
|
||||
WithTwoDerivatives {
|
||||
@ -85,7 +85,7 @@ impl<P: VectorSpace> SampleTwoDerivatives<P> for CubicCurve<P> {
|
||||
|
||||
// -- RationalSegment
|
||||
|
||||
impl<P: VectorSpace> Curve<P> for RationalSegment<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> Curve<P> for RationalSegment<P> {
|
||||
#[inline]
|
||||
fn domain(&self) -> Interval {
|
||||
Interval::UNIT
|
||||
@ -97,7 +97,7 @@ impl<P: VectorSpace> Curve<P> for RationalSegment<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: VectorSpace> SampleDerivative<P> for RationalSegment<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> SampleDerivative<P> for RationalSegment<P> {
|
||||
#[inline]
|
||||
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<P> {
|
||||
WithDerivative {
|
||||
@ -107,7 +107,7 @@ impl<P: VectorSpace> SampleDerivative<P> for RationalSegment<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: VectorSpace> SampleTwoDerivatives<P> for RationalSegment<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> SampleTwoDerivatives<P> for RationalSegment<P> {
|
||||
#[inline]
|
||||
fn sample_with_two_derivatives_unchecked(&self, t: f32) -> WithTwoDerivatives<P> {
|
||||
WithTwoDerivatives {
|
||||
@ -121,7 +121,7 @@ impl<P: VectorSpace> SampleTwoDerivatives<P> for RationalSegment<P> {
|
||||
// -- RationalCurve
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> Curve<P> for RationalCurve<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> Curve<P> for RationalCurve<P> {
|
||||
#[inline]
|
||||
fn domain(&self) -> Interval {
|
||||
// The non-emptiness invariant guarantees the success of this.
|
||||
@ -136,7 +136,7 @@ impl<P: VectorSpace> Curve<P> for RationalCurve<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> SampleDerivative<P> for RationalCurve<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> SampleDerivative<P> for RationalCurve<P> {
|
||||
#[inline]
|
||||
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<P> {
|
||||
WithDerivative {
|
||||
@ -147,7 +147,7 @@ impl<P: VectorSpace> SampleDerivative<P> for RationalCurve<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> SampleTwoDerivatives<P> for RationalCurve<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> SampleTwoDerivatives<P> for RationalCurve<P> {
|
||||
#[inline]
|
||||
fn sample_with_two_derivatives_unchecked(&self, t: f32) -> WithTwoDerivatives<P> {
|
||||
WithTwoDerivatives {
|
||||
|
@ -68,7 +68,7 @@ impl<P: VectorSpace> CubicBezier<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> CubicGenerator<P> for CubicBezier<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CubicGenerator<P> for CubicBezier<P> {
|
||||
type Error = CubicBezierError;
|
||||
|
||||
#[inline]
|
||||
@ -176,7 +176,7 @@ impl<P: VectorSpace> CubicHermite<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> CubicGenerator<P> for CubicHermite<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CubicGenerator<P> for CubicHermite<P> {
|
||||
type Error = InsufficientDataError;
|
||||
|
||||
#[inline]
|
||||
@ -202,7 +202,7 @@ impl<P: VectorSpace> CubicGenerator<P> for CubicHermite<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> CyclicCubicGenerator<P> for CubicHermite<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CyclicCubicGenerator<P> for CubicHermite<P> {
|
||||
type Error = InsufficientDataError;
|
||||
|
||||
#[inline]
|
||||
@ -313,7 +313,7 @@ impl<P: VectorSpace> CubicCardinalSpline<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> CubicGenerator<P> for CubicCardinalSpline<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CubicGenerator<P> for CubicCardinalSpline<P> {
|
||||
type Error = InsufficientDataError;
|
||||
|
||||
#[inline]
|
||||
@ -351,7 +351,7 @@ impl<P: VectorSpace> CubicGenerator<P> for CubicCardinalSpline<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> CyclicCubicGenerator<P> for CubicCardinalSpline<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CyclicCubicGenerator<P> for CubicCardinalSpline<P> {
|
||||
type Error = InsufficientDataError;
|
||||
|
||||
#[inline]
|
||||
@ -471,7 +471,7 @@ impl<P: VectorSpace> CubicBSpline<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> CubicGenerator<P> for CubicBSpline<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CubicGenerator<P> for CubicBSpline<P> {
|
||||
type Error = InsufficientDataError;
|
||||
|
||||
#[inline]
|
||||
@ -494,7 +494,7 @@ impl<P: VectorSpace> CubicGenerator<P> for CubicBSpline<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> CyclicCubicGenerator<P> for CubicBSpline<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CyclicCubicGenerator<P> for CubicBSpline<P> {
|
||||
type Error = InsufficientDataError;
|
||||
|
||||
#[inline]
|
||||
@ -620,7 +620,7 @@ pub struct CubicNurbs<P: VectorSpace> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> CubicNurbs<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CubicNurbs<P> {
|
||||
/// Build a Non-Uniform Rational B-Spline.
|
||||
///
|
||||
/// If provided, weights must be the same length as the control points. Defaults to equal weights.
|
||||
@ -781,7 +781,7 @@ impl<P: VectorSpace> CubicNurbs<P> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> RationalGenerator<P> for CubicNurbs<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> RationalGenerator<P> for CubicNurbs<P> {
|
||||
type Error = InsufficientDataError;
|
||||
|
||||
#[inline]
|
||||
@ -962,7 +962,7 @@ pub struct CubicSegment<P: VectorSpace> {
|
||||
pub coeff: [P; 4],
|
||||
}
|
||||
|
||||
impl<P: VectorSpace> CubicSegment<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CubicSegment<P> {
|
||||
/// Instantaneous position of a point at parametric value `t`.
|
||||
#[inline]
|
||||
pub fn position(&self, t: f32) -> P {
|
||||
@ -1184,7 +1184,7 @@ pub struct CubicCurve<P: VectorSpace> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> CubicCurve<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> CubicCurve<P> {
|
||||
/// Create a new curve from a collection of segments. If the collection of segments is empty,
|
||||
/// a curve cannot be built and `None` will be returned instead.
|
||||
pub fn from_segments(segments: impl IntoIterator<Item = CubicSegment<P>>) -> Option<Self> {
|
||||
@ -1347,7 +1347,7 @@ pub struct RationalSegment<P: VectorSpace> {
|
||||
/// The width of the domain of this segment.
|
||||
pub knot_span: f32,
|
||||
}
|
||||
impl<P: VectorSpace> RationalSegment<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> RationalSegment<P> {
|
||||
/// Instantaneous position of a point at parametric value `t` in `[0, 1]`.
|
||||
#[inline]
|
||||
pub fn position(&self, t: f32) -> P {
|
||||
@ -1484,7 +1484,7 @@ pub struct RationalCurve<P: VectorSpace> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<P: VectorSpace> RationalCurve<P> {
|
||||
impl<P: VectorSpace<Scalar = f32>> RationalCurve<P> {
|
||||
/// Create a new curve from a collection of segments. If the collection of segments is empty,
|
||||
/// a curve cannot be built and `None` will be returned instead.
|
||||
pub fn from_segments(segments: impl IntoIterator<Item = RationalSegment<P>>) -> Option<Self> {
|
||||
|
@ -208,10 +208,12 @@ where
|
||||
|
||||
// -- ZipCurve
|
||||
|
||||
impl<S, T, C, D> SampleDerivative<(S, T)> for ZipCurve<S, T, C, D>
|
||||
impl<U, V, S, T, C, D> SampleDerivative<(S, T)> for ZipCurve<S, T, C, D>
|
||||
where
|
||||
S: HasTangent,
|
||||
T: HasTangent,
|
||||
U: VectorSpace<Scalar = f32>,
|
||||
V: VectorSpace<Scalar = f32>,
|
||||
S: HasTangent<Tangent = U>,
|
||||
T: HasTangent<Tangent = V>,
|
||||
C: SampleDerivative<S>,
|
||||
D: SampleDerivative<T>,
|
||||
{
|
||||
@ -225,10 +227,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T, C, D> SampleTwoDerivatives<(S, T)> for ZipCurve<S, T, C, D>
|
||||
impl<U, V, S, T, C, D> SampleTwoDerivatives<(S, T)> for ZipCurve<S, T, C, D>
|
||||
where
|
||||
S: HasTangent,
|
||||
T: HasTangent,
|
||||
U: VectorSpace<Scalar = f32>,
|
||||
V: VectorSpace<Scalar = f32>,
|
||||
S: HasTangent<Tangent = U>,
|
||||
T: HasTangent<Tangent = V>,
|
||||
C: SampleTwoDerivatives<S>,
|
||||
D: SampleTwoDerivatives<T>,
|
||||
{
|
||||
@ -248,9 +252,10 @@ where
|
||||
|
||||
// -- GraphCurve
|
||||
|
||||
impl<T, C> SampleDerivative<(f32, T)> for GraphCurve<T, C>
|
||||
impl<V, T, C> SampleDerivative<(f32, T)> for GraphCurve<T, C>
|
||||
where
|
||||
T: HasTangent,
|
||||
V: VectorSpace<Scalar = f32>,
|
||||
T: HasTangent<Tangent = V>,
|
||||
C: SampleDerivative<T>,
|
||||
{
|
||||
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<(f32, T)> {
|
||||
@ -262,9 +267,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C> SampleTwoDerivatives<(f32, T)> for GraphCurve<T, C>
|
||||
impl<V, T, C> SampleTwoDerivatives<(f32, T)> for GraphCurve<T, C>
|
||||
where
|
||||
T: HasTangent,
|
||||
V: VectorSpace<Scalar = f32>,
|
||||
T: HasTangent<Tangent = V>,
|
||||
C: SampleTwoDerivatives<T>,
|
||||
{
|
||||
fn sample_with_two_derivatives_unchecked(&self, t: f32) -> WithTwoDerivatives<(f32, T)> {
|
||||
@ -321,9 +327,10 @@ where
|
||||
|
||||
// -- CurveReparamCurve
|
||||
|
||||
impl<T, C, D> SampleDerivative<T> for CurveReparamCurve<T, C, D>
|
||||
impl<V, T, C, D> SampleDerivative<T> for CurveReparamCurve<T, C, D>
|
||||
where
|
||||
T: HasTangent,
|
||||
V: VectorSpace<Scalar = f32>,
|
||||
T: HasTangent<Tangent = V>,
|
||||
C: SampleDerivative<T>,
|
||||
D: SampleDerivative<f32>,
|
||||
{
|
||||
@ -349,9 +356,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C, D> SampleTwoDerivatives<T> for CurveReparamCurve<T, C, D>
|
||||
impl<V, T, C, D> SampleTwoDerivatives<T> for CurveReparamCurve<T, C, D>
|
||||
where
|
||||
T: HasTangent,
|
||||
V: VectorSpace<Scalar = f32>,
|
||||
T: HasTangent<Tangent = V>,
|
||||
C: SampleTwoDerivatives<T>,
|
||||
D: SampleTwoDerivatives<f32>,
|
||||
{
|
||||
@ -386,9 +394,10 @@ where
|
||||
|
||||
// -- LinearReparamCurve
|
||||
|
||||
impl<T, C> SampleDerivative<T> for LinearReparamCurve<T, C>
|
||||
impl<V, T, C> SampleDerivative<T> for LinearReparamCurve<T, C>
|
||||
where
|
||||
T: HasTangent,
|
||||
V: VectorSpace<Scalar = f32>,
|
||||
T: HasTangent<Tangent = V>,
|
||||
C: SampleDerivative<T>,
|
||||
{
|
||||
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<T> {
|
||||
@ -413,9 +422,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, C> SampleTwoDerivatives<T> for LinearReparamCurve<T, C>
|
||||
impl<V, T, C> SampleTwoDerivatives<T> for LinearReparamCurve<T, C>
|
||||
where
|
||||
T: HasTangent,
|
||||
V: VectorSpace<Scalar = f32>,
|
||||
T: HasTangent<Tangent = V>,
|
||||
C: SampleTwoDerivatives<T>,
|
||||
{
|
||||
fn sample_with_two_derivatives_unchecked(&self, t: f32) -> WithTwoDerivatives<T> {
|
||||
|
@ -32,7 +32,7 @@ pub trait Ease: Sized {
|
||||
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self>;
|
||||
}
|
||||
|
||||
impl<V: VectorSpace> Ease for V {
|
||||
impl<V: VectorSpace<Scalar = f32>> Ease for V {
|
||||
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
|
||||
FunctionCurve::new(Interval::EVERYWHERE, move |t| V::lerp(start, end, t))
|
||||
}
|
||||
|
@ -40,11 +40,12 @@
|
||||
|
||||
use core::f32::consts::{PI, TAU};
|
||||
|
||||
use crate::{ops, primitives::*, NormedVectorSpace, Vec2, Vec3};
|
||||
use crate::{ops, primitives::*, NormedVectorSpace, ScalarField, Vec2, Vec3};
|
||||
use rand::{
|
||||
distributions::{Distribution, WeightedIndex},
|
||||
Rng,
|
||||
};
|
||||
use rand_distr::uniform::SampleUniform;
|
||||
|
||||
/// Exposes methods to uniformly sample a variety of primitive shapes.
|
||||
pub trait ShapeSample {
|
||||
@ -281,22 +282,24 @@ impl ShapeSample for Cuboid {
|
||||
}
|
||||
|
||||
/// Interior sampling for triangles which doesn't depend on the ambient dimension.
|
||||
fn sample_triangle_interior<P: NormedVectorSpace, R: Rng + ?Sized>(
|
||||
vertices: [P; 3],
|
||||
rng: &mut R,
|
||||
) -> P {
|
||||
fn sample_triangle_interior<P, R>(vertices: [P; 3], rng: &mut R) -> P
|
||||
where
|
||||
P: NormedVectorSpace,
|
||||
P::Scalar: SampleUniform + PartialOrd,
|
||||
R: Rng + ?Sized,
|
||||
{
|
||||
let [a, b, c] = vertices;
|
||||
let ab = b - a;
|
||||
let ac = c - a;
|
||||
|
||||
// Generate random points on a parallelepiped and reflect so that
|
||||
// we can use the points that lie outside the triangle
|
||||
let u = rng.gen_range(0.0..=1.0);
|
||||
let v = rng.gen_range(0.0..=1.0);
|
||||
let u = rng.gen_range(P::Scalar::ZERO..=P::Scalar::ONE);
|
||||
let v = rng.gen_range(P::Scalar::ZERO..=P::Scalar::ONE);
|
||||
|
||||
if u + v > 1. {
|
||||
let u1 = 1. - v;
|
||||
let v1 = 1. - u;
|
||||
if u + v > P::Scalar::ONE {
|
||||
let u1 = P::Scalar::ONE - v;
|
||||
let v1 = P::Scalar::ONE - u;
|
||||
a + (ab * u1 + ac * v1)
|
||||
} else {
|
||||
a + (ab * u + ac * v)
|
||||
@ -304,16 +307,18 @@ fn sample_triangle_interior<P: NormedVectorSpace, R: Rng + ?Sized>(
|
||||
}
|
||||
|
||||
/// Boundary sampling for triangles which doesn't depend on the ambient dimension.
|
||||
fn sample_triangle_boundary<P: NormedVectorSpace, R: Rng + ?Sized>(
|
||||
vertices: [P; 3],
|
||||
rng: &mut R,
|
||||
) -> P {
|
||||
fn sample_triangle_boundary<P, R>(vertices: [P; 3], rng: &mut R) -> P
|
||||
where
|
||||
P: NormedVectorSpace,
|
||||
P::Scalar: SampleUniform + PartialOrd + for<'a> ::core::ops::AddAssign<&'a P::Scalar>,
|
||||
R: Rng + ?Sized,
|
||||
{
|
||||
let [a, b, c] = vertices;
|
||||
let ab = b - a;
|
||||
let ac = c - a;
|
||||
let bc = c - b;
|
||||
|
||||
let t = rng.gen_range(0.0..=1.0);
|
||||
let t = rng.gen_range(P::Scalar::ZERO..=P::Scalar::ONE);
|
||||
|
||||
if let Ok(dist) = WeightedIndex::new([ab.norm(), ac.norm(), bc.norm()]) {
|
||||
match dist.sample(rng) {
|
||||
|
@ -91,7 +91,7 @@ Set the `PKG_CONFIG_PATH` env var to `/usr/lib/<target>/pkgconfig/`. For example
|
||||
export PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig/"
|
||||
```
|
||||
|
||||
## Arch / Manjaro
|
||||
## [Arch](https://archlinux.org/) / [Manjaro](https://manjaro.org/)
|
||||
|
||||
```bash
|
||||
sudo pacman -S libx11 pkgconf alsa-lib libxcursor libxrandr libxi
|
||||
@ -102,7 +102,7 @@ Install `pipewire-alsa` or `pulseaudio-alsa` depending on the sound server you a
|
||||
Depending on your graphics card, you may have to install one of the following:
|
||||
`vulkan-radeon`, `vulkan-intel`, or `mesa-vulkan-drivers`
|
||||
|
||||
## Void
|
||||
## [Void](https://voidlinux.org/)
|
||||
|
||||
```bash
|
||||
sudo xbps-install -S pkgconf alsa-lib-devel libX11-devel eudev-libudev-devel
|
||||
@ -110,6 +110,80 @@ sudo xbps-install -S pkgconf alsa-lib-devel libX11-devel eudev-libudev-devel
|
||||
|
||||
## [Nix](https://nixos.org)
|
||||
|
||||
### flake.nix
|
||||
|
||||
Add a `flake.nix` file to the root of your GitHub repository containing:
|
||||
|
||||
```nix
|
||||
{
|
||||
description = "bevy flake";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
nixpkgs,
|
||||
rust-overlay,
|
||||
flake-utils,
|
||||
...
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
overlays = [ (import rust-overlay) ];
|
||||
pkgs = import nixpkgs {
|
||||
inherit system overlays;
|
||||
};
|
||||
in
|
||||
{
|
||||
devShells.default =
|
||||
with pkgs;
|
||||
mkShell {
|
||||
buildInputs =
|
||||
[
|
||||
# Rust dependencies
|
||||
(rust-bin.stable.latest.default.override { extensions = [ "rust-src" ]; })
|
||||
pkg-config
|
||||
]
|
||||
++ lib.optionals (lib.strings.hasInfix "linux" system) [
|
||||
# for Linux
|
||||
# Audio (Linux only)
|
||||
alsa-lib
|
||||
# Cross Platform 3D Graphics API
|
||||
vulkan-loader
|
||||
# For debugging around vulkan
|
||||
vulkan-tools
|
||||
# Other dependencies
|
||||
libudev-zero
|
||||
xorg.libX11
|
||||
xorg.libXcursor
|
||||
xorg.libXi
|
||||
xorg.libXrandr
|
||||
libxkbcommon
|
||||
];
|
||||
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
|
||||
LD_LIBRARY_PATH = lib.makeLibraryPath [
|
||||
vulkan-loader
|
||||
xorg.libX11
|
||||
xorg.libXi
|
||||
xorg.libXcursor
|
||||
libxkbcommon
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> We have confirmed that this flake.nix can be used successfully on NixOS and MacOS with Rust's edition set to 2021.
|
||||
|
||||
### shell.nix
|
||||
|
||||
Add a `shell.nix` file to the root of the project containing:
|
||||
|
||||
```nix
|
||||
@ -138,8 +212,8 @@ If running nix on a non NixOS system (such as ubuntu, arch etc.), [NixGL](https:
|
||||
to link graphics drivers into the context of software installed by nix:
|
||||
|
||||
1. Install a system specific nixGL wrapper ([docs](https://github.com/nix-community/nixGL)).
|
||||
* If you're running a nvidia GPU choose `nixVulkanNvidia`.
|
||||
* Otherwise, choose another wrapper appropriate for your system.
|
||||
- If you're running a nvidia GPU choose `nixVulkanNvidia`.
|
||||
- Otherwise, choose another wrapper appropriate for your system.
|
||||
2. Run `nixVulkanNvidia-xxx.xxx.xx cargo run` to compile a bevy program, where `xxx-xxx-xx` denotes the graphics driver version `nixVulkanNvidia` was compiled with.
|
||||
|
||||
This is also possible with [Nix flakes](https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html).
|
||||
@ -152,7 +226,7 @@ for more information about `devShells`.
|
||||
Note that this template does not add Rust to the environment because there are many ways to do it.
|
||||
For example, to use stable Rust from nixpkgs, you can add `cargo` and `rustc` to `nativeBuildInputs`.
|
||||
|
||||
[Here]([https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/ju/jumpy/package.nix](https://github.com/NixOS/nixpkgs/blob/0da3c44a9460a26d2025ec3ed2ec60a895eb1114/pkgs/games/jumpy/default.nix))
|
||||
[Here](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/ju/jumpy/package.nix)
|
||||
is an example of packaging a Bevy program in nix.
|
||||
|
||||
## [OpenSUSE](https://www.opensuse.org/)
|
||||
@ -161,7 +235,7 @@ is an example of packaging a Bevy program in nix.
|
||||
sudo zypper install libudev-devel gcc-c++ alsa-lib-devel
|
||||
```
|
||||
|
||||
## Gentoo
|
||||
## [Gentoo](https://www.gentoo.org/)
|
||||
|
||||
```bash
|
||||
sudo emerge --ask libX11 pkgconf alsa-lib
|
||||
|
@ -3,8 +3,8 @@
|
||||
use bevy::{math::VectorSpace, prelude::*};
|
||||
|
||||
// We define this trait so we can reuse the same code for multiple color types that may be implemented using curves.
|
||||
trait CurveColor: VectorSpace + Into<Color> + Send + Sync + 'static {}
|
||||
impl<T: VectorSpace + Into<Color> + Send + Sync + 'static> CurveColor for T {}
|
||||
trait CurveColor: VectorSpace<Scalar = f32> + Into<Color> + Send + Sync + 'static {}
|
||||
impl<T: VectorSpace<Scalar = f32> + Into<Color> + Send + Sync + 'static> CurveColor for T {}
|
||||
|
||||
// We define this trait so we can reuse the same code for multiple color types that may be implemented using mixing.
|
||||
trait MixedColor: Mix + Into<Color> + Send + Sync + 'static {}
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
title: `VectorSpace` implementations
|
||||
pull_requests: [19194]
|
||||
---
|
||||
|
||||
Previously, implementing `VectorSpace` for a type required your type to use or at least interface with `f32`. This made implementing `VectorSpace` for double-precision types (like `DVec3`) less meaningful and useful, requiring lots of casting. `VectorSpace` has a new required associated type `Scalar` that's bounded by a new trait `ScalarField`. `bevy_math` implements this trait for `f64` and `f32` out of the box, and `VectorSpace` is now implemented for `DVec[N]` types.
|
||||
|
||||
If you manually implemented `VectorSpace` for any type, you'll need to implement `Scalar` for it. If you were working with single-precision floating-point types and you want the exact behavior from before, set it to `f32`.
|
Loading…
Reference in New Issue
Block a user