# Three.js – Drawing Waves

http://mrdoob.github.io/three.js/

As part of the JavaScript study, I made some trials for 3D rendering using Three.js library.

In the beginning, I had some difficulty to understand the API usage, maybe due to the lack of its documentation. But, by looking through the examples and tutorials, I could build up some basic 3D shape drawings on the HTML canvas.

I’m a little surprised by the power of WebGL. Though I once had seen several graphical WebGL demos, it seemed to require very complex coding/processing. Three.js API seems simple enough to use even for novice user like myself. It may require more efforts to create complex objects and consider performance tuning, but I didn’t have to struggle too much at least for the basic one.

The following is some trials I made, and working example on jsdo.it.

**Working Example**

http://jsdo.it/parroty/2Rix

**Source Code**

var stats, camera, scene, renderer; var geometry, points = []; var windowHalfX = window.innerWidth / 2; var windowHalfY = window.innerHeight / 2; // parameters var SEPARATION = 25; var AMOUNTX = 50; var AMOUNTY = 50; var INITIAL_FACTOR = 1.0; var WAVE_HEIGHT = 200; var WAVE_SPEED = 0.2; var ROTATION_SPEED = 0.1; var DAMP_SPEED = 0.005; var CAMERA_SPEED = 0.05; var rotation = 0; var factor = INITIAL_FACTOR; var mouseX = -300; var mouseY = -300; var initial_camera_zpos = 500; var initial_camera_ypos = 500; init(); animate(); function init() { var container = document.createElement('div'); document.body.appendChild(container); camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = initial_camera_zpos; camera.position.y = initial_camera_ypos; scene = new THREE.Scene(); var width = SEPARATION * AMOUNTX; var height = SEPARATION * AMOUNTY; geometry = new THREE.PlaneGeometry(width, height, AMOUNTX, AMOUNTY); var ground = new THREE.Mesh(geometry); calculateInitialPoints(); updatePoints(); ground.rotation.x = Math.PI / -2; scene.add(ground); renderer = new THREE.CanvasRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); container.appendChild(renderer.domElement); stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; container.appendChild(stats.domElement); document.addEventListener('mousemove', onDocumentMouseMove, false); document.addEventListener('mousedown', onMouseDown, false); window.addEventListener('resize', onWindowResize, false); } function calculateInitialPoints() { for(var i = 0; i < geometry.vertices.length; i++) { var v = geometry.vertices[i]; var x = (v.x / SEPARATION) * WAVE_SPEED; var y = (v.y / SEPARATION) * WAVE_SPEED; points[i] = WAVE_HEIGHT * (Math.cos(x*x + y*y) / Math.sqrt(x*x + y*y + 0.25)); } } function updatePoints() { for(var i = 0; i < geometry.vertices.length; i++) { var v = geometry.vertices[i]; v.z = points[i] * Math.cos(rotation) * factor; } } function calculateNextParameters() { rotation += ROTATION_SPEED; if(factor > 0) { factor -= DAMP_SPEED; } } function onWindowResize() { windowHalfX = window.innerWidth / 2; windowHalfY = window.innerHeight / 2; camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function onDocumentMouseMove(event) { mouseX = event.clientX - windowHalfX; mouseY = event.clientY - windowHalfY; } function onMouseDown(event) { factor = INITIAL_FACTOR; } function animate() { requestAnimationFrame(animate); render(); stats.update(); } function render() { camera.position.x += ( mouseX - camera.position.x) * CAMERA_SPEED; camera.position.y += (-mouseY - camera.position.y) * CAMERA_SPEED; camera.lookAt(scene.position); updatePoints(); renderer.render(scene, camera); calculateNextParameters(); }

Posted on April 18, 2013, in JavaScript. Bookmark the permalink. Leave a comment.

## Leave a comment

## Comments 0