OpenGL + vc6.0 控制台实现《太阳系模型》

OpenGL + vc6.0 控制台实现《太阳系模型》

 

#define BITMAP_ID 0x4D42
#define PI 3.1415926

#include 
#include 
#include 
#include 
#include 

#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )

//---------- 纹理数据结构
typedef struct{
	int width;				//纹理宽度
	int height;				//纹理高度
	unsigned int texID;		//纹理对象 ID
	unsigned char * data;	//实际纹理数据
}texture;


static float year = 0, month =0,day = 0, angle=30;
static bool first=false;

texture * sun,* earth,* moon;			//纹理指针

//---------- 调入位图作为纹理数据
unsigned char * LoadBmpFile(char * filename,BITMAPINFOHEADER * bmpInfoHeader){
	
	FILE * file;
	BITMAPFILEHEADER bmpFileHeader;
	unsigned char * image;
	unsigned int imageIdx =0;
	unsigned char tempRGB;
	
	file = fopen(filename,"rb");		
	if(file == NULL)
		return 0;
	
	fread(& bmpFileHeader,sizeof(BITMAPFILEHEADER),1,file);			// 读取 BMP 文件头
	
	if (bmpFileHeader.bfType != BITMAP_ID)							// 验证是否是一个 BMP 文件
	{
		fclose(file);
		return 0;
	}
	
	fread(bmpInfoHeader,sizeof(BITMAPINFOHEADER),1,file);			// 读位图信息头
	fseek(file,bmpFileHeader.bfOffBits,SEEK_SET);					// 将文件指针移到位图数据的开始处
	image = (unsigned char * )malloc(bmpInfoHeader->biSizeImage);	// 分配内存给位图数据
	
	if (! image)
	{
		free(image);
		fclose(file);
		return 0;
	}
	
	
	fread(image,1,bmpInfoHeader->biSizeImage,file);					// 读取位图数据
	
	if (image == NULL)
	{
		fclose(file);
		return 0;	
	}
	
	// 反转 R 和 B 值以得到 RGB,因为位图颜色格式是 BGR
	for (imageIdx = 0;imageIdx < bmpInfoHeader->biSizeImage;imageIdx += 3)
	{
		tempRGB = image[imageIdx];
		image[imageIdx] = image[imageIdx + 2];
		image[imageIdx + 2] = tempRGB;
	}
	
	fclose(file);
	return image;
	
}

//---------- 调入纹理文件
texture * LoadTexFile(char * filename){
	
	BITMAPINFOHEADER texInfo;
	texture * thisTexture;
	
	thisTexture = (texture * )malloc(sizeof(texture));
	if(thisTexture == NULL)
		return 0;
	
	thisTexture->data = LoadBmpFile(filename,&texInfo);	// 调入纹理数据并检查有效性
	if (thisTexture->data == NULL)
	{
		free(thisTexture);
		return 0;
	}

	thisTexture->width = texInfo.biWidth;				// 设置纹理的宽和高
	thisTexture->height = texInfo.biHeight;
	
	glGenTextures(1,&thisTexture->texID);				// 生成纹理对象名
	
	return thisTexture;
}

//---------- 初始化所有纹理数据和属性
BOOL LoadAllTextures(){

	sun = LoadTexFile("sun.bmp");				
	if(sun == NULL)
		return FALSE;
	
	glBindTexture(GL_TEXTURE_2D,sun->texID);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,sun->width,sun->height,GL_RGB,GL_UNSIGNED_BYTE,sun->data);


	earth = LoadTexFile("earth.bmp");			
	if(earth == NULL)
		return FALSE;
	
	glBindTexture(GL_TEXTURE_2D,earth->texID);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,earth->width,earth->height,GL_RGB,GL_UNSIGNED_BYTE,earth->data);


	moon = LoadTexFile("moon.bmp");			
	if(moon == NULL)
		return FALSE;
	
	glBindTexture(GL_TEXTURE_2D,moon->texID);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,moon->width,moon->height,GL_RGB,GL_UNSIGNED_BYTE,moon->data);

	return TRUE;
}

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 myinit(void) 
{
	glClearColor (0.0, 0.0, 0.0, 0.0);

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);	//启用二维纹理

	GLfloat light0_ambient[]  = {1, 1, 1, 1};	//环境光
	GLfloat light0_diffuse[]  = {1, 1, 1, 1};	//散射光
	GLfloat light0_position[] = {0, 0, 0, 1};	//光源位置

	glLightfv(GL_LIGHT0,GL_AMBIENT,light0_ambient);
	glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);
	glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
	
	LoadAllTextures();			//调入纹理
}

