Skip to content

Commit

Permalink
Add reflect and refract to vector types (#531)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nexfader authored Jun 25, 2024
1 parent a42fa02 commit a87b996
Show file tree
Hide file tree
Showing 19 changed files with 656 additions and 0 deletions.
38 changes: 38 additions & 0 deletions codegen/templates/vec.rs.tera
Original file line number Diff line number Diff line change
Expand Up @@ -1976,6 +1976,44 @@ impl {{ self_t }} {
{% endif %}
}

/// Returns the reflection vector for a given incident vector `self` and surface normal
/// `normal`.
///
/// `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn reflect(self, normal: Self) -> Self {
glam_assert!(normal.is_normalized());
self - 2.0 * self.dot(normal) * normal
}

/// Returns the refraction direction for a given incident vector `self`, surface normal
/// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs,
/// a zero vector will be returned.
///
/// `self` and `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn refract(self, normal: Self, eta: {{ scalar_t }}) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(normal.is_normalized());
let n_dot_i = normal.dot(self);
let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
if k >= 0.0 {
eta * self - (eta * n_dot_i + math::sqrt(k)) * normal
} else {
Self::ZERO
}
}

{% if dim == 2 %}
/// Creates a 2D vector containing `[angle.cos(), angle.sin()]`. This can be used in
/// conjunction with the [`rotate()`][Self::rotate()] method, e.g.
Expand Down
38 changes: 38 additions & 0 deletions src/f32/coresimd/vec3a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,44 @@ impl Vec3A {
Self(self.0.mul_add(a.0, b.0))
}

/// Returns the reflection vector for a given incident vector `self` and surface normal
/// `normal`.
///
/// `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn reflect(self, normal: Self) -> Self {
glam_assert!(normal.is_normalized());
self - 2.0 * self.dot(normal) * normal
}

/// Returns the refraction direction for a given incident vector `self`, surface normal
/// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs,
/// a zero vector will be returned.
///
/// `self` and `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn refract(self, normal: Self, eta: f32) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(normal.is_normalized());
let n_dot_i = normal.dot(self);
let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
if k >= 0.0 {
eta * self - (eta * n_dot_i + math::sqrt(k)) * normal
} else {
Self::ZERO
}
}

/// Returns the angle (in radians) between two vectors in the range `[0, +π]`.
///
/// The inputs do not need to be unit vectors however they must be non-zero.
Expand Down
38 changes: 38 additions & 0 deletions src/f32/coresimd/vec4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,44 @@ impl Vec4 {
Self(self.0.mul_add(a.0, b.0))
}

/// Returns the reflection vector for a given incident vector `self` and surface normal
/// `normal`.
///
/// `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn reflect(self, normal: Self) -> Self {
glam_assert!(normal.is_normalized());
self - 2.0 * self.dot(normal) * normal
}

/// Returns the refraction direction for a given incident vector `self`, surface normal
/// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs,
/// a zero vector will be returned.
///
/// `self` and `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn refract(self, normal: Self, eta: f32) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(normal.is_normalized());
let n_dot_i = normal.dot(self);
let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
if k >= 0.0 {
eta * self - (eta * n_dot_i + math::sqrt(k)) * normal
} else {
Self::ZERO
}
}

/// Casts all elements of `self` to `f64`.
#[inline]
#[must_use]
Expand Down
38 changes: 38 additions & 0 deletions src/f32/neon/vec3a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,44 @@ impl Vec3A {
Self(unsafe { vfmaq_f32(b.0, self.0, a.0) })
}

/// Returns the reflection vector for a given incident vector `self` and surface normal
/// `normal`.
///
/// `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn reflect(self, normal: Self) -> Self {
glam_assert!(normal.is_normalized());
self - 2.0 * self.dot(normal) * normal
}

/// Returns the refraction direction for a given incident vector `self`, surface normal
/// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs,
/// a zero vector will be returned.
///
/// `self` and `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn refract(self, normal: Self, eta: f32) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(normal.is_normalized());
let n_dot_i = normal.dot(self);
let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
if k >= 0.0 {
eta * self - (eta * n_dot_i + math::sqrt(k)) * normal
} else {
Self::ZERO
}
}

