ThreeJS camera control with TweenMax

Recently I started exploring the world of 3D, I mostly wanted to work in a familiar environment so I chose ThreeJS an excellent framework for 3D construction/animation with javascript. And of course I wanted to inject my favorite tool for javascript animation TweenMax.
So after a few examples and documentation reading I came up with a very simple example/tutorial of how to control various aspects of the camera in 3D space using TweenMax to animate properties and end-values.
For this example I also used the extremely helpful threejs boilerplate

You can view a DEMO here

And here is how, first off we are going to create the basic scene were everything will be rendered upon.

Note: These initial declarations are all covered and automatically created by threejs boilerplate, but I’ll go through them explaining what is what anyhow.


function init(){

      if( Detector.webgl ){
        renderer = new THREE.WebGLRenderer({
          antialias    : true,  // to get smoother output
          preserveDrawingBuffer  : true  // to allow screenshot
        });
        renderer.setClearColorHex( 0x1e1e1e, 1 );
      // uncomment if webgl is required
      //}else{
      //  Detector.addGetWebGLMessage();
      //  return true;
      }else{
        renderer  = new THREE.CanvasRenderer();
      }
      renderer.setSize( window.innerWidth, window.innerHeight );
      document.getElementById('container').appendChild(renderer.domElement);

                        // create a scene
      scene = new THREE.Scene();

Now we have created the basic renderer for our example of course this requires a div with id = “container” in the html


<!-- three.js container -->
<div id="container"></div>

Next step is to create the camera that offers us the perspective of the “world”


// put a camera in the scene
      camera = new THREE.PerspectiveCamera(100, window.innerWidth / (window.innerHeight), 1, 10000 );
      camera.position.set(0, 0, 50);
      camera.setViewOffset(window.innerWidth,window.innerHeight,0,-100,window.innerWidth,window.innerHeight);
      scene.add(camera);

      // create a camera contol
      cameraControls  = new THREE.TrackballControls( camera )

Now we have set up a camera showing us the scene, and we set its position at x:0, y:0, z:50 (slightly set forward), and then we lowered it a bit with “setViewOffset”.
The TrackballControls allow us to rotate the camera by holding the mouse button down, or zooming with the scrollwheel.

Next step is to add some light. And heres how we do it.


// LIGHT
      var light = new THREE.AmbientLight(0xffaa00);
      light.position.set(0,0,0);
      scene.add(light);

So by now we should have an empty 3D World with a camera set at a specific point and an ambient light source.

But since we find no fun in an empty world lets create some boxes!

There are 3 basic ingredients to create a basic shape with ThreeJS:

    geometry
    material
    mesh
  • geometry defines the dimentions of the object and its position
  • material defines the color of the surface of the object or its texture
  • mesh defines the actual object with the combination of geometry and material
  • So lets create a simple cube with what we learned here:


    var geometry;
    var material;
    var mesh;
    geometry    = new THREE.CubeGeometry( 5, 5, 1, 1, 1, 1 );
    material    = new THREE.MeshBasicMaterial({ color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } );
    mesh        = new THREE.Mesh( geometry, material );

    for details about cube geometry take a look at the ThreeJS API : http://mrdoob.github.com/three.js/docs/54/#Reference/Extras.Geometries/CubeGeometry

    And since we want some control over our cube we create some buttons and attach appropriate event handlers.

    HTML:


    <div class="top">
                <div class="buttons" id="left"><< Rotate Left</div>
                <div class="buttons" id="right">Rotate Right >> </div>
                <div class="buttons" id="in">Zoom-In +</div>
                <div class="buttons" id="out">Zoom-Out -</div>
                <div class="buttons" id="rotate">Auto Rotate</div>
                <div class="buttons" id="reset">Reset</div>
            </div>

    JS:


    /// CAMERA CONTROL /////

                    $("#left").live('click',function(){
                            var theta = 0.1;
                             var x = camera.position.x;
                             var z = camera.position.z;

                            var moveX = x * Math.cos(theta) + z * Math.sin(theta);
                            var moveZ = z * Math.cos(theta) - x * Math.sin(theta);

                            TweenMax.to(camera.position,0.5,{x:moveX,z:moveZ,onUpdate:function(){
                            camera.updateProjectionMatrix();
                            camera.lookAt(scene.position);
                        }});
                    });

                    $("#right").live('click',function(){
                             var theta = 0.1;
                             var x = camera.position.x;
                             var z = camera.position.z;

                            var moveX = x * Math.cos(theta) - z * Math.sin(theta);
                            var moveZ = z * Math.cos(theta) + x * Math.sin(theta);

                            TweenMax.to(camera.position,0.5,{x:moveX,z:moveZ,onUpdate:function(){
                            camera.updateProjectionMatrix();
                            camera.lookAt(scene.position);
                        }});
                    });

                    $("#in").live('click',function(){
                            TweenMax.to(camera,0.5,{fov:"-=5",onUpdate:function(){
                            camera.updateProjectionMatrix();
                        }});
                    });

                    $("#out").live('click',function(){
                            TweenMax.to(camera,0.5,{fov:"+=1",onUpdate:function(){
                            camera.updateProjectionMatrix();
                        }});
                    });

                     $("#reset").live('click',function(){
                        TweenMax.to(camera,0.5,{fov:35,onUpdate:function(){
                            autoRotate = false;
                            cameraControls.target  = scene.position;
                            camera.lookAt(scene.position);
                            camera.updateProjectionMatrix();
                        }});
                    });

                    $("#rotate").live('click',function(){
                        autoRotate = true;
                    });
            }

    What we have done here to attach event listeners with JQuery to the buttons we created earlier. These buttons with the help of TweenMax animate properties of the camera on demand.
    For example zooming-in is done by animating the property fov by an amount.

    For more info about camera controls and options visit the ThreeJS API here: http://mrdoob.github.com/three.js/docs/54/#Reference/Cameras/PerspectiveCamera

    Finnaly we add the functions that will actually update and animate our world.


    // animation loop
            function animate() {

                if(autoRotate == true){

                    _autoRotate();
                }
                camera.updateProjectionMatrix();
                requestAnimationFrame( animate );
                // do the render
                render();
                // update stats
                stats.update();
            }

            // render the scene
            function render() {
                // update camera controls
                cameraControls.update();
                // actually render the scene
                renderer.render( scene, camera );
            }

            var radius = 300;
            var theta = 0;
            function _autoRotate(){
                //theta = 0.01 //the speed of rotation
                // rotate camera
                theta += 0.1;

                camera.position.x = radius * Math.sin( degToRad( theta ) );
                camera.position.y = radius * Math.sin( degToRad( theta ) );
                camera.position.z = radius * Math.cos( degToRad( theta ) );
                camera.lookAt( scene.position );

                camera.updateMatrixWorld();
            }

    So at each “tick” or frame-update we render the scene to display any changes that took place.

    Auto-rotate function simply rotates the camera around a certain point.

    *On a solid color background it seems like the object is animating, however it is the camera that moves around that object. We will see more about object moving on another tutorial.

    You can view a DEMO here

    Enjoy!

    Facebooktwittergoogle_pluspinterestlinkedin
    linkedin
    Tagged , , , . Bookmark the permalink.

    3 Responses to ThreeJS camera control with TweenMax

    1. po says:

      Hello. Your article may be old, but the demo page doesn’t work on my computer (using chrome). .

    2. I will try and update it to the current version of threejs. Thanks!

    3. I have updated the example, it is not perfect but at least it is not breaking and one can see the functionality explained in this tutorial.

    Leave a Reply

    Your email address will not be published. Required fields are marked *