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

Joint Controler(描画test)

3Dオブジェクトの位置移動と回転を制御できるコントローラー描画テスト
リングパーツが長すぎて描画に破綻をきたすためalphaで誤魔化してます。
Get Adobe Flash player
by Kay 09 Feb 2011
/**
 * Copyright Kay ( http://wonderfl.net/user/Kay )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3OE2
 */

// 3Dオブジェクトの位置移動と回転を制御できるコントローラー描画テスト
// リングパーツが長すぎて描画に破綻をきたすためalphaで誤魔化してます。

package {
    
    import flash.display.*;
    import flash.geom.*;
    import flash.events.*;
    
    [SWF(width=465,height=465,frameRate=30, backgroundColor=0x666666)]
    public class Main extends Sprite {
        
        private const SW:Number = stage.stageWidth;
        private const SH:Number = stage.stageHeight;
        public var proj:PerspectiveProjection = new PerspectiveProjection();
        
        public function Main():void {
            var container:Sprite = new Sprite();
            addChild(container);
            container.x=SW/2;
            container.y=SH/2;

            var numJoint:uint=3;
            var dist:Number=150;
            var shift:Number = dist*(numJoint-1)/2;
            for (var v:int = 0; v < numJoint; v++) {
                var nY:Number=dist*v-shift;
                for (var h:int = 0; h < numJoint; h++) {
                    var nX:Number=dist*h-shift;
                    var jointControler:JointControler = new JointControler();
                    container.addChild(jointControler);
                    jointControler.mtx.prepend(proj.toMatrix3D());
                    jointControler.mtx.prependTranslation(nX, nY, proj.focalLength);
                    jointControler.xRender();
                    jointControler.addEventListener(Event.ENTER_FRAME, xRotate);
                }
            }
        }
        public function xRotate(e:Event):void {
            // Box空間ではなくBox座標を回転させる
            e.target.rMtx.appendRotation(2,Vector3D.X_AXIS);
            e.target.rMtx.appendRotation(3,Vector3D.Y_AXIS);
            e.target.rMtx.appendRotation(4,Vector3D.Z_AXIS);
            e.target.xRender();
        }
    }
}

import flash.display.*;
import flash.geom.*;
import flash.events.*;

class JointControler extends Sprite {
    private var vertices3D:Vector.<Number> = new Vector.<Number>();
    private var vertices2D:Vector.<Number> = new Vector.<Number>();
    private var vertices3Db:Vector.<Number> = new Vector.<Number>();
    private var indices:Vector.<int> = new Vector.<int>();
    private var uvt:Vector.<Number> = new Vector.<Number>();
    private var tempVerts:Vector.<Number>;
    private var staticVerts:Vector.<Number>;
    public var mtx:Matrix3D = new Matrix3D();
    public var rMtx:Matrix3D = new Matrix3D();
    private var ringParts:Array;

    public function JointControler(radius:Number=50, innerRadius:Number=30, ballRadius:Number=25):void {
        // curveToで描くための座標群を取得
        var arcPoints:Array = new Array();
        var arcInfo:Object      = getArcValues(radius, Math.PI*2);
        var innerArcInfo:Object = getArcValues(innerRadius, Math.PI*2);
        var ballPoints:Array = new Array();
        var ballArcInfo:Object  = getArcValues(ballRadius, Math.PI*2);
            
        for (var i:int = 0; i <= arcInfo.divideNum; i++) {
            // Outer Control Point
            arcPoints.push(new Point(arcInfo.distance*Math.cos(arcInfo.dividedRadian*(i-0.5)),
                                     arcInfo.distance*Math.sin(arcInfo.dividedRadian*(i-0.5))));
            // Outer Anchor Point
            arcPoints.push(new Point(radius*Math.cos(arcInfo.dividedRadian*i),
                                     radius*Math.sin(arcInfo.dividedRadian*i)));
            // Inner Control Point
            arcPoints.push(new Point(innerArcInfo.distance*Math.cos(innerArcInfo.dividedRadian*(i-0.5)),
                                     innerArcInfo.distance*Math.sin(innerArcInfo.dividedRadian*(i-0.5))));
            // Inner Anchor Point
            arcPoints.push(new Point(innerRadius*Math.cos(innerArcInfo.dividedRadian*i),
                                     innerRadius*Math.sin(innerArcInfo.dividedRadian*i)));
            // Ball Control Point
            ballPoints.push(new Point(ballArcInfo.distance*Math.cos(ballArcInfo.dividedRadian*(i-0.5)),
                                      ballArcInfo.distance*Math.sin(ballArcInfo.dividedRadian*(i-0.5))));
            // Ball Anchor Point 
            ballPoints.push(new Point(ballRadius*Math.cos(ballArcInfo.dividedRadian*i),
                                      ballRadius*Math.sin(ballArcInfo.dividedRadian*i)));
        }
        var numPoint:int = arcPoints.length; // 36(=8*2(outer&inner)*2(anchor&control))
        // Z回転軸(Ballにも利用)
        for (i = 0; i < numPoint; i++) {
            vertices3D.push(arcPoints[i].x,arcPoints[i].y,0);
        }
        // Y回転軸
        for (i = 0; i < numPoint; i++) {
            vertices3D.push(arcPoints[i].x,0,arcPoints[i].y);
        }
        // X回転軸
        for (i = 0; i < numPoint; i++) {
            vertices3D.push(0,arcPoints[i].x,arcPoints[i].y);
        }
        // 移動用ボール
        numPoint = ballPoints.length;
        for (i = 0; i < numPoint; i++) {
            vertices3Db.push(ballPoints[i].x,ballPoints[i].y,0);
        }
    }

    public function xRender():void {
        // 回転させた座標に透視投影を反映してた後に2D化する
        tempVerts = new Vector.<Number>();
        rMtx.transformVectors(vertices3D, tempVerts);
        Utils3D.projectVectors(mtx,tempVerts,vertices2D,uvt);
        
        // ボール用は回転させずに透視投影のみ反映する
        staticVerts = new Vector.<Number>();
        Utils3D.projectVectors(mtx,vertices3Db,staticVerts,uvt);
            
        // 初期化
        while (numChildren > 0) removeChildAt(0);
        ringParts = new Array();
           
        drawRing(0x33ffff,0);    // Z軸
        drawRing(0xffff33,1);    // Y軸
        drawRing(0xff33ff,2);    // X軸
        drawBall(0xff0000);    // 移動用ボール
            
        // ソートして配置
        ringParts.sortOn("nZ", Array.NUMERIC);
        for (var i:int = 0; i <13; i++) {
            addChild(ringParts[i]);
        }
    }
    // 中心に球もどきを配置
    private function drawBall(color:int):void {
        var ball:QuarterRing = new QuarterRing();
        ball.graphics.beginFill(color);
        ball.graphics.moveTo(staticVerts[2],staticVerts[3]);
        for (var i:int = 0; i < 9; i++) {
            ball.graphics.curveTo(staticVerts[(i*4)+0],staticVerts[(i*4)+1],staticVerts[(i*4)+2],staticVerts[(i*4)+3]);
        }
        ball.graphics.endFill();
        ball.nZ = 0;
        ball.alpha = 0.75;
        ringParts.push(ball);
    }
        
    // 4枚のパーツに分けて描画する
    private function drawRing(color:int, num:int):void {
        for (var i:int = 0; i < 4; i++) {
            var ringPart:QuarterRing = new QuarterRing();
            drawRingPart(ringPart,color,num*72,i*2+1);
            ringPart.nZ = tempVerts[num*108+27*i+17];    // 17,26
            ringParts.push(ringPart);
        }
    }
    public function drawRingPart(obj:Object,color:int,num:int,offset:int):void {
        obj.graphics.lineStyle(0,0x666666);
        obj.graphics.beginFill(color);
        // Outer
        obj.graphics.moveTo(vertices2D[(offset-1)*8+num+2],vertices2D[(offset-1)*8+num+3]);
        for (var i:int = offset; i <= offset+1; i++) {
            var base:int = i*8;
            obj.graphics.curveTo(vertices2D[i*8+num+0],vertices2D[i*8+num+1],vertices2D[i*8+num+2],vertices2D[i*8+num+3]);
        }
        // Inner(逆から)
        obj.graphics.lineTo(vertices2D[(offset+1)*8+num+6],vertices2D[(offset+1)*8+num+7]);
        for (i = offset+1; i >= offset; i--) {
            obj.graphics.curveTo(vertices2D[i*8+num+4],vertices2D[i*8+num+5],vertices2D[i*8+num-2],vertices2D[i*8+num-1]);
        }
        obj.graphics.lineTo(vertices2D[(offset-1)*8+num+2],vertices2D[(offset-1)*8+num+3]);
        obj.graphics.endFill();
    }
        
    //----------------------------------------------------------------------
    // 以下LineClassより
    
    /*
     * 円弧を描くのに必要な材料をオブジェクトとして返す
     * @return divideNum: 分割数
     * @return dividedRadian: 分割された角度
     * @return distance: 中心点からコントロールポイントまでの距離
     */
     public static function getArcValues(nRadius:Number, nRadian:Number):Object {
        // 分割数を得る(45°未満:1)
        var divideNum:int = 1;
        while (Math.abs(nRadian)/divideNum > Math.PI/4) divideNum++;
        // 分割された角度
        var dividedRadian:Number = nRadian/divideNum;
        // コントロールポイントまでの距離を得る
        var distance:Number = getControlRadius(nRadius,Math.abs(dividedRadian));
        return {divideNum:divideNum, dividedRadian:dividedRadian, distance:distance};
    }
        
    // 角度からコントロールポイントの半径を取得
    public static function getControlRadius(nRadius:Number, nRadian:Number):Number {
        var rHalf:Number = nRadian/2;
        var nHeight:Number = nRadius * Math.atan(rHalf);
        var radius:Number = Math.sqrt(Math.pow(nHeight,2)+Math.pow(nRadius,2));
        return radius;
    }

    // 数値を+-limitの範囲に収束
    public function getRangeValue(num:Number, limit:Number):Number {
        while(num >  limit) num -= limit*2;
        while(num < -limit) num += limit*2;
        return num;
    }
        
    // angleをradianに変換
    private function angle2radian(angle:Number=0):Number {
        var radian:Number= angle * (Math.PI / 180);
        return radian;
    }
}
/*
 * ソート情報(nZ)記録用
 */
class QuarterRing extends Shape {
    public var nZ:Number;
    public function QuaterRing():void {
    }
}