2008年5月 9日 (金)

JavascriptでProcessing

Processingをjsに移行したらしい。
http://ejohn.org/blog/processingjs/

IEじゃ動かなくて基本FireFoxなのと、動作もやっぱり重いのでまだ実用的ではないな。

でも、とりあえずこれ作ったやつすごい。

| | コメント (0) | トラックバック (0)

2007年8月10日 (金)

Processing 「ライブの音と同期させる」

Processingで作ったやつを音に合わせて動かしたいなーということでやってみました。

まずProcessingは標準で音は扱えないのでどこかのすごい人が作ったライブラリを使用。
今回はProcessingのサイトにも紹介されている「Minim」を使ってます。
サンプルもついてくるので、その中の「getLineIn」を参考に(てかコピペ)ラインに入力したサウンドを取得します。
安物のオーディオインターフェイスもどきにiPodから音楽を入力させて、それをUSBでPCにつないでます。

できたものをプロジェクタで映してみました。
(音汚いけど気にしない・・・)

色は今はランダムなので、音域で変わるようにしたいなあ。
これをMotionDiveとかの映像にビデオミキサーで重ねて使います。
ちなみに今年の忘年会はこんな感じでいこうと思ってます。(本気)
DJをやるT島が流す音に合わせたり、社長とかのスピーチに合わせて動くのだ。
これにGainerも絡める予定。

ソースはこちら。

import processing.opengl.*;
import javax.media.opengl.*;
import ddf.minim.*;

PGraphicsOpenGL pgl;
GL gl;

PImage light01;

ArrayList aLight01;
int[] cl,dcl;
AudioInput in;

void setup() {
  size(800,600,OPENGL);
  background(0);
  pgl = (PGraphicsOpenGL) g;
  gl = pgl.gl;
  light01 = loadImage("light.jpg");
  aLight01 = new ArrayList();
  
  for (int i=0;i<=10;i++) {
    aLight01.add(new Light01()); 
  }

  cl = new int[3];
  cl[0] = 0;
  cl[1] = 0;
  cl[2] = 0;
  dcl = new int[3];
  dcl[0] = ceil(random(1,4));
  dcl[1] = ceil(random(1,4));
  dcl[2] = ceil(random(1,4));
  
  //
  Minim.start(this);
  in = Minim.getLineIn(Minim.STEREO, 512);
}

void draw() {
  translate(width/2,height/2);
  fill(0, 15);
  rect(-width/2, -height/2, width, height);
  
  pgl.beginGL();
  gl.glDisable(GL.GL_DEPTH_TEST);
  gl.glEnable(GL.GL_BLEND);
  gl.glBlendFunc(GL.GL_ONE,GL.GL_ONE);
  pgl.endGL();
  
  noTint();
  //Sound
  float left = 0;
  float right = 0;
  for(int i = 0; i < in.left.size()-1; i++) {
    left += abs(in.left.get(i));
    right += abs(in.right.get(i));
  }
  //
  //Particle
  pushMatrix(); 
  translate(0,0,100);
  for (int i=0;i<aLight01.size();i++) {
    Light01 lt = (Light01) aLight01.get(i);
    lt.update(left+right);
    tint(cl[0], cl[1], cl[2]);
    image(light01,lt.getX(),lt.getY(),lt.getR(),lt.getR());
  }
  popMatrix();

  for (int i=0;i<3;i++) {
    cl[i]+=dcl[i];
    if (dcl[i]>0&&cl[i]>255) {
      cl[i] = 255;
      dcl[i] = -ceil(random(1,4));
    } else if (dcl[i]<0&&cl[i]<0) {
      cl[i] = 0;
      dcl[i] = ceil(random(1,4));
    }
  }
}


