Thursday, March 12, 2015

Create 3D graphics using three.js.

Being a JavaScript developer if we want to create 3D visualization, we have a great native support from webgl (Web Graphics Library). But Again If we are going to draw a Cube using webgl it needs more that 500 Lines of code. But on the same time we have some 3D library, which are Like a Wrapper on webgl & using them we can draw the same cube in Less than 50 Lines. Now I don't need to write 500 lines of code. But i can get all the features of webgl with these wrappers as well. Let’s have a look on webgl features.

  1. It's a JavaScript API for rendering interactive 3D graphics and 2D graphics within any compatible web browser without the use of plug-ins.
  2. It brings 3D graphics to the Web by introducing an API that closely conforms to OpenGL ES 2.0 that can be used in HTML5 <canvas> elements.
  3. Complicated in comparison to other web technologies because it's designed to work directly with graphics card.
  4. Drastically decrease the amount of code we need to write. While a simple cube in raw webgl turns out hundreds of lines of shader and JavaScript code, a Three.js equivalent is only a part of that.
  5. Most of them build on top of webgl to create elements intuitive to a 3D environment like a scene, a camera, a light source, ambient light, ready-made shapes, materials, textures, and effects such as fog, and floating particles.
  6. Most libraries provide easy ways to handle events and vertex and fragment shaders, small programs that run on GPU

This is all about webgl features. Now have a look on some notable Library based on webgl

  1. Three.js (Three GitHub repo) - Three.js is a lightweight 3D engine with a very low level of complexity. The engine can render using <canvas>, <svg> and webgl.
  2. PhiloGL (PhiloGL GitHub repo) - PhiloGL is built with a focus on JavaScript good practices and idioms. Its modules cover a number of categories from program and shader management to XHR, JSONP, effects, web workers and much more.
  3. GLGE (GLGE GitHub repo) - GLGE has some more complex features, like skeletal animation and animated materials.
  4. J3D (J3D GitHub repo) - J3D allows you not only to create your own scenes but also to export scenes from Unity to webgl.
  5. SceneJS (Scene GitHub repo) - SceneJS is an extensible webgl-based engine for high-detail 3D visualization using JavaScript. Specialized towards fast rendering of large numbers of individually articulated objects, like in CAD, without game engine effects like shadows, reflections etc. Less flexibility than three.js, GLGE and PhiloGL.
  6. Babylon.js(Babylon GitHub Repo) – Suitable for Game Creation due to features such as collision detection

Amongst All mention above we have very good popularity (18000+) & Support from Stack-overflow as well as good number of contributors (443+) with Three.JS. With Other Library all these figures are very less.

About ThreeJs:
  • A lightweight cross-browser JavaScript library/API.
  • Can be used in conjunction with the HTML5 canvas element, SVG or webgl.
  • Has a great fall-back feature. ThreeJs can fall-back to use canvas for rendering if webgl is not available.
  • A fraction of webgl code.
  • Just need to understand the webgl concepts, does an excellent job of abstracting away many of the details of webgl.
  • Allows the creation of GPU-accelerated 3D animations using the JavaScript language as part of a website without relying on proprietary browser plugins.
  • ThreeJs come with exporters that will take 3DS and FBX and translate these into JSON files readable by ThreeJs. It also comes with Blender export and import JSON files.

To start with ThreeJs rendering we need to know what are the features ThreeJs have. Like Any movie shooting I would like to say "Lights-camera-Action". On Action our Object has to be in Scene. Let’s us have an idea what is Lights Camera & Action.SceneThreeJs uses the concept of a display list. This means that all objects are stored in the list and then drawn to the screen. Here, it's a THREE.Scene object. To draw an object on the screen add the Object to scene.RendererThe renderer simply draws everything from the scene to the webgl canvas.
  • Canvas Renderer
The Canvas renderer displays scenes using the Canvas 2D Context API.renderer = new THREE.CanvasRenderer();
  • WebGL Renderer
