In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Stage3D test05

「Stage3Dプログラミング」読みながらいじってみました。その5。
ワイヤーフレームの続き。

ワイヤフレームの作り方について、bkzenさんから以下の方法を教えていただきました。
ありがとうございました。
http://wonderfl.net/c/9rE2


あと、球の方がワイヤフレーム映えるかなと思って図形も変更。
重なる頂点とか気にしてないです。
Get Adobe Flash player
by sakef 04 Sep 2012
/**
 * Copyright sakef ( http://wonderfl.net/user/sakef )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/437c
 */

package {
    // AGALプログラム文字列をバイトコード仕様に変換する&射影変換計算に利用する
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;
    
    import flash.display.Sprite;
    import flash.display.Stage3D;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DTriangleFace;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
    import flash.system.System;
    
    [SWF(backgroundColor="#000000")]
    public class Main extends Sprite
    {    
        private const WIDTH:int = 465;
        private const HEIGHT:int = 465;
        private const W:int = 60;
        private const H:int = 70;
        private const RADIUS:int = 120;
        private const CAMERA_RADIUS:int=500;
        private const RADIAN:Number= Math.PI/180;
        private const VECTOR_ZERO:Vector3D = new Vector3D();
        private var stage3d:Stage3D;
        private var ctx:Context3D;
        private var indexBuffer:IndexBuffer3D;
        private var modelMatrix:Matrix3D;
        private var viewMatrix:Matrix3D;
        private var rotX:Number;
        private var rotCamera:Number;
        
        public function Main()
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.quality = StageQuality.HIGH;
            stage.frameRate = 60;
            System.pauseForGCIfCollectionImminent(1);
            
            stage3d = stage.stage3Ds[0];
            stage3d.addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
            stage3d.requestContext3D();
        }
        private function onContext3DCreate(e:Event):void 
        {
            ctx = Stage3D(e.target).context3D;
            ctx.configureBackBuffer(WIDTH, HEIGHT, 2, true);
            ctx.enableErrorChecking = true;
            ctx.setCulling(Context3DTriangleFace.BACK);
            
            // 座標計算
            var vertices:Vector.<Number> = new <Number>[];
            var indices:Vector.<uint> = new <uint>[];
            var numVert:int=0;
            var hh:Number=180/H, ww:Number = 360/W, hi:int=H-2;
            var theta0:Number, theta1:Number=90-hh;
            var rr:Number, ox:Number, oy:Number, oz:Number;
            for(var i:int=0; i<hi;i++)
            {
                theta0=0;
                theta1 -= hh;
                for(var j:int=0 ; j<W ; j++)
                {
                    setVertices(vertices,theta0,theta1,1,0,0,1);
                    setVertices(vertices,theta0+ww,theta1+hh,0,1,0,1);
                    setVertices(vertices,theta0,theta1+hh,0,0,1,1);
                    setVertices(vertices,theta0+ww,theta1,0,0,1,1);
                    numVert+=4;
                    theta0 += ww;
                    indices.push(numVert-4,numVert-3,numVert-2);
                    indices.push(numVert-3,numVert-4,numVert-1);
                }
            }
            
            var vb:VertexBuffer3D = ctx.createVertexBuffer(numVert, 7);
            vb.uploadFromVector(vertices, 0, numVert);
            ctx.setVertexBufferAt(0, vb, 0, Context3DVertexBufferFormat.FLOAT_3);
            ctx.setVertexBufferAt(1, vb, 3, Context3DVertexBufferFormat.FLOAT_4);
            indexBuffer = ctx.createIndexBuffer(indices.length);
            indexBuffer.uploadFromVector(indices, 0, indices.length);
            var program:Program3D = ctx.createProgram();
            var vertexPrg:String = "m44 vt0, va0, vc8\n" + "m44 vt1, vt0, vc4\n" + "m44 op,  vt1, vc0\n" + "mov v0,  va1";
            
            // 断片シェーダ
            // bkzenさんに教えていただきました。ありがとうございました。
            // 参考:http://wonderfl.net/c/9rE2
            //----------------------------------------------------------------
            var fragmentPrg:String =
                "add ft0.x, v0.x,     v0.y     \n" + 
                "add ft0.y, v0.y,     v0.z     \n" + 
                "add ft0.z, v0.z,     v0.x     \n" + 
                "add ft0.w, v0.w,     v0.x     \n" + 
                "sub ft0,   ft0,      fc1.xxxx \n" + 
                "slt ft0,   ft0,      fc1.yyyy \n" + 
                "mul ft0.x, ft0.x,    ft0.y    \n" + 
                "mul ft0.x, ft0.x,    ft0.z    \n" + 
                "sub ft0.x, fc1.x,    ft0.x    \n" + 
                "kil ft0.x \n" + 
                "mov oc, fc0";
            // 断片シェーダの一時定数に追加
            ctx.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([
                0, 1, 1, 1,       // ワイヤ―の色を作成
                1 - 0.02, 0, 0, 0 // fc1.x = 1 - line size
            ]));
            //----------------------------------------------------------------
            
            var assembler:AGALMiniAssembler = new AGALMiniAssembler();
            program.upload(
                assembler.assemble(Context3DProgramType.VERTEX, vertexPrg), 
                assembler.assemble(Context3DProgramType.FRAGMENT, fragmentPrg)
            );
            ctx.setProgram(program);
            
            // 射影変換用行列
            var perspectiveMatrix:PerspectiveMatrix3D = new PerspectiveMatrix3D;
            perspectiveMatrix.identity();
            perspectiveMatrix.perspectiveFieldOfViewLH( 35*RADIAN, WIDTH/HEIGHT, 10, 1000);  
            ctx.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, perspectiveMatrix,true);
            
            modelMatrix = new Matrix3D;
            viewMatrix = new Matrix3D;
            rotCamera = rotX = 0;
            
            addEventListener(Event.ENTER_FRAME, onFrame);
            stage.addEventListener(Event.RESIZE, onResize);
            onResize();
        }
        
        // 座標計算用
        private function setVertices(vertices:Vector.<Number>, theta0:Number, theta1:Number, r:int, g:int, b:int, a:int):void
        {
            var rr:Number = RADIUS * Math.cos(theta1*RADIAN);
            vertices.push(rr * Math.sin(theta0*RADIAN),RADIUS*Math.sin(theta1*RADIAN),rr*Math.cos(theta0*RADIAN),r,g,b,a);
        }
        
        private function onFrame(e:Event=null):void
        {
            // モデル
            rotX ++;
            modelMatrix.identity();
            modelMatrix.appendRotation(rotX,Vector3D.X_AXIS);
            ctx.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,8, modelMatrix,true);
            
            // ビュー
            rotCamera ++;
            viewMatrix.identity();
            viewMatrix.appendTranslation(CAMERA_RADIUS*Math.sin(rotCamera*RADIAN),0,-CAMERA_RADIUS*Math.cos(rotCamera*RADIAN));
            viewMatrix.pointAt(VECTOR_ZERO, Vector3D.Z_AXIS, Vector3D.Y_AXIS);
            viewMatrix.invert();
            ctx.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 4, viewMatrix, true);
            
            // 描画
            ctx.clear();
            ctx.drawTriangles(indexBuffer,0,-1);
            ctx.present();
        }
        
        private function onResize(e:Event=null):void
        {
            if(stage3d)
            {
                stage3d.x = (stage.stageWidth - WIDTH) / 2;
                stage3d.y = (stage.stageHeight - HEIGHT) / 2;
            }
        }
    }
}