第 3 章アプリケーションの開発 ・すべてのイベントの動作を見るプログラム #include "Leap . h" class SampleListener publ i ( : public Leap: :Listener VOid onlnit(const Leap: :controller& controller) FUNCTION std: :cout くく VOid onconnect(const Leap: :controller&) std: :cout くく くく std: :endl ; FUNCT 工 ON— . くく std: :endl ; VOid onFrame(const Leap: :controller&) std: •.COUt くく FUNCTION—くく std: :endl ; VOid onExit(const Leap: :controller&) std: :cout くく FUNCT 工 ON—くく std: :endl ; VOid onDisconnect(const Leap: :controller&) //std: :cout くく FUNCTION—くく std: :endl ; VOid onFocusGained(const Leap: :controller&) std: :cout くく FUNCTION 80 くく std: :endl ;
[ 3-3 ] イベント駆動でデータを取得 (Leap::Listener クラス ) くく std: :endl ; 1 VOid onserviceconnect(const Leap: :controller&) std: •.COUt くく FUNCTION—くく std: :endl ; VOid onFocusLOSt(const Leap: :controller&) std: :cout くく FUNCTION—くく std: :endl ; VOid onServiceDisconnect(const Leap: std: :cout くく FUNCTION. -ーくく std: :endl ; :controller&) VOid onDevicechange(const Leap: :controller& controller) std: :cout くく—FUNCTION—くく std: :endl ; leap. removeListener( listener ) ; std::cin . get(); std: :cout くく " 終了するには何かキーを押してください " leap. addListener( listener ) ; Leap: :controller leap; SampleListener listener; / / リスナーとのやり取りは別スレッドにて行われる / / リスナーを登録する void main()
[ 3-1 ] 「 Leap Motion SDK 」の概要 くく std: :endl ; 次のコードは、イベント駆動で「 Leap Motion 」のフレームデータを取得する最小 イベント駆動方式の最初のコード / / フレームの更新イベント publ i c : class SampIeListener : public Leap: :Listener / / イベントを受け取るためのクラス #include "Leap.h" ・イベント駆動のプログラム のプログラムです。 VOid onFrame(const Leap: :controller& controller ) Leap: : Frame frame controller. frame() ; leap. removeListener( listener ) ; std::cin.get(); std: :cout くく " 終了するには何かキーを押してください " leap . addListener( listener ) ; Leap: :controller leap; sampleListener listener; / / リスナーとのやり取りは別スレッドにて行われる / / リスナーを登録する voi d mai n ( ) std: :cout くく frame.id() くく std: :endl ; 65
第 3 章アプリケーションの開発 std: FUNCT 工 ON_ くく std : : endl ; :cout くく void mai n ( ) / / リスナーを登録する / / リスナーとのやり取りは別スレッドにて行われる SampleListener listener; Leap: :Contr011er leap; leap. addListener( listener ) ; 〃 1 eap. setP01 i cyFIags( Leap : :control 1 er : : P01 i cyFlag : : POLICY-BACKGROUND-FRAMES ) ; std: :cout くく " 終了するには何かキーを押してください " くく std: :endl ; std::cin . get(); leap. removeListener( listener ) ; [ プログラム解説 ] 「 setPoIicyFIags() 」はコメント化しているので、デフォルトのポリシーが適用され ま このプログラムを実行し、アプリケーションのウインドウを最前面にすると「 onFra me() 」が継続的に発生します。 別のウインドウ ( たとえば「エクスプローラ」や「 Finder 」 ) を最前面にすると、「 on FocusLost() 」が呼び出され、「 onFrame() 」が止まります。 ノヾックグラウンドになったので、「 Leap Motion 」からのデータが通知されなくなりま 再度アプリケーションのウインドウを最前面にすると、「 onFocusGained() 」が呼ば れ、「 onFrame() 」の呼び出しが再開されます。
第 4 章サンプルアプリを作る 1 void setDiffuseCOIor( ci : :COIorA diffusecolor ) gl : : C010r ( diffusecolor ) ; g1Lightfv( GL—LIGHTO , GL—DIFFUSE, diffusecolor ) ; / / Leap SDK の vector を cinder の vec3f に変換する vec3f tovec3f( Leap: :vector vec ) return Vec3f( vec. x, vec . y, vec . z ) ; pri vate : b001 mIs3D; / / Leap MOti on Leap: :ControlIer mLeap; Leap: : Frame mCurrentFrame; / / 描画用の座標 std: :vector<std: :vector<Leap: :vector>> mcompletestrokes; std: :map く int, std: :vector<Leap: :vector>> mcurrentstrokes; std: :vector く Leap: :vector> mpointablepoints; プログラム解説 ・基本的な流れ 処理の流れとしては、「 PointabIe オプジェクト」から得られる座標を保存しておき、 表示します。 座標は、 ID ごとに複数取れるため、現在書き込み中の軌跡と、書き込みが終了 した軌跡をそれぞれ持っことにします。 184
第 3 章アプリケーションの開発 ・両方式を組み合わせたプログラム class P011ingApp : public AppNative, public : void setupC) mLeap. addListener( *this ) ; void draw() gl : : cl ear ( C01 or ( 0 , 0 , 0 ) ) ; publ i ( Leap : :Listener { Leap: : Frame frame = mLeap. frame() ; console() くく frame . id() くく std: :endl ; VOid onconnect(const Leap: :controller&) console() くく "connect! ! " くく std: :endl ; console() くく "Disconnect! ! " VOid onDisconnect(const Leap: :controller&) くく std: :endl ; Leap: :Contr011er mLeap; 70
[ 3-2 ] 「 Leap M0tion 」はじめの一歩 (Leap::Contr011er クラス ) ・「動作ボリシー」の設定、取得 73 VOid onFocusLost(const Leap: :controller&) FUNCT 工 ON std: :cout くく くく std: :endl ; VOid onFocusGained(const Leap: :controller&) std: •.COUt くく FUNCTION— < く std: :endl ; VOid onFrame(const Leap: :controller&) publi ( : class SampleListener : public Leap: :Listener #include "Leap. h" この動作の違いを見るための最小のコードが、次のものです。 現在のポリシーの状態は「 policyFIags() 」で取得できます。 yFlags() 」で「 POLICY—BACKGROUND_FRAMES ポリシー」を設定します。 バックグラウンドでも「 Leap Motion 」のデータを取得したい場合には、「 setpolic ではデータの取得はできません。 データを受け取ることができ、「ノヾックグラウンド」 ( ほかのウインドウが最前面 ) の状態 グラウンド」 ( アプリケーションのウインドウが最前面 ) の状態のみ「 Leap Motion 」の 「 POLICY_DEFAULT 」は、デフォルトのポリシーで、アプリケーションは「フォア ・ POL ℃ Y BACKGROUND_FRAMES ・ POL ℃ Y_DEFAULT ます。 「動作ポリシー」は、「 PolicyFlag 列挙体」で定義され、現在は次の 2 種類があり アプリケーションの「動作ポリシー」を設定し、取得します。
第 3 章 アプリケーションの開発 これは手間になるので、「イベント駆動方式」を組み合わせて、イベントも取得でき るようにします。 ・両方式を組み合わせたプログラム #include "cinder/app/AppNative. h" #include "cinder/gl/gl . h" #include "Leap. h" uslng namespace CI ; uslng namespace ( 1 : :app; using namespace Std; public AppNative, class PoIIingApp public: void setup() mLeap. addListener( *this ) ; public Leap: :Listener { void draw() gl : : cl ea r ( C010 r ( 0 , 0 , VOid onFrame( const Leap: :controller& ) console() くく frame . id() くく std: :endl ; Leap: : Frame frame = mLeap. frame() ; 68 console() くく "connect! ! " VOid onconnect(const Leap: :controller&) くく std: :endl ;
[ 3-2 ] 「 Leap M0tion 」はじめの一歩 (Leap::Contr011er クラス ) 続いて、「 setPoIicyFIags() 」の行のコメントを外してみましよう。 するとポリシーが「 POLICY_BACKGROUND_FRAMES 」に設定されるため、 ノヾックグラウンド状態でも「 Leap Motion 」のデータが通知されるようになります。 先ほどと同じように、工クスプローラなどを前面にしても、「 onFrame() 」の呼び出 しが継続されることが分かるでしよう。 アプリケーションの処理には CPU コストがかかるため、アプリケーションの性質に よって適切なポリシーを選択してください。 ・リスナーの登録、削除 「 addListener() 」と「 removeListener() 」は、最初に解説したイベント駆動方式 でデータを取得するときに利用します。 「 Leap::Listener クラス」を継承したクラスを作成し、欲しいイベント実装、「 addL istener() 」で登録します。 「 removeListener() 」は、これを削除するときに呼び出します。 ※「 Leap::Listener クラス」の詳細は「 3-3 イベント駆動でデータを取得 (Leap::Listen e 「クラス ) 」を参照してください。 void main() / / リスナーを登録する / / リスナーとのやり取りは別スレッドにて行われる SampleListener listener; Leap: :controller leap; leap. addListener( listener ) ; std: :cout くく " 終了するには何かキーを押してください " std::cin . get(); leap. removeListener( listener ) ; くく std: :endl ; 75
[ 4-1 ] じゃんけんゲーム if ( mTransrates . size() > = 5 ) { / / 手の移動量が一定以下なら、プレイヤーのポーズを決定する = std : :count—if(mTransrates. begi n() , mTransrates. end() , autO count [ ] ( float move ) { return std: :abs( move ) < 10 ; } ) ; if ( count mTransrates . size() ) { return new ResultState( mAssets, mplayer ,mcomputer ) ; / / 一定時間ポーズが決まらなかったら、アイドル状態にもどる if ( (mAssets->getFrame() . timestamp() ー mEnterTime) > ( 5 ☆ 1000 ☆ 1000 ) ) { return new 工 dlestate( mAssets ) ; return thi 5 ; これで、よりきれいにポーズを検出できるようになりました。 177