321dev Posted May 5, 2021 Share Posted May 5, 2021 There are quite a few posts about this, but they're many years old, and many of them mention a plugin that can handle quaternions. What's the state today? Can GSAP tween quaternions, or do we still need a plugin? Specifically, i'd like to use interpolate() with three.js quaternions. (I know about three.js quaternion.slerp, but i need to interpolate over a dynamic number of values.) Link to comment Share on other sites More sharing options...
Cassie Posted May 5, 2021 Share Posted May 5, 2021 I don't have personal experience of this so I will bow out to anyone else that wants to help, but I didn't want to leave you hanging. I did a bit of googling and stumbled on this thread on the three.js discourse site - does this help at all?https://discourse.threejs.org/t/interpolate-between-different-poses/15202/4https://jsfiddle.net/fqcs6epr/ 1 Link to comment Share on other sites More sharing options...
321dev Posted May 5, 2021 Author Share Posted May 5, 2021 14 minutes ago, Cassie said: I did a bit of googling and stumbled on this thread on the three.js discourse site - does this help at all? Thanks for your response, but unfortunately that does not help. Interpolating any linear values (like a 3D position) with GSAP is not a problem, but Quaternions can't be interpolated that way. The interpolating code must be aware of the meaning of the values. E.g. when you wanted to interpolate a rotation in degrees from 350 to 10, the code should go from 350...359..0...10, instead of going backwards from 350 to 10. 1 Link to comment Share on other sites More sharing options...
Cassie Posted May 5, 2021 Share Posted May 5, 2021 Ah, I see. I'm afraid I'm not going to be able to help here. Maybe @OSUblake or @Rodrigo will be able to help? Link to comment Share on other sites More sharing options...
elegantseagulls Posted May 5, 2021 Share Posted May 5, 2021 7 minutes ago, 321dev said: E.g. when you wanted to interpolate a rotation in degrees from 350 to 10, the code should go from 350...359..0...10, instead of going backwards from 350 to 10. This seems like it could be a good use case for gsap's modifiers. Like @Cassie I'm not super familiar with what you are trying to do... can you set up a basic CodePen of what GSAP should/could be tweening?https://greensock.com/docs/v3/GSAP/CorePlugins/ModifiersPlugin 3 Link to comment Share on other sites More sharing options...
Cassie Posted May 5, 2021 Share Posted May 5, 2021 Yeah, I'd love to see. I'm really fascinated by this. It sounds like crazy sci-fi tweening. Link to comment Share on other sites More sharing options...
321dev Posted May 5, 2021 Author Share Posted May 5, 2021 The modifiers might work, if i knew how to interpolate quaternions at low level - which i don't. For now, i'll try to use "normal" Euler rotations like i found here: See the Pen GRooLza by ste-vg (@ste-vg) on CodePen and see how it goes. Thanks for your help. 1 Link to comment Share on other sites More sharing options...
OSUblake Posted May 5, 2021 Share Posted May 5, 2021 8 hours ago, 321dev said: There are quite a few posts about this, but they're many years old, and many of them mention a plugin that can handle quaternions. What's the state today? Can GSAP tween quaternions, or do we still need a plugin? That's from the flash days. You should be able to just use onUpdate kind of like what shown here... although they are using Tween.js https://discourse.threejs.org/t/animating-quaternion-rotation/8015/12 1 Link to comment Share on other sites More sharing options...
OSUblake Posted May 5, 2021 Share Posted May 5, 2021 2 hours ago, 321dev said: E.g. when you wanted to interpolate a rotation in degrees from 350 to 10, the code should go from 350...359..0...10, instead of going backwards from 350 to 10. @GreenSock do you have some code for this? I can't find my demos that show this. 1 Link to comment Share on other sites More sharing options...
321dev Posted May 5, 2021 Author Share Posted May 5, 2021 10 minutes ago, OSUblake said: @GreenSock do you have some code for this? I can't find my demos that show this. That was just an example showing why the "normal" interpolation doesn't work with angles. I don't have code for this. Link to comment Share on other sites More sharing options...
OSUblake Posted May 5, 2021 Share Posted May 5, 2021 I know, that's why I tagged someone else 😉 Link to comment Share on other sites More sharing options...
321dev Posted May 5, 2021 Author Share Posted May 5, 2021 19 minutes ago, OSUblake said: You should be able to just use onUpdate kind of like what shown here... although they are using Tween.js https://discourse.threejs.org/t/animating-quaternion-rotation/8015/12 Yes, thanks. But as i mentioned in my OP, i know how to interpolate between two Quaternions using three.js method. But i need to interpolate between more values, but i don't think just interpolating between 0 and 1, then 1 and 2, etc. will give a smooth result. But maybe i should try it out and check how bad it looks. Link to comment Share on other sites More sharing options...
OSUblake Posted May 5, 2021 Share Posted May 5, 2021 What properties are you trying to animate? Do you have some psuedo code? 1 Link to comment Share on other sites More sharing options...
321dev Posted May 5, 2021 Author Share Posted May 5, 2021 45 minutes ago, OSUblake said: What properties are you trying to animate? Do you have some psuedo code? In an ideal world, i 'd like to use gsap.utils.interpolate like this: let q1 = new THREE.Quaternion() q1.setFromEuler(new THREE.Euler( THREE.Math.degToRad(0), THREE.Math.degToRad(45), THREE.Math.degToRad(0), 'XYZ' )) let q2 = new THREE.Quaternion() q2.setFromEuler(new THREE.Euler( THREE.Math.degToRad(45), THREE.Math.degToRad(0), THREE.Math.degToRad(90), 'XYZ' )) let q3 = new THREE.Quaternion() q3.setFromEuler(new THREE.Euler( THREE.Math.degToRad(90), THREE.Math.degToRad(90), THREE.Math.degToRad(90), 'XYZ' )) var interp = gsap.utils.interpolate([q1, q2, q3]); let qx = interp(0.3) Link to comment Share on other sites More sharing options...
OSUblake Posted May 5, 2021 Share Posted May 5, 2021 So using three.js's slerp is fine, you just need to interpolate an array of them? Would something like this work? const interp = interpolate([q1, q2, q3]); let qx = interp(0.3); function interpolate(targets) { const interpolators = []; let len = targets.length; const iLen = len - 2; const q = new THREE.Quaternion(); for (let i = 1; i < len; i++) { interpolators.push(slerp(targets[i - 1], targets[i], q)); } len--; return p => { p *= len; let i = Math.min(iLen, ~~p); return interpolators[i](p - i); } } function slerp(a, b, q) { return p => { // three.js slerp return q.slerpQuaternions(a, b, p); } } 1 Link to comment Share on other sites More sharing options...
321dev Posted May 5, 2021 Author Share Posted May 5, 2021 So this would first interpolate between items 0 and 1, then 1 and 2, and so on. That's what i planed to do, but i wasn't sure if the transitions were smooth (enough). I'll try it out tomorrow. BTW: Maybe gsap.utils.interpolate() could be expanded so that you could pass a custom function that interpolates between two elements? Thanks a lot for your time and effort! Link to comment Share on other sites More sharing options...
OSUblake Posted May 5, 2021 Share Posted May 5, 2021 1 minute ago, 321dev said: So this would first interpolate between items 0 and 1, then 1 and 2, and so on. Yep. 2 minutes ago, 321dev said: BTW: Maybe gsap.utils.interpolate() could be expanded so that you could pass a custom function that interpolates between two elements? That's not a bad idea. Any thoughts on this @GreenSock? Link to comment Share on other sites More sharing options...
OSUblake Posted May 5, 2021 Share Posted May 5, 2021 4 minutes ago, 321dev said: That's what i planed to do, but i wasn't sure if the transitions were smooth (enough). If it's not smooth, maybe make a simple demo so we can mess around and tweak it. Link to comment Share on other sites More sharing options...
GreenSock Posted May 5, 2021 Share Posted May 5, 2021 2 hours ago, OSUblake said: 3 hours ago, 321dev said: BTW: Maybe gsap.utils.interpolate() could be expanded so that you could pass a custom function that interpolates between two elements? That's not a bad idea. Any thoughts on this @GreenSock? An interpolator for an interpolator? I'm a little fuzzy on what exactly you mean here - got a sketch of an API and a sample use case? Link to comment Share on other sites More sharing options...
321dev Posted May 5, 2021 Author Share Posted May 5, 2021 18 minutes ago, GreenSock said: An interpolator for an interpolator? I'm a little fuzzy on what exactly you mean here - got a sketch of an API and a sample use case? The purpose is to enable gsap.utils.interpolate() to interpolate values it can't interpolate (correctly) otherwise, in my example a THREE.Quaternion Link to comment Share on other sites More sharing options...
GreenSock Posted May 5, 2021 Share Posted May 5, 2021 19 minutes ago, 321dev said: The purpose is to enable gsap.utils.interpolate() to interpolate values it can't interpolate (correctly) otherwise, in my example a THREE.Quaternion Ha ha - I figured that much. I'm asking about implementation details. What would this function look like exactly? How would it integrate with gsap.utils.interpolate()? Got pseudo code? Link to comment Share on other sites More sharing options...
OSUblake Posted May 5, 2021 Share Posted May 5, 2021 Maybe like this? const interp = interpolate([q1, q2, q3], (start, end, progress) => { // custom interpolation return ...; }); Link to comment Share on other sites More sharing options...
GreenSock Posted May 8, 2021 Share Posted May 8, 2021 On 5/5/2021 at 6:02 PM, OSUblake said: Maybe like this? const interp = interpolate([q1, q2, q3], (start, end, progress) => { // custom interpolation return ...; }); Yeah, I'm not seeing a very clean way of fitting that in there. It'd take a lot of extra code to accommodate, and it would definitely muddy the API - it already has 4 different method signatures; this would literally double that. I think for a situation like this, a custom plugin or an effect would be a more intuitive option. Or just a straight-up helper function like you suggested earlier. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now