OpenGL-入门-初级日地月

学习于OpenGL入门、OpenGL编程指南、gluPerspective

#include "pch.h"
#include  
#include 
#include  
#include  
const GLdouble Pi = 3.1415926536;

/*
	太阳半径69600km
	地球半径6378km
	月球半径1739km
	地球到太阳的距离约为1.5亿km=150000000km
	月亮到地球的距离约为		380000km
*/

/*修改不至于比例差距太大
	太阳半径69600000km(放大100倍)
	地球半径15945000km(放大 2500 倍)
	月球半径4345000km (放大 2500 倍)
	地球到太阳的距离约为1.5亿km=150000000km(保持不变)
	月亮到地球的距离约为	    38000000km(放大 100 倍)
*/

/*
	假设三个天体都是球体,都处于同一平面
	假设每个月都是30天,一年12个月,共有360天
	太阳中心为原点,天体轨迹所在的平面表示了 X 轴与 Y 轴决定的平面,
	且每年第一天,地球在 X 轴正方向上,月亮在地球的正 X 轴方向。 
*/

static int day = 200;

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);
	//glEnable(GL_DEPTH_TEST);	//启动深度测试 
	//glClear清除   GL_COLOR_BUFFER_BIT 表示清除颜色,GL_DEPTH_BUFFER_BIT表示清空深度缓冲
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	
	/**************第一步确立可视空间*****************/
	glMatrixMode(GL_PROJECTION);//操作投影矩阵
	glLoadIdentity();	//将当前矩阵设置为单位矩阵
	//为了透视效果,使用gluPerspective设置可视空间,设定视角为75(可修改)
	//窗口大小为(400,400),所以高宽比为1.0。
	//最近可视距离为1.0。最远可视距离为200000000*2=400000000
	gluPerspective(75,1,1, 400000000);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	/*
		gluLookAt();前三个参数表示了观察点的位置,中间三个参数表示了观察目标的参数,
		最后三个参数表示从(0,0,0)到(x,y,z)的直线,他表示观察者认为上的方向
		观察目标设置为太阳中心,选择Z轴正方向为上方向,将地球半径取整200000000 
	*/
	gluLookAt(0, -200000000, 200000000, 0, 0,0, 0, 0, 1);
	
	/****************绘制红色的太阳**************************/
	glColor3f(1.0f,0.0f,0.0f);
	glutSolidSphere(69600000, 20, 20);//球体半径,薄片数值,堆数值(后面两个都是描述球体精确度的)
	
	//绘制蓝色的地球
	glColor3f(0.0f,0.0f,1.0f);
	//今年已经经过的天数已知为 day,则地球转过的角度为 day/一年的天数*360 度。 前面已经假定每年都是 360 天
	// 注意地球公转是“自西向东”的,因此是饶着 Z 轴负方向进行逆时针旋转 
	glRotatef(day / 360.0*360.0, 0.0f, 0.0f, -1.0f);
	//glTranslatef(地球轨道半径, 0, 0); 
	glTranslatef(150000000, 0.0f, 0.0f);
	glutSolidSphere(15945000, 20, 20);
	
	//绘制黄色的月亮
	glColor3f(1.0f,1.0f,0.0f);
	/*
		在绘制地球是,坐标已经旋转过的,现在的旋转是在以前的基础上进行旋转的,所以要处理差值
		可以在绘制地球前用glPushMatrix保存矩阵,绘制完地球后用glPopMatrix恢复矩阵。
		再设计一个跟地球位置无关的月亮位置公式绘制月亮
	*/
	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);

	/* OpenGL 把三维坐标中的物体绘制到二维屏幕,绘制的顺序是按照代码的顺序来进行的。
		因此 后绘制的物体会遮住先绘制的物体,即使后绘制的物体在先绘制的物体的“后面”也是如此。*/
	glFlush();
	glutSwapBuffers();
}

void myIdle(void) {     /* 新的函数,在空闲时调用,作用是把日期往后移动一天并重新绘制,达到动画效果 */     
	++day;     
	if (day >= 360)         
		day = 0;     
	myDisplay(); 
}

int main(int argc, char *argv[]) 
{
	glutInit(&argc, argv);     /*glutInit,对 GLUT 进行初始化,这个函数必须在其它的 GLUT 使用之前调用一次。 */
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); // 设置显示方式,使用RGB颜色 GLUT_DOUBLE 双缓冲    
	glutInitWindowPosition(100, 100);     /*设置窗口在屏幕中的位置*/
	glutInitWindowSize(400, 400);     /*设置窗口的大小*/
	glutCreateWindow("太阳,地球和月亮");   // 改了窗口标题     
	glutDisplayFunc(&myDisplay);     
	glutIdleFunc(&myIdle);                   
	glutMainLoop();      /*进行一个消息循环*/
	return 0; 
} 

void gluPerspective(
GLdouble fovy, //角度
GLdouble aspect,//视景体的宽高比
GLdouble zNear,//沿z轴方向的两裁面之间的距离的近处
GLdouble zFar //沿z轴方向的两裁面之间的距离的远处
)
这个函数指定了观察的视景体(frustum为锥台的意思,通常译为视景体)在世界坐标系中的具体大小。

(1)参数fovy,指定视景体的视野的角度,以度数为单位,y轴的上下方向(Specifies the field of view angle, in degrees, in the y direction.)

(2)参数aspect,应该与窗口的宽高比大小相同。比如说,aspect=2.0表示在观察者的角度中物体的宽度是高度的两倍,在视口中宽度也是高度的两倍,这样显示出的物体才不会被扭曲。(Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height).)

(3)参数zNear,指定观察者到视景体的最近的裁剪面的距离(必须为正数)
(Specifies the distance from the viewer to the near clipping plane (always positive).)

(4)参数zFar,指定观察者到视景体的最远的裁剪面的距离(必须为正数)
(Specifies the distance from the viewer to the far clipping plane (always positive).)

由gluPerspective产生的矩阵是与当前矩阵与指定的矩阵相乘得到的,就好像是调用glMatrix()产生的矩阵一样。为了使透视矩阵替代当前矩阵,在调用gluPerspective之前要先调用glLoadidentity()这个函数(就是把当前矩阵s设置为单位矩阵)。
OpenGL-入门-初级日地月_第1张图片

你可能感兴趣的:(OpenGL)