How to change the rotation center of my group in the world scene after moving the group to a new location in the scene

Hi Team,

I have a problem that have not been able to figure out the solution to yet. I have a group of meshes that originally it is positioned in the center of the scene. So, when I rotate the group using my mouse it rotates around the center in a tight rotation which is fine. Then I move the group to the right or left of the scene and try to rotate, At this point the rotation becomes a wide circle around the center of the scene again which is not what I want. I would like it to rotate around its new center in the same tight rotation. I have figured out the mouse movement and know when the right click drag stops so I can record the new coordinates. But I dont know what is the correct call to get the world position and then change the groups center of rotation at the new location in the scene.

I have followed all the articles around different algorithms on stack overflow and threejs discourse site. But none of them have worked for me so far.

Any help is appreciated,

Thanks

How are you moving the group? Moving the group and then rotating the group should still rotate all children around the group.position?

I am moving the group using right click/drag of my mouse. So it is user initiated move and not an automatic move. Then I proceed to rotate it using leftclick/drag.

In that case, i think you are moving the camera with orbitcontrols.
You’re not actually moving your object.
OrbitControls makes the camera orbit around the controls.target vector3.
Usually to move objects with the mouse we use TransformControls or something, in conjunction with OrbitControls.

1 Like

I’m having a deja-vu here. Why are you starting a new thread for the same question?

2 Likes

I am using ArcballControl @manthrax .
@vielzutun.ch: The reason is I couldn’t get this approach to work. So I thought I try again with a fresh approach. I have exhausted all threejs examples to see if I see one that can help with that. But no matter what controller I use, whether it is Arcball control or trackball control (I am not using OrbitControl because I can’t use it to rotate in all directions) I don’t seem to see any examples that actually behave this way. Every example that I’ve seen in three JS once you move the mesh away from the center of the screen and rotate it, it rotates around the center of that scene and not around it’s own access.
For my spatial single cellular app, I need the entire group of meshes which is in a bounding box, to rotate in a tight axis around itself and not around the center of the scene, No matter where I move that group on the screen.

I would love to see a working example so I could dig in and figure out the logic playing with l it.

Sorry if this was a duplicate. I have Been at this for 6 days now and very eager to find a solution and see if my ask is even possible or this is not achievable.

Thanks again

make a repro we can look at in codepen or glitch.

That’s the fundamental misconception right there:

An Arcball Control moves the camera, not the object.

Arcball controls allow the camera to be controlled by a virtual trackball with full touch support and advanced navigation functionality.

Add a second object to your scene - an AxesHelper at the coordinate origin, and it should immediately become obvious what’s going on.

No, you did not.

@Manthrax linked a perfect example involving TransformControls, and as of now I’ve been the only one who clicked it.

Generally, it is much appreciated if people who ask for some solution also post a minimal working example, so that people who might provide help can easily work on it.

If you want to move and rotate a group of objects you could either use TransformControls (this is its main purpose), or make you own interactivity (this is what I’d do if I need such functionality).

The other controls are made for manipulating the camera. You might be able to force them to work the way you need, but you need some magic. Here is how this could be done with OrbitControls. Left mouse button to rotate, right to pan:

https://codepen.io/boytchev/full/XJJmEQg

I’m not proud of this code, it is not what I’d do, it is just a demo.

5 Likes

Hi @vielzutun.ch I did not click that one because I had signed off by the time @manthrax posted it. I was just talking about other examples upto that point. BTW: that example also has the same issue. When you move the object to the side and rotate it rotates around the center of the scene in a wide circle instead of rotating around itself using the mouse. The one closest to what I need is this one by @PavelBoytchev : https://codepen.io/boytchev/full/XJJmEQg
Big thanks to @PavelBoytchev for putting this up. Also big thanks to @vielzutun.ch and @manthrax for being patient with me and giving me their guidance. I am going to play with @PavelBoytchev example in my setup and see how far I will get and update the friends here.

One question I have here is this: @PavelBoytchev example is using orbitcontrol which limits rotation from certain angles to 180 degrees and not 360 degrees. Is there anyway we can enable that to do full rotation in all directions? I was able to do that with TrackBallControl and ArcBallControl. But then I had the issue that I have already posted here.

Thanks again

Yes, by replacing OrbitControls with ArcballControls. Here is what happens when I try it:

1 Like

I would like to compliment @PavelBoytchev on his creative and extraordinarily concise (in terms of visible lines of code) demonstration :+1:, which however comes with some serious (and as of now hidden) limitations. More on that later.

1 Like

Exactly. That’s why I mentioned:

1 Like

@PavelBoytchev I am glad I started this new thread. If I had not, I would not have seen your code sample. Your few lines of code that you said you are not proud of actually have gotten me 90% there. So, I would say you should be very proud of your help. This gave me the idea about how using two controllers work in conjunction to achieve this. I tried to post a small video of it but this site does not allow anything over 8MB. And my screen captures how ever small keep exceeding that limit. Here is a screenshot of it:

For 360 degree rotation while I was waiting for some feedback here, I also did play with the code and changed rotControls to TrackBallControls, but kept panControls as OrbitControl as follows:

 rotControls = new TrackballControls( rotCamera, renderer.domElement ); 
        rotControls.rotateSpeed = 5.0;
            rotControls.enableDamping = true;
                rotControls.enablePan = false;

          panControls = new OrbitControls( camera, renderer.domElement );
                panControls.enableRotate = false;
            panControls.enableDamping = true;

