Fl020_DotsDemo.as (Main)

/**
 * @date    01/11/2008
 * @author    borealkiss    
 * @see     http://boreal-kiss.com/flash/ex/50/
 */ 
package {
    import flash.display.Sprite;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
    import flash.geom.PerspectiveProjection;
    import com.borealkiss.display.dots.Dots;
    import com.borealkiss.display.dots.MultiTori;
    
    [SWF(width="700",height="500",backgroundColor="0x0")]
    
    public class Fl020_DotsDemo extends Sprite{
        private var _projectionMatrix:Matrix3D;
        private var _primitive:Dots;
        private var _scene:Sprite;
        private var _canvasBitmap:BitmapData;
        
        /**
         * Constructor
         */ 
        public function Fl020_DotsDemo(){
            init();
        }
        
        private function init():void{
            //Canvas the same as stage in size.
            _canvasBitmap = new BitmapData(stage.stageWidth,stage.stageHeight,false,0x0);
            addChild(new Bitmap(_canvasBitmap));
            
            //Invisible scene in motion
            _scene = new Sprite();
            _scene.transform.matrix3D = new Matrix3D();
                        
            //Primitive            
            _primitive = new MultiTori(0.9,0.05,15000);
            
            var pp:PerspectiveProjection= new PerspectiveProjection();
            pp.fieldOfView = 100;
            _projectionMatrix = pp.toMatrix3D();
            
            addEventListener(Event.ENTER_FRAME,drawBitmap);
        }
        
        private function drawBitmap(e:Event):void{
            rotate(_scene);
               var world:Matrix3D = _scene.transform.matrix3D.clone();
            world.append(_projectionMatrix);
            var projectedVerts:Array = project3D(_primitive.vertices,world);
            
            _canvasBitmap.fillRect(_canvasBitmap.rect,0x0);
            for (var i:int=0; i<projectedVerts.length; i++){
                   var v:Vector3D = projectedVerts[i];
                   var x:Number = _canvasBitmap.width/2 + v.x;
                   var y:Number = _canvasBitmap.height/2 + v.y;
                   _canvasBitmap.setPixel(x,y,getColor(x,y));
               }
        }
       
        private function project3D(verts:Array,world:Matrix3D):Array{
            var results:Array = new Array();
               for (var i:int=0; i<verts.length; i++){
                   var v:Vector3D = world.transformVector(verts[i]);
                   results.push(v);
               }
               return results;
        }
        
        private function rotate(target:Sprite):void{
            var dx:Number = (mouseX - stage.stageWidth/2);
            var dy:Number = (mouseY - stage.stageHeight/2);
            target.rotationX = 0.5*dy;
            target.rotationY = -0.8*dx;
        }
        
        private function getColor(x:Number,y:Number):uint{
            var r:int = 255 * Math.random();
            var g:int = 255*x/_canvasBitmap.width;
            var b:int = 255*y/_canvasBitmap.height;
            return r << 16 | g << 8 | b;
        }
    }
}

com.borealkis.display.dots.Dots.as (Abstract)

package com.borealkiss.display.dots{
    import flash.errors.IllegalOperationError;
    
    /**
     * Abstract class.
     */ 
    public dynamic class Dots{
        protected var _vertices:Array;
        public function get vertices():Array{
            return _vertices;
        }
        public function set vertices(value:Array):void{
            _vertices = value
        }
        
        /**
         * Constructor
         */ 
        public function Dots(){
            if(Object(this).constructor == Dots){
                throw new IllegalOperationError("Abstract class  must be inherited in a subclass.");
            }
        }
    }
}

com.borealkis.display.dots.Torus.as

package com.borealkiss.display.dots{
    import flash.geom.Vector3D;
    import com.borealkiss.display.dots.Dots;
    
    public class Torus extends Dots{        
        protected var _majorRadius:Number;
        public function get majorRadius():Number{
            return _majorRadius;
        }
        public function set majorRadius(value:Number):void{
            _majorRadius = value;
            init();
        }
        
        protected var _minorRadius:Number;
        public function get minorRadius():Number{
            return _minorRadius;
        }
        public function set minorRadius(value:Number):void{
            _minorRadius = value;
            init();
        }
        
        protected var _totalPoints:int;
        public function get totalPoints():int{
            return _totalPoints;
        }
        
        /**
         * Constructor
         * 
         * @param majorRadius Major radius of a torus (i.e., radius of a donut)
         * @param minorRadius Minor radius of the torus (i.e., thickness of the donut)
         * @param totalPoints Total rendering points on the torus's surface.
          */
        public function Torus(majorRadius:Number,minorRadius:Number,totalPoints:int){
            _majorRadius = majorRadius;
            _minorRadius = minorRadius;
            _totalPoints = totalPoints;
            init();
        }
        
        protected function init():void{
            this.vertices = new Array();
            for (var i:int=0; i<_totalPoints; i++){
                var vertex:Vector3D = randomPlot();
                this.vertices.push(vertex);
            }
        }
        
        /**
         * Calculate a random poit on the surface of the torus.
         * @return Vector3D
         */ 
        protected function randomPlot():Vector3D{
            var majorTheta:Number = 2*Math.PI*Math.random();//0<=phi<=2PI
            var minorTheta:Number = 2*Math.PI*Math.random();//0<=phi<=2PI
            var x:Number = (_majorRadius + _minorRadius*Math.cos(minorTheta))*Math.cos(majorTheta);
            var y:Number = _minorRadius*Math.sin(minorTheta);    
            var z:Number = (_majorRadius + _minorRadius*Math.cos(minorTheta))*Math.sin(majorTheta);
            return new Vector3D(x,y,z);
        }
    }
}

com.borealkis.display.dots.MultiTori.as

package com.borealkiss.display.dots{
    import flash.geom.Vector3D;
    import flash.geom.Matrix3D;
    import com.borealkiss.display.dots.Torus;
    
    /**
     * Multiple tori inheriting from Torus class.
     */ 
    public class MultiTori extends Torus{
        
        /**
         * Constructor
         */ 
        public function MultiTori(majorRadius:Number, minorRadius:Number, totalPoints:int){
            super(majorRadius, minorRadius, totalPoints);
        }
        
        override protected function init():void{
            this.vertices = new Array();
            for (var i:int=0; i<_totalPoints; i++){
                var vertex:Vector3D = randomPlot();
                
                //Rotate along z-axis
                switch (i%4){
                    case 1:
                    vertex = rotateZ(vertex,45);
                    break;
                    
                    case 2:
                    vertex = rotateZ(vertex,90);
                    break;
                    
                    case 3:
                    vertex = rotateZ(vertex,135);
                    break;
                }                
                
                this.vertices.push(vertex);
            }
        }
        
        private function rotateZ(vector:Vector3D,degrees:Number):Vector3D{
            var mat:Matrix3D = new Matrix3D();
            mat.appendRotation(degrees,Vector3D.Z_AXIS);
            return mat.transformVector(vector);
        }
    }
}
Powered by blog Boreal Kiss 2008.