Media Art II 2013 第5回:openFrameworks Addonを使用する

Preview:

DESCRIPTION

 

Citation preview

Media Art II 2013 第5回:openFrameworksAddonを使用する

2013年10月14日多摩美術大学 情報デザイン学科 メディア芸術コース田所 淳

Addonとは?‣ Addonとは、oepnFrameworksの機能を何らかの方法で拡張するコード

‣ 「ofx」という接頭辞で始まる

Addonとは?‣ openFrameworksに機能を拡張するためのライブラリー‣ processingのLibrariesのような存在‣ openFrameworks単体ではできなかった様々な機能を実現‣ oF本体の開発者以外でも独自に開発して追加することが可能

‣ アドオン情報‣ ofxAddons‣ http://ofxaddons.com/

Addonとは?‣ ofxAddons.com リニューアル

Addonとは?‣ どうやってofxAddons.comのアドオンをインストールすのか?

‣ 方法1: git コマンドをつかって、コードの複製をつくる

‣ 方法2: WebサイトからZip形式ダウンロード

$cd of_preRelease/addons/$git clone https://github.com/obviousjim/ofxSomeAddon

コレ

Addonとは?‣ Addonは何のためにあるの?

‣ 外部ライブラリやフレームワークをoFに統合‣ ofxKinect, ofxMidi etc..

‣ 定型の作業、複雑な操作を単純化‣ ofxQuadWrap、ofxControlPanel etc...

Addonsとは?

コンピュータ・ビジョン / ARofxOpenCv, ofxARToolkitPlus

シミュレーション / 物理計算 / 流体力学ofxBox2d, ofxMSAFluid, ofxMSAPhisics, ofxRuiPhusics2d

音響ofxMidi, ofxOsc, ofxSoundObj, ofxSuperCollider

デバイス / ハードウェアofxiPhone, ofxSuddenMotion

Addonsとは?‣ 最初からいくつかのアドオンが付属してくる

アドオンの名称 説明

ofxDirList ディレクトリの項目の一覧を生成

ofxXmlSettings アプリケーションの設定をXML形式で保存、読込み

ofxOsc Open Sound ControlをOpenFrameworksで使用する

ofxOpenCv 画像処理・画像認識用のC言語ライブラリOpenCVを使用できるようにする

ofxNetwork ネットワーク通信のプロトコル、TCPとUDPを使用可能にする、マルチキャストにも対応

ofxThred クロスプラットフォームでスレッドの管理を実現

ofxVectorGraphics OpenFrameworksからPostscriptを生成し出力する

ofx3dModelLoader 3ds形式の3DモデルをOpenFrameworksに読みこむ

Addonsとは?‣ アドオンがインストールされている場所‣ 《oFをインストールしたフォルダ》/addons/

Addonsとは?‣ 今回は題材として2つのAddonを試してみます

‣ ofxGui:GUI‣ 長らく待望されていた、oFオフィシャルGUI‣ プログラムで頻繁に調整する必要のあるパラメータをGUIから設定可能にする

‣ 設定した項目は、XML形式で設定ファイルとして保存と読込が可能

‣ ofxBox2d:物理演算‣ 重力や、物体同士の衝突、ばねや引力など様々な物理演算を簡単に実装可能

ofxGui

ofxGui‣ 長らく待望されていた(?) openFrameworks開発チーム純正のGUI を作成するためのAddon

‣ v.0.8.0 から配布パッケージに同梱‣ 簡単にプロジェクトにGUIを追加可能

ofxGui‣ Addon の使用法を知るにはサンプルをみるのが一番!‣ Addon の多くにはサンプルが付属してる‣ ofxGuiの場合は「of_v0.8.0_osx_release/examples/gui/」に大量に掲載 (オフィシャル感!!)

ofxGui‣ まずは基本の「guiExample」をみてみる

ofxGui‣ 「guiExample」に含まれる様々なGUIの機能

‣ 数値のスライダー (int, float)‣ カラー設定スライダー‣ 位置 (ofVec2f)‣ トグルボタン‣ ボタン‣ ... etc.

ofxGui‣ ofxGuiで使用できる機能いろいろ

アドオンの名称 説明

