forked from: QbicQube

by ohisama forked from QbicQube (diff: 185)
QbicQube

Papervision3Dのお勉強のためにつくった。
当初、オイラー角(rotationXとか)だけでやるつもりだったけど、
見事にジンバルロックでどうにもならなくなった。
いろいろやったけど、コードがどんどん汚くなって、
Papervision3Dの勉強にもなっていないことに気がついて、
一念発起でクオータニオンを使ってみた。

とりあえずできた。
いやークオータニオンってほんっとに素晴らしいですね!

Papervision3Dのプロパティが行き当たりばったりで作られている感が見えてきた。
まあ、それを差し引いてもすごいけどね。

あと、なんかクオータニオンまわりの実装をしたら重くなった。
なんだろう。Tweenerとの組み合わせ方がへたっぴなのかな。

もうちょっと勉強する必要がありそう。

参考
http://blog.r3c7.net/?p=152
http://yamasv.blog92.fc2.com/blog-entry-139.html
♥0 | Line 431 | Modified 2013-02-07 15:02:08 | MIT License
play

ActionScript3 source code

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

// forked from umhr's QbicQube
/*
QbicQube

Papervision3Dのお勉強のためにつくった。
当初、オイラー角(rotationXとか)だけでやるつもりだったけど、
見事にジンバルロックでどうにもならなくなった。
いろいろやったけど、コードがどんどん汚くなって、
Papervision3Dの勉強にもなっていないことに気がついて、
一念発起でクオータニオンを使ってみた。

とりあえずできた。
いやークオータニオンってほんっとに素晴らしいですね!

Papervision3Dのプロパティが行き当たりばったりで作られている感が見えてきた。
まあ、それを差し引いてもすごいけどね。

あと、なんかクオータニオンまわりの実装をしたら重くなった。
なんだろう。Tweenerとの組み合わせ方がへたっぴなのかな。

もうちょっと勉強する必要がありそう。

参考
http://blog.r3c7.net/?p=152
http://yamasv.blog92.fc2.com/blog-entry-139.html
*/
package 
{
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.events.*
    import org.papervision3d.objects.primitives.Cube;
    import org.papervision3d.view.*;
    import org.papervision3d.materials.*;
    import org.papervision3d.materials.utils.MaterialsList;
    import org.papervision3d.lights.PointLight3D;
    import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.core.math.Quaternion;
    import org.papervision3d.core.math.Matrix3D;
    import caurina.transitions.Tweener;
    import flash.display.SimpleButton;
    public class Quater extends BasicView 
    {
        private var cube : Cube;
        private var stageWidth : int = stage.stageWidth;
        private var stageHeight : int = stage.stageHeight;
        private var light : PointLight3D = new PointLight3D();
        private var cubes_array : Array = new Array();
        private var anchors_array : Array = new Array();
        private var cubePoz : Array = 
        [
            { x: -1, y: -1, z: -1 }, { x:0, y: -1, z: -1 }, { x:1, y: -1, z: -1 },
            { x: -1, y: 0, z: -1 }, { x:0, y: 0, z: -1 }, { x:1, y: 0, z: -1 },
            { x: -1, y:1, z: -1 }, { x:0, y:1, z: -1 }, { x:1, y:1, z: -1 },
            { x: -1, y: -1, z: 0 }, { x:0, y: -1, z: 0 }, { x:1, y: -1, z: 0 },
            { x: -1, y: 0, z: 0 }, { x:0, y: 0, z: 0 }, { x:1, y: 0, z: 0 },
            { x: -1, y:1, z: 0 }, { x:0, y:1, z: 0 }, { x:1, y:1, z: 0 },
            { x: -1, y: -1, z: 1 }, { x:0, y: -1, z: 1 }, { x:1, y: -1, z: 1 },
            { x: -1, y: 0, z: 1 }, { x:0, y: 0, z: 1 }, { x:1, y: 0, z: 1 },
            { x: -1, y:1, z: 1 }, { x:0, y:1, z: 1 }, { x:1, y:1, z: 1 }
        ];
        private var do3d : DisplayObject3D = new DisplayObject3D();
        private var myCubicData : CubicData = new CubicData();
        private var shield : Sprite = Create.newSprite(null, null, [["beginFill", [0x000000, 0]], ["drawRect", [0, 0, stageWidth, stageHeight]]]);
        public function Quater()
        {
            super(0, 0, true);
            var colors_array : Array = [0x00d3ff, 0xff003e, 0x9dff00, 0xff9300, 0x0400ff, 0xe200ff];
            var ml : MaterialsList = new MaterialsList( 
            {
                front : new FlatShadeMaterial(light, colors_array[0], 0x333333),
                back : new FlatShadeMaterial(light, colors_array[1], 0x333333),
                right : new FlatShadeMaterial(light, colors_array[2], 0x333333),
                left : new FlatShadeMaterial(light, colors_array[3], 0x333333),
                top : new FlatShadeMaterial(light, colors_array[4], 0x333333),
                bottom : new FlatShadeMaterial(light, colors_array[5], 0x333333)
                } )
            var cubicPoz_array : Array = new Array();
            for (var i : int = 0; i < cubePoz.length; i++) 
            {
                var _cube : Cube;
                if (i < 30) 
                {
                    _cube = new Cube(ml, 200, 200, 200, 4, 4, 4);
                }
                else 
                {
                }
                _cube.x = cubePoz[i].x * 210;
                _cube.y = cubePoz[i].y * 210;
                _cube.z = cubePoz[i].z * 210;
                var _anchor : DisplayObject3D = new DisplayObject3D();
                cubes_array[i] = _cube;
                _anchor.addChild(_cube);
                anchors_array[i] = _anchor;
                do3d.addChild(_anchor);
            }
            do3d.localRotationX = 45;
            do3d.localRotationY = 45;
            scene.addChild(do3d);
            startRendering();
            var btnName_array : Array = ["0_0", "0_1", "1_0", "1_1", "2_0", "2_1", "3_0", "3_1", "4_0", "4_1", "5_0", "5_1", "6_0", "6_1", "7_0", "7_1", "8_0", "8_1"];
            var btnXYWH : Array = 
            [
            [380, 50, 40, 40], [145, 415, 40, 40], [330, 30, 40, 40], [95, 395, 40, 40], [280, 10, 40, 40], [45, 375, 40, 40],
            [410, 270, 40, 40], [15, 270, 40, 40], [415, 220, 40, 40], [10, 220, 40, 40], [420, 170, 40, 40], [5, 170, 40, 40],
            [280, 415, 40, 40], [45, 50, 40, 40], [330, 395, 40, 40], [95, 30, 40, 40], [380, 375, 40, 40], [145, 10, 40, 40]];
            for (i = 0; i < btnName_array.length; i++) 
            {
                var _btn : SimpleButton = Create.newSimpleButton(btnXYWH[i]);
                _btn.name = btnName_array[i];
                _btn.addEventListener(MouseEvent.CLICK, CLICK);
                addChild(_btn);
            }
            var auto_btn : SimpleButton = Create.newSimpleButton([0,0,45,22,"shuffle"]);
            auto_btn.addEventListener(MouseEvent.CLICK, autoCLICK);
            addChild(auto_btn);
            function autoCLICK(e : MouseEvent = null) : void 
            {
                Tweener.addCaller(auto_btn, { onUpdate:fnAuto, time:5, count:10 , transition : "linear"} );
                function fnAuto() : void 
                {
                    CLICK(null, btnName_array[Math.floor(Math.random()*btnName_array.length)]);
                }
            }
            addChild(shield);
            shield.visible = false;
            function CLICK(e : MouseEvent = null , auto : String = null):void 
            {
                if (shield.visible) 
                {
                    return;
                }
                shield.visible = true;
                var _ar : Array;
                var step : int;
                if (auto) 
                {
                    _ar = auto.split("_");
                    step = 1;
                }
                else
                {
                    _ar = e.currentTarget.name.split("_");
                    step = 10;
                }
                _ar = [int(_ar[0]), int(_ar[1])];
                var move_array : Array = myCubicData.moveRotation(_ar);
                var count_array : Array = new Array();
                var ai_array : Array = new Array();
                for (var i : int = 0; i < move_array.length; i++) 
                {
                    ai_array[i] = move_array[i];
                    var pos1 : Quaternion = Quaternion.createFromMatrix(anchors_array[ai_array[i]].transform);
                    var pos2 : Quaternion;
                    if (_ar[0] < 3) 
                    {
                        pos2 = Quaternion.createFromEuler(0, -90+180*_ar[1], 0, true);
                    }
                    else if (_ar[0] <6) 
                    {
                        pos2 = Quaternion.createFromEuler(-90+180*_ar[1], 0, 0, true);
                    }
                    else if (_ar[0] <9) 
                    {
                        pos2 = Quaternion.createFromEuler(0, 0, -90+180*_ar[1], true);
                    }
                    pos2.mult(pos1);
                    count_array[i] = 0;
                    Tweener.addCaller(do3d, { onUpdate:update, time:step/20, count:step ,onUpdateParams:[i,pos1,pos2], transition : "linear"} );
                    function update(n : int, p1 : *, p2 : *) : void 
                    {
                        count_array[n] ++;
                        if (count_array[n] > step) {return };
                        var gpos : Quaternion = Quaternion.slerp( p1, p2, count_array[n]/step );
                        anchors_array[ai_array[n]].copyTransform(Matrix3D.quaternion2matrix(gpos.x, gpos.y, gpos.z, gpos.w));
                        if (count_array[n] == step && n==8) {shield.visible = false };
                    }
                }
            }
        }
        override protected function onRenderTick(event:Event = null):void 
        {
            var mouseX : Number = Math.min(Math.max(stage.mouseX, 0), stageWidth) - stageWidth / 2;
            var mouseY : Number = Math.min(Math.max(stage.mouseY, 0), stageHeight) - stageHeight / 2;
            light.x = mouseX;
            light.y = -mouseY;
            super.onRenderTick(event);
        }
    }
}
class CubicData 
{
    public var poz : Array = [];
    public function CubicData() 
    {
        for (var i : int = 0; i < 27; i++) 
        {
            poz[i] = i;
        }
    }
    public function moveRotation(_ar:Array):Array
    {
        var n : int = _ar[0];
        var r : int = _ar[1];
        var _temp : Array = poz.concat();
        var _result : Array = [];
        if (n < 3) 
        {
            if (r == 0)
            {
                _temp[0+n*9] = poz[2+n*9];
                _temp[1+n*9] = poz[5+n*9];
                _temp[2+n*9] = poz[8+n*9];
                _temp[3+n*9] = poz[1+n*9];
                _temp[4+n*9] = poz[4+n*9];
                _temp[5+n*9] = poz[7+n*9];
                _temp[6+n*9] = poz[0+n*9];
                _temp[7+n*9] = poz[3+n*9];
                _temp[8+n*9] = poz[6+n*9];
            }
            else 
            {
                _temp[0+n*9] = poz[6+n*9];
                _temp[1+n*9] = poz[3+n*9];
                _temp[2+n*9] = poz[0+n*9];
                _temp[3+n*9] = poz[7+n*9];
                _temp[4+n*9] = poz[4+n*9];
                _temp[5+n*9] = poz[1+n*9];
                _temp[6+n*9] = poz[8+n*9];
                _temp[7+n*9] = poz[5+n*9];
                _temp[8+n*9] = poz[2+n*9];
            }
            _result = [_temp[0+n*9], _temp[1+n*9], _temp[2+n*9], _temp[3+n*9], _temp[4+n*9], _temp[5+n*9], _temp[6+n*9], _temp[7+n*9], _temp[8+n*9]];
        }
        else if (n < 6) 
        {
            n -= 3;
            if(r==0)
            {
                _temp[0+n*3] = poz[18+n*3];
                _temp[1+n*3] = poz[9+n*3];
                _temp[2+n*3] = poz[0+n*3];
                _temp[9+n*3] = poz[19+n*3];
                _temp[10+n*3] = poz[10+n*3];
                _temp[11+n*3] = poz[1+n*3];
                _temp[18+n*3] = poz[20+n*3];
                _temp[19+n*3] = poz[11+n*3];
                _temp[20+n*3] = poz[2+n*3];
            }
            else 
            {
                _temp[0+n*3] = poz[2+n*3];
                _temp[1+n*3] = poz[11+n*3];
                _temp[2+n*3] = poz[20+n*3];
                _temp[9+n*3] = poz[1+n*3];
                _temp[10+n*3] = poz[10+n*3];
                _temp[11+n*3] = poz[19+n*3];
                _temp[18+n*3] = poz[0+n*3];
                _temp[19+n*3] = poz[9+n*3];
                _temp[20+n*3] = poz[18+n*3];
            }
            _result = [_temp[0+n*3], _temp[1+n*3], _temp[2+n*3], _temp[9+n*3], _temp[10+n*3], _temp[11+n*3], _temp[18+n*3], _temp[19+n*3], _temp[20+n*3]];
        }
        else
        {
            n -= 6;
            if (r == 0)
            {
                _temp[0+n] = poz[6+n];
                _temp[3+n] = poz[15+n];
                _temp[6+n] = poz[24+n];
                _temp[9+n] = poz[3+n];
                _temp[12+n] = poz[12+n];
                _temp[15+n] = poz[21+n];
                _temp[18+n] = poz[0+n];
                _temp[21+n] = poz[9+n];
                _temp[24+n] = poz[18+n];
            }
            else 
            {
                _temp[0+n] = poz[18+n];
                _temp[3+n] = poz[9+n];
                _temp[6+n] = poz[0+n];
                _temp[9+n] = poz[21+n];
                _temp[12+n] = poz[12+n];
                _temp[15+n] = poz[3+n];
                _temp[18+n] = poz[24+n];
                _temp[21+n] = poz[15+n];
                _temp[24+n] = poz[6+n];
            }
            _result = [_temp[0+n], _temp[3+n], _temp[6+n], _temp[9+n], _temp[12+n], _temp[15+n], _temp[18+n], _temp[21+n], _temp[24+n]];
        }
        poz = _temp.concat();
        return _result;
    }
}
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.SimpleButton;
class Create
{
    public static var defaultTextFormat : TextFormat = new TextFormat();
    public static function newSimpleButton(x_y_w_h_txt : Array = null, property : Array = null, graphics : Array = null) : SimpleButton
    {
        var upState : Sprite = newSprite([x_y_w_h_txt[0], x_y_w_h_txt[1]], null, [["beginFill", [0xCCCCCC,1]], ["drawRoundRect", [0, 0, x_y_w_h_txt[2], x_y_w_h_txt[3], 8]]]);
        upState.addChild(newShape([2, 2], null,[["beginFill", [0xE5E5E5, 1]], ["drawRoundRect", [0, 0, x_y_w_h_txt[2] - 4, x_y_w_h_txt[3] - 4, 6]]]))
        var overState : Sprite = newSprite([x_y_w_h_txt[0],x_y_w_h_txt[1]],null,[["beginFill",[0xBBBBBB,1]],["drawRoundRect",[0,0,x_y_w_h_txt[2],x_y_w_h_txt[3],8]]]);
        overState.addChild(newShape([2,2],null,[["beginFill",[0xEEEEEE,1]],["drawRoundRect",[0,0,x_y_w_h_txt[2]-4,x_y_w_h_txt[3]-4,6]]]))
        var downState : Sprite = newSprite([x_y_w_h_txt[0],x_y_w_h_txt[1]],null,[["beginFill",[0xAAAAAA,1]],["drawRoundRect",[0,0,x_y_w_h_txt[2],x_y_w_h_txt[3],8]]]);
        downState.addChild(newShape([2,2],null,[["beginFill",[0xDDDDDD,1]],["drawRoundRect",[0,0,x_y_w_h_txt[2]-4,x_y_w_h_txt[3]-4,6]]]))
        var hitTestState : Shape = newShape([x_y_w_h_txt[0],x_y_w_h_txt[1]],null,[["beginFill",[0,1]],["drawRoundRect",[0,0,x_y_w_h_txt[2],x_y_w_h_txt[3],8]]]);
        if (x_y_w_h_txt[4])
        {
            upState.addChild(newTextField([0,2,x_y_w_h_txt[2],x_y_w_h_txt[3]-2],[["defaultTextFormat",new TextFormat("_sans", null, null, null, null, null, null, null, "center")],["text",x_y_w_h_txt[4]]]));
            overState.addChild(newTextField([0,2,x_y_w_h_txt[2],x_y_w_h_txt[3]-2],[["defaultTextFormat",new TextFormat("_sans", null, null, null, null, null, null, null, "center")],["text",x_y_w_h_txt[4]]]));
            downState.addChild(newTextField([0,3,x_y_w_h_txt[2],x_y_w_h_txt[3]-3],[["defaultTextFormat",new TextFormat("_sans", null, null, null, null, null, null, null, "center")],["text",x_y_w_h_txt[4]]]));
        }
        var sb : SimpleButton = new SimpleButton(upState,overState,downState,hitTestState);
        return sb;
    }
    public static function newShape(x_y_w_h_sh:Array = null,property:Array=null,graphics:Array=null):Shape
    {
        var i : int;
        var sh : Shape;
        if (x_y_w_h_sh && x_y_w_h_sh[4])
        {
            sh = x_y_w_h_sh[4];
        }
        else
        {
            sh = new Shape();
        }
        if (x_y_w_h_sh)
        {
            if (x_y_w_h_sh[0]) { sh.x = x_y_w_h_sh[0] };
            if (x_y_w_h_sh[1]) { sh.y = x_y_w_h_sh[1] };
        }
        if (property)
        {
            for (i = 0; i < property.length; i++) 
            {
                if (property[i] && property[i].length > 1)
                {
                    sh[property[i][0]] = property[i][1];
                }
            }
        }
        if (graphics)
        {
            for (i = 0; i < graphics.length; i++) 
            {
                if (graphics[i] && graphics[i].length > 1)
                {
                    sh.graphics[graphics[i][0]].apply(null, graphics[i][1]);
                }
            }
        }
        if (x_y_w_h_sh)
        {
            if (x_y_w_h_sh[2]) { sh.width = x_y_w_h_sh[2] };
            if (x_y_w_h_sh[3]) { sh.height = x_y_w_h_sh[3] };
        }
        return sh;
    }
    public static function newSprite(x_y_w_h_sp:Array = null,property:Array=null,graphics:Array=null,addChild:DisplayObject = null):Sprite
    {
        var i : int;
        var sp : Sprite;
        if (x_y_w_h_sp && x_y_w_h_sp[4])
        {
            sp = x_y_w_h_sp[4];
        }
        else
        {
            sp = new Sprite();
        }
        if (x_y_w_h_sp)
        {
            if (x_y_w_h_sp[0]) { sp.x = x_y_w_h_sp[0] };
            if (x_y_w_h_sp[1]) { sp.y = x_y_w_h_sp[1] };
        }
        if (property)
        {
            for (i = 0; i < property.length; i++) 
            {
                if (property[i] && property[i].length > 1)
                {
                    sp[property[i][0]] = property[i][1];
                }
            }
        }
        if (graphics)
        {
            for (i = 0; i < graphics.length; i++) 
            {
                if (graphics[i] && graphics[i].length > 1)
                {
                    sp.graphics[graphics[i][0]].apply(null, graphics[i][1]);
                }
            }

        }
        if (addChild)
        {
            sp.addChild(addChild);
        }
        if (x_y_w_h_sp)
        {
            if (x_y_w_h_sp[2]) { sp.width = x_y_w_h_sp[2] };
            if (x_y_w_h_sp[3]) { sp.height = x_y_w_h_sp[3] };
        }
        return sp;
    }
    public static function newTextField(x_y_w_h_txt_color_alpha:Array = null,property:Array=null,method:Array=null):TextField
    {
        var i : int;
        var ta : TextField = new TextField();
        ta.defaultTextFormat = defaultTextFormat;
        if (x_y_w_h_txt_color_alpha)
        {
            if (x_y_w_h_txt_color_alpha[0]) { ta.x = x_y_w_h_txt_color_alpha[0] };
            if (x_y_w_h_txt_color_alpha[1]) { ta.y = x_y_w_h_txt_color_alpha[1] };
            if (x_y_w_h_txt_color_alpha[2]) { ta.width = x_y_w_h_txt_color_alpha[2] };
            if (x_y_w_h_txt_color_alpha[3]) { ta.height = x_y_w_h_txt_color_alpha[3] };
            if (x_y_w_h_txt_color_alpha[4]) { ta.text = x_y_w_h_txt_color_alpha[4] };
            if (x_y_w_h_txt_color_alpha[5]) { ta.textColor = x_y_w_h_txt_color_alpha[5] };
            if (x_y_w_h_txt_color_alpha[6]) { ta.alpha = x_y_w_h_txt_color_alpha[6] };
        }
        if (property)
        {
            for (i = 0; i < property.length; i++) 
            {
                if (property[i] && property[i].length > 1)
                {
                    ta[property[i][0]] = property[i][1];
                }
            }
        }
        if (method)
        {
            for (i = 0; i < method.length; i++) 
            {
                if (method[i] && method[i].length > 1)
                {
                    ta[method[i][0]].apply(null, method[i][1]);
                }
            }
        }
        return ta;
    }
}