Speaking of Three.js

Trigonometry experiment using Three.js

Click the above image to see a recreation of a previous Flash experiment (source code here), using Three.js. And see below for the source code used to create this thing.

// shim layer with setTimeout fallback set to 60 frames per second
window.requestAnimFrame = (function(){
	return  window.requestAnimationFrame	|| 
		window.webkitRequestAnimationFrame || 
		window.mozRequestAnimationFrame    || 
		window.oRequestAnimationFrame      || 
		window.msRequestAnimationFrame     || 
		function( callback ){
			window.setTimeout(callback, 1000 / 60);
		};
})();

var canvas,
	stage,
	container,
	scene,
	camera,
	renderer,
	projector,
	light;
	
var w = 800;
var h = 600;
var VIEW_ANGLE = 45;
var ASPECT = w/h;
var NEAR = .1;
var FAR = 10000;
var centerX = 0;
var centerY = 0;
var centerZ = 0;
var radius = 175;
var cameraRadius = 1000;
var cameraX = cameraRadius;
var cameraY = cameraRadius;
var cameraZ = cameraRadius;
var theta = 0;
var group;
var objects = [];
var numObjects = 0;
var orbitSteps = 1000;
var orbitSpeed = Math.PI*2/orbitSteps;
var objectInterval;
var objectPosition;
var direction = 1;
var index = 0;
var startingObjects = 400;

onload = init;
function init() {
	canvas = document.getElementById("myCanvas");
	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR );
	camera.position.x = cameraX;
	camera.position.y = cameraY;
	camera.position.z = cameraZ;
	camera.lookAt(scene.position);
	scene.add( camera );
	projector = new THREE.Projector();
	renderer = new THREE.WebGLRenderer( { antialias: true } );
	renderer.setSize( w, h );
	light = new THREE.SpotLight();
	light.position.set( centerX, centerY, 160 );
	scene.add(light);
	canvas.appendChild( renderer.domElement );
	renderer.render(scene,camera);
	initObjects();
	onEnterFrame();
}
function initObjects() {
	group = new THREE.Object3D();
	group.position.x = centerX;
	group.position.y = centerY;
	group.position.x = centerZ;
	for(var i=0;i<startingObjects;i++) {
		addObject();
	}
	scene.add(group);
}
function addObject() {
	var sphereMaterial = new THREE.MeshLambertMaterial({
		color: Math.round(Math.random()*0xffffff)
	});	
	var obj = new THREE.Mesh(
	   new THREE.SphereGeometry(8,8,8),	//	radius,segments,rings
	   sphereMaterial);
	obj.position.x = 0;
	obj.position.y = 0;
	obj.position.z = 0;
	obj.overdraw = true;
	group.add(obj);
	objects.push(obj);
	numObjects = objects.length;
	objectInterval = orbitSteps/numObjects;
}
function onEnterFrame() {
	requestAnimFrame(onEnterFrame);
	renderer.render(scene,camera);
	for(var i = 0; i < numObjects; i++) {
		objectPosition = orbitSpeed*objectInterval*i;    //    each object is individually updated
		objects[i].position.x = radius * (Math.cos(theta + objectPosition) * (Math.pow(5,Math.cos(theta+objectPosition)) - 2 * Math.cos(4 * (theta+objectPosition)) - Math.pow(Math.sin((theta+objectPosition)/12),4)));
		objects[i].position.y = radius * (Math.sin(theta + objectPosition) * (Math.pow(5,Math.cos(theta+objectPosition)) - 2 * Math.cos(4 * (theta+objectPosition)) - Math.pow(Math.sin((theta+objectPosition)/12),4)));
		objects[i].position.z = centerZ + radius * Math.sin(theta + objectPosition) - radius*1*(Math.sin((radius/radius + 3) * (theta + objectPosition)));
	}
	group.rotation.x += .002;
	group.rotation.y += .004;
	group.rotation.z += .008;
	theta += (orbitSpeed*direction);
}