LeapMotion と C++ glut OpenGL の描画方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Toshita
記事: 23
登録日時: 9年前

LeapMotion と C++ glut OpenGL の描画方法

#1

投稿記事 by Toshita » 9年前

プログラムを初めて3年くらい立ちます.
と言っても,週に2〜3回簡単なプログラムを触るくらいで初心者に毛が生えた程度の能力です.

また LeapMotion C++ glut OpenGL 3D描画 と全て初めて触って3週間程度しかたっていません.

現在LeapMotionを使って簡単なゲームを作っています.
仕様言語は C++ です.
描画方法は glut を使ってOpenGLで描画しています.
また,下記の全てのプログラムは,色んなサイトや教授が作られたプログラムを元に作成していて,
完全に私が作ったというわけではありません.

今求めている事は
LeapMotionとc++ glut OpenGL の描画を完成させることです.
ループがうまく行かず、LeapMotion から値を取得してもOpenGLに描画されなかったりします.
下記に掲載しているプログラムはまだそのような動作をおこなっていませんが、
LeapMotion から値を取得し,OpenGLに描画する.そしてまたイベント取得を待つという流れがうまくできません.


まず,元となるプログムラを掲載します.
内容はクリックするとボールが飛んでいく様子を描いています.
しかし,プログラム内ではクリック毎にボールの位置を戻しています.
ところどころ必要ない変数とかありますが,無視して下さい.

Makefile
CFLAGS = -I/usr/X11R6/include
LDLIBS = -L/usr/X11R6/lib -lglut -lGLU -lGL -lXi -lXext -lX11 -lm -lpthread -Wall /usr/lib/Leap/libLeap.so -I/usr/local/include/Leap

#all: main.cpp

#start: main.cpp
# $(CC) $(CFLAGS) main.cpp -o start $(LDLIBS)

game: game.cpp
$(CC) $(CFLAGS) game.cpp -o game $(LDLIBS)
プログラム .cpp

コード:

/* Include */
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include "Leap.h"

using namespace Leap;
using namespace std;

/* フィールド生成用 */
#define W 10                    /* フィールドの幅 */
#define D 10                    /* フィールドの長さ */
#define G (-9.8)                /* 重力加速度 */
#define V 25.0                  /* 球の初速度 */
#define QX 0.0                  /* 球の初期位置 x座標 */
#define QY 1.5                  /* 球の初期位置 y座標 */
#define QZ (10.0)               /* 球の初期位置 z座標 */
#define KEY_ESCAPE 27           /*  */
#define DEFAULT_WIDTH 800       /* ウィンドウの幅 */
#define DEFAULT_HEIGHT 600      /* ウィンドウの高さ */
#define TSTEP 0.01              /* フレームごとの時間 */

int window;
int screen_width = DEFAULT_WIDTH;
int screen_height = DEFAULT_HEIGHT;
int flag = 0;
Controller controller;
Screen screen;

void idle(void){
        glutPostRedisplay();
}

/* 地面を描く */
void myGround(double height){
        static GLfloat ground[][4] = {
                { 0.6, 0.6, 0.6, 1.0 },
                { 0.3, 0.3, 0.3, 1.0 }
        };

        int i,j;

        glBegin(GL_QUADS);
        glNormal3d(0.0, 1.0, 0.0);
        for(j = -D / 2; j < D / 2; ++j){
                for(i = -W / 2; i < W / 2; ++i){
                        glMaterialfv(GL_FRONT, GL_DIFFUSE, ground[(i+j) & 1]); //質感
                        glVertex3d((GLdouble)i, height, (GLdouble)j);
                        glVertex3d((GLdouble)i, height, (GLdouble)(j+1));
                        glVertex3d((GLdouble)(i+1), height, (GLdouble)(j+1));
                        glVertex3d((GLdouble)(i+1), height, (GLdouble)j);
                }
        }
        glEnd();
}

