Problem with camera rotation coordinates in OrbitControls

when i rotate the camera, or some other element, through obzh.rotation.y, only the Y coordinate changes. When you rotate the camera through OrbitControls, all 3 coordinates change, here is an example
examp1

as you can see in this example, I have displayed the camera rotation along 3 axes

ctx2.fillRect(130+camera.rotation.x*10,30,35,35)
ctx2.fillRect(130+camera.rotation.y*10,80,35,35)
ctx2.fillRect(130+camera.rotation.z*10,130,35,35)	

And even when rotating only along the Y axis, all 3 axes change. The same thing happens in PointerLockControls. I already asked a similar question some time ago Attaching an object to the camera's y-axis
Everything looks great, but the axles are still jumping
exampl2
The problem is this: I need to get the correct rotation coordinates in order to smoothly bring the mesh rotation to the camera rotation, for example, if the camera angle is 30 degrees greater, then each frame adds 1 degree to the mesh. the same thing with the x coordinate, only for another object. In fact, I have already come up with a solution, but for this I will have to abandon OrbitControls and go to camera.lookAt(), in which case I can attach the camera to the mesh, which I can already rotate around the object I need, and take the rotation coordinates of the mesh, but it seems to me this is a bad decision, but what do you say?

It’s rooted in the fact that three uses Quaternions instead of Euler rotations (.rotation property of Object3D is derived from .quaternion, so to rotate an object on several axes, or to retrieve object rotation when it’s rotated on several axes, you should consider using .quaternion instead of .rotation. Keep in mind quaternions represent rotations using 4 coordinates XYZW, not only 3 XYZ.)

I’m aware of the use of quaternions, but they are too complex for me. I apologize for my rudeness, as I should have started with the solution. Previously I created a parody game on the cannon engine
https://proginvert.github.io/tanki/
, now I’m switching to the ammo engine. There were many unpopular decisions in the old project, and here is one of them https://codepen.io/Dek-ker/pen/vYPWXrN In this example, I abandoned OrbitControls for the sake of smooth control of the rotation of the turret and gun. Is it possible to implement this using OrbitControls?

1 Like

And if any of the mentors or experienced users are interested in helping me create a project on Ammo Three js, then I can create a new topic. This project will be dedicated to the creation of voxel armored vehicles, with open source code posted on GitHub (without an obfuscator, and without a minifier). I will do all the main work on the project; you are only required to help with any problems that arise during the development stage.

1 Like

If all you want to do is create something that rotates around a center (or other point), that is remarkably easy to do.- probably only 10 lines of code or less. You can also easily change the center of the camera rotation.

But if you want more features, like being able to strafe or use pinch controls on an iPhone, then it is worthwhile to learn the features of OrbitControls.

Regarding quaternions, I had problems when using the LookAt command because it used quaternions and refused to allow z-axis rotation.

Just like @mjurczyk pointed out, OrbitControls use quaternions, the main reasons are the gimbal lock and transitions (You can’t lerp Euler).

Now, for the “Why multiple axis get updated at the same time?” question. You need to know that object.rotation and object.quaternion, both reflect the same value in there own way, .rotation as an Euler and the latter as a Quaternion. When you update .quaterion the .rotation get updated and vice versa. In your particular case OrbitControls is updating the .quaternion wish means the .rotation get updated too, and the quaternion generally updates multiple axis at the same time to avoid gimbal locks.

If I’m not mistaken, you’re looking for some sort of follow camera, where you want to set each axis individually. If that’s the case, most developers uses a yaw/pitch approach, where the pitch is the x axis (vertical rotation), and the yaw is the y axis (horizontal rotation).

Check this Follow Camera tutorial, the author is creating a pivot object > holding a yaw object > holding a pitch object > holding the camera

const pivot = new THREE.Object3D()
pivot.position.set(0, 1, 10)

const yaw = new THREE.Object3D()
const pitch = new THREE.Object3D()

scene.add(pivot)
pivot.add(yaw)
yaw.add(pitch)
pitch.add(camera)

In the onDocumentMouseMove listener, you can see how the mouse x movement is assigned to the yaw rotation, and the y movement assigned to the pith rotation.

That’s an ambitious project, and I wish you good luck. But if you don’t understand how quaternions work, you will run into the same problem. As a small example, if at some point, you feel the need to add some sort of smoothing to the camera movements, you’ll have to deal with lerp/slerp functions, Euler don’t offer a lerp method, while with quaternion you can use the built-in slerp method, and that’s just the tip of the iceberg, with three js quaternions are used everywhere.

Don’t let it intimidate you, in most cases you don’t need to understand how they fundamentally works, they have built-in methods that does most of the math for you, you just need to know where and when to use them.

This is how I use to feel about quaternions (And I still do :grin:)

It’s not possible. No, it’s necessary

1 Like

3x3 matrices are like horses. Quaternions are like squids.

1 Like

If i use OrbitControls https://codepen.io/Dek-ker/pen/rNRYoBY then the first 2 problems arise, the first: the camera imitation only works at 270 degrees, after which it starts rotating in the other direction, I had a similar problem in a 2D game. Problem 2 is that the camera does not follow the turret, is there a simple solution, or do I need to remember the position of the previous frame and this one, and shift the camera by the difference between these positions.

My own orbiting camera is positioned using setFromSphericalCoords. It is agnostic of how you rotate your camera, and is only responsible for positioning the camera relative to a target.

//from my understanding, this is setting the axis priorities
camera.rotation.order = 'YXZ';
//some variables for convinience
const rad90 = Math.PI/2;//90 degrees in radians
let maxCamDist = 3;//your maximum camera distance from the target

//on update/animate
camera.position.setFromSphericalCoords(maxCamDist, rad90 + camera.rotation.x, camera.rotation.y);
camera.position.add(target.postion);

Getting the camera rotation to rotate your tank turret however is gonna take some creativity. Not in a position to test whether this will work, but it should work conceptually.

let targetAngle = camera.rotation.y;//add a lerp or some other form of easing if you need it.
tankTurret.setRotationFromAxis(tankBody.up, targetAngle);