这里写目录标题
- 一、基本原理
- 二、代码(完整版本)
- 2.1 头文件
- 2.2 mian函数
- 2.3 OnReshape防止变形函数
- 2.4 Init初始化函数
- 2.5 OnTimer函数
- 2.6 DrawCircle画轨道函数
- 2.7 gltDrawSphere绘制星球函数
- 2.8 OnDisplay函数
- 三、注意事项
一、基本原理
- 使用封装的gltDrawSphere绘制星球,DrawCircle绘制轨道
- 在封装的Init函数中开启灯光,OnDisplay函数中绘制时候写好光照参数
- 在封装的Init函数中使用auxDIBImageLoad函数读取bmp文件的宽、高与data
- 在封装的OnDisplay函数中使用glPushMatrix与glPopMatrix依次绘制每一个星球
- 使用glutTimerFun函数实现动画
二、代码(完整版本)
2.1 头文件
ifndef _HERDER_H_
#define _HERDER_H_
#include <GL/glut.h>
#include <GL/GLAux.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
AUX_RGBImageRec* Images[10];
GLuint ImagesIDs[11]; //索引
char* szFiles[10] = {
("F:\\OGL\\sun\\Sun.bmp"),
("F:\\OGL\\sun\\Mercury.bmp"),
("F:\\OGL\\sun\\Venus.bmp"),
("F:\\OGL\\sun\\Earth.bmp"),
("F:\\OGL\\sun\\Mars.bmp"),
("F:\\OGL\\sun\\Jupiter.bmp"),
("F:\\OGL\\sun\\Saturn.bmp"),
("F:\\OGL\\sun\\Uranus.bmp"),
("F:\\OGL\\sun\\Neptune.bmp"),
("F:\\OGL\\sun\\Moon.bmp"),};
GLubyte* pImg;
GLint iWidth, iHeight;
#define PI 3.1415926
static float year = 0, month = 0, day = 0, angle = 30;
GLint W, H, width, height;
float pox = 2, poy = 3, poz = 8; //照相机的位置
GLint fovy = 60;
void Init();
void OnDisplay();
void OnReshape(int, int);
void OnTimer(int);
void DrawCircle(GLdouble);
void gltDrawSphere(GLfloat, GLint, GLint);
#endif
2.2 mian函数
int main(int argc, char* argv[]){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("太阳系");
Init();
glutReshapeFunc(OnReshape);
glutDisplayFunc(&OnDisplay);
glutTimerFunc(100, OnTimer, 1);
glutMainLoop();
return 0;
}
2.3 OnReshape防止变形函数
void OnReshape(int w, int h){
W = w; H = h;
width = W; height = H;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1, 20);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();}
2.4 Init初始化函数
void Init(){
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < 10; i++){
glGenTextures(1, &ImagesIDs[i]); //生成纹理
glBindTexture(GL_TEXTURE_2D, ImagesIDs[i]); //绑定纹理
//vs2019下必须进行转化
WCHAR wfilename[256];
memset(wfilename, 0, sizeof(wfilename));
//该函数映射一个字符串到一个宽字符(unicode)的字符串
MultiByteToWideChar(CP_ACP, 0, szFiles[i], strlen(szFiles[i]) + 1, wfilename, sizeof(wfilename) / sizeof(wfilename[0]));
Images[i] = auxDIBImageLoad(wfilename); //加载图片
iWidth = Images[i]->sizeX;
iHeight = Images[i]->sizeY;
pImg = Images[i]->data;
//装载纹理
glTexImage2D(GL_TEXTURE_2D, 0, 3, iWidth, iHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pImg);
//纹理过滤、纹理裁剪
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//纹理环境
glTexEnvf(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//启动纹理
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
}
glEnable(GL_LIGHTING); // 开启光照效果
glEnable(GL_LIGHT0);
}
2.5 OnTimer函数
void OnTimer(int value){
day += angle;
glutPostRedisplay();
glutTimerFunc(100, OnTimer, 1);
}
2.6 DrawCircle画轨道函数
//轨道函数
void DrawCircle(GLdouble R){
glPushMatrix();
glRotatef(90.0, 1.0, 0.0, 0.0);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 1000; i++){
GLdouble angle1 = i * 2 * PI / 1000;
glVertex2d(R * cos(angle1), R * sin(angle1));
}
glEnd();
glPopMatrix();
}
2.7 gltDrawSphere绘制星球函数
//绘制星球
void gltDrawSphere(GLfloat fRadius, GLint iSlices, GLint iStacks){
GLfloat drho = (GLfloat)(3.141592653589) / (GLfloat)iStacks;
GLfloat dtheta = 2.0f * (GLfloat)(3.141592653589) / (GLfloat)iSlices;
GLfloat ds = 1.0f / (GLfloat)iSlices;
GLfloat dt = 1.0f / (GLfloat)iStacks;
GLfloat t = 1.0f;
GLfloat s = 0.0f;
GLint i, j;
for (i = 0; i < iStacks; i++){
GLfloat rho = (GLfloat)i * drho;
GLfloat srho = (GLfloat)(sin(rho));
GLfloat crho = (GLfloat)(cos(rho));
GLfloat srhodrho = (GLfloat)(sin(rho + drho));
GLfloat crhodrho = (GLfloat)(cos(rho + drho));
glBegin(GL_TRIANGLE_STRIP);
s = 0.0f;
}
for (j = 0; j <= iSlices; j++){
GLfloat theta = (j == iSlices) ? 0.0f : j * dtheta;
GLfloat stheta = (GLfloat)(-sin(theta));
GLfloat ctheta = (GLfloat)(cos(theta));
GLfloat x = stheta * srho;
GLfloat y = ctheta * srho;
GLfloat z = crho;
glTexCoord2f(s, t);
glNormal3f(x, y, z);
glVertex3f(x * fRadius, y * fRadius, z * fRadius);
x = stheta * srhodrho;
y = ctheta * srhodrho;
z = crhodrho;
glTexCoord2f(s, t - dt);
s += ds;
glNormal3f(x, y, z);
glVertex3f(x * fRadius, y * fRadius, z * fRadius);
}
glEnd();
t -= dt;
}
2.8 OnDisplay函数
void OnDisplay(){
glColor3f(1.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
year = day / 365;
month = day / 30;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fovy, (GLfloat)W / (GLfloat)H, 2, 60.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(pox, poy, poz, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
//太阳光
GLfloat sun_mat_ambient[4] = { 1.0,1.0,1.0,0.0 };
GLfloat sun_mat_diffuse[4] = { 1.0,1.0,0.5,1.0 };
GLfloat sun_mat_specular[4 = { 1.0,1.0,1.0,1.0 };
GLfloat sun_mat_shininess[] = { 10.0 };
GLfloat sun_mat_emission[4]= { 0.1,0.1,0.1,1.0 };
GLfloat mat_ambient[4] = { 0.2,0.2,0.2,1.0 };
GLfloat mat_diffuse[4] = { 1.0,1.0,1.0,1.0 };
GLfloat mat_specular[4] = { 0.5,0.5,0.5,1.0 };
GLfloat mat_shininess[] = { 5.0 };
GLfloat light_position[]={ -10.0,10.0,0.0, 1.0};//光源位置
glLightfv(GL_LIGHT0, GL_POSITION, light_position); // 创建光源
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, sun_mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, sun_mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, sun_mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, sun_mat_shininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, sun_mat_emission);
//绘制太阳
glPushMatrix();
glLightfv(GL_LIGHT0, GL_POSITION, light_position); // 创建光源
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, sun_mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, sun_mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, sun_mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, sun_mat_shininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, sun_mat_emission);
glBindTexture(GL_TEXTURE_2D, ImagesIDs[0]);
glRotatef((GLfloat)month, 0.0, 1.0, 0.0); //太阳自转
glRotatef(90.0, -1.0, 0.0, 0.0);
gltDrawSphere(1.0, 50, 50);
glPopMatrix();
//绘制水星
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
DrawCircle(2.0);//绘制水星的轨道
glRotatef((GLfloat)month / 2, 0.0, 1.0, 0.0); //水星围绕太阳转
glTranslatef(2, 0.0, 0.0); //向x轴右移,让其在轨道上
glBindTexture(GL_TEXTURE_2D, ImagesIDs[1]);
glRotatef((GLfloat)month, 0.0, 1.0, 0.0);
glRotatef(90.0, -1.0, 0.0, 0.0);//自转
gltDrawSphere(0.2, 10, 10);
glPopMatrix();
//绘制金星
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
DrawCircle(3.0);
glRotatef((GLfloat)month / 3, 0.0, 1.0, 0.0); //金星围绕太阳转
glTranslatef(3, 0.0, 0.0); //向x轴右移
glRotatef(30.0, -1.0, 0.0, 0.0);
glBindTexture(GL_TEXTURE_2D, ImagesIDs[2]);
glRotatef((GLfloat)month, 0.0, 1.0, 0.0);
glRotatef(90.0, -1.0, 0.0, 0.0);
gltDrawSphere(0.25, 10, 10);
glPopMatrix();
//绘制地月系统
glPushMatrix();
//绘制地球
DrawCircle(4.5);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
glRotatef((GLfloat)year, 0.0, 1.0, 0.0); //地球公转
glTranslatef(4.5, 0.0, 0.0); //向x轴右移
glRotatef(30.0, -1.0, 0.0, 0.0);//让地球倾斜
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, ImagesIDs[3]);
glRotatef((GLfloat)month, 0.0, 1.0, 0.0);
glRotatef(90.0, -1.0, 0.0, 0.0);
gltDrawSphere(0.4, 20, 20);
glPopMatrix();
//绘制月亮
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
DrawCircle(1.0);
glBindTexture(GL_TEXTURE_2D, ImagesIDs[9]);
glRotatef((GLfloat)month, 0.0, 1.0, 0.0); //月球绕地球转
glTranslatef(1.0, 0.0, 0.0);
glRotatef((GLfloat)month, 0.0, 1.0, 0.0);
glRotatef(90.0, -1.0, 0.0, 0.0);
gltDrawSphere(0.15, 10, 10);
glPopMatrix();
glPopMatrix();
//绘制火星
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
DrawCircle(6.0);
glBindTexture(GL_TEXTURE_2D, ImagesIDs[4]);
glRotatef((GLfloat)month / 1.5, 0.0, 1.0, 0.0);
glTranslatef(6.0, 0.0, 0.0);
glRotatef(30, -1, 0, 0);
glRotatef((GLfloat)month, 0.0, 1.0, 0.0);
glRotatef(90, -1, 0, 0);
gltDrawSphere(0.3, 10, 10);
glPopMatrix();
//绘制木星
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
DrawCircle(7.0);
glBindTexture(GL_TEXTURE_2D, ImagesIDs[5]);
glRotatef((GLfloat)month / 4, 0.0, 1.0, 0.0);
glTranslatef(7.0, 0.0, 0.0);
glRotatef((GLfloat)month / 2, 0.0, 1.0, 0.0);
glRotatef(90, -1, 0, 0);
gltDrawSphere(0.42, 10, 10);
glPopMatrix();
//绘制土星
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
DrawCircle(8.0);
glBindTexture(GL_TEXTURE_2D, ImagesIDs[6]);
glRotatef((GLfloat)month / 3.5, 0.0, 1.0, 0.0);
glTranslatef(8.0, 0.0, 0.0);
glRotatef((GLfloat)month / 2, 0.0, 1.0, 0.0);
glRotatef(90, -1, 0, 0);
gltDrawSphere(0.35, 10, 10);
glPopMatrix();
//绘制天王星
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
DrawCircle(9.0);
glBindTexture(GL_TEXTURE_2D, ImagesIDs[7]);
glRotatef((GLfloat)month / 3, 0.0, 1.0, 0.0);
glTranslatef(9.0, 0.0, 0.0);
glRotatef(30, -1, 0, 0);
glRotatef((GLfloat)month / 2, 0.0, 1.0, 0.0);
glRotatef(90, -1, 0, 0);
gltDrawSphere(0.3, 10, 10);
glPopMatrix();
//绘制海王星
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); // 材质设定
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
DrawCircle(10.0);
glBindTexture(GL_TEXTURE_2D, ImagesIDs[8]);
glRotatef((GLfloat)month / 2, 0.0, 1.0, 0.0);
glTranslatef(10.0, 0.0, 0.0);
glRotatef(30, -1, 0, 0);
glRotatef((GLfloat)month / 2, 0.0, 1.0, 0.0);
glRotatef(90, -1, 0, 0);
gltDrawSphere(0.25, 10, 10);
glPopMatrix();
glutSwapBuffers();
}
三、注意事项
- 除了头文件,其他都是依次放到cpp文件中就可以
- 代码使用vs2019,其他版本的可能会报错,直接百度错误就可以很快的解决
- .glutXXXX的模型都是很简陋的,没有纹理UV坐标的模型,使用glutSolidSphere函数是无法进行贴图。所以写了一个gltDrawSphere函数绘制星球
- 我使用的是vs2019,在使用加载的纹理图片之前,要把路径字符串转化为宽字符字符串,这一点可以查看上面glutSolidSphere函数代码。其他版本可能不需要转化,去掉就可以。