58
Media Art II 2011 第5回:openFrameworks アニメーションを極める 動きを生みだす様々なアルゴリズム 2011年10月4日 多摩美術大学 情報デザイン学科 情報芸術コース 田所 淳

openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

Media Art II 2011 第5回:openFrameworksアニメーションを極める動きを生みだす様々なアルゴリズム

2011年10月4日多摩美術大学 情報デザイン学科 情報芸術コース田所 淳

Page 2: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

今日の内容‣ 課題の簡単な講評‣ Particleを使用した表現

‣ 動きを生みだす様々なアルゴリズムを紹介‣ パーティクルによるドローイング‣ 重力、バウンド‣ 弾力、ばね、ばねの連結‣ ベクトル場 (Vector Field) - 流体、磁性体の表現‣ 群れの動き (Flocking)‣ 空間の充填

Page 3: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

動きを生みだす様々なアルゴリズム‣ 乱数や単純な運動だけでなく、より複雑で有機的な動きを生みだすための手法を紹介

‣ 手持ちの表現の持駒を増やす‣ 今後の作品制作の表現の幅を拡げる基礎体力に

Page 4: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

サンプルファイル‣ 紹介した全てのプログラムのソースは下記のリンクからダウンロード可能

‣ openFramewroks v.007 で動作確認済み

‣ http://goo.gl/zyfQR (Google Docsにリンク)

Page 5: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

パーティクルによるドローイング

Page 6: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

パーティクルによるドローイング‣ マウスを動かす勢いと方向を、パーティクルに付加‣ マウスドラッグに対応させる → パーティクルによるドローイングのような効果に

Page 7: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

パーティクルによるドローイング‣ コードのポイント‣ マウスの勢いを、パーティクルの座標に変換している部分‣ testApp.cpp

void testApp::mouseMoved(int x, int y ){! prevMouseX = x;! prevMouseY = y;}

