OpenGLでkeyboardやmouseを使いたい

このQ&Aのポイント
  • キーボードとマウスを使ってOpenGLでグラフィックを制御する方法についてのヒントをお願いします。
  • キーボードで入力した内容に応じてグラフィックが動作する方法や、マウスの動きに合わせて視点を回転させる方法について教えてください。
  • 既存のプログラムを参考にして試してみたのですが、クリックするたびに視点が遠ざかるばかりで最終的には表示が消えてしまいます。どのように修正すれば良いでしょうか。
回答を見る
  • ベストアンサー

OpenGLでkeyboardやmouseを使いたい

OpenGLでグラフィックを描いてるんですが キーボードやマウスを使って次のことが したいんですが、上手くいきません。 よいヒントをお願いします。 キーボードでしたいこと: キーボードで何かを入力したら グラフィックが既定の動作をする。 マウスでしたいこと: マウスで動かした方向に 視点を回転させたい。 またホイールを上に回すと、拡大 ホイールを下に回すと、縮小。 上のプログラムを組む方法が よくわからず上手くいきません。 視点を回転させる方は static int x0, y0, z0; switch (button) { case GLUT_LEFT_BUTTON: if (state==GLUT_DOWN) { x0+=1; gluLookAt(0.0, 75.0, 225.0, x0, 0.0, 0.0, 0.0, 1.0, 0.0); glFlush(); } break; case GLUT_MIDDLE_BUTTON: if (state==GLUT_DOWN) { z0+=1; gluLookAt(0.0, 75.0, 225.0, 0.0, 0.0, z0, 0.0, 1.0, 0.0); glFlush(); } break; case GLUT_RIGHT_BUTTON: if (state==GLUT_DOWN) { y0+=1; gluLookAt(0.0, 75.0, 225.0, 0.0, y0, 0.0, 0.0, 1.0, 0.0); glFlush(); } break; default: break; } という風にプログラムしてみたんですが クリックするたびに視点が遠ざかり 最後には消えました・・・・。

質問者が選んだベストアンサー

  • ベストアンサー
  • Shinoa
  • ベストアンサー率92% (12/13)
回答No.3

私は以下の方法でマウスによる視点の制御を行っています。 移動パラメータを _mx, _my, _mz 、 回転パラメータを _rx, _ry, _rz 、 マウスの移動量を dx , dy として、    1.回転   _ry += dx ;   _rx += dy ;   _rz += dx ;  2.拡大縮小   _mz += dy ;  3.並行移動   _my += dy ;   _mx += dx ;   ホイール操作の場合は、移動量dyを回転量に置き換えてください。 視点の初期値、移動量、移動方向はお好みに合わせて調整してください。 また、視点の回転は、 『シフトキー押下しながらマウス移動』で1軸固定回転 などの制御を加えると、視点操作しやすくなると思います。   後は、実際に描画する時に、物体自体を移動させます。      // 移動   glTranslated( _mx, _my, _mz );   // 回転   glRotated( _rx, 1.0, 0.0, 0.0 );   glRotated( _ry, 0.0, 1.0, 0.0 );   glRotated( _rz, 0.0, 0.0, 1.0 );      // ここで、描画を行う。    これで、お望みの動きに近い事はできると思うのですが、どうでしょう? 以上、ご参考になれば幸いです。

star_blue
質問者

お礼

ありがとうございます。 今は、ほかの事で手がいっぱいなんですが それが済み次第挑戦してみます。 ありがとうございました。

その他の回答 (2)

  • togino
  • ベストアンサー率75% (97/129)
回答No.2

#1 の回答勘違いしてます・・・ごめんなさい。

  • togino
  • ベストアンサー率75% (97/129)
回答No.1

外していたらすみません。ごめんなさい。 gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz); ってなっているので、視点を動かすなら 引数の前3つの方を動かすのでは・・・ > クリックするたびに視点が遠ざかり ではなくて、中心が遠ざかっていったのではないかと。 あと、x0,y0,z0 って増加する一方ですよね。 クリックする度にいずれは・・・

