The beauty of FIVe3D (other than its size, ease of use, and a few other things) is how easily extendable it is. For a previous experiment, I needed a way to draw an arc in 3D space. This isn’t something that FIVe3D provides, and in fact it was a little challenging to find the math I needed. However! Once I found it, I was able to easily use FIVe3D’s drawing API to put it into action.
The arc code, by the way, is from an ancient AS2 function called drawWedge() by Ric Ewing, which drew pizza-style wedges. Close enough. With a little elbow grease I managed to bend it to my will. Here’s an example of a bunch of arcs doing their thing:
And here is the code that draws the arc, which extends FIVe3D’s Drawing class. This could probably be cleaned up a bit, since I run through Ric’s arc code twice to create the thing; it wasn’t originally that way, but getting the fill on the inside of the arc proved more difficult than I originally thought.
/** * An extension of Mathieu Badimon's FIVe3D Drawing class. * This class draws an additional shape onto a FIVe3D Graphics3D instance. * This class includes code from by Ric Ewing. * * @author Zack Jordan * { P I X E L W E L D E R S } */ package com.pixelwelders.five3d { import five3D.display.Graphics3D; import five3D.utils.Drawing; public class PXWDrawing extends Drawing { /** * Draws a wedge shape onto a Graphics3D instance. * * @param graphics a Graphics3D instance on which to draw * @param x x position of the center of this wedge * @param y y position of the center of this wedge * @param startAngle the angle of one straight line of this wedge * @param arc the angle (in degrees) of the total arc of this wedge * @param xRadius the external radius along the x axis * @param yRadius the external radius along the y axis * @param innerXRadius the internal radius along the x axis * @param innerYRadius the internal radius along the y axis * @param color the color of the wedge fill * @param fillAlpha the alpha value of the wedge fill * * @return nothing */ static public function drawWedge( graphics:Graphics3D, x:Number, y:Number, startAngle:Number, arc:Number, xRadius:Number, yRadius:Number, innerXRadius:Number, innerYRadius:Number, color:uint = 0xFF0000, fillAlpha:Number = .5 ): void { var segAngle : Number var theta : Number var angle : Number var angleMid : Number var segs : Number var bx : Number var by : Number var cx : Number var cy : Number; segs = Math.ceil( Math.abs( arc ) / 45 ); segAngle = arc / segs; theta = -( segAngle / 180 ) * Math.PI; angle = -( startAngle / 180 ) * Math.PI; graphics.lineStyle( 1, 0x000000, 1 ); graphics.beginFill( color, fillAlpha ); graphics.moveTo( x + Math.cos( startAngle / 180 * Math.PI ) * innerXRadius, y + Math.sin( -startAngle/180 * Math.PI ) * innerYRadius ); // line 1 graphics.lineTo( x + Math.cos( startAngle / 180 * Math.PI ) * xRadius, y + Math.sin( -startAngle / 180 * Math.PI ) * yRadius ); // outer arc for ( var i:int = 0; i < segs; i++ ) { angle += theta; angleMid = angle - ( theta / 2 ); bx = x + Math.cos( angle ) * xRadius; by = y + Math.sin( angle ) * yRadius; cx = x + Math.cos( angleMid ) * ( xRadius / Math.cos( theta / 2 ) ); cy = y + Math.sin( angleMid ) * ( yRadius / Math.cos( theta / 2 ) ); graphics.curveTo( cx, cy, bx, by ); } // line 2 graphics.lineTo( x + Math.cos( ( startAngle + arc ) / 180 * Math.PI ) * innerXRadius, y + Math.sin( -( startAngle + arc ) / 180 * Math.PI ) * innerYRadius ); theta = -( segAngle / 180 ) * Math.PI; angle = -( ( startAngle + arc ) / 180 ) * Math.PI; // inner arc for (var j:int = 0; j < segs; j++ ) { angle -= theta; angleMid = angle + ( theta / 2 ); bx = x + Math.cos( angle ) * innerXRadius; by = y + Math.sin( angle ) * innerYRadius; cx = x + Math.cos( angleMid ) * ( innerXRadius / Math.cos( theta / 2 ) ); cy = y + Math.sin( angleMid ) * ( innerYRadius / Math.cos( theta / 2 ) ); graphics.curveTo( cx, cy, bx, by ); } graphics.endFill(); } } }
Another note on this experiment: the SWF is 16k. Holy crap.
That’s pretty cool. It is strange that there is no better way to draw an arc. I still don’t know why Adobe sticks with Bezier curves rather than something nicer. It must be harder than I think to implement.
[…] engine used is Five3D + a Wedge class made by pixelwelders specially for this 3D engine […]
Rational Bezier curves can exactly represent arcs. To be honest, I’m not sure if Adobe uses rational Bezier curves, or if they expose the weights, but Bezier curves in and of themselves are much more expressive than arcs.
If you’re interested, I’d be happy to help.
From what I’ve read, the Flash player uses multiple quadratic Bézier curves to approximate all curves. Apparently a quadratic curve is significantly faster to calculate and draw than a cubic curve (which is definitely more expressive). So I believe it’s a speed thing rather than a difficulty thing.
With a quadratic curve, the most of a circle that I can draw appears to be 45 degrees. With a cubic curve, I think it would be possible to draw 90- and of course, it would be possible to draw much more interesting shapes. Then again, maybe I’m wrong; I’m no mathematician.
Thanks for doing the hard work of making arcs possible in the FIVe3D engine. I altered the class slightly and used it to create an interface that shows all the samples used in a song off of Girl Talk’s latest album, Feed the Animals.
http://media.mgnetwork.com/creativeservices/design_tests/five3d/five3d_song_arc.htm
very impressing !
However, ihave a question about five3d and i dont know where ask this, so i try here….
I just want to know if it’s possible to attach a vector graphic form the library to a sprite 3d…i have a logo in vector and i want to convert it in a 3dsprite…it’s possible or we are obligated to use bitmap ? thanks