Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

First person simulation with three.js using keyboard arrows

For my source, visit http://jsfiddle.net/fYtwf/

Background

I have a simple 3d simulation using three.js where the camera is surrounded in 3 dimensions by cubes. These cubes are to help visualise where the camera is looking until the view controls are coded and tested. I want to create a simple 3D application, where the camera is controlled via up, down, left and right keys. Just like moving your head

Issues

In my current application, when facing forward, and starting to look up, we are successful. However when we turn left 90 degrees, and we press the up arrow... The wrong thing happens. the camera increments the x axis, but because we're facing another direction, modifying the x axis ALONE is WRONG...

Now I'm assuming this is because some trigonometry is required to calculate the correct values for the z axis. However, my trig isn't brilliant.

Current

To get a better understanding of what i mean, please visit my jsfiddle : http://jsfiddle.net/fYtwf/

UP key ONLY increments X

DOWN key ONLY decrements X

LEFT key ONLY increments Y

RIGHT key ONLY decrements Y

Q key ONLY increments Z

W key ONLY decrements Z

( Q and W were only coded to try and help me understand. )

From my current understanding, when I press the UP key, X must increment and the Z axis must be modified based on what the current Y axis is. However I don't know the algorithm :(

So X and Z must be modified in the KEYUP code ( I think, please correct me if I am wrong )

// setRotateX, getRotateX, setRotateY and getRotateY are extended
// camera functions I wrote so I could work with degrees. Solution
// IS NOT required to use them, they just helped me

switch( key )
{
    case KEYUP:
        if ( camera.getRotateX() < 90 ){ // restrict so they cannot look overhead
            camera.setRotateX( camera.getRotateX() + VIEW_INCREMENT );
        }
        break;
                
    case KEYDOWN:
        if ( camera.getRotateX() > -90 ){ // restrict so they cannot look under feet
            camera.setRotateX( camera.getRotateX() - VIEW_INCREMENT );
        }
        break;
                
    case KEYLEFT:
        camera.setRotateY( camera.getRotateY() + VIEW_INCREMENT );
        break;
                
    case KEYRIGHT:
        camera.setRotateY( camera.getRotateY() - VIEW_INCREMENT );
        break;
}
like image 514
AlexMorley-Finch Avatar asked Nov 06 '12 23:11

AlexMorley-Finch


2 Answers

There are a number of solutions to this problem, but since you only want the camera to rotate up, down, left, and right, the answer in this case is easy.

You just need to set the camera Euler order to "YXZ" like so:

camera.rotation.order = "YXZ"; // three.js r.65

If you do that, everything becomes very intuitive.

Here is an updated fiddle: http://jsfiddle.net/fYtwf/3/ (this demo is using r.54, however)

Once you change camera.rotation.z from it's default value of zero, things will become very confusing. So don't do that. :-)

three.js r.65

like image 115
WestLangley Avatar answered Sep 20 '22 17:09

WestLangley


While this does not directly fix your code, I thought I'd mention that Three.js provides two ready-made controllers to navigate in FPS mode. They both use mouse for looking and can move, but should be rather simple to adapt to keyboard look and remove movement if needed. They are:

  • FirstPersonControls
  • PointerLockControls

I'd recommend the latter as a starting point because it's rather simple and the former confusingly has the looking code twice, probably as an artifact from old features.

like image 27
Tapio Avatar answered Sep 17 '22 17:09

Tapio