From 8b8ad0927e7a6f0202be8a20770d8459525bb469 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Sat, 24 Apr 2021 16:17:06 +0200 Subject: [PATCH 01/22] smooth damp for f32, f64, vec2, vec3 --- crates/bevy_math/src/lib.rs | 6 ++- crates/bevy_math/src/smooth.rs | 95 ++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 crates/bevy_math/src/smooth.rs diff --git a/crates/bevy_math/src/lib.rs b/crates/bevy_math/src/lib.rs index f7315b35d50be..16c771ca10fe6 100644 --- a/crates/bevy_math/src/lib.rs +++ b/crates/bevy_math/src/lib.rs @@ -1,13 +1,15 @@ mod face_toward; mod geometry; +mod smooth; pub use face_toward::*; pub use geometry::*; pub use glam::*; +pub use smooth::*; pub mod prelude { pub use crate::{ - BVec2, BVec3, BVec4, FaceToward, IVec2, IVec3, IVec4, Mat3, Mat4, Quat, Rect, Size, UVec2, - UVec3, UVec4, Vec2, Vec3, Vec4, + BVec2, BVec3, BVec4, FaceToward, IVec2, IVec3, IVec4, Mat3, Mat4, Quat, Rect, Size, + SmoothDamp, UVec2, UVec3, UVec4, Vec2, Vec3, Vec4, }; } diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs new file mode 100644 index 0000000000000..1c0147fef3dd7 --- /dev/null +++ b/crates/bevy_math/src/smooth.rs @@ -0,0 +1,95 @@ +use crate::{Vec2, Vec3}; + +/// Smooths value to a goal using a damped spring. +pub trait SmoothDamp { + /// Smooths value to a goal using a damped spring. + /// + /// Returns smoothed value and new velocity. + fn smooth_damp( + from: Self, + to: Self, + velocity: Self, + smooth_time: f32, + delta_time: f32, + ) -> (Self, Self) + where + Self: Sized; +} + +impl SmoothDamp for f32 { + fn smooth_damp( + from: f32, + to: f32, + velocity: f32, + smooth_time: f32, + delta_time: f32, + ) -> (f32, f32) { + let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero + // from game programming gems 4, chapter 1.10 + let omega = 2.0 / smooth_time; + let x = omega * delta_time; + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); + // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + let change = from - to; + let temp = (velocity + omega * change) * delta_time; + + ( + to + (change + temp) * exp, // position + (velocity - omega * temp) * exp, // velocity + ) + } +} + +impl SmoothDamp for f64 { + fn smooth_damp( + from: f64, + to: f64, + velocity: f64, + smooth_time: f32, + delta_time: f32, + ) -> (f64, f64) { + let smooth_time = f64::max(smooth_time as f64, 0.0001); // ensure smooth_time is positive and non-zero + let delta_time = delta_time as f64; + // from game programming gems 4, chapter 1.10 + let omega = 2.0 / smooth_time; + let x = omega * delta_time; + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); + // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + let change = from - to; + let temp = (velocity + omega * change) * delta_time; + + ( + to + (change + temp) * exp, // position + (velocity - omega * temp) * exp, // velocity + ) + } +} + +impl SmoothDamp for Vec2 { + fn smooth_damp( + from: Vec2, + to: Vec2, + velocity: Vec2, + smooth_time: f32, + delta_time: f32, + ) -> (Vec2, Vec2) { + let (x, vx) = f32::smooth_damp(from.x, to.x, velocity.x, smooth_time, delta_time); + let (y, vy) = f32::smooth_damp(from.y, to.y, velocity.y, smooth_time, delta_time); + (Vec2::new(x, y), Vec2::new(vx, vy)) + } +} + +impl SmoothDamp for Vec3 { + fn smooth_damp( + from: Vec3, + to: Vec3, + velocity: Vec3, + smooth_time: f32, + delta_time: f32, + ) -> (Vec3, Vec3) { + let (x, vx) = f32::smooth_damp(from.x, to.x, velocity.x, smooth_time, delta_time); + let (y, vy) = f32::smooth_damp(from.y, to.y, velocity.y, smooth_time, delta_time); + let (z, vz) = f32::smooth_damp(from.z, to.z, velocity.z, smooth_time, delta_time); + (Vec3::new(x, y, z), Vec3::new(vx, vy, vz)) + } +} From a79e3cc402c1b40152a5bdeebaecf9162a46aaf2 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Sat, 24 Apr 2021 17:40:25 +0200 Subject: [PATCH 02/22] format --- crates/bevy_math/src/smooth.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 1c0147fef3dd7..62c85d7e0cea5 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -3,7 +3,7 @@ use crate::{Vec2, Vec3}; /// Smooths value to a goal using a damped spring. pub trait SmoothDamp { /// Smooths value to a goal using a damped spring. - /// + /// /// Returns smoothed value and new velocity. fn smooth_damp( from: Self, @@ -25,6 +25,7 @@ impl SmoothDamp for f32 { delta_time: f32, ) -> (f32, f32) { let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero + // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; @@ -50,6 +51,7 @@ impl SmoothDamp for f64 { ) -> (f64, f64) { let smooth_time = f64::max(smooth_time as f64, 0.0001); // ensure smooth_time is positive and non-zero let delta_time = delta_time as f64; + // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; From 3b31005d0f33727e2420a02820b2688ef5b1acab Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 00:42:01 +0200 Subject: [PATCH 03/22] smooth_time comment --- crates/bevy_math/src/smooth.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 62c85d7e0cea5..5683dc87648e3 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -4,6 +4,8 @@ use crate::{Vec2, Vec3}; pub trait SmoothDamp { /// Smooths value to a goal using a damped spring. /// + /// `smooth_time` is the expected time to reach the target when at maximum velocity + /// /// Returns smoothed value and new velocity. fn smooth_damp( from: Self, From 565f5569bd4d5aa6d9131867ba536fe1ca86dbcc Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 00:42:01 +0200 Subject: [PATCH 04/22] smooth_time comment --- crates/bevy_math/src/smooth.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 62c85d7e0cea5..5683dc87648e3 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -4,6 +4,8 @@ use crate::{Vec2, Vec3}; pub trait SmoothDamp { /// Smooths value to a goal using a damped spring. /// + /// `smooth_time` is the expected time to reach the target when at maximum velocity + /// /// Returns smoothed value and new velocity. fn smooth_damp( from: Self, From 16ba211e7a41a1b108f1511cd473b6654b2c998c Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 00:59:15 +0200 Subject: [PATCH 05/22] smooth damp with max speed --- crates/bevy_math/src/smooth.rs | 154 ++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 1 deletion(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 5683dc87648e3..fe8ebea816c2e 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -4,7 +4,7 @@ use crate::{Vec2, Vec3}; pub trait SmoothDamp { /// Smooths value to a goal using a damped spring. /// - /// `smooth_time` is the expected time to reach the target when at maximum velocity + /// `smooth_time` is the expected time to reach the target when at maximum velocity. /// /// Returns smoothed value and new velocity. fn smooth_damp( @@ -31,8 +31,10 @@ impl SmoothDamp for f32 { // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + let change = from - to; let temp = (velocity + omega * change) * delta_time; @@ -57,8 +59,10 @@ impl SmoothDamp for f64 { // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + let change = from - to; let temp = (velocity + omega * change) * delta_time; @@ -97,3 +101,151 @@ impl SmoothDamp for Vec3 { (Vec3::new(x, y, z), Vec3::new(vx, vy, vz)) } } + +/// Smooths value to a goal using a damped spring limited by a maximum speed. +pub trait SmoothDampMax { + /// Smooths value to a goal using a damped spring limited by a maximum speed. + /// + /// `smooth_time` is the expected time to reach the target when at maximum velocity. + /// + /// Returns smoothed value and new velocity. + fn smooth_damp_max( + from: Self, + to: Self, + velocity: Self, + max_speed: f32, + smooth_time: f32, + delta_time: f32, + ) -> (Self, Self) + where + Self: Sized; +} + +impl SmoothDampMax for f32 { + fn smooth_damp_max( + from: f32, + to: f32, + velocity: f32, + max_speed: f32, + smooth_time: f32, + delta_time: f32, + ) -> (f32, f32) { + let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero + + // from game programming gems 4, chapter 1.10 + let omega = 2.0 / smooth_time; + let x = omega * delta_time; + + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); + // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + + let change = from - to; + let max = max_speed * delta_time; + let change = f32::clamp(change, -max, max); + + let temp = (velocity + omega * change) * delta_time; + + ( + to + (change + temp) * exp, // position + (velocity - omega * temp) * exp, // velocity + ) + } +} + +impl SmoothDampMax for f64 { + fn smooth_damp_max( + from: f64, + to: f64, + velocity: f64, + max_speed: f32, + smooth_time: f32, + delta_time: f32, + ) -> (f64, f64) { + let smooth_time = f64::max(smooth_time as f64, 0.0001); // ensure smooth_time is positive and non-zero + let delta_time = delta_time as f64; + + // from game programming gems 4, chapter 1.10 + let omega = 2.0 / smooth_time; + let x = omega * delta_time; + + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); + // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + + let change = from - to; + let max = (max_speed as f64) * delta_time; + let change = f64::clamp(change, -max, max); + + let temp = (velocity + omega * change) * delta_time; + + ( + to + (change + temp) * exp, // position + (velocity - omega * temp) * exp, // velocity + ) + } +} + +impl SmoothDampMax for Vec2 { + fn smooth_damp_max( + from: Vec2, + to: Vec2, + velocity: Vec2, + max_speed: f32, + smooth_time: f32, + delta_time: f32, + ) -> (Vec2, Vec2) { + let smooth_time = f32::max(smooth_time as f32, 0.0001); // ensure smooth_time is positive and non-zero + let delta_time = delta_time as f32; + + // from game programming gems 4, chapter 1.10 + let omega = 2.0 / smooth_time; + let x = omega * delta_time; + + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); + // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + + let change = from - to; + let max = max_speed * delta_time; + let sq_len = change.length_squared(); + let change = if sq_len > max * max { change * (max / sq_len.sqrt()) } else { change }; + + let temp = (velocity + omega * change) * delta_time; + + ( + to + (change + temp) * exp, // position + (velocity - omega * temp) * exp, // velocity + ) + } +} + +impl SmoothDampMax for Vec3 { + fn smooth_damp_max( + from: Vec3, + to: Vec3, + velocity: Vec3, + max_speed: f32, + smooth_time: f32, + delta_time: f32, + ) -> (Vec3, Vec3) { + let smooth_time = f32::max(smooth_time as f32, 0.0001); // ensure smooth_time is positive and non-zero + let delta_time = delta_time as f32; + + // from game programming gems 4, chapter 1.10 + let omega = 2.0 / smooth_time; + let x = omega * delta_time; + + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); + // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + + let change = from - to; + let max = max_speed * delta_time; + let sq_len = change.length_squared(); + let change = if sq_len > max * max { change * (max / sq_len.sqrt()) } else { change }; + + let temp = (velocity + omega * change) * delta_time; + + ( + to + (change + temp) * exp, // position + (velocity - omega * temp) * exp, // velocity + ) + } +} \ No newline at end of file From 2f3b0cbe87fb902a67bb0e9d39d943e8079a8176 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 00:59:35 +0200 Subject: [PATCH 06/22] format --- crates/bevy_math/src/smooth.rs | 50 ++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index fe8ebea816c2e..ecfd4e9b47958 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -5,7 +5,7 @@ pub trait SmoothDamp { /// Smooths value to a goal using a damped spring. /// /// `smooth_time` is the expected time to reach the target when at maximum velocity. - /// + /// /// Returns smoothed value and new velocity. fn smooth_damp( from: Self, @@ -31,10 +31,10 @@ impl SmoothDamp for f32 { // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; - + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - + let change = from - to; let temp = (velocity + omega * change) * delta_time; @@ -59,10 +59,10 @@ impl SmoothDamp for f64 { // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; - + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - + let change = from - to; let temp = (velocity + omega * change) * delta_time; @@ -107,7 +107,7 @@ pub trait SmoothDampMax { /// Smooths value to a goal using a damped spring limited by a maximum speed. /// /// `smooth_time` is the expected time to reach the target when at maximum velocity. - /// + /// /// Returns smoothed value and new velocity. fn smooth_damp_max( from: Self, @@ -135,14 +135,14 @@ impl SmoothDampMax for f32 { // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; - + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - + let change = from - to; let max = max_speed * delta_time; let change = f32::clamp(change, -max, max); - + let temp = (velocity + omega * change) * delta_time; ( @@ -167,14 +167,14 @@ impl SmoothDampMax for f64 { // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; - + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - + let change = from - to; let max = (max_speed as f64) * delta_time; let change = f64::clamp(change, -max, max); - + let temp = (velocity + omega * change) * delta_time; ( @@ -199,15 +199,19 @@ impl SmoothDampMax for Vec2 { // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; - + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - + let change = from - to; let max = max_speed * delta_time; let sq_len = change.length_squared(); - let change = if sq_len > max * max { change * (max / sq_len.sqrt()) } else { change }; - + let change = if sq_len > max * max { + change * (max / sq_len.sqrt()) + } else { + change + }; + let temp = (velocity + omega * change) * delta_time; ( @@ -232,15 +236,19 @@ impl SmoothDampMax for Vec3 { // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; let x = omega * delta_time; - + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - + let change = from - to; let max = max_speed * delta_time; let sq_len = change.length_squared(); - let change = if sq_len > max * max { change * (max / sq_len.sqrt()) } else { change }; - + let change = if sq_len > max * max { + change * (max / sq_len.sqrt()) + } else { + change + }; + let temp = (velocity + omega * change) * delta_time; ( @@ -248,4 +256,4 @@ impl SmoothDampMax for Vec3 { (velocity - omega * temp) * exp, // velocity ) } -} \ No newline at end of file +} From 830fef9d49898ca4b38689bb1734405a4f2ac579 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 01:04:20 +0200 Subject: [PATCH 07/22] use clamp_length_max --- crates/bevy_math/src/smooth.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index ecfd4e9b47958..d9e0274a2c0db 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -203,14 +203,8 @@ impl SmoothDampMax for Vec2 { let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - let change = from - to; let max = max_speed * delta_time; - let sq_len = change.length_squared(); - let change = if sq_len > max * max { - change * (max / sq_len.sqrt()) - } else { - change - }; + let change = (from - to).clamp_length_max(max); let temp = (velocity + omega * change) * delta_time; @@ -240,14 +234,8 @@ impl SmoothDampMax for Vec3 { let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - let change = from - to; let max = max_speed * delta_time; - let sq_len = change.length_squared(); - let change = if sq_len > max * max { - change * (max / sq_len.sqrt()) - } else { - change - }; + let change = (from - to).clamp_length_max(max); let temp = (velocity + omega * change) * delta_time; From 1485281667c260d2c8a2beaa53db89a34a23a23b Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 01:06:53 +0200 Subject: [PATCH 08/22] ensure max speed validity to avoid any divide by zero --- crates/bevy_math/src/smooth.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index d9e0274a2c0db..b929dda51bcbc 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -130,6 +130,7 @@ impl SmoothDampMax for f32 { smooth_time: f32, delta_time: f32, ) -> (f32, f32) { + let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero // from game programming gems 4, chapter 1.10 @@ -161,6 +162,7 @@ impl SmoothDampMax for f64 { smooth_time: f32, delta_time: f32, ) -> (f64, f64) { + let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero let smooth_time = f64::max(smooth_time as f64, 0.0001); // ensure smooth_time is positive and non-zero let delta_time = delta_time as f64; @@ -193,7 +195,8 @@ impl SmoothDampMax for Vec2 { smooth_time: f32, delta_time: f32, ) -> (Vec2, Vec2) { - let smooth_time = f32::max(smooth_time as f32, 0.0001); // ensure smooth_time is positive and non-zero + let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero + let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero let delta_time = delta_time as f32; // from game programming gems 4, chapter 1.10 @@ -224,6 +227,7 @@ impl SmoothDampMax for Vec3 { smooth_time: f32, delta_time: f32, ) -> (Vec3, Vec3) { + let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero let smooth_time = f32::max(smooth_time as f32, 0.0001); // ensure smooth_time is positive and non-zero let delta_time = delta_time as f32; From b74ae4f1cc261601bb1861d32aa8c69a74563f4e Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 01:08:17 +0200 Subject: [PATCH 09/22] removed needless casts --- crates/bevy_math/src/smooth.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index b929dda51bcbc..7295b1d4bc638 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -197,7 +197,6 @@ impl SmoothDampMax for Vec2 { ) -> (Vec2, Vec2) { let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero - let delta_time = delta_time as f32; // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; @@ -228,8 +227,7 @@ impl SmoothDampMax for Vec3 { delta_time: f32, ) -> (Vec3, Vec3) { let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero - let smooth_time = f32::max(smooth_time as f32, 0.0001); // ensure smooth_time is positive and non-zero - let delta_time = delta_time as f32; + let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; From f685e66aea676cad11c7a28338146b7085a009ef Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 01:09:48 +0200 Subject: [PATCH 10/22] removed unnecessary variable --- crates/bevy_math/src/smooth.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 7295b1d4bc638..a1cad0f90e954 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -140,9 +140,8 @@ impl SmoothDampMax for f32 { let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - let change = from - to; let max = max_speed * delta_time; - let change = f32::clamp(change, -max, max); + let change = f32::clamp(from - to, -max, max); let temp = (velocity + omega * change) * delta_time; @@ -173,9 +172,8 @@ impl SmoothDampMax for f64 { let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - let change = from - to; let max = (max_speed as f64) * delta_time; - let change = f64::clamp(change, -max, max); + let change = f64::clamp(from - to, -max, max); let temp = (velocity + omega * change) * delta_time; From a060a0df5e08fa27ceb561bd97c862043511a965 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 01:41:53 +0200 Subject: [PATCH 11/22] macros to avoid code duplication --- crates/bevy_math/src/smooth.rs | 303 +++++++++++---------------------- 1 file changed, 104 insertions(+), 199 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index a1cad0f90e954..5abf8885aa36f 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -18,89 +18,42 @@ pub trait SmoothDamp { Self: Sized; } -impl SmoothDamp for f32 { - fn smooth_damp( - from: f32, - to: f32, - velocity: f32, - smooth_time: f32, - delta_time: f32, - ) -> (f32, f32) { - let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero - - // from game programming gems 4, chapter 1.10 - let omega = 2.0 / smooth_time; - let x = omega * delta_time; - - let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); - // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - - let change = from - to; - let temp = (velocity + omega * change) * delta_time; - - ( - to + (change + temp) * exp, // position - (velocity - omega * temp) * exp, // velocity - ) +macro_rules! impl_smooth_damp_scalar { + ($t:ty, $f:ty) => { + impl SmoothDamp for $t { + fn smooth_damp( + from: $t, + to: $t, + velocity: $t, + smooth_time: f32, + delta_time: f32, + ) -> ($t, $t) { + let smooth_time = <$f>::max(smooth_time as $f, 0.0001); // ensure smooth_time is positive and non-zero + let delta_time = delta_time as $f; + + // from game programming gems 4, chapter 1.10 + let omega = 2.0 / smooth_time; + let x = omega * delta_time; + + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); + // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + + let change = from - to; + let temp = (velocity + omega * change) * delta_time; + + ( + to + (change + temp) * exp, // position + (velocity - omega * temp) * exp, // velocity + ) + } + } } } -impl SmoothDamp for f64 { - fn smooth_damp( - from: f64, - to: f64, - velocity: f64, - smooth_time: f32, - delta_time: f32, - ) -> (f64, f64) { - let smooth_time = f64::max(smooth_time as f64, 0.0001); // ensure smooth_time is positive and non-zero - let delta_time = delta_time as f64; - - // from game programming gems 4, chapter 1.10 - let omega = 2.0 / smooth_time; - let x = omega * delta_time; - - let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); - // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - - let change = from - to; - let temp = (velocity + omega * change) * delta_time; - - ( - to + (change + temp) * exp, // position - (velocity - omega * temp) * exp, // velocity - ) - } -} - -impl SmoothDamp for Vec2 { - fn smooth_damp( - from: Vec2, - to: Vec2, - velocity: Vec2, - smooth_time: f32, - delta_time: f32, - ) -> (Vec2, Vec2) { - let (x, vx) = f32::smooth_damp(from.x, to.x, velocity.x, smooth_time, delta_time); - let (y, vy) = f32::smooth_damp(from.y, to.y, velocity.y, smooth_time, delta_time); - (Vec2::new(x, y), Vec2::new(vx, vy)) - } -} - -impl SmoothDamp for Vec3 { - fn smooth_damp( - from: Vec3, - to: Vec3, - velocity: Vec3, - smooth_time: f32, - delta_time: f32, - ) -> (Vec3, Vec3) { - let (x, vx) = f32::smooth_damp(from.x, to.x, velocity.x, smooth_time, delta_time); - let (y, vy) = f32::smooth_damp(from.y, to.y, velocity.y, smooth_time, delta_time); - let (z, vz) = f32::smooth_damp(from.z, to.z, velocity.z, smooth_time, delta_time); - (Vec3::new(x, y, z), Vec3::new(vx, vy, vz)) - } -} +impl_smooth_damp_scalar! {f32, f32} +impl_smooth_damp_scalar! {f64, f64} +impl_smooth_damp_scalar! {Vec2, f32} +impl_smooth_damp_scalar! {Vec3, f32} /// Smooths value to a goal using a damped spring limited by a maximum speed. pub trait SmoothDampMax { @@ -121,127 +74,79 @@ pub trait SmoothDampMax { Self: Sized; } -impl SmoothDampMax for f32 { - fn smooth_damp_max( - from: f32, - to: f32, - velocity: f32, - max_speed: f32, - smooth_time: f32, - delta_time: f32, - ) -> (f32, f32) { - let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero - let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero - - // from game programming gems 4, chapter 1.10 - let omega = 2.0 / smooth_time; - let x = omega * delta_time; - - let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); - // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - - let max = max_speed * delta_time; - let change = f32::clamp(from - to, -max, max); - - let temp = (velocity + omega * change) * delta_time; - - ( - to + (change + temp) * exp, // position - (velocity - omega * temp) * exp, // velocity - ) - } -} - -impl SmoothDampMax for f64 { - fn smooth_damp_max( - from: f64, - to: f64, - velocity: f64, - max_speed: f32, - smooth_time: f32, - delta_time: f32, - ) -> (f64, f64) { - let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero - let smooth_time = f64::max(smooth_time as f64, 0.0001); // ensure smooth_time is positive and non-zero - let delta_time = delta_time as f64; - - // from game programming gems 4, chapter 1.10 - let omega = 2.0 / smooth_time; - let x = omega * delta_time; - - let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); - // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - - let max = (max_speed as f64) * delta_time; - let change = f64::clamp(from - to, -max, max); - - let temp = (velocity + omega * change) * delta_time; - - ( - to + (change + temp) * exp, // position - (velocity - omega * temp) * exp, // velocity - ) +macro_rules! impl_smooth_damp_max_scalar { + ($t:ty) => { + impl SmoothDampMax for $t { + fn smooth_damp_max( + from: $t, + to: $t, + velocity: $t, + max_speed: f32, + smooth_time: f32, + delta_time: f32, + ) -> ($t, $t) { + let max_speed = <$t>::max(max_speed as $t, 0.0001); // ensure max speed is positive and non-zero + let smooth_time = <$t>::max(smooth_time as $t, 0.0001); // ensure smooth_time is positive and non-zero + let delta_time = delta_time as $t; + + // from game programming gems 4, chapter 1.10 + let omega = 2.0 / smooth_time; + let x = omega * delta_time; + + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); + // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + + let max = max_speed * delta_time; + let change = <$t>::clamp(from - to, -max, max); + + let temp = (velocity + omega * change) * delta_time; + + ( + to + (change + temp) * exp, // position + (velocity - omega * temp) * exp, // velocity + ) + } + } } } -impl SmoothDampMax for Vec2 { - fn smooth_damp_max( - from: Vec2, - to: Vec2, - velocity: Vec2, - max_speed: f32, - smooth_time: f32, - delta_time: f32, - ) -> (Vec2, Vec2) { - let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero - let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero - - // from game programming gems 4, chapter 1.10 - let omega = 2.0 / smooth_time; - let x = omega * delta_time; - - let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); - // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - - let max = max_speed * delta_time; - let change = (from - to).clamp_length_max(max); - - let temp = (velocity + omega * change) * delta_time; - - ( - to + (change + temp) * exp, // position - (velocity - omega * temp) * exp, // velocity - ) - } +impl_smooth_damp_max_scalar!{f32} +impl_smooth_damp_max_scalar!{f64} + +macro_rules! impl_smooth_damp_max_vec { + ($t:ty) => { + impl SmoothDampMax for $t { + fn smooth_damp_max( + from: $t, + to: $t, + velocity: $t, + max_speed: f32, + smooth_time: f32, + delta_time: f32, + ) -> ($t, $t) { + let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero + let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero + + // from game programming gems 4, chapter 1.10 + let omega = 2.0 / smooth_time; + let x = omega * delta_time; + + let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); + // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + + let max = max_speed * delta_time; + let change = (from - to).clamp_length_max(max); + + let temp = (velocity + omega * change) * delta_time; + + ( + to + (change + temp) * exp, // position + (velocity - omega * temp) * exp, // velocity + ) + } + } + }; } -impl SmoothDampMax for Vec3 { - fn smooth_damp_max( - from: Vec3, - to: Vec3, - velocity: Vec3, - max_speed: f32, - smooth_time: f32, - delta_time: f32, - ) -> (Vec3, Vec3) { - let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero - let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero - - // from game programming gems 4, chapter 1.10 - let omega = 2.0 / smooth_time; - let x = omega * delta_time; - - let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); - // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - - let max = max_speed * delta_time; - let change = (from - to).clamp_length_max(max); - - let temp = (velocity + omega * change) * delta_time; - - ( - to + (change + temp) * exp, // position - (velocity - omega * temp) * exp, // velocity - ) - } -} +impl_smooth_damp_max_vec! {Vec2} +impl_smooth_damp_max_vec! {Vec3} From e54efb34be32d1dbaee935c166c804bc185c54e8 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 01:42:01 +0200 Subject: [PATCH 12/22] export smooth damp max in prelude --- crates/bevy_math/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_math/src/lib.rs b/crates/bevy_math/src/lib.rs index 16c771ca10fe6..2c2da17a7af4c 100644 --- a/crates/bevy_math/src/lib.rs +++ b/crates/bevy_math/src/lib.rs @@ -10,6 +10,6 @@ pub use smooth::*; pub mod prelude { pub use crate::{ BVec2, BVec3, BVec4, FaceToward, IVec2, IVec3, IVec4, Mat3, Mat4, Quat, Rect, Size, - SmoothDamp, UVec2, UVec3, UVec4, Vec2, Vec3, Vec4, + SmoothDamp, SmoothDampMax, UVec2, UVec3, UVec4, Vec2, Vec3, Vec4, }; } From 5755ffd706ab96337c4e4b19f873013afe098ef5 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 01:42:36 +0200 Subject: [PATCH 13/22] format --- crates/bevy_math/src/smooth.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 5abf8885aa36f..179d1322b2bd8 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -47,7 +47,7 @@ macro_rules! impl_smooth_damp_scalar { ) } } - } + }; } impl_smooth_damp_scalar! {f32, f32} @@ -107,11 +107,11 @@ macro_rules! impl_smooth_damp_max_scalar { ) } } - } + }; } -impl_smooth_damp_max_scalar!{f32} -impl_smooth_damp_max_scalar!{f64} +impl_smooth_damp_max_scalar! {f32} +impl_smooth_damp_max_scalar! {f64} macro_rules! impl_smooth_damp_max_vec { ($t:ty) => { From ece16673a88670b3150370f312bd6b0d14058b83 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 01:55:57 +0200 Subject: [PATCH 14/22] more macros for even less code duplication --- crates/bevy_math/src/smooth.rs | 56 ++++++---------------------------- 1 file changed, 10 insertions(+), 46 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 179d1322b2bd8..c6b0f951a4aac 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -74,8 +74,8 @@ pub trait SmoothDampMax { Self: Sized; } -macro_rules! impl_smooth_damp_max_scalar { - ($t:ty) => { +macro_rules! impl_smooth_damp_max { + ($t:ty, $f:ty, $clamp:expr) => { impl SmoothDampMax for $t { fn smooth_damp_max( from: $t, @@ -85,47 +85,9 @@ macro_rules! impl_smooth_damp_max_scalar { smooth_time: f32, delta_time: f32, ) -> ($t, $t) { - let max_speed = <$t>::max(max_speed as $t, 0.0001); // ensure max speed is positive and non-zero - let smooth_time = <$t>::max(smooth_time as $t, 0.0001); // ensure smooth_time is positive and non-zero - let delta_time = delta_time as $t; - - // from game programming gems 4, chapter 1.10 - let omega = 2.0 / smooth_time; - let x = omega * delta_time; - - let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); - // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - - let max = max_speed * delta_time; - let change = <$t>::clamp(from - to, -max, max); - - let temp = (velocity + omega * change) * delta_time; - - ( - to + (change + temp) * exp, // position - (velocity - omega * temp) * exp, // velocity - ) - } - } - }; -} - -impl_smooth_damp_max_scalar! {f32} -impl_smooth_damp_max_scalar! {f64} - -macro_rules! impl_smooth_damp_max_vec { - ($t:ty) => { - impl SmoothDampMax for $t { - fn smooth_damp_max( - from: $t, - to: $t, - velocity: $t, - max_speed: f32, - smooth_time: f32, - delta_time: f32, - ) -> ($t, $t) { - let max_speed = f32::max(max_speed, 0.0001); // ensure max speed is positive and non-zero - let smooth_time = f32::max(smooth_time, 0.0001); // ensure smooth_time is positive and non-zero + let max_speed = <$f>::max(max_speed as $f, 0.0001); // ensure max speed is positive and non-zero + let smooth_time = <$f>::max(smooth_time as $f, 0.0001); // ensure smooth_time is positive and non-zero + let delta_time = delta_time as $f; // from game programming gems 4, chapter 1.10 let omega = 2.0 / smooth_time; @@ -135,7 +97,7 @@ macro_rules! impl_smooth_damp_max_vec { // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release let max = max_speed * delta_time; - let change = (from - to).clamp_length_max(max); + let change = $clamp(from, to, max); //<$t>::clamp(from - to, -max, max); let temp = (velocity + omega * change) * delta_time; @@ -148,5 +110,7 @@ macro_rules! impl_smooth_damp_max_vec { }; } -impl_smooth_damp_max_vec! {Vec2} -impl_smooth_damp_max_vec! {Vec3} +impl_smooth_damp_max! {f32, f32, |from, to, max:f32| { f32::clamp(from - to, -max, max) }} +impl_smooth_damp_max! {f64, f64, |from, to, max:f64| { f64::clamp(from - to, -max, max) }} +impl_smooth_damp_max! {Vec2, f32, |from:Vec2, to, max| { (from - to).clamp_length_max(max)}} +impl_smooth_damp_max! {Vec3, f32, |from:Vec3, to, max| { (from - to).clamp_length_max(max)}} From 19ed7e4d432039a048c2969361ccd64466cffda1 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 02:38:01 +0200 Subject: [PATCH 15/22] fixed smooth_damp_max and simplified its macro --- crates/bevy_math/src/smooth.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index c6b0f951a4aac..21bbd686ad407 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -18,7 +18,7 @@ pub trait SmoothDamp { Self: Sized; } -macro_rules! impl_smooth_damp_scalar { +macro_rules! impl_smooth_damp { ($t:ty, $f:ty) => { impl SmoothDamp for $t { fn smooth_damp( @@ -50,10 +50,10 @@ macro_rules! impl_smooth_damp_scalar { }; } -impl_smooth_damp_scalar! {f32, f32} -impl_smooth_damp_scalar! {f64, f64} -impl_smooth_damp_scalar! {Vec2, f32} -impl_smooth_damp_scalar! {Vec3, f32} +impl_smooth_damp! {f32, f32} +impl_smooth_damp! {f64, f64} +impl_smooth_damp! {Vec2, f32} +impl_smooth_damp! {Vec3, f32} /// Smooths value to a goal using a damped spring limited by a maximum speed. pub trait SmoothDampMax { @@ -96,8 +96,10 @@ macro_rules! impl_smooth_damp_max { let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release - let max = max_speed * delta_time; - let change = $clamp(from, to, max); //<$t>::clamp(from - to, -max, max); + let max = max_speed * smooth_time; + let change = from - to; + let change = $clamp(change, max); + let to = from - change; let temp = (velocity + omega * change) * delta_time; @@ -110,7 +112,7 @@ macro_rules! impl_smooth_damp_max { }; } -impl_smooth_damp_max! {f32, f32, |from, to, max:f32| { f32::clamp(from - to, -max, max) }} -impl_smooth_damp_max! {f64, f64, |from, to, max:f64| { f64::clamp(from - to, -max, max) }} -impl_smooth_damp_max! {Vec2, f32, |from:Vec2, to, max| { (from - to).clamp_length_max(max)}} -impl_smooth_damp_max! {Vec3, f32, |from:Vec3, to, max| { (from - to).clamp_length_max(max)}} +impl_smooth_damp_max! {f32, f32, |change, max:f32| { f32::clamp(change, -max, max) }} +impl_smooth_damp_max! {f64, f64, |change, max:f64| { f64::clamp(change, -max, max) }} +impl_smooth_damp_max! {Vec2, f32, |change:Vec2, max| { change.clamp_length_max(max) }} +impl_smooth_damp_max! {Vec3, f32, |change:Vec3, max| { change.clamp_length_max(max) }} From 745b36872c34d20cffc403ba6d953881cb31ce90 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 09:47:51 +0200 Subject: [PATCH 16/22] use faster exponential approximation --- crates/bevy_math/src/smooth.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 21bbd686ad407..07e6d59f5c343 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -35,8 +35,8 @@ macro_rules! impl_smooth_damp { let omega = 2.0 / smooth_time; let x = omega * delta_time; - let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); - // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + // fast and good enough approximation of exp(x) + let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); let change = from - to; let temp = (velocity + omega * change) * delta_time; @@ -93,8 +93,8 @@ macro_rules! impl_smooth_damp_max { let omega = 2.0 / smooth_time; let x = omega * delta_time; - let exp = 1.0 / (1.0 + x + 0.48 * x * x + 0.235 * x * x * x); - // let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); // TODO: profile me, both in debug & release + // fast and good enough approximation of exp(x) + let exp = 1.0 / (1.0 + x * (1.0 + x * (0.48 + 0.235 * x))); let max = max_speed * smooth_time; let change = from - to; From 687e47a604188a0cf65eda32d0d087c2d42457f5 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 10:29:01 +0200 Subject: [PATCH 17/22] added doc example --- crates/bevy_math/src/smooth.rs | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 07e6d59f5c343..a03e3d4036ab5 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -7,6 +7,46 @@ pub trait SmoothDamp { /// `smooth_time` is the expected time to reach the target when at maximum velocity. /// /// Returns smoothed value and new velocity. + /// + /// # Example + /// ``` + /// #[doc(hidden)] + /// use bevy_math::prelude::{Vec3, Quat}; + /// use bevy_math::SmoothDamp; + /// + /// struct SmoothTransform { + /// smoothness: f32, + /// target: Vec3, + /// velocity: Vec3 + /// } + /// + /// struct Transform { + /// translation: Vec3, + /// rotation: Quat, + /// scale: Vec3 + /// } + /// + /// fn smooth_transform_update(dt: f32, transform: &mut Transform, smoother: &mut SmoothTransform) { + /// let (p, v) = Vec3::smooth_damp( + /// transform.translation, + /// smoother.target, + /// smoother.velocity, + /// smoother.smoothness, + /// dt, + /// ); + /// transform.translation = p; + /// smoother.velocity = v; + /// // When destructured assignement will be supported by Rust: + /// // (transform.translation, smoother.velocity) = + /// // Vec3::smooth_damp( + /// // transform.translation, + /// // smoother.target, + /// // smoother.velocity, + /// // smoother.smoothness, + /// // dt, + /// // ); + /// } + /// ``` fn smooth_damp( from: Self, to: Self, From 24b0b2f1640b9d273a77735dba066feac0898829 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 10:29:41 +0200 Subject: [PATCH 18/22] format... --- crates/bevy_math/src/smooth.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index a03e3d4036ab5..c3bccbfa9a6ce 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -30,8 +30,8 @@ pub trait SmoothDamp { /// let (p, v) = Vec3::smooth_damp( /// transform.translation, /// smoother.target, - /// smoother.velocity, - /// smoother.smoothness, + /// smoother.velocity, + /// smoother.smoothness, /// dt, /// ); /// transform.translation = p; @@ -39,7 +39,7 @@ pub trait SmoothDamp { /// // When destructured assignement will be supported by Rust: /// // (transform.translation, smoother.velocity) = /// // Vec3::smooth_damp( - /// // transform.translation, + /// // transform.translation, /// // smoother.target, /// // smoother.velocity, /// // smoother.smoothness, From 3397f2650e13576a67a0ae89bfd4c3b8ec1cc8aa Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 11:34:32 +0200 Subject: [PATCH 19/22] properly hide example boilerplate --- crates/bevy_math/src/smooth.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index c3bccbfa9a6ce..04b752d7d9c51 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -10,22 +10,19 @@ pub trait SmoothDamp { /// /// # Example /// ``` - /// #[doc(hidden)] - /// use bevy_math::prelude::{Vec3, Quat}; - /// use bevy_math::SmoothDamp; - /// + /// # use bevy_math::prelude::{Vec3, Quat}; + /// # use bevy_math::SmoothDamp; + /// # struct Transform { + /// # translation: Vec3, + /// # rotation: Quat, + /// # scale: Vec3 + /// # } /// struct SmoothTransform { /// smoothness: f32, /// target: Vec3, /// velocity: Vec3 /// } /// - /// struct Transform { - /// translation: Vec3, - /// rotation: Quat, - /// scale: Vec3 - /// } - /// /// fn smooth_transform_update(dt: f32, transform: &mut Transform, smoother: &mut SmoothTransform) { /// let (p, v) = Vec3::smooth_damp( /// transform.translation, From 4331defaac0f0e4f874f3d34318c6f8564a34355 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 11:35:56 +0200 Subject: [PATCH 20/22] make example parameters public --- crates/bevy_math/src/smooth.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 04b752d7d9c51..496cb6e257c88 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -18,9 +18,9 @@ pub trait SmoothDamp { /// # scale: Vec3 /// # } /// struct SmoothTransform { - /// smoothness: f32, - /// target: Vec3, - /// velocity: Vec3 + /// pub smoothness: f32, + /// pub target: Vec3, + /// velocity: Vec3 /// } /// /// fn smooth_transform_update(dt: f32, transform: &mut Transform, smoother: &mut SmoothTransform) { From e4d42ad4ec83d98182d6a735a61396936055dfd1 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 20:22:56 +0200 Subject: [PATCH 21/22] replaced maxs with asserts on inputs --- crates/bevy_math/src/smooth.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 496cb6e257c88..3f0e137c1cb08 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -65,7 +65,9 @@ macro_rules! impl_smooth_damp { smooth_time: f32, delta_time: f32, ) -> ($t, $t) { - let smooth_time = <$f>::max(smooth_time as $f, 0.0001); // ensure smooth_time is positive and non-zero + assert!(smooth_time > 0.0); + let smooth_time = smooth_time as $f; + let delta_time = delta_time as $f; // from game programming gems 4, chapter 1.10 @@ -122,8 +124,12 @@ macro_rules! impl_smooth_damp_max { smooth_time: f32, delta_time: f32, ) -> ($t, $t) { - let max_speed = <$f>::max(max_speed as $f, 0.0001); // ensure max speed is positive and non-zero - let smooth_time = <$f>::max(smooth_time as $f, 0.0001); // ensure smooth_time is positive and non-zero + assert!(max_speed > 0.0); + let max_speed = max_speed as $f; + + assert!(smooth_time > 0.0); + let smooth_time = smooth_time as $f; + let delta_time = delta_time as $f; // from game programming gems 4, chapter 1.10 From 71ab2089c04fbd87ba5f72d4d3d73ecc71f36313 Mon Sep 17 00:00:00 2001 From: Daniel Borges Date: Tue, 27 Apr 2021 20:27:44 +0200 Subject: [PATCH 22/22] document panics + SmoothDampMax example --- crates/bevy_math/src/smooth.rs | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/crates/bevy_math/src/smooth.rs b/crates/bevy_math/src/smooth.rs index 3f0e137c1cb08..51d398d9d1ce0 100644 --- a/crates/bevy_math/src/smooth.rs +++ b/crates/bevy_math/src/smooth.rs @@ -8,6 +8,9 @@ pub trait SmoothDamp { /// /// Returns smoothed value and new velocity. /// + /// # Panics + /// Panics if `smooth_time <= 0.0`. + /// /// # Example /// ``` /// # use bevy_math::prelude::{Vec3, Quat}; @@ -101,6 +104,49 @@ pub trait SmoothDampMax { /// `smooth_time` is the expected time to reach the target when at maximum velocity. /// /// Returns smoothed value and new velocity. + /// + /// # Panics + /// Panics if `smooth_time <= 0.0` or `max_speed <= 0.0`. + /// + /// # Example + /// ``` + /// # use bevy_math::prelude::{Vec3, Quat}; + /// # use bevy_math::SmoothDampMax; + /// # struct Transform { + /// # translation: Vec3, + /// # rotation: Quat, + /// # scale: Vec3 + /// # } + /// struct SmoothTransform { + /// pub smoothness: f32, + /// pub max_speed: f32, + /// pub target: Vec3, + /// velocity: Vec3 + /// } + /// + /// fn smooth_transform_update(dt: f32, transform: &mut Transform, smoother: &mut SmoothTransform) { + /// let (p, v) = Vec3::smooth_damp_max( + /// transform.translation, + /// smoother.target, + /// smoother.velocity, + /// smoother.max_speed, + /// smoother.smoothness, + /// dt, + /// ); + /// transform.translation = p; + /// smoother.velocity = v; + /// // When destructured assignement will be supported by Rust: + /// // (transform.translation, smoother.velocity) = + /// // Vec3::smooth_damp_max( + /// // transform.translation, + /// // smoother.target, + /// // smoother.velocity, + /// // smoother.max_speed, + /// // smoother.smoothness, + /// // dt, + /// // ); + /// } + /// ``` fn smooth_damp_max( from: Self, to: Self,