You know, you’d think with all the 3D crap I’ve been playing with lately that I actually like the stuff. I’m really not that into 3D work in Flash. I just had to try out Augmented reality when it first came around and seemed to get sucked into it all. I guess it really is interesting. Just wish I understood it all beyond utilizing libraries written by others. Ah well. That bit of rambling aside, I was looking around the other day for a way to extrude text with Papervision3D, when a bit of googling led me to Den Ivanov’s awesome ExtrudedBitmap class. This seemed like it would do just what I needed. My first thought was to put the text I wanted into a .png file and load it using Ivanov’s class. But poking through the code a bit, I thought, why bother loading something – why not simply pass the class an image directly and let it do its thing? So, I played around a little bit and came up with this ExtrudedImage class (still 98.23% Ivanov’s work, but still)…
package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.DisplayObject; import flash.display.Loader; import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.net.URLRequest; import org.papervision3d.core.proto.MaterialObject3D; import org.papervision3d.materials.BitmapMaterial; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Plane; /** * @author den ivanov * www.cleoag.ru * den [at] cleoag.ru * * slightly modified by devon wolfgang * www.onebyonedesign.com * */ public class ExtrudedImage extends DisplayObject3D { private var front:Plane; private var back:Plane; private var sides:ExtrudedBitmapSides; private var zoom:int; private var image:BitmapData; private var depth:Number; private var loader:Loader; private var useSmooth:Boolean; public function ExtrudedImage(img:DisplayObject, useSmooth:Boolean = false, zoomRatio:int = 20, depth:Number = 100) { super(); this.zoom = zoomRatio; this.depth = depth * .5; this.useSmooth = useSmooth; extrudeImage(img); } private function extrudeImage(img:DisplayObject):void { clear(); image = new BitmapData(img.width, img.height, true, 0x00000000); image.draw(img); var m1:BitmapMaterial = new BitmapMaterial(image); m1.smooth = useSmooth; front = new Plane(m1, image.width * zoom, image.height * zoom, Math.floor(image.width * .25), Math.floor(image.height * .25)); front.name = "front"; var m2:BitmapMaterial = new BitmapMaterial(image); m2.smooth = useSmooth; m2.opposite = true; back = new Plane(m2, image.width * zoom, image.height * zoom, Math.floor(image.width * .25), Math.floor(image.height * .25)); back.name = "back"; front.z = -depth; back.z = depth; addChild(front); addChild(back); var m3:BitmapMaterial = new BitmapMaterial(image); m3.smooth = useSmooth; sides = new ExtrudedBitmapSides(m3, image, zoom, depth); sides.name = "sides"; addChild(sides); } override public function get material():MaterialObject3D { return front.material } override public function set material(value:MaterialObject3D):void { front.material = value; back.material = value; sides.material = value; } public function clear() : void { if (image != null) { removeChild(sides); removeChild(front); removeChild(back); sides = null; front = null; back = null; image.dispose(); } } } }
With these changes, now intstead of passing the class a url to an image file, you just pass it an image (DisplayObject instance, that is) directly. This means you can create DisplayObjects on the fly (including those with text) and make 3D extrusions of them. Also, by giving the PV3D items inside the ExtrudedImage class names (“front”, “back”, and “sides”) you can reference those items and swap out their materials (or add a shader to them or what have you). Sort of like this:
var extrudedImage = new ExtrudedImage(someSprite, true, 4); var shader:GouraudShader = new GouraudShader(_light); var shadeMat:ShadedMaterial = new ShadedMaterial((extrudedImage.material) as BitmapMaterial, shader); shadeMat.smooth = true; extrudedImage.getChildByName("front").material = shadeMat;
So, after coming up with text effect I was looking for in the first place, I played around a bit more and came up with little example app. Use the drawing tool to the left to create a work of art (click the top black square to change the color, the black circle to change the brush shape, the slider to change the brush size, and draw on the graph paper). When finished, click “save”, give it a span of time or two, then check out your creation in glorious 3D to the right (use the mouse to hover around a bit and mousewheel to zoom in/out). Pretty freaking nifty. Of course all the credit really goes to Den Ivanov. I have next to no idea how it works. 🙂
[kml_flashembed fversion=”10.0.0″ movie=”http://blog.onebyonedesign.com/wp-content/uploads/2009/09/foo.swf” targetclass=”flashmovie” publishmethod=”static” width=”450″ height=”200″]
[/kml_flashembed]
Date:
7 September, 2009