class Light01 {
  int xx,yy,zz;
  float ssx,ssy;
  float dssx,dssy;
  float rr,dd,minD,maxD,endD;
  Light01() {
    xx = 0;
    yy = 0;
    zz = 0;
    ssx = random(-PI*2,PI*2);
    ssy = random(-PI*2,PI*2);
    dssx = PI/72;
    dssy = PI/72;
    minD = random(10,20);
    maxD = random(100,200);
    endD = maxD;
    dd = 0;
    rr = 50;
  }
  void update(float d) {
    xx = int(dd*cos(ssy)*cos(ssx));
    yy = int(dd*sin(ssy));
    zz = int(dd*cos(ssy)*sin(ssx));
    ssx += dssx;
    ssy += dssy;
    endD = d*0.6;
    dd += (endD-dd)/2;
  }
  int getX() {
    return xx-ceil(rr/2); 
  }
  int getY() {
    return yy-ceil(rr/2); 
  }
  int getZ() {
    return zz; 
  }
  float getR() {
    return rr; 
  }
}

| | コメント (0) | トラックバック (0)

2007年8月 9日 (木)

Processing 「ブレンドする方法」

こちらのブログを参考にやってみました。
http://www.flight404.com/blog/?p=71

ProcessingでopenGLを使ってブレンドする方法です。
「オーバーレイ」とか「乗算」とかあのへんのことができるっぽいです。

このブログに書いてあるとおり簡単にできます。
ソース中の、
「gl.glBlendFunc(GL.GL_ONE,GL.GL_ONE);」
でブレンドモードを指定してるようです。
この場合は「加算(ADD)」ですかね。
ここの「GL_ONE」を他のに変えるとブレンドの仕方が変わります。
例えば↓ここに載ってるものに変えてみてください。
http://pyopengl.sourceforge.net/documentation/manual/glBlendFunc.3G.html

ブレンドできるだけでなんかいい感じになってる気がしてしまいます。

以下、簡単に作ってみたものです。
使ってる画像は コチラ 。(Photoshopの逆光です)

import processing.opengl.*;
import javax.media.opengl.*;

PGraphicsOpenGL pgl;
GL gl;

PImage light01;

int oldX,oldY,oldZ;
float rot,ss;
ArrayList aLight01;
int[] cl,dcl;

void setup() {
  size(640,480,OPENGL);
  background(0);
  pgl = (PGraphicsOpenGL) g;
  gl = pgl.gl;
  light01 = loadImage("light.jpg");
  oldX = 0;
  oldY = 0;
  oldZ = 0;
  rot = 0;
  ss = 0;
  aLight01 = new ArrayList();
  for (int i=0;i<=5;i++) {
    aLight01.add(new Light01()); 
  }
  cl = new int[3];
  cl[0] = 0;
  cl[1] = 0;
  cl[2] = 0;
  dcl = new int[3];
  dcl[0] = ceil(random(1,4));
  dcl[1] = ceil(random(1,4));
  dcl[2] = ceil(random(1,4));
}

void draw() {
  translate(width/2,height/2);
  fill(0, 8);
  rect(-width/2, -height/2, width, height);
  
  pgl.beginGL();
  gl.glDisable(GL.GL_DEPTH_TEST);
  gl.glEnable(GL.GL_BLEND);
  gl.glBlendFunc(GL.GL_ONE,GL.GL_ONE);
  pgl.endGL();

  for (int i=0;i<aLight01.size();i++) {
    Light01 lt = (Light01) aLight01.get(i);
    lt.update();
    translate(0,0,lt.getZ());
    tint(cl[0], cl[1], cl[2]);
    image(light01,lt.getX(),lt.getY(),lt.getW(),lt.getW());
    translate(0,0,-lt.getZ());
  }
  for (int i=0;i<3;i++) {
    cl[i]+=dcl[i];
    if (dcl[i]>0&&cl[i]>255) {
      cl[i] = 255;
      dcl[i] = -ceil(random(1,4));
    } else if (dcl[i]<0&&cl[i]<0) {
      cl[i] = 0;
      dcl[i] = ceil(random(1,4));
    }
  }
}


class Light01 {
  int xx,yy,zz,ww,rx,ry,rz;
  float sx,dsx,sy,dsy,sz,dsz;
  Light01() {
    xx = 0;
    yy = 0;
    zz = 0;
    ww = 50;
    rx = ceil(random(150,300));
    ry = ceil(random(150,300));
    rz = ceil(random(150,400));
    sx = 0;
    dsx = PI/random(18,72);
    sy = 0;
    dsy = PI/random(18,72);
    sz = 0;
    dsz = PI/random(18,72);
  }
  void update() {
    xx = ceil(sin(sx)*rx);
    yy = ceil(sin(sy)*ry);
    zz = ceil(sin(sz)*rz);
    sx += dsx;
    sy += dsy;
    sz += dsz;
  }
  int getX() {
   return xx-ww; 
  }
  int getY() {
   return yy-ww; 
  }
  int getZ() {
   return zz; 
  }
  int getW() {
   return ww*2; 
  }
}


