[英]OpenGL/Glut: Making the camera rotate around X axis with arrow keys?
我正在嘗試使用 gluLookAt() 函數,以便當我按下向上和向下鍵時,相機會圍繞 X 軸移動
我正在嘗試一種我在以下網址看到的方法: http : //www.lighthouse3d.com/tutorials/glut-tutorial/keyboard-example-moving-around-the-world/但它對我不起作用。 有人知道更簡單的方法嗎? 我應該將 gluLookAt() 放在 myDisplay() 函數上的什么位置?
#include"glut.h"
#include<cmath>
#include<iostream>
using namespace std;
float xr = 0, yr = 0; //to control the object's movement from left to right
// actual vector representing the camera's direction
float lx = 0.0f, lz = -1.0f;
// XZ position of the camera
float x = 0.0f, z = 5.0f;
GLfloat angle = 0.0f;
int refreshmill = 1;
void timer(int value) { //to control the rotation of the object
glutPostRedisplay();
glutTimerFunc(refreshmill, timer, 0);
}
void myDisplay(void) {
//Circle One
float theta;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glBegin(GL_POLYGON);
for (int x = 0; x < 360; x++) {
theta = x * 3.142 / 180;
glVertex2f(150 * cos(theta)+xr,150 * sin(theta)+yr);
}
glEnd();
glPopMatrix();
//Circle Two
float theta2;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(0.5f, 0.0f, 0.0f); // rotation
glRotatef(angle, 0.0f, 0.0f, -0.5f); // rotation
glBegin(GL_POLYGON);
glColor3f(0, 0, 1);
for (int x = 0; x < 360; x++) {
theta2 = x * 3.142 / 180;
glVertex2f(150 + 15 * cos(theta2) + xr, 15 * sin(theta2) + yr);
}
glutSwapBuffers();
angle += 0.2; // rotation
glEnd();
glPopMatrix();
//Draw Star
glColor3ub(119, 193, 15);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glBegin(GL_POLYGON);
glVertex2d(15+xr, 60+yr);
glVertex2d(75+xr, 75+yr); //right peak
glVertex2d(15+xr, 90+yr);
glVertex2d(0+xr, 150+yr); //Up-peak Changed
glVertex2d(-15+xr, 90+yr);
glVertex2d(-75+xr,75+yr);
glVertex2d(-15+xr, 60+yr);
glVertex2d(0+xr,0+yr);
glEnd();
glPopMatrix();
glFlush();
glutPostRedisplay();
glutSwapBuffers();
}
void renderScene(void) {
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
// Set the camera
gluLookAt(x, 1.0f, z,
x + lx, 1.0f, z + lz,
0.0f, 1.0f, 0.0f);
// Draw ground
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, -100.0f);
glEnd();
myDisplay();
glutSwapBuffers();
}
//Move to left or right
void keyboard(int key, int x, int y) {
float fraction = 0.1f;
switch (key) {
case GLUT_KEY_RIGHT:
xr++;
cout << x << endl;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
xr--;
cout << x << endl;
glutPostRedisplay();
break;
case GLUT_KEY_UP:
angle -= 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
case GLUT_KEY_DOWN:
angle += 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
}
}
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-250, 250, -250, 250); //IMPORTANT- Define from negative to positive
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
// init GLUT and create window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Homework: Circle");
// register callbacks
glutDisplayFunc(myDisplay);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutTimerFunc(0,timer,0);
glutSpecialFunc(keyboard);
// OpenGL init
init();
// enter GLUT event processing cycle
glutMainLoop();
}
您可以在init()
處使用gluLookAt
初始化您的相機,然后在按下箭頭鍵時旋轉它。 如果你想圍繞它的局部 x 軸旋轉相機,假設你的初始模型視圖矩陣是V
,新發生的圍繞 x 軸的旋轉是R
,你需要將模型視圖矩陣設置為R*V
,而不是V*R
。
case GLUT_KEY_UP:
GLfloat temp[16];
glGetFloatv(GL_MODELVIEW_MATRIX, temp);
glLoadIdentity();
glRotate(stepAngle, 1, 0, 0); // calculate stepAngle by your self
glMultMatrixf(temp);
break;
渲染過程中不需要重置modelview矩陣,視圖部分已經完成,請確保在渲染整個場景后恢復它:
glPushMatrix(GL_MODELVIEW_MATRIX)
// don't call glLoadIdentity() here, you don't need to reset view part.
...
...
glPopMatrix()
首先應該只有1個顯示回調函數:
int main(int argc, char** argv) {
// [...]
// glutDisplayFunc(myDisplay); <----- DELETE!!!
glutDisplayFunc(renderScene);
// glutIdleFunc(renderScene); <----- DELETE!!!
// [...]
}
使用擴展的近平面和遠平面設置正交投影。 如果對象繞 X 軸旋轉,它會占用 3 個維度的空間:
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-250, 250, -250, 250, -250, 250); // <----
glMatrixMode(GL_MODELVIEW);
}
添加一個在鍵盤事件中改變的變量anglaX
:
float angleX = 0.0f;
void keyboard(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT: xr++; break;
case GLUT_KEY_LEFT: xr--; break;
case GLUT_KEY_UP: angleX -= 1.0f; break;
case GLUT_KEY_DOWN: angleX += 1.0f; break;
}
}
設置視圖后旋轉模型:
gluLookAt(x, 0.0f, z, x, 0.0f, z-1.0f, 0.0f, 1.0f, 0.0f);
glRotatef(angleX, 1, 0, 0);
不要調用glutSwapBuffers()
、 glFlush()
和glutPostRedisplay()
,除非在renderScene
結束時:
void timer(int value) { //to control the rotation of the object
// glutPostRedisplay(); <--- DELETE
glutTimerFunc(refreshmill, timer, 0);
}
void myDisplay(void) {
//Circle One
float theta;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glPushMatrix();
glBegin(GL_POLYGON);
for (int x = 0; x < 360; x++) {
theta = x * 3.142 / 180;
glVertex2f(150 * cos(theta)+xr,150 * sin(theta)+yr);
}
glEnd();
glPopMatrix();
//Circle Two
float theta2;
glPushMatrix();
glTranslatef(0.5f, 0.0f, 0.0f); // rotation
glRotatef(angle, 0.0f, 0.0f, -0.5f); // rotation
glBegin(GL_POLYGON);
glColor3f(0, 0, 1);
for (int x = 0; x < 360; x++) {
theta2 = x * 3.142 / 180;
glVertex2f(150 + 15 * cos(theta2) + xr, 15 * sin(theta2) + yr);
}
angle += 0.2; // rotation
glEnd();
glPopMatrix();
//Draw Star
glColor3ub(119, 193, 15);
glPushMatrix();
glBegin(GL_POLYGON);
glVertex2d(15+xr, 60+yr);
glVertex2d(75+xr, 75+yr); //right peak
glVertex2d(15+xr, 90+yr);
glVertex2d(0+xr, 150+yr); //Up-peak Changed
glVertex2d(-15+xr, 90+yr);
glVertex2d(-75+xr,75+yr);
glVertex2d(-15+xr, 60+yr);
glVertex2d(0+xr,0+yr);
glEnd();
glPopMatrix();
}
void renderScene(void) {
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set the camera
gluLookAt(x, 0.0f, z, x, 0.0f, z-1.0f, 0.0f, 1.0f, 0.0f);
glRotatef(angleX, 1, 0, 0);
// Draw ground
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, -100.0f);
glEnd();
myDisplay();
glFlush();
glutPostRedisplay();
glutSwapBuffers();
}
此外,我建議使用雙緩沖:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.