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

来源:互联网 发布:广州市梦享网络 编辑:程序博客网 时间:2024/05/16 07:05

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

 

#define BITMAP_ID 0x4D42#define PI 3.1415926#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <math.h>#include <gl\glut.h>#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )//---------- 纹理数据结构typedef struct{int width;//纹理宽度int height;//纹理高度unsigned int texID;//纹理对象 IDunsigned 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,因为位图颜色格式是 BGRfor (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

 

以下为运行效果图: