forked from: FLARToolKit Sample Simple_PV3D

by hacker_agodz82y forked from FLARToolKit Sample Simple_PV3D (diff: 416)
[コップの重さをメーターで表示する試み]
水を入れた量に応じて、メータの表示が変化する
*コップの重さは、コップ下においた感圧センサ(SFE-SEN-09376(Switch Science))の抵抗値を
japanino(Funnel Server)経由で取得し、その値を元に計算。
*メータは、FLARToolKitを使用して、コップを囲むように描画。
また、コップ形状にあわせた3Dオプジェクトを用意、blendMode.ERASEを使って、メータと重なった部分の
アルファ値を下げる。(コップの背後に回った部分を薄く描画することで、実際にある感じが出るよう試みた)
*動作のイメージは( http://wonderfl.net/c/xsMi )
→なんか、フレームレートがすごく遅い。
→この感圧センサで500g以下の重さを測るのは、誤差が大きくて、あまりうまく行かなかった。
FLARToolKit Sample - Simple cube PV3D
* --------------------------------------------------------------------------------
* Copyright (C)2010 rokubou
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Gene
♥0 | Line 471 | Modified 2010-08-11 18:39:15 | GPLv3 License | (replaced)
play

ActionScript3 source code

/**
 * Copyright hacker_agodz82y ( http://wonderfl.net/user/hacker_agodz82y )
 * GNU General Public License, v3 ( http://www.gnu.org/licenses/quick-guide-gplv3.html )
 * Downloaded from: http://wonderfl.net/c/znj8
 */

// forked from rokubou's FLARToolKit Sample Simple_PV3D
// [コップの重さをメーターで表示する試み]
// 水を入れた量に応じて、メータの表示が変化する
// *コップの重さは、コップ下においた感圧センサ(SFE-SEN-09376(Switch Science))の抵抗値を
//   japanino(Funnel Server)経由で取得し、その値を元に計算。
// *メータは、FLARToolKitを使用して、コップを囲むように描画。
//   また、コップ形状にあわせた3Dオプジェクトを用意、blendMode.ERASEを使って、メータと重なった部分の
//   アルファ値を下げる。(コップの背後に回った部分を薄く描画することで、実際にある感じが出るよう試みた)
// *動作のイメージは( http://wonderfl.net/c/xsMi )
//
// →なんか、フレームレートがすごく遅い。
// →この感圧センサで500g以下の重さを測るのは、誤差が大きくて、あまりうまく行かなかった。
/**
 * FLARToolKit Sample - Simple cube PV3D
 * --------------------------------------------------------------------------------
 * Copyright (C)2010 rokubou
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * For further information please contact.
 *  http://www.libspark.org/wiki/saqoosha/FLARToolKit
 * 
 * Contributors
 *  rokubou
 */
package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
	import flash.display.BlendMode;
    import flash.display.PixelSnapping;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
	import flash.filters.BlurFilter;
    
    import org.libspark.flartoolkit.core.FLARCode;
    import org.libspark.flartoolkit.core.param.FLARParam;
    import org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData;
    import org.libspark.flartoolkit.core.transmat.FLARTransMatResult;
    import org.libspark.flartoolkit.detector.FLARSingleMarkerDetector;
    import org.libspark.flartoolkit.support.pv3d.FLARBaseNode;
    import org.libspark.flartoolkit.support.pv3d.FLARCamera3D;
    import org.papervision3d.materials.WireframeMaterial;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.objects.primitives.Plane;
    import org.papervision3d.render.LazyRenderEngine;
    import org.papervision3d.scenes.Scene3D;
    import org.papervision3d.view.Viewport3D;
    
    [SWF(width=640, height=480, backgroundColor=0x808080, frameRate=30)]
    
    public class FLARToolKit_Sample_SimpleCube_PV3D extends Sprite
    {
        /**
         * 画面の幅と高さ
         */
        protected var canvasWidth:int;
        protected var canvasHeight:int;
        
        /**
         * 画面の幅と高さ
         */
        protected var captureWidth:int;
        protected var captureHeight:int;
        
        /**
         * マーカーの一辺の長さ(px)
         */
        protected var codeWidth:int;
        
        /**
         * カメラパラメータのファイル名
         * 内部的に初期化される処理が含まれるので読み込む必要は無い。
         * 例外的に 16:9 で使う場合は、それようのパラメータファイルを読み込むこと。
         */
        protected var cameraParamFile:String;
        
        /**
         * マーカーパターンのファイル名
         */
        protected var markerPatternFile:String;
        
        /**
         * パラメータファイル、マーカーパターンファイルの読込み用
         * @see flash.net.URLLoader
         */
        private var urlLoader:URLLoader;
        
        /**
         * カメラパラメータデータ
         * アスペクト比や歪みなどの補正のための情報が含まれる
         * @see org.libspark.flartoolkit.core.param.FLARParam
         */
        protected var cameraParam:FLARParam;
        
        /**
         * マーカーパターン
         * マーカーを複数パターン使う場合はVectorなどで管理する
         * @see org.libspark.flartoolkit.core.FLARCode
         */
        protected var markerPatternCode:FLARCode;
        
        /**
         * @see flash.media.Camera
         */
        protected var webCamera:Camera;
        
        /**
         * flash.media.Video
         */
        protected var video:Video;
        
        /**
         * Webカメラからの入力をBitmapに確保する
         * @see flash.display.Bitmap
         */
        private var capture:Bitmap;
        
        /**
         * ラスタイメージ
         * @see org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData
         */
        private var raster:FLARRgbRaster_BitmapData;
        
        /**
         * Marker detector
         * @see org.libspark.flartoolkit.detector.FLARSingleMarkerDetector
         */
        private var detector:FLARSingleMarkerDetector;
        
        /**
         * 3Dモデル表示用
         */
        protected var scene:Scene3D;
        
        /**
         * 3Dモデル表示用
         */
        protected var viewport:Viewport3D;
        
        /**
         * 3Dモデル表示字の視点
         */
        protected var camera3D:FLARCamera3D;
        
        /**
         * Marker base node
         */
        protected var markerNode:FLARBaseNode;
        
        /**
         * 3D Renderer
         */
        protected var renderer:LazyRenderEngine;
        
        /**
         * 表示モデルを一括して押し込めるコンテナ
         */
        protected var container:DisplayObject3D;
        
        private var plane:Plane;
        // private var _cube:Cube;

		private var _meter:Meter;
		private var _occlude:OccludeObject;
		private var _debug:DebugWindow;
		private var _sensor:FSRSensor;
		private var _rawData:Number;
		private var _weight:Number;
		private var _height:Number;
        
        /**
         * Constructor
         * ここから初期化処理を呼び出して処理をスタート
         */
        public function FLARToolKit_Sample_SimpleCube_PV3D()
        {
            Wonderfl.capture_delay( 5 );
            this.initialize();
        }
        
        /**
         * initialize
         *  各種サイズの初期化
         */
        protected function initialize():void
        {
            // 各種サイズの初期化
            captureWidth = 320;
            captureHeight = 240;
            canvasWidth = 640
            canvasHeight = 480;
            codeWidth = 80;
            
            //
            markerPatternFile = 'http://assets.wonderfl.net/static/flar/flarlogo.pat';
            
            // パラメータファイルの読込み
            // 今回は省略して初期値を用いる
            this.cameraParam = new FLARParam();
            this.cameraParam.changeScreenSize(captureWidth, captureHeight);
            
            // マーカーパターンファイルの読込み
            this.urlLoader = new URLLoader();
            this.urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
            this.urlLoader.addEventListener(Event.COMPLETE, this.onLoadCode);
            this.urlLoader.addEventListener(IOErrorEvent.IO_ERROR, dispatchEvent);
            this.urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, dispatchEvent);
            this.urlLoader.load(new URLRequest(markerPatternFile));
        }
        
        /**
         * マーカーパターンを読み込む
         * @param e Event
         */
        protected function onLoadCode(e:Event):void
        {
            // URL Loader関連のイベントを削除
            this.urlLoader.removeEventListener(Event.COMPLETE, this.onLoadCode);
            
            // 分割数(縦・横)、黒枠の幅(縦・横)
            this.markerPatternCode = new FLARCode(16, 16, 50, 50);
            this.markerPatternCode.loadARPatt(this.urlLoader.data);
            // loaderがgc対象になるようにnullを突っ込む
            this.urlLoader = null;
            
            // 初期化
            dispatchEvent(new Event(Event.INIT));
            this.onInit();
        }
        
        /**
         * Webカメラの設定と、ARToolKitの準備
         */
        protected function onInit():void
        {
            // setup webcam
            this.webCamera = Camera.getCamera();
            if (!this.webCamera) {
                throw new Error('No webcamera!');
            }
            this.webCamera.setMode(this.captureWidth, this.captureHeight, 30);
            
            this.video = new Video( this.captureWidth, this.captureHeight);
            this.video.attachCamera(this.webCamera);
            
            // setup ARToolKit
            this.capture = new Bitmap(new BitmapData(this.captureWidth, this.captureHeight, false, 0),
                                       PixelSnapping.AUTO,
                                       true);
            // ウェブカメラの解像度と表示サイズが異なる場合は拡大する
            this.capture.width = this.canvasWidth;
            this.capture.height= this.canvasHeight;
            this.addChild(this.capture);
            
            this.raster = new FLARRgbRaster_BitmapData(this.capture.bitmapData);
            // setup Single marker detector
            this.detector = new FLARSingleMarkerDetector(this.cameraParam,
                                                          this.markerPatternCode,
                                                          this.codeWidth);
            this.detector.setContinueMode(true);
            
            // 表示関係の設定(使用するライブラリによって変化します)
            this.viewport = this.addChild(new Viewport3D(this.captureWidth,
                                                          this.captureHeight)) as Viewport3D;
            this.viewport.scaleX = this.canvasWidth / this.captureWidth;
            this.viewport.scaleY = this.canvasHeight / this.captureHeight;
            this.viewport.x = -4; // なぜかずれるので補正
            
            // 
            this.scene = new Scene3D();
            this.markerNode = this.scene.addChild(new FLARBaseNode()) as FLARBaseNode;
            
            // 3Dモデル表示時の視点を設定
            this.camera3D = new FLARCamera3D(this.cameraParam);
            
            // setup renderer
            this.renderer = new LazyRenderEngine(this.scene, this.camera3D, this.viewport);
            
            // モデル格納用のコンテナ作成
            this.container = new DisplayObject3D();
            // モデルデータ
            this.setModelData();
            // モデルデータを登録
            this.markerNode.addChild(this.container);
            
			// その他の初期化
			_sensor = new FSRSensor();
			_debug = new DebugWindow();
			this.addChild( _debug.out );
			
            // start
            this.start();
        }
        
        /**
         * モデルデータを書く場所
         */
        protected function setModelData():void
        {
            // ワイヤーフレームで、マーカーと同じサイズのPlaneを作成
            var wmat:WireframeMaterial = new WireframeMaterial(0x0000ff, 1, 2);
            this.plane = new Plane(wmat, 80, 80);
            this.plane.rotationX = 180;
//            this.container.addChild(this.plane);
			this.markerNode.addChild( this.plane );
			
			container.rotationX = 90.0;
			container.x = 100.0;
			container.z = 30.0;

			_meter = new Meter();
			_occlude = new OccludeObject();
            this.container.addChild( this._meter.out );
            this.container.addChild( this._occlude.out );
			
			this.viewport.blendMode = BlendMode.LAYER;
			this.viewport.getChildLayer( this._occlude.out ).blendMode = BlendMode.ERASE;
			this.viewport.getChildLayer( this._occlude.out ).filters = [ new BlurFilter( 8, 8, 4 ) ];
        }
        
        /**
         * マーカーの認識と3次元モデルの描写を開始する
         */
        public function start():void
        {
            // マーカー認識・非認識時用のイベントを登録
            this.addEventListener(MarkerEvent.MARKER_ADDED, this.onMarkerAdded);
            this.addEventListener(MarkerEvent.MARKER_UPDATED, this.onMarkerUpdated);
            this.addEventListener(MarkerEvent.MARKER_REMOVED, this.onMarkerRemoved);
            
            // 処理開始
            this.addEventListener(Event.ENTER_FRAME, this.run);
        }
        /**
         * 認識したマーカーの情報を格納
         */
        protected var resultMat:FLARTransMatResult = new FLARTransMatResult();

        public function onMarkerAdded(e:Event=null):void
        {
//          trace("[add]");
            this.detector.getTransformMatrix(this.resultMat);
            this.markerNode.setTransformMatrix(this.resultMat);
            this.markerNode.visible = true;
        }
        
        public function onMarkerUpdated(e:Event=null):void
        {
            // 今回は実装していない
        }

        public function onMarkerRemoved(e:Event=null):void
        {
            this.markerNode.visible = false;
//          this.renderer.render();
        }
        
        /**
         * ここで処理振り分けを行っている
         */
        public function run(e:Event):void
        {
            this.capture.bitmapData.draw(this.video);
            
            // Marker detect
            var detected:Boolean = false;
            try {
                detected = this.detector.detectMarkerLite(this.raster, 80) && this.detector.getConfidence() > 0.5;
            } catch (e:Error) {}
            
            // 認識時の処理
            if (detected) {
                // 一工夫できる場所
                // 前回認識した場所と今回認識した場所の距離を測り、
                // 一定範囲なら位置情報更新 MARKER_UPDATED を発行するなど、
                // 楽しい工夫が出来る。 参照: FLARManager
                this.dispatchEvent(new MarkerEvent(MarkerEvent.MARKER_ADDED));
            // 非認識時
            } else {
                this.dispatchEvent(new MarkerEvent(MarkerEvent.MARKER_REMOVED));
            }

			// センサ情報の更新
			_sensor.update();
			// 重さ・高さ情報の決定
			_debug.rawData = _rawData = _sensor.out;
			_debug.weight = _weight = rawData2weight( _rawData );
			_debug.height = _height = weight2height( _weight );			
/*
			// マウスの座標を元に、重さ・高さを決定する
			_height = 100.0 * ( 1 - stage.mouseY / stage.stageHeight );
			_weight = 999.0 * ( 1 - stage.mouseX / stage.stageWidth );
*/
			// 入力パラメータの設定
			_meter.input( _weight, _height );
			_occlude.input( _height );
			// 各種状態を更新
			_meter.update();
			_occlude.update();
			_debug.update();
			
            this.renderer.render();
        }
        
		// 予め取得したデータ群を元に、近似曲線をExcelのグラフ機能で取得、変換式を作る
		private function rawData2weight( x:Number ):Number {
			return( Math.exp( ( x + 1514.92 ) / 376.62 ) );
		}
		private function weight2height( x:Number ):Number {
			return( 0.46 * x - 81.46 );
		}
    }
}