ofxIntSlider 整数型 (int) のスライダーofxFloatSlider 浮動小数点型 (float) のスライダーofxVec2Slider 2次元ベクトルのスライダーofxColorSlider カラー生成スライダーofxButton ボタンofxToggle トグルスイッチofxLabel ラベル (テキスト表示)ofxPanel GUIの外枠

ofxGui‣ 簡単なプログラムで使い方をマスター‣ まずは新規プロジェクトの生成方法から‣ ProjectGeneratorの設定方法から

ofxGui‣ プロジェクト名を設定したら、「Addons」ボタンを押す

←ココ

ofxGui‣ ofxGuiのチェックボックスをチェックして戻る‣ GENERATE PROJECT ボタンを押して完了

ofxGui‣ プロジェクトを開いてみる‣ addonsフォルダにAddonsが追加されているはず

ofxGui‣ 以下のようなシンプルなGUI操作を実現したい

‣ 画面に円を描く‣ 円の半径をスライダーで調整‣ 円の色もスライダーで調整

#pragma once

#include "ofMain.h"#include "ofxGui.h"

class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void keyPressed(int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); };

ofxGui‣ まず始めに、testApp.h の冒頭で ofxGui を 読み込む

←ココ

#pragma once

#include "ofMain.h"#include "ofxGui.h"

class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); ... ofxPanel gui; ofxFloatSlider radius; ofxColorSlider color; ofxVec2Slider position; };

ofxGui‣ 必要なパーツを全てインスタンス化

←ココ

ofxGui‣ まず、gui.setup() でGUI生成

‣ そこへ、スライダーの初期設定を追加していく‣ gui.add(スライダー.setup(“名前”, 初期値, 最小値, 最大値));

#include "testApp.h"

//--------------------------------------------------------------void testApp::setup(){ ofSetFrameRate(60); ofBackground(127); ofSetCircleResolution(32); // colorの初期値、最小値、最大値を設定 ofColor initColor = ofColor(0, 127, 255, 255); ofColor minColor = ofColor(0,0,0,0); ofColor maxColor = ofColor(255,255,255,255); // positionの初期値、最小値、最大値を設定 ofVec2f initPos = ofVec2f(ofGetWidth()/2, ofGetHeight()/2); ofVec2f minPos = ofVec2f(0, 0); ofVec2f maxPos = ofVec2f(ofGetWidth(), ofGetHeight()); gui.setup(); gui.add(radius.setup("radius", 200, 0, 400)); gui.add(color.setup("color", initColor, minColor, maxColor)); gui.add(position.setup("position", initPos, minPos, maxPos));}

ofxGui‣ testApp.cpp 必要なパーツを全てインスタンス化

