oFで純正マルチタッチ

2010.12.13 月曜日

Mac版openFrameworksで純正マルチタッチ入力を取得する方法について。

デバイスを一つしか使わない(MacBookのトラックパッドやiMacにMagicTrackpad)場合はopenFrameworks.jp forum 「MacBookProのトラックパッドでマルチタッチ」のサンプルとかリンク先を見てください。

ここではすでにトラックパッドが搭載されているMacBookにMagicTrackpadをつないでMagicTrackpad側を認識したい場合、など複数のデバイスを混在させoFで認識させる方法について書きます。基本は上のサンプルとほとんど同じで、デバイスの取得で使う関数がObjective-Cで動作させる必要があるので少し変更が必要です。下記コードの変更は24行目と78~82行目の部分がメイン。

まず、oFのemptyExampleをコピーして、addonsの「ofxVectorMath」とフレームワークの「MultitouchSupport.framework」を読み込みます。次に「testApp.cpp」を「testApp.mm」に名称変更し、右クリック>情報を見る>ファイルタイプで「sourcecode.cpp.cpp」を「sourcecode.cpp.objcpp」に変更します。そしてtestApp.mmには以下のコード。

#include "testApp.h"
#include "ofxVectorMath.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:
	ofxVec2f pos;
	float size;
	int id;
	bool enable;
	float phase;
	float freq, amp;
	float trem_phase;
};

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;
	}
	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();
}

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 * ofGetWidth();
		float yy = t.pos.y * ofGetHeight();
		ofCircle(xx, yy, t.size * 50);

		ofDrawBitmapString(ofToString(t.freq, 1), xx, yy);
	}
}

void testApp::keyPressed(int key) {
}

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) {
}

Posted by tmdf|

trackback

http://tmdf.net/blog/20101213_of_multitouch.html/trackback

comments(0)

POST NEW COMMENT

  • name:*
  • e-mail:*

    The content of this field is kept private and will not be shown publicly.
  • website:
  • comment:*

    Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code>
    Lines and paragraphs break automatically.

Photo

PROFILE

森田 考陽 [Takaaki Morita]
Twitter: @tmdf
Other: mtdf.net

Designer / Programmer

RECENT POSTS

MONTHLY ARCHIVES