Ambimation

Posted by oliver
Fri, 05/02/2008 - 02:43

This is an ambigram by Scott Kim, vectorized by Miles Steele, cleaned up by Dan Lewis, and put inside an OpenLaszlo application. (If you don't see it, click here.)

Trackback URL for this post:

http://osteele.com/trackback/165

Comments

Anonymous - Fri, 05/02/2008 - 07:43

Isn't Scott Kim one of the people interviewed in Programmers at Work? Cool.

Mind giving a few details on how you implemented this?

oliver - Fri, 05/02/2008 - 11:38

Thanks! It’s an OpenLaszlo application; the core looks like this:

<canvas>
  <include href="filter-effects.lzx"/>
  <class name="oflip"
	 width="${canvas.width}" height="${canvas.height}"
	 resource="oflip.swf" stretches="both"/>
    <view id="outer" x="${canvas.width/2}" y="${canvas.height/2}">
      <view id="rotor">
	<oflip id="inner"
	       x="${-canvas.width/2}" y="${-canvas.height/2}"
	       onclick="spin()">
	  <BlurFilterEffect name="fx"/>
	</oflip>
      </view>
    </view>
    <script>
      function spin() { rotor.animate(‘rotation’, 180, 1500, true) }
    </script>
</canvas>

class defines a view that’s scaled to the canvas size and that embeds a Flash movie of the image. The three levels of view hierarchy are because ‘rotation’ is relative to the origin (the upper left corner); the x and y on inner place the center of the image at the origin of the rotor, and the x and y on outer place the origin of the rotor at the center of the canvas. With matrices you rotate around a point by sandwiching the rotation between a translation and its inverse; instead I represent each transformation as a view and let the rendering engine do this, so that I can animate the rotation attribute and let the animation system handle the rest.

To get the shadow, move the x and y from inner to the definition of oflip in the code above, and then make two more copies of oflip right above rotor. An interval timer copies the rotations from inner -> s1 -> s2 on each frame.

      <view id="shadows">
        <view id="s2" opacity="0.25"><oflip/></view>
        <view id="s1" opacity="0.5"><oflip/></view>
      </view>

Mouse tracking uses Math.atan2 and the mouse position relative to outer. Motion blur animates the blur effect’s blur radius up to 4 when the image is spinning and back down to 0 when it stops. Both of these piggy-back on the same interval timer that makes the shadow. I tried to turn off the effects when the frame rate got slow, but I don’t think this worked, and I ran out of time.