void testApp::draw(){ // パラメータを適用して円を描画 ofSetColor(color); ofCircle(ofVec2f(position), radius); // GUIを表示 gui.draw();}

ofxGui‣ あとは、その値を描画に適用するのみ (簡単!!)

ofxGui‣ 実行結果

ofxGui‣ ofxGuiのより実践的な練習‣ 先週のVector FieldのサンプルのパラメータをGUIで操作

ofxGui‣ 先週のVector FieldのサンプルのパラメータをGUIで操作

‣ GUIで操作するパラメータをスライダーで‣ friction (摩擦) float‣ radius (パーティクル半径) float‣ color (パーティクル色) ofColor ...etc.

‣ イベントを発生させるボタン‣ パーティクルの位置をリセット‣ Vector Fieldの力をリセット‣ Vector Fieldの力をランダマイズ

‣ 既に生成されて、vectorに格納された大量のParticleのオブジェクトに対してパラメータ変更するにはちょっと工夫が必要

‣ イベントリスナーをつかう

‣ 例えば、friction (摩擦) の場合‣ testApp.hで、イベントリスナーの関数を定義しておく

ofxGui

ofxFloatSlider friction;void frictionChanged(float & friction);

‣ testApp.cpp スライダーを作成する際にイベントリスナーを追加する

‣ 摩擦を変化させた際のイベントを記述する

‣ 同じようにして、半径や、各種ボタンに関しても

ofxGui

friction.addListener(this, &testApp::frictionChanged);

void testApp::frictionChanged(float & friction){ for (int i = 0; i < particles.size(); i++){ particles[i].friction = friction; }}

ofxGui‣ 完成!!

ofxBox2d

ofxBox2d‣ 本日のAddonsその2

‣ 2次元の物理シミュレーションのためのAddon‣ ofxBox2d

ofxBox2d‣ ofxBox2d:‣ Box2DをoFのアドオン形式にしたもの

‣ Box2Dとは‣ C++で書かれた、物理エンジン‣ 重力や反発力、摩擦、衝突判定といった物理計算を複雑な計算をすることなく利用できる

‣ ActionScript、Java、C#、Pythonなどにも移植されている

ofxBox2d‣ Box2D Google Codeページ‣ http://code.google.com/p/box2d/

ofxBox2d‣ ofxBox2d → Box2Dを、openFrameworksのAddons形式にしたもの

‣ oF v007用に大幅に機能が向上している‣ http://vanderlin.cc/2011/07/ofxbox2d-007/

Addonをプロジェクトに追加する‣ Box2Dを題材にして、実際に空のプロジェクトにBox2Dを追加してみる

‣ ProjectGeneratorから、ofxBox2dを追加する‣ 必要となるAddonはofxBox2Dだけ

Box2D基本

Box2D基本‣ Box2Dに描かれる図形は全てBox2Dの物理世界に配置‣ testAppのsetup()関数内で、まずBox2Dの世界を初期化する‣ 初期化の例

void testApp::setup() {! ...!! box2d.init(); // Box2Dの世界の初期化! box2d.setGravity(0, 10); // 重力を下向きに10! box2d.createBounds(); // 地面を生成! box2d.setFPS(30.0); // Box2Dの世界でのFPS! box2d.registerGrabbing(); // 物体に接触可能に}

Box2D基本‣ Box2Dの物理計算を実行するには、testAppのupdate()関数で、ofxBox2Dのupdate()メソッドを呼びだすだけ

‣ 自動的に全ての「重力」「摩擦」「衝突」「反射」などの物理計算を行なってくれる

void testApp::update() {! box2d.update(); // Box2Dの更新}

Box2D基本‣ Box2Dの物理世界に配置する物体は、Box2Dで用いられる専用のクラスから生成する

‣ 基本クラスを継承して、自分独自の形態にすることも可能

‣ ofxBox2Dで使用できる物体

クラス名 形態

ofxBox2dCircle 円

ofxBox2dRect 四角形

ofxBox2dPolygon ポリゴン(多角形)

ofxBox2dJoint 図形同士を結ぶジョイント

たくさんの円を配置してみる

たくさんの円を配置してみる‣ まずはシンプルなサンプルを作成してみましょう‣ Box2Dの物理世界に、沢山の円(ofxBox2dCircle)を配置してその動きを観察

‣ 配置する円の数に制限を設けたくないので、ofxBox2dCircleの動的配列(vector)を生成して管理すると便利

vector <ofxBox2dCircle> circles;! // Circleを格納する動的配列

Box2D基本:たくさんの円で物理演算‣ testApp.h‣#pragma once#include "ofMain.h"#include "ofxBox2d.h"

class testApp : public ofBaseApp {!public:!! void setup();! void update();! void draw();! void keyPressed(int key);!! ofxBox2d box2d;!// Box2Dの世界を構築! vector <ofxBox2dCircle> circles;!// Circleを格納する動的配列};

Box2D基本:たくさんの円で物理演算‣ testApp.cpp - 1 of 2#include "testApp.h"

void testApp::setup() {! ofSetVerticalSync(true);! ofBackgroundHex(0x000000);!! box2d.init(); // Box2Dの世界の初期化! box2d.setGravity(0, 10); // 重力を下向きに10! box2d.createBounds(); // 地面を生成! box2d.setFPS(30.0); // Box2Dの世界でのFPS! box2d.registerGrabbing(); // 物体に接触可能に}

void testApp::update() {! box2d.update(); // Box2Dの更新}

void testApp::draw() {! // circlesを描く! for(int i=0; i<circles.size(); i++) {! ! ofSetHexColor(0x3366ff);! ! circles[i].draw();! }}

Box2D基本:たくさんの円で物理演算‣ testApp.cpp - 2 of 2

void testApp::keyPressed(int key) {! // [c]キーを押すと、Circleを追加! if(key == 'c') {! ! float r = ofRandom(4, 20); //半径をランダムに! ! ofxBox2dCircle circle; //円! ! circle.setPhysics(3.0, 0.53, 0.1); //物理法則を追加! ! // Box2dの世界に生成した円を追加! ! circle.setup(box2d.getWorld(), mouseX, mouseY, r);! ! circles.push_back(circle); // 動的配列に追加! }}

Box2D基本:たくさんの円で物理演算‣ 「c」キーを押すと、円が追加されていく

いろいろな形を描いてみる

いろいろな形を描いてみる‣ さらに色々な形を描いてみましょう‣ 円 - ofxBox2dCircle‣ 四角形 - ofxBox2dRect‣ ポリゴン - ofxBox2dPolygon

‣ それぞれ以下の操作でBox2Dの世界で追加‣ 円 - 「c」キーを押すと追加‣ 四角形 - 「r」キーを押すと追加‣ ポリゴン - 画面をマウスでドラッグして描く

いろいろな形を描いてみる‣ testApp.h#pragma once#include "ofMain.h"#include "ofxBox2d.h"

class testApp : public ofBaseApp {!public:!! void setup();! void update();! void draw();! void keyPressed(int key);! void mouseDragged(int x, int y, int button);! void mousePressed(int x, int y, int button);! void mouseReleased(int x, int y, int button);!! ofxBox2d box2d;!// Box2Dの世界を構築! vector <ofxBox2dCircle> circles;!// Circleを格納する動的配列! vector <ofxBox2dRect> rects;!// Rectを格納する動的配列! ofPolyline drawing; // 画面に描く線! ofxBox2dPolygon polyLine; // 描いた線から、多角形の物体を生成};

いろいろな形を描いてみる‣ testApp.cpp - 1 of 1#include "testApp.h"

void testApp::setup() {! ofSetVerticalSync(true);! ofBackgroundHex(0x000000);!! box2d.init(); // Box2Dの世界の初期化! box2d.setGravity(0, 10); // 重力を下向きに10! box2d.setFPS(30.0); // Box2Dの世界でのFPS! box2d.registerGrabbing(); // 物体に接触可能に!! polyLine.setPhysics(0.0, 0.5, 0.5);! polyLine.create(box2d.getWorld());!}

void testApp::update() {! box2d.update(); // Box2Dの更新}

いろいろな形を描いてみる‣ testApp.cpp - 1 of 3void testApp::draw() {! // 円を描く! ofFill();! for(int i=0; i<circles.size(); i++) {! ! ofSetHexColor(0x3366ff);! ! circles[i].draw();! }!! // 四角形を描く! for(int i=0; i<rects.size(); i++) {! ! ofSetHexColor(0xff6633);! ! rects[i].draw();! }!! // 多角形(描画した線分)を描く! ofNoFill();! ofSetHexColor(0xffffff);! if(drawing.size()==0) {! ! polyLine.draw();!! }! else {! ! drawing.draw();!! }}

いろいろな形を描いてみる‣ testApp.cpp - 2 of 3void testApp::keyPressed(int key) {! // [c]キーを押すと、ofxBox2DCircleを追加! if(key == 'c') {! ! float r = ofRandom(4, 20); //半径をランダムに! ! ofxBox2dCircle circle; //円! ! circle.setPhysics(3.0, 0.53, 0.1); //物理法則を追加! ! // Box2dの世界に生成した円を追加! ! circle.setup(box2d.getWorld(), mouseX, mouseY, r);! ! circles.push_back(circle); // 動的配列に追加! }! // [r]キーを押すと、ofxBox2DRectを追加! if(key == 'r') {! ! float w = ofRandom(4, 20); // 幅をランダムに! ! float h = ofRandom(4, 20); // 高さをランダムに! ! ofxBox2dRect rect; // 四角形! ! rect.setPhysics(3.0, 0.53, 0.1); // 物理法則を追加! ! // Box2dの世界に生成した四角形を追加! ! rect.setup(box2d.getWorld(), mouseX, mouseY, w, h);! ! rects.push_back(rect); // 動的配列に追加! }}

いろいろな形を描いてみる‣ testApp.cpp - 3 of 3void testApp::mouseDragged(int x, int y, int button) {! drawing.addVertex(x, y);}

void testApp::mousePressed(int x, int y, int button) {! // もしも既に多角形が存在していたら、消去する! if(polyLine.isBody()) {! ! drawing.clear();! ! polyLine.destroy();!! }! // 描画中の線分に辺を追加! drawing.addVertex(x, y);}

void testApp::mouseReleased(int x, int y, int button) {! // 描画していた多角形を確定! drawing.setClosed(false);! drawing.simplify();! // ofxBox2dPlyLineとして生成! polyLine.addVertexes(drawing);! polyLine.simplify();! polyLine.setPhysics(0.0, 0.5, 0.5);! polyLine.create(box2d.getWorld());! drawing.clear();}

いろいろな形を描いてみる‣ マウスで描いた形にそって、円と四角が落ちていく

いろいろな形を描いてみる‣ 参考:Line Rider‣ 描いた線にそって、そり滑り!!

「ばね」の運動

「ばね」の運動‣ ofxBox2dJoint - Box2Dで生成した図形の間を連結する‣ パラメータを調節することで、固い棒のような性質から、やわらかい「ばね」の動きなど様々なシミュレーションが可能

‣ 配置した全ての円の間を「ばね」で繋いでみる

いろいろな形を描いてみる‣ testApp.h#pragma once#include "ofMain.h"#include "ofxBox2d.h"

class testApp : public ofBaseApp {!public:!! void setup();! void update();! void draw();! //void keyPressed(int key);! void mouseReleased(int x, int y, int button);! void mouseDragged(int x, int y, int button);!! ofxBox2d box2d;!// Box2Dの世界を構築! vector <ofxBox2dRect> rects;!// Circleを格納する動的配列! vector <ofxBox2dJoint> joints; // バネの配列};

「ばね」の運動‣ testApp.cpp - 1 of 3#include "testApp.h"

void testApp::setup() {! ofSetVerticalSync(true);! ofBackgroundHex(0x000000);!! box2d.init(); // Box2Dの世界の初期化! box2d.setGravity(0, 0); // 無重力に! box2d.createBounds(); // 地面を生成! box2d.setFPS(30.0); // Box2Dの世界でのFPS! box2d.registerGrabbing(); // 物体に接触可能に}

void testApp::update() {! box2d.update(); // Box2Dの更新}

void testApp::draw() {! // バネを描く! for(int i=0; i<joints.size(); i++) {! ! ofNoFill();! ! ofSetHexColor(0x333333);! ! joints[i].draw();! }

「ばね」の運動‣ testApp.cpp - 2 of 3! // circlesを描く! for(int i=0; i<rects.size(); i++) {! ! ofFill();! ! ofSetHexColor(0x3366ff);! ! rects[i].draw();! }}

void testApp::mouseReleased(int x, int y, int button) {! ofxBox2dRect rect; //円! rect.setPhysics(10.0, 0.99, 0.0);!! // Box2dの世界に生成した円を追加! rect.setup(box2d.getWorld(), x, y, 2, 2);! rects.push_back(rect); // 動的配列に追加!! if (rects.size() > 1) {! ! for (int i = 0; i < rects.size()-1; i++) {! ! ! ofxBox2dJoint joint;! ! ! joint.setup(box2d.getWorld(), rects[rects.size()-1].body, rects[i].body);! ! ! joint.setFrequency(0.4);! ! ! joint.setDamping(0.1);! ! ! joint.setLength(200);! ! ! joints.push_back(joint);

「ばね」の運動‣ testApp.cpp - 3 of 3! ! }! }}

void testApp::mouseDragged(int x, int y, int button) {! for (int i = 0; i < rects.size()-1; i++) {! ! rects[i].addRepulsionForce(x, y, -1);! }}

「ばね」の運動‣ ばねで連結された物体が出現‣ マウスをドラッグすると、動きまわる

「ばね」の運動‣ 参考:SodaPlay (http://sodaplay.com/)‣ ばねの連結でできた、生物たち