opengl绘制太阳、地球、月亮,贴上纹理,设置光照,符合自转和公转规律

1)    场景中分别绘制太阳、地球、月球,要求位置关系大体正确,并为三者贴

上纹理。三者的旋转符合实际公转自转规律;

(2)    启用z-buffer,实现面消隐;

(3)    启用光照系统,光源的环境光设置为(0.2,0.2,0.2,1)   漫反射(1,

1,1,1)和镜面反射光(1,1,1,1);

(4)    材料特性: 太阳黄色且自己向外辐射光,地球蓝色,月球灰色;

(5)    视角可以通过键盘a,d,s,w切换;

(6)    采用动画设计,使得场景能够自动运行;

(7)    分别采用透视、正交投影方式。

#include "stdafx.h"
#include <GL/glut.h>
#include<math.h>
#include<GL\GLAUX.H>

_AUX_RGBImageRec *sun, *earth, *moon;//纹理数据
unsigned int sunID,earthID,moonID;   //纹理ID
double angle=0;
float theta=60,phi=60,r=2;
float eyex=0, eyey=0, eyez=0, atx=0, aty=0, atz=0;

void myinit();
void texInit();//纹理初始化
void display();
void gltDrawSphere(GLfloat fRadius, GLint iSlices, GLint iStacks);
void idle();
void myKeyboard();

//键盘控制视角函数
void myKeyboard(unsigned char key,int x,int y){	
switch(key)
{
case'A':
case'a':
	if(phi-1>-180)
		phi=phi-5;
	break;
case'D':
case'd':
	if(phi+1<0)
		phi=phi+5;
	break;
case'S':
case's':
	if(theta+1<180)
		theta=theta+5;
	break;
case'W':
case'w':
	if(theta-1>0)
		theta=theta-5;
	break;

 }
	glutPostRedisplay();
}

//设置光照函数
void myinit()
{
	GLfloat light_ambient[] = { 0.2,0.2,0.2,1 };     //环境光
	GLfloat light_diffuse[] = { 1.0,1.0,1.0,1.0 };     //漫反射光
	GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };    //镜面反射光
	glClearColor(0.5f, 0.5f, 0.5f, 1.0f);              //设置背景颜色
	GLfloat light_position[] = { 0, 0, 0 ,1 }; // 光源位置设置												   
	// 创建光源		
	//glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE,GL_FALSE);//双面光照

	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_LIGHTING);                          // 开启光照效果
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);                        // 开启深度测试			
	
}

