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 = https://www.it610.com/article/LoadBmpFile(filename,&texInfo); // 调入纹理数据并检查有效性 if (thisTexture->data =https://www.it610.com/article/= 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}; GLfloatno_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 + vc6.0 控制台实现《太阳系模型》】

    推荐阅读