void testApp::mouseDragged(int x, int y, int button){! //1フレーム前の座標から、現在のマウス座標との差分を算出! float dx = x - prevMouseX;! float dy = y - prevMouseY;!! //新規にパーティクルを作成、計算したベクトルを付与! particle myParticle;! myParticle.setInitialCondition(x,y, dx*0.5,dy*0.5);! //配列に追加! particles.push_back(myParticle);!! //現在のマウス座標を記録! prevMouseX = x;! prevMouseY = y;!}

Page 8: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

パーティクルによるドローイング‣ 実行結果:マウスの動きでドローイング

Page 9: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

パーティクルによるドローイング‣ ofCurveVertexを、ofNoFill() から ofFill()にしてみると…

Page 10: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

重力とバウンド

Page 11: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

重力とバウンド‣ 画面の下方向に重力を (これは先週に解説済み)‣ さらに、画面の端に架空の「壁」をつくりたい‣ 壁にパーティクルが衝突すると、バウンドして跳ね返る

重力

Page 12: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

‣ バウンドとはどういうことか?‣ 壁に当たった瞬間に、力の方向が反転する‣ + と - が逆転。力の方向に、-1 を掛ける

重力とバウンド

F -F

Page 13: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

重力とバウンド‣ コードのポイント:バウンドする動きをParticleクラスに追加‣ Particle.cpp - bounceOffWalls() 関数void particle::bounceOffWalls(){! //壁の範囲を設定! float minx = 0;! float miny = 0;! float maxx = ofGetWidth();! float maxy = ofGetHeight();! //左右の壁でのバウンド! if (pos.x > maxx){! ! pos.x = maxx;! ! vel.x *= -1;! } else if (pos.x < minx){! ! pos.x = minx;! ! vel.x *= -1;! }! //上下の壁でのバウンド! if (pos.y > maxy){! ! pos.y = maxy;! ! vel.y *= -1;! } else if (pos.y < miny){! ! pos.y = miny;! ! vel.y *= -1;! }}

Page 14: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

重力とバウンド‣ 実行結果:弾むパーティクル!!

Page 15: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結

Page 16: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 「ばね」を数学的に定義する‣ フックの法則 - バネの伸びが x のとき、それによって生じる力を F とすると

‣ F = -kx ‣ ( k:ばね定数)

振動を繰り返す(単振動)

0

x

F = -kxma = -kx

x = -sinmk t

x = Csin(ωt + θ)

Page 17: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ フックの定理は以下のように書き直すことができる

‣ springForce = -stiffness * stretch‣ バネの力 = -バネの硬さ * バネの伸び

‣ さらに「バネの伸び」の部分を座標として解釈する

‣ springForce = -stiffness * (position - restPosition)‣ バネの力 = -バネの硬さ * (現在位置 - ばねの静止位置)

Page 18: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 式を整理

‣ springForce = stiffness * (restPositon - position)バネの力 = バネの硬さ * (静止位置 - 現在位置)

‣ バネの力から、ばねの移動速度が導きだせる

‣ velocity = dumping * (velocity + springFroce)速度 = 摩擦 * (速度 + バネの力)

Page 19: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ まずは、単体のバネを実現してみる‣ ばねの性質をクラスとしてまとめる → springクラス‣ 「ばね」は、2つのparticleの間に張られる‣ Particle A と Particle B

Particle A

Particle B

Spring

Page 20: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ ばねの運動は、springクラスのupdateで計算‣ spring.cpp - update()関数‣ フックの法則から、2つのParticleにかかる力をそれぞれ計算void spring::update(){! if ((particleA == NULL) || (particleB == NULL)){! ! return;! }!! ofVec2f pta = particleA->pos;! ofVec2f ptb = particleB->pos;!! float theirDistance = (pta - ptb).length();! float springForce = (springiness * (distance - theirDistance));! ofVec2f frcToAdd = (pta-ptb).normalized() * springForce;!! particleA->addForce(frcToAdd.x, frcToAdd.y);! particleB->addForce(-frcToAdd.x, -frcToAdd.y);}

Page 21: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ testAppからは、2つのparticleと、それに挟まれる1つのspringを指定する

‣ testApp.cpp - setup()関数void testApp::setup(){!!! ofBackground(0,0,0);!! ofSetVerticalSync(true);! ofSetFrameRate(60);

! //Particle A 初期設定! particle_a.setInitialCondition(400, 400, 0, 0);!! //Particle B 初期設定! particle_b.setInitialCondition(500, 500, 0, 0);

! //ばね(spring)を、パーティクル間に張る! mySpring.distance = 100; //ばねの長さ! mySpring.springiness = 0.1f; //ばねの硬さ! mySpring.particleA = &particle_a;! mySpring.particleB = &particle_b;}

Page 22: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ testAppでは、2つのparticleとspringの更新をする‣ testApp.cpp - update()関数

void testApp::update(){!! //力をリセット! particle_a.resetForce();! particle_b.resetForce();!! //バネを更新! mySpring.update();!! //パーティクルの状態を更新 (壁でバウンド)! particle_a.bounceOffWalls();! particle_a.update();!! particle_b.bounceOffWalls();! particle_b.update();}

Page 23: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ あとは、描画するのみ!!‣ testApp.cpp - draw()関数

void testApp::draw(){! ofSetColor(255, 255, 255);!! //ばねを描画! mySpring.draw();!! //particleを描画! particle_a.draw();! particle_b.draw();}

Page 24: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 実行結果:空間を漂うバネが描画される‣ マウスドラッグで操作可能

Page 25: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 次に、ばねを数珠繋ぎにしてみる‣ spring と particle をそれぞれ動的配列(vector)として作成‣ 全てのばねの伸縮と、それに伴なう全てのパーティクルにかかる力を計算する

Page 26: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 数珠繋ぎのばねを生成している箇所‣ testApp - setup() 関数内void testApp::setup(){!! ofBackground(0,0,0);! ofSetVerticalSync(true);! ofSetFrameRate(60);! ofSetBackgroundAuto(false);! pimg.loadImage("particle32.png");

! //particleの配列を生成! for (int i = 0; i < 20; i++){! ! particle myParticle;! ! myParticle.setInitialCondition(ofRandom(500,550),ofRandom(500,550),0,0);! ! particles.push_back(myParticle);! }!! //全ての配列を順番にspringで接続していく! for (int i = 0; i < (particles.size()-1); i++){! ! spring mySpring;! ! mySpring.distance = 25;! ! mySpring.springiness = 0.2f;! ! mySpring.particleA = & (particles[i]);! ! mySpring.particleB = & (particles[(i+1)%particles.size()]);! ! springs.push_back(mySpring);! }}

Page 27: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 数珠繋ぎになった、ばねとparticleの更新‣ testApp - update() 関数内void testApp::update(){! //全てのparticleの力をリセット! for (int i = 0; i < particles.size(); i++){! ! particles[i].resetForce();! }

! //全てのばねの伸縮を計算! for (int i = 0; i < springs.size(); i++){! ! springs[i].update();! }!! //全てのparticleの状態を更新! for (int i = 0; i < particles.size(); i++){! ! particles[i].addDampingForce();! ! particles[i].bounceOffWalls();! ! particles[i].update();! }}

Page 28: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 全てのばねとpatricleを描画‣ testApp - draw() 関数内void testApp::draw(){

! //全てのばねを描画! ofSetColor(255, 255, 255, 127);! for (int i = 0; i < springs.size(); i++){! ! springs[i].draw();! }!! //全てのparticleを描画! ofSetColor(255, 255, 255);! for (int i = 0; i < particles.size(); i++){! ! particles[i].draw();! }!}

Page 29: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 実行結果:数珠繋ぎになったばね

Page 30: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 応用1:ばねを、円弧に数珠繋ぎにして力を加える

Page 31: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

弾力、ばね、ばねの連結‣ 応用2:パーティクル同士をすべて接続して「筋肉」のように

Page 32: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場 (Vector Field)- 流体、磁性体の表現

Page 33: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場 (Vector Field) とは‣ ベクトル場 (Vector Field)‣ 空間の広がりの中でベクトル的な量の分布‣ 例えば…‣ 動いている流体の早さと向き‣ 磁力や重力などの力の強さと向きなど

‣ ベクトル場をシミュレーションできれば、流体は磁性体などの動きを再現することが可能になるはず

Page 34: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

‣ ベクトル場 (Vector Field) のイメージ‣ 向きと方向をもった力が、グリッド上に整列している

ベクトル場 (Vector Field) とは

Page 35: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

vectorFirldクラスの設計‣ まずは、ベクトル場を生成してみる

‣ vectorFieldクラス‣ ベクトル場を生成し、座標を指定すると、その位置に働く力の向きと方向を算出する

‣ 座標を指定して新たにベクトル場に力を加えることも可能‣ 外側に向う力 (噴出?)‣ 内側に向う力 (吸引?)‣ 渦巻のように回転する力 (時計回り、反時計回り)

‣ vectorFieldクラスのプロパティとメソッドを整理する‣ vectorFieldの実装の詳細は省略…

Page 36: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

vectorFirldクラスの設計‣ vectorFirldクラス:プロパティ

型 変数名 内容

int fieldWidth ベクトルの数、横

int fieldHeight ベクトルの数、縦

int fieldSize ベクトルの総数

int externalWidth ベクトル場の幅

int externalHeight ベクトル場の高さ

vector field ベクトルの配列

Page 37: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

vectorFirldクラスの設計‣ vectorFirldクラス:メソッド

メソッド名と引数・戻り値 説明

vectorField(); コンストラクタ

virtual ~vectorField(); デストラクタ

void setupField(int innerW, int innerH, int outerW, int outerH); ベクトル場の初期化

void clear(); ベクトル場を消去

void fadeField(float fadeAmount); 徐々にベクトル場の力が減衰するようにする

void randomizeField(float scale); 全てのベクトル場の力をランダムに生成

void draw(); ベクトル場の様子を描画

ofVec2f getForceFromPos(float xpos, float ypos); 指定した座標にかかる力のベクトルを算出

Page 38: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

vectorFirldクラスの設計‣ vectorFirldクラス:メソッド (つづき)

メソッド名と引数・戻り値 説明

void addOutwardCircle(float x, float y, float radius, float strength); 外向きの力を加える (噴出)

void addInwardCircle(float x, float y, float radius, float strength); 内向きの力を加える (吸引)

void addClockwiseCircle(float x, float y, float radius, float strength); 時計回りの渦巻

void addCounterClockwiseCircle(float x, float y, float radius, float strength); 反時計回りの渦巻

void addVectorCircle(float x, float y, float vx, float vy, float radius, float strength);

円形の力を加える

Page 39: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場を生成‣ testAppクラスからvectorFieldクラスをインスタンス化して、画面にベクトル場を生成し描画する

‣ キーをタイプすると、様々な方法でベクトル場に力を付加できるようにする‣ 1:外向きの力‣ 2:内向きの力‣ 3:時計回りの渦巻‣ 4:反時計回りの渦巻

‣ ベクトル場の力は、徐々に減衰していく

Page 40: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場を生成‣ ベクトル場の初期化‣ testApp.cpp - setup() 関数oid testApp::setup(){!!! ofSetVerticalSync(true);! ofSetFrameRate(60);! ofBackground(0, 0, 0);!! //ベクトル場の初期化 (画面いっぱいに、横102コ、縦76コのベクトル)! VF.setupField(102, 76, ofGetWidth(), ofGetHeight());

! //初期状態は、外向きの力! addMode = 1;}

Page 41: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場を生成‣ ベクトル場の描画‣ testApp.cpp - draw() 関数void testApp::draw(){

! //ベクトル場を描画! ofEnableBlendMode(OF_BLENDMODE_ADD);! ofSetColor(0,130,130, 200);! VF.draw();! ofDisableBlendMode();!}

Page 42: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場を生成‣ 完成!! : 1~ 4 のキーで加える力の向きを決定し、マウスをドラッグしてベクトル場に力を加えてみる

Page 43: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場にパーティクルを浮遊させる‣ 生成したベクトル場にパーティクルを配置してみる

‣ ベクトル場から、それぞれのパーティクルの座標にかかる力を算出して、空間の力を受けて浮遊するようにしてみる

‣ 座標上にあるパーティクルにかかる力は getForceFromPos() 関数で算出することが可能

Page 44: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場にパーティクルを浮遊させる‣ ベクトル場に配置するパーティクルの初期化‣ testApp.cpp - setup() 関数void testApp::setup(){!!! ofSetVerticalSync(true);! ofSetFrameRate(60);! ofBackground(0, 0, 0);!! //パーティクルを10000個生成! for (int i = 0; i < 10000; i++){! ! particle myParticle;! ! myParticle.setInitialCondition! ! (ofRandom(0,ofGetWidth()),ofRandom(0,ofGetHeight()),0,0);! ! particles.push_back(myParticle);! }!! //ベクトル場の初期化 (画面いっぱいに、横102コ、縦76コのベクトル)! VF.setupField(102, 76, ofGetWidth(), ofGetHeight());!! //初期状態は、内向きの力! addMode = 2;}

Page 45: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場にパーティクルを浮遊させる‣ ベクトル場からパーティクルにかかる力を算出する‣ testApp.cpp - update() 関数void testApp::update(){!! for (int i = 0; i < particles.size(); i++){! !! ! //particleの力をリセット! ! particles[i].resetForce();! !! ! //ベクトル場から、それぞれのparticleにかかる力を算出! ! ofVec2f frc;! ! frc = VF.getForceFromPos(particles[i].pos.x, particles[i].pos.y);! !! ! //Particleの状態を更新! ! particles[i].addForce(frc.x, frc.y);! ! particles[i].addDampingForce();! ! particles[i].bounceOffWalls();! ! particles[i].update();! }!! //ベクトル場の力の減衰! VF.fadeField(0.998f);}

Page 46: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場にパーティクルを浮遊させる‣ あとは、全てのパーティクルを描画するのみ‣ testApp.cpp - update() 関数void testApp::draw(){!! ofEnableBlendMode(OF_BLENDMODE_ADD);!! //ベクトル場を描画! ofSetColor(0,130,130, 127);! VF.draw();!! //ベクトル場に配置されたparticleを描画! ofSetColor(0, 127, 255)! ;! for (int i = 0; i < particles.size(); i++){! ! particles[i].draw();! }!!! ofDisableBlendMode();!}

Page 47: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場にパーティクルを浮遊させる‣ 完成:マウスをドラッグするとパーティクルが浮遊する

Page 48: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

‣ 最初のサンプルで使用した、マウスの軌跡でドローインングするアルゴリズムと、ベクトル場を融合する

‣ マウスをドラッグすると、ベクトル場を自由に描くことができるように

ベクトル場 + ドローイング

Page 49: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場 + ドローイング‣ マウスをドラッグすると、その方向と距離でベクトル場に力を加えるようにする

‣ testApp.cpp - mouseDragged() 関数

void testApp::mouseDragged(int x, int y, int button){!! float diffx = x - prevMouseX;! float diffy = y - prevMouseY;!! VF.addVectorCircle((float)x, (float)y, diffx*0.3, diffy*0.3, 60, 0.3f);!! prevMouseX = x;! prevMouseY = y;}

Page 50: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場 + ドローイング‣ 完成:空間上の粒子を指でなぞるように動かすことが可能

Page 51: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場 + ドローイング‣ 応用:iPadなどのマルチタッチのデバイスと組み合せ‣ MSAFluid:Memo Akten氏による流体のシミュレーション‣ http://www.msavisuals.com/msafluid

Page 52: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

生物の動き鳥の群れをシミュレート (Boids)

Page 53: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

鳥の群れをシミュレート (Boid)‣ Boids 「鳥もどき(bird-oid)」‣ 1987年にCraig Raynoldsによって発表された理論‣ 3つのルールを規定するだけで鳥の群れをシミュレーションできるというもの

‣ 単純な規則を用いて群体としての複雑な振る舞いを再現できることを示した

‣ Craig ReynoldsのBoidsの解説ページ‣ http://www.red3d.com/cwr/boids/

Page 54: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

鳥の群れをシミュレート (Boid)‣ Boidsのルール

‣ Separation(引き離し)‣ 近くの鳥や物体に近づきすぎたらぶつからないように離れるルール

‣ Alingment(整列)‣ 近くの鳥たちと飛ぶスピードや方向を合わせようとするルール

‣ Cohesion(結合)‣ 鳥たちが多くいる方へ向かって飛ぶルール

Page 55: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

鳥の群れをシミュレート (Boid)‣ このサンプルでは、particleクラス自身にBoidsのルールをメソッドとして追加している

‣ addForFlocking()‣ addFlockingForce()

Page 56: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場にパーティクルを浮遊させる‣ Boidsの3つのルールを、particle.cppに追加void particle::addFlockingForce(){

! // seperation! if(seperation.count > 0){! ! seperation.sum /= (float)seperation.count;! ! float sepFrc ! = seperation.strength;! ! frc -= (seperation.sum.normalized() * sepFrc);! }!! // alignment! if(alignment.count > 0){! ! alignment.sum /= (float)alignment.count;! ! float alignFrc ! = alignment.strength;! ! frc += (alignment.sum!! * alignFrc);! }!! // cohesion! if(cohesion.count > 0){! ! cohesion.sum /= (float)cohesion.count;! ! cohesion.sum -= pos;! ! float cohFrc ! = cohesion.strength;! ! frc += (cohesion.sum.normalized() * cohFrc);! }!}

Page 57: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

ベクトル場にパーティクルを浮遊させる‣ Boidsの3つのルールを、particle.cppに追加 (つづき)void particle::addForFlocking(particle &p){!! ofVec3f diff, diffNormalized;! float distance;!! diff! ! ! = p.pos - pos;! distance! ! = diff.length();! diffNormalized! = diff;! diffNormalized.normalize();

! if( distance > 0 && distance < seperation.distance ){! ! seperation.sum += diffNormalized;! ! seperation.count++;! }!! if( distance > 0 && distance < alignment.distance ){! ! alignment.sum += p.vel.getNormalized();! ! alignment.count++;! }!! if( distance > 0 && distance < cohesion.distance ){! ! cohesion.sum += p.pos;! ! cohesion.count++;! }}

Page 58: openFrameworks 動きを生みだす様々なアルゴリズム - 多摩美メディアアートII

鳥の群れをシミュレート (Boid)‣ 驚くほどリアルな群れの動きが再現される