代码部分参考:
参考
使用glut + opengl
题目要求:
完成一个简单的日地月系统演示程序。要求必须考虑太阳的自转、 地球和月亮的公转和自转;能够演示地球上的白天黑夜和四季变化,以及月亮的圆缺效果。为了增强演示效果,请绘制出太阳、地球和月亮的经纬线、赤道和轴线。为了增强真实感,请在太阳、地球、月亮的表面使用合 适的纹理。太阳的自转周期、地球和月亮的自转和公转周期以及地球的黄 赤角等数据请到互联网上查阅。
结果图:
以下源码存在几个问题:
注意,没有实现月亮的圆缺和四季变换
四季变换的实现思路是判断每次重绘图时,判断角度的取值分成四个区间。
不同区间贴不同的图。
月亮的圆缺则需要复杂的光照,来自地球的光的镜面反射,和太阳光的镜面反射。
还有一个小问题,不清楚为什么贴图没有跟着一起转,如果你知道怎么修改欢迎提出来。
#include <windows.h>
#include <gl/glew.h>
#include <math.h>
#include <GL/freeglut.h>
#include <cstdio>
#define PI 2*acos(0)
GLdouble speed=0.1,day,month,year,solarcycle;
//月亮、地球、太阳的半径
GLfloat mr=0.15,er=0.3,sr=0.4;
//月亮、地球的公转半径
GLfloat mrr=0.6,err=2;
// 三个贴图
GLuint texSun;
GLuint texPlanet;
GLuint texMoon;
// 创建贴图
void Texture(const char *FileName,GLuint& unTexture)
{
FILE *file =fopen(FileName ,"rb");
fseek(file,sizeof(BITMAPFILEHEADER),SEEK_SET);
BITMAPINFOHEADER info;
fread(&info ,sizeof(info),1,file);
long Width=info.biWidth;
long Height=info.biHeight;
GLubyte* pixels;
pixels = (GLubyte*)malloc(Width*Height*3);
fread(pixels,Width*Height*3,1,file);
fclose(file);
glGenTextures(1, &unTexture); // 创建一个纹理,unTexture
glBindTexture(GL_TEXTURE_2D, unTexture);
glTexImage2D(GL_TEXTURE_2D,0,3,Width,Height,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,pixels);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
}
void textPara(){
glEnable(GL_TEXTURE_2D);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); // 设置s方向的纹理自动生成
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); // 设置t方向的纹理
glEnable(GL_TEXTURE_GEN_S); // 自动生成s方向纹理坐标
glEnable(GL_TEXTURE_GEN_T); // 自动生成t方向纹理坐标
}
// 设置贴图
void setTex(GLuint tex){
textPara();
glBindTexture(GL_TEXTURE_2D, tex);
}
// 关闭贴图
void shutdownTex(){
glDisable(GL_TEXTURE_2D);
}
void init()
{
glClearColor(0,0,0.1,1);
glEnable(GL_POINT_SMOOTH|GL_LINE_SMOOTH|GL_POLYGON_SMOOTH);
}
void keyboard(GLubyte key,GLint x,GLint y)
{
if(key==27) exit(0);
}
void timer(GLint millis)
{
day+=speed*360/0.997;
month+=speed*360/29.5;
year+=speed*360/365.2475;
solarcycle+=speed*360/27.5;
glutPostRedisplay();
glutTimerFunc(millis,timer,millis);
}
void reshape(GLint w,GLint h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30,(GLfloat)w/h,1,1000);
glTranslatef(0,0,-8);
glRotatef(30,1,0,0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// 光源设置
void light(GLfloat r)
{
GLfloat pos[][4]=
{
{r,0,0,1},{-r,0,0,1},{0,r,0,1},
{0,-r,0,1},{0,0,r,1},{0,0,-r,1}
};
GLfloat params[]={0.9,0.9,0.9,1};
for(int i=0;i<6;i++)
{
glLightfv(GL_LIGHT0+i,GL_POSITION,pos[i]);
glLightfv(GL_LIGHT0+i,GL_DIFFUSE,params);
glEnable(GL_LIGHT0+i);
}
}
void material(GLfloat r,GLfloat g,GLfloat b)
{
GLfloat params[]={r,g,b,1};
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT,GL_DIFFUSE,params);
}
void color(GLfloat r,GLfloat g,GLfloat b)
{
glDisable(GL_LIGHTING);
glColor3f(r,g,b);
}
// 经纬线
void wire(GLfloat r)
{
color(0.5,0.5,0.5);
glutWireSphere(1.005*r,1,1);
}
void sun(GLfloat r)
{
glPushMatrix();
glRotatef(90,-1,0,0);
color(0.9,0.1,0.1);
setTex(texSun);
glutSolidSphere(r,24,12);
wire(r);
glPopMatrix();
shutdownTex();
}
void earth(GLfloat r)
{
glPushMatrix();
glRotatef(90,-1,0,0);
material(0.1,0.1,0.9);
setTex(texPlanet);
//glBindTexture(GL_TEXTURE_2D,texPlanet);
glutSolidSphere(r,24,12);
wire(r);
glPopMatrix();
shutdownTex();
}
void moon(GLfloat r)
{
glPushMatrix();
glRotatef(90,-1,0,0);
material(0.75,0.75,0.1);
setTex(texMoon);
glutSolidSphere(r,24,12);
wire(r);
glPopMatrix();
}
// 黄道
void ecliptic(){
int n=1000;
glPushMatrix();
glColor3f(255, 232, 150);
glBegin(GL_LINE_LOOP);
for (int i=0; i<n; i++) {
glVertex3d(err*cos(2*PI*i/n), 0, err*sin(2*PI*i/n));
}
glEnd();
glPopMatrix();
}
// 月球公转轨道 白道
void moonglade(){
int n=1000;
glPushMatrix();
glColor3f(0, 1, 0);
glBegin(GL_LINE_LOOP);
for (int i=0; i<n; i++) {
glVertex3d(mrr*cos(2*PI*i/n), 0, mrr*sin(2*PI*i/n));
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// 显示黄道
ecliptic();
// 太阳光照、太阳自转
light(sr);
glPushMatrix();
glRotatef(solarcycle,0,1,0);
sun(sr);
glPopMatrix();
// 地球公转
glRotatef(year,0,1,0);
glTranslatef(err,0,0);
glRotatef(-year,0,1,0);
// 黄赤交角
glRotatef(-23.5,0,0,1);
// 地球自转
//自传的同时显示月球公转轨道
moonglade();
glEnd();
glRotatef(day,0,1,0);
earth(er);
glPopMatrix();
// 月球公转
glRotatef(month,0,1,0);
glTranslatef(mrr,0,0);
moon(mr);
shutdownTex();
glutSwapBuffers();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGBA|GLUT_DOUBLE);
glutInitWindowSize(1200,600);
glutCreateWindow("Galaxy");
glutKeyboardFunc(keyboard);
init();
Texture("F:/Graph/sun.bmp",texSun);
Texture("F:/Graph/planet.bmp",texPlanet);
Texture("F:/Graph/planet.bmp",texMoon);
textPara();
glutTimerFunc(25,timer,25);
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}
贴图为:
要自己修改成bmp格式,简书不让上传bmp格式