OpenGlでのキーボードハンドラについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
SINA

OpenGlでのキーボードハンドラについて

#1

投稿記事 by SINA » 6年前

現在OpenGLを勉強しておりモデルを作ってキーの入力でglLookatの中身の値を変えて
いろいろな視点から眺めたいのですがキーを押しても全く動いてくれません
似たような質問を探してみたのですが解決には至りませんでした。
どうかよろしくお願いいたします。

コード:


#include "glut.h"
#include <GL/gl.h>
#include<math.h>
#define PI 3.14159265358979

int X=4;
int Y=4;
int Z=0;

void Prism(int N) // N角柱描関数
{ 
	int n=N;
	double rad=2*PI/n;
	//上面を描画 (GL_POLYGON) 
	glBegin(GL_POLYGON);
		glNormal3f(0,1,0);
		for(int i=0;i<=n;i++)
		{
			glVertex3f(cos(rad*i), 2,sin(rad*i));  //i点_目U
		}
		glEnd();

	//下面を描画 (GL_POLYGON)
	glBegin(GL_POLYGON);
		glNormal3f(0,-1,0);
		for(int i=0;i<=n;i++)
		{
			glVertex3f(cos(rad*i), -2,sin(rad*i));  //i点_目U
		}
		glEnd();
	//側面を描画 (GL_QUAD_STRIP)
	glBegin(GL_QUAD_STRIP);
		for(int i=0;i<=n;i++)
		{
			glNormal3f(cos(rad*i),0,sin(rad*i));  //i点_目U

			glVertex3f(cos(rad*i),2,sin(rad*i));
			glVertex3f(cos(rad*i),-2,sin(rad*i));
			glVertex3f(cos(rad*(i+1)),2,sin(rad*(i+1)));
			glVertex3f(cos(rad*(i+1)),-2,sin(rad*(i+1)));
		}
		glEnd();
}

void Prism2(int N) // 
{ 
	int n=N;
	double rad=2*PI/n;
	//上の面描画 (GL_POLYGON) 
	glBegin(GL_POLYGON);
		glNormal3f(0,1,0);
		for(int i=0;i<=n;i++)
		{
			glVertex3f(2,0.5*cos(rad*i) ,0.5*sin(rad*i));  //i点_目U
		}
		glEnd();

	//下の画面(GL_POLYGON)
	glBegin(GL_POLYGON);
		glNormal3f(0,-1,0);
		for(int i=0;i<=n;i++)
		{
			glVertex3f(-2,0.5*cos(rad*i),0.5*sin(rad*i));  //i点_目U
		}
		glEnd();
	//側面を描画 (GL_QUAD_STRIP)
	glBegin(GL_QUAD_STRIP);
		for(int i=0;i<=n;i++)
		{
			glNormal3f(0,0.5*cos(rad*i),0.5*sin(rad*i));  //i点_目U

			glVertex3f(2,0.5*cos(rad*i),0.5*sin(rad*i));
			glVertex3f(-2,0.5*cos(rad*i),0.5*sin(rad*i));
			glVertex3f(2,0.5*cos(rad*(i+1)),0.5*sin(rad*(i+1)));
			glVertex3f(-2,0.5*cos(rad*(i+1)),0.5*sin(rad*(i+1)));
		}
		glEnd();
}

//===== キーボードハンドラ
void KeyboardHandler(unsigned char key, int x, int y)
{
    if(key =='a')
		X++;
	if(key=='s')
		Y++;
	if(key=='d')
		Z++;
	
}

void display( void )
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f( 1.0, 1.0, 1.0 );

    glMatrixMode(GL_MODELVIEW);s
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -8.0);
	Prism(12);
	Prism2(12);
	glutPostRedisplay();
    glFlush();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);

    glutInitWindowPosition(0, 0); 
    glutInitWindowSize(400, 400);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
    glutCreateWindow("test");
    glClearColor ( 0.0, 0.0, 0.0, 1.0 );
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, 1.0, 1.0, 20.0);
	gluLookAt(X, Y, Z,   0, 0, -8,   0, 1, 0);
    glShadeModel(GL_FLAT);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);
    glEnable(GL_DEPTH_TEST);

    float light_position[] = {5.0, 10.0, 2.0, 0.0};
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
	glutKeyboardFunc(KeyboardHandler);
    glutDisplayFunc(display);
	glutPostRedisplay();
    glutMainLoop();
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: OpenGlでのキーボードハンドラについて

