1- use super :: { Basis , IsEqualApprox , Vector3 } ;
1+ use super :: { Basis , IsEqualApprox , Vector3 , CMP_EPSILON } ;
22use glam:: EulerRot ;
3- use std:: ops:: Mul ;
3+ use std:: ops:: { Mul , Neg } ;
44
55#[ derive( Copy , Clone , Debug , PartialEq ) ]
66#[ repr( C ) ]
@@ -119,7 +119,38 @@ impl Quat {
119119 pub fn slerp ( self , b : Self , t : f32 ) -> Self {
120120 debug_assert ! ( self . is_normalized( ) , "Quaternion `self` is not normalized" ) ;
121121 debug_assert ! ( b. is_normalized( ) , "Quaternion `b` is not normalized" ) ;
122- Self :: gd ( self . glam ( ) . lerp ( b. glam ( ) , t) )
122+
123+ // Copied from Godot's Quat::slerp as glam::lerp version diverges too much
124+
125+ // calc cosine
126+ let cosom = self . dot ( b) ;
127+
128+ // adjust signs (if necessary)
129+ let ( cosom, b) = if cosom < 0.0 {
130+ ( -cosom, -b)
131+ } else {
132+ ( cosom, b)
133+ } ;
134+
135+ // calculate coefficients
136+ let scale = if ( 1.0 - cosom) > CMP_EPSILON as f32 {
137+ // standard case (slerp)
138+ let omega = cosom. acos ( ) ;
139+ let sinom = omega. sin ( ) ;
140+ ( ( ( 1.0 - t) * omega) . sin ( ) / sinom, ( t * omega) . sin ( ) / sinom)
141+ } else {
142+ // "from" and "to" quaternions are very close
143+ // ... so we can do a linear interpolation
144+ ( 1.0 - t, t)
145+ } ;
146+
147+ // calculate final values
148+ Self :: new (
149+ scale. 0 * self . x + scale. 1 * b. x ,
150+ scale. 0 * self . y + scale. 1 * b. y ,
151+ scale. 0 * self . z + scale. 1 * b. z ,
152+ scale. 0 * self . w + scale. 1 * b. w ,
153+ )
123154 }
124155
125156 /// Returns the result of the spherical linear interpolation between this quaternion and `t` by
@@ -128,6 +159,9 @@ impl Quat {
128159 pub fn slerpni ( self , b : Self , t : f32 ) -> Self {
129160 debug_assert ! ( self . is_normalized( ) , "Quaternion `self` is not normalized" ) ;
130161 debug_assert ! ( b. is_normalized( ) , "Quaternion `b` is not normalized" ) ;
162+
163+ // Copied from Godot's Quat::slerpni as glam::slerp version diverges too much
164+
131165 let dot = self . dot ( b) ;
132166 if dot. abs ( ) > 0.9999 {
133167 self
@@ -172,6 +206,15 @@ impl Mul<Vector3> for Quat {
172206 }
173207}
174208
209+ impl Neg for Quat {
210+ type Output = Quat ;
211+
212+ #[ inline]
213+ fn neg ( self ) -> Self {
214+ Self :: gd ( -self . glam ( ) )
215+ }
216+ }
217+
175218#[ cfg( test) ]
176219mod test {
177220 use super :: * ;
0 commit comments