OpenGL 键盘相机控制

发布于 2024-08-11 09:11:29 字数 3604 浏览 2 评论 0原文

我一直在关注 OpenGL 的教程系列:过剩

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);
}

我相信这几乎是我正在处理的所有事情,所以基本上应该发生的是,当我按 UP 键 deltaMove 应该 = 50 时,当发生这种情况时, void display(void) 中的 if 语句应该执行 moveMeFlat (增量移动);我不知道我是否做错了,或者是否有更好的结果......

我可以在相关开关案例中移动“moveMeFlat(deltaMove)”,但这不允许我进行我想要的运动。它似乎可以使用上面教程中的源代码来实现正确的功能,但在我的情况下则不然,所以我的假设是它与显示中的 if 语句有关。

我正在寻找的最终结果是能够通过左右旋转相机来向前和向后工作。我希望能够按前进和向左键并看到相机转向像一款赛车游戏...

I have been following this tutorial series for OpenGL: GLUT:

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

I have reached the stage of implementing camera controls using the keyboard:

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

When doing the advanced tutorial it stops working. I've pretty much just copied and pasted it. When I run its version of the code it works. Mine just doesn't seem to work. It should rotate the camera view when moving left and right and move forward and backwards when using up and down keys.

My code is here broken down:

This part of my code renders components in the scene with init() which initilizes values etc.:

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();
}

This is my main loop function:

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;
}

Here are my input functions which are called:

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);
}

Variables that get used by the camera and the functions that should change it:

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);
}

I believe that's pretty much everything I am working with so basically what should happen is that when I press UP key deltaMove should = 50 and when this happens the if statement in void display(void) should do moveMeFlat(deltaMove); I don't know if I am doing this wrong or if there is a better result....

I can move "moveMeFlat(deltaMove)" within the relevant switch cases but this does not allow me to have the movement that I want. It seems to work using the source code from the tutorials above with the right functionality but not in my case so my assumption is that it's to do with the if statement in display.

The end result I am looking for is to be able to have forwards and backwards working with left and right rotating the camera. I would like to be able to press forward and left key and see the camera swerve left like in a racing game...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薯片软お妹 2024-08-18 09:11:29

尝试去掉所有全局变量声明前面的 static 。

static 的最后一个用途是作为代码文件中的全局变量。在这种情况下,使用 static 表示属于项目一部分的其他文件中的源代码无法访问该变量。只有单个文件内的代码才能看到该变量。 (它的范围(或可见性)仅限于文件。)此技术可用于模拟面向对象的代码,因为它限制了变量的可见性,从而有助于避免命名冲突。这种 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);
 }

Try getting rid of static in front of all of your global variable declarations.

The last use of static is as a global variable inside a file of code. In this case, the use of static indicates that source code in other files that are part of the project cannot access the variable. Only code inside the single file can see the variable. (It's scope -- or visibility -- is limited to the file.) This technique can be used to simulate object oriented code because it limits visibility of a variable and thus helps avoid naming conflicts. This use of static is a holdover from C.

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

Also, instead of this:

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

try this:

if (deltaMove != 0)
  moveMeFlat(deltaMove);
 if (deltaAngle != 0.0) {
  angle += deltaAngle;
  orientMe(angle);
 }
相权↑美人 2024-08-18 09:11:29

当按键发生时 GLUT 是否空闲?我想它并没有闲着。仅当创建窗口且 GLUT 空闲时才会调用您的 display() 函数,这不允许更改您的位置。

我建议添加:

glutTimerFunc(40, display, 1);

到显示函数的末尾。这将导致每 40 毫秒调用一次显示。

另外,不要将显示注册为空闲函数,否则您将让空闲函数启动许多系列的计时器函数。

PS 我会调用 glFlush();就在交换显示函数中的缓冲区之前。

Is GLUT idle when a key press is occurring? I think it is not idle. Your display() function is only called when the window is created and when GLUT is idle, which doesn't allow your position to be changed.

I suggest adding:

glutTimerFunc(40, display, 1);

to the end of your display function. This will cause display to be called every 40 milliseconds.

Also, don't register display as the idle function, or you'll have the idle function starting lots of series of timer functions.

P.S. I would call glFlush(); just before swapping the buffers in your display function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文