なぜかアプレットで書き出すとうまくいきませんでした。。
あと、うちのノートPCだとグラフィックカードがしょぼいせいか、画面がちらついて全然ダメ。。

| | コメント (2) | トラックバック (0)

2007年7月25日 (水)

FLASH+Processing 「ProcessingからFLASHへ その2」

前回Processingで作成したものをFLASH(AS3)に移行します。
といってもProcessingとAS3の書き方の違いがあるのでそれを直すだけです。
考え方、処理の流れはそのままです。

AS3では同じpackage内に複数のclassを書けた気がするんだけど、なぜかうまくいかなかったので分けてます。
FLASH CS3でAS3設定にしてドキュメントクラスに「Particle」を入れてください。

Particleコンストラクタ内がProcessingのほうでの「setup()」になってます。
ここの処理は単にステージの設定をするのと、BitmapDataという描画用のオブジェクトを作成するというのが違ってたりしますが
イメージ的には似たようなもんですね。
あとは「draw()」が勝手に動いてくれるか、イベントリスナーを設定しないといけないか、の違い。
これ以降の処理はただ書き方が違うだけで内容はほぼ同じかと。

Particle.as

package {
    import flash.display.MovieClip;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.*;
    public class Particle extends MovieClip {
        var bd:BitmapData;
        var bm:Bitmap;
        var aPoints:Array;
        var nStageWidth:Number = 640;
        var nStageHeight:Number = 480;
        function Particle() {
            bd = new BitmapData(nStageWidth,nStageHeight,false,0xFFFFFFFF);
            bm = new Bitmap(bd);
            addChild(bm);
            aPoints = new Array();
            addEventListener(Event.ENTER_FRAME,draw);
        }
        private function draw(e:Event):void {
            aPoints.push(new PointObject());
            //
            for (var i:Number=0; i<aPoints.length; i++) {
                var po:PointObject = aPoints[i];
                po.update();
                var xx:Number = po.getX();
                var yy:Number = po.getY();
                if (xx<0||xx>=nStageWidth||yy<0||yy>=nStageHeight) {
                    aPoints.splice(i,1);
                } else {
                    bd.setPixel(xx,yy,0x000000);
                }
            }
        }
    }
}

PointObject.as

package {
    public class PointObject {
        var xx:Number;
        var yy:Number;
        var ss:Number;
        var dss:Number;
        var vx:Number;
        var vy:Number;
        var rr:Number;
        function PointObject() {
            xx = 640/2;
            yy = 480/2;
            vx = Math.round(Math.random()*4)-2;
            vy = Math.round(Math.random()*4)-2;
            ss = 0;
            dss = Math.PI/(Math.random()*72-36)/4;
            rr = Math.random()*60+20;
        }
        public function update():void {
            xx+=vx;
            yy+=vy;
            ss+=dss;
            rr+=(0-rr)/50;
        }
        public function getX():Number {
            return int(xx + Math.cos(ss) * rr);
        }
        public function getY():Number {
            return int(yy + Math.sin(ss) * rr);
        }
    }
}

できたのがこちら。

こんな感じでProcessingで作ったものをFLASH(AS)に移行する時は型宣言とかちょっとした変更で簡単にできます。
もちろんものによりますけどね。。

いらなくなったPointObjectを削除したほうがいいと思うんだけど、やり方がよく分からない。。どうやったら消えるんだろ?

| | コメント (0) | トラックバック (0)

2007年7月24日 (火)

FLASH+Processing 「ProcessingからFLASHへ その1」

Processingで作った簡単なサンプルです。
これをFLASH(AS3)に移行していきます。

サンプル:

まずはProcessingのソースの説明を。
「->」の後に書いてるのがAS3で何に置き換えるか、です。

