在openGL中使用箭头键旋转参考系
Posted
技术标签:
【中文标题】在openGL中使用箭头键旋转参考系【英文标题】:Use arrow keys to rotate refrence system in openGL 【发布时间】:2013-07-23 13:06:24 【问题描述】:这是写在openGL SuperBible
一书中的代码,用于在屏幕上创建一个弹簧状的点路径:
#include "stdafx.h"
#include <Windows.h>
#include <gl\glut.h>
#include <gl\GLU.h>
#include <gl\GL.h>
#include <math.h>
// Define a constant for the value of PI
#define GL_PI 3.1415f
void ChangeSize(GLsizei , GLsizei );
void SetupRC();
void RenderScene(void);
int main(int argc, CHAR* argv[])
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutCreateWindow("Points Example");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
SetupRC();
glutMainLoop();
return 0;
// Change viewing volume and viewport. Called when window is resized
void ChangeSize(GLsizei w, GLsizei h)
GLfloat nRange = 100.0f;
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset projection matrix stack
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Establish clipping volume (left, right, bottom, top, near, far)
if (w <= h)
glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
else
glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);
// Reset Model view matrix stack
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// This function does any needed initialization on the rendering context
void SetupRC()
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
// Set drawing color to green
glColor3f(0.0f, 1.0f, 0.0f);
// Called to draw scene
void RenderScene(void)
GLfloat x,y,z,angle;
int xRot,yRot; // Storage for coordinates and angles
xRot = 45;
yRot = 45;
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT);
// Save matrix state and do the rotation
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
// Call only once for all remaining points
glBegin(GL_POINTS);
z = -50.0f;
for(angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f)
x = 50.0f*sin(angle);
y = 50.0f*cos(angle);
// Specify the point and move the Z value up a little
glVertex3f(x, y, z);
z += 0.5f;
// Done drawing points
glEnd();
// Restore transformations
glPopMatrix();
// Flush drawing commands
glutSwapBuffers();
其实通过设置xRot=yRot=45度,我已经达到了这个形状。 但是书里说:当这个程序运行时,你看到的只是一个圆圈 点数,因为您最初是直接向下看 z 轴。要查看效果,请使用 箭头键围绕 x 轴和 y 轴旋转绘图。 这意味着我们应该有一些代码使用箭头键来增加和减少 xRot 和 yRot 的值。我为此付出了一些努力。
1-编写函数:
void _cdecl keyboard(int key ,int xRot,int yRot)
switch (key)
case GLUT_KEY_PAGE_UP:
yRot++;
case GLUT_KEY_PAGE_DOWN:
yRot--;
case GLUT_KEY_HOME:
xRot--;
case GLUT_KEY_END:
xRot++;
2-代码顶部的原型:
void _cdecl keyboard(int,int,int);
3-将这两行代码添加到函数RenderScene
的主体中:
GLint key = GLUT_KEY_PAGE_UP;
glutSpecialFunc(keyboard(key,xRot,yRot));
但我不确定它是否会起作用。代码得到错误:
error C2664: 'glutSpecialFunc' : cannot convert parameter 1 from 'void' to 'void (__cdecl *)(int,int,int)'
而且我不知道如何将xRot
和yRot
的更改值返回给调用者函数,因为编译器不允许我定义Pass by referrence
参数并且glutSpecialFunc
的参数是指向空函数的指针!
我的问题的编辑部分 正如 jblocksom 建议的那样,我将代码更改为以下内容: 1-在 main 开始之前定义和初始化全局变量:
int xRot = 0;
int yRot = 0;
2- 在 main 的某处调用 glutSpecialFunc
glutSpecialFunc(keyboard);
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
3-修改键盘功能中的代码
void keyboard(int keyParam ,int mx,int my)
switch (keyParam)
case GLUT_KEY_PAGE_UP:
my++;
case GLUT_KEY_PAGE_DOWN:
my--;
case GLUT_KEY_HOME:
mx--;
case GLUT_KEY_END:
mx++;
glutPostRedisplay();
没有编译和运行时错误。但它不起作用。我认为这是因为当我调用glutSpecialFunc(keyboard)
时,该函数使用鼠标和按键的坐标作为输入参数,因此任何增量或减量都应用于鼠标坐标而不是xRot
或yRot
,这将在@987654339 中使用@ 或 glRotatef(yRot, 0.0f, 1.0f, 0.0f)
所以当调用后两者时,xRot
和 yRot
仍然等于零,不会有旋转。我需要将 xRot
和 yRot
传递给函数 @987654345 @ 但是怎么做???
甚至把函数写成:
void keyboard(int keyParam ,int mx,int my)
switch (keyParam)
case GLUT_KEY_PAGE_UP:
yRot++;
case GLUT_KEY_PAGE_DOWN:
yRot--;
case GLUT_KEY_HOME:
xRot--;
case GLUT_KEY_END:
xRot++;
glutPostRedisplay();
并以glutSpecialFunc(keyboard)
的形式调用它不会有任何区别!!!
【问题讨论】:
【参考方案1】:glutSpecialFunc
向 GLUT 注册一个回调,当用户点击其中一个箭头键时调用该回调;你给它的功能,keyboard
,不是你自称的东西。这就是为什么你不能从中返回任何东西。要从回调中获取数据,您需要设置一个全局变量。
您需要在设置了其他 GLUT 回调的main
中的某个位置调用glutSpecialFunc
(例如glutRenderFunc
)。为了克服编译错误,你可以这样称呼它:
glutSpecialFunc(keyboard);
告诉 GLUT 使用键和鼠标位置调用 keyboard()
。
将RenderScene
中引用的xRot
和yRot
变量设为全局变量。
将keyboard
的函数签名更改为不使用xRot
和yRot
作为变量名,以便引用全局变量名:
void _cdecl keyboard(int key, int mx, int my)
您可能还需要在keyboard
末尾调用glutPostRedisplay()
,这将告诉GLUT 重绘场景。
希望之后它应该可以工作,祝你好运!
【讨论】:
感谢@jblocksom,但请参阅我的问题的已编辑部分。我希望你能帮助我。以上是关于在openGL中使用箭头键旋转参考系的主要内容,如果未能解决你的问题,请参考以下文章
在 OpenGL 中使用箭头键移动一些形状 - 它缩小而不是移动