void myidle()
{
	day+=angle;
	glutPostRedisplay();

}

void mymouse(int button,int state,int x,int y)
{	
	if(state==GLUT_DOWN && button==GLUT_LEFT_BUTTON){
		if(first)
		{
			glutIdleFunc(myidle);
			first=!first;
		}
		else
		{
			glutIdleFunc(0);
			first=!first;
		}
	}	
}

void mykeyboard(unsigned char key, int x, int y) 
{
	if (key == 27)         
		exit(0); 
} 

void mydisplay(void)
{
	year=day/365;
	month=day/30;

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	GLfloat mat_ambient1[]  = {1,0,0,1};
	GLfloat mat_emission[]  = {1,1,1,0};

	GLfloat mat_ambient2[]  = {0.4,0.4,0.8,1};
	GLfloat  no_emission[]  = {0,0,0,1};

	glPushMatrix();	
		glBindTexture(GL_TEXTURE_2D,sun->texID);
		glRotatef (month, 0.0, 1.0, 0.0);				//太阳自转
		glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient1);
		glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
		glRotatef (90, -1, 0, 0);
		gltDrawSphere(1.0, 40, 40);			//绘制太阳
	glPopMatrix();

	glPushMatrix();
		glRotatef (year, 0.0, 1.0, 0.0);				//月亮与地球一起绕太阳转(地球公转)
		glPushMatrix();
			glBindTexture(GL_TEXTURE_2D,earth->texID);
			glTranslatef (3.0, 0.0, 0.0);
			glRotatef (month, 0.0, 1.0, 0.0);			//地球自转 
			glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient2);
			glMaterialfv(GL_FRONT, GL_EMISSION, no_emission);
			glRotatef (90, -1, 0, 0);
			gltDrawSphere(0.4, 40, 40);		//绘制地球	
		glPopMatrix();

		glPushMatrix();
			glBindTexture(GL_TEXTURE_2D,moon->texID);
			glTranslatef (3.0, 0.0, 0.0);
			glRotatef (60, -1, 1, 0);
			glRotatef (month, 0, 1.0, 0);				//月球绕地球转
			glTranslatef (0.6, 0.0, 0.0);
			glRotatef (90, -1, 0, 0);
			gltDrawSphere(0.07, 20, 20);	//绘制月球
		glPopMatrix();
	glPopMatrix();

	glFlush();
	glutSwapBuffers();   
}

void myreshape (int w, int h)
{
	glViewport (0, 0, (GLsizei) w, (GLsizei) h);				//指定视口大小
	glMatrixMode (GL_PROJECTION);
	glLoadIdentity ();
		
	gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1, 20);		//透视投影
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
		
	gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);	//指定照相机的位置	
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize (1000, 600); 
	glutInitWindowPosition (100, 100);
	glutCreateWindow (argv[0]);
	myinit ();

	glutDisplayFunc(mydisplay); 
	glutReshapeFunc(myreshape);
	glutIdleFunc(myidle);
	glutMouseFunc(mymouse);
	glutKeyboardFunc(mykeyboard);

	glutMainLoop();
	return 0;
}

 

 

说明:上述代码已经在vc控制台中编译运行通过。

此链接为此程序的源代码文件(包含此程序所需的三个bmp图片,及exe文件)

http://download.csdn.net/detail/shen_gan/4279261

 

以下为运行效果图:

你可能感兴趣的:(OpenGL)