ArrayList aPoints;  //配列の宣言

void setup() {  //初期設定
  frameRate(30);  //フレームレート
  size(640,480,P3D);  //ステージサイズの設定 -> BitmapDataのサイズ
  background(255);  //ステージの背景色 -> BitmapDataの背景色
  aPoints = new ArrayList();  //PointObject格納用配列
}

void draw() {  //この関数をループします。 -> ENTER_FRAME
  aPoints.add(new PointObject());  //新しいPointObjectを作成して配列に格納
  //
  loadPixels();  //ピクセルを処理する前のおまじない -> ASでは無し
  for (int i=0;i<aPoints.size();i++) {
    PointObject po = (PointObject) aPoints.get(i);
    po.update();
    int xx = po.getX();
    int yy = po.getY();
    if (xx<0||xx>=width||yy<0||yy>=height) {  //PointObjectの位置が端まで来ていたら
      aPoints.remove(i);  //PointObjectを削除
    } else {
      pixels[xx+yy*width] = color(0,0,0);
    }
  }
  updatePixels();  //ピクセルへの処理を反映させるためのおまじない -> ASでは無し



}



class PointObject {  //PointObjectクラス
  int xx;
  int yy;
  float ss;
  float dss;
  float vx;
  float vy;
  float rr;
  PointObject() {  //コンストラクタ 初期設定
    xx = width/2;
    yy = height/2;
    vx = random(-2,3);
    vy = random(-2,3);
    ss = 0;
    dss = PI/random(-36,36)/4;
    rr = random(20,80);
  }
  void update() {  //座標情報の更新
    xx+=vx;
    yy+=vy;
    ss+=dss;
    rr+=(0-rr)/50;
  }
  int getX() {  //X座標を返す
    return int(xx+cos(ss)*rr);
  }
  int getY() {  //Y座標を返す
    return int(yy+sin(ss)*rr); 
  }
}

フレームレートはFLASHに合わせて30にしてますが、Processingではもっと速くても全然いけます。120とか。
FLASHでのASの書き方は次回。

ソースちょっとおかしくなってたので修正しました。(7.24 19時)

| | コメント (0) | トラックバック (0)

2007年7月23日 (月)

FLASH+Processing 「BitmapDataと似てる」

「FLASH+Processing」というタイトルにしてみたけど、FLASHとProcessingを連携させるわけではないです。
単にFLASHにつながる話題として。

Processingをちょっとやってみての感想だけど、「FLASHのBitmapDataを扱うときの感覚に似てる」と思いました。
この前のProcessingのイベントでも、最初にProcessingでがーっと作って、その後にFLASHでもC++でも他のに移行する感じで使うのがいいという話もありました。
Processingがほんと軽く実験したりするのがやりやすいので、まずはProcessingで試して、いいのができたらFLASHに移行するという使い方はいいと思います。その時には「BitmapData」でやるのが移行しやすいです。

Processingの構造は簡単に言うと「setup」という関数で初期設定して、「draw」関数をひたすら繰り返します。
指定したサイズのステージに点や線、四角、丸などのオブジェクトを描画していきます。
紙に絵を描くように、ステージに対して描いてしまうので、例えば●を描画した後それだけを消すことができません。●を左から右へ移動させていくと●●●●●・・・となってしまいます。(実際は重なりつつ)
こういう場合は毎フレームごとに背景色と同じ色の四角を描画して全てを消し、また描画し直す必要があります。
といってもそれが普通のことでサンプルもそういう処理になってるし、すごく簡単にできます。

FLASHでいうと「draw」は「ENTER_FRAME」だし、「指定したサイズのステージ」は「BitmapData」になります。
その「BitmapData」に対して点や線、四角、丸などのオブジェクトを描画していきます。
BitmapDataも例えば●を描画した後、それだけを消すことはできません。BitmapData上で●の位置を変更させていきたい場合も、毎フレームごとに背景色と同じ色を描画して全てを消し、また描画していきます。

言葉だと分かりにくいかも。。実際にやってみると分かると思います。
後でサンプルを載せてみようかと。

| | コメント (0) | トラックバック (0)