Jump to content
Search Community

Tweening three.js quaternions

321dev test
Moderator Tag

Recommended Posts

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

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.

 

 

 

  • Like 1
Link to comment
Share on other sites

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

  • Like 3
Link to comment
Share on other sites

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

 

 

  • Like 1
Link to comment
Share on other sites

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

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

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

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);
  }
}

 

  • Like 1
Link to comment
Share on other sites

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

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

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

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

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

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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...