#include <GL/glut.h>
#include<windows.h>
#include<time.h>
#include<stdio.h>
// 太阳、地球和月亮
// 假设每个月都是30天
// 一年12个月,共是360天
static int day = 200; // day的变化:从0到359
void myDisplay0(void)
{
/****************************************************
这里的内容照搬上一课的,只因为使用了双缓冲,补上最后这句
*****************************************************/
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75, 1, 1, 4000000000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, -2000000000, 2000000000, 0, 0, 0, 0, 0, 1);
// 绘制红色的“太阳”
glColor3f(1.0f, 0.0f, 0.0f);
glutSolidSphere(69600000, 20, 20);
// 绘制蓝色的“地球”
glColor3f(0.0f, 0.0f, 1.0f);
glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f);
glTranslatef(150000000, 0.0f, 0.0f);
glutSolidSphere(15945000, 20, 20);
// 绘制黄色的“月亮”
glColor3f(1.0f, 1.0f, 0.0f);
glRotatef(day/30.0*360.0 - day/360.0*360.0, 0.0f, 0.0f, -1.0f);
glTranslatef(38000000, 0.0f, 0.0f);
glutSolidSphere(4345000, 20, 20);
glFlush();
glutSwapBuffers();
}
void setLight(void)
{
static const GLfloat light_position[] = {-1.0f, -1.0f, 1.0f, 1.0f};
static const GLfloat light_ambient[] = {0.2f, 0.2f, 0.2f, 1.0f};
static const GLfloat light_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
static const GLfloat light_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
}
void setMatirial(const GLfloat mat_diffuse[4], GLfloat mat_shininess)
{
static const GLfloat mat_specular[] = {0.0f, 0.0f, 0.0f, 0.0f};//
static const GLfloat mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};
// static const GLfloat mat_diffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
glMaterialf (GL_FRONT, GL_SHININESS, mat_shininess);
}
double CalFrequency()//获取帧速度
{
static int count;
static double save;
static clock_t last, current;
double timegap;
++count;
if( count <= 50 )
return save;
count = 0;
last = current;
current = clock();
timegap = (current-last)/(double)CLK_TCK;
save = 50.0/timegap;
return save;
}
void myDisplay(void)
{
//double FPS = CalFrequency();
// printf("FPS = %f\n", FPS);
// 定义一些材质颜色
const static GLfloat red_color[] = {1.0f, 0.0f, 0.0f, 1.0f};
const static GLfloat y_color[] = {0.0f, 1.0f, 1.0f, 0.3333f};
const static GLfloat blue_color[] = {0.0f, 0.0f, 1.0f, 0.5f};
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// 清除屏幕
gluPerspective(90, 1, 1, 120);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, -60, 60, 0, 0, 0, 0, 0, 1);
// 启动混合并设置混合因子
// glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// 设置光源
setLight();
setMatirial(red_color, 30.0);
//glColor3f(1.0f, 0.0f, 0.0f);
glutSolidSphere(6.96, 20, 20);
/* // 以(0, 0, 0.5)为中心,绘制一个半径为.3的不透明红色球体(离观察者最远)
glPushMatrix();
glTranslatef(-0.5f, 0.0f, 0.5f);
glutSolidSphere(0.3, 30, 30);
glPopMatrix();
// 下面将绘制半透明物体了,因此将深度缓冲设置为只读
glDepthMask(GL_FALSE);
*/
// 绘制蓝色的“地球”
//glColor3f(0.0f, 0.0f, 1.0f);
setMatirial(blue_color, 30.0);
glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f);
glTranslatef(15.0000000, 0.0f, 0.0f);
glutSolidSphere(1.5945000, 20, 20);
// 以(0.2, 0, -0.5)为中心,绘制一个半径为.2的半透明蓝色球体(离观察者最近)
/* setMatirial(blue_color, 30.0);
glPushMatrix();
glTranslatef(0.2f, 0.0f, -0.5f);
glutSolidSphere(0.5, 30, 30);
glPopMatrix();
*/
// glColor3f(1.0f, 1.0f, 0.0f);
setMatirial(y_color, 30.0);
glRotatef(day/30.0*360.0 - day/360.0*360.0, -0.0f, -0.0f, -1.0f);
glTranslatef(38.000000, 0.0f, 0.0f);
glutSolidSphere(4.345000, 20, 20);
// 以(0.1, 0, 0)为中心,绘制一个半径为.15的半透明绿色球体(在前两个球体之间)
/*setMatirial(green_color, 30.0);
glPushMatrix();
glTranslatef(0.5, 0, 0);
glutSolidSphere(0.4, 30, 30);
glPopMatrix();
*/
// 完成半透明物体的绘制,将深度缓冲区恢复为可读可写的形式
// glDepthMask(GL_TRUE);
glutSwapBuffers();
glFlush();
}
void myIdle(void)
{
/* 新的函数,在空闲时调用,作用是把日期往后移动一天并重新绘制,达到动画效果 */
++day;
if( day >= 360 )
day = 0;
Sleep(10);
myDisplay();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); // 修改了参数为GLUT_DOUBLE
glutInitWindowPosition(100, 100);
glutInitWindowSize(800, 800);
glutCreateWindow("太阳,地球和月亮"); // 改了窗口标题
glutDisplayFunc(&myDisplay);
glutIdleFunc(&myIdle); // 新加入了这句
glutMainLoop();
return 0;
}