Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス
-
Upload
atsushi-tadokoro -
Category
Technology
-
view
4.065 -
download
5
description
Transcript of Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス
![Page 1: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/1.jpg)
Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス openSoundControl, reacTIVision
多摩美術大学情報デザイン学科情報芸術コース 2013年12月9日 田所 淳
![Page 2: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/2.jpg)
Open Sound Control (OSC) について
![Page 3: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/3.jpg)
Open Sound Control とは‣ Open Sound Control のプロジェクトのWebページより
!‣ Open Sound Control (OSC) is a protocol for communication among computers, sound synthesizers, and other multimedia devices that is optimized for modern networking technology. Bringing the benefits of modern networking technology to the world of electronic musical instruments, OSC's advantages include interoperability, accuracy, flexibility, and enhanced organization and documentation.
![Page 4: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/4.jpg)
Open Sound Control とは‣ Open Sound Control のプロジェクトのWebページより
!‣ Open Sound Control (OSC) は、コンピュータやシンセサイザーや、その他のマルチメディアデバイス同士でコミュニケーションするための通信プロトコルです。現代のネットワーク技術の成果を電子楽器の世界に適用することで、OSCは、相互運用性、正確さ、柔軟さ、また、拡張性に優れた性能を持ちます。
![Page 5: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/5.jpg)
Open Sound Control とは‣ Open Sound Control のポイント !
‣ ポストMIDIを目指す ‣ インターネットのプロトコルの仕組みを、音楽やマルチメディアの世界へ適用 (UDP/IPを利用)
‣ 多くの機器、言語、アプリケーションに実装済み ‣ オープンでシンプルな命名規則 ← URLの仕組みに似ている
![Page 6: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/6.jpg)
Open Sound Control とは‣ Open Sound Control が実装された主な環境
!‣ サウンド系 ‣ Max/MSP ‣ Pd ‣ SuperCollider ‣ Chuck ‣ Csound ‣ Reactor など !
‣ ビジュアル系 ‣ Flash ( flosc ) ‣ Processing ‣ OpenFrameworks ‣ QuartzComposer ‣ vvvv
![Page 7: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/7.jpg)
Open Sound Control とは‣ Open Sound Control が実装された主な環境
!‣ デバイス ‣ Lemur ‣ monome
![Page 8: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/8.jpg)
Open Sound Control とは‣ Open Sound Control が実装された主な環境 ‣ iPhoneやiPadからも!
![Page 9: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/9.jpg)
OSCのプロトコル
OSC Message OSC Arguments
• 情報内容をラベリング • URLに同様の名前付けの規則
• 情報の本体 • いろいろな型を同時に含めることができる
‣ では、実際にOSCのプロトコルは、どんななっているのか? !!/trigger/inst/a 440 0.1 “hello”
![Page 10: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/10.jpg)
OSC Message‣ OSC Messageのアドレスパターン → URLのような階層構造
![Page 11: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/11.jpg)
OSC の通信のしくみ
![Page 12: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/12.jpg)
‣ 送信側:IPアドレスとportを指定
OSC の通信のしくみ
IP: 192.168.1.3 port: 57120
![Page 13: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/13.jpg)
‣ 受信側:ポートをオープン
OSC の通信のしくみ
IP: 192.168.1.3 port: 57120
![Page 14: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/14.jpg)
‣ 接続
OSC の通信のしくみ
IP: 192.168.1.3 port: 57120
![Page 15: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/15.jpg)
‣ 送信側:情報を送信 ‣ 受信側:受信
OSC の通信のしくみ
/trigger/inst/a 440 0.1 “hello”
IP: 192.168.1.3 port: 57120
![Page 16: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/16.jpg)
‣ 受信側:OSCのメッセージを解釈、アプリケーションに適用
OSC の通信のしくみ
/trigger/inst/a 440 0.1 “hello”
IP: 192.168.1.3 port: 57120
![Page 17: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/17.jpg)
openFrameworksのアプリケーション同士でOSCを送受信する
![Page 18: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/18.jpg)
アプリケーション同士でOSCを送受信する‣ プロジェクトの準備 ‣ OSCの送信側、受信側双方のaddons内にofxOscを追加する
![Page 19: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/19.jpg)
アプリケーション同士でOSCを送受信する‣ まず始めに、openFrameworksのアプリケーション同士でOSCを送受信してみる !
‣ まずは簡単なサンプル ‣ マウスの位置とマウスボタンの状態をOSCで表現してみる
![Page 20: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/20.jpg)
アプリケーション同士でOSCを送受信する‣ マウスの位置とマウスボタンの状態 !
‣ マウスの位置 ‣ メッセージ:/mouse/position ‣ 引数:X座標 Y座標 (例: 320 240) !
‣ マウスボタンの状態 ‣ メッセージ:/mouse/button ‣ 引数:ボタンの状態 (“up”, “down”)
![Page 21: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/21.jpg)
アプリケーション同士でOSCを送受信する‣ 実際にやりとりされるOSCメッセージの例: !
‣ マウスを座標(480, 240)に動かした場合 ‣ /mouse/position 480 240 !
‣ マウスボタンを押した瞬間 ‣ /mouse/button “down” !
‣ マウスボタンを離した瞬間 ‣ /mouse/button “up”
![Page 22: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/22.jpg)
アプリケーション同士でOSCを送受信する‣ 実際にOSCがやりとりされている様子を視覚的に表現 !
‣ 送信側のマウス位置 → 受信側では円で表示 ‣ マウスボタンを離している時 → 色は青 ‣ マウスボタンを押している時 → 色は赤
![Page 23: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/23.jpg)
#pragma once !#include "ofMain.h" #include "ofxOsc.h" !#define HOST "127.0.0.1" // 受信側のIPアドレス #define PORT 8000 // 受信側のポート番号 !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); 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); //OSCメッセージの送信者 ofxOscSender sender; };
OSC送信側プログラム‣ testApp.h
![Page 24: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/24.jpg)
#include "testApp.h" !void testApp::setup(){ ofBackground(0, 0, 0); // 指定したIPアドレスとポート番号でサーバーに接続 sender.setup(HOST, PORT); } !void testApp::update(){ } !void testApp::draw(){ // 現在のマウスの場所に円を描画 ofSetColor(255, 255, 255); ofCircle(mouseX, mouseY, 10); } !void testApp::mouseMoved(int x, int y){ // OSCメッセージの準備 ofxOscMessage m; // OSCアドレスの指定 m.setAddress("/mouse/position"); // OSC引数として、現在のマウスの座標(x, y)を送信 m.addIntArg(x); m.addIntArg(y); // メッセージを送信 sender.sendMessage(m);
OSC送信側プログラム‣ testApp.cpp
![Page 25: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/25.jpg)
void testApp::mouseDragged(int x, int y, int button){ //OSCメッセージの準備 ofxOscMessage m; //OSCアドレスの指定 m.setAddress("/mouse/position"); //OSC引数として、現在のマウスの座標(x, y)を送信 m.addIntArg(x); m.addIntArg(y); //メッセージを送信 sender.sendMessage(m); } !void testApp::mousePressed(int x, int y, int button){ //OSCメッセージの準備 ofxOscMessage m; //OSCアドレスの指定 m.setAddress("/mouse/button"); //OSC引数として、マウス状態"down"を送信 m.addStringArg("down"); //メッセージを送信 sender.sendMessage(m); }
OSC送信側プログラム‣ testApp.cpp
![Page 26: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/26.jpg)
void testApp::mouseReleased(int x, int y, int button){ //OSCメッセージの準備 ofxOscMessage m; //OSCアドレスの指定 m.setAddress("/mouse/button"); //OSC引数として、マウス状態"up"を送信 m.addStringArg("up"); //メッセージを送信 sender.sendMessage( m ); }
OSC送信側プログラム‣ testApp.cpp
![Page 27: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/27.jpg)
#pragma once !#include "ofMain.h" #include "ofxOsc.h" !// OSCを受信するポート番号を設定 #define PORT 8000 !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); ! void dumpOSC(ofxOscMessage m); //OSCメッセージを出力 // OSCメッセージを受信するインスタンス ofxOscReceiver receiver; ! // 受信したマウス座標 ofPoint remoteMouse; ! // 受信したマウスボタンの状態 ("up", "down") string mouseButtonState;
OSC受信側プログラム‣ testApp.h
![Page 28: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/28.jpg)
#include "testApp.h" !void testApp::setup(){ ofBackground(0, 0, 0); //指定したポートで接続 receiver.setup( PORT ); //値を初期化 mouseX = 0; mouseY = 0; mouseButtonState = ""; } !void testApp::update(){ // 現在順番待ちのOSCメッセージがある間は受信を続ける while(receiver.hasWaitingMessages()){ //次のメッセージを取得 ofxOscMessage m; receiver.getNextMessage(&m); // メッセージが /mouse/position ならマウスの位置を取得 if (m.getAddress() == "/mouse/position"){ remoteMouse.x = m.getArgAsInt32(0); remoteMouse.y = m.getArgAsInt32(1);
OSC受信側プログラム‣ testApp.cpp
![Page 29: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/29.jpg)
! // メッセージが /mouse/button ならマウスボタンの状態を取得 else if (m.getAddress() == "/mouse/button"){ mouseButtonState = m.getArgAsString(0) ; } //OSCメッセージをそのままコンソールに出力 dumpOSC(m); } } !void testApp::draw(){ int radius; ! // マウスボタンが押されていたら、赤い円を描画 if (mouseButtonState == "down") { radius = 20; ofSetColor(255, 127, 0); } else { // そうでなければ、青い円を描画 radius = 10; ofSetColor(0, 127, 255); } ofCircle(remoteMouse.x, remoteMouse.y, radius); }
OSC受信側プログラム‣ testApp.cpp
![Page 30: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/30.jpg)
// OSCメッセージをコンソールに出力する関数 void testApp::dumpOSC(ofxOscMessage m) { string msg_string; msg_string = m.getAddress(); for (int i=0; i<m.getNumArgs(); i++ ) { msg_string += " "; if(m.getArgType(i) == OFXOSC_TYPE_INT32) msg_string += ofToString( m.getArgAsInt32(i)); else if(m.getArgType(i) == OFXOSC_TYPE_FLOAT) msg_string += ofToString( m.getArgAsFloat(i)); else if(m.getArgType(i) == OFXOSC_TYPE_STRING) msg_string += m.getArgAsString(i); } cout << msg_string << endl; }
OSC受信側プログラム‣ testApp.cpp
![Page 31: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/31.jpg)
アプリケーション同士でOSCを送受信する‣ OscSenderの画面でマウスを操作 ‣ OscReceiverに現在のマウスの位置と状態が表示される
![Page 32: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/32.jpg)
アプリケーション同士でOSCを送受信する‣ OSCでやりとりするメッセージは、同一のマシン内でだけではない
‣ IP網を介して、ネットワークで通信することが可能
OSC
![Page 33: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/33.jpg)
アプリケーション同士でOSCを送受信する‣ 教室内のMac同士でOSC通信してみる ‣ お互いのIPアドレスを調べる ‣ システム環境設定 → ネットワーク の「IPアドレス」の数値
![Page 34: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/34.jpg)
#pragma once !#include "ofMain.h" #include "ofxOsc.h" !#define HOST "192.168.10.8" // 受信側のIPアドレス !#define PORT 8000 // 受信側のポート番号 !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); 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); //OSCメッセージの送信者 ofxOscSender sender; };
アプリケーション同士でOSCを送受信する‣ 送信先のIPに、OscSenderのtestApp.hのHOSTを変更
![Page 35: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/35.jpg)
アプリケーション同士でOSCを送受信する‣ OscSenderでマウスを動かすと、ネットワークに接続された他のマシンの円を動かすことができるはず
![Page 36: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/36.jpg)
複数のマシンでアプリケーションを共有
![Page 37: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/37.jpg)
‣ では次に、複数のPCで一つの端末のアプリケーションを共有するプログラムを作成してみる
複数のPCでアプリケーションを共有
![Page 38: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/38.jpg)
複数のPCでアプリケーションを共有‣ 外部のPCからアクセスがあるたびに、輪が追加され波紋のように拡がっていくプログラム
![Page 39: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/39.jpg)
#pragma once !#include "ofMain.h" #include "ofxOsc.h" #include "Ring.h" !#define HOST "127.0.0.1" #define PORT 8000 !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); 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); ! ofxOscSender sender; // OSCメッセージの送信 vector <Ring *> rings; //輪の動的配列 };
複数のマシンでアプリケーションを共有‣ 送信側: testApp.h
![Page 40: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/40.jpg)
#pragma once !#include "ofMain.h" #include "ofxOsc.h" #include "Ring.h" !#define HOST "127.0.0.1" #define PORT 8000 !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void mouseMoved(int x, int y ); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); ! ofxOscSender sender; // OSCメッセージの送信 vector <Ring *> rings; // 輪の動的配列 };
複数のマシンでアプリケーションを共有‣ 送信側: testApp.h
![Page 41: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/41.jpg)
#include "testApp.h" !void testApp::setup(){ ofBackground(0, 0, 0); ofSetFrameRate(60); //指定したIPアドレスとポート番号でサーバーに接続 sender.setup( HOST, PORT ); } !void testApp::update(){ //Ring更新 for(vector <Ring *>::iterator it = rings.begin(); it != rings.end();){ (*it)->update(); if ((*it)->dead) { delete (*it); it = rings.erase(it); } else { ++it; } } } !void testApp::draw(){ //Ringを描画 for(vector <Ring *>::iterator it = rings.begin(); it != rings.end(); ++it){ (*it)->draw(); }
複数のマシンでアプリケーションを共有‣ 送信側: testApp.cpp
![Page 42: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/42.jpg)
!void testApp::mouseMoved(int x, int y ){ //OSCメッセージの準備 ofxOscMessage m; //OSCアドレスの指定 m.setAddress( "/mouse/position" ); //OSC引数として、現在のマウスの座標(x, y)を送信 m.addIntArg( x ); m.addIntArg( y ); //メッセージを送信 sender.sendMessage( m ); } !void testApp::mousePressed(int x, int y, int button){ //OSCメッセージの準備 ofxOscMessage m; //OSCアドレスの指定 m.setAddress( "/mouse/button" ); //OSC引数として、マウス状態"down"を送信 m.addStringArg( "down" ); //OSC引数として、現在のマウスの座標(x, y)を送信 m.addIntArg( x ); m.addIntArg( y ); sender.sendMessage( m ); }
複数のマシンでアプリケーションを共有‣ 送信側: testApp.cpp
![Page 43: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/43.jpg)
void testApp::mouseReleased(int x, int y, int button){ //OSCメッセージの準備 ofxOscMessage m; //OSCアドレスの指定 m.setAddress( "/mouse/button" ); //OSC引数として、マウス状態"up"を送信 m.addStringArg( "up" ); //OSC引数として、現在のマウスの座標(x, y)を送信 m.addIntArg( x ); m.addIntArg( y ); sender.sendMessage( m ); //Ringを追加 rings.push_back(new Ring(ofPoint(x, y))); }
複数のマシンでアプリケーションを共有‣ 送信側: testApp.cpp
![Page 44: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/44.jpg)
#pragma once #include "ofMain.h" !class Ring { public: Ring(ofPoint pos); void update(); void draw(); ofPoint pos; float radius; float radiusSpeed; bool dead; };
複数のマシンでアプリケーションを共有‣ 送信側: Ring.h
![Page 45: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/45.jpg)
#include "Ring.h" !Ring::Ring(ofPoint _pos){ pos = _pos; radius = 0; radiusSpeed = 0.5; dead = false; } void Ring::update(){ radius += radiusSpeed; if (radius > ofGetWidth()){ dead = true; } } void Ring::draw(){ ofSetCircleResolution(64); ofEnableBlendMode(OF_BLENDMODE_ADD); ofEnableSmoothing(); ofSetLineWidth(1); ofPushMatrix(); ofTranslate(pos.x, pos.y); ofNoFill(); ofSetColor(63, 127, 255, 127 - radius * 127 / ofGetHeight()); ofCircle(0, 0, radius); ofFill(); ofSetColor(63, 127, 255, 31 - radius * 31 / ofGetHeight()); ofCircle(0, 0, radius); ofPopMatrix();
複数のマシンでアプリケーションを共有‣ 送信側: Ring.cpp
![Page 46: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/46.jpg)
#pragma once !#include "ofMain.h" #include "ofxOsc.h" #include "Ring.h" !//ポート番号を設定 #define PORT 8000 !class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void dumpOSC(ofxOscMessage m); ofxOscReceiver receiver; ofPoint remoteMouse; string mouseButtonState; string oscString; vector <Ring *> rings; // 拡大する輪"Ring"の配列 };
複数のマシンでアプリケーションを共有‣ 受信側: testApp.h
![Page 47: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/47.jpg)
#include "testApp.h" !void testApp::setup(){ //指定したポートで接続 receiver.setup( PORT ); ofSetFrameRate(60); //値を初期化 mouseX = 0; mouseY = 0; mouseButtonState = ""; ofBackground(0, 0, 0); } !void testApp::update(){ //現在順番待ちのOSCメッセージがあるか確認 while(receiver.hasWaitingMessages()){ //次のメッセージを取得 ofxOscMessage m; oscString = m.getAddress(); receiver.getNextMessage(&m); ! //マウスの位置を取得 if(m.getAddress() == "/mouse/position"){ remoteMouse.x = m.getArgAsInt32(0); remoteMouse.y = m.getArgAsInt32(1);
複数のマシンでアプリケーションを共有‣ 受信側: testApp.cpp
![Page 48: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/48.jpg)
! //マウスボタンの状態を取得 else if (m.getAddress() == "/mouse/button") { mouseButtonState = m.getArgAsString(0) ; } //OSCメッセージをそのままコンソールに出力 dumpOSC(m); } //マウスアップされたら、新規にRingを追加 if(mouseButtonState == "up"){ rings.push_back(new Ring(ofPoint(remoteMouse.x, remoteMouse.y))); mouseButtonState = ""; } //Ring更新 for(vector <Ring *>::iterator it = rings.begin(); it != rings.end();){ (*it)->update(); if ((*it)->dead) { delete (*it); it = rings.erase(it); } else { ++it; } }
複数のマシンでアプリケーションを共有‣ 受信側: testApp.cpp
![Page 49: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/49.jpg)
void testApp::draw(){ //Ringを描画 for(vector <Ring *>::iterator it = rings.begin(); it != rings.end(); ++it){ (*it)->draw(); } } !//OSCメッセージをコンソールに出力する関数 void testApp::dumpOSC(ofxOscMessage m) { string msg_string; msg_string = m.getAddress(); for (int i=0; i<m.getNumArgs(); i++ ) { msg_string += " "; if(m.getArgType(i) == OFXOSC_TYPE_INT32) msg_string += ofToString( m.getArgAsInt32(i)); else if(m.getArgType(i) == OFXOSC_TYPE_FLOAT) msg_string += ofToString( m.getArgAsFloat(i)); else if(m.getArgType(i) == OFXOSC_TYPE_STRING) msg_string += m.getArgAsString(i); } cout << msg_string << endl; }
複数のマシンでアプリケーションを共有‣ 受信側: testApp.cpp
![Page 50: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/50.jpg)
複数のPCでアプリケーションを共有‣ 複数のPCから1台のアプリに波紋を追加!!
![Page 51: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/51.jpg)
reacTIVision + ofxTUIO で タンジブルなインタフェイスを作る
![Page 52: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/52.jpg)
reacTIVisionでタンジブルなインタフェイス‣ OSCを使用した、より実践的なプロジェクトの例 ‣ reacTIVisionを使用して、タンジブル(Tangible)なユーザインタフェイスを作成してみる
‣ 様々な作品に応用可能なのでは?
![Page 53: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/53.jpg)
reacTIVisionでタンジブルなインタフェイス‣ タンジブル(Tangible)ユーザインタフェイスとは? ‣ 形のない情報を直接触れることができる(タンジブル)ように ‣ MITの石井裕教授が提唱 !
‣ 参考: MIT Media Lab, Tangible Media Group ‣ http://tangible.media.mit.edu/
![Page 54: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/54.jpg)
reacTIVisionでタンジブルなインタフェイス‣ タンジブルな作品の例 ‣ musicBottles ‣ http://tangible.media.mit.edu/project/musicbottles/
![Page 55: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/55.jpg)
reacTIVisionでタンジブルなインタフェイス‣ reacTIVIsion ‣ タンジブル(Tangible)なユーザインタフェイスを実現するための、オープンソースのツールキット
‣ http://reactivision.sourceforge.net/
![Page 56: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/56.jpg)
reacTIVisionでタンジブルなインタフェイス‣ reacTivisionを活用したプロジェクト ‣ Reactable http://www.reactable.com/
![Page 57: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/57.jpg)
reacTIVisionでタンジブルなインタフェイス‣ reacTIVIsionは、 fiducial markerという独特なパターンのマーカーを光学的に読み込んで解析する
‣ 複数のマーカーの位置だけでなく、角度も検出可能
![Page 58: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/58.jpg)
reacTIVisionでタンジブルなインタフェイス‣ reacTIVIsionのシステムの概要 ‣ マーカーを読み取った情報を、TUIOというプロトコルで送信
![Page 59: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/59.jpg)
reacTIVisionでタンジブルなインタフェイス‣ TUIO - タンジブルなマルチタッチなインタフェイスのためのオープンな通信プロトコル
‣ OpenSoundControlのプロトコルをベースにして拡張 ‣ 参考: http://www.tuio.org/
![Page 60: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/60.jpg)
reacTIVisionのセットアップ‣ まずは、マーカーを読み取る、reacTIVIsionをセットアップ ‣ reacTIVisionのWebサイトのreacTIVision filesから、最新のreacTIVison vision engineをダウンロード
‣ http://reactivision.sourceforge.net/
![Page 61: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/61.jpg)
reacTIVisionのセットアップ‣ reacTIVisionのためのfiducial markerを印刷 ‣ reacTIVision-1.4 > symbols > default.pdf ‣ マーカーをひとつずつ切り抜く
![Page 62: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/62.jpg)
reacTIVisionのセットアップ‣ reacTIVision.appを起動 ‣ reacTIVision-1.4 > reacTIVision.app
![Page 63: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/63.jpg)
reacTIVisionのセットアップ‣ マーカーをかざすと、中心位置を検出 ‣ 複数でもOK
![Page 64: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/64.jpg)
reacTIVisionをopenFrameworksで使用‣ reacTIVisionで検出されたマーカーの情報を、openFrameworksで利用する
‣ TUIOの解析には、ofxTuioを利用する ‣ https://github.com/patriciogonzalezvivo/ofxTuio
![Page 65: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/65.jpg)
マーカーの位置を認識する‣ まず初めに認識したマーカーの位置と角度とIDを表示するだけの簡単なプログラムを作成
‣ このプログラムがofxTUIOを用いたアプリケーションのテンプレートとなる
![Page 66: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/66.jpg)
#pragma once !#include "ofMain.h" #include "ofxTuio.h" !class testApp : public ofSimpleApp{ public: void setup(); void update(); void draw(); // --- TUIOの物体(マーカー)に関係するイベントを追加 --- // 物体の追加を検知 void objectAdded(ofxTuioObject & tuioObject); // 物体の削除を検知 void objectRemoved(ofxTuioObject & tuioObject); // 物体の状態の更新を検知 void objectUpdated(ofxTuioObject & tuioObject);
マーカーの位置を認識する‣ testApp.h
![Page 67: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/67.jpg)
// ---TUIOのカーソル(タッチポイントなど)に関係するイベント--- // カーソルの追加を検知 void tuioAdded(ofxTuioCursor & tuioCursor); // カーソルの削除を検知 void tuioRemoved(ofxTuioCursor & tuioCursor); // カーソルの状態の更新を検知 void tuioUpdated(ofxTuioCursor & tuioCursor); //TUIOのクライアントのインスタンス化 ofxTuioClient tuio; //ログの出力用 string log; };
マーカーの位置を認識する‣ testApp.h
![Page 68: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/68.jpg)
#include "testApp.h" !void testApp::setup(){ //TUIOに関連するイベントリスナーの追加 ofAddListener(tuio.objectAdded,this,&testApp::objectAdded); ofAddListener(tuio.objectRemoved,this,&testApp::objectRemoved); ofAddListener(tuio.objectUpdated,this,&testApp::objectUpdated); ofAddListener(tuio.cursorAdded,this,&testApp::tuioAdded); ofAddListener(tuio.cursorRemoved,this,&testApp::tuioRemoved); ofAddListener(tuio.cursorUpdated,this,&testApp::tuioUpdated); //フレームレート設定 ofSetFrameRate(60); //背景を黒に ofBackground(0); //ポート番号3333で、TUIOの通信開始 tuio.start(3333); //ログのテキストを空に log=""; } !void testApp::update(){ //TUIOのメッセージを受信 tuio.getMessage();
マーカーの位置を認識する‣ testApp.cpp
![Page 69: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/69.jpg)
void testApp::draw(){ //カーソルの状態を表示 tuio.drawCursors(); //オブジェクトの状態を表示 tuio.drawObjects(); //ログを表示 ofSetColor(255); ofDrawBitmapString(log, 20, 20); } !void testApp::objectAdded(ofxTuioObject & tuioObject){ // マーカー追加 log = " new object: " + ofToString(tuioObject.getFiducialId())+ " X: "+ofToString(tuioObject.getX())+ " Y: "+ofToString(tuioObject.getY())+ " angle: "+ofToString(tuioObject.getAngleDegrees()); } !void testApp::objectRemoved(ofxTuioObject & tuioObject){ // マーカー削除 log = " object removed: " + ofToString(tuioObject.getFiducialId())+ " X: "+ofToString(tuioObject.getX())+ " Y: "+ofToString(tuioObject.getY())+ " angle: "+ofToString(tuioObject.getAngleDegrees()); }
マーカーの位置を認識する‣ testApp.cpp
![Page 70: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/70.jpg)
!void testApp::objectUpdated(ofxTuioObject & tuioObject){ // マーカーの状態更新 log = " object updated: " + ofToString(tuioObject.getFiducialId())+ " X: "+ofToString(tuioObject.getX())+ " Y: "+ofToString(tuioObject.getY())+ " angle: "+ofToString(tuioObject.getAngleDegrees()); } void testApp::tuioAdded(ofxTuioCursor & tuioCursor){ // カーソル追加 log = " new cursor: " + ofToString(tuioCursor.getFingerId())+ " X: "+ofToString(tuioCursor.getX())+ " Y: "+ofToString(tuioCursor.getY()); } void testApp::tuioRemoved(ofxTuioCursor & tuioCursor){ // カーソル削除 log = " cursor removed: " + ofToString(tuioCursor.getFingerId())+ " X: "+ofToString(tuioCursor.getX())+ " Y: "+ofToString(tuioCursor.getY()); } void testApp::tuioUpdated(ofxTuioCursor & tuioCursor){ // カーソル状態更新 log = " cursor updated: " + ofToString(tuioCursor.getFingerId())+ " X: "+ofToString(tuioCursor.getX())+ " Y: "+ofToString(tuioCursor.getY()); }
マーカーの位置を認識する‣ testApp.cpp
![Page 71: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/71.jpg)
マーカーの位置を認識する‣ 複数のマーカーの位置と角度を検出
![Page 72: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/72.jpg)
オリジナルなマーカーを描画する‣ tuio.drawObjects()を利用してマーカーの状態を描画 ‣ この表示はあくまで状態の確認用 ‣ 実際に作品を制作する際には、マーカーの状態(ID、座標、角度)にアクセスして、オリジナルの表現方法で描画する必要 !
![Page 73: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/73.jpg)
オリジナルなマーカーを描画する‣ tuio.getTuioObjects() メソッドを実行すると、全てのオブジェクトのリストを取得可能
‣ データの形式は、ofxTuioObjectのポインタ型を格納したlistという形式
‣ list - vectorとよく似た動的な配列型 ‣ vectorと違って、listはその配列内の要素にアクセスする際には必ずイテレータ(iterator)を用いなければならない
![Page 74: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/74.jpg)
//オブジェクトのリストを取得 list<ofxTuioObject*> objectList = tuio.getTuioObjects(); //リスト操作のためのイテレータを準備 list<ofxTuioObject*>::iterator tobj; !//全てのオブジェクトをイテレータで操作 for (tobj=objectList.begin(); tobj != objectList.end(); tobj++) { //物体を取得 ofxTuioObject *blob = (*tobj); //座標を記録 glPushMatrix(); //座標を移動 glTranslatef(blob->getX()*ofGetWidth(), blob->getY()*ofGetHeight(), 0.0); //ID番号を表示 ofDrawBitmapString("id = " + ofToString(blob->getFiducialId(), 0), -64, 80); //回転 glRotatef(blob->getAngleDegrees(), 0.0, 0.0, 1.0); ofSetColor(255, 255, 255); //画像を描画 myImage.draw(-64, -64); //座標を復帰 glPopMatrix(); }
オリジナルなマーカーを描画する‣ ofxTuioObjectのlistからマーカーの位置を取得する例
![Page 75: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/75.jpg)
オリジナルなマーカーを描画する‣ マーカーの位置に、読み込んだ画像を配置してみる ‣ 位置だけでなく、検出した角度で画像を回転
![Page 76: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/76.jpg)
#pragma once !#include "ofMain.h" #include "ofxTuio.h" !class testApp : public ofSimpleApp{ public: void setup(); void update(); void draw(); //TUIOの物体(マーカー)に関係するイベントを追加 //物体の追加を検知 void objectAdded(ofxTuioObject & tuioObject); //物体の削除を検知 void objectRemoved(ofxTuioObject & tuioObject); //物体の状態の更新を検知 void objectUpdated(ofxTuioObject & tuioObject); //TUIOのカーソル(タッチポイントなど)に関係するイベント //カーソルの追加を検知 void tuioAdded(ofxTuioCursor & tuioCursor); //カーソルの削除を検知 void tuioRemoved(ofxTuioCursor & tuioCursor); //カーソルの状態の更新を検知
オリジナルなマーカーを描画する‣ testApp.h
![Page 77: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/77.jpg)
//TUIOのクライアントのインスタンス化 ofxTuioClient tuio; //ログの出力用 string log; //表示する画像 ofImage myImage; };
オリジナルなマーカーを描画する‣ testApp.h
![Page 78: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/78.jpg)
#include "testApp.h" !void testApp::setup(){ //TUIOに関連するイベントリスナーの追加 ofAddListener(tuio.objectAdded,this,&testApp::objectAdded); ofAddListener(tuio.objectRemoved,this,&testApp::objectRemoved); ofAddListener(tuio.objectUpdated,this,&testApp::objectUpdated); ofAddListener(tuio.cursorAdded,this,&testApp::tuioAdded); ofAddListener(tuio.cursorRemoved,this,&testApp::tuioRemoved); ofAddListener(tuio.cursorUpdated,this,&testApp::tuioUpdated); //フレームレート設定 ofSetFrameRate(60); //背景を黒に ofBackground(0,0,0); //ポート番号3333で、TUIOの通信開始 tuio.start(3333); //ログのテキストを空に log=""; //画像ファイルを読み込み myImage.loadImage("images/photo.png"); } !void testApp::update(){ //TUIOのメッセージを受信
オリジナルなマーカーを描画する‣ testApp.cpp
![Page 79: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/79.jpg)
void testApp::draw(){ //オブジェクトのリストを取得 list<ofxTuioObject*> objectList = tuio.getTuioObjects(); ! //リスト操作のためのイテレータを準備 list<ofxTuioObject*>::iterator it; ! //全てのオブジェクトをイテレータで操作 for (it = objectList.begin(); it != objectList.end(); it ++) { //物体を取得 ofxTuioObject *blob = (*it); //座標を記録 glPushMatrix(); //座標を移動 glTranslatef(blob->getX()*ofGetWidth(), blob->getY()*ofGetHeight(), 0.0); //ID番号を表示 ofDrawBitmapString("id = " + ofToString(blob->getFiducialId(), 0), -64, 80); //回転 glRotatef(blob->getAngleDegrees(), 0.0, 0.0, 1.0); ofSetColor(255, 255, 255); //画像を描画 myImage.draw(-64, -64); //座標を復帰 glPopMatrix();
オリジナルなマーカーを描画する‣ testApp.cpp
![Page 80: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/80.jpg)
//ログを表示 ofSetColor(0xffffff); ofDrawBitmapString(log, 20, 20); } !void testApp::objectAdded(ofxTuioObject & tuioObject){ //マーカー追加 log = " new object: " + ofToString(tuioObject.getFiducialId())+ " X: "+ofToString(tuioObject.getX())+ " Y: "+ofToString(tuioObject.getY())+ " angle: "+ofToString(tuioObject.getAngleDegrees()); } void testApp::objectRemoved(ofxTuioObject & tuioObject){ //マーカー削除 log = " object removed: " + ofToString(tuioObject.getFiducialId())+ " X: "+ofToString(tuioObject.getX())+ " Y: "+ofToString(tuioObject.getY())+ " angle: "+ofToString(tuioObject.getAngleDegrees()); } void testApp::objectUpdated(ofxTuioObject & tuioObject){ //マーカーの状態更新 log = " object updated: " + ofToString(tuioObject.getFiducialId())+ " X: "+ofToString(tuioObject.getX())+ " Y: "+ofToString(tuioObject.getY())+ " angle: "+ofToString(tuioObject.getAngleDegrees());
オリジナルなマーカーを描画する‣ testApp.cpp
![Page 81: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/81.jpg)
void testApp::tuioAdded(ofxTuioCursor & tuioCursor){ //カーソル追加 log = " new cursor: " + ofToString(tuioCursor.getFingerId())+ " X: "+ofToString(tuioCursor.getX())+ " Y: "+ofToString(tuioCursor.getY()); } void testApp::tuioRemoved(ofxTuioCursor & tuioCursor){ //カーソル削除 log = " cursor removed: " + ofToString(tuioCursor.getFingerId())+ " X: "+ofToString(tuioCursor.getX())+ " Y: "+ofToString(tuioCursor.getY()); } void testApp::tuioUpdated(ofxTuioCursor & tuioCursor){ //カーソル状態更新 log = " cursor updated: " + ofToString(tuioCursor.getFingerId())+ " X: "+ofToString(tuioCursor.getX())+ " Y: "+ofToString(tuioCursor.getY()); }
オリジナルなマーカーを描画する‣ testApp.cpp
![Page 82: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/82.jpg)
タンジブル・サウンドプレーヤー‣ 応用例として、マーカーの位置や角度によって複数の音を同時再生するタンジブル・サウンドプレーヤーを作ってみる !
‣ 5つのofSoundPlayerを準備して、それぞれにサウンドファイルを読み込み !
‣ マーカーのX座標を音の左右の定位に ‣ マーカーのY座標をオーディオの再生スピード ‣ マーカーの角度でサウンドのボリュームが変化するように
![Page 83: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/83.jpg)
#pragma once !#include "ofMain.h" #include "ofxTuio.h" !#define NUM 5 !class testApp : public ofSimpleApp{ public: void setup(); void update(); void draw(); void objectAdded(ofxTuioObject & tuioObject); void objectRemoved(ofxTuioObject & tuioObject); void objectUpdated(ofxTuioObject & tuioObject); void tuioAdded(ofxTuioCursor & tuioCursor); void tuioRemoved(ofxTuioCursor & tuioCursor); void tuioUpdated(ofxTuioCursor & tuioCursor); ofxTuioClient tuio; string log; ofSoundPlayer mySounds[NUM]; };
タンジブル・サウンドプレーヤー‣ testApp.h
![Page 84: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/84.jpg)
#include "testApp.h" !void testApp::setup(){ //イベントリスナーの追加 ofAddListener(tuio.objectAdded,this,&testApp::objectAdded); ofAddListener(tuio.objectRemoved,this,&testApp::objectRemoved); ofAddListener(tuio.objectUpdated,this,&testApp::objectUpdated); ofAddListener(tuio.cursorAdded,this,&testApp::tuioAdded); ofAddListener(tuio.cursorRemoved,this,&testApp::tuioRemoved); ofAddListener(tuio.cursorUpdated,this,&testApp::tuioUpdated); //画面の基本設定 ofBackground(0,0,0); ofSetFrameRate(60); ofSetCircleResolution(32); ofEnableAlphaBlending(); ofSetVerticalSync(true); ofEnableSmoothing(); //サウンドファイルの読み込み for (int i = 0; i < NUM; i++) { mySounds[i].loadSound("sounds/rainstick.aif"); mySounds[i].setLoop(true); } //TUIO通信開始、ポート3333
タンジブル・サウンドプレーヤー‣ testApp.cpp
![Page 85: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/85.jpg)
void testApp::update(){ //TUIOメッセージの受信 tuio.getMessage(); ! //オブジェクトのリストを取得 list<ofxTuioObject*> objectList = tuio.getTuioObjects(); //イテレータの準備 list<ofxTuioObject*>::iterator it; //表示されている物体の数だけくりかえし for (it = objectList.begin(); it != objectList.end(); it++) { //個別の物体を取り出し ofxTuioObject *blob = (*it); //IDを抽出 int id = blob->getFiducialId(); //サウンドが設定されたIDの範囲なら if (id >= 0 && id < NUM) { //X座標を左右の定位に適用 mySounds[id].setPan(blob->getX()); //Y座標を再生スピードの適用 mySounds[id].setSpeed((1.0f - blob->getY()) * 2.0); //角度をサウンドのボリュームに適用 mySounds[id].setVolume(blob->getAngleDegrees()/360.0); } }
タンジブル・サウンドプレーヤー‣ testApp.cpp
![Page 86: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/86.jpg)
void testApp::draw(){ //オリジナルの図形を描画 //半径を20に float radius = 20; //オブジェクトのリストを取得 list<ofxTuioObject*> objectList = tuio.getTuioObjects(); //イテレータの準備 list<ofxTuioObject*>::iterator tobj; //表示されている物体の数だけくりかえし for (tobj=objectList.begin(); tobj != objectList.end(); tobj++) { //個別の物体を取り出し ofxTuioObject *blob = (*tobj); //オリジナルの物体を描画 glPushMatrix(); glTranslatef(blob->getX()*ofGetWidth(), blob->getY()*ofGetHeight(), 0.0); glRotatef(blob->getAngleDegrees(), 0.0, 0.0, 1.0); ofFill(); ofSetColor(0, 0, 255, 127); //サウンドのレベルによって半径を変化させて青い円を描く float* spectrum; spectrum = ofSoundGetSpectrum(1); ofCircle(0, 0, spectrum[0] * radius * 100.0); ofSetColor(255, 255, 255); ofNoFill(); ofCircle(0, 0, radius);
タンジブル・サウンドプレーヤー‣ testApp.cpp
![Page 87: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/87.jpg)
! glPopMatrix(); } //ログを表示 ofSetColor(0xffffff); ofDrawBitmapString(log, 20, 20); } !void testApp::objectAdded(ofxTuioObject & tuioObject){ int id = tuioObject.getFiducialId(); if (id >= 0 && id < NUM) { mySounds[tuioObject.getFiducialId()].play(); } //マーカー追加 log = " new object: " + ofToString(tuioObject.getFiducialId())+ " X: "+ofToString(tuioObject.getX())+ " Y: "+ofToString(tuioObject.getY())+ " angle: "+ofToString(tuioObject.getAngleDegrees()); } void testApp::objectRemoved(ofxTuioObject & tuioObject){ int id = tuioObject.getFiducialId(); if (id >= 0 && id < NUM) { mySounds[tuioObject.getFiducialId()].stop(); }
タンジブル・サウンドプレーヤー‣ testApp.cpp
![Page 88: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/88.jpg)
//マーカー削除 log = " object removed: " + ofToString(tuioObject.getFiducialId())+ " X: "+ofToString(tuioObject.getX())+ " Y: "+ofToString(tuioObject.getY())+ " angle: "+ofToString(tuioObject.getAngleDegrees()); } void testApp::objectUpdated(ofxTuioObject & tuioObject){ //マーカーの状態更新 log = " object updated: " + ofToString(tuioObject.getFiducialId())+ " X: "+ofToString(tuioObject.getX())+ " Y: "+ofToString(tuioObject.getY())+ " angle: "+ofToString(tuioObject.getAngleDegrees()); } void testApp::tuioAdded(ofxTuioCursor & tuioCursor){ //カーソル追加 log = " new cursor: " + ofToString(tuioCursor.getFingerId())+ " X: "+ofToString(tuioCursor.getX())+ " Y: "+ofToString(tuioCursor.getY()); } void testApp::tuioRemoved(ofxTuioCursor & tuioCursor){ //カーソル削除 log = " cursor removed: " + ofToString(tuioCursor.getFingerId())+ " X: "+ofToString(tuioCursor.getX())+ " Y: "+ofToString(tuioCursor.getY()); }
タンジブル・サウンドプレーヤー‣ testApp.cpp
![Page 89: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/89.jpg)
void testApp::tuioUpdated(ofxTuioCursor & tuioCursor){ //カーソル状態更新 log = " cursor updated: " + ofToString(tuioCursor.getFingerId())+ " X: "+ofToString(tuioCursor.getX())+ " Y: "+ofToString(tuioCursor.getY()); }
タンジブル・サウンドプレーヤー‣ testApp.cpp
![Page 90: Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス](https://reader034.fdocument.pub/reader034/viewer/2022042813/54c305884a7959ca778b46ca/html5/thumbnails/90.jpg)
タンジブル・サウンドプレーヤー‣ 完成!!