I'm trying to use a gamepad to rotate a camera in Three.js, using first-person-shooter style controls.
The browser detects the gamepad and recognises it's input, but the camera's order of rotation is wrong. When I rotate on the camera's local Y axis, it takes into account the local X rotation too, which is unwanted.
It seems I'm having the same problem as this guy, but his issue was solved using Three.js r54 and I'm using r60. He set camera.eulerOrder = "YXZ";
to get it working, but the current equivalent camera.rotation.order = "YXZ";
doesn't seem to work for me.
I'm aware of Three.js' built-in "FirstPersonControls" class, but it's not suitable for me as it doesn't accept controller input and it would be messy to shoehorn other non-movement controls in there later. I'm also aware of gamepad.js and have no interest in using it.
Can anyone help?
My rotation code:
function pollGamepad()
{
gamepad = navigator.webkitGetGamepads()[0];
//Rotation
if(gamepad.axes[3] > 0.20)
{
camera.rotateX(-gamepad.axes[3] * 0.02);
}
if(gamepad.axes[3] < -0.20)
{
camera.rotateX(-gamepad.axes[3] * 0.02);
}
if(gamepad.axes[2] < -0.20)
{
camera.rotateY(-gamepad.axes[2] * 0.02);
}
if(gamepad.axes[2] > 0.20)
{
camera.rotateY(-gamepad.axes[2] * 0.02);
}
}
The approach that PointerLockControls
uses is to create a hierarchy of objects: yawObject
contains pitchObject
contains camera
. Then horizontal mouse (or joystick) movement would change the Y-rotation of the yaw object, vertical mouse (or joystick) movement would change the X-rotation of the pitch object, and the camera's rotation would stay fixed at the default (0, 0, -1)
. This just manually simulates Euler YXZ
ordering but it may work better for you. It does create some awkwardness if you need to get the overall rotation.
In a custom controller I wrote recently, I achieved the same result by add()
ing the camera to a single parent object and setting the parent object's Euler order to YXZ
. I don't remember why this worked better than setting it on the camera directly, but it did.