// forked from zerogravity's forked from: PapervisionMini3D // forked from timknip's PapervisionMini3D package { import flash.display.StageAlign; import flash.display.StageQuality; import flash.display.StageScaleMode; import flash.display.Graphics; import flash.display.Sprite; import flash.display.TriangleCulling; import flash.events.Event; import flash.geom.Matrix3D; import flash.geom.Utils3D; import flash.text.TextField; import flash.text.TextFormat; import net.hires.debug.Stats; [SWF (width="640", height="480", backgroundColor="#000000", frameRate="60")] public class PapervisionMini3D extends Sprite { private var _container :Sprite; private var _info :TextField; private var _scene :SceneGraph3D; private var _camera :Camera3D; private var _cube :TriangleMesh3D; private var _stats :Stats; private var _modelingTransform :IRenderPipeProcessor; private var _viewingTransform :IRenderPipeProcessor; private var _renderSessionData :RenderSessionData; public function PapervisionMini3D() { super(); stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.quality = StageQuality.LOW; _container = new Sprite(); addChild(_container); _container.x = stage.stageWidth / 2; _container.y = stage.stageHeight / 2; _stats = new Stats(); addChild(_stats); _info = new TextField(); addChild(_info); _info.x = _info.y = 5; _info.width = 400; _info.height = 400; _info.multiline = true; _info.selectable = false; _info.defaultTextFormat = new TextFormat("Arial", 12, 0xff000); _info.text = ""; _modelingTransform = new ModelingTransform(); _viewingTransform = new ViewingTransform(); _renderSessionData = new RenderSessionData(); _scene = new SceneGraph3D(); _camera = new Camera3D(50, 1.333, 0.01, 500, "Camera01"); _camera.z = 30; _cube = buildCube(); _scene.addChild(_camera); _scene.addChild(_cube); stage.addEventListener(Event.RESIZE, onStageResize); addEventListener(Event.ENTER_FRAME, onRenderTick); } private function onRenderTick(e:Event=null):void { renderScene(); _cube.rotationY += (Math.PI/180)*.2; Utils3D.projectVectors(_cube.viewTransform, _cube.vertices, _cube.screenVertices, _cube.uvtData); _container.graphics.clear(); draw(_cube.screenVertices, _cube.indices, _cube.uvtData); } public function renderScene():void { _renderSessionData.sceneGraph = _scene; _renderSessionData.camera = _camera; _modelingTransform.process(_renderSessionData); _camera.update(); _renderSessionData.projection.rawData = _camera.worldTransform.rawData; _renderSessionData.projection.invert(); _renderSessionData.projection.append(_camera.projection); _viewingTransform.process(_renderSessionData); } private function draw(verts:Vector.<Number>, indices :Vector.<int>, uvt:Vector.<Number>):void { var g :Graphics = _container.graphics; g.lineStyle(0, 0xff0000); g.drawTriangles(verts, indices, uvt, TriangleCulling.NEGATIVE); g.endFill(); } protected function onStageResize(e:Event=null):void { _camera.aspect = stage.stageWidth / stage.stageHeight; _container.x = stage.stageWidth / 2; _container.y = stage.stageHeight / 2; _stats.x = stage.stageWidth - _stats.width - 10; _stats.y = 10; } private function buildCube(scale:Number=200):TriangleMesh3D { var mesh :TriangleMesh3D = new TriangleMesh3D("cube"); mesh.vertices.push(-1 * scale, -1 * scale, 1 * scale); mesh.vertices.push(1 * scale, -1 * scale, 1 * scale); mesh.vertices.push(1 * scale, 1 * scale, 1 * scale); mesh.vertices.push(-1 * scale, 1 * scale, 1 * scale); mesh.vertices.push(-1 * scale, 1 * scale, -1 * scale); mesh.vertices.push(-1 * scale, -1 * scale, -1 * scale); mesh.vertices.push(-1 * scale, -1 * scale, 1 * scale); mesh.vertices.push(-1 * scale, 1 * scale, 1 * scale); mesh.screenVertices.push(0,0, 0,0, 0,0, 0,0); mesh.screenVertices.push(0,0, 0,0, 0,0, 0,0); mesh.uvtData.push(0,0,0, 0,0,0, 0,0,0, 0,0,0); mesh.uvtData.push(0,0,0, 0,0,0, 0,0,0, 0,0,0); mesh.indices = new Vector.<int>(); mesh.indices.push(0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7); return mesh; } } } import flash.display.Sprite; import flash.events.Event; import flash.geom.Matrix3D; import flash.geom.Vector3D; internal class DisplayObjectContainer3D { public var name :String; public var children :Vector.<DisplayObjectContainer3D>; public var parent :DisplayObjectContainer3D; public function DisplayObjectContainer3D(name:String=null) { this.name = name; children = new Vector.<DisplayObjectContainer3D>(); } public function addChild(child:DisplayObjectContainer3D):DisplayObjectContainer3D { if(children.indexOf(child) == -1) { children.push(child); } return child; } public function removeChild(child:DisplayObjectContainer3D):DisplayObjectContainer3D { var idx :int = children.indexOf(child); if(idx >= 0) { child = children.splice(idx, 1)[0]; child.parent = null; return child; } return null; } } internal class DisplayObject3D extends DisplayObjectContainer3D { public var localTransform :Matrix3D; public var worldTransform :Matrix3D; public var viewTransform :Matrix3D; public var components :Vector.<Vector3D>; private var _orientation :Vector3D; private var _translation :Vector3D; private var _scale :Vector3D; public function DisplayObject3D(name:String=null) { super(name); localTransform = new Matrix3D(); worldTransform = new Matrix3D(); viewTransform = new Matrix3D(); _orientation = new Vector3D(); _translation = new Vector3D(); _scale = new Vector3D(1, 1, 1); components = new Vector.<Vector3D>(3, true); components[0] = _translation; components[1] = _orientation; components[2] = _scale; } public function set x(value:Number):void { _translation.x = value; } public function get x():Number { return _translation.x; } public function set y(value:Number):void { _translation.y = value; } public function get y():Number { return _translation.y; } public function set z(value:Number):void { _translation.z = value; } public function get z():Number { return _translation.z; } public function set rotationX(value:Number):void { _orientation.x = value; } public function get rotationX():Number { return _orientation.x; } public function set rotationY(value:Number):void { _orientation.y = value; } public function get rotationY():Number { return _orientation.y; } public function set rotationZ(value:Number):void { _orientation.z = value; } public function get rotationZ():Number { return _orientation.z; } public function updateTransform():void { localTransform.recompose(components); } } internal class Vertices3D extends DisplayObject3D { public var vertices :Vector.<Number>; public var viewVertices :Vector.<Number>; public var screenVertices :Vector.<Number>; public var uvtData :Vector.<Number>; public var indices :Vector.<int>; public function Vertices3D(name:String=null) { super(name); vertices = new Vector.<Number>(); viewVertices = new Vector.<Number>(); screenVertices = new Vector.<Number>(); uvtData = new Vector.<Number>(); } } internal class TriangleMesh3D extends Vertices3D { public function TriangleMesh3D(name:String=null) { super(name); } } internal class SceneGraph3D extends DisplayObject3D { } internal class Camera3D extends DisplayObject3D { public var projection :Matrix3D; private var _fov :Number; private var _aspect :Number; private var _near :Number; private var _far :Number; private var _dirty :Boolean; public function Camera3D(fov:Number=90, aspect:Number=1.333, near:Number=1, far:Number=10000, name:String=null) { super(name); this.fov = fov; this.aspect = aspect; this.near = near; this.far = far; update(); } public function set fov(value:Number):void { if(value != _fov) { _fov = value; _dirty = true; } } public function get fov():Number { return _fov; } public function set aspect(value:Number):void { if(_aspect != value) { _aspect = value; _dirty = true; } } public function get aspect():Number { return _aspect; } public function set near(value:Number):void { if(_near != value) { _near = value; _dirty = true; } } public function get near():Number { return _near; } public function set far(value:Number):void { if(_far != value) { _far = value; _dirty = true; } } public function get far():Number { return _far; } public function update():void { if(_dirty) { _dirty = false; projection = init(_fov, _aspect, _near, _far); } } private function init(fovy:Number=90, aspect:Number=1.333, near:Number=1, far:Number = 10000):Matrix3D { var fov2:Number = (fovy/2) * (Math.PI/180); var tan:Number = Math.tan(fov2); var f:Number = 1 / tan; var v:Vector.<Number> = new Vector.<Number>(16, true); v[0] = f / aspect; v[1] = v[2] = v[3] = v[4] = 0; v[5] = f; v[6] = v[7] = v[8] = v[9] = v[12] = v[13] = v[15] = 0; v[10] = (near+far) / (near-far); v[11] = (2*far*near) / (near-far); v[14] = -1; return new Matrix3D(v); } } internal class RenderSessionData { public var sceneGraph :DisplayObject3D; public var camera :Camera3D; public var projection :Matrix3D; public function RenderSessionData() { projection = new Matrix3D(); } } internal interface IRenderPipeProcessor { function process(renderSessionData:RenderSessionData):void; } internal class ModelingTransform implements IRenderPipeProcessor { public function ModelingTransform() {} public function process(renderSessionData:RenderSessionData):void { transform(renderSessionData.sceneGraph); } private function transform(object:DisplayObject3D):void { for each(var child:DisplayObject3D in object.children) { child.updateTransform(); child.worldTransform.rawData = object.worldTransform.rawData; child.worldTransform.append(child.localTransform); transform(child); } } } internal class ViewingTransform implements IRenderPipeProcessor { public function ViewingTransform() {} public function process(renderSessionData:RenderSessionData):void { transform(renderSessionData.sceneGraph, renderSessionData.projection); } private function transform(object:DisplayObject3D, projection:Matrix3D):void { for each(var child:DisplayObject3D in object.children) { child.viewTransform.rawData = child.worldTransform.rawData; child.viewTransform.append(projection); transform(child, projection); } } } forked from: forked from: PapervisionMini3D