読者です 読者をやめる 読者になる 読者になる

ツタンラーメンの忘備録

プログラミングや精神疾患、ラーメンについて書いていきます。たぶん。

WindowsのopenFrameworksでLeap Motionを使えるようにする

手軽にまとまった記事がないのでここでまとめて記載する。

1. Visual C++で必要な処理
2. oFで必要な処理
の二点にわかれる。

1. VC++に関して
下記記事を参考
www.naturalsoftware.jp

2. oFに関して
下記記事を参照
gndo.blogspot.jp
Macの記事だけど基本的にoFと名前が被っているところをどうにかするだけ。
サンプルコードも

testApp::drawSphere(Vector vector, float radius) {
//を
ofApp::drawSphere(Vector vector, float radius) {
//に変える

だけです。簡単!

ただWindowsにまとまったサイトがなかったのでここを参照してくださいということで。
下記サンプルは実験するには冗長なので、軽く遊びたいだけなら上記サイトを見てください。


でサンプルコードと合わせて球を表示させつつなんかコンソールにむっちゃ表示させるようにした。

//ofApp.h
#pragma once

#include "ofMain.h"
#include "Leap.h"
using namespace Leap;
class ofApp : public ofBaseApp, public Listener{

	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 mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);

		// Leap Motionのコントローラー
		Controller leap;
		// カメラ
		ofCamera camera;
		// 球体の描画処理
		void drawSphere(Vector vector, float radius);


		//----- 一過性のイベントだけListnerから取得 ----------------------------//
		//----- フレームの処理はdraw()で行う -----------------------------------//
		void onConnect(const Controller&) {
			cout << __FUNCTION__ << endl;
		}

		void onDisconnect(const Controller&) {
			cout << __FUNCTION__ << endl;
		}

		void onFocusGained(const Controller&) {
			cout << __FUNCTION__ << endl;
		}

		void onFocusLost(const Controller&) {
			cout << __FUNCTION__ << endl;
		}

		void onServiceConnect(const Controller&) {
			cout << __FUNCTION__ << endl;
		}

		void onServiceDisconnect(const Controller&) {
			cout << __FUNCTION__ << endl;
		}
		//------------------------------------------------------------//
};
//ofApp.cpp
#include "ofApp.h"

const std::string fingerNames[] = { "Thumb", "Index", "Middle", "Ring", "Pinky" };
const std::string boneNames[] = { "Metacarpal", "Proximal", "Middle", "Distal" };
const std::string stateNames[] = { "STATE_INVALID", "STATE_START", "STATE_UPDATE", "STATE_END" };

//--------------------------------------------------------------
void ofApp::setup(){
	// カメラの初期位置と方向を指定
	camera.setFov(60);
	camera.setPosition(0, 200, ofGetWidth() / 3);
	camera.lookAt(ofVec3f(0, 200, 0));
	//ofSetFrameRate(1);
}

//--------------------------------------------------------------
void ofApp::update(){
	const Frame frame = leap.frame();
	std::cout << "Frame id: " << frame.id()
		<< ", timestamp: " << frame.timestamp()
		<< ", hands: " << frame.hands().count()
		<< ", extended fingers: " << frame.fingers().extended().count()
		<< ", tools: " << frame.tools().count()
		<< ", gestures: " << frame.gestures().count() << std::endl;

	HandList hands = frame.hands();
	for (HandList::const_iterator hl = hands.begin(); hl != hands.end(); ++hl) {
		// Get the first hand
		const Hand hand = *hl;
		std::string handType = hand.isLeft() ? "Left hand" : "Right hand";
		std::cout << std::string(2, ' ') << handType << ", id: " << hand.id()
			<< ", palm position: " << hand.palmPosition() << std::endl;
		// Get the hand's normal vector and direction
		const Vector normal = hand.palmNormal();
		const Vector direction = hand.direction();

		// Calculate the hand's pitch, roll, and yaw angles
		std::cout << std::string(2, ' ') << "pitch: " << direction.pitch() * RAD_TO_DEG << " degrees, "
			<< "roll: " << normal.roll() * RAD_TO_DEG << " degrees, "
			<< "yaw: " << direction.yaw() * RAD_TO_DEG << " degrees" << std::endl;

		// Get the Arm bone
		Arm arm = hand.arm();
		std::cout << std::string(2, ' ') << "Arm direction: " << arm.direction()
			<< " wrist position: " << arm.wristPosition()
			<< " elbow position: " << arm.elbowPosition() << std::endl;

		// Get fingers
		const FingerList fingers = hand.fingers();
		for (FingerList::const_iterator fl = fingers.begin(); fl != fingers.end(); ++fl) {
			const Finger finger = *fl;
			std::cout << std::string(4, ' ') << fingerNames[finger.type()]
				<< " finger, id: " << finger.id()
				<< ", length: " << finger.length()
				<< "mm, width: " << finger.width() << std::endl;

			// Get finger bones
			for (int b = 0; b < 4; ++b) {
				Bone::Type boneType = static_cast<Bone::Type>(b);
				Bone bone = finger.bone(boneType);
				std::cout << std::string(6, ' ') << boneNames[boneType]
					<< " bone, start: " << bone.prevJoint()
					<< ", end: " << bone.nextJoint()
					<< ", direction: " << bone.direction() << std::endl;
			}
		}
	}

	// Get tools
	const ToolList tools = frame.tools();
	for (ToolList::const_iterator tl = tools.begin(); tl != tools.end(); ++tl) {
		const Tool tool = *tl;
		std::cout << std::string(2, ' ') << "Tool, id: " << tool.id()
			<< ", position: " << tool.tipPosition()
			<< ", direction: " << tool.direction() << std::endl;
	}

	// Get gestures
	const GestureList gestures = frame.gestures();
	for (int g = 0; g < gestures.count(); ++g) {
		Gesture gesture = gestures[g];

		switch (gesture.type()) {
		case Gesture::TYPE_CIRCLE:
		{
			CircleGesture circle = gesture;
			std::string clockwiseness;

			if (circle.pointable().direction().angleTo(circle.normal()) <= PI / 2) {
				clockwiseness = "clockwise";
			}
			else {
				clockwiseness = "counterclockwise";
			}

			// Calculate angle swept since last frame
			float sweptAngle = 0;
			if (circle.state() != Gesture::STATE_START) {
				CircleGesture previousUpdate = CircleGesture(leap.frame(1).gesture(circle.id()));
				sweptAngle = (circle.progress() - previousUpdate.progress()) * 2 * PI;
			}
			std::cout << std::string(2, ' ')
				<< "Circle id: " << gesture.id()
				<< ", state: " << stateNames[gesture.state()]
				<< ", progress: " << circle.progress()
				<< ", radius: " << circle.radius()
				<< ", angle " << sweptAngle * RAD_TO_DEG
				<< ", " << clockwiseness << std::endl;
			break;
		}
		case Gesture::TYPE_SWIPE:
		{
			SwipeGesture swipe = gesture;
			std::cout << std::string(2, ' ')
				<< "Swipe id: " << gesture.id()
				<< ", state: " << stateNames[gesture.state()]
				<< ", direction: " << swipe.direction()
				<< ", speed: " << swipe.speed() << std::endl;
			break;
		}
		case Gesture::TYPE_KEY_TAP:
		{
			KeyTapGesture tap = gesture;
			std::cout << std::string(2, ' ')
				<< "Key Tap id: " << gesture.id()
				<< ", state: " << stateNames[gesture.state()]
				<< ", position: " << tap.position()
				<< ", direction: " << tap.direction() << std::endl;
			break;
		}
		case Gesture::TYPE_SCREEN_TAP:
		{
			ScreenTapGesture screentap = gesture;
			std::cout << std::string(2, ' ')
				<< "Screen Tap id: " << gesture.id()
				<< ", state: " << stateNames[gesture.state()]
				<< ", position: " << screentap.position()
				<< ", direction: " << screentap.direction() << std::endl;
			break;
		}
		default:
			std::cout << std::string(2, ' ') << "Unknown gesture type." << std::endl;
			break;
		}
	}

	if (!frame.hands().isEmpty() || !gestures.isEmpty()) {
		std::cout << std::endl;
	}
}

//--------------------------------------------------------------
void ofApp::draw(){
	camera.begin();
	// 背景を黒に塗りつぶし
	ofBackground(0, 0, 0);
	// フレームを取得
	Frame frame = leap.frame();
	// Handをあるだけ列挙
	for (int i = 0; i<frame.hands().count(); i++) {
		Hand hand = frame.hands()[i];
		// てのひらの位置に球体を描画
		drawSphere(hand.palmPosition(), 20);
		// Hand内のFingerをあるだけ描画
		for (int j = 0; j<hand.fingers().count(); j++) {
			Finger finger = frame.fingers()[j];
			drawSphere(finger.tipPosition(), 8);
			//drawSphere(finger.jointPosition(), 2);
		}
	}
	camera.end();
}

void ofApp::drawSphere(Vector vector, float radius) {
	// 球体の描画処理    
	ofNoFill();
	ofPushMatrix();
	ofPoint point = ofPoint(vector.x, vector.y, vector.z);
	ofTranslate(point);
	ofRotateX(point.x);
	ofRotateY(point.y);
	ofRotateZ(point.z);
	ofSetColor(0xCC, 0, 0, 255);
	ofSphere(radius);
	ofPopMatrix();
}

コメントもそのまま残っていて草はえますね。
これを描くとコンソールにむっちゃ言葉が出てきて追いきれません。位置とかを送ってそうですね(雑な理解)