#2

投稿記事 by h2so5 » 6年前

gluLookAtをdisplay関数の中に入れてみてください。

SINA

Re: OpenGlでのキーボードハンドラについて

#3

投稿記事 by SINA » 6年前

コード:

void display( void )
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f( 1.0, 1.0, 1.0 );

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -8.0);
	Prism(12);
	Prism2(12);
	gluLookAt(X, Y, Z,   0, 0, -8,   0, 1, 0);//←
	glutPostRedisplay();
    glFlush();
}
main関数のものを矢印の場所に移動させたのですがうまくいきませんでした

アバター
usao
記事: 1569
登録日時: 6年前

Re: OpenGlでのキーボードハンドラについて

#4

投稿記事 by usao » 6年前

うまくいかないとはどういう状況ですか(まだ キーを押してもなにも動かない のでしょうか)?

gluLookAt()やglutPostRedisplay()などをdisplay()に書かずにキーボードハンドラに書いたら
変わりませんか?

コード:

void KeyboardHandler(unsigned char key, int x, int y)
{  //※他のキーについては省略
    if(key =='a')
    {
        X++;
        //キー操作により視点変更が必要になったならばその場でやる
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45, 1.0, 1.0, 20.0);
        gluLookAt(X, Y, Z,   0, 0, -8,   0, 1, 0);
        glMatrixMode(GL_MODELVIEW);
        //再描画の必要性が出たのはここなのでglutPostRedisplay()はここでやる
        glutPostRedisplay();
    }
}
[追記]
>main関数のものを矢印の場所に移動させたのですがうまくいきませんでした
mainの記述はとりあえず最初のままにして,↑のように変更したらとりあえずキーを押すと何かしら絵に変化が見られます.
(想定されている動作かどうかは別として.
 ・これだと視点とオブジェクトの距離がどんどん離れて行ってしまう
 ・Near/Farの設定が無いためか,すぐに描画範囲外になってしまう模様.

SINA

Re: OpenGlでのキーボードハンドラについて

#5

投稿記事 by SINA » 6年前

上手くいかないというのはその通りでキーを押しても反応が見られませんでした。
張ってくださったコードを参考になんとか回ってくれる様になりました!
有難うございます。

コード:

#include "glut.h"
#include <GL/gl.h>
#include<math.h>
#define PI 3.14159265358979

int X=4;
int Y=4;
int Z=0;

void Prism(int N) // N角柱描関数
{ 
	int n=N;
	double rad=2*PI/n;
	//上面を描画 (GL_POLYGON) 
	glBegin(GL_POLYGON);
		glNormal3f(0,1,0);
		for(int i=0;i<=n;i++)
		{
			glVertex3f(cos(rad*i), 2,sin(rad*i));  //i点_目U
		}
		glEnd();

	//下面を描画 (GL_POLYGON)
	glBegin(GL_POLYGON);
		glNormal3f(0,-1,0);
		for(int i=0;i<=n;i++)
		{
			glVertex3f(cos(rad*i), -2,sin(rad*i));  //i点_目U
		}
		glEnd();
	//側面を描画 (GL_QUAD_STRIP)
	glBegin(GL_QUAD_STRIP);
		for(int i=0;i<=n;i++)
		{
			glNormal3f(cos(rad*i),0,sin(rad*i));  //i点_目U

			glVertex3f(cos(rad*i),2,sin(rad*i));
			glVertex3f(cos(rad*i),-2,sin(rad*i));
			glVertex3f(cos(rad*(i+1)),2,sin(rad*(i+1)));
			glVertex3f(cos(rad*(i+1)),-2,sin(rad*(i+1)));
		}
		glEnd();
}

void Prism2(int N) // 
{ 
	int n=N;
	double rad=2*PI/n;
	//上の面描画 (GL_POLYGON) 
	glBegin(GL_POLYGON);
		glNormal3f(0,1,0);
		for(int i=0;i<=n;i++)
		{
			glVertex3f(2,0.5*cos(rad*i) ,0.5*sin(rad*i));  //i点_目U
		}
		glEnd();

	//下の画面(GL_POLYGON)
	glBegin(GL_POLYGON);
		glNormal3f(0,-1,0);
		for(int i=0;i<=n;i++)
		{
			glVertex3f(-2,0.5*cos(rad*i),0.5*sin(rad*i));  //i点_目U
		}
		glEnd();
	//側面を描画 (GL_QUAD_STRIP)
	glBegin(GL_QUAD_STRIP);
		for(int i=0;i<=n;i++)
		{
			glNormal3f(0,0.5*cos(rad*i),0.5*sin(rad*i));  //i点_目U

			glVertex3f(2,0.5*cos(rad*i),0.5*sin(rad*i));
			glVertex3f(-2,0.5*cos(rad*i),0.5*sin(rad*i));
			glVertex3f(2,0.5*cos(rad*(i+1)),0.5*sin(rad*(i+1)));
			glVertex3f(-2,0.5*cos(rad*(i+1)),0.5*sin(rad*(i+1)));
		}
		glEnd();
}

//===== キーボードハンドラ
void KeyboardHandler(unsigned char key, int x, int y)
{  //※他のキーについては省略
	double rad2=2*PI/360;
    if(key =='a')
    {
        X=X+4;
        //キー操作により視点変更が必要になったならばその場でやる
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45, 1.0, 1.0, 20.0);
		gluLookAt(4*cos(rad2*X), 4*cos(rad2*Y), cos(rad2*Z),   0, 0, -8,   0, 1, 0);
        glMatrixMode(GL_MODELVIEW);
        //再描画の必要性が出たのはここなのでglutPostRedisplay()はここでやる
        glutPostRedisplay();
    }
	if(key =='s')
    {
        Y=Y+4;
        //キー操作により視点変更が必要になったならばその場でやる
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45, 1.0, 1.0, 20.0);
        gluLookAt(4*cos(rad2*X), 4*cos(rad2*Y), cos(rad2*Z),   0, 0, -8,   0, 1, 0);
        glMatrixMode(GL_MODELVIEW);
        //再描画の必要性が出たのはここなのでglutPostRedisplay()はここでやる
        glutPostRedisplay();
    }
	if(key =='d')
    {
        Z=Z+4;
        //キー操作により視点変更が必要になったならばその場でやる
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45, 1.0, 1.0, 20.0);
        gluLookAt(4*cos(rad2*X), 4*cos(rad2*Y), cos(rad2*Z),   0, 0, -8,   0, 1, 0);
        glMatrixMode(GL_MODELVIEW);
        //再描画の必要性が出たのはここなのでglutPostRedisplay()はここでやる
        glutPostRedisplay();
    }
}

