Skip to content

Instantly share code, notes, and snippets.

@matthewreagan
Created June 15, 2020 20:28
Show Gist options
  • Save matthewreagan/491e950fe85ce356560e98a7001dad09 to your computer and use it in GitHub Desktop.
Save matthewreagan/491e950fe85ce356560e98a7001dad09 to your computer and use it in GitHub Desktop.
SceneKit Quaternion from Axis + Angle
import SceneKit
extension SCNVector3 {
func normalized() -> SCNVector3 {
let magnitude = ((self.x * self.x) + (self.y * self.y) + (self.z * self.z)).squareRoot()
return SCNVector3(self.x / magnitude, self.y / magnitude, self.z / magnitude)
}
}
func QuaternionFromAxisAngle(_ inAxis: SCNVector3, radians: CGFloat) -> SCNQuaternion {
// See:
// https://www.youtube.com/watch?v=zjMuIxRvygQ
// http://sacredsoftware.net/tutorials/quaternion.html
// For a better explanation as to why the angle is halved, see:
// https://eater.net/quaternions/
let halfAngle = radians * 0.5
let sinAngle: CGFloat = sin(halfAngle)
let axis = inAxis.normalized()
// Recall that a quaternion can be expressed as:
// cos(angle) + sin(angle) * (x + y + z)
// Which expands to:
// cos(a) + sin(a)x + sin(a)y + sin(a)z
// The cos(a) is our real component (W)
return SCNQuaternion(x: axis.x * sinAngle,
y: axis.y * sinAngle,
z: axis.z * sinAngle,
w: cos(halfAngle))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment