GDD HTML5 Challenge
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:
- Only HTML5; no plugins
- Related to the location of the Developer Day
- Licensed under the Creative Commons Attribution 3.0 Unported License
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.