How do you fix the 180 degree flip of the camera when using pitch controls?

I’ve seen this question pop up alot on Google yet I haven’t really found an answer :frowning:

My context is I have an object with ‘WASD’ controls to give it pitch, yaw and roll controls

I have a camera placed behind the object to follow it as I move around in the scene

If I continously pitch up, effectively doing roller coaster loops, the camera will flip 180 degrees

I initially was using just normal XYZ rotations, but I tried changing everything to use quaternions, tried setting an up vector, nothing worked for me

I put together a basic sandbox that has the problem im describing, hoping someone could explain to me how to avoid this issue, much love <3

I think, you’ll first need to describe what you would consider a “proper” behaviour, before someone will tell you that you’ll need to adjust your expectations :wink:

Honestly: are you talking about a 3rd-person view, or a 1st person view? And please describe as exactly as possible what a “camera flip” exactly means.

1 Like

If you’re going to allow the camera to do loops like that, you might want to not use OrbitControls, and instead attach the camera directly to the target object.
You can try setting the “up” vector of the camera to it’s actual up instead of 0,1,0… and possibly get it to do a loop without flipping.
so like…
at init camera.up = new THEE.Vector3();
then in your game loop…

camera.up.set(0,1,0).applyQuaternion(camera.quaternion);

By proper I was referring to the camera not flipping 180 degrees past certain points, effectively to prevent reorientation once the up vector becomes flipped

The solution that worked for me is to get the cross product between forward and right vectors, and constantly update what is the new up vector

const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(groupRef.current.quaternion);
const right = new THREE.Vector3(1, 0, 0).applyQuaternion(groupRef.current.quaternion);
upVector.current.crossVectors(right, forward).normalize();
camera.up.copy(upVector.current);

Yeah. Thats kinda exactly what:

camera.up.set(0,1,0).applyQuaternion(camera.quaternion);

should do… but glad you figured out a way to make it work. :smiley:

1 Like