OpenGL实现简单的日地月旋转动画,在日地月球体表面贴上纹理,使之更加真实,加上鼠标和键盘简单操作的代码
时间: 2024-02-12 12:04:32 浏览: 21
以下是实现简单的日地月旋转动画,并在日地月球体表面贴上纹理的 OpenGL 代码,同时还加入了鼠标和键盘简单操作的代码。
```c++
#include <GL/glut.h>
#include <cmath>
GLuint sunTexture, earthTexture, moonTexture;
GLfloat earthAngle = 0.0, moonAngle = 0.0;
GLfloat distance = -20.0;
void loadTextures() {
// 加载纹理
sunTexture = SOIL_load_OGL_texture("sun.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
earthTexture = SOIL_load_OGL_texture("earth.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
moonTexture = SOIL_load_OGL_texture("moon.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
}
void init() {
// 初始化纹理
loadTextures();
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_DEPTH_TEST);
}
void reshape(int w, int h) {
// 设置视口
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, GLfloat(w) / GLfloat(h), 1.0, 100.0);
}
void drawSphere(GLfloat radius, GLuint texture) {
// 绘制球体
glBindTexture(GL_TEXTURE_2D, texture);
GLUquadricObj *sphere = gluNewQuadric();
gluQuadricTexture(sphere, GL_TRUE);
gluQuadricNormals(sphere, GLU_SMOOTH);
gluSphere(sphere, radius, 32, 32);
gluDeleteQuadric(sphere);
}
void display() {
// 渲染场景
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, distance);
// 绘制太阳
glBindTexture(GL_TEXTURE_2D, sunTexture);
drawSphere(2.0, sunTexture);
// 绘制地球
glRotatef(earthAngle, 0.0, 1.0, 0.0);
glTranslatef(5.0, 0.0, 0.0);
drawSphere(1.0, earthTexture);
// 绘制月球
glRotatef(moonAngle, 0.0, 1.0, 0.0);
glTranslatef(1.5, 0.0, 0.0);
drawSphere(0.5, moonTexture);
glutSwapBuffers();
}
void idle() {
// 动画效果
earthAngle += 0.5;
moonAngle += 1.0;
glutPostRedisplay();
}
void mouse(int button, int state, int x, int y) {
// 鼠标控制视角
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
int centerX = glutGet(GLUT_WINDOW_WIDTH) / 2;
int centerY = glutGet(GLUT_WINDOW_HEIGHT) / 2;
glutWarpPointer(centerX, centerY);
glutSetCursor(GLUT_CURSOR_NONE);
} else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
glutSetCursor(GLUT_CURSOR_INHERIT);
}
}
void motion(int x, int y) {
// 鼠标控制视角
int centerX = glutGet(GLUT_WINDOW_WIDTH) / 2;
int centerY = glutGet(GLUT_WINDOW_HEIGHT) / 2;
int deltaX = x - centerX;
int deltaY = y - centerY;
glRotatef(deltaX, 0.0, 1.0, 0.0);
glRotatef(deltaY, 1.0, 0.0, 0.0);
glutWarpPointer(centerX, centerY);
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y) {
// 键盘控制视角
switch (key) {
case 'w':
glTranslatef(0.0, 0.0, 1.0);
break;
case 's':
glTranslatef(0.0, 0.0, -1.0);
break;
case 'a':
glTranslatef(1.0, 0.0, 0.0);
break;
case 'd':
glTranslatef(-1.0, 0.0, 0.0);
break;
}
glutPostRedisplay();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutCreateWindow("Solar System");
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(idle);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
```
在代码中,我们使用了 SOIL 库来加载纹理图片,并使用 gluQuadric 对象来绘制球体。在 display 函数中,我们分别绘制了太阳、地球和月球,并使用 glRotatef 和 glTranslatef 函数来实现它们的旋转和平移。在 idle 函数中,我们每次增加一定的角度来实现不断旋转的动画效果。
同时,我们还加入了鼠标和键盘控制视角的功能。当用户按下鼠标左键时,我们将光标移动到窗口中心,并隐藏光标,以实现视角旋转。当用户松开鼠标左键时,我们将光标恢复,并取消视角旋转。当用户按下键盘上的 WASD 按键时,我们分别对视角进行前后移动和左右移动的操作。
需要注意的是,由于我们使用了深度缓冲,因此在渲染时需要先清除深度缓冲区。另外,在绘制球体时,我们使用了纹理映射来贴上纹理,使得球体表面更加真实。