openFrameworksでマルチタッチしてみた (Mac only)
Mac純正のマルチタッチフレームワークであるMultitouchSupport.frameworkを使ってマルチタッチをしてみる
参考サイトは死んでるので、覚えてる範囲で...
必要なもの
- openFrameworks本体
- ofxVectorMath (Addon)
- MultitouchSupport.framework (/System/Library/PrivateFrameworks/にある)
- ofxOsc (任意)
手順
- ofxVectorMath、MultitouchSupport.frameworkとofxOscをXcodeのプロジェクトに入れる...ドラッグするだけ
こんな感じになる

- testApp.cppをtestApp.mmに変更する
※ 一応、ファイルタイプがObjective-C++ Sourceになってるか確認 - コードを書く
#pragma once
#include "ofMain.h"
#include "ofxOsc.h"
#define TUIOPORT 3333
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);
int width, height;
ofxOscSender send;
};
#include "testApp.h"
#include "ofVectorMath.h"
extern "C" {
typedef struct { float x,y; } mtPoint;
typedef struct { mtPoint pos,vel; } mtReadout;
typedef struct {
int frame;
double timestamp;
int identifier, state, foo3, foo4;
mtReadout normalized;
float size;
int zero1;
float angle, majorAxis, minorAxis;
mtReadout mm;
int zero2[2];
float unk2;
}
Finger;
typedef void *MTDeviceRef;
typedef int (*MTContactCallbackFunction)(int,Finger*,int,double,int);
CFMutableArrayRef MTDeviceCreateList(void);
void MTRegisterContactFrameCallback(MTDeviceRef, MTContactCallbackFunction);
void MTDeviceStart(MTDeviceRef, int);
}
class TouchPoint {
public:
ofVec2f pos;
ofVec2f vel;
float size;
int id;
bool enable;
float phase;
float freq, amp;
float trem_phase;
int stat;
};
vector<TouchPoint> touchPoints;
int mtCallback(int device, Finger *data, int nFingers, double timestamp, int frame) {
for (int i = 0; i < touchPoints.size(); i ++) {
touchPoints[i].enable = false;
}
for (int i=0; i<nFingers; i++) {
Finger *f = &data[i];
/*
printf("Frame %7d: Angle %6.2f, ellipse %6.3f x%6.3f; "
"position (%6.3f,%6.3f) vel (%6.3f,%6.3f) "
"ID %d, state %d [%d %d?] size %6.3f, %6.3f?n",
f->frame,
f->angle * 90 / atan2(1,0),
f->majorAxis,
f->minorAxis,
f->normalized.pos.x,
f->normalized.pos.y,
f->normalized.vel.x,
f->normalized.vel.y,
f->identifier, f->state, f->foo3, f->foo4,
f->size, f->unk2);
*/
TouchPoint &t = touchPoints[f->identifier];
t.pos.x = f->normalized.pos.x;
t.pos.y = 1 - f->normalized.pos.y;
t.size = f->size;
t.enable = true;
t.id = f->identifier;
t.vel.x = f->normalized.vel.x;
t.vel.y = f->normalized.vel.y;
t.stat = f->foo3;
}
return 0;
}
void testApp::setup() {
touchPoints.resize(20);
NSMutableArray* deviceList = (NSMutableArray*)MTDeviceCreateList();
for(int i = 0; i < [deviceList count]; i ++) {
MTRegisterContactFrameCallback([deviceList objectAtIndex:i], mtCallback);
MTDeviceStart([deviceList objectAtIndex:i], 0);
}
ofEnableSmoothing();
ofEnableAlphaBlending();
ofSetVerticalSync(true);
ofSetFrameRate(60);
ofHideCursor();
ofBackground(0, 0, 0);
ofSetColor(255, 255, 255);
ofNoFill();
width = ofGetWidth();
height = ofGetHeight();
send.setup("127.0.0.1", TUIOPORT);
}
void testApp::update() {
}
void testApp::draw() {
for (int i = 0; i < touchPoints.size(); i++)
{
TouchPoint &t = touchPoints[i];
if (t.enable == false) {
continue;
}
float xx = t.pos.x * width;
float yy = t.pos.y * height;
ofCircle(xx, yy, t.size * 50);
ofDrawBitmapString("x: " + ofToString(t.pos.x*width), xx-10, yy-15);
ofDrawBitmapString("y: " + ofToString(t.pos.y*height), xx-10, yy);
ofDrawBitmapString("ID :" + ofToString(t.id), xx-10, yy+15);
ofDrawBitmapString("ID :" + ofToString(t.id), xx-10, yy+15);
cout << t.stat << endl;
ofxOscMessage m;
m.setAddress("/tuio/2Dcur");
m.addStringArg("set");
m.addIntArg(t.id);
m.addFloatArg(t.pos.x);
m.addFloatArg(t.pos.y);
m.addFloatArg(t.vel.x);
m.addFloatArg(t.vel.y);
m.addFloatArg(t.vel.x * t.vel.y);
send.sendMessage(m);
}
}
void testApp::keyPressed(int key) {
if(key == 'f')
ofToggleFullscreen();
if (key == 'i') {
width = ofGetWidth();
height = ofGetHeight();
}
}
void testApp::keyReleased(int key) {
}
void testApp::mouseMoved(int x, int y){
}
void testApp::mouseDragged(int x, int y, int button) {
}
void testApp::mousePressed(int x, int y, int button) {
}
void testApp::mouseReleased(int x, int y, int button) {
}
void testApp::windowResized(int w, int h) {
}
これを実行すればこんな感じになるはず...
メンバ変数をPrivateにしてないのは(ry
oFの仕様なのか、ofGetWidth()とかはofToggleFullscreen()を実行しても更新されないようです