Jump to content
Search Community

threeJS object rotation trough rotateY instead of rotation

Houseofdreams test
Moderator Tag

Go to solution Solved by akapowl,

Recommended Posts

Hi. I have a 3D object, made in blender,exported as glb and imported in ThreeJS, that has to rotate on it's local axis, instead of the global axis.  ( local/global axis, coming from blender)

 

I tried using object.rotation as follows:

 

GSAP.to(this.object.model.children[0].rotation, {
                duration: 3,
                y:  3
            });

 

This way, it rotates around the global axis, the wrong way. In ThreeJS, you can also use the object.rotateY  function, but I cannot seem to get it to work with GSAP.

If I use the following example, it rotates correctly around the Y axis, but "locally"

 

this.object.model.children[0].rotateY(1)

 

Anyone know the correct code to use rotateY with GSAP, or is this not possible?

 

Kind regards

 

Link to comment
Share on other sites

Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependancies as possible. Start minimal and then incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen

that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import the gsap-trial NPM package for using any of the bonus plugins: 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

If we can see the code in action it will be much easier to see what is going on. The Codepen window is as big as you make it, you can even view it in de debug view which gets you the full webpage. 

 

GSAP has a PixiJS  plugin https://gsap.com/docs/v3/Plugins/PixiPlugin/ are you using that? It should expose all the properties directly. Have you tried setting the rotationY in GSAP? Otherwise please provide a demo, so that we can take a look at your setup. Hope it helps and happy tweening! 

Link to comment
Share on other sites

  • Solution

TLDR:
At the bottom of the post you'll find an example for how you could approach it.
Nonetheless, I think reading through all this can help get a better understanding.

 

23 hours ago, Houseofdreams said:

Maybe I could ask this question on the ThreeJS forum instead?


I think that would definitely be the best way to go, if you want a solid answer - because what you are asking is heavily about how three.js works to begin with.

My attempt at a short answer would be: you can not easily do that in a way that it would logically work the same as e.g. changing the object.rotation.y does.

And here is why (please keep in mind that I am no full-fledged expert with three.js though):



While object.rotation.y (or x or z) is a 'property' of your 3D model that three.js gives you access to, you can easily set it - e.g. by tweening on it via GSAP.

object.geometry.rotateY() on the other hand is a method - it is a function you can execute on that object, where internally three.js will do all the work with the value provided by you. So for starters it is not a simple value you can easily manipulate via GSAP.

See the Pen ZEPgYLP by akapowl (@akapowl) on CodePen



As you can see in the codepen above, technically of course you can tween a value you set up on an object of your own via GSAP and onUpdate of that tween call that method provided by three.js  - but:
 

  • a) it will not work in the same way as tweening on the object.rotation.y in the same way would - because you are only providing a value to another pipeline (i.e. the rotateY method of three) which then again does different things with it. With some trickery around the tweening on the value you sure could settle on similar behaviour - but that would really be logic for you to figure out.

    Just for illustration purposes, here is that same tween (albeit with different numbers) on the object.rotation.y value to show how it behaves different.

    See the Pen vYPoNyq by akapowl (@akapowl) on CodePen



    Now in the first pen you could e.g. get a similar effect of yoyo-ing back and forth between the two values by simply using a linear ease or an ease that goes in and out - so you see it is not impossible to achieve similar behaviour. I'm just saying that because of that extra pipeline you'll have an extra layer of abstraction and complexity added to how you'll have to approach things, which would be all yours to figure out in the process.

    Still I wouldn't really recommend doing that though, because...
     
  • ...probably even more importantly b) You probably should not really consider doing that all that much to begin with. What three.js does under the hood of that method is to calculate the position of every single vertex of your model; as this answer on a stackoverflow post mentions:

    https://stackoverflow.com/questions/71506350/three-js-set-absolute-rotation-of-sphere-rather-than-cumulative-rotation#answer-71506597

    That can already be taxing with simple 3D shapes, but depending on the level of detail of your model(s) this can become rather hefty rather quickly.
     

 

You can certainly access and manipulate the values neccessary to do that in different ways in JS already - like e.g. by using three's BufferGeometry instead three's provided 'pre-made' geometries, but even then the calculations would be quite a bit  more complex than just setting one single value somewhere. And since you say you are loading a .glb model, that will very likely not be a way to go for you anyway.

Another way you could think about doing it would be to use a shader that you provide with a value you tween on via GSAP. That would probably be a whole lot better with regard to computation cost because you could outsource all the calculations based on that value to the GPU, but it would also be a whole new world you'd open up outside of JS - and the complexity of the calculations would still stand on top of that.

So yeah, depending on the level of control you want to have over what you're doing, personally - with my limited knowledge about three.js - I don't think what you are aiming to do is as easy as you might think. But maybe I'm totally off track somewehere here, and the folks over in the three.js forum can provide you with some better input and an easy solution.

If so, it would be great, if you'd post back here with what you found out. Good luck!

----

Edit:

Alright, I played around with it a bit now, and have now stumbled upon an oversight logic-wise, that has a huge effect on how things behave.


In the first example above, I am just providing the value I am tweening on to three's .rotateY method, which does cause the appearance of 'no control' because every tick I am basically telling three.js: 'add that value the tween is currently at to the rotation'. So along the tweens duration, the rotation would add up more and more and get vastly out of what I wanted it to be.

An easy way to fix that is to keep track of the rotation value in an extra variable that I called oldValue in the pen below. Now in the onUpdate callback, I subtract that oldValue from the value the tween is currently at when passing it to three's .rotateY method. And after that, I set this oldValue to the value the tween is currently at.

This way I can make sure that every tick only the difference between the previous tick and the current tick will get added to the rotation.

And now it behaves just like the example with tweening on the object.rotation.y does.

 

Note, that I am now also using three's built in MathUtils.degToRad, so instead of just some arbitrary values, I can work with to me far more familiar degrees instead of radians.


But for the aforementioned reasons with regard to it having huge potential for killing performance, I probably still wouldn't really recommend doing that. Maybe thiss will help you out, though.

See the Pen qBvebOB by akapowl (@akapowl) on CodePen


 

  • Like 1
Link to comment
Share on other sites

also since you are trying to animate a model I would add it to a group and animate the group, so you don't worry about the names or  axes or children order every time you export from blender

 

if you are using R3F you can easily just convert the glb file to a react component thanks to pmndrs and animate only the part you want instead of just importing the whole object and animating it 

  • Like 1
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...