three.js rotate camera in plane

23,834

Solution 1

You might get what you want simply by setting camera.rotation.order = 'YXZ';

Solution 2

believe what your looking for conceptually is a camera rig setup. In this approach you first build an Object3D to be the "neck", then attach the camera to that object with your desired rotation. Then you can apply the rotations to the Object3D to look around without the wobble effect. To carry it further you could nest that "neck" object in another Object3D to act as the "body" and apply the translations to that object to move about the scene. In this way you have a basic camera controller rig. I modified your fiddle like so:

Edit: implementation change to better suit @ostapische use case. Here's the fiddle link

function degInRad(deg) {
    return deg * Math.PI / 180;
}
/////////////////////////////////
function render() {
    requestAnimationFrame(render);
    if (leftPressed) {
        neck.rotation.y += degInRad(1);
    } else if (rightPressed) {
        neck.rotation.y -= degInRad(1);
    }
    if (upPressed) {
        camera.rotation.x += degInRad(1);
    } else if (downPressed) {
        camera.rotation.x -= degInRad(1);
    }
    renderer.render(scene, camera);
}
/////////////////////////////////
var scene, camera, renderer, grass, neck;
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
/////////////////////////////////
window.onload = function() {
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
    cameraHolder = new THREE.Object3D();
    cameraHolder.add( camera );
    renderer = new THREE.WebGLRenderer();
    renderer.rendererSize = {width: window.innerWidth, height: window.innerHeight, quality: 100, maxQuality: 400, minQuality: 20};
    renderer.setSize( renderer.rendererSize.width, renderer.rendererSize.height );
    document.body.appendChild( renderer.domElement );

    var texture, material, geometry, element;

    material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
    material.side = THREE.DoubleSide;
    geometry = new THREE.PlaneGeometry(24, 24);   
    grass = new THREE.Mesh( geometry, material );
    grass.name = "grass";
    scene.add( grass );

    neck = new THREE.Object3D();
    neck.rotateOnAxis(new THREE.Vector3(1, 0, 0), degInRad(90));
    neck.up = new THREE.Vector3(0, 0, 1);
    neck.position.z = 1;
    neck.position.y = -5;


    neck.add(camera);
    scene.add(neck);    

    KeyboardJS.on('left', function() { leftPressed = true; }, function() { leftPressed = false; });
    KeyboardJS.on('right', function() { rightPressed = true; }, function() { rightPressed = false; });
    KeyboardJS.on('up', function() { upPressed = true; }, function() { upPressed = false; });
    KeyboardJS.on('down', function() { downPressed = true; }, function() { downPressed = false; });

    render();
}

I was going to mention the PointLockControl or FirstPersonControl, but I see WestLangley has been so kind to suggest. Anyway good luck,

Share:
23,834
ostapische
Author by

ostapische

Updated on September 18, 2020

Comments

  • ostapische
    ostapische over 3 years

    I have a camera in my app:

    camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
    camera.position.z = 1;
    camera.position.y = -5;
    camera.rotateOnAxis(new THREE.Vector3(1, 0, 0), degInRad(90));
    camera.up = new THREE.Vector3(0, 0, 1);  
    

    Those code in render function must rotate the camera while I'm pressing the keys:

    if (leftPressed) {
        camera.rotateOnAxis((new THREE.Vector3(0, 1, 0)).normalize(), degInRad(1));
    } else if (rightPressed) {
        camera.rotateOnAxis((new THREE.Vector3(0, 1, 0)).normalize(), degInRad(-1));
    }
    if (upPressed) {
        camera.rotateOnAxis((new THREE.Vector3(1, 0, 0)).normalize(), degInRad(1));
    } else if (downPressed) {
        camera.rotateOnAxis((new THREE.Vector3(1, 0, 0)).normalize(), degInRad(-1));
    }  
    

    Camera rotates, but not in way I need. I want that camera rotates like in FPS (first person shooter) on plane. See picture to understand what I want...
    I'm try to use sin(1) and cos(1) but can't understand how rotateOnAxis works, cause translate functions work like a charm and moves camera in direction in what she sees.
    P.S.
    Here is a docs to the three.js maybe it helps.
    To handle keyboard events I use KeyboardJS
    And here is a degInRad function:

    function degInRad(deg) {
        return deg * Math.PI / 180;
    }  
    

    Link on JSFiddle

    camera rotation

    O - position of camera
    O-O1 - current camera direction
    R1 - current rotation direction
    R - direction what I want
    Sorry for good picture.