関連するQ&A

  • C言語で電卓を作成する。

    C言語を用いて三項まで計算できる電卓を作りたいのですが、どうも上手くいきません。 四則演算(+、-、×、÷)の優先順位を用いたプログラミング方法が分かりません。 以下に自分で作成したソースを添付します。 このソースに修正や追加して3項までの四則演算できるプログラミングを教えていただけますか? 宜しくお願いします。 #include <stdio.h> int main(void) { int answer; /*答え*/ int x,y,z; /*x=第一項,y=第二項,第三項*/ char op1,op2; /*演算子1、演算子2*/ while(1){ printf("式を入力してください\n"); printf("式:"); scanf("%d %c %d %c %d" ,&x,&op1,&y,&op2,&z); if((op1=='+'|'-'|'*'|'/') && (op2=='+'|'-'|'*'|'/')){ switch(op2){ case '+': answer=y+z; break; case '-': answer=y-z; break; case '*': answer=y*z; break; case '/': if(z==0){ printf("ERROR\n"); return 0; } answer=y/z; break; default: printf("ERROR\n"); return 0; } switch(op1){ case '+': answer=x+answer; break; case '-': answer=x-answer; break; case '*': answer=x*answer; break; case '/': if(y==0){ printf("ERROR\n"); return 0; } answer=x/answer; break; default: printf("ERROR\n"); return 0; } printf("答え:%d\n",answer); } else { switch(op1){ case '+': answer=x+y; break; case '-': answer=x-y; break; case '*': answer=x*y; break; case '/': if(y==0){ printf("ERROR\n"); return 0; } answer=x/y; break; default: printf("ERROR\n"); return 0; } printf("答え:%d\n",answer); } } } 左辺に×、÷が来ても優先的に計算されません。

  • c言語 プログラミング

    以下のプログラムで分からないところがあります。 数式をxpyの形式で入力して、(x,y:整数、p:x,-,*,/のいずれかの演算記号) 答えを表示するというプログラムなのですが、 5行目と9行目にある”-'0'”の意味が分からないので教えてください。 01: int x=0,y=0,z,i;char a[30],p; 02: printf("式を入力してください。:);gets(a); 03: for(i=0;a[i];i++) 04:  if('0'<=a[i] && a[i]<='9') 05:   x=10*x+a[i]-'0'; 06:  else{p=a[i]-'0';break;} 07: for(i++;a[i];i++) 08:  if('0'<=a[i] && a[i]<='9') 09:   y=10*y+a[i]-'0'; 010: switch(p){ 11:  case '+':z=x+y;break; 12:  case '-':z=x+y;break; 13:  case '*':z=x*y;break; 14:  case '/':z=x/y;break; 15:  default:puts("入力エラーです。");return 0; 16: } 17: printf("%d%c%d=%d\n",x,p,y,z); よろしくお願いします。(読みにくかったらメモ帳などにコピペしてください)

  • 画像処理のチェーンコード

    画像処理のチェーンコードが上手くいきません。 言語はC#です。下のようにやってますが、どこかで上手くいっていないみたいです。間違いの指摘をおねがいします。 あるいは、画像処理のチェーンコードのサンプルコードのあるサイトを教えてもらえると助かります。言語はメジャーなものならなんでもかまいません。 for (; ; ) { if (x == xs && y == ys && l != 0) { break; } switch (vec) { case 3: if (data[x, y + 1] == 0 && data[x - 1, y + 1] == 255) { x = x - 1; y = y + 1; list.Add(1); l++; } vec = 0; break; case 4: if (data[x - 1, y + 1] == 0 && data[x - 1, y] == 255) { x = x - 1; y = y + 0; list.Add(2); l++; } vec = 1; break; case 5: if (data[x - 1, y] == 0 && data[x - 1, y - 1] == 255) { x = x - 1; y = y - 1; list.Add(3); l++; } vec = 2; break; case 6: if (data[x - 1, y - 1] == 0 && data[x, y - 1] == 255) { x = x + 0; y = y - 1; list.Add(4); l++; } vec = 3; break; case 7: if (data[x, y - 1] == 0 && data[x + 1, y - 1] == 255) { x = x + 1; y = y - 1; list.Add(5); l++; } vec = 4; break; case 0: if (data[x + 1, y - 1] == 0 && data[x + 1, y] == 255) { x = x + 1; y = y + 0; list.Add(6); l++; } vec = 5; break; case 1: if (data[x + 1, y] == 0 && data[x + 1, y + 1] == 255) { x = x + 1; y = y + 1; list.Add(7); l++; } vec = 6; break; case 2: if (data[x + 1, y + 1] == 0 && data[x, y + 1] == 255) { x = x + 0; y = y + 1; list.Add(0); l++; } vec = 7; break; } }

  • C言語 ツェラーの公式を使った曜日の計算

    ツェラーの公式を使い、年、月、日にちから曜日を表示するプログラムを作りました。 #include<stdio.h> main() { int y,m,d,x,z; printf("年、月、日にちの順に入力してください→"); scanf("%d%d%d",&y,&m,&d); if(m<2){ m=m+12; y=y-1; } x=y+y/4-y/100+y/400+(13*m+8)/5+d; z=x%7; switch(z){ case 0: printf("日曜日\n"); break; case 1: printf("月曜日\n"); break; case 2: printf("火曜日\n"); break; case 3: printf("水曜日\n"); break; case 4: printf("木曜日\n"); break; case 5: printf("金曜日\n"); break; case 6: printf("土曜日\n"); break; } } これを基本に、1582年10月5日以前の入力があったとき「エラー」と表示するにはどうすればいいですか? 解答お願いします。

  • c言語

    c言語で写真の課題を出されたのですが自分のプログラムでは上手くいきません。どこが間違っているのか教えて欲しいです。 自分のプログラム #include<stdio.h> #include<math.h> int main(){ int i,j; double c,d,x,y,z; for(i=0;i<=360;i++){ c=10*cos(i*M_PI/180); d=10*sin(i*M_PI/180); if(c>=0 && d>=0){ for(j=0;j<=1000;j++){ x=0.001*j; y =x*d/c; z=1-x*x-(sqrt(x)+y)*(sqrt(x)+y); if(z<=0.0){break;} } } if(c<=0 && d>=0){ for(j=0;j<=1000;j++){ x=-0.001*j; y=x*d/c; z=1-x*x-(sqrt(-x)+y)*(sqrt(-x)+y); if(z<=0.0){break;} } } if(c<=0 && d<=0){ for(j=0;j<=1000;j++){ x=-0.001*j; y=x*d/c; z=1-x*x-(sqrt(-x)+y)*(sqrt(-x)+y); if(z<=0.0){break;} } } if(c>=0 && d<=0){ for(j=0;j<=1000;j++){ x=0.001*j; y=x*d/c; z=1-x*x-(sqrt(x)+y)*(sqrt(x)+y); if(z<=0.0){break;} } } printf("x=%lf y=%lf z=%lf\n",x,y,z); } return(0); }

  • Openglでテクスチャを透明にする方法について

    Microsoft Visual C++ 2008 Express Edition を使ってtgaファイルをテクスチャとして取り込んで表示するプログラムを作っております. Openglのスポットライト機能を使ってテクスチャを照らしたいと考えています. しかし,どこかのプログラミングがおかしいのか,テクスチャの張り付けに指定された座標4点付近にライトが当たったときでないとテクスチャが光りません. 方法がわからなかったので,テクスチャを大きな球体の内部に配置し,球体の内部からスポットライトでテクスチャ方向を照らすようにしました. 添付した図の左下にスポットライトが白っぽく見えているのは,この大きな球体の内部を照らした光となっています. このように球体内部がスポットライトで照ったので,後はテクスチャさえ透明にすることができれば,間接的にテクスチャをスポットライトで照らしているような感じで見えるのではないかと考えています. しかし肝心のテクスチャを透明にする方法が全くわかりません.(´・ω・) アルファ値というのを使ったり,ブレンド?を使ったりしたらできるのでは,と思ったのですが,どこにどうプログラムしたらいいのかの具体的な説明がなかったので,わかりませんでした(´・ω・) テクスチャを透かして,奥の大きな球体内部を照らすことができれば,その明るさで半透明の手前のテクスチャもうっすら光るのではないかと考えています. わかる方,教えてください. 本当に困ってます;w; 今のプログラム内部のテクスチャの部分は以下に書きます. よろしくお願いします><; void initTexture(void) { FILE *fp; int x, z; /* texture file open */ if((fp=fopen("ougonzan.tga", "rb"))==NULL){ fprintf(stderr, "texture file cannot open\n"); return; } fseek(fp, 18, SEEK_SET); for(x=0; x<TEX_HEIGHT; x++){ for(z=0; z<TEX_WIDTH; z++){ image[x][z][2]=fgetc(fp);/* B */ image[x][z][1]=fgetc(fp);/* G */ image[x][z][0]=fgetc(fp);/* R */ image[x][z][3]=fgetc(fp);/* alpha */ } } fclose(fp); } void displayTexPolygon(void) { glEnable(GL_TEXTURE_2D); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(0.0, 0.0); glVertex3f(-16.0,-12.0, 5.0); //左下 glTexCoord2f(0.0, 1.0); glVertex3f(-16.0, 12.0, 5.0); //左上 glTexCoord2f(1.0, 1.0); glVertex3f( 16.0, 12.0, 5.0); //右上 glTexCoord2f(1.0, 0.0); glVertex3f( 16.0,-12.0, 5.0); //右下 glEnd(); glDisable(GL_TEXTURE_2D); } void display(void) { static const float floor_Color[] = { 1.0, 1.0, 1.0, 1.0 }; static GLfloat red[] = { 0.8, 0.2, 0.2, 1.0 }; static GLfloat yellow[] = { 0.8, 0.8, 0.2, 0.0 }; static GLfloat white[] = { 1.0, 1.0, 1.0, 0.0 }; static float spin=0.0; glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity(); //gluLookAt( 視点の位置x,y,z, 視界の中心位置の参照点座標x,y,z, 視界の上方向のベクトルx,y,z); gluLookAt( 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0); // 内側から //集中型スポットライト //glLightfv(光源番号, パラメータ, パラメータの値); glLightfv(GL_LIGHT0, GL_POSITION, SpotLight.pos); //光源の位置[pos] glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, SpotLight.spotDir); glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, SpotLight.spotCutoff); glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, SpotLight.spotExp); //巨大な球体 glPushMatrix(); glTranslated(0.0, 0.0, 7); glMaterialfv(GL_FRONT, GL_DIFFUSE, white); glutSolidSphere(60, 10000, 10000); glPopMatrix(); glPushMatrix(); glPopMatrix(); glPushMatrix(); glClearColor(0.0, 0.0, 1.0, 0.5); glTranslatef(0.0, 0.0, 45.0); //テクスチャの位置設定 // glRotatef(spin, 0.0, 1.0, 0.0); //テクスチャの回転 glColor4f(1.0, 0.0, 0.0, 0.0); //テクスチャの色設定 displayTexPolygon(); } spin+=1.0; glPopMatrix(); glFlush(); glutSwapBuffers(); }

  • ダイヤログボックス内のマウスイベントの処理

    WinXP + BCC でCのプログラムを作成しています。 ダイヤログボックス内のマウスイベントの処理で、ALTキーが押されている場合と押されていない場合で処理を変えたいのです。 alt_downという変数を用意してみましたがダメでした。 case WM_MOUSEMOVE:  if(alt_down == 1) {   ALTキーが押されているときの処理  } else {   ALTキーが押されていないときの処理  }  break; case WM_SYSKEYDOWN:  if(wParam == VK_MENU) alt_down=1;  break; case WM_SYSKEYUP:  if(wParam == VK_MENU) alt_down=0;  break;

  • プログラムの画面表示のことで

    このような場面で、プレイヤーが倒されてしまったときに、 HPが0にならずに、残ってしまいます。 処理が上から下に向かって動いているためだと思いますが、 プレイヤーやモンスターが倒れた時に、画面の構成を変えずに、 HPを0にすることができるでしょうか? int main(void) { system("cls"); //クリアー dungeon( /* 略 */); //ダンジョン表示(ステータスの表示) player_turn( /* 略 */);//キー入力(プレイヤーのターン) monster_turn( /* 略 */); //モンスターのターン } return 0; } //ダンジョン表示 void dungeon(PC *pc, MC *mc) { for(y=0; y<10; ++y){ for(x=0; x<10; ++x){ if(pc->y==y && pc->x==x){ printf("%s", "@"); }else if((mc->y==y) && (mc->x==x) && (mc->hp>=0)){ printf("%s", "Sk"); }else if(field[y][x]==9){ printf("%s", "■"); }else if(field[y][x]==8){ printf("%s", "□"); }else if(field[y][x]==7){ printf("%s", "<"); }else{ printf("%s", " "); } } status(pc, mc, y); //ステータスのある場所 printf("\n"); } } //ステータス表示 void status(PC *pc, MC *mc, int y) { switch(y) { case 0:printf(" *****************************");break; case 1:printf(" %s Lv%3d HP%3d %3dG", pc->name, pc->lv, pc->hp, pc->gold);break; case 2:break; case 3:break; case 4:break; case 5:break; case 6:break; case 7:break; case 8:printf(" %s Lv%3d HP%3d %3dG", mc->name, mc->lv, mc->hp, mc->gold);break; case 9:printf(" *****************************");break; default:break; } }

  • switch文について

    お世話になります。switch文について教えてください。 分岐の条件を複数使用することは出来ますか。 たとえば switch(a) [ case "1": if (x == "0") { document.write(1x0); } else if (x == "1") { document.write(1x1); else { document.write(1x); break; } case "2": if (x == "0") { document.write(2x0); } else if (x == "1") { document.write(2x1); else if (y == "0") { document.write(2y0); else { document.write(2x); break; ] という構文は可能ですか。 case 2でx yの二分岐しても可能ですか。 教えてください。

    • ベストアンサー
    • Java
  • プログラミングのopenglで困っています.

    OpenGlの超初心者です. openglで,円を一つ作ってあるsampleプログラムを拾ってきたのですが, 円をもう一つ,別の座標で作りたいのですが,以下のプログラムをどのように編集すればいいですか? 誰か助けてください. ========================================== #include <GLUT/glut.h> #include "glut.h" #include <math.h> //--初期化処理------------------------------------------------------------------ void myinit(void){ glClearColor(1.0f, 1.0f, 1.0f, 1.0f);//背景色の設定(R,G,B,ALPHA) 0.0-1.0の範囲で } //--描画内容-------------------------------------------------------------------- void display(void){ float x1,y1,x2,y2; float th1,th2; float th1_rad, th2_rad; float hankei = 0.1; glClear(GL_COLOR_BUFFER_BIT);//画面全体を背景色で塗りつぶす glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //単位行列を行列スタックに読み込む glColor3f(0.0f, 0.0f, 0.0f);//頂点カラーの指定( R, G, B すべてが1.0fなら白) for (th1 = 0.0; th1 <= 360.0; th1 = th1 + 10.0){ th2 = th1 + 10.0; th1_rad = th1 / 180.0 * 3.1415926; // 「度」を「ラジアン」に直す th2_rad = th2 / 180.0 * 3.1415926; x1 = hankei * cos(th1_rad); y1 = hankei * sin(th1_rad); x2 = hankei * cos(th2_rad); y2 = hankei * sin(th2_rad); glBegin(GL_LINES);//glBegin(GL_LINES)とglEnd()の間に glVertex2f( x1, y1 ); //描画したい直線の頂点を並べる glVertex2f( x2, y2 ); glEnd(); //ここまでで,ひとつのオブジェクトの宣言がおわる } glFlush();//OpenGLで実際に描画を行う } //--再描画---------------------------------------------------------------------- void myReshape(GLsizei w, GLsizei h){ glViewport(0,0,w,h); //ウィンドウ全体をビューポートにする glMatrixMode(GL_PROJECTION); glLoadIdentity();//単位行列を行列スタックに読み込む glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); } //--メイン関数------------------------------------------------------------------ int main(int argc, char **argv){ glutInitWindowPosition(100, 100); //(図形が描画される)ウィンドウ位置の設定 glutInitWindowSize(600, 600); //(図形が描画される)ウィンドウサイズの設定 glutInit(&argc, argv);//環境の初期化 glutInitDisplayMode(GLUT_RGBA|GLUT_SINGLE); //表示モードの設定 glutCreateWindow("kadai"); //ウィンドウを開く glutDisplayFunc(display); //図形表示関数の指定 myinit(); glutReshapeFunc(myReshape); //座標軸・ビューポート設定関数の指定 glutMainLoop();//無限ループ return 0; } ==========================================

専門家に質問してみよう