/* 画面表示 */
void display(void){
        /* 光源の位置 */
        static GLfloat lightpos[] = { 3.0, 4.0, 5.0, 1.0 };

        /* 球の色 */
        static GLfloat white[] = { 0.8, 0.8, 0.8, 1.0 };

        /* 球の位置 */
        static double px = QX, py = QY, pz = QZ;

        // pyv y軸の速度 pa 加速度 pe 跳ね上がり係数

        /* 物理演算 */
        if(flag) {
                pz = 10;
                flag = 0;
        }
        px += 0.000;
        py += 0.000;
        pz -= 0.01;



        /* 画面クリア */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        /* モデルビュー変換行列の初期化 */
        glLoadIdentity();

        /* 光源の位置を設定 */
        glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

        /* 視点の移動(物体の方を奥に移す) */
        glTranslated(0.0, -QY, -D);

        /* シーンの描画 */
        myGround(0.0);
        glTranslated(px, py, pz);
        glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
        glutSolidSphere(0.1, 16, 8);

        glFlush();
}
void resize(int w, int h){
        /* ウインドウ全体をビューボート */
        glViewport(0, 0, w, h);

        /* 透視変換行列の設定 */
        glMatrixMode(GL_PROJECTION);

        /* 透視変換行列の初期化 */
        glLoadIdentity();
        gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

        /* モデルビュー変換行列の指定 */
        glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
        switch(button){
        case GLUT_LEFT_BUTTON:
                if(state == GLUT_DOWN){
                        /*アニメーション開始*/
                        glutIdleFunc(idle);
                        flag = 1;
                }
                //else glutIdleFunc(0);
                break;
        case GLUT_RIGHT_BUTTON:
                if(state == GLUT_DOWN){
                        /* コマ送り(1ステップだけ進める) */
                        glutPostRedisplay();
                }
                break;
        //defaul:
        //      break;
        }
}

void keyboard(unsigned char key, int x, int y){
        /* ETCで終了 */
        if(key == '\033')
                exit(0);
}

void init(void){
        /*初期設定*/
        glClearColor(1.0, 1.0, 1.0, 1.0);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
}

void ReSizeGLScene(int Width, int Height)
{
        if(Height==0)
                Height=1;
        screen_width = Width;
        screen_height = Height;
}

int main(int argc, char *argv[]){
        const char *title = "Game";
        //SampleListener listener;
        //Controller controller;

        //controller.addListener(listener);

        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
        glutInitWindowSize(screen_width, screen_height);
        glutInitWindowPosition(0, 0);
        glutCreateWindow(title);
        glutDisplayFunc(display);
        glutReshapeFunc(resize);
        glutMouseFunc(mouse);
        glutKeyboardFunc(keyboard);
        init();

        glutMainLoop();

        return 0;
}
次にLeapMotionのプログラムです.
こちらは単純に数値をとるだけになります.

Makefile
test: test1.cpp
gcc -Wall test1.cpp /usr/lib/Leap/libLeap.so -I/usr/local/include/Leap -o test
プログラム.cpp

コード:

#include <stdio.h>
#include "Leap.h"
using namespace Leap;

class SampleListener : public Listener {
  public:
    virtual void onInit(const Controller&);
    virtual void onConnect(const Controller&);
    virtual void onDisconnect(const Controller&);
    virtual void onExit(const Controller&);
    virtual void onFrame(const Controller&);
    virtual void onFocusGained(const Controller&);
    virtual void onFocusLost(const Controller&);
};

void SampleListener::onInit(const Controller& controller) {
}

void SampleListener::onConnect(const Controller& controller) {
  /* 使用するジェスチャーをセットする */
  controller.enableGesture(Gesture::TYPE_CIRCLE);
  controller.enableGesture(Gesture::TYPE_KEY_TAP);
  controller.enableGesture(Gesture::TYPE_SCREEN_TAP);
  controller.enableGesture(Gesture::TYPE_SWIPE);
}

void SampleListener::onDisconnect(const Controller& controller) {
}

void SampleListener::onExit(const Controller& controller) {
}

void SampleListener::onFrame(const Controller& controller) {
  Frame frame = controller.frame();// 最新のFrameを取得する
  HandList handList = frame.hands();// 全ての手の情報を取得する
  FingerList allFingerList = frame.fingers();// 全ての指の情報を取得する
  GestureList gesturesInFrame = frame.gestures();// 全てのジェスチャーの情報を取得する
  int i, j;
   
  //それぞれの個数を表示する
  printf("hands:%d, fingers:%2d, gestures:%d\n",
          handList.count(), allFingerList.count(), gesturesInFrame.count());

  //手と指の処理
  for(i = 0; i < handList.count(); i++){
    Hand hand = handList[i];
    Vector handCenter = hand.palmPosition();
    FingerList fingerList = hand.fingers();// handの指の情報を取得する
    
    //個別の手の情報を出力する
    printf("  hand[%d] (%6.1f,%6.1f,%6.1f), fingers:%d\n",
             i, handCenter.x, handCenter.y, handCenter.z, fingerList.count());
    for(j = 0; j < fingerList.count(); j++){
      Finger finger = fingerList[j];
      Vector currentPosition = finger.tipPosition();
      
      //個別の指の情報を出力する
      printf("    finger[%d] (%6.1f,%6.1f,%6.1f)\n",
               j, currentPosition.x, currentPosition.y, currentPosition.z);
    }
  }

  //ジェスチャーの処理
  GestureList gestures = frame.gestures();
  for (i = 0; i < gestures.count(); i++){
    Gesture gesture = gestures[i];

    //ジェスチャーの種類の出力
    printf("  gesture[%d] ",i);
    switch (gesture.type()) {
      case Gesture::TYPE_CIRCLE:
        printf("CIRCLE\n");
        break;
      case Gesture::TYPE_SWIPE:
        printf("SWIPE\n");
        break;
      case Gesture::TYPE_KEY_TAP:
        printf("KEY_TAP\n");
        break;
      case Gesture::TYPE_SCREEN_TAP:
        printf("SCREEN_TAP\n");
        break;
      default:
        printf("unknown\n");
        break;
    }
  }
}

