gonum.org/v1/gonum@v0.15.1-0.20240517103525-f853624cb1bb/spatial/r3/slerp_example_test.go (about) 1 // Copyright ©2022 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package r3_test 6 7 import ( 8 "fmt" 9 "math" 10 11 "gonum.org/v1/gonum/num/quat" 12 "gonum.org/v1/gonum/spatial/r3" 13 ) 14 15 // slerp returns the spherical interpolation between q0 and q1 16 // for t in [0,1]; 0 corresponds to q0 and 1 corresponds to q1. 17 func slerp(r0, r1 r3.Rotation, t float64) r3.Rotation { 18 q0 := quat.Number(r0) 19 q1 := quat.Number(r1) 20 // Based on Simo Särkkä "Notes on Quaternions" Eq. 35 21 // p(t) = (q1 ∗ q0^−1) ^ t ∗ q0 22 // https://users.aalto.fi/~ssarkka/pub/quat.pdf 23 q1 = quat.Mul(q1, quat.Inv(q0)) 24 q1 = quat.PowReal(q1, t) 25 return r3.Rotation(quat.Mul(q1, q0)) 26 } 27 28 // Spherically interpolate between two quaternions to obtain a rotation. 29 func Example_slerp() { 30 const steps = 10 31 // An initial rotation of pi/4 around the x-axis (45 degrees). 32 initialRot := r3.NewRotation(math.Pi/4, r3.Vec{X: 1}) 33 // Final rotation is pi around the x-axis (180 degrees). 34 finalRot := r3.NewRotation(math.Pi, r3.Vec{X: 1}) 35 // The vector we are rotating is (1, 1, 1). 36 // The result should then be (1, -1, -1) when t=1 (finalRot) since we invert the y and z axes. 37 v := r3.Vec{X: 1, Y: 1, Z: 1} 38 for i := 0.0; i <= steps; i++ { 39 t := i / steps 40 rotated := slerp(initialRot, finalRot, t).Rotate(v) 41 fmt.Printf("%.2f %+.2f\n", t, rotated) 42 } 43 44 // Output: 45 // 46 // 0.00 {+1.00 -0.00 +1.41} 47 // 0.10 {+1.00 -0.33 +1.38} 48 // 0.20 {+1.00 -0.64 +1.26} 49 // 0.30 {+1.00 -0.92 +1.08} 50 // 0.40 {+1.00 -1.14 +0.83} 51 // 0.50 {+1.00 -1.31 +0.54} 52 // 0.60 {+1.00 -1.40 +0.22} 53 // 0.70 {+1.00 -1.41 -0.11} 54 // 0.80 {+1.00 -1.34 -0.44} 55 // 0.90 {+1.00 -1.21 -0.74} 56 // 1.00 {+1.00 -1.00 -1.00} 57 }