void display( void )
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f( 1.0, 1.0, 1.0 );

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -8.0);
	Prism(12);
	Prism2(12);
	
    glFlush();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);

    glutInitWindowPosition(0, 0); 
    glutInitWindowSize(400, 400);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
    glutCreateWindow("test");
    glClearColor ( 0.0, 0.0, 0.0, 1.0 );
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, 1.0, 1.0, 20.0);
	
    glShadeModel(GL_FLAT);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);
    glEnable(GL_DEPTH_TEST);

    float light_position[] = {5.0, 10.0, 2.0, 0.0};
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
	glutKeyboardFunc(KeyboardHandler);
    glutDisplayFunc(display);
	glutPostRedisplay();
    glutMainLoop();
}
現状ではcos関数で回しているのですが性質上
裏側(と言っていいのでしょうか?)に周ってくれません
どの様な条件わけをすればいいのでしょうか?

アバター
usao
記事: 1569
登録日時: 6年前

Re: OpenGlでのキーボードハンドラについて

#6

投稿記事 by usao » 6年前

同じコードを3箇所に書かずにまとめましょうね.

さて,そのcosの式がどうやってでてきたのかわかりませんが…
複雑なカメラ移動をしたいのでなければ,
・視点を動かすのではなくて,結果が相対的に同じになるようにモデルの方を動かす
という方法をとったほうが楽かもしれませんよ.
(例えば,glRotated()とかでモデル側を回転させれば裏側を見るのは簡単かと.)

SINA

Re: OpenGlでのキーボードハンドラについて

#7

投稿記事 by SINA » 6年前

なるほどOpenGLにはその様な関数もあるんですね
どうも皆様、色々と有難うございました。

閉鎖

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