forked from: flash on 2010-4-13

by yotsu42keisuke
Gainerでの加速度センサによる、オブジェクトの回転、移動。

回転は360度回転したかったし、
移動は回転とは独立な値にしたかったけど、
加速度センサの限界っぽい。

◆360度回転
まず、360度回転は、x軸のみ、y軸のみだったら、問題ない。
ただ、x,y両方を360度回転ではうまくいかない。
いろいろ値をこねくり回してみたが駄目だった。
結局の所、z軸回転をとれないのだから、
正確な姿勢取得ができないという前提に戻ってあきらめた。

◆水平移動の取得
回転とは独立の移動については、
z軸の変化が少ない時に水平移動としてとらえる方法を試したが、
回転値の取得と兼用だとその判別が難しい。
またセンサの誤差も吸収が困難だった。

wiiやPS3で、赤外線センサやジャイロセンサを併用している
理由もなんとなく実感できた。

◆トラッキング
加速度センサはモジュールによって誤差が大きそうだったので、
とりあえず水平時のトラッキング(xとyの中央値、zの最大値)を
取得してから始めるようにした。
もっと正確にやるには、全部の値の最少、中央、最大値を
取得したほうがいいはずだけど、煩雑すぎるような。
♥0 | Line 189 | Modified 2010-12-02 22:38:28 | MIT License
play

ActionScript3 source code

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

