Math and (Quasi) Physics in Action Script 3

3D renderer (1) - projecting 3D points to 2D

A sketch from a project to buid a 3D rendering package just for learning porpose.
The camera(or point of view) can be rotated with arrow, q and w keys.

Main.as

package {
  import flash.display.*;
  import flash.events.*;
  import flash.geom.Point;
  import flash.ui.*;
  public class Main extends Sprite {
    private var points:Array,lines:Array;
    private var vp:Pp3dViewPoint;
    private var va:Number = Math.PI / 180;
    private var canvas:Sprite;
    private var keyNum:uint;
    public function Main() {
      addChild(canvas = new Sprite());
      canvas.x = stage.stageWidth / 2;
      canvas.y = stage.stageHeight / 2;
      addEventListener(Event.ENTER_FRAME, h_enterFrame);
      stage.addEventListener(KeyboardEvent.KEY_DOWN, h_keyDown);
      stage.addEventListener(KeyboardEvent.KEY_UP, h_keyUp);
    
      vp = new Pp3dViewPoint();
      defineShape();
    }
    
    private function h_keyDown(evt:KeyboardEvent):void {
      keyNum = evt.keyCode;
    }
    
    private function h_keyUp(evt:KeyboardEvent):void {
      keyNum = 0;
    }
    
    protected function h_enterFrame(evt:Event):void {
      var g:Graphics = canvas.graphics;
      g.clear();
      var p:Point;
      var op:Point;
      
      switch (keyNum) {
        case Keyboard.LEFT:
        vp.rotationY = Math.max(-30, vp.rotationY - 1);
        break;
        case Keyboard.RIGHT:
        vp.rotationY = Math.min(30, vp.rotationY + 1);
        break;
        case Keyboard.UP:
        vp.rotationX = Math.max(-30, vp.rotationX - 1);;
        break;
        case Keyboard.DOWN:
        vp.rotationX = Math.min(30, vp.rotationX + 1);
        break;
        case 81:
        vp.rotationZ = Math.max(-30, vp.rotationZ - 1);
        break;
        case 87:
        vp.rotationZ = Math.min(30, vp.rotationZ + 1);
        break;
      }
      
      var temp:Array = new Array();
      var p1:Pp2dPoint, p2:Pp2dPoint;
      for (var i:uint = 0; i < points.length; i ++) {
        temp.push(vp.projectTo2d(points[i]));
      }
      for (i = 0; i < lines.length; i ++) {
        p1 = temp[lines[i][0]];
        p2 = temp[lines[i][1]];
        g.lineStyle(0,0xDDDDDD);
        g.moveTo(p1.x, p1.y);
        g.lineTo(p2.x, p2.y);
      }
    }
    
    private function defineShape():void {
      points = [  new Pp3dPoint(-100,-100,-100), 
                new Pp3dPoint(-100,100,-100),
                new Pp3dPoint(100,100,-100),
                new Pp3dPoint(100,-100,-100),
                new Pp3dPoint(-100,-100,100), 
                new Pp3dPoint(-100,100,100),
                new Pp3dPoint(100,100,100),
                new Pp3dPoint(100,-100,100),
                
                new Pp3dPoint(200,-100,-100), 
                new Pp3dPoint(200,100,-100),
                new Pp3dPoint(400,100,-100),
                new Pp3dPoint(400,-100,-100),
                new Pp3dPoint(200,-100,100), 
                new Pp3dPoint(200,100,100),
                new Pp3dPoint(400,100,100),
                new Pp3dPoint(400,-100,100),
                
                new Pp3dPoint(-400,-100,-100), 
                new Pp3dPoint(-400,100,-100),
                new Pp3dPoint(-200,100,-100),
                new Pp3dPoint(-200,-100,-100),
                new Pp3dPoint(-400,-100,100), 
                new Pp3dPoint(-400,100,100),
                new Pp3dPoint(-200,100,100),
                new Pp3dPoint(-200,-100,100)];
      
      lines = [  [0,1],[1,2],[2,3],[3,0],
              [4,5],[5,6],[6,7],[7,4],
              [0,4],[1,5],[2,6],[3,7],
              
              [8,9],[9,10],[10,11],[11,8],
              [12,13],[13,14],[14,15],[15,12],
              [8,12],[9,13],[10,14],[11,15],
              
              [16,17],[17,18],[18,19],[19,16],
              [20,21],[21,22],[22,23],[23,20],
              [16,20],[17,21],[18,22],[19,23]];
    }
    
    
  }
}

Pp3dPoint.as

package {
  public class Pp3dPoint  extends Pp3dObject{
    private var _x:Number, _y:Number,_z:Number;
    public function Pp3dPoint(x:Number = 0, y:Number = 0, z:Number = 0) {
      super(x , y, z);
     }
  }
}

Pp2dPoint.as

package {
  import flash.geom.Point;
  public class Pp2dPoint extends Point {
    private var _scale:Number;
    public function Pp2dPoint(x:Number = 0, y:Number = 0, s:Number = 1) {
       super(x,y);
       _scale = s;
     }
     public function get scale():Number { return _scale }
     public function set scale(n):void { _scale = n }
  }
}

Pp3dViewPoint.as

package {
  import flash.geom.*;
  public class Pp3dViewPoint extends Pp3dObject {
    private var _fl:Number;
    private var _zoom:Number;
    public function Pp3dViewPoint(x:Number = 0, y:Number = 0, z:Number = -600) {
       super(x,y,z);
       zoom = 5;
       focalLength = 200;
    }
    public function set focalLength(n:Number):void {
      _fl = n;
    }
    public function set zoom(n:Number):void {
      _zoom = n;
    }
    public function get focalLength():Number {
      return _fl;
    }
    public function get zoom():Number {
      return _zoom;
    }
    
    public function projectTo2d(p3d:Pp3dPoint):Pp2dPoint {
      var p2d:Pp2dPoint = new Pp2dPoint();
      var zero:Pp3dPoint = new Pp3dPoint();
      p3d = new Pp3dPoint(p3d.x - x, p3d.y - y, p3d.z - z);
      p3d = rotateX(p3d, -1);
      p3d = rotateY(p3d, -1);
      p3d = rotateZ(p3d, -1);
      p2d.scale = _fl / p3d.z / 2 * zoom;
      p2d.x = p3d.x  * p2d.scale;
      p2d.y = p3d.y * p2d.scale;
      return p2d
    }
  }
}