import flash.events.Event;

/**
 * イベント制御用の簡易クラス
 */
class MarkerEvent extends Event
{
    /**
     * Markerを認識した時
     */
    public static const MARKER_ADDED:String = "markerAdded";
    
    /**
     * Marker更新時
     */
    public static const MARKER_UPDATED:String = "markerUpdated";
    
    /**
     * Markerが認識しなくなった時
     */
    public static const MARKER_REMOVED:String = "markerRemoved";
    
    public function MarkerEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
    {
        super(type, bubbles, cancelable);
    }
}

import flash.filters.*;
import org.papervision3d.core.math.Plane3D;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.materials.special.*;
import org.papervision3d.core.geom.*;
import org.papervision3d.typography.fonts.*;
import org.papervision3d.typography.*;
import org.papervision3d.view.layer.*;
import flash.display.*;
import flash.events.KeyboardEvent;
import caurina.transitions.Tweener;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import funnel.*;

class Meter {
	// 定数
	private const _prmRing:Object = {
		nDiv:20, radius:100, width:20.0, height:18.0,
		color: { on:0xFFFFFF, off:0x000000 },
		alpha: { on:0.8, off:0.05 }
	};
	private const _prmLine:Object = {
		nDiv:30, radius:80, startPosz:-102, width:2.0,
		color:0xFFFFFF, alpha:0.9
	};
	private const _prmDisp:Object = {
		posx:-54, posz:-100, scale:0.22,
		color:0xFFFFFF, alpha:0.8
	};
	private const _prmBlur:Object = {
		blurX:2, blurY:2, quality:1
	};
	private const _prmGlow:Object = {
		color:0x00FF00, alpha:0.5, blurX:10, blurY:10, strength:4, quality:2
	};
	private const _prmGlowRing:Array = [
		{ thresh:0.00, color:0x00FF00 },
		{ thresh:0.50, color:0xC08000 },
		{ thresh:0.80, color:0xFF0000 }
	];
	private const _weightFullscale:Number = 500.0;

	//
    private var _percent:Number;
	private var _weight:Number;
	private var _height:Number;
    private var _wrap:DisplayObject3D;
	private var _ring:DisplayObject3D;
	private var _line:Lines3D;
	private var _disp:Text3D;
	private var _planesRing:Array;
	private var _matRing:Object;
	private var _filterBlur:BlurFilter;
	private var _filterGlow:GlowFilter;
	
    public function Meter() {
		////////// 変数初期化
		_percent = 0.0;
        _height = 0.0;
        _weight = 0.0;
		_matRing = new Object();
        _planesRing = new Array();
        _wrap = new DisplayObject3D();

		////////// 全体に適用するフィルタを生成
		_filterBlur = new BlurFilter( _prmBlur.blurX, _prmBlur.blurX, _prmBlur.quality );
		_filterGlow = new GlowFilter( _prmGlow.color, _prmGlow.alpha, _prmGlow.blurX, _prmGlow.blurY, _prmGlow.strength, _prmGlow.quality );

		////////// 表示部分の生成
		// リング型メータ部の生成
		_ring = createRing( _planesRing, _prmRing.width, _prmRing.height, _prmRing.nDiv );
		// リング型メータ部のマテリアル生成(ON/OFF状態によりマテリアルを変更)
		_matRing[ "on"  ] = new ColorMaterial( _prmRing.color.on,  _prmRing.alpha.on  );
		_matRing[ "off" ] = new ColorMaterial( _prmRing.color.off, _prmRing.alpha.off );
		// ライン部の生成
		_line = createLine( _prmLine.width, _prmLine.color, _prmLine.alpha, _prmLine.nDiv );
		// テキスト表示部の生成
		_disp = createDisplay( _prmDisp.color, _prmDisp.alpha );
		// 生成した各要素を統合
		_wrap.addChild( _ring );
		_wrap.addChild( _line );
		_wrap.addChild( _disp );
		
		////////// 各パラメータを更新
		update();
    }

    public function update():void {
		_percent = _weight / _weightFullscale;
		
		// メータの各Plane毎に、マテリアルを決定
		for ( var i:int = 0; i < _prmRing.nDiv; i++ ) {
			var pln:Plane;
			var onThresh:Number;

			// このPlaneのON/OFF閾値を計算
			onThresh = ( i + 0.5 ) / _prmRing.nDiv;			

			// このPlaneのON/OFF状態に応じて、マテリアルを設定
			pln  = _planesRing[i]  as Plane;
			if ( onThresh < _percent ) {
				pln.material  = _matRing.on;
			} else {
				pln.material  = _matRing.off;
			}
       }
       
	   _wrap.y = _height;
	   _disp.text = weightText( int( _weight ) );	   
    }

    public function get out():DisplayObject3D {
        return( _wrap );
    }
        
    public function input( weight:Number, height:Number ):void {
        _weight = weight;
        _height = height;
    }
    
	private function createRing( objArray:Array, width:Number, height:Number, nDiv:int ):DisplayObject3D {
		var wrap:DisplayObject3D = new DisplayObject3D();
		
        for ( var i:int = 0; i < nDiv; i++ ) {
            var cmat:ColorMaterial = new ColorMaterial( 0x000000, 0.0 );
            var flt:GlowFilter = new GlowFilter( 0x000000, _prmGlow.alpha, _prmGlow.blurX, _prmGlow.blurY, _prmGlow.strength, _prmGlow.quality );
            var pln:Plane = new Plane( cmat, width, height );
			var col:Number;
			var rot:Number;

			// 動的に変更する内容は、配列に格納しておく
			objArray.push( pln );					// マテリアルを途中で変更するので
			
			// リング上での位置によって、グローフィルタの色を変更する
			col = _prmGlowRing[0].color;
			for ( var j:int = 0; j < _prmGlowRing.length; j++ ) {
				if ( _prmGlowRing[j].thresh * (nDiv - 1) <= i ) {
					col = _prmGlowRing[j].color;
				}
			}
			flt.color = col;

			// フィルタの設定
			pln.filters = [ _filterBlur, flt ];		// グローフィルタだけは、他とは異なるものを使用する
			pln.useOwnContainer = true;
			
            rot = 360.0 * 4/5 * ( i / nDiv );
            pln.x = _prmRing.radius * Math.cos( rot * Math.PI / 180 );
            pln.z = _prmRing.radius * Math.sin( rot * Math.PI / 180 );
            pln.rotationX = 90.0;
            pln.rotationY = -rot;
            wrap.addChild( pln );
        }

		wrap.rotationY = 90.0;		
		return( wrap );
	}
	
