BAM Weblog

GDD HTML5 Challenge

Brian McKenna2011-08-14

This week I entered the Google Developer Day HTML5 challenge. The goal was to use HTML5 to do something interesting with the Google Developer Day logo (a dymaxion map):

Some restrictions:

I came up with the idea of using WebGL to transform the logo into the Sydney Opera House. This is what I made:

Implementation

I first looked at three.js to see what options there were for using 3D data and animating it. I found that morph animation was added to three.js as part of the RO.ME project. Perfect!

I imported the SVG logo into Blender. I had some troubles at first but it imported nicely after deleting the text from the vector. The next problem was that each edge had many unnecessary vertices.

I tried extruding the mesh but the polycount increased to about 5,000 - not very acceptable for morphing. I minimised the original polycount largely by using the Decimate modifier. Decimate would close up a few of the small holes so I decreased the polycount there by manually merging vertices. I eventually got the extruded polycount down to about 300.

For animation, I added a photo of the Opera House as a background for reference. I used shape keys to transform the triangles to corresponding positions/sizes.

To export, I just had to step through the timeline and export each frame separately. This created 10 obj files that I could use with the three.js conversion script:

python convert_obj_three.py -i frame_00.obj -o Visual.js -m "frame*.obj"

The model could then be used with three.js:

var loader = new THREE.JSONLoader(true);
loader.load({
  model: "Visual.js",
  callback: function(geometry) {
    // Create material and add to scene
  }
});

I wanted animation to be achieved through "scrubbing" the mouse across the X axis. That was pretty easy to implement using three.js morph targets:

var currentFrame = Math.floor(ratio * framesCount);
var transitionAmount = (ratio * framesCount) % 1;

mesh.morphTargetInfluences[currentFrame] = 1 - transitionAmount;
mesh.morphTargetInfluences[currentFrame + 1] = transitionAmount;

To finish it off, I added some animated three.js particles, a CSS3 gradient for the background and some simple visual cues. I've put my entry live and pushed the code to Bitbucket.

Please enable JavaScript to view the comments powered by Disqus.