Second Story

In an attempt to get a creative programming job at Second Story I put together a work sample (  700 lines of code ) demonstrating some advanced JavaScript programming techniques applied to 3D graphics on the web. The sample uses three.js & tween.js to transform the 2D Second Story logo into a 3D experience.

See Work Sample Here

Currently there are several JavaScript libraries being developed that provide a game engine type framework for working with 3D & 2D content ( CopperLicht, KickJS, ingenioJS, CAAT, Scirra, Turbulenz, ...  ). This project doesn't use any current game engine frameworks. In this sample I have written my own framework.  As I learn about 3D interactive programming, when I have time I go out of my way to re-create common game engine tools to better understand how things work.

Let me highlight some aspects of this project that I find interesting.

Subscribing / Unsubscribing Action to the Animation Frame

When working with anything that is rendered live there is code that loops through tasks that need to be preformed in each rendered frame. In this work sample you can see that there are several things going on that need to be run in each frame:

In order to create a 3D framework that has the ability to add new animations based on game triggers I needed to create a mechanism to connect & remove executable code to each frame without manually writing to the animation loop.

The solution I came up with uses a publisher / subscribing JavaScript design pattern. The design pattern structure is from Essential JS Design Patterns; a reference I often use. I re-wrote the pattern to be more compact and efficient for animation tasks. My publisher / subscriber module looks like this:

var pubsub = {};

(function(q) {

 var objs = [];

 var uid = 0;

 q.publish = function() {

  for (var i in objs) {

   objs[i].obj.step();

  }

 };

 q.subscribe = function( obj ) {

  objs.push( {id: uid, obj: obj} );

  uid++;

  return uid - 1;

 };

 q.unsubscribe = function( id ) {

  for (var i in objs) {

   if ( objs[i].id == id ) {

    objs.splice(i,1);

   }

  }

 };

}( pubsub ));

The pubsub module can do 3 things:

When the module is published all of the subscribed objects are looped and their .step() methods are called. All animations & time dependent logic will be stored in an object that will contain a method .step() that will store all animation frame related tasks.

The animation frame loop for the whole project looks like this:

function animate() {

 requestAnimationFrame( animate );

 pubsub.publish();

 TWEEN.update();

 renderer.render( scene, camera );

}

Generating Controlled "Random" Patterns

In JavaScript programs it's easy to generate random patterns using Math.random(). In this work sample I use Math.random() to generate random colors and sizes for all of the particles that are shot out of the Second Story windows. 

What if I wanted to make the windows flash to the beat of a song? I created a simple re-usable piece of code that I applied to several constructors in my project that let me do just that. Let's take a look at the Flash constructor:

var Flash = function (obj, color, pattern) {

 // assume object is a THREE.Material

 this.object = obj;

 this.color = color;

 this.startcolor = this.object.color.getHex();

 this.clock = new THREE.Clock();

 this.subToken;

 this.pattern = pattern; // [0] used for internal tracking, must be 0

 //this.pattern = [0,0.1,0.1,0.3,0.3,0.1,0.5];

};

Flash.prototype.start = function () {

 this.clock.start();

 this.subToken = pubsub.subscribe(this);

};

Flash.prototype.stop = function () {

 this.clock.stop();

 pubsub.unsubscribe(this.subToken);

 this.object.color = new THREE.Color(this.startcolor);

 this.pattern[0] = 0; // reset pattern

};

Flash.prototype.step = function () {

 var i = this.pattern[0];

 if (this.clock.getElapsedTime() >= this.pattern[i + 1]) {

  if (i == this.pattern.length - 2) {

   this.pattern[0] = 0;

  }

  // toggle color

  if (this.object.color.getHex() == this.startcolor ){

   this.object.color = new THREE.Color(this.color);

  } else {

   this.object.color = new THREE.Color(this.startcolor);

  }

  this.pattern[0]++;

  this.clock = new THREE.Clock();

  this.clock.start();

 }

};

The flash constructor creates an animation object that controls a THREE.Material color based on a pattern. The pattern is specified at the creation of the animation object and it takes the form of:

 [0, t1, t2, t3 ... ]

Once started the code will wait t1 seconds then toggle the color of the TREE.Material, then from that time it will wait t2 seconds and it will toggle back to the original color. It will repeat until it reaches the end of the array and then will start at t1 again. 

Notice how the start() and stop() methods use my pubsub module to attach the animation logic to run in each frame.

To instantiate a flash controller in my sample you would need to write something like this:

var flash1 = new Flash (building.window1.mat, 0xE6DF1C, [0,0.1,0.5,0.5,0.1,0.1,0.5,0.5,0.1]);

This mechanism is very light weight but it allowed me to create very complicated repeatable patterns that can match one another if needed. You will see this code re-used several times in this sample project.