void SampleListener::onFocusGained(const Controller& controller) {
}

void SampleListener::onFocusLost(const Controller& controller) {
}

int main(){
  SampleListener listener;
  Controller controller;

  controller.addListener(listener);

  getchar();

  controller.removeListener(listener);

  return 0;
}

そして,現在作成中のプログラムです.
未完成です.メイン関数の中身をどうすればいいかが知りたいため,その他の関数も載せています.

コンパイルエラー内容
cc -I/usr/X11R6/include game.cpp -o game -L/usr/X11R6/lib -lglut -lGLU -lGL -lXi -lXext -lX11 -lm -lpthread -Wall /usr/lib/Leap/libLeap.so -I/usr/local/include/Leap
/tmp/cccQXTJm.o:(.rodata._ZTV14SampleListener[vtable for SampleListener]+0x24): undefined reference to `SampleListener::onFocusGained(Leap::Controller const&)'
/tmp/cccQXTJm.o:(.rodata._ZTV14SampleListener[vtable for SampleListener]+0x28): undefined reference to `SampleListener::onFocusLost(Leap::Controller const&)'
collect2: ld はステータス 1 で終了しました
make: *** [game] エラー 1
Makefile
CFLAGS = -I/usr/X11R6/include
LDLIBS = -L/usr/X11R6/lib -lglut -lGLU -lGL -lXi -lXext -lX11 -lm -lpthread -Wall /usr/lib/Leap/libLeap.so -I/usr/local/include/Leap

#all: main.cpp

#start: main.cpp
# $(CC) $(CFLAGS) main.cpp -o start $(LDLIBS)

game: game.cpp
$(CC) $(CFLAGS) game.cpp -o game $(LDLIBS)
プログラム.cpp

コード:

/* Include */
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include "Leap.h"

using namespace Leap;
using namespace std;

/* フィールド生成用 */
#define W 10			/* フィールドの幅 */
#define	D 10			/* フィールドの長さ */
#define G (-9.8)		/* 重力加速度 */
#define V 25.0			/* 球の初速度 */
#define QX 0.0			/* 球の初期位置 x座標 */
#define QY 1.5			/* 球の初期位置 y座標 */
#define QZ (10.0)		/* 球の初期位置 z座標 */
#define KEY_ESCAPE 27		/*  */
#define DEFAULT_WIDTH 800	/* ウィンドウの幅 */
#define DEFAULT_HEIGHT 600	/* ウィンドウの高さ */
#define TSTEP 0.01		/* フレームごとの時間 */


int window;
int screen_width = DEFAULT_WIDTH;
int screen_height = DEFAULT_HEIGHT;
int flag = 0;
Controller controller;
Screen screen;

class SampleListener : public Listener {
        public:
                virtual void onInit(const Controller&);
                virtual void onConnect(const Controller&);
                virtual void onDisconnect(const Controller&);
                virtual void onExit(const Controller&);
                virtual void onFrame(const Controller&);
                virtual void onFocusGained(const Controller&);
		virtual void onFocusLost(const Controller&);
};

void SampleListener::onInit(const Controller& controller) {
	std::cout << "Initialized" << std::endl;
}

void SampleListener::onConnect(const Controller& controller) {
	std::cout << "Connected" << std::endl;
	/* 使用するジェスチャーをセットする */
  	controller.enableGesture(Gesture::TYPE_CIRCLE);
  	controller.enableGesture(Gesture::TYPE_KEY_TAP);
  	controller.enableGesture(Gesture::TYPE_SCREEN_TAP);
  	controller.enableGesture(Gesture::TYPE_SWIPE);
}

void SampleListener::onDisconnect(const Controller& controller) {
	std::cout << "Disconnected" << std::endl;
}

void SampleListener::onExit(const Controller& controller) {
	std::cout << "Exited" << std::endl;
}

void SampleListener::onFrame(const Controller& controller) {
	//ここに処理を書く
}

SampleListener listener;

void CleanupExit(){
	controller.removeListener(listener);
	exit (1);
}

/* OpenGL */
void idle(void){
        glutPostRedisplay();
}

/* 地面を描く */
void myGround(double height){
	static GLfloat ground[][4] = {
		{ 0.6, 0.6, 0.6, 1.0 },
		{ 0.3, 0.3, 0.3, 1.0 }
	};
	
	int i,j;
	
	glBegin(GL_QUADS);
	glNormal3d(0.0, 1.0, 0.0);
	for(j = -D / 2; j < D / 2; ++j){
		for(i = -W / 2; i < W / 2; ++i){
			glMaterialfv(GL_FRONT, GL_DIFFUSE, ground[(i+j) & 1]); //質感
			glVertex3d((GLdouble)i, height, (GLdouble)j);
			glVertex3d((GLdouble)i, height, (GLdouble)(j+1));
			glVertex3d((GLdouble)(i+1), height, (GLdouble)(j+1));
			glVertex3d((GLdouble)(i+1), height, (GLdouble)j);
		}
	}
	glEnd();
}

/* 画面表示 */
void display(void){
	
	/* 光源の位置 */
	static GLfloat lightpos[] = { 3.0, 4.0, 5.0, 1.0 };
	
	/* 球の色 */
	static GLfloat white[] = { 0.8, 0.8, 0.8, 1.0 };
	
	/* 球の位置 */
	static double px = QX, py = QY, pz = QZ;
	
	// pyv y軸の速度 pa 加速度 pe 跳ね上がり係数
	
	/* 物理演算 */
	if(flag) {
		pz = 10;
		flag = 0;
	}
	px += 0.000;
	py += 0.000;
	pz -= 0.01;
	
	
	
	/* 画面クリア */
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	/* モデルビュー変換行列の初期化 */
	glLoadIdentity();
	
	/* 光源の位置を設定 */
	glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
	
	/* 視点の移動(物体の方を奥に移す) */
	glTranslated(0.0, -QY, -D);
	
	/* シーンの描画 */
	myGround(0.0);
	glTranslated(px, py, pz);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
	glutSolidSphere(0.1, 16, 8);
	
	glFlush();
}


void resize(int w, int h){
	/* ウインドウ全体をビューボート */
	glViewport(0, 0, w, h);
	
	/* 透視変換行列の設定 */
	glMatrixMode(GL_PROJECTION);
	
	/* 透視変換行列の初期化 */
	glLoadIdentity();
	gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
	
	/* モデルビュー変換行列の指定 */
	glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
	switch(button){
	case GLUT_LEFT_BUTTON:
		if(state == GLUT_DOWN){
			/*アニメーション開始*/
			glutIdleFunc(idle);
			flag = 1;
		}
		//else glutIdleFunc(0);
		break;
	case GLUT_RIGHT_BUTTON:
		if(state == GLUT_DOWN){
			/* コマ送り(1ステップだけ進める) */
			glutPostRedisplay();
		}
		break;
	//defaul:
	//	break;
	}
}

void keyboard(unsigned char key, int x, int y){
	/* ETCで終了 */
	if(key == '\033') 
		exit(0);
}

void init(void){
	/*初期設定*/
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
}

void ReSizeGLScene(int Width, int Height)
{
	if(Height==0)
		Height=1;
	screen_width = Width;
	screen_height = Height;
}

int main(int argc, char *argv[]){	
	const char *title = "Game";
 	SampleListener listener;
  	Controller controller;
	
	controller.addListener(listener);
	
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(screen_width, screen_height);
	glutInitWindowPosition(0, 0);
	glutCreateWindow(title);
	glutDisplayFunc(display);
	glutReshapeFunc(resize);
	glutMouseFunc(mouse);
	glutKeyboardFunc(keyboard);
	init();
	
	glutMainLoop();
	
	return 0;
}



最後まで読んでいただき有難うございます.
LeapMotion も C++ も glut と OpenGL も最近初めて,かつ3Dの描画をするという内容ですが,
アドバイス等をいただけると幸いです.
よろしくお願い致します.

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: LeapMotion と C++ glut OpenGL の描画方法

#2

投稿記事 by みけCAT » 9年前

LeapMotionについては全くわかりませんが、とりあえず提示されたコンパイルエラー(リンクエラー?)を消すには、
単純に定義されていないonFocusGainedとonFocusLostを適当に定義すればいいのではないでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Toshita
記事: 23
登録日時: 9年前

Re: LeapMotion と C++ glut OpenGL の描画方法

#3

投稿記事 by Toshita » 9年前

あ、定義されてなかったからエラーがでてたんですね^^;
やってみます!

閉鎖

“C言語何でも質問掲示板” へ戻る