Skip to content

Instantly share code, notes, and snippets.

@cecilemuller
Last active February 16, 2023 13:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cecilemuller/ba5746cfe2ee659a23329193a89880d5 to your computer and use it in GitHub Desktop.
Save cecilemuller/ba5746cfe2ee659a23329193a89880d5 to your computer and use it in GitHub Desktop.
Swift Dampers
import simd
// Interpolate a Quaternion without specifying duration, in the style of Herbert Stocker's X3D OrientationDamper:
// https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/sai/Followers/OrientationDamper.html
class OrientationDamper {
private(set) var isActive: Bool = false
private(set) var value: simd_quatf
private(set) var destination: simd_quatf
private(set) var tau: Float
private(set) var tolerance: Float
init(value: simd_quatf = .init(), tau: Float = 1.0, tolerance: Float = 0.0005) {
let normalized = value.normalized
self.value = normalized
self.destination = normalized
self.tau = tau
self.tolerance = tolerance
}
func animate(to: simd_quatf) {
destination = to.normalized
isActive = (value != destination)
}
func animate(from: simd_quatf, to: simd_quatf) {
value = from.normalized
destination = to.normalized
isActive = (value != destination)
}
func tick(delta: Float) {
let newValue = simd_slerp(destination, value, exp(-delta / tau))
if abs((newValue.inverse * value).angle) < tolerance {
isActive = false
value = destination
} else {
value = newValue
}
}
}
import simd
// Interpolate a Float3 without specifying duration, in the style of Herbert Stocker's X3D PositionDamper:
// https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/sai/Followers/PositionDamper.html
class PositionDamper {
private(set) var isActive: Bool = false
private(set) var value: simd_float3
private(set) var destination: simd_float3
private(set) var tau: Float
private(set) var tolerance: Float
init(value: simd_float3 = .init(), tau: Float = 1.0, tolerance: Float = 0.001) {
self.value = value
self.destination = value
self.tau = tau
self.tolerance = tolerance
}
func animate(to: simd_float3) {
destination = to
isActive = (value != destination)
}
func animate(from: simd_float3, to: simd_float3) {
value = from
destination = to
isActive = (value != destination)
}
func tick(delta: Float) {
let newValue = destination + (value - destination) * exp(-delta / tau)
let tmp = abs(newValue - destination)
if (tmp.x < tolerance) && (tmp.y < tolerance) && (tmp.z < tolerance) {
isActive = false
value = destination
} else {
value = newValue
}
}
}
import simd
// Interpolate a Float without specifying duration, in the style of Herbert Stocker's X3D ScalarDamper:
// https://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/sai/Followers/ScalarDamper.html
class ScalarDamper {
private(set) var isActive: Bool = false
private(set) var value: Float
private(set) var destination: Float
private(set) var tau: Float
private(set) var tolerance: Float
init(value: Float = 0, tau: Float = 1.0, tolerance: Float = 0.001) {
self.value = value
self.destination = value
self.tau = tau
self.tolerance = tolerance
}
func animate(to: Float) {
destination = to
isActive = (value != destination)
}
func animate(from: Float, to: Float) {
value = from
destination = to
isActive = (value != destination)
}
func tick(delta: Float) {
let newValue = destination + (value - destination) * exp(-delta / tau)
if abs(newValue - destination) < tolerance {
isActive = false
value = destination
} else {
value = newValue
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment