くるくるカール with Motion Tracking
forked from mousepancyo's くるくるカール(forked from: Draw worm by mouse gesture)
Webカメラでのモーショントラッキングを追加してみました。
// forked from mousepancyo's くるくるカール(forked from: Draw worm by mouse gesture)
// forked from nutsu's Draw worm by mouse gesture.
// forked from nutsu's Worm matrix based.
/**
LOVE MATRIX.
a study for drawing curl curve.
license under the GNU Lesser General Public License.
*/
package
{
import flash.display.Sprite;
[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "0")]
public class Main extends Sprite
{
private var _canvas:WormMatrix;
private var _w:int = stage.stageWidth;
private var _h:int = stage.stageHeight;
public function Main()
{
_canvas = new WormMatrix(_w, _h);
var sp:Sprite = new Sprite();
sp.addChild(_canvas.video);
sp.scaleX = -2;
sp.scaleY = 2;
sp.x = stage.stageWidth;
addChild(sp);
addChild(new Grid());
addChild(_canvas);
}
}
}
// ------------ Class WormMatrix ----------------------------------//
//package {
import frocessing.display.F5MovieClip2DBmp;
import frocessing.geom.FMatrix2D;
import frocessing.color.ColorHSV;
import flash.geom.ColorTransform;
import flash.media.Camera;
import flash.media.Video;
import flash.geom.Point;
internal class WormMatrix extends F5MovieClip2DBmp{
private var vms:Array;
private var MAX_NUM:int = 150;
private var N:Number = 120;
private var px:Number;
private var py:Number;
private var ct:ColorTransform = new ColorTransform(1, 1, 1, .99);
private var t:Number = 0;
//
public var video:Video;
private var _cam:Camera;
private var _tracker:Tracker;
private var _trackX:Number = 0;
private var _trackY:Number = 0;
private var _p:Point = new Point();
//
private var _w:int;
private var _h:int;
public function WormMatrix (w:int, h:int) {
_w = w;
_h = h;
//
super( true, 0 );
vms = [];
initVideo();
}
public function setup():void
{
size( _w, _h );
background(0, 0);
noStroke();
px = _tracker.trackPoint.x;
py = _tracker.trackPoint.y;
}
private function initVideo():void {
video = new Video(320, 240);
_cam = Camera.getCamera();
_cam.setMode(video.width, video.height, 10);
video.attachCamera(_cam);
//
_tracker = new Tracker(_w, _h, video);
}
public function check():void
{
var x0:Number = _tracker.trackPoint.x;
var y0:Number = _tracker.trackPoint.y;
var vx:Number = x0 - px;
var vy:Number = y0 - py;
var len:Number = min( mag( vx, vy ), 50 );
if( len<10 ) return;
var mtx:FMatrix2D = new FMatrix2D();
mtx.rotate( atan2( vy, vx ) );
mtx.translate( x0, y0 );
createObj( mtx, len );
px = x0;
py = y0;
}
public function createObj( mtx:FMatrix2D, len:Number ):void
{
var angle:Number = random(PI/180, PI/2);
if( Math.random() > 0.5 ) angle *= -1;
var tmt:FMatrix2D = new FMatrix2D();
tmt.scale( 0.95, 0.95 );
tmt.rotate( angle );
tmt.translate( len, 0 );
var w:Number = 0.5;
var obj:WormObject = new WormObject();
obj.c1x = obj.p1x = -w * mtx.c + mtx.tx;
obj.c1y = obj.p1y = -w * mtx.d + mtx.ty;
obj.c2x = obj.p2x = w * mtx.c + mtx.tx;
obj.c2y = obj.p2y = w * mtx.d + mtx.ty;
obj.vmt = mtx;
obj.tmt = tmt;
obj.r = angle;
obj.w = len * .1;
obj.count = 0;
vms.push( obj );
if( vms.length > MAX_NUM )
vms.shift();
}
public function draw():void
{
if( isMousePressed )
{
background(0, 0);
vms = [];
}
stroke(0xFFFFFF, .5);
var len:int = vms.length;
for( var i:int=0; i<len; i++ )
{
var o:WormObject = vms[i];
if( o.count<N){
drawWorm( o );
o.count++;
}else{
len--;
vms.splice( i, 1 );
i--;
}
}
check();
bitmapData.colorTransform( bitmapData.rect, ct );
}
public function drawWorm( obj:WormObject ):void
{
var color:ColorHSV = new ColorHSV(t, 0.6, 1, 0.1);
t += 0.1;
if( Math.random()>0.9 ){
obj.tmt.rotate( -obj.r*2 );
obj.r *= -1;
}
obj.vmt.prepend( obj.tmt );
var cc1x:Number = -obj.w*obj.vmt.c + obj.vmt.tx;
var cc1y:Number = -obj.w*obj.vmt.d + obj.vmt.ty;
var pp1x:Number = (obj.c1x+cc1x)/2;
var pp1y:Number = (obj.c1y+cc1y)/2;
var cc2x:Number = obj.w*obj.vmt.c + obj.vmt.tx;
var cc2y:Number = obj.w*obj.vmt.d + obj.vmt.ty;
var pp2x:Number = (obj.c2x+cc2x)/2;
var pp2y:Number = (obj.c2y+cc2y)/2;
beginFill( uint(color), .7 );
moveTo( obj.p1x, obj.p1y );
curveTo( obj.c1x, obj.c1y, pp1x, pp1y );
lineTo( pp2x, pp2y );
curveTo( obj.c2x, obj.c2y, obj.p2x, obj.p2y );
closePath();
endFill();
obj.c1x = cc1x;
obj.c1y = cc1y;
obj.p1x = pp1x;
obj.p1y = pp1y;
obj.c2x = cc2x;
obj.c2y = cc2y;
obj.p2x = pp2x;
obj.p2y = pp2y;
}
}
//}
import frocessing.geom.FMatrix2D;
internal class WormObject{
public var c1x:Number;
public var c1y:Number;
public var c2x:Number;
public var c2y:Number;
public var p1x:Number;
public var p1y:Number;
public var p2x:Number;
public var p2y:Number;
public var w:Number;
public var r:Number;
public var count:int;
public var vmt:FMatrix2D;
public var tmt:FMatrix2D;
}
// ------------ Class Tracker ----------------------------------//
//package {
import flash.display.BlendMode;
import flash.filters.BlurFilter;
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.Video;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;
import org.libspark.betweenas3.*;
internal class Tracker extends Sprite {
private var _w:Number;
private var _h:Number;
private var _trackX:Number = 0;
private var _trackY:Number = 0;
// -- Track Position OutPut --//
public var trackPoint:Point = new Point();
public var _previous:BitmapData;
public var _current:BitmapData;
private var _px:Number;
private var _py:Number;
private var _blur:BlurFilter = new BlurFilter(64,64);
private var _vid:Video;
private var _mirror:Matrix;
private var _point:Point = new Point();
private var _area:Rectangle;
private var _isMotion:Boolean = false;
public function Tracker(w:Number, h:Number, vid:Video) {
_w = w;
_h = h;
_vid = vid;
_mirror = new Matrix();
_mirror.scale( -1, 1);
_mirror.translate(_vid.width, 0);
_current = new BitmapData(_vid.width,_vid.height,false,0x000000);
_previous = _current.clone();
//
var timer:Timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, trackerUpdate);
timer.start();
}
private function trackerUpdate(e:TimerEvent):void{
track();
_trackX = _px * (_w / _vid.width);
_trackY = _py * (_h / _vid.height);
//
BetweenAS3.tween(trackPoint, { x:_trackX, y:_trackY }, null, .1).play();
}
private function track():void {
_current.draw(_vid, _mirror);
_current.draw(_previous, null, null, BlendMode.DIFFERENCE);
_current.applyFilter(_current, _current.rect, _point, _blur);
_current.threshold(_current, _current.rect, _point, ">", 0xFF333333, 0xFFFFFFFF);
_previous.draw(_vid, _mirror);
_area = _current.getColorBoundsRect(0xFFFFFFFF,0xFFFFFFFF,true);
_isMotion = ( _area.width > ( _vid.width / 100) * 10 || _area.height > (_vid.height / 100) * 10 );
if (_isMotion) {
_px = _area.x;
_py = _area.y;
}
}
}
//}
// ------------ Class Grid ----------------------------------//
import flash.display.Bitmap;
import flash.display.BitmapData;
internal class Grid extends Bitmap
{
public function Grid()
{
var bmd:BitmapData = new BitmapData(465, 465, true, 0);
for(var i:int=0; i<720; i++){
for(var j:int=0; j<1280; j++){
if(i%2 == 0 && j%2 == 0){
bmd.setPixel32(j, i, 0xFF000000);
}
}
}
super(bmd);
}
}