速度マップによるブラー
http://tpot.jpn.ph/t-pot/program/26_blur/blur.html
int numblur = 10; // ブラーの数 int sizbox = 40; // 箱のサイズ void setup() { size(200, 200); framerate(10); ax = floor(random(10))+1; ay = floor(random(10))+1; for (int i = 0; i< 4; i++) { for (int j = 0; j< numblur; j++) { oldPos[j][i] = new Vec(x, y); } resPos[i] = new Vec(); } } class Vec{ public int x, y; Vec(){x = y = 0;} Vec(int ax, int ay){ x = ax; y = ay;} }; Vec[] v = {new Vec(-1, -1), new Vec(1, -1), new Vec(1, 1), new Vec(-1, 1)}; // 頂点の法線 Vec[] p = {new Vec(0, 0), new Vec(sizbox, 0), new Vec(sizbox, sizbox), new Vec(0, sizbox)}; // 頂点座標 int x, y; // チューブの位置 int ax, ay; // チューブの速度 Vec[][] oldPos = new Vec[numblur][4]; // 古い座標 Vec[] resPos = new Vec[4]; // 速度マップされた座標 int idxOldPos; // 内積 int Vec2dDotProduct(Vec iVec1, Vec iVec2 ){ return ((iVec1.x * iVec2.x) + (iVec1.y * iVec2.y)); } void draw() { background(0,0,255); // 新しい座標を求める for (int i = 0; i< 4; i++) { oldPos[idxOldPos][i].x = p[i].x + x; oldPos[idxOldPos][i].y = p[i].y + y; } for (int j = 0; j< numblur-1; j++) { // 新しい点のインデクス int k = idxOldPos - j; if (k < 0) k += numblur; // ひとつ古い点のインデクス int m = k - 1; if (m < 0) m += numblur; // 速度ベクトル Vec spd = new Vec(); spd.x = oldPos[k][0].x - oldPos[m][0].x; spd.y = oldPos[k][0].y - oldPos[m][0].y; // 速度マップを作成 for (int i = 0; i< 4; i++) { // 速度と頂点の法線のない積を求める if (Vec2dDotProduct(spd, v[i]) <= 0) { // 向きが異なるので古い点を使う resPos[i] = oldPos[m][i]; } else { // 向きが同じなので新しい点を使う resPos[i] = oldPos[k][i]; } } // ブラーイメージを描く stroke(255 * (numblur-1-j)/ (numblur-1), 0, 0); strokeWeight(1); for (int i = 0; i< 3; i++) { line(resPos[i].x, resPos[i].y, resPos[i+1].x, resPos[i+1].y); } line(resPos[3].x, resPos[3].y, resPos[0].x, resPos[0].y); } // 元画像を画面に転送 noStroke(); fill(0, 255, 0, 100); rect( x, y, sizbox, sizbox); // 毎フレームの移動 x += ax; if (x > width-sizbox) ax = -floor(random(10))+1; if (x < 0) ax = floor(random(10))+1; y += ay; if (y > height-sizbox) ay = -floor(random(10))+1; if (y < 0) ay = floor(random(10))+1; idxOldPos = (1 + idxOldPos) % numblur; }
- 結果