Creating an Interactive 3D Model Viewer

INTRO

In this tutorial, you will learn how to create a simple WebGL interactive model viewer using the Three.js library. It will involve creating an html page, setting up the 3D scene, loading a model, and adding controls that will allow you to zoom, rotate, and pan around the object. A basic understanding of HTML, JavaScript, and 3D will come in handy here. Note that you will need a WebGL-enabled browser, eg Chrome, Firefox, Safari 5, Opera 12. You will also need to put these files on a server in order for them to work properly. If you don’t have a web host already, you can run a local server like LAMP or MAMP. So without further ado, let's take a look at what we'll be making!

STEP 1: Download Three.js

First, download the latest Three.js package from Github. Before jumping right in, it may be helpful to familiarize yourself with its contents. It includes:.

STEP 2: Make a new HTML Document

Next we’ll create a new HTML document.

STEP 3: Include the Three.js library and Supporting Scripts

Place the minified Three.js file in your folder (I keep them in a folder named js) and link to the file from your HTML page. Ensure that the path corresponds to your file structure and upload all of these files to your server.

       <script src="js/Three_min.js"> </script>
    

In addition to the minified Three.js file, you must also include several supporting scripts for camera controls and the loaders. The scripts are located in the downloaded Three.js master files: The camera controls are located in three.js-master/examples/js/controls/TrackballControls.js. The loader is located in three.js-master/src/loaders/JSONLoader.js. Copy these files into your js folder and upload to your server.

       <script src="js/TrackballControls.js"> </script>
       <script src="js/JSONLoader.js"> </script>
    

STEP 4: Add a Container for the WebGL Content

Next add a div with an ID of “container” to the body of your HTML page. This will house the WebGL content.

       <div id='container'>
       </div>
    

STEP 5: Call the OnLoad Function

Once the body has finished loading, we’ll call a function named OnLoad(), which we’ll write in the subsequent steps. OnLoad() will be located up in the head of your HTML page and will contain several other functions for creating the WebGL content. You can name these functions however you like, but we will call them initScene(), animate(), and render().

        <body onLoad="onLoad();">
          <div id='container'>
          </div>
        </body>
    

STEP 6: Write the InitScene Function

Init Scene() will initialize the scene, setting up all of the basic elements required to create the 3D world. These include a scene, a renderer, a camera, a light, and 3D objects with materials. Begin by grabbing the container div (line 11).

        <script type="text/javascript">
            function onLoad(){
              initScene();
              function initScene() {
                var container = document.getElementById("container");
              }
            }
        </script>
    

Next create a new renderer and set the size (lines 13-14). Here we will use the window size, but you could set a specific width and height if you wish. Then add the render to the DOM by appending it to the container div (line 15).

        function initScene() 
          var container = document.getElementById("container");
          
          renderer = new THREE.WebGLRenderer( { antialias: true } );
          renderer.setSize(window.innerWidth, window.innerHeight);
          container.appendChild( renderer.domElement );
        }
    

Create a new scene (line 17).

        scene = new THREE.Scene();
    

Create a perspective camera (line 19). Here you can set the field of view, the aspect ratio, and the near and far clipping planes. Set the position of the camera (line 20) and add it to the scene (line 21).

        camera = new THREE.PerspectiveCamera( 75, container.offsetWidth / container.offsetHeight, 1, 1000 );
        camera.position.z = 10;
        scene.add( camera );
    

Create some lights. We’ll add a directional light and a point light.

        var dirLight = new THREE.DirectionalLight(0xffffff, 0.95);
        dirLight.position.set(-3, 3, 7);
        dirLight.position.normalize();
        scene.add(dirLight);

        var pointLight = new THREE.PointLight(0xFFFFFF, 5, 50);
        pointLight.position.set(10, 20, -10);
        scene.add(pointLight);
    

Next we’ll load the model. Any 3D program like Autodesk Maya, 3ds Max, Cinema4D, etc. can be used to create models to be used here. Three.js supports several file types, but the most stable is the JSON based file type developed for Three.js. The package includes utilities for converting more common file types like OBJ and FBX to this file type. For the sake of this tutorial, let’s just assume you have already converted your model. Create a new JSON loader then use it to load your model (line31). Make sure that you have uploaded your models to your server and the path matches your file structure. The loader will store the model in as a Mesh object and add it to the scene (lines 32-35). Give your model a descriptive name. Here we’ve named it hemostat.

        var jsonLoader = new THREE.JSONLoader();
        jsonLoader.load( "models/hemostat.js", function( geometry ) { 
              var hemostat = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );
              scene.add(hemostat);
        } );
    

At the end of initScene(), call the animate() function, which we will write in the next step.

        animate();
    

STEP 7: Write the Animate Function

The animate function will first check whether the browser window is active or inactive. If it it is active, it will call the render function at a rate of up to sixty frames per second depending on bandwidth speed, power of graphics card, and complexity of the scene.

        function animate() {
          requestAnimationFrame( animate );
          render();
        }
    

STEP 8: Write the Render Function

The render function simply renders the scene.

        function render() {
          renderer.render( scene, camera );
        }
    

STEP 9: Add camera controls

If you’re following along, you should now see the static model being rendered on the screen. That’s all well and good, but what’s the point of having a 3D object if you can’t see it from other angles? Next we will go back up to the initScene() function to add some controls to the camera that will allow the user to rotate, zoom, and pan around the object using a mouse or keystrokes (lines 23-27). Then in the render function, add a line to update the controls (line 60).

          camera = new THREE.PerspectiveCamera( 75, container.offsetWidth / container.offsetHeight, 1, 1000 );
          camera.position.z = 10;
          scene.add( camera );

          controls = new THREE.TrackballControls( camera, renderer.domElement );
          controls.rotateSpeed = 1.0;
          controls.zoomSpeed = 1.2;
          controls.panSpeed = 0.2;
        
          controls.noZoom = false;
          controls.noPan = false;
        
          controls.staticMoving = false;
          controls.dynamicDampingFactor = 0.3;
        
          controls.minDistance = 1.1;
          controls.maxDistance = 100;
        
          controls.keys = [ 16, 17, 18 ]; // [ rotateKey, zoomKey, panKey ]
    
        function render() {
          controls.update(); //for cameras
          renderer.render( scene, camera );
        }
    

Conclusion

That should do it! You’ve now created a simple interactive model viewer. Please feel free to contact me with any feedback, questions, or just to say hello.