(AS3) Making 3D function from the scratch (2)

| No Comments | No TrackBacks
What I made is a sample to understand how 3D objects are renderd by comparing two classes, one that uses the built in API of "Flash Player 10" (FP10api3DSquare) and another implements similar functions made from the scratch(My3DSquare).
Each of the classes draws a white square that can be rotated and be seen from different distances by changing the values in the spin boxes.



Test3D.as(main class)

package {
    import flash.display .Sprite;
    import flash.events.Event;
    public class Test3D extends Sprite {
        var squareA:My3DSquare;
        var squareB:FP10api3DSquare;
       
        public function Test3D() {
            squareA = new My3DSquare();
            squareA.x = 100;
            squareA.y = 100;
            addChild(squareA);
            squareB = new FP10api3DSquare();
            squareB.x = 300;
            squareB.y = 100;
            addChild(squareB);

            //add listeners to the NumericSteppers
            flA.addEventListener(Event.CHANGE, h_stepperChange);
            rxA.addEventListener(Event.CHANGE, h_stepperChange);
            ryA.addEventListener(Event.CHANGE, h_stepperChange);
            rzA.addEventListener(Event.CHANGE, h_stepperChange);
            flB.addEventListener(Event.CHANGE, h_stepperChange);
            rxB.addEventListener(Event.CHANGE, h_stepperChange);
            ryB.addEventListener(Event.CHANGE, h_stepperChange);
            rzB.addEventListener(Event.CHANGE, h_stepperChange);
        }
       
        private function h_stepperChange(evt:Event):void {
            switch(evt.target) {
                case flA:
                squareA.focalLength = evt.target.value;
                break;
                case rxA:
                squareA.rX = evt.target.value;
                break;
                case ryA:
                squareA.rY = evt.target.value;
                break;
                case rzA:
                squareA.rZ = evt.target.value;
                break;
                case flB:
                squareB.focalLength = evt.target.value;
                break;
                case rxB:
                squareB.rotationX = evt.target.value;
                break;
                case ryB:
                squareB.rotationY = evt.target.value;
                break;
                case rzB:
                squareB.rotationZ = evt.target.value;
                break;
            }
        }
    }
}

My3DSquare.as
package {
    import flash.display .Sprite;
    import flash.events.Event;
    public class My3DSquare extends Sprite {
        private var points:Array = [
                            {x:50,y:50,z:0},
                            {x:50,y:-50,z:0},
                            {x:-50,y:-50,z:0},
                            {x:-50,y:50,z:0}
                            ]
                         
        private var _focalLength:Number = 200, _rotationX:Number = 0, _rotationY:Number = 0, _rotationZ:Number = 0;
       
        public function My3DSquare() {
            draw();
        }
       
        public function set focalLength(n:Number):void {
            _focalLength = n;
            draw();
        }
        public function set rX(n:Number):void {
            _rotationX = n;
            draw();
        }
        public function set rY(n:Number):void {
            _rotationY = n;
            draw();
        }
        public function set rZ(n:Number):void {
            _rotationZ = n;
            draw();
        }
       
       
        private function draw():void {
            graphics.clear();
           
            var i:uint;
            var tPoints:Array = points.concat();;
            var point:Object = new Object;
           
            // rotate
            for (i = 0; i < points.length; i ++) {
                tPoints[i] = rotateX(tPoints[i], _rotationX);
                tPoints[i] = rotateY(tPoints[i], _rotationY);
                tPoints[i] = rotateZ(tPoints[i], _rotationZ);
            }
           
            // project to 2D and Draw
            var p:Object;
            var p3d:Object;
           
            graphics.beginFill(0xFFFFFF);
           
            for (i = 0; i < tPoints.length; i ++) {
                p3d = tPoints[i]
                p = p3Dto2D(p3d, _focalLength);
                if (i == 0) {
                    graphics.moveTo(p.x, p.y);
                } else {
                    graphics.lineTo(p.x, p.y);
                }
            }
            graphics.endFill();
        }
       
        private function rotateX(p3d:Object, angle:Number):Object {
            var p:Object = new Object();
            angle = angle /180 * Math.PI;
            p.x = p3d.x;
            p.y = Math.cos(angle) * p3d.y - Math.sin(angle) * p3d.z;
            p.z = Math.cos(angle) * p3d.z+ Math.sin(angle) * p3d.y;
            return p
        }
       
        private function rotateY(p3d:Object, angle:Number):Object {
            var p:Object = new Object();
            angle = angle /180 * Math.PI;
            p.x = Math.cos(angle) * p3d.x - Math.sin(angle) * p3d.z;
            p.y = p3d.y;
            p.z = Math.cos(angle) * p3d.z+ Math.sin(angle) * p3d.x;
            return p
        }
       
        private function rotateZ(p3d:Object, angle:Number):Object {
            var p:Object = new Object();
            angle = angle /180 * Math.PI;
            p.x = Math.cos(angle) * p3d.x - Math.sin(angle) * p3d.y;
            p.y = Math.cos(angle) * p3d.y+ Math.sin(angle) * p3d.x;
            p.z = p3d.z;
            return p
        }
       
        private function p3Dto2D(p3d:Object, _fl:Number):Object {
            var scale:Number;
            var p:Object = new Object();
            scale = _fl / (_fl + p3d.z);
            p.x = p3d.x  * scale;
            p.y = p3d.y * scale;
            return p
        }
       
    }
}

FP10api3DSquare
package {
    import flash.display .Sprite;
    import flash.events.Event;
    import flash.geom.PerspectiveProjection;
    import flash.geom.Point;
   
    public class FP10api3DSquare extends Sprite {
       
        public function FP10api3DSquare() {
            graphics.beginFill(0xFFFFFF);
            graphics.drawRect(-50,-50,100,100);
            graphics.endFill();
            addEventListener(Event.ADDED_TO_STAGE, h_addedToStage);
        }
       
        private function h_addedToStage(evt:Event):void {
            var pp:PerspectiveProjection = new PerspectiveProjection();
            pp.projectionCenter = new Point(300,100);
            pp.focalLength = 200;
            transform.perspectiveProjection = pp;
        }
       
        public function set focalLength(n:Number):void {
            transform.perspectiveProjection.focalLength = n;
        }
    }
}

Install flash player 10 or later if you don't see the sample movie.

No TrackBacks

TrackBack URL: http://www.kynd.info/cp-bin/mt/mt-tb.cgi/18

Leave a comment