	private function createLine( lineWidth:Number, color:Number, alpha:Number, nDiv:int ):Lines3D {
        var lmat:LineMaterial = new LineMaterial( color, alpha );
		var line:Lines3D = new Lines3D( lmat );

		// フィルタの設定
		line.filters = [ _filterBlur, _filterGlow ];
		line.useOwnContainer = true;
		
		for ( var i:int = 0; i < ( nDiv - 1 ); i++ ) {
			var rot1:Number  = 360.0 * 4/5 * ( i / nDiv );
			var rot2:Number  = 360.0 * 4/5 * ( (i+1) / nDiv );
			var posx1:Number = _prmLine.radius * Math.cos( rot1 * Math.PI / 180 );
			var posz1:Number = _prmLine.radius * Math.sin( rot1 * Math.PI / 180 );
			var posx2:Number = _prmLine.radius * Math.cos( rot2 * Math.PI / 180 );
			var posz2:Number = _prmLine.radius * Math.sin( rot2 * Math.PI / 180 );
			line.addNewLine( lineWidth, posx1, 0, posz1, posx2, 0, posz2 );
		}
		line.addNewLine( lineWidth, _prmLine.radius, 0, _prmLine.startPosz, _prmLine.radius, 0, 0 );

		line.rotationY = 90.0;		
		return( line );
	}
	
	private function createDisplay( color:Number, alpha:Number ):Text3D {
		var lmat:Letter3DMaterial = new Letter3DMaterial( color, alpha );
		var disp:Text3D = new Text3D( "" , new HelveticaMedium(), lmat);

		// フィルタの設定
		disp.filters = [ _filterBlur, _filterGlow ];
		disp.useOwnContainer = true;
		
		disp.scale = _prmDisp.scale;
		disp.x = _prmDisp.posx;
		disp.z = _prmDisp.posz;
		disp.rotationX = 60;
		return( disp );
	}
	
	private function weightText( wt:int ):String {
		var result:String = "Wt:";
		var str:String = wt.toString();
		for ( var i:int = 0; i < ( 3 - str.length ); i++ ) {
			result += "0";
		}
		result += str + "g";
		return( result );
	}
}

class OccludeObject {
	// 定数
    private const _nDiv:int = 32;
	private const _topPos:Number = 135.0;			// オプジェクトの上面位置
	private const _tempHeight:Number = 20.0;		// 仮の高さ
													//  プリミティブの高さを途中で変える方法がわからないので
													//  仮の高さで生成しておいて、Y方向のスケール変更で伸縮させる
	private const _color:Number  = 0xFFFFFF;
	private const _radius:Number = 30.0;
	private const _alpha:Object  = { enable:0.8, disable:0.0 };
	
