// Solar.c
// OpenGL SuperBible
// Demonstrates OpenGL nested coordinate transformations
// and perspective
// Program by Richard S. Wright Jr.
/*原作者: Richard S. Wright Jr, 我在这里学习翻译一下 */
#include "../../Common/OpenGLSB.h" // System and OpenGL Stuff
#include <math.h>
// Lighting values
GLfloat whiteLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat sourceLight[] = { 0.8f, 0.8f, 0.8f, 1.0f };
//光源位置
GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
// 画场景的回调函数
void RenderScene(void)
{
// 地球和月亮旋转角度
static float fMoonRot = 0.0f;
static float fEarthRot = 0.0f;
// 清除颜色缓存和深度缓存
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 保存矩阵
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
//向远移动场景 -移动到300 处,为地球绕太阳旋转腾出空间
glTranslatef(0.0f, 0.0f, -300.0f);
//设置材料,颜色
// 太阳
glDisable(GL_LIGHTING);
glColor3ub(255, 255, 0);
//在屏幕中心画球体半径15
glutSolidSphere(15.0f, 30, 17);
glEnable(GL_LIGHTING);
//画完太阳,把光源置于屏幕中心!
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
//沿y=1旋转坐标系统 fEarthRot 角度
glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f);
//画地球
glColor3ub(0,0,255);
//在距离太阳105处画半径15地球
glTranslatef(105.0f,0.0f,0.0f);
glutSolidSphere(15.0f, 30, 17);
//画围绕地球旋转的月亮
glColor3ub(200,200,200);
//沿着y=1旋转 fMoonRot 角度
glRotatef(fMoonRot,0.0f, 1.0f, 0.0f);
//在距离地球30地方画半径为6月亮
glTranslatef(30.0f, 0.0f, 0.0f);
//月球旋转角度增量
fMoonRot+= 15.0f;
if(fMoonRot > 360.0f)
fMoonRot = 0.0f;
glutSolidSphere(6.0f, 30, 17);
//还原矩阵
glPopMatrix(); // Modelview matrix
//地球旋转角度增量
fEarthRot += 5.0f;
if(fEarthRot > 360.0f)
fEarthRot = 0.0f;
//显示图像
glutSwapBuffers();
}
// 渲染初始化函数,上下文环境设置.
void SetupRC()
{
//设置灯光和坐标
//启用深度测试,有遮挡的效果
glEnable(GL_DEPTH_TEST);
//逆时针为多边形正面
glFrontFace(GL_CCW);
//启用剔除效果,多边形背面不用光照处理
glEnable(GL_CULL_FACE);
//启动灯光效果
glEnable(GL_LIGHTING);
//设置灯泡0
//环境光颜色
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
//散射光强度
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
//光源位置
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
//开灯
glEnable(GL_LIGHT0);
//使用颜色材质
glEnable(GL_COLOR_MATERIAL);
//设置材料反射属性, 以相同的强度反射环境光和散射光
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
//黑色背景
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
}
void TimerFunc(int value)
{
glutPostRedisplay();
glutTimerFunc(100, TimerFunc, 1);
}
void ChangeSize(int w, int h)
{
GLfloat fAspect;
//防止被0除
if(h == 0)
h = 1;
//设置视口大小
glViewport(0, 0, w, h);
//计算屏幕比例
fAspect = (GLfloat)w/(GLfloat)h;
//指定投影矩阵为当前矩阵
glMatrixMode(GL_PROJECTION);
//把坐标系重置为视觉坐标,即屏幕中心
glLoadIdentity();
//设置眼睛睁开的大小(摄像机焦距一般45合适,看到最近1,最远425处的东西),
gluPerspective(45.0f, fAspect, 1.0, 425.0);
//制定模型视图矩阵为当前矩阵
glMatrixMode(GL_MODELVIEW);
//把坐标系重置为视觉坐标,即屏幕中心
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("Earth/Moon/Sun System");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
glutTimerFunc(250, TimerFunc, 1);
SetupRC();
glutMainLoop();
return 0;
}
效果如下: