#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
以下为运行效果图: