Drag to rotate an object in local space

I’d like to rotate an object along its local y axis based on the user’s dragged input. I’ve just spent about 6-8 hours trying to figure it out, but to no avail. I’ve love some pointers.

Here’s a bit of what I’ve tried so far:

  • Using a method similar to the tutorial about rotating an object with the mouse
    My first thought was to use the approach listed here. The problem with this is that since it’s pretty much mapping directly from mouse/touch dx/dy, it doesn’t translate into local space (at least not that I could figure out. For example, what if I’m at an odd angle to the object, and I want to rotate it around the y axis?

  • Using a method similar to a previous forum post about dragging an object (translation) in 3D space
    This doesn’t really work, at least from what I could figure out, because whereas for translation I can project along the object’s axis to get the distance, rotation doesn’t work the same. That is, dragging in a straight line along the x axis can kind of be used to calculate rotation if the camera is facing the object from the front , slightly above the ground. But what if the camera is above the object facing down? Then, to rotate the object around it’s y axis, the user shouldn’t need to drag in a straight line along the x axis. Rather, they’d expect to drag the object around in a circle.

I tried several other similar methods too, but nothing worth mentioning really.

Any ideas?

Do you want to rotate the object by having the user drag from screen left to right? Or do you want to rotate the object by having the user drag from the object’s left towards the object’s right?

If you want to do the first you can simply get the mouse dx, scale it by the desired sensitivity factor you want and then call something like entity.rotateLocal(0, dx * sensitivity, 0).

Hi @vaios, thanks for the input! That’s more or less the method used in the tutorial about rotating an object with the mouse. That works great if you’re using a fixed camera that is oriented so that it’s facing the object. I’ve included a few illustrations below that illustrate what I’d like to do. In short, I’d like the user to be able to drag their mouse at the angle that most intuitively will rotate the object along the local y axis (as opposed to mouse dx being mapped directly to y rotation). So, if viewing the object from a strange angle, the drag angle would certainly be an odd angle as well.

I can totally get by with the simpler method (straight line, aligned with the object to be dragged), but best case scenario would be the second method, which seems more intuitive to me.

METHOD 1: Simplest straight line drag angle

METHOD 2: Straight line if facing the object, circular if above

I’d love any input or ideas, I’m pretty stumped at this point.

EDIT:
Regarding the second method, I can totally see using the following method:

  1. Create a pc.Plane aligned with the rotate object
  2. Do a raycast on every frame during a rotation
  3. Get the hitpoint on the pc.Plane
  4. Figure out the angle between the hitpoint and the rotate object’s center (using Math.atan2)
  5. Use the angle to rotate the object

That seems like it would work great, except that if the plane is aligned with the rotate object, then you must neccesarily be looking “down” at the object in order for your raycast to hit the plane. If the camera is looking straight at the object (or worse, looking at it with a slight upwards tilt), the raycast won’t hit the plane at all and the effect will be lost.

This is pretty tricky as how would you know which axis the user is trying to manipulate based on their drag direction. In the first image of the orange cube, the user could just as easily be trying to rotate around one of the other axis:

Unless the requirement is to only rotate around the local Y axis no matter what.

Thanks for the input @yaustar and @vaios! vaios is right, I’d like to make it only rotate around the y axis no matter what. Both other axes will be locked.

In which case, the way I would approach is to project everything into screen space and use some vector math to work out which way to rotate the object. Something like this? (Press spacebar to random reset the cube)

Nice! Any chance you can share the project link for that so that I can inspect the code? Right now it just links to the published/play version.

https://playcanvas.com/project/490224/overview/rotate-around-local-axis

The code is on the rough side and I think it can be simplified further by using the view matrix to convert the cube’s up into screen space but didn’t have time to fully look into it.

Hi Yaustar, Is there any way that I can implement rotation around z axis as well in the example that you shared? I tried changing the following lines but it gives improper rotations.

 if (rotateDirection > 0) {
            this.cubeEntity.rotateLocal(0, this.rotateSensitivity * projected.length(), this.rotateSensitivity * projected.length());
        } else {
            this.cubeEntity.rotateLocal(0, this.rotateSensitivity * -projected.length(), this.rotateSensitivity * -projected.length()); 
        }

Any help would be appreciated.

Which Z axis are you trying to rotate around? The world or the local?

Local Z Axis. I wanted to rotate around Y and Z axis at the same time. Now the existing code rotates around Y perfectly. The code which I changed given in my previous post didn’t work as expected.

Which order of rotations do you need it to be in? PlayCanvas applies the local rotations in a ZYX order which means it rotates the local Z first, then the Y and finally the X.

This thread may help pending on what you looking to achieve: https://github.com/playcanvas/engine/issues/1871

There’s also this example: https://developer.playcanvas.com/en/tutorials/rotating-objects-with-mouse/

Can you also talk more about the effect/behaviour you trying to achieve please? Maybe there is a better solution.

I got your point. Let me try explaining you what I want exactly in a simple way. We have a mouse orbiter script. In which, the camera rotates around the object. What I want now is to make the camera static, I mean stable, not rotating or moving anywhere but wanted to rotate the object, so that users can rotate and look at the object by mouse or touch.

There’s also this example: https://developer.playcanvas.com/en/tutorials/rotating-objects-with-mouse/

I saw this example but what I found in that example is the uncontrolled rotation of the object around each axis. Imagine a product that is rotated like in the above example, that will make the user feel that the rotation is not pleasing as it feels like when using mouse orbiter. Hope you got my point.

Something like this? https://playcanvas.com/editor/scene/664238

If not, can you supply an example from somewhere that helps visualise the type of rotation you would like?

This is perfect Yaustar !.. Exactly what I wanted. Thank you so much for this. I was expecting a snippet or any code help but you written the entire code. Owe you a lot. :slight_smile:

No problem, this was an old project I did last year because someone wanted to see how to implement The Room style item examination.

Oh I see. Anyway, that was perfect. Keep up the good work yaustar…

Basically, I was lucky to have the project on hand :grin:

1 Like