molehill用

by zahir
stage3dとカメラの実験。
まだwonderflだと動かないですね。
♥0 | Line 127 | Modified 2011-08-14 23:54:49 | MIT License
play

ActionScript3 source code

/**
 * Copyright zahir ( http://wonderfl.net/user/zahir )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/xrbr
 */

package
{
    import com.adobe.utils.AGALMiniAssembler;
    
    import flash.display.Sprite;
    import flash.display.Stage3D;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DRenderMode;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.geom.Matrix3D;
    import flash.geom.PerspectiveProjection;
    import flash.geom.Rectangle;
    import flash.geom.Vector3D;
    
    [SWF(width="640", height="480", frameRate="60")]
    
    public class molehillTest2 extends Sprite
    {
        private var world:Stage3D;
        private var context:Context3D;
        private var program:Program3D;
        private var indexBuffer:IndexBuffer3D;
        private var vertexBuffer:VertexBuffer3D;
        
        private var rot:Number = 0;
        private var mtx:Matrix3D;
        private var m_identity:Vector.<Number>;
        
        private const Z_Axis:Vector3D = Vector3D.Z_AXIS;
        private var cam:Camera3D;
        
        public function molehillTest2()
        {
            // init stage3D
            world = stage.stage3Ds[0];
            world.addEventListener( Event.CONTEXT3D_CREATE, onCreateStage3D );
            world.requestContext3D( Context3DRenderMode.AUTO );
        }
        
        private function onCreateStage3D( e:Event ):void
        {
            trace("create");
            world.removeEventListener( Event.CONTEXT3D_CREATE, onCreateStage3D );
            
            // set Context3D
            context = world.context3D;
            if(context == null ) return;
            context.configureBackBuffer( stage.stageWidth, stage.stageHeight, 8 );
            
            // create vertices
            vertexBuffer = context.createVertexBuffer( 3, 6 );
            vertexBuffer.uploadFromVector( new <Number>[
                0, 1, 0,    1, 0, 0,
                -1, -1, 0,    0, 1, 0,
                1, -1, 0,    0, 0, 1
            ], 0, 3 );
            
            // create indices
            indexBuffer = context.createIndexBuffer( 3 );
            indexBuffer.uploadFromVector( new <uint>[0, 1, 2], 0, 3 );
            
            // create program & shader's
            var vertexShader:AGALMiniAssembler = new AGALMiniAssembler();
            vertexShader.assemble( Context3DProgramType.VERTEX, 
                "m44 op va0, vc0 \n" +
                "mov v0, va1"
            );
            
            var fragmentShader:AGALMiniAssembler = new AGALMiniAssembler();
            fragmentShader.assemble( Context3DProgramType.FRAGMENT,
                "mov oc, v0"
            );
            
            program = context.createProgram();
            program.upload( vertexShader.agalcode, fragmentShader.agalcode );
            context.setProgram( program );
            
            // create Matrix3D
            mtx = new Matrix3D();
            m_identity = mtx.rawData;
            
            cam = new Camera3D(45,4/3,0.1,1000);
            
            cam.x = 2;
            cam.y = -1;
            cam.z = -10;
            
            cam.lookAt = new Vector3D();
            rot = 0;
            
            addEventListener( Event.ENTER_FRAME, onEnter );
        }
        private var proj:PerspectiveProjection = new PerspectiveProjection();
        private function onEnter( e:Event ):void
        {
            
            mtx.rawData = m_identity;
            //mtx.appendRotation( rot, Z_Axis );
            mtx.appendTranslation(0,0, -10);
            
            cam.x = Math.sin( 0.01745 * rot ) * 5;
            
            var m:Matrix3D = cam.getViewMatrix();
            m.invert();
            mtx.append( m );
            mtx.append( cam.getProjectionMatrix() );
            
            
            context.setProgramConstantsFromMatrix( Context3DProgramType.VERTEX, 0, mtx, true);
            context.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
            context.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
            
            context.clear( 0, 0, 0, 1 );
            context.drawTriangles( indexBuffer, 0, 1 );
            context.present();
            
            rot++;
        }
    }
}
import flash.geom.Matrix3D;
import flash.geom.Vector3D;

class Camera3D
{
    //*
    private var _fov:Number;
    private var _near:Number;
    private var _far:Number;
    private var _aspectRatio:Number;
    private var _lookAt:Vector3D;
    private var _up:Vector3D;
    private var _pos:Vector3D;
    protected var dir:Vector3D;
    
    protected var view:Vector.<Number>;
    protected var proj:Vector.<Number>;
    
    protected var calculated:Boolean = false;
    
