mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Add helpers for translate, rotate, and scale operations - Mesh (#11675)
# Objective - Fixes #11594 ## Solution - Add helpers for translate, rotate, and scale operations. --- ## Changelog - Added functions `translated_by`, `translate_by`, `rotated_by`, `rotate_by`, `scaled_by`, and `scale_by`.
This commit is contained in:
parent
5c52d0aeee
commit
1352bf1df4
1 changed files with 114 additions and 0 deletions
|
@ -613,6 +613,120 @@ impl Mesh {
|
|||
}
|
||||
}
|
||||
|
||||
/// Translates the vertex positions of the mesh by the given [`Vec3`].
|
||||
pub fn translated_by(mut self, translation: Vec3) -> Self {
|
||||
self.translate_by(translation);
|
||||
self
|
||||
}
|
||||
|
||||
/// Translates the vertex positions of the mesh in place by the given [`Vec3`].
|
||||
pub fn translate_by(&mut self, translation: Vec3) {
|
||||
if translation == Vec3::ZERO {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(VertexAttributeValues::Float32x3(ref mut positions)) =
|
||||
self.attribute_mut(Mesh::ATTRIBUTE_POSITION)
|
||||
{
|
||||
// Apply translation to vertex positions
|
||||
positions
|
||||
.iter_mut()
|
||||
.for_each(|pos| *pos = (Vec3::from_slice(pos) + translation).to_array());
|
||||
}
|
||||
}
|
||||
|
||||
/// Rotates the vertex positions, normals, and tangents of the mesh by the given [`Quat`].
|
||||
pub fn rotated_by(mut self, rotation: Quat) -> Self {
|
||||
self.rotate_by(rotation);
|
||||
self
|
||||
}
|
||||
|
||||
/// Rotates the vertex positions, normals, and tangents of the mesh in place by the given [`Quat`].
|
||||
pub fn rotate_by(&mut self, rotation: Quat) {
|
||||
if let Some(VertexAttributeValues::Float32x3(ref mut positions)) =
|
||||
self.attribute_mut(Mesh::ATTRIBUTE_POSITION)
|
||||
{
|
||||
// Apply rotation to vertex positions
|
||||
positions
|
||||
.iter_mut()
|
||||
.for_each(|pos| *pos = (rotation * Vec3::from_slice(pos)).to_array());
|
||||
}
|
||||
|
||||
// No need to transform normals or tangents if rotation is near identity
|
||||
if rotation.is_near_identity() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(VertexAttributeValues::Float32x3(ref mut normals)) =
|
||||
self.attribute_mut(Mesh::ATTRIBUTE_NORMAL)
|
||||
{
|
||||
// Transform normals
|
||||
normals.iter_mut().for_each(|normal| {
|
||||
*normal = (rotation * Vec3::from_slice(normal).normalize_or_zero()).to_array();
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(VertexAttributeValues::Float32x3(ref mut tangents)) =
|
||||
self.attribute_mut(Mesh::ATTRIBUTE_TANGENT)
|
||||
{
|
||||
// Transform tangents
|
||||
tangents.iter_mut().for_each(|tangent| {
|
||||
*tangent = (rotation * Vec3::from_slice(tangent).normalize_or_zero()).to_array();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Scales the vertex positions, normals, and tangents of the mesh by the given [`Vec3`].
|
||||
pub fn scaled_by(mut self, scale: Vec3) -> Self {
|
||||
self.scale_by(scale);
|
||||
self
|
||||
}
|
||||
|
||||
/// Scales the vertex positions, normals, and tangents of the mesh in place by the given [`Vec3`].
|
||||
pub fn scale_by(&mut self, scale: Vec3) {
|
||||
// Needed when transforming normals and tangents
|
||||
let covector_scale = scale.yzx() * scale.zxy();
|
||||
|
||||
debug_assert!(
|
||||
covector_scale != Vec3::ZERO,
|
||||
"mesh transform scale cannot be zero on more than one axis"
|
||||
);
|
||||
|
||||
if let Some(VertexAttributeValues::Float32x3(ref mut positions)) =
|
||||
self.attribute_mut(Mesh::ATTRIBUTE_POSITION)
|
||||
{
|
||||
// Apply scale to vertex positions
|
||||
positions
|
||||
.iter_mut()
|
||||
.for_each(|pos| *pos = (scale * Vec3::from_slice(pos)).to_array());
|
||||
}
|
||||
|
||||
// No need to transform normals or tangents if scale is uniform
|
||||
if scale.x == scale.y && scale.y == scale.z {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(VertexAttributeValues::Float32x3(ref mut normals)) =
|
||||
self.attribute_mut(Mesh::ATTRIBUTE_NORMAL)
|
||||
{
|
||||
// Transform normals, taking into account non-uniform scaling
|
||||
normals.iter_mut().for_each(|normal| {
|
||||
let scaled_normal = Vec3::from_slice(normal) * covector_scale;
|
||||
*normal = scaled_normal.normalize_or_zero().to_array();
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(VertexAttributeValues::Float32x3(ref mut tangents)) =
|
||||
self.attribute_mut(Mesh::ATTRIBUTE_TANGENT)
|
||||
{
|
||||
// Transform tangents, taking into account non-uniform scaling
|
||||
tangents.iter_mut().for_each(|tangent| {
|
||||
let scaled_tangent = Vec3::from_slice(tangent) * covector_scale;
|
||||
*tangent = scaled_tangent.normalize_or_zero().to_array();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the Axis-Aligned Bounding Box of the mesh vertices in model space
|
||||
///
|
||||
/// Returns `None` if `self` doesn't have [`Mesh::ATTRIBUTE_POSITION`] of
|
||||
|
|
Loading…
Reference in a new issue