And that seemed to relatively work well.

I also changed both of them to ArcBallControl but that did not work properly.
In your statement above did you mean changing both rotControls and panControls to ArcBallController or just one of them?

It’s obvious how happy you are to have finally gotten your hands on some sample code which you can copy&paste into your project. Apparently, you haven’t gotten an understanding along the way of why it’s working for 90% and, by extension, why it’s not working for the remaining 10%.

Personally I consider this preliminary result regrettable, after all the effort by so many people willing to help. And I would like to put in a last effort:

1st, it helps to know that in a 1 geometry - 1 camera setup it makes no difference for the visual output if you move the geometry “x” units to one side or you move the camera the same “x” units to the opposite side. The only way to distinguish one from the other is with the help of a static reference geometry (I’ll come to that):

2nd, you need to be aware of the concept of the Commutative property. In various realms of math the concept of commutativity means, that you can exchange the order of operands or operators, without changing the final result. Prime examples for commutative operations are addition and multiplication:

a + b = b + a
a * b = b * a

By contrast, subtraction and division are not commutative:

a - b ≠ b - a
a : b ≠ b : a

In that light, the sequence of translation and rotation is not commutative. The results of a switch of sequence results in decidedly different outcomes:

Note, how in both variants the rotation is always performed about the coordinate origin, which is why I’d call the coordinate origin the “sweet spot” of rotation.

Coming back to @PavelBoytchev 's cool magic trick: if you peek behind the curtain, by inserting an AxesHelper at the coordinate origin, as a static reference geometry:


and then do some panning and rotating around you’ll see, that the geometry always remains centered about the sweet spot at the coordinate origin. @PavelBoytchev 's rotation does not involve an off-center geometry. The off-center-ness is being simulated by panning the camera away from the center (see my first illustration in this post).


What’s the problem with this approach, you may ask? Really nothing much, as long as you limit yourself to just one (1) off-center object which you want to rotate. As soon as you want to rotate two or more off-center objects, Pavel’s approach falls flat on its face. Because the “sweet spot” exists only once.

I still think, that the TransformControls approach as linked by @Manthrax is the way better approach. But that’s stuff for a continuation post …

Sneak preview: you barely scratched the surface of the power displayed in that linked example.

1 Like

Not true.

The TransformControls example starts out in “translate” mode.
Only as long as you fail to activate the “rotate” mode by hitting the “E” key, you would be right with your claim.

Also, clicking&dragging outside of the red/green/blue colored gizmo lines defaults to an OrbitControl camera control.

You need to click&drag on one of the red/green/blue colored gizmo lines to get the off-center object rotation you are looking for, with unlimited number of rotations.

1 Like

Hi @vielzutun.ch ,
First I wanted to thank you again for putting so much time in educating me on this issue. I am an intermediate threejs developer and still have a lot of learning to do. And I truly appreciate you and every one else’s great educational posts.
I would like to bring your attention to this important point: I dont just copy and paste to finish the project. I have an insatiable thirst to learn and I used that code to implement it in my own project with a single group. And when I said it is working 90%, it was because I have not completed porting the rest of my code to this new way. I was not implying it is only working 90%.
Also, when I used @PavelBoytchev code, I started looking at everything in the debugger and understanding the flow and the logic. So, it is more about learning new ways, and for me sometimes code examples that I could follow in the debugger is the best way to learn.

That being said I have to admit I did not know that the E mode with transform control example will get activated only when you drag and click on each colored line gizmo. Somehow that was not very clear by first glance at that example. And that was my bad. So, now that you mentioned how to activate that mode, I will also check that example with another implementation verses the one I already did with @PavelBoytchev.

Again I wanted to thank you , @PavelBoytchev and @manthrax for all your help. I definitely have more insight from this new thread. I also implemented or tried to implement your suggestions in the old thread but some how it wasnt working for me. But at least I made a lot of progress and a lot of good understanding in this discourse.
I will update you all with further progress.

Thanks again

2 Likes

Do not use OrbitControls, use camera-controls instead.
You can see this example: https://yomotsu.github.io/camera-controls/examples/view-offset.html

1 Like

Here is an example of how I’m handling camera rotation around a focus point at the moment. Not all the logic is in this function, but it returns the camera coordinates after a specific rotation increment, in this case I chose 0.05 radians. The direction variable is either 1 or -1 when I call the function, which shifts the rotation either clockwise or counterclockwise depending on if I’m pressing the left or right arrow key. After applying the new coordinates with camera.position.set(newCoords) you might want to camera.lookAt(centerObject)

function orbitCamera(camX,camY,camZ, direction){
    const p = player.position; // Vector3
    // get relative position then convert back
    // from (0,0,0) after unit circle Math
    const relX = camX - p.x;
    const relZ = camZ - p.z;

    const currentAngle = Math.atan2(relZ, relX);
    const angleStep = 0.05; //radians

    const newAngle = currentAngle + (angleStep * direction); // direction is + or - 1 for left/right

    const radius = Math.sqrt(relX*relX + relZ*relZ);
    const newX = radius * Math.cos(newAngle);
    const newZ = radius * Math.sin(newAngle);

    // new camera coordinates, don't forget to add the player coordinate back to adjust for
    // distance from (0,0,0)
    return {x: newX + p.x, y: camY, z: newZ + p.z};
}