/// Returns the angle (in radians) between two vectors in the range `[0, +π]`.
///
/// The inputs do not need to be unit vectors however they must be non-zero.
Expand Down
38 changes: 38 additions & 0 deletions src/f32/neon/vec4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,44 @@ impl Vec4 {
Self(unsafe { vfmaq_f32(b.0, self.0, a.0) })
}

/// Returns the reflection vector for a given incident vector `self` and surface normal
/// `normal`.
///
/// `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn reflect(self, normal: Self) -> Self {
glam_assert!(normal.is_normalized());
self - 2.0 * self.dot(normal) * normal
}

/// Returns the refraction direction for a given incident vector `self`, surface normal
/// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs,
/// a zero vector will be returned.
///
/// `self` and `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn refract(self, normal: Self, eta: f32) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(normal.is_normalized());
let n_dot_i = normal.dot(self);
let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
if k >= 0.0 {
eta * self - (eta * n_dot_i + math::sqrt(k)) * normal
} else {
Self::ZERO
}
}

/// Casts all elements of `self` to `f64`.
#[inline]
#[must_use]
Expand Down
38 changes: 38 additions & 0 deletions src/f32/scalar/vec3a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,44 @@ impl Vec3A {
)
}

/// Returns the reflection vector for a given incident vector `self` and surface normal
/// `normal`.
///
/// `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn reflect(self, normal: Self) -> Self {
glam_assert!(normal.is_normalized());
self - 2.0 * self.dot(normal) * normal
}

/// Returns the refraction direction for a given incident vector `self`, surface normal
/// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs,
/// a zero vector will be returned.
///
/// `self` and `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn refract(self, normal: Self, eta: f32) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(normal.is_normalized());
let n_dot_i = normal.dot(self);
let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
if k >= 0.0 {
eta * self - (eta * n_dot_i + math::sqrt(k)) * normal
} else {
Self::ZERO
}
}

/// Returns the angle (in radians) between two vectors in the range `[0, +π]`.
///
/// The inputs do not need to be unit vectors however they must be non-zero.
Expand Down
38 changes: 38 additions & 0 deletions src/f32/scalar/vec4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,44 @@ impl Vec4 {
)
}

/// Returns the reflection vector for a given incident vector `self` and surface normal
/// `normal`.
///
/// `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn reflect(self, normal: Self) -> Self {
glam_assert!(normal.is_normalized());
self - 2.0 * self.dot(normal) * normal
}

/// Returns the refraction direction for a given incident vector `self`, surface normal
/// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs,
/// a zero vector will be returned.
///
/// `self` and `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn refract(self, normal: Self, eta: f32) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(normal.is_normalized());
let n_dot_i = normal.dot(self);
let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
if k >= 0.0 {
eta * self - (eta * n_dot_i + math::sqrt(k)) * normal
} else {
Self::ZERO
}
}

/// Casts all elements of `self` to `f64`.
#[inline]
#[must_use]
Expand Down
38 changes: 38 additions & 0 deletions src/f32/sse2/vec3a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,44 @@ impl Vec3A {
)
}

/// Returns the reflection vector for a given incident vector `self` and surface normal
/// `normal`.
///
/// `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn reflect(self, normal: Self) -> Self {
glam_assert!(normal.is_normalized());
self - 2.0 * self.dot(normal) * normal
}

/// Returns the refraction direction for a given incident vector `self`, surface normal
/// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs,
/// a zero vector will be returned.
///
/// `self` and `normal` must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn refract(self, normal: Self, eta: f32) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(normal.is_normalized());
let n_dot_i = normal.dot(self);
let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
if k >= 0.0 {
eta * self - (eta * n_dot_i + math::sqrt(k)) * normal
} else {
Self::ZERO
}
}

/// Returns the angle (in radians) between two vectors in the range `[0, +π]`.
///
/// The inputs do not need to be unit vectors however they must be non-zero.
Expand Down
Loading

0 comments on commit a87b996

Please sign in to comment.