    public function Camera3D( fov:Number = 45, aspectRatio:Number = 1.3333, near:Number = 0.1, far:Number = 100)
    {
        this.fov = fov;
        this.aspectRatio = aspectRatio;
        this.near = near;
        this.far = far;
        
        up = new Vector3D(0,1,0);
        _pos = new Vector3D();
        dir = new Vector3D();
        lookAt = new Vector3D();
        
        view = new Vector.<Number>(16, false);
        proj = new Vector.<Number>(16, false);
        
        calc();
    }
    
    public function getProjectionMatrix():Matrix3D
    {
        if( calculated == false ) calc();
        return new Matrix3D( proj );
    }
    
    public function getViewMatrix():Matrix3D
    {
        if( calculated == false ) calc();
        return new Matrix3D( view );
    }
    
    public function projectionRawData():Vector.<Number>
    {
        if( calculated == false ) calc();
        return proj.slice();
    }

    public function viewRawData():Vector.<Number>
    {
        if( calculated == false ) calc();
        return view.slice();
    }
    
    protected function calc():void
    {
        calcView();
        calcProj();
        calculated = true;
    }
    
    protected function calcView():void
    {
        var Z:Vector3D = direction;
        var X:Vector3D = up.crossProduct( Z );
        var Y:Vector3D = Z.crossProduct( X );
        var v:Vector.<Number> = view;
        v[3] = v[7] = v[11] = 0;
        v[0] = X.x; v[1] = Y.x; v[2] = Z.x;
        v[4] = X.y; v[5] = Y.y; v[6] = Z.y;
        v[8] = X.z; v[9] = Y.z; v[10] = Z.z;
        v[12] = position.dotProduct( X ) * -1;
        v[13] = position.dotProduct( Y ) * -1;
        v[14] = position.dotProduct( Z ) * -1;
        v[15] = 1;
    }
    protected function calcProj():void
    {
        var ymax:Number = near * Math.tan( fov * Math.PI / 360 );
        var xmax:Number = ymax * aspectRatio;
        var left:Number = -xmax;
        var right:Number = xmax;
        var top:Number = ymax;
        var bottom:Number = -ymax;
        var t1:Number = 2 * near;
        var t2:Number = right - left;
        var t3:Number = top - bottom;
        var t4:Number = far - near;
        var v:Vector.<Number> = proj;
        v[0] = t1 / t2;
        v[1] = v[2] = v[3] = v[4] = v[6] = v[7] = v[12] = v[13] = v[15] = 0;
        v[5] = t1 / t3;
        v[8] = (right + left) / t2;
        v[9] = (top + bottom) / t3;
        v[10] = (-far - near) / t4;
        v[11] = -1.0;
        v[14] = (-t1 * far) / t4;
    }
    
    public function get direction():Vector3D
    {
        if( calculated == true ) return dir;
        dir.x = lookAt.x - _pos.x;
        dir.y = lookAt.y - _pos.y;
        dir.z = lookAt.z - _pos.z;
        dir.normalize();
        return dir;
    }
    
    public function get x():Number
    {
        return -_pos.x;
    }
    public function set x( value:Number ):void
    {
        _pos.x = -value;
        calculated = false;
    }
    
    public function get y():Number
    {
        return -_pos.y;
    }
    public function set y( value:Number ):void
    {
        _pos.y = -value;
        calculated = false;
    }
    
    public function get z():Number
    {
        return _pos.z;
    }
    public function set z( value:Number ):void
    {
        _pos.z = value;
        calculated = false;
    }
    
    public function get position():Vector3D
    {
        return _pos;
    }

    public function set position(value:Vector3D):void
    {
        x = value.x;
        y = value.y;
        z = value.z;
        calculated = false;
    }

    public function get up():Vector3D
    {
        return _up;
    }

    public function set up(value:Vector3D):void
    {
        _up = value;
        calculated = false;
    }

    public function get lookAt():Vector3D
    {
        return _lookAt;
    }
    
    public function set lookAt(value:Vector3D):void
    {
        _lookAt = value;
        calculated = false;
    }
    
    public function get fov():Number
    {
        return _fov;
    }
    public function set fov(value:Number):void
    {
        value = value < 1 ? 1 : value >= 180 ? 179 : value;
        _fov = value;
        calculated = false;
    }
    
    /*
    public function get zoom():Number
    {
        return 1 / Math.tan( fov / 2 );
    }
    public function set zoom( value:Number ):void
    {
        fov = 2 * Math.atan( 1 / value );
        calculated = false;
    }
    */
    
    public function get near():Number
    {
        return _near;
    }
    public function set near(value:Number):void
    {
        _near = value;
        calculated = false;
    }

    public function get far():Number
    {
        return _far;
    }
    public function set far(value:Number):void
    {
        _far = value;
        calculated = false;
    }

    public function get aspectRatio():Number
    {
        return _aspectRatio;
    }
    public function set aspectRatio(value:Number):void
    {
        _aspectRatio = value;
        calculated = false;
    }//*/
}