Войти
OpenGL communityФорумВопросы по программированию

Вопрос про поворот.

#0
21:04, 19 апр. 2019

Здравствуйте. Являюсь начинающим в вопросах графики. Нужно, чтобы объект можно было рассмотреть со всех сторон, вертеться вокруг него, но при этом оси мировой системы координат не поворачивались, оставались как бы прикреплёнными к объекту. Для поворота была выбрана функция gluLookAt(). Однако с ней происходит что-то непонятно, уже через несколько нажатий поворота объект куда-то уплывает, а обзор остаётся на пустое пространство. В чём ошибка? Где неправильно? Код прилагаю. (Пишу на чистом С).

double rotate_x = 0;
double rotate_y = 0;
double koord_x = 0;
double koord_y = 0;
double koord_z = -5;

void display() {

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;

  
  
  gluLookAt(koord_x, koord_y, koord_z, 0, 0, 0, 0, 1, 0);
  
  
  WriteCube();
  

  
  glFlush();
  glutSwapBuffers();
}


void specialKeys(int key, int x, int y) {
  
  koord_x = 0;
  koord_y = 0;


  //  Right arrow - increase rotation by 5 degree
  if (key == GLUT_KEY_RIGHT)
    rotate_y += 5;

  //  Left arrow - decrease rotation by 5 degree
  else if (key == GLUT_KEY_LEFT)
    rotate_y -= 5;

  else if (key == GLUT_KEY_UP)
    rotate_x += 5;

  else if (key == GLUT_KEY_DOWN)
    rotate_x -= 5;

  double rotate_xRad, rotate_yRad;
  rotate_xRad = rotate_x * M_PI / 180;
  rotate_yRad = rotate_y * M_PI / 180;

  koord_x = 1* cos(rotate_xRad);
  koord_y = 1* cos(rotate_yRad);

  //  Request display update
  glutPostRedisplay();

}

void MouseKlick(int button, int state, int x, int y) {
  if (button == GLUT_LEFT_BUTTON) {
    if (state == GLUT_DOWN) {

      GLint viewport[4];
      GLdouble modelview[16];
      GLdouble projection[16];
      GLfloat winX, winY, winZ;
      GLdouble posX, posY, posZ;

      glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
      glGetDoublev(GL_PROJECTION_MATRIX, projection);
      glGetIntegerv(GL_VIEWPORT, viewport);

      winX = x;
      winY = y;
      winZ = -1;
      
      gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
      
      printf("qwa");
      
    }
  }
}

int main(int argc, char* argv[]) {

  glutInit(&argc, argv);

  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

  glutInitWindowSize(700, 700);
  glutCreateWindow("Cube");

  glEnable(GL_DEPTH_TEST);

  glutDisplayFunc(display);

  glutSpecialFunc(specialKeys);
  glutMouseFunc(MouseKlick);

  glutMainLoop();

  return 0;


}


#1
10:18, 20 апр. 2019

Навскидку, ты юзаешь glLoadIdentity но не указываешь к какой матрице
юзай перед glLoadIdentity glMatrixMode(GL_PROJECTION)

#2
15:25, 22 апр. 2019

gluLookAt меняет текущую матрицу, а какая у тебя текущая? выстави прямо перед gluLookAt glMatrixMode(GL_PROJECTION)

а после

glMatrixMode(GL_MODELVIEW)
glLoadIdentity();
тогда кубик будет рисоваться в нуле, а ты будешь смотреть в точку koord_x, koord_y, koord_z из нуля.
Дальше сообразишь что с чем поменять чтобы вышло нормально.
На плюсах для этих дела есть библиотека OpenGL Mathematics (GLM). На чистом C такой не знаю, но использовать раритетные функции gluxxx идея явно не лучшая. Нынче пришли к тому что ничего кроме glMatrixMode и glLoadMatrix не используется, больно уж код с поворотами в состоянии кривой выходил. Вычисляют матрицы для каждого объекта и грузят при отрисовке, по большей части вообще прямо в шейдер.

#3
(Правка: 11:37) 8:40, 6 мая 2019

Функция specialKeys написана полностью некорректно.

> Нужно, чтобы объект можно было рассмотреть со всех сторон, вертеться вокруг него, но при этом оси мировой системы координат не поворачивались, оставались как бы прикреплёнными к объекту.

Ты хочешь чтобы камера смотрела на объект и кнопками вращался только объект (ты глядишь на глобус, и крутишь его), или ты хочешь чтобы камера летала вокруг объекта, постоянно глядя на него (ты энергично бегаешь вокруг глобуса, постоянно глядя в его центр)? Судя по коду всё-таки предполагается второе.

ShadowTeolog
> gluLookAt меняет текущую матрицу, а какая у тебя текущая? выстави прямо перед
> gluLookAt glMatrixMode(GL_PROJECTION)

gluLookAt это как раз modelview матрица. Она не из frustum строится, а из перемноженных rotate/translate.

#4
11:45, 6 мая 2019

Так как предполагается второй вариант, то оперировать понятиями koord_x/y, rotate_x/y в корне не верно. Потому что ты по факту носишься по сфере камерой.
И это у тебя не x/y, а широта/долгота (lat/lon). У тебя koord_z фиксированный, а по факту он не может быть фискированным.

Надо получить точку (x,y,z) из lat/lon.

koord_x = R * cos(rotate_xRad) * cos(rotate_yRad);
koord_y = R * cos(rotate_xRad) * sin(rotate_yRad);
koord_z = R * sin(rotate_xRad);
OpenGL communityФорумВопросы по программированию