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

落書きノート

ふと自分が気になった事を書いてます

OpenGL ウォークスルー問題 再トライそして完成

C/C++,OpenGLのウォークスルー問題です。懲りずにやりました。結果、出来ました。gluLookAt関数じゃないと出来ないと思ってましたけど、glRotate関数とglTranslate関数でも出来るものですね。微調整もしました。個人的には完璧に出来たと思います。実験とはまた違う感じかもしれないですけど、これで行けるでしょう!

A. ウォークスルーの実験

#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>

int w0, h0;
int wa, ha;
double a;
double v;
const double t = 10;
const double PI = 3.14;

void scene(void)
{
  /* 物体の色 */
  static GLfloat red[] = { 0.8, 0.2, 0.2, 1.0 };
  static GLfloat green[] = { 0.2, 0.8, 0.2, 1.0 };
  static GLfloat blue[] = { 0.2, 0.2, 0.8, 1.0 };
  static GLfloat yellow[] = { 0.8, 0.8, 0.2, 1.0 };
  static GLfloat ground[][4] = {
    { 0.6, 0.6, 0.6, 1.0 },
    { 0.3, 0.3, 0.3, 1.0 }
  };

  int i, j;

  /* 赤い箱 */
  glPushMatrix();
  glTranslated(0.0, 0.0, -3.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, red);
  glutSolidCube(1.0);
  glPopMatrix();

  /* 緑の箱 */
  glPushMatrix();
  glTranslated(0.0, 0.0, 3.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, green);
  glutSolidCube(1.0);
  glPopMatrix();

  /* 青い箱 */
  glPushMatrix();
  glTranslated(-3.0, 0.0, 0.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, blue);
  glutSolidCube(1.0);
  glPopMatrix();

  /* 黄色い箱 */
  glPushMatrix();
  glTranslated(3.0, 0.0, 0.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
  glutSolidCube(1.0);
  glPopMatrix();

  /* 地面 */
  glBegin(GL_QUADS);
  glNormal3d(0.0, 1.0, 0.0);
  for (j = -5; j < 5; ++j) {
    for (i = -5; i < 5; ++i) {
      glMaterialfv(GL_FRONT, GL_DIFFUSE, ground[(i + j) & 1]);
      glVertex3d((GLdouble)i, -0.5, (GLdouble)j);
      glVertex3d((GLdouble)i, -0.5, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), -0.5, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), -0.5, (GLdouble)j);
    }
  }
  glEnd();
}

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

  static double ex = 0.0, ez = 0.0; /* 視点の位置 */
  static double r = 0.0;            /* 視点の向き */
  static double rd = 0.0;
  
  /* 画面クリア */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

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

  /* 視点の移動 */
  glRotated(r, 0.0, 1.0, 0.0);
  glTranslated(ex, 0.0, ez);

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

  /* シーンの描画 */
  scene();

  glutSwapBuffers();

  if(ha < 0) {
    v = abs(ha) * 0.0001;
    ex = ex - v * sin(r * PI / 180) * t;
    ez = ez + v * cos(r * PI / 180) * t;
  } else if(ha > 0){
    v = abs(ha) * 0.0001;
    ex = ex + v * sin(r * PI / 180) * t;
    ez = ez - v * cos(r * PI / 180) * t;
  }

  if(wa > 0) {
    rd = abs(wa);
    a = rd / t * 0.01;
    r = r + a * t;
  } else if(wa < 0){
    rd = abs(wa);
    a = rd / t * 0.01;
    r = r - a * t;
  }
}

void resize(int w, int h)
{
  w0 = w / 2, h0 = h / 2;
  /* ウィンドウ全体をビューポートにする */
  glViewport(0, 0, w, h);

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

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

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

void keyboard(unsigned char key, int x, int y)
{
  /* ESC か q をタイプしたら終了 */
  if (key == '\033' || key == 'q') {
    exit(0);
  }
}

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

void idle(void) {
  glutPostRedisplay();
}

void mouse(int button, int state, int x, int y) {
  switch(button) {
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN) {
      glutIdleFunc(idle);
    } else {
      glutIdleFunc(0);
    }
    break;
  }
}

void motion(int x, int y) {
  wa = x - w0, ha = y - h0;
}

int main(int argc, char *argv[])
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutKeyboardFunc(keyboard);
  glutMouseFunc(mouse);
  glutMotionFunc(motion);
  init();
  glutMainLoop();
  return 0;
}
> brew cask install xquartz
> brew install freeglut
> gcc core.cpp -o core -I/usr/local/include -L/usr/local/lib -framework GLUT -framework OpenGL -mmacosx-version-min=10.8

f:id:kh2n:20170516000726p:plain