package { import flash.display.Sprite; import flash.geom.Vector3D; import flash.geom.Point; [SWF(width=600, height=600, backgroundColor=0xFFFFFF)] /** * Demonstrates how to use Vector3D and local3DToGlobal() to render polygons in 3D space. * Also demonstrates how to calculate lighting of polygons based on orientation in relation * to virtual light source. */ public class graphic_flex_image_effects_06_Flex_DrawingPolygons extends Sprite { private static const LIGHT_DIRECTION:Vector3D = new Vector3D(0, 0, 1); private static const FACE_COLOR:uint = 0x9900FF; /** * Constructor. Centers sprite and kicks off creation of polygons. */ public function graphic_flex_image_effects_06_Flex_DrawingPolygons() { x = stage.stageWidth/2; y = stage.stageHeight/2; createPolygons(); } /** * Creates three polygons using collections of Vector3D points * and calls to custom drawPolygon() method. */ private function createPolygons():void { var vectors:Vector. = new Vector.(); vectors.push(new Vector3D(-250, -250, 0)); vectors.push(new Vector3D(-100, -250, 0)); vectors.push(new Vector3D(-100, -100, 0)); vectors.push(new Vector3D(-250, -100, 0)); drawPolygon(vectors); vectors = new Vector.(); vectors.push(new Vector3D(-50, -75, -50)); vectors.push(new Vector3D(50, -75, 50)); vectors.push(new Vector3D(50, 75, 50)); vectors.push(new Vector3D(-50, 75, -50)); drawPolygon(vectors); vectors = new Vector.(); vectors.push(new Vector3D(100, 160, 50)); vectors.push(new Vector3D(250, 160, 50)); vectors.push(new Vector3D(250, 180, -50)); vectors.push(new Vector3D(100, 180, -50)); drawPolygon(vectors); } /** * Draws a polygon based on the 3D points passed. * * @param vectors A collection of vectors defining a single planar polygon. */ private function drawPolygon(vectors:Vector.):void { // determines color based on polygon orientation in relation to light source var color:uint = getFaceColor(vectors); // converts 3D points to 2D coordinates on screen var points:Vector. = getPoints2D(vectors); // runs through all points and draws shape graphics.beginFill(color); graphics.moveTo(points[0].x, points[0].y); for (var i:uint = 1; i < points.length; i++) { graphics.lineTo(points[i].x, points[i].y); } // draw bak to initial point graphics.lineTo(points[0].x, points[0].y); graphics.endFill(); } /** * Converts 3D points to 2D screen coordinates. * * @param vectors A collection of 3D vector points. * * @return A collection of the 2D coordinates needed to represent the 3D points. */ private function getPoints2D(vectors:Vector.):Vector. { var points:Vector. = new Vector.; var point:Point; // runs through each point for each (var vector:Vector3D in vectors) { // convert the 3D point to a global 2D coordinate point = local3DToGlobal(vector); // convert back to local coordinate space and push into vector points.push(globalToLocal(point)); } return points; } /** * Determines color based on polygon orientation in relation to light source. * * @param vectors A collection of vectors defining a single planar polygon. * * @return The darkened color of the polygon based on its orientation. */ private function getFaceColor(vectors:Vector.):uint { // find two edges of plane in order to determine normal vector var U:Vector3D = getEdge(vectors[1], vectors[0]); var V:Vector3D = getEdge(vectors[1], vectors[2]); // find normal of plane using edges var crossProduct:Vector3D = U.crossProduct(V); // determine angle between plane's normal and light source's directional vector var angle:Number = Vector3D.angleBetween(crossProduct, LIGHT_DIRECTION); // angle will be between 0 and PI, so divide by PI to get between 0 and 1 var brightness:Number = angle/Math.PI; // darken color based on its orientation return darkenColor(FACE_COLOR, brightness); } /** * Darkens the specified color by the specified percentage. * * @param color The color to darken. * @param percent The percent by which to darken the color. * * @return The darkened color. */ private function darkenColor(color:uint, percent:Number):uint { // separate each color component var red:uint = color >> 16 & 0xFF; var green:uint = color >> 8 & 0xFF; var blue:uint = color & 0xFF; // reduce each component by percentage red *= percent; green *= percent; blue *= percent; return red << 16 | green << 8 | blue; } /** * Returns a vector describing the edge between two points on a polygon. * * @param v1 One vector point on the polygon. * @param v1 A second vector point on the polygon. * * @return A vector describing the edge between two points on a polygon. */ private function getEdge(v1:Vector3D, v2:Vector3D):Vector3D { // find distance between each coordinate var x:Number = v1.x-v2.x; var y:Number = v1.y-v2.y; var z:Number = v1.z-v2.z; return new Vector3D(x, y, z); } } }