OpenGL Клавиатура Управление камерой - PullRequest
0 голосов
/ 15 ноября 2009

Я следил за этой серией уроков для OpenGL : GLUT :

http://www.lighthouse3d.com/opengl/glut/

Я достиг стадии реализации управления камерой с помощью клавиатуры:

http://www.lighthouse3d.com/opengl/glut/index.php?8

При продвинутом обучении оно перестает работать. Я просто скопировал и вставил его. Когда я запускаю свою версию кода, он работает. Моя, похоже, не работает. При перемещении влево и вправо он должен вращать камеру и перемещаться вперед и назад при использовании клавиш вверх и вниз.

Мой код здесь сломан:

Эта часть моего кода отображает компоненты в сцене с помощью init (), которая инициализирует значения и т. Д. :

void display(void)
{
 if (deltaMove)
  moveMeFlat(deltaMove);
 if (deltaAngle) {
  angle += deltaAngle;
  orientMe(angle);
 }

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glBindTexture(GL_TEXTURE_2D, texture[0]);
 RenderSkyDome();
 glBindTexture(GL_TEXTURE_2D, NULL);

 glutSwapBuffers();

}

void init(void)
{
 glClearColor(0.0, 0.0, 0.0, 0.0);
 glClearDepth(1.0f);
 glColor3f(0.0, 0.0, 1.0);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glEnable(GL_TEXTURE_2D);
 glEnable(GL_DEPTH_TEST);
 glDepthFunc(GL_LEQUAL);
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

 LoadTextures("clouds2.bmp", 0);
 GenerateDome(600.0f, 5.0f, 5.0f, 1.0f, 1.0f);

 snowman_display_list = createDL();
}

Это моя основная функция цикла:

int main ()
{
 glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
 glutInitWindowSize(800, 600);
 glutInitWindowPosition(0, 0);
 glutCreateWindow("Captain Ed's Adventures: Great Wall of China");
 init();

 //Glut Input Commands
 glutIgnoreKeyRepeat(1);
 glutSpecialFunc(pressKey);
 glutSpecialUpFunc(releaseKey);
 glutKeyboardFunc(processNormalKeys);

 glutDisplayFunc(display);
 glutIdleFunc(display);
 glutReshapeFunc(reshape);  // This redraws everything on screen when window size is changed.               
 glutMainLoop();
 return 0;
}

Вот мои функции ввода, которые называются:

void pressKey(int key, int x, int y) {

 switch (key) {
  case GLUT_KEY_LEFT : deltaAngle = -0.10f;break;
  case GLUT_KEY_RIGHT : deltaAngle = 0.10f;break;
  case GLUT_KEY_UP : deltaMove = 50;break;
  case GLUT_KEY_DOWN : deltaMove = -50;break;
 }
}

void releaseKey(int key, int x, int y) {

 switch (key) {
  case GLUT_KEY_LEFT : if (deltaAngle < 0.0f) 
         deltaAngle = 0.0f;
        break;
  case GLUT_KEY_RIGHT : if (deltaAngle > 0.0f) 
         deltaAngle = 0.0f;
        break;
  case GLUT_KEY_UP :  if (deltaMove > 0) 
         deltaMove = 0;
        break;
  case GLUT_KEY_DOWN : if (deltaMove < 0) 
         deltaMove = 0;
        break;
 }
}

void processNormalKeys(unsigned char key, int x, int y) {

 if (key == 27) 
  exit(0);
}

Переменные, которые используются камерой, и функции, которые должны ее изменять:

static float angle=0.0,deltaAngle = 0.0,ratio;
static float x=0.0f,y=1.75f,z=5.0f;
static float lx=0.0f,ly=0.0f,lz=-1.0f;
static int deltaMove=0;

void orientMe(float ang) {

 lx = sin(ang);
 lz = -cos(ang);
 glLoadIdentity();
 gluLookAt(x, y, z, 
        x + lx,y + ly,z + lz,
     0.0f,1.0f,0.0f);
} 

void moveMeFlat(int i) {
 x = x + i*(lx)*0.1;
 z = z + i*(lz)*0.1;
 glLoadIdentity();
 gluLookAt(x, y, z, 
        x + lx,y + ly,z + lz,
     0.0f,1.0f,0.0f);
}

Я считаю, что это почти все, с чем я работаю, поэтому в основном должно произойти следующее: когда я нажимаю клавишу ВВЕРХ, deltaMove должен = 50, и когда это происходит, оператор if в void display (void) должен выполнять moveMeFlat (deltaMove); Я не знаю, делаю ли я это неправильно или есть ли лучший результат ...

Я могу переместить «moveMeFlat (deltaMove)» в соответствующих случаях переключения, но это не позволяет мне получить движение, которое я хочу. Кажется, он работает с использованием исходного кода из приведенных выше руководств с правильной функциональностью, но не в моем случае, поэтому я предполагаю, что это связано с оператором if на дисплее.

Конечный результат, который я ищу, - это иметь возможность работать вперед и назад, вращая камеру влево и вправо. Я хотел бы иметь возможность нажать вперед и влево и увидеть камеру отклонение влево, как в гоночной игре ...

Ответы [ 2 ]

2 голосов
/ 01 января 2010

Попробуйте избавиться от статики перед всеми объявлениями глобальных переменных.

Последнее использование static - это глобальная переменная внутри файла кода. В этом случае использование статического указывает, что исходный код в других файлах, которые являются частью проекта, не может получить доступ к переменной. Только код внутри одного файла может видеть переменную. (Его область действия - или видимость - ограничена файлом.) Этот метод можно использовать для имитации объектно-ориентированного кода, поскольку он ограничивает видимость переменной и, таким образом, помогает избежать конфликтов имен. Такое использование статики является пережитком C.

http://www.cprogramming.com/tutorial/statickeyword.html

Кроме того, вместо этого:

if (deltaMove)
  moveMeFlat(deltaMove);
 if (deltaAngle) {
  angle += deltaAngle;
  orientMe(angle);
 }

попробуйте это:

if (deltaMove != 0)
  moveMeFlat(deltaMove);
 if (deltaAngle != 0.0) {
  angle += deltaAngle;
  orientMe(angle);
 }
0 голосов
/ 17 ноября 2009

GLUT бездействует, когда происходит нажатие клавиши? Я думаю, что это не праздно. Ваша функция display () вызывается только тогда, когда окно создано и когда GLUT бездействует, что не позволяет изменить вашу позицию.

Я предлагаю добавить:

glutTimerFunc(40, display, 1);

до конца вашей функции дисплея. Это будет вызывать отображение каждые 40 миллисекунд.

Кроме того, не регистрируйте отображение в качестве функции ожидания, иначе функция ожидания будет запускать множество серий функций таймера.

P.S. Я бы назвал glFlush (); непосредственно перед заменой буферов в вашей функции отображения.

...