package com.dafishinsea.experiments { import flash.display.Sprite; import flash.events.Event; import flash.geom.Matrix3D; import flash.geom.PerspectiveProjection; import flash.geom.Point; import flash.geom.Utils3D; import flash.geom.Vector3D; /** * try pushing and popping matrices */ [SWF(backgroundColor="0x000000", width="800", height="600", frameRate="30")] public class MatrixStack extends Sprite { private var stack:Array = new Array(); private var vertices:Vector. = new Vector.(); private var commands:Vector. = new Vector.(); private var points:Vector. = new Vector.(); private var uvts:Vector. = new Vector.(); private var modelViewMatrix:Matrix3D = new Matrix3D(); private var perspective:PerspectiveProjection; private var projectionMatrix:Matrix3D; private var canvas:Sprite = new Sprite(); private var rx:Number = 0; private var ry:Number = 0; private const X_AXIS:Vector3D = new Vector3D(1,0,0); private const Y_AXIS:Vector3D = new Vector3D(0,1,0); private const Z_AXIS:Vector3D = new Vector3D(0,0,1); private var numverts:int = 0; private var numcommands:int = 0; public function MatrixStack() { init(); } private function init():void { canvas.x = stage.stageWidth/2; canvas.y = stage.stageHeight/2; addChild(canvas); perspective = new PerspectiveProjection(); perspective.fieldOfView = 50; addEventListener(Event.ENTER_FRAME, onEnterFrame); stage.addEventListener(Event.RENDER, render); /*update(); stage.invalidate()*/ } private function onEnterFrame(event:Event):void { ry++; rx++; update(); stage.invalidate(); } private function update():void { vertices = Vector.([]); commands = Vector.([]); modelViewMatrix = new Matrix3D(); //apply global rotations modelViewMatrix.prependRotation(ry, Y_AXIS); modelViewMatrix.prependRotation(rx, X_AXIS); //shift over half a square-width modelViewMatrix.prependTranslation(-50,-50,50); //goto origin of modelview matrix move(0,0,0); //middle 3 push(); drawCube(); pop(); push(); move(150,0,0); drawCube(); pop(); push(); move(-150,0,0); drawCube(); pop(); } private function drawCube():void { //draw cube //back drawSquare(); //left push(); rotate(0,90,0); drawSquare(); pop(); //top push(); rotate(-90,0,0); drawSquare(); pop(); //right push(); move(100,0,0); rotate(0,90,0); drawSquare(); pop(); //bottom push(); move(0,100,0); rotate(-90,0,0); drawSquare(); pop(); //front (not really necessary) push(); move(0,0,-100); drawSquare(); pop(); } private function drawSquare():void { draw(100,0,0); rotate(0,0,90); draw(100,0,0); rotate(0,0,90); draw(100,0,0); rotate(0,0,90); draw(100,0,0); rotate(0,0,90);//return to starting orientation } private function rotate(angleX:Number, angleY:Number, angleZ:Number):void { modelViewMatrix.prependRotation(angleX, X_AXIS); modelViewMatrix.prependRotation(angleY, Y_AXIS); modelViewMatrix.prependRotation(angleZ, Z_AXIS); } private function draw(xd:Number, yd:Number, zd:Number):void { var tv:Vector3D = modelViewMatrix.transformVector(new Vector3D(xd,yd,zd)); vertices.push(tv.x, tv.y, tv.z); commands.push(2); modelViewMatrix.prependTranslation(xd,yd,zd); } private function move(xd:Number, yd:Number, zd:Number):void { var tv:Vector3D = modelViewMatrix.transformVector(new Vector3D(xd,yd,zd)); vertices.push(tv.x, tv.y, tv.z); commands.push(1); modelViewMatrix.prependTranslation(xd,yd,zd); } private function push():void { stack.push(modelViewMatrix.clone()); } private function pop():void { modelViewMatrix = stack.pop(); } private function loadIdentity():void { modelViewMatrix = new Matrix3D(); } private function render(event:Event):void { projectionMatrix = perspective.toMatrix3D(); projectionMatrix.prependTranslation(0,0,300); //project points Utils3D.projectVectors(projectionMatrix, vertices, points, uvts); //connect the dots canvas.graphics.clear(); canvas.graphics.lineStyle(1,0xFF0000); canvas.graphics.drawPath(commands, points); } } }