芸大 – メディアアート・プログラミング I 2017
第6回 Processing実習 2 : Visual Harmony – アルゴリズムによるアニメーション表現
今回は、より複雑なアニメーションに挑戦します。たくさんの図形を、一定の手続き(= アルゴリズム)にそって動かしてみます。動きのアルゴリズムはいろいろありますが、今回はその一例として、三角関数(sin, cos , tan)を使用した動きをとりあげます。三角関数の定義は、直角三角形の角度とそれを取り囲む辺の比率で定義されます。しかし、同時に円運動を座標に変換する仕組みとしても活用可能です。この仕組みを応用してアニメーションするとどうなるか、三角関数を用いたアニメーションで美しいパターン「ビジュアルハーモニー」を生成する手法を紹介します。
スライド資料
サンプルプログラム
sin関数による動き
PVector location; PVector velocity; void setup() { size(800, 800); frameRate(60); background(0); noStroke(); velocity = new PVector(4, 0); location = new PVector(0, 0); } void draw() { background(0); translate(width / 2.0, height / 2.0); location.add(velocity); location.y = sin(frameCount/20.0)*height/4.0; fill(0, 127, 255); ellipse(location.x, location.y, 10, 10); if (location.x > width/2) { location.x = -width/2; } }
円運動
PVector location; float angle, velocity, radius; void setup() { size(800, 800); frameRate(60); background(0); noStroke(); angle = 0.0; //現在の角度 velocity = 2.0; //角速度 radius = height / 4.0; //半径 location = new PVector(0, 0); } void draw() { background(0); translate(width / 2.0, height / 2.0); location.x = cos(radians(angle)) * radius; location.y = sin(radians(angle)) * radius; fill(0, 127, 255); ellipse(location.x, location.y, 10, 10); angle += velocity; //角速度から角度を更新 }
配列をつかった沢山の円運動
int NUM = 32; PVector[] location = new PVector[NUM]; float angle, velocity, radius; void setup() { size(800, 800); frameRate(60); background(0); noStroke(); angle = 0.0; velocity = 2.0; radius = height / 4.0; for (int i = 0; i < NUM; i++) { location[i] = new PVector(0, 0); } } void draw() { background(0); translate(width / 2.0, height / 2.0); for (int i = 0; i < NUM; i++) { location[i].x = cos(radians(angle) / NUM * (i+1)) * radius; location[i].y = sin(radians(angle) / NUM * (i+1)) * radius; fill(0, 127, 255); ellipse(location[i].x, location[i].y, 10, 10); } angle += velocity; }
ビジュアルハーモニー 01 - 基本
int NUM = 32; PVector[] location = new PVector[NUM]; float angle, velocity, radius; void setup() { size(800, 800); frameRate(60); background(0); noFill(); angle = 0.0; velocity = 2.0; radius = height / 4.0; for (int i = 0; i < NUM; i++) { location[i] = new PVector(0, 0); } } void draw() { background(0); translate(width / 2.0, height / 2.0); for (int i = 0; i < NUM; i++) { location[i].x = cos(radians(angle) / NUM * (i+1)) * radius; location[i].y = sin(radians(angle) / NUM * (i+1)) * radius; stroke(0, 127, 255); ellipse(location[i].x, location[i].y, 4 * i, 4 * i); } angle += velocity; }
ビジュアルハーモニー 02 - 円の数を増やしてみる
int NUM = 256; PVector[] location = new PVector[NUM]; float angle, velocity, radius; void setup() { size(800, 800, P3D); frameRate(60); background(0); noFill(); angle = 0.0; velocity = 2.0; radius = height / 4.0; for (int i = 0; i < NUM; i++) { location[i] = new PVector(0, 0); } } void draw() { background(0); translate(width / 2.0, height / 2.0); for (int i = 0; i < NUM; i++) { location[i].x = cos(radians(angle) / NUM * (i+1)) * radius; location[i].y = sin(radians(angle) / NUM * (i+1)) * radius; stroke(0, 127, 255); float diameter = i * (height / 2) / float(NUM); ellipse(location[i].x, location[i].y, diameter, diameter); } angle += velocity; }
ビジュアルハーモニー 03 - 周波数の比率を変化させる
int NUM = 256; PVector[] location = new PVector[NUM]; float angle, velocity, radius; void setup() { size(800, 800, P3D); frameRate(60); background(0); noFill(); angle = 0.0; velocity = 2.0; radius = height / 4.0; for (int i = 0; i < NUM; i++) { location[i] = new PVector(0, 0); } } void draw() { background(0); translate(width / 2.0, height / 2.0); for (int i = 0; i < NUM; i++) { location[i].x = cos(radians(angle) / NUM * (i+1) * 1.2) * radius; location[i].y = sin(radians(angle) / NUM * (i+1) * 1.5) * radius; stroke(0, 127, 255); float diameter = i * (height / 2) / float(NUM); ellipse(location[i].x, location[i].y, diameter, diameter); } angle += velocity; }