//设置太阳,地球,月亮
void display()
{
	/*材质参数*/
	glClearColor(0.1, 0.1, 0.1, 1.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 清空屏幕和深度缓存
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();                                  // 重置当前的模型观察矩阵
	glOrtho(-10, 10, -6, 6, -50, 50);
	//glFrustum(-5, 5, -3, 3, 1, 100);
	gluLookAt(r*sin(theta*3.14159/180)*sin(phi*3.14159/180),r*cos(theta*3.14159/180),r*sin(theta*3.14159/180)*cos(phi*3.14159/180),0.0,0.0,0.0,0.0,0.0,1.0);
	//透视投影gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	//太阳
	glBindTexture(GL_TEXTURE_2D, sunID);// 绑定sunID,后续操作是对sun纹理进行的操作	
	//设置纹理环境
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );       //纹理 与 颜色的处理模式 GL_REPLACE 替换GL_DECAL贴花 GL_BLEND混合 GL_MODULATE调节
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //纹理缩小 情况
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //纹理放大 情况
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);   //在S方向 重复纹理
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);   //在T方向 重复纹理 
    //指定纹理数据和绑定对象关联BLEND
	glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, sun->sizeX, sun->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, sun->data);
	//设置材质
	  GLfloat em[4] ={0.8F, 0.7F, 0.0F,0.0f}; //黄色辐射光
		GLfloat sun_mat_diffuse[]   = {0.8f, 0.7f, 0.0f, 1.0f};  //定义材质的漫反射光颜色,偏黄色
		GLfloat sun_mat_specular[] = {0.8f, 0.57, 0.0f, 1.0f};   //定义材质的镜面反射光颜色,黄色
		GLfloat sun_mat_shininess   = 100.0f;  
		glMaterialfv(GL_FRONT, GL_DIFFUSE,   sun_mat_diffuse);   
		glMaterialfv(GL_FRONT, GL_SPECULAR,   sun_mat_specular);      
		glMaterialf (GL_FRONT, GL_SHININESS, sun_mat_shininess);   
		//glMaterialfv(GL_FRONT,GL_EMISSION, em);//自发光
    //
		
	glRotatef(angle, 1, 1, 1);
	gltDrawSphere(0.8, 200, 200); //绘制球体
	
	//地球	
	glBindTexture(GL_TEXTURE_2D, earthID);	
	//设置纹理环境
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);       //纹理 与 颜色的处理模式 GL_REPLACE GL_DECAL GL_BLEND GL_MODULATE
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //纹理缩小 情况
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //纹理放大 情况
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);   //在S方向 重复纹理
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);   //在T方向 重复纹理 
    //指定纹理数据和绑定对象关联
	glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, earth->sizeX, earth->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, earth->data);
	    GLfloat earth_mat_diffuse[]   = {0.5f, 0.5f, 0.5f, 1.0f};  //定义材质的漫反射光颜色,偏蓝色
		GLfloat earth_mat_specular[] = {1.0f,1.0f, 1.0f, 1.0f};   //定义材质的镜面反射光颜色,蓝色
		GLfloat earth_mat_shininess   = 100.0f;  
		glMaterialfv(GL_FRONT, GL_DIFFUSE,  earth_mat_diffuse);   
		glMaterialfv(GL_FRONT, GL_SPECULAR,  earth_mat_specular);      
		glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess); 
		//GLfloat bm[4] ={0.5F, 0.6F, 0.8F,1.0f}; //蓝色辐射光
		//glMaterialfv(GL_FRONT,GL_EMISSION, bm);//自发光
	glRotatef(angle/360.0*360.0, 1,1,1);
	glTranslatef(-3,0,0);
	gltDrawSphere(0.5, 200, 200); //绘制球体
	//glFlush();
	 glPopMatrix();

	 //月亮,
	glBindTexture(GL_TEXTURE_2D, moonID);	
	//设置纹理环境
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );       //纹理与颜色的处理模式 GL_REPLACE GL_DECAL GL_BLEND GL_MODULATE
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //纹理缩小情况
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //纹理放大情况
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);   //在S方向 重复纹理
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);   //在T方向 重复纹理 
    //指定纹理数据和绑定对象关联
	glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, moon->sizeX, moon->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, moon->data);
//材质
	GLfloat  moon_mat_diffuse[]   = {0.5f, 0.5f, 0.5f, 1.0f};  //定义材质的漫反射光颜色,偏灰色
		GLfloat moon_mat_specular[] = {0.5f, 0.5f, 0.5f, 1.0f};   //定义材质的镜面反射光颜色,灰色
		GLfloat moon_mat_shininess   = 100.0f;  
		glMaterialfv(GL_FRONT, GL_DIFFUSE,   moon_mat_diffuse);   
		glMaterialfv(GL_FRONT, GL_SPECULAR,   moon_mat_specular);      
		glMaterialf (GL_FRONT, GL_SHININESS, moon_mat_shininess); 

	glRotatef(angle/30.0*360.0 - angle/360.0*360.0,0,1,0);
	glTranslatef(0.5,0,1);
	gltDrawSphere(0.2, 200, 200); //绘制球体
	glutSwapBuffers();
}
//画圆函数
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;
	}
}

void texInit()
{
	//启用二维纹理
	glEnable(GL_TEXTURE_2D);
	//创建3个纹理ID
	glGenTextures(1, &sunID);
	glGenTextures(1, &earthID);
	glGenTextures(1, &moonID);	
    //载入纹理数据  将bmp文件 放在 .cpp/.c所在文件夹下
	char *filename = "sun.bmp";
	sun = auxDIBImageLoadA(filename);
	char * filename1 = "earth.bmp";
	earth = auxDIBImageLoadA(filename1);
	char *filename2 = "moon.bmp";
	moon = auxDIBImageLoadA(filename2);
}

void idle()
{
	angle = angle + 1;
	if (angle > 360)
		angle = 0;
	glutPostRedisplay();
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(1000, 600);
	glutCreateWindow("Texture");
	myinit(); //纹理初始化
	texInit();//纹理初始化
	glutDisplayFunc(display);
	glutIdleFunc(idle);
	 glutKeyboardFunc(myKeyboard);
	
	glutMainLoop();
    return 0;
}

扫描二维码关注公众号,回复: 13224356 查看本文章

猜你喜欢

转载自blog.csdn.net/y0205yang/article/details/121315400