// forked from Phahede's flash on 2010-4-13
/*
 * Gainerでの加速度センサによる、オブジェクトの回転、移動。
 * 
 * 回転は360度回転したかったし、
 * 移動は回転とは独立な値にしたかったけど、
 * 加速度センサの限界っぽい。
 * 
 * ◆360度回転
 * まず、360度回転は、x軸のみ、y軸のみだったら、問題ない。
 * ただ、x,y両方を360度回転ではうまくいかない。
 * いろいろ値をこねくり回してみたが駄目だった。
 * 結局の所、z軸回転をとれないのだから、
 * 正確な姿勢取得ができないという前提に戻ってあきらめた。
 * 
 * ◆水平移動の取得
 * 回転とは独立の移動については、
 * z軸の変化が少ない時に水平移動としてとらえる方法を試したが、
 * 回転値の取得と兼用だとその判別が難しい。
 * またセンサの誤差も吸収が困難だった。
 * 
 * wiiやPS3で、赤外線センサやジャイロセンサを併用している
 * 理由もなんとなく実感できた。
 * 
 * ◆トラッキング
 * 加速度センサはモジュールによって誤差が大きそうだったので、
 * とりあえず水平時のトラッキング(xとyの中央値、zの最大値)を
 * 取得してから始めるようにした。
 * もっと正確にやるには、全部の値の最少、中央、最大値を
 * 取得したほうがいいはずだけど、煩雑すぎるような。
 * 
 * */

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix3D;
    import flash.geom.PerspectiveProjection;
    import flash.geom.Point;
    import flash.geom.Vector3D;
    import flash.display.DisplayObjectContainer;
    
    public class Main extends Sprite {
        private var fin:Fin;
        public function Main() {
            
            stage.transform.perspectiveProjection = new PerspectiveProjection();
            stage.transform.perspectiveProjection.projectionCenter = new Point(465/2,465/2);
            
            fin = new Fin();
            fin.z = 0;
            fin.x = 465 / 2;
            fin.y = 465 / 2+50;
            this.addChild(fin);
            zSort(fin);
            
            var accelerometerWrapper:AccelerometerWrapper = new AccelerometerWrapper();
            this.addChild(accelerometerWrapper);
            accelerometerWrapper.onParam = onParam;
            
        }
        
        public function onParam(rArray:Array, tArray:Array):void {
            fin.rotationX = rArray[0];
            fin.rotationY = rArray[1];
            fin.rotationZ = rArray[2];
            fin.x += tArray[0];
            fin.y += tArray[1];
            fin.z += tArray[2];
            zSort(fin);
        }
        
        private function zSort(target:DisplayObjectContainer):void {
            if(!target.root){return};
            var n:int = target.numChildren;
            var array:Array = [];
            var reference:Array = [];
            for (var i:int = 0; i < n; i++) {
                var poz:Vector3D = target.getChildAt(i).transform.getRelativeMatrix3D(this.root.stage).position;
                var point:Point = stage.transform.perspectiveProjection.projectionCenter;
                array[i] = poz.subtract(new Vector3D(point.x,point.y,-stage.transform.perspectiveProjection.focalLength)).length;
                reference[i] = target.getChildAt(i);
            }
            var temp:Array = array.sort(Array.NUMERIC | Array.RETURNINDEXEDARRAY);
            for (i = 0; i < n; i++) {
                target.setChildIndex(reference[temp[i]],0);
                if(reference[temp[i]].numChildren > 1){
                    zSort(reference[temp[i]]);
                }
            }
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import funnel.*;
import funnel.gui.*;
import funnel.ui.*;

class AccelerometerWrapper extends Sprite {
    // Gainerオブジェクト
    private var _gainer:Gainer;
    private var _textSp:Sprite;
    public function AccelerometerWrapper() {
        // Gainerのインスタンスを生成
        _gainer = new Gainer();
        
        // Gainer GUIのインスタンスを生成して配置
        var gui:GainerGUI = new GainerGUI();
        //gui.x = 200;
        //gui.y = 200;
        addChild(gui);
        _gainer.gui = gui;
        
        
        var _textField:TextField = new TextField();
        _textField.defaultTextFormat = new TextFormat("_sans", 14, 0xFFFFFF);
        _textField.text = "Gainerモジュールを\n平らな机の上に置いて\nマウスをクリック\nしてください。";
        _textField.autoSize = "left";
        
        _textSp = new Sprite();
        _textSp.graphics.beginFill(0x000000, 0.8);
        _textSp.graphics.drawRoundRect(0, 0, _textField.width+32, _textField.height+32, 16, 16);
        _textSp.graphics.endFill();
        _textSp.x = (465 - _textSp.width) / 2;
        _textSp.y = (465 - _textSp.height) / 2+32;
        this.addChild(_textSp);
        
        _textField.x = (_textSp.width - _textField.width) / 2;
        _textField.y = (_textSp.height - _textField.height) / 2;
        _textSp.addChild(_textField);
        
        
        // ボタンに対してイベントリスナをセット
        _gainer.button.addEventListener(ButtonEvent.PRESS, onPress);
        _gainer.analogInput(0).filters = [new Convolution(Convolution.MOVING_AVERAGE)];
        _gainer.analogInput(1).filters = [new Convolution(Convolution.MOVING_AVERAGE)];
        _gainer.analogInput(2).filters = [new Convolution(Convolution.MOVING_AVERAGE)];
        
    }
    private function onPress(event:ButtonEvent):void {
        trace(event.type);
        if (event.type == "press") {
            _gainer.button.removeEventListener(ButtonEvent.PRESS, onPress);
            this.removeChild(_textSp);
            trace(_gainer.analogInput(0).value);
            trace(_gainer.analogInput(1).value);
            trace(_gainer.analogInput(2).value);
            
            setTrackingValue(_gainer.analogInput(0).value, _gainer.analogInput(1).value, _gainer.analogInput(2).value);
            
            this.removeEventListener(Event.ENTER_FRAME, onEnter);
            this.addEventListener(Event.ENTER_FRAME, onEnter);
        }
    }
    
    private var tracking:Array;
    private function setTrackingValue(a0:Number, a1:Number, a2:Number):void {
        tracking = [];
        tracking[0] = [0.345, 0.584, 0.831];
        tracking[1] = [0.328, 0.561, 0.815];
        tracking[2] = [0.42, 0.635, 0.853];
        tracking[0][1] = a0;
        tracking[1][1] = a1;
        tracking[2][2] = a2;
    }
    private function scale0(num:Number):Number {
        var y:Number;
        if (num < tracking[0][1]) {
            y = -(tracking[0][1] - num) / (tracking[0][1] - tracking[0][0]);
        }else {
            y = (num - tracking[0][1]) / (tracking[0][2] - tracking[0][1]);
        }
        y = Math.min(1, Math.max(-1, y));
        return y;
    }
    private function scale1(num:Number):Number {
        var y:Number;
        if (num < tracking[1][1]) {
            y = -(tracking[1][1] - num) / (tracking[1][1] - tracking[1][0]);
        }else {
            y = (num - tracking[1][1]) / (tracking[1][2] - tracking[1][1]);
        }
        y = Math.min(1, Math.max(-1, y));
        return y;
    }
    private function scale2(num:Number):Number {
        var y:Number;
        if (num < tracking[2][1]) {
            y = -(tracking[2][1] - num) / (tracking[2][1] - tracking[2][0]);
        }else {
            y = (num - tracking[2][1]) / (tracking[2][2] - tracking[2][1]);
        }
        y = Math.min(1, Math.max(-1, y));
        return y;
    }
    
    private function onEnter(event:Event):void {
        atParam(_gainer.analogInput(0).value, _gainer.analogInput(1).value, _gainer.analogInput(2).value);
    }
    
    public var onParam:Function = function(rArray:Array, tArray:Array):void { };
    public function atParam(a0:Number, a1:Number, a2:Number):void {
        a0 = scale0(a0);
        a1 = scale1(a1);
        a2 = scale2(a2);
        
        var rArray:Array = [0, 0, 0];
        var tArray:Array = [0, 0, 0];
        if(Math.abs(a2)<97){
            rArray[0] = Math.asin(a0) / Math.PI * 180;
            tArray[0] = a1*5;
            rArray[2] = Math.asin(a1) / Math.PI * 180;
            tArray[2] = -a0*5;
        }
        onParam(rArray, tArray);
    }
}


import flash.display.Sprite;
class Fin extends Sprite {
    public function Fin() {
        var xyr:Array = [[90, 0, 0, 0xFF0000], [0, 0, 0, 0x00FF00], [0, 90, 0, 0x0000FF]];
        for (var j:int = 0; j < 3; j++) {
            for (var i:int = 0; i < 4; i++) {
                var sp:Sprite = new Sprite();
                sp.graphics.lineStyle(1, xyr[j][3], 0.5);
                sp.graphics.beginFill(xyr[j][3], 0.25);
                sp.graphics.drawRect(-25, -25, 50, 50);
                sp.graphics.endFill();
                sp.rotationX = xyr[j][0];
                sp.rotationY = xyr[j][1];
                if (j == 0) {
                    sp.x = 25-50 * (i % 2);
                    sp.z = 25-50*(Math.floor(i/2));
                }else if (j == 1) {
                    sp.x = 25-50 * (i % 2);
                    sp.y = 25-50*(Math.floor(i/2));
                }else if (j == 2) {
                    sp.y = 25-50 * (i % 2);
                    sp.z = 25-50*(Math.floor(i/2));
                }
                
                this.addChild(sp);
            }
        }
        
    }
}