The webgl renderer displays scenes using webgl, if your device supports it. This renderer has way better performance than CanvasRenderer.renderer = new THREE.WebGLRenderer();Both WebGLRenderer and CanvasRenderer are embedded in the web page using an HTML5 <canvas> tag. The "Canvas" in CanvasRenderer means it uses Canvas 2D instead of webglCameraCamera tells the renderer to from which point of view it should be render. Camera is of two types
Orthographic                                  Perspective
    • PerspectiveCamera

    camera = new THREE.PerspectiveCamera( fov, aspect, near, far )
    fov — Camera frustum vertical field of view.
    aspect — Camera frustum aspect ratio.
    near — Camera frustum near plane.
    far — Camera frustum far plane.

  • OrthographicCamera

  • camera=new THREE.OrthographicCamera (left,right,top,bottom,near, far)
    left — Camera frustum left plane.
    right — Camera frustum right plane.
    top — Camera frustum top plane.
    bottom — Camera frustum bottom plane.
    near — Camera frustum near plane.
    far — Camera frustum far plane.


Geometry
Geometry is a set of points that need to be connected in order to create the object.
var geometry = new THREE.CubeGeometry(200, 1, 200);

Material
Material is simply the paint that will cover the object.
var material = new THREE.MeshBasicMaterial({color:0XFFAA00, overdraw: true });

Mesh
A mesh is an object that takes geometry, and applies a material to it, which we then can insert to the scene, and move freely around.
var cube = new THREE.Mesh(geometry, material);

Time for Action:

Let’s us have a module to render a cube as shown in below picture.
For that let's have a start with our HTML page.

<html>
     <head>
<title>My first Three.js app</title>
<style>
canvas { width: 100%; height: 100% }
</style>
     </head>
      <body>
<script  src="three.js"></script>
<script src="custom.js"></script>
     </body>
</html>

Here three.js is our library, & custom.js is our JavaScript code which will render 3D cube shown above.

Adding Scene Camera & rendere to initilize the App.
There are a multiple types of cameras in ThreeJs. For now, let's use a PerspectiveCamera.
var scene, camera, renderer;
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.x = 50;
    camera.position.y = 100;
    camera.position.z = 200;
    renderer = new THREE.WebGLRenderer();
     renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

Now Adding scene & camera to renderer
var render = function() {
    renderer.render(scene, camera);
};

Add Some Animation
Animating frames with render loop
var animate = function() {
    requestAnimationFrame(animate);
};


Adding an Object to Scene
Now everything is ready, But nothing is getting Displayed guess why?  So let’s add an Object to display a mesh.

var getMesh=function(){
     var geometry = new THREE.CubeGeometry(10, 10, 10);
     var material = new THREE.MeshBasicMaterial({vertexColors: THREE.FaceColors, color:"red", overdraw: 0.5, opacity: 0.9});
     var cube = new THREE.Mesh(geometry, material);
     cube.position.x = 100;
     cube.position.y = 100;
     cube.position.z = 100;
     scene.add(cube);
}

Now just call the above function as.

getMesh(); // to render our cube into scene

Want some Extra Animation?? Let’s Update our Animation as

var animate = function() {
  1. cube.rotation.x += 0.1;
  2. cube.rotation.y += 0.1;
requestAnimationFrame(animate);
render();
};

finally our code will look like

(function () {
    'use strict';
    var scene, camera, renderer, cube;
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.x = 50;
    camera.position.y = 100;
    camera.position.z = 200;
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    getMesh();
    function animate() {
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
        requestAnimationFrame(animate);
        render();
    }
    function getMesh(){
        var geometry = new THREE.CubeGeometry(50, 50, 50);
        var material = new THREE.MeshNormalMaterial({vertexColors: THREE.FaceColors, color:'red', overdraw: 0.5, opacity: 0.9});
        cube = new THREE.Mesh(geometry, material);
        cube.position.x = 50;
        cube.position.y = 100;
        cube.position.z = 100;
        scene.add(cube);
    }
    function render() {
        renderer.render(scene, camera);
    }
    animate();
})();

We Are Done. Our Cube is Displayed & rotating in the 3D plane. For Demo visit this link

Now We Saw that Creating a cube with ThreeJs is really handy & easier. It can be used for 3D charts & visualizations. Though ThreeJs supports blender exported data for 3D animation. If you are good with Blender, we can go with Animation's or interactive 3D computer graphics.