写在前面:最近在学习三维Opengl相关技术,做了一个太阳系三维场景的简单动画,先看一下效果图:
演示视屏:https://www.bilibili.com/video/BV1HK4y1D7pM
界面采用Qt进行搭建,主要的渲染绘制过程如下:
1.球体的绘制函数:
glPushMatrix();
if (m_enableOrbit)
{
glDisable(GL_LIGHTING);
glColor3d(0.5, 0.5, 0.5);
glBegin(GL_LINE_LOOP);
int n = 50;
for (int i = 0; i < n; ++i)
glVertex3f(rotateRadius*cos(2 * 3.1415926 / n * i), 0.0f, rotateRadius*sin(2 * 3.1415926 / n * i));
glEnd();
glEnable(GL_LIGHTING);
}
glRotatef(revolution * speed, 0, 1, 0);
glTranslatef(0, 0, rotateRadius);
glRotatef(rotation * speed * 5.0, 0, 1, 0);
glRotatef(90, 1, 0, 0);
glScalef(scale, scale, scale);
glColor3f(1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex_id);
gluSphere(sphere, 1, 40, 40);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
2.环境的渲染:
clock_t current_t = GetTick();
float delta_t = (current_t - m_time) * 0.001 * m_pMainOpenGLWidgetPrivate->m_speed;
if (m_pMainOpenGLWidgetPrivate->m_enableRevolution)
revolution += delta_t;
m_rotation += delta_t;
m_time = current_t;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-m_pMainOpenGLWidgetPrivate->m_translateZ * aspect, m_pMainOpenGLWidgetPrivate->m_translateZ * aspect, -m_pMainOpenGLWidgetPrivate->m_translateZ, m_pMainOpenGLWidgetPrivate->m_translateZ, -100, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
m_pMainOpenGLWidgetPrivate->drawBackground();
glTranslated(m_pMainOpenGLWidgetPrivate->m_translateX, m_pMainOpenGLWidgetPrivate->m_translateY, m_pMainOpenGLWidgetPrivate->m_translateZ - 40);
glRotated(m_rotateX + 25, 1.0, 0.0, 0.0);
glRotated(m_rotateZ, 0.0, 0.0, 1.0);
//light
float sunlight_pos[4] = { 0.0, 0.0, 0.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, sunlight_pos);
float artfical_light_pos[4] = { 1.0, 1.0, 1.0, 0.0 };
glLightfv(GL_LIGHT1, GL_POSITION, artfical_light_pos);
float while_color[4] = { 1.0f * m_pMainOpenGLWidgetPrivate->m_lightBrightness, 1.0f * m_pMainOpenGLWidgetPrivate->m_lightBrightness, 1.0f * m_pMainOpenGLWidgetPrivate->m_lightBrightness, 1.0 };
float black_color[4] = { 0.0, 0.0, 0.0, 1.0 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, while_color);
glLightfv(GL_LIGHT0, GL_SPECULAR, while_color);
glLightfv(GL_LIGHT0, GL_AMBIENT, black_color);
glLightfv(GL_LIGHT1, GL_DIFFUSE, while_color);
glLightfv(GL_LIGHT1, GL_SPECULAR, while_color);
glLightfv(GL_LIGHT1, GL_AMBIENT, black_color);
m_pMainOpenGLWidgetPrivate->m_enableSunLight? glEnable(GL_LIGHT0): glDisable(GL_LIGHT0);
glEnable(GL_LIGHT1);
float base_color[4] = { 1.0f, 1.0f, 1.0f, 1 };
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, base_color);
float specular_color[4] = { 1.0f, 1.0f, 1.0f, 1 };
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color);
glMaterialf(GL_FRONT, GL_SHININESS, 50);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glScalef(3.0, 3.0, 3.0);
glColor3f(1.0, 1.0, 1.0);
glRotatef(m_rotation, 0, 1, 0);
glRotatef(90, 1, 0, 0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_pMainOpenGLWidgetPrivate->m_textures_ids[0]);
gluSphere(m_sphere, 1, 40, 40);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
float color[4] = { 0.5f, 0.5f, 0.5f, 1 };
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
float specular_color2[4] = { 0.8f, 0.8f, 0.8, 1 };
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color2);
glMaterialf(GL_FRONT, GL_SHININESS, 30);
m_pMainOpenGLWidgetPrivate->drawPlanet(m_pMainOpenGLWidgetPrivate->m_textures_ids[1], 0.2, 6, 3,revolution,m_rotation,m_sphere);
m_pMainOpenGLWidgetPrivate->drawPlanet(m_pMainOpenGLWidgetPrivate->m_textures_ids[2], 0.6, 9, 2, revolution, m_rotation, m_sphere);
m_pMainOpenGLWidgetPrivate->drawPlanet(m_pMainOpenGLWidgetPrivate->m_textures_ids[3], 0.7, 11, 1, revolution, m_rotation, m_sphere);
m_pMainOpenGLWidgetPrivate->drawPlanet(m_pMainOpenGLWidgetPrivate->m_textures_ids[4], 0.5, 16, 0.8, revolution, m_rotation, m_sphere);
m_pMainOpenGLWidgetPrivate->drawPlanet(m_pMainOpenGLWidgetPrivate->m_textures_ids[5], 1.5, 19, 0.7, revolution, m_rotation, m_sphere);
m_pMainOpenGLWidgetPrivate->drawPlanet(m_pMainOpenGLWidgetPrivate->m_textures_ids[6], 1.2, 21, 0.5, revolution, m_rotation, m_sphere);
float saturnScale = 1.2; float rotateRadius = 21; float saturnm_speed = 0.5;
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
glPushMatrix();
glRotatef(revolution * saturnm_speed, 0, 1, 0);
glTranslatef(0, 0, rotateRadius);
glRotatef(m_rotation * saturnm_speed * 5.0, 0, 1, 0);
saturnScale *= 2;
glScalef(saturnScale, saturnScale, saturnScale);
glColor3f(1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_pMainOpenGLWidgetPrivate->m_textures_ids[10]);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(-1.0, 0.0, -1.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 0.0, 1.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 0.0, 1.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glDisable(GL_ALPHA_TEST);
m_pMainOpenGLWidgetPrivate->drawPlanet(m_pMainOpenGLWidgetPrivate->m_textures_ids[7], 1.1, 24, 0.4, revolution, m_rotation, m_sphere);
m_pMainOpenGLWidgetPrivate->drawPlanet(m_pMainOpenGLWidgetPrivate->m_textures_ids[8], 0.9, 28, 1, revolution, m_rotation, m_sphere);
m_pMainOpenGLWidgetPrivate->drawSatellites(revolution,m_rotation,m_sphere);
glPushMatrix();
glScaled(5.0, 5.0, 5.0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_pMainOpenGLWidgetPrivate->m_textures_ids[12]);
glPushMatrix();
glTranslated(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glTexCoord2d(0.0, 0.0);
glVertex3f(0.0, 0.0, -1.0);
glTexCoord2d(1.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glTexCoord2d(1.0, 1.0);
glVertex3f(1.0, 0.0, 1.0);
glTexCoord2d(0.0, 1.0);
glVertex3f(0.0, 0.0, 1.0);
glEnd();
glPopMatrix();
glPushMatrix();
glRotated(180, 0.0, 1.0, 0.0);
glTranslated(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glTexCoord2d(0.0, 0.0);
glVertex3f(0.0, 0.0, -1.0);
glTexCoord2d(1.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glTexCoord2d(1.0, 1.0);
glVertex3f(1.0, 0.0, 1.0);
glTexCoord2d(0.0, 1.0);
glVertex3f(0.0, 0.0, 1.0);
glEnd();
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
gluSphere(m_sphere, 1, 40, 40);
glPopMatrix();
所有的鼠标事件操作使用了Qt的信号槽进行处理:
void MainWindow::initConnect(void)
{
connect(ui.orbitCheckBox, &QCheckBox::stateChanged, this, &MainWindow::on_orbitCheckBoxstateChanged);
connect(ui.lightCheckBox, &QCheckBox::stateChanged, this, &MainWindow::on_lightCheckBoxChanged);
connect(ui.startPushButton, &QPushButton::clicked, this, &MainWindow::on_startPushButtonClicked);
connect(ui.spinBox, SIGNAL(valueChanged(int)), this, SLOT(on_spinBoxValueChanged(int)));
connect(ui.horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(on_horizontalSliderValueChanged(int)));
connect(ui.verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(on_verticalSliderValueChanged(int)));
connect(ui.horizontalSliderLightness, SIGNAL(valueChanged(int)), this, SLOT(on_horizontalSliderLightnessValueChanged(int)));
connect(ui.horizontalSliderZoom, SIGNAL(valueChanged(int)), this, SLOT(on_horizontalSliderZoomValueChanged(int)));
}
void MainWindow::disConnect(void)
{
disconnect(ui.orbitCheckBox, &QCheckBox::stateChanged, this, &MainWindow::on_orbitCheckBoxstateChanged);
disconnect(ui.lightCheckBox, &QCheckBox::stateChanged, this, &MainWindow::on_lightCheckBoxChanged);
disconnect(ui.startPushButton, &QPushButton::clicked, this, &MainWindow::on_startPushButtonClicked);
disconnect(ui.spinBox, SIGNAL(valueChanged(int)), this, SLOT(on_spinBoxValueChanged(int)));
disconnect(ui.horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(on_horizontalSliderValueChanged(int)));
disconnect(ui.verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(on_verticalSliderValueChanged(int)));
disconnect(ui.horizontalSliderLightness, SIGNAL(valueChanged(int)), this, SLOT(on_horizontalSliderLightnessValueChanged(int)));
disconnect(ui.horizontalSliderZoom, SIGNAL(valueChanged(int)), this, SLOT(on_horizontalSliderZoomValueChanged(int)));
}
可执行工程下载:https://download.csdn.net/download/weixin_39951988/15490556
工程源码下载:https://download.csdn.net/download/weixin_39951988/15490585