yoppa.org


芸大 – メディアアート・プログラミング 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;
}