	//
	private var _bottomPos:Number;					// オプジェクトの下面位置
	private var _objectHeight:Number;				// オブジェクトの高さ
	private var _isEnable:Boolean;					// 遮蔽を有効・無効化する
	private var _colorMat:ColorMaterial;
	private var _cylinder:Cylinder;
	private var _occludeObj:DisplayObject3D;

	public function OccludeObject() {
		// 変数初期化
		_bottomPos = 0.0;
		_objectHeight = 0.0;
		_isEnable = false;
		_colorMat = new ColorMaterial( _color, _alpha.disable );
		_occludeObj = new DisplayObject3D();
		
		// 遮蔽用オブジェクトの生成
		_cylinder = new Cylinder( _colorMat, _radius, _tempHeight, _nDiv ); 
		_occludeObj.addChild( _cylinder );
		
		// 各パラメータを更新
		update();
	}
	
	public function update():void {
		// 遮蔽用オプジェクトの高さ計算
		_objectHeight = _topPos - _bottomPos;
		
		// 高さの検証し、プラスの場合のみ遮蔽を行う
		if ( _objectHeight > 0 ) {
			_isEnable = true;
		} else {
			_isEnable = false;
			// 高さをデフォルト値(プラスの値にしたいので)に書き換える
			_objectHeight = _tempHeight;
		}
		
		// 遮蔽用オプジェクトの高さに応じて、Y方向中心位置、Y方向スケールを変更する
		_cylinder.y = _topPos - _objectHeight / 2.0;			// 上面位置を基準とする
		_cylinder.scaleY = _objectHeight / _tempHeight;
		
		// 遮蔽の有効・無効に応じて、遮蔽用オブジェクトの透過率を変化させる
		if ( _isEnable ) {
			_colorMat.fillAlpha = _alpha.enable;
		} else {
			_colorMat.fillAlpha = _alpha.disable;
		}		
	}
	
	public function get out():DisplayObject3D {
		return( _occludeObj );
	}

	public function input( basePosition:Number ):void {
		_bottomPos = basePosition;
	}
}

class FSRSensor {
	private var _arduino:Arduino;
	private var _sensorPin:Pin;
	private var _rawData:Number;

	public function FSRSensor() {
		_arduino = new Arduino( Arduino.FIRMATA );
		_sensorPin = _arduino.analogPin(0);
	}
	
	public function update():void {
		_rawData = _sensorPin.value * 1000;
	}

	public function get out():int
	{
		return( _rawData );
	}
}

class DebugWindow {
	private const _prm:Object = {
		width:200, height:73, posx:2, posy:482
	};

	public var rawData:Number = 0.0;
	public var weight:Number = 0.0;
	public var height:Number = 0.0;

	private var _sprite:Sprite;
	private var _text:TextField;
	
	public function DebugWindow() {
		_sprite = new Sprite();
		_sprite.x = _prm.posx;
		_sprite.y = _prm.posy;

		var g:Graphics = _sprite.graphics;
		g.beginFill( 0x202020, 0.7 );
		g.drawRect( 0, 0, _prm.width, _prm.height );
		g.endFill();
		
		_text = new TextField();
		var _tf:TextFormat = new TextFormat( "_等幅", 16, 0xFFFFFF );
		_text.defaultTextFormat = _tf;
		_text.textColor = 0xFFFFFF;
		_text.x = 20;
		_text.y = 3;
		_text.width = _prm.width - _text.x * 2;
		_sprite.addChild( _text );
		
		update();
	}
	
	public function get out():Sprite {
		return( _sprite );
	}
	
	public function update():void {
		_text.text = "FSR Sensor\n";
		_text.appendText( "RawData: " + rawData.toFixed(1) + "\n" );
		_text.appendText( " Weight: " +  weight.toFixed(1) + "\n" );
		_text.appendText( " Height: " +  height.toFixed(1) + "\n" );
	}
}