OpenGL画太阳系

该代码展示了如何使用OpenGL创建一个太阳系的3D模拟,包括太阳和多个行星的运动轨迹。通过调整观察点的位置和角度,可以观察到太阳系中行星的环绕运动。代码中定义了每个行星的轨道半径和自转速度,并使用光源和材质设置了光照效果。

分享一个OpenGL画太阳系的代码。

#include <GL/glut.h>
#include <GL/SOIL.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#pragma pack(1)
#define DISCRETE_GRAPHICS 1
#if DISCRETE_GRAPHICS
__declspec(dllexport) int NvOptimusEnablement = 0x00000001; //使用独显
#endif

#define Pi 3.1415926
#define RADIUS       10.0       //观察点位置所在球面半径
#define ROTATE_SPEED 0.01       //观察点移动速度
#define MERCURY_ORBIT_RADIUS 0.6
#define VENUS_ORBIT_RADIUS   1.0
#define EARTH_ORBIT_RADIUS   1.5
#define MARS_ORBIT_RADIUS    2.0
#define JUPITER_ORBIT_RADIUS 2.7
#define SATURN_ORBIT_RADIUS  3.4
#define URANUS_ORBIT_RADIUS  4.0
#define NEPTUNE_ORBIT_RADIUS 4.76

#define SUN_RADIUS 0.5
#define MERCURY_RADIUS 0.05

static void Resize(int w, int h);
static void Display(void);                                      //显示回调函数
static void Idle(void);                                         //空闲回调函数
static void ProcessNormalKeys(unsigned char key, int x, int y); //ASCII按键响应函数
static void ProcessSpecialKeys(int skey, int x, int y);         //非ASCII按键响应函数
static void MouseMove(int x, int y);                            //鼠标移动回调函数
static void MouseButton(int button, int state, int x, int y);   //鼠标按键回调函数

static void ChangeViewPosition(GLdouble theta, GLdouble phi);
static void CreateGLUTMenus(void);
//display text function
static void SetOrthographicProjection(void);
static void RestorePerspectiveProjection(void);
static void RenderBitmapFontString(GLfloat x, GLfloat y, GLfloat z, void *font, char *string); //show bitmap font
static void RenderStrokeFontString(GLfloat x, GLfloat y, GLfloat z, void *font, char *string); //show stroke font
//texture
void LoadPicture(char *file_name, GLuint *texture);

static int window_width, window_height;
static int main_menu;
static int mouse_x = -1, mouse_y = -1;
//observer's parameters
static GLdouble radius = RADIUS; //The radius of the sphere where the observer is located
static GLdouble theta_angle = 0.0, phi_angle = Pi / 2.0;
static GLdouble delta_theta = 0.0, delta_phi = 0.0;
static GLdouble x = RADIUS, y = 0.0, z = 0.0; //position of the viewer
static GLdouble cx = 0.0, cy = 0.0, cz = 0.0; //viewer's direction
static GLdouble hx = 0.0, hy = 0.0, hz = 1.0; //viewer's head direction
//light
const GLfloat light0_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f}; //光源中环境光的颜色,黑色。红,绿,蓝,第四个分量1.0表示不透明。
const GLfloat light0_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; //光源中漫射光的颜色,白色
const GLfloat light0_position[] = {0.0f, 0.0f, 0.0f, 1.0f}; //定向光源,指定了光源的方向
//materials
const GLfloat mat_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};      //材质的环境颜色
const GLfloat mat_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};      //材质的漫射光颜色
const GLfloat high_shininess[] = {10.0f};                    //材质的镜面反射指数

int main(int argc, char *argv[])
{
    // init GLUT and create window
    glutInit(&argc, argv);
    // GLuint texture;
    // LoadPicture("img_test.bmp", &texture);
    glutInitWindowSize(1000, 1000);   //set window size
    glutInitWindowPosition(1000, -1); //set window position
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("solar system"); //根据前面设置的创建窗口,参数被作为窗口的标题。
    glShadeModel(GL_SMOOTH);
    //light
    glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
    glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
    //materials
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, high_shininess);

    glEnable(GL_LIGHT0);//启用0号光源
    glEnable(GL_NORMALIZE);// 启用自动单位化法向量
    glEnable(GL_COLOR_MATERIAL);//启用材质颜色
    glEnable(GL_LIGHTING);//启用光照

    // register callbacks
    glutReshapeFunc(Resize);  //注册当前窗口的再整形回调函数
    glutDisplayFunc(Display); //注册当前窗口的显示回调函数
    glutIdleFunc(Idle);       //注册空闲回调函数
    glutKeyboardFunc(ProcessNormalKeys); //注册ASCII按键响应函数
    glutSpecialFunc(ProcessSpecialKeys); //注册非ASCII按键响应函数
	glutMouseFunc(MouseButton);
	glutMotionFunc(MouseMove);

    glClearColor(0,0,0,0);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    //启用反走样
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);  // Antialias the lines
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    ChangeViewPosition(theta_angle, phi_angle);
    CreateGLUTMenus();
    
    glutMainLoop();//主循环处理
    return EXIT_SUCCESS;
}

void Idle(void)
{
    glutPostRedisplay();
}

static void Resize(int width, int height)
{
    GLdouble ratio;
    height = (!height) ? 0.1 : height;
    window_width = width;
    window_height = height;
    ratio = 1.0 * width / height;
    // Reset the coordinate system before modifying
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //设置视口为整个窗口大小
    glViewport(0, 0, width, height);
    //设置可视空间
    gluPerspective(60,ratio,0.1,1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(x + cx, y + cy, z + cz,
              cx, cy, cz,
              hx, hy, hz);
}

void DrawCircle(GLdouble R)
{
    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < 7200; i++)
    {
        glVertex2f(R * cos(2 * Pi * i / 7200), R * sin(2 * Pi * i / 7200));
    }
    glEnd();
}

inline double GetDistance(double x1, double y1, double z1, double x2, double y2, double z2)
{
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));
}

void AutoChangeTextAngle(void)
{
    glRotated(90, 0, 0, 1);
    glRotated(90, 1, 0, 0);
    glRotated((theta_angle + delta_theta) * 180.0l / Pi, 0, 1, 0);
    glRotated((phi_angle + delta_phi) * 180.0l / Pi, -1, 0, 0);
}
//display
static void Display(void)//显示回调函数 图片绘制在XOY平面上
{
    static double angle=0;
    const int slices =60;
    const int stacks =60;
    GLdouble star_x, star_y, star_z;
#if DISCRETE_GRAPHICS
    angle += 0.005;
#else
    angle += 0.001;
#endif
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除颜色缓冲区和深度缓冲区
    //Sun
    glColor3d(1, 0.5, 0.04);
    glPushMatrix();
    glutSolidSphere(SUN_RADIUS, slices, stacks);
    AutoChangeTextAngle();
    glPopMatrix();
    //Mercury
    star_x = MERCURY_ORBIT_RADIUS * cos(1 / 0.24 * angle);
    star_y = MERCURY_ORBIT_RADIUS * sin(1 / 0.24 * angle);
    star_z = 0.0;
    glColor3f(0.61f, 0.33f, 0.16f);
    glPushMatrix();
    glTranslated(star_x, star_y, star_z);
    glutSolidSphere(MERCURY_RADIUS, slices, stacks);
    if(GetDistance(star_x, star_y, star_z, x, y, z) < GetDistance(0, 0, 0, x, y, z))
    {
        AutoChangeTextAngle();
        RenderStrokeFontString(-0.25f, 0.1f, 0.0f, GLUT_STROKE_ROMAN, (char*)"Mercury");
    }
    glPopMatrix();
    DrawCircle(MERCURY_ORBIT_RADIUS);
    //Venus
    star_x = VENUS_ORBIT_RADIUS * cos(1 / 0.62 * angle);
    star_y = VENUS_ORBIT_RADIUS * sin(1 / 0.62 * angle);
    star_z = 0.0;
    glColor3f(1.0f, 0.65f, 0.31f);
    glPushMatrix();
    glTranslated(star_x, star_y, star_z);
    glutSolidSphere(0.065, slices, stacks);
    if(GetDistance(star_x, star_y, star_z, x, y, z) < GetDistance(0, 0, 0, x, y, z))
    {
        AutoChangeTextAngle();
        RenderStrokeFontString(-0.2f, 0.1f, 0.0f, GLUT_STROKE_ROMAN, (char*)"Venus");
    }
    glPopMatrix();
    DrawCircle(VENUS_ORBIT_RADIUS);
	//Earth
    star_x = EARTH_ORBIT_RADIUS * cos(1.0 * angle);
    star_y = EARTH_ORBIT_RADIUS * sin(1.0 * angle);
    star_z = 0.0;
    glColor3f(0.18f, 0.3f, 0.41f);
    glPushMatrix();
    glTranslated(star_x, star_y, star_z);
    glutSolidSphere(0.07, slices, stacks);
    if(GetDistance(star_x, star_y, star_z, x, y, z) < GetDistance(0, 0, 0, x, y, z))
    {
        AutoChangeTextAngle();
        RenderStrokeFontString(-0.15f, 0.1f, 0.0f, GLUT_STROKE_ROMAN, (char*)"Earth");
    }
    glPopMatrix();
    DrawCircle(EARTH_ORBIT_RADIUS);
    //Mars
    star_x = MARS_ORBIT_RADIUS * cos(1 / 1.9 * angle);
    star_y = MARS_ORBIT_RADIUS * sin(1 / 1.9 * angle);
    star_z = 0.0;   
    glColor3f(0.54, 0.058, 0.027);
    glPushMatrix();
    glTranslated(star_x, star_y, star_z);
    glutSolidSphere(0.053, slices, stacks);
    if(GetDistance(star_x, star_y, star_z, x, y, z) < GetDistance(0, 0, 0, x, y, z))
    {
        AutoChangeTextAngle();
        RenderStrokeFontString(-0.15f, 0.1f, 0.0f, GLUT_STROKE_ROMAN, (char*)"Mars");
    }
    glPopMatrix();
    DrawCircle(MARS_ORBIT_RADIUS);
	//Jupiter
    star_x = JUPITER_ORBIT_RADIUS * cos(1 / 11.9 * angle);
    star_y = JUPITER_ORBIT_RADIUS * sin(1 / 11.9 * angle);
    star_z = 0.0;   
    glColor3f(0.55, 0.42, 0.35);
    glPushMatrix();
    glTranslated(star_x, star_y, star_z);
    glutSolidSphere(0.2, slices, stacks);
    if(GetDistance(star_x, star_y, star_z, x, y, z) < GetDistance(0, 0, 0, x, y, z))
    {
        AutoChangeTextAngle();
        RenderStrokeFontString(-0.2f, 0.3f, 0.0f, GLUT_STROKE_ROMAN, (char*)"Jupiter");
    }
    glPopMatrix();
    DrawCircle(JUPITER_ORBIT_RADIUS);
    //Saturn
    star_x = SATURN_ORBIT_RADIUS * cos(1 / 29.5 * angle);
    star_y = SATURN_ORBIT_RADIUS * sin(1 / 29.5 * angle);
    star_z = 0.0;  
    glColor3f(0.7, 0.46, 0.22);
    glPushMatrix();
    glTranslated(star_x, star_y, star_z);
    glutSolidSphere(0.1, slices, stacks);
    if(GetDistance(star_x, star_y, star_z, x, y, z) < GetDistance(0, 0, 0, x, y, z))
    {
        AutoChangeTextAngle();
        RenderStrokeFontString(-0.2f, 0.2f, 0.0f, GLUT_STROKE_ROMAN, (char*)"Saturn");
    }
    glPopMatrix();
    DrawCircle(SATURN_ORBIT_RADIUS);
    //Uranus
    star_x = URANUS_ORBIT_RADIUS * cos(1 / 83.0 * angle);
    star_y = URANUS_ORBIT_RADIUS * sin(1 / 83.0 * angle);
    star_z = 0.0;  
    glColor3f(0.39, 0.68, 0.87);
    glPushMatrix();
    glTranslated(star_x, star_y, star_z);
    glutSolidSphere(0.07, slices, stacks);
    if(GetDistance(star_x, star_y, star_z, x, y, z) < GetDistance(0, 0, 0, x, y, z))
    {
        AutoChangeTextAngle();
        RenderStrokeFontString(-0.2f, 0.17f, 0.0f, GLUT_STROKE_ROMAN, (char*)"Uranus");
    }   
    glPopMatrix();
    DrawCircle(URANUS_ORBIT_RADIUS);
    //Neptune
    star_x = NEPTUNE_ORBIT_RADIUS * cos(1 / 164.8 * angle);
    star_y = NEPTUNE_ORBIT_RADIUS * sin(1 / 164.8 * angle);
    star_z = 0.0; 
    glColor3f(0.29, 0.53, 0.9);
    glPushMatrix();
    glTranslated(star_x, star_y, star_z);
    glutSolidSphere(0.07, slices, stacks);
    if(GetDistance(star_x, star_y, star_z, x, y, z) < GetDistance(0, 0, 0, x, y, z))
    {
        AutoChangeTextAngle();
        RenderStrokeFontString(-0.25f, 0.17f, 0.0f, GLUT_STROKE_ROMAN, (char*)"Neptune");
    }  
    glPopMatrix();
    DrawCircle(NEPTUNE_ORBIT_RADIUS);
    //compute frames per second
    static int time = 0, frame = 0, last_time = 0;
    static double fps = 0.0l;
    frame++;
    time = glutGet(GLUT_ELAPSED_TIME);
    if(time-last_time >= 1000)
    {
        fps = frame * 1000.0l / (time - last_time);
        last_time = time;
        frame = 0;
    }
    //display a string with bitmap fonts
    SetOrthographicProjection();
	glPushMatrix();
	glLoadIdentity();
    glColor3d(1, 0.5, 0.04);
    
    char str[64];
    int wwidth = glutGet(GLUT_WINDOW_WIDTH);
    RenderBitmapFontString(wwidth / 2 - 50, 20, 0, GLUT_BITMAP_HELVETICA_18, (char *)"Solar System");
    glColor3f(1.0f, 1.0f, 1.0f);
    sprintf(str, "FPS: %.2lf", fps);
    RenderBitmapFontString(5, 20, 0, GLUT_BITMAP_HELVETICA_18, str);
    sprintf(str, "Observation Point: x=%.2lf, y=%.2lf, z=%.2lf", x + cx, y + cy, z + cz);
    RenderBitmapFontString(5, 40, 0, GLUT_BITMAP_HELVETICA_18, str);
    sprintf(str, "theta=%.2lf, phi=%.2lf, radius=%.2lf", (theta_angle + delta_theta) * 180.0 / Pi, (phi_angle + delta_phi) * 180.0 / Pi, radius);
    RenderBitmapFontString(5, 60, 0, GLUT_BITMAP_HELVETICA_18, str);  
    glPopMatrix();
	RestorePerspectiveProjection();
    //交换缓冲区
    glutSwapBuffers();
}
//view
void ChangeViewDistance(unsigned char option)
{
    switch (option)
    {
        case '+' :
            radius -= 0.1;
            radius = (radius < 0.1) ? 0.1 : radius;
            ChangeViewPosition(theta_angle, phi_angle);
            break;
        case '-' :
            radius += 0.1;
            radius = (radius > 15) ? 15 : radius;
            ChangeViewPosition(theta_angle, phi_angle);
            break;
        default:
            break;
    }
}

void ChangeViewPosition(GLdouble theta, GLdouble phi)
{
    x = radius * cos(phi) * cos(theta);
    y = radius * cos(phi) * sin(theta);
    z = radius * sin(phi);
    glLoadIdentity();
    gluLookAt(x + cx, y + cy, z + cz,
              cx, cy, cz,
              hx, hy, hz);
}
//key
static void ProcessSpecialKeys(int skey, int x, int y)//非ASCII按键响应函数
{
    switch(skey){
		case GLUT_KEY_LEFT :
            theta_angle -= ROTATE_SPEED;
            theta_angle = (theta_angle < -Pi) ? -Pi : theta_angle;
            ChangeViewPosition(theta_angle, phi_angle);
            break;
		case GLUT_KEY_RIGHT:
            theta_angle += ROTATE_SPEED;  
            theta_angle = (theta_angle > Pi) ? Pi : theta_angle;         
            ChangeViewPosition(theta_angle, phi_angle);
            break;
		case GLUT_KEY_UP:
            phi_angle += ROTATE_SPEED;
            phi_angle = (phi_angle > Pi / 2.0l) ? Pi / 2.0l : phi_angle;         
            ChangeViewPosition(theta_angle, phi_angle);
            break;
		case GLUT_KEY_DOWN :
            phi_angle -= ROTATE_SPEED;
            phi_angle = (phi_angle < 0.0l) ? 0.0l : phi_angle;
            ChangeViewPosition(theta_angle, phi_angle);
            break;
        case GLUT_KEY_HOME:
            theta_angle = 0.0l;
            phi_angle = Pi / 2.0l;
            ChangeViewPosition(theta_angle, phi_angle);
            break;
        default:
            break;
    }
}

static void ProcessNormalKeys(unsigned char key, int x, int y)//ASCII按键响应函数
{
    switch (key)
    {
        case ' ' :
        case 'q' :
            glutDestroyMenu(main_menu);
            exit(0);
            break;
        case '+' :
            ChangeViewDistance('+');
            break;
        case '-' :
            ChangeViewDistance('-');
            break;
        default:
            break;
    }
}
//mouse
void MouseMove(int x, int y)
{
	// this will only be true when the left button is down
	if (mouse_x >= 0 && abs(mouse_x - x) >= 5)
    {
        delta_theta = (double)(mouse_x - x) * ROTATE_SPEED;
        if(theta_angle+delta_theta > Pi)
            delta_theta = Pi - theta_angle;
        else if(theta_angle+delta_theta < -Pi)
            delta_theta = -Pi - theta_angle;
    }
    if(mouse_y >= 0 && abs(y - mouse_y) >= 10)
    {
        delta_phi = (double)(y - mouse_y) * ROTATE_SPEED;
        if(phi_angle+delta_phi > Pi/2.0l)
            delta_phi = Pi / 2.0l - phi_angle;
        else if(phi_angle+delta_phi < 0.0l)
            delta_phi = -phi_angle;
    }
    ChangeViewPosition(theta_angle + delta_theta, phi_angle + delta_phi);
}

void MouseButton(int button, int state, int x, int y)
{
    switch(button)
    {
        case GLUT_LEFT_BUTTON:
        // only start motion if the left button is pressed
            if(state == GLUT_UP)
            {
                theta_angle += delta_theta;
                phi_angle += delta_phi;
                delta_theta = 0;
                delta_phi = 0;
                mouse_x = -1;
                mouse_y = -1;
            }
            else
            {
                mouse_x = x;
                mouse_y = y;
            }
            break;
        case 3:
            if(state == GLUT_UP)
            {
                radius += ROTATE_SPEED;
            }
        default:
            break;
    }
}
//menu
void ProcessMenuEvents(int option)
{
    switch(option)
    {
        case 1:
            ProcessSpecialKeys(GLUT_KEY_HOME, 0, 0);
            break;
        case 2:
            ChangeViewDistance('+');
            break;
        case 3:
            ChangeViewDistance('-');
            break;
        case 4:
            ProcessNormalKeys('q', 0, 0);
            break;
        default:
            break;
    }
}

void CreateGLUTMenus(void)
{
    main_menu = glutCreateMenu(ProcessMenuEvents);
    glutAddMenuEntry("Reset        'home'", 1);
    glutAddMenuEntry("Zoom In    '+'", 2);
    glutAddMenuEntry("Zoom Out  '-'", 3);
    glutAddMenuEntry("Exit            'q'", 4);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
}
//font
void SetOrthographicProjection(void)
{

    glMatrixMode(GL_PROJECTION); // switch to projection mode
    glPushMatrix();              // save previous matrix which contains the settings for the perspective projection
    glLoadIdentity();                              // reset matrix
    gluOrtho2D(0, window_width, window_height, 0); // set a 2D orthographic projection
    glMatrixMode(GL_MODELVIEW);                    // switch back to modelview mode
}

void RestorePerspectiveProjection(void)
{
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();              // restore previous projection matrix
    glMatrixMode(GL_MODELVIEW); // get back to modelview mode
}

void RenderBitmapFontString(GLfloat x, GLfloat y, GLfloat z, void *font, char *string)
{
    glRasterPos3f(x, y, z);
    while(*string != '\0')
    {
        glutBitmapCharacter(font, *string);
        string++;
    }
}

void RenderStrokeFontString(GLfloat x, GLfloat y, GLfloat z, void *font, char *string)
{  
	glPushMatrix();
    glTranslatef(x, y, z);
    glScalef(0.001f, 0.001f, 0.001f);
    while(*string != '\0')
    {
        glutStrokeCharacter(font, *string);
        string++;
    }
	glPopMatrix();
}
//texture
GLuint texture_name;
struct BITMAPFILEHEADER{
    unsigned short bfType;
    unsigned int bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned int bfOffBits;
};
struct BITMAPINFOHEADER{
    unsigned int biSize;
    long biWidth;
    long biHeight;
    unsigned short biPlanes;
    unsigned short biBitcount;
    unsigned int biCompression;
    unsigned int biSizeImage;
    long biXPelsPerMeter;
    long biYPelsPerMeter;
    unsigned int biClrUsed;
    unsigned int biClrImportant;
};
void LoadPicture(char *file_name, GLuint *texture)
{
    FILE *bmp = NULL;
    struct BITMAPFILEHEADER bmfh;
    struct BITMAPINFOHEADER bmih;
    bmp = fopen(file_name, "rb"); //装入位图
    if (bmp == NULL)
        printf("load picture error!\r\n");
    fseek(bmp, 0, SEEK_END);
    int bmp_size = ftell(bmp);
    fseek(bmp, 0, SEEK_SET);
    unsigned char *p_image = malloc(bmp_size * sizeof(char));
    fread(p_image, bmp_size, 1, bmp);
    fseek(bmp, 0, SEEK_SET);
    fread(&bmfh,sizeof(struct BITMAPFILEHEADER),1,bmp);
    fread(&bmih,sizeof(struct BITMAPINFOHEADER),1,bmp);    
    glGenTextures(1, texture);              //生成贴图
    glBindTexture(GL_TEXTURE_2D, *texture); //贴图生效
    gluBuild2DMipmaps(GL_TEXTURE_2D, 4, bmih.biWidth, bmih.biHeight,
                      GL_RGB, GL_UNSIGNED_BYTE, p_image); //贴图数据
    printf("%ld %ld\n", bmih.biWidth, bmih.biHeight);
    printf("%d", bmp_size);
    fclose(bmp);
}

运行结果:
在这里插入图片描述

视点变换,旋转,加速减速,星空背景 太阳,光晕 各行星纹理 #include #include #include #include #include #include #include #pragma comment(lib, "winmm.lib") #pragma comment(lib,"wininet") // 纹理图像结构 typedef struct { int imgWidth; // 纹理宽度 int imgHeight; // 纹理高度 unsigned char byteCount; // 每个象素对应的字节数,3:24位图,4:带alpha通道的24位图 unsigned char *data; // 纹理数据 }TEXTUREIMAGE; // BMP文件头 #pragma pack(2) typedef struct { unsigned short bfType; // 文件类型 unsigned long bfSize; // 文件大小 unsigned short bfReserved1; // 保留位 unsigned short bfReserved2; // 保留位 unsigned long bfOffBits; // 数据偏移位置 }BMPFILEHEADER; #pragma pack() // BMP信息头 typedef struct { unsigned long biSize; // 此结构大小 long biWidth; // 图像宽度 long biHeight; // 图像高度 unsigned short biPlanes; // 调色板数量 unsigned short biBitCount; // 每个象素对应的位数,24:24位图,32:带alpha通道的24位图 unsigned long biCompression; // 压缩 unsigned long biSizeImage; // 图像大小 long biXPelsPerMeter;// 横向分辨率 long biYPelsPerMeter;// 纵向分辨率 unsigned long biClrUsed; // 颜色使用数 unsigned long biClrImportant; // 重要颜色数 }BMPINFOHEADER; // 定义窗口的标题、宽度、高度、全屏布尔变量 #define WIN_TITLE "模拟太阳系各星球的转动" const int WIN_WIDTH = 800; const int WIN_HEIGHT = 600; BOOL isFullScreen = FALSE; // 初始不为全屏 #define DEG_TO_RAD 0.017453 float angle=0.0; static GLdouble viewer[]= {0,0,0,0,0}; // 初始化视角 GLUquadricObj *quadric; // 建立二次曲面对象 GLfloat angle_Z; // 星空旋转角度 bool g_bOrbitOn = true; // 控制转动暂停 float g_fSpeedmodifier = 1.0f; // 时间控制 float g_fElpasedTime; double g_dCurrentTime; double g_dLastTime; GLfloat LightAmbient[] = { 1.0f, 1.0f, 1.0f, 0.0f }; // 环境光参数 GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 0.0f }; // 漫射光参数 GLfloat LightPosition[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // 光源的位置 // 纹理图象 TEXTUREIMAGE skyImg; TEXTUREIMAGE sunImg; TEXTUREIMAGE rayImg; TEXTUREIMAGE mercuImg; TEXTUREIMAGE venusImg; TEXTUREIMAGE earthImg; TEXTUREIMAGE marsImg; TEXTUREIMAGE jupiterImg; TEXTUREIMAGE saturnImg; TEXTUREIMAGE uranusImg; TEXTUREIMAGE neptuneImg; TEXTUREIMAGE moonImg; GLuint texture[12]; // 纹理数组 // 星球速度定义 static float fSunSpin = 0.0f; // 太阳自转速度 static float fMercuSpin = 0.0f; // 水星自转速度 static float fMercuOrbit = 0.0f; // 水星公转速度 static float fVenusSpin = 0.0f; // 金星自转速度 static float fVenusOrbit = 0.0f; // 金星公转速度 static float fEarthSpin = 0.0f; // 地球自转速度 static float fEarthOrbit = 0.0f; // 地球公转速度 static float fMarsSpin = 0.0f; // 火星自转速度 static float fMarsOrbit = 0.0f; // 火星公转速度 static float fJupiterSpin = 0.0f; // 木星自转速度 static float fJupiterOrbit = 0.0f; // 木星公转速度 static float fSaturnSpin = 0.0f; // 土星自转速度 static float fSaturnOrbit = 0.0f; // 土星公转速度 static float fUranusSpin = 0.0f; // 天王星自转速度 static float fUranusOrbit = 0.0f; // 天王星公转速度 static float fNeptuneSpin = 0.0f; // 海王星自转速度 static float fNeptuneOrbit = 0.0f; // 海王星公转速度 static float fMoonSpin = 0.0f; // 月亮自转速度 static float fMoonOrbit = 0.0f; // 月亮公转速度 void MakeTexture(TEXTUREIMAGE textureImg, GLuint * texName) //转换为纹理 { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //对齐像素字节函数 glGenTextures(1,texName); //第一个参数指定表明获取多少个连续的纹理标识符 glBindTexture(GL_TEXTURE_2D , *texName); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureImg.imgWidth,textureImg.imgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImg.data); } // 初始化OpenGL void InitGL(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //设置黑色背景 glClearDepth(2.0f); // 设置深度缓存 glEnable(GL_DEPTH_TEST); //启动深度测试 glDepthFunc(GL_LEQUAL); //深度小或相等的时候渲染 glShadeModel(GL_SMOOTH); //启动阴影平滑 glEnable(GL_CULL_FACE); //开启剔除操作效果 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //使用质量最好的模式指定颜色和纹理坐标的插值质量 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // 设置环境光 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // 设置漫反射光 glEnable(GL_LIGHTING); // 打开光照 glEnable(GL_LIGHT1); // 打开光源1 // 载入纹理 glEnable(GL_TEXTURE_2D); // 开启2D纹理映射 MakeTexture(skyImg, &texture;[0]); MakeTexture(sunImg, &texture;[1]); MakeTexture(rayImg, &texture;[2]); MakeTexture(mercuImg, &texture;[3]); MakeTexture(venusImg, &texture;[4]); MakeTexture(earthImg, &texture;[5]); MakeTexture(marsImg, &texture;[6]); MakeTexture(jupiterImg, &texture;[7]); MakeTexture(saturnImg, &texture;[8]); MakeTexture(uranusImg, &texture;[9]); MakeTexture(neptuneImg, &texture;[10]); MakeTexture(moonImg, &texture;[11]); quadric = gluNewQuadric(); // 建立一个曲面对象指针 gluQuadricTexture(quadric, GLU_TRUE); // 建立纹理坐标 gluQuadricDrawStyle(quadric, GLU_FILL); // 面填充 } void Display(void) { glLoadIdentity(); // 设置观察点的位置和观察的方向 gluLookAt(viewer[0],viewer[1],viewer[2],viewer[3],viewer[4],-5,0,1,0); //摄像机x,摄像机y,摄像机z, 目标点x,目标点y,目标点z, 摄像机顶朝向x,摄像机顶朝向y,摄像机顶朝向z // 获得系统时间使太阳系有动态效果 g_dCurrentTime = timeGetTime(); g_fElpasedTime = (float)((g_dCurrentTime - g_dLastTime) * 0.0005); g_dLastTime = g_dCurrentTime; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode( GL_MODELVIEW ); //指定GL_MODELVIEW是下一个矩阵操作的目标 glTranslatef(0.0f, 0.0f, -5.0f); // 将坐标系移入屏幕5.0f glRotatef(10, 1.0f ,0.0f, 0.0f); // 将坐标系绕x轴旋转10度 glEnable(GL_LIGHT0); // 打开光源0 /**********************************绘制背景星空********************************************/ glPushMatrix (); // 当前模型矩阵入栈 glTranslatef(-10.0f, 3.0f, 0.0f); glRotatef(angle_Z, 0.0f, 0.0f, 1.0f); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[0]); // 星空纹理 glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f( 50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f( 50.0f, 50.0f, -50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, 50.0f, -50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, -1.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f( 50.0f, -50.0f, 50.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 50.0f, 50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f, 50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 0.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f( 50.0f, -50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f( 50.0f, -50.0f, -50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 0.0f, -1.0f, 0.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, 50.0f, -50.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 50.0f, 50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f( 50.0f, 50.0f, -50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f, 50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 1.0f, 0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, 50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f, -50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( -1.0f, 0.0f, 0.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(50.0f, -50.0f, -50.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(50.0f, 50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(50.0f, -50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(50.0f, 50.0f, -50.0f); glEnd(); glPopMatrix (); // 当前模型矩阵出栈 /**********************************绘制太阳************************************************/ glBindTexture(GL_TEXTURE_2D, texture[2]); // 光晕纹理 glEnable(GL_BLEND); // 开启混合 glDisable(GL_DEPTH_TEST); // 关闭深度测试 // 绘制太阳光晕 glDisable(GL_LIGHTING); // 关闭光照 glBlendFunc(GL_SRC_ALPHA,GL_ONE); // 半透明混合函数 glColor4f(1.0f, 0.5f, 0.0f, 0.5f); // 设置RGBA值 glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f); glEnd(); glDisable(GL_BLEND); // 关闭混合 glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); // 开启光照 glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // 设置光源1位置 glBindTexture(GL_TEXTURE_2D, texture[1]); // 太阳纹理 // 将坐标系绕Y轴旋转fSunSpin角度,控制太阳自转 glRotatef(fSunSpin,0.0,1.0,0.0); gluSphere(quadric, 0.3f, 32, 32); // 绘制太阳球体 /**********************************绘制水星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fMercuOrbit角度,控制水星公转 glRotatef(fMercuOrbit, 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(0.5f, 0.0f, 0.0f); // 将坐标系右移0.5f glBindTexture(GL_TEXTURE_2D, texture[3]); // 水星纹理 // 将坐标系绕Z轴旋转fMercuSpin角度 控制水星自转 glRotatef(fMercuSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.04f, 32, 32); // 水星球体 glPopMatrix (); // 当前模型视图矩阵出栈 // 绘制轨道 glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(0.5f*sin(DEG_TO_RAD*angle),0,0.5f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制金星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fVenusOrbit角度,控制金星公转 glRotatef(fVenusOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);// 将坐标系绕X轴旋转-90度 glTranslatef(0.8f, 0.0f, 0.0f); // 将坐标系右移0.8f glBindTexture(GL_TEXTURE_2D, texture[4]); // 金星纹理 // 将坐标系绕Z轴旋转fVenusSpin角度,控制金星自转 glRotatef(fVenusSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.06f, 32, 32); // 金星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(0.8f*sin(DEG_TO_RAD*angle),0,0.8f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制地球************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fEarthOrbit角度,控制地球公转 glRotatef(fEarthOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);// 将坐标系绕X轴旋转-90度 glTranslatef(1.1f, 0.0f, 0.0f); // 将坐标系右移1.1f glBindTexture(GL_TEXTURE_2D, texture[5]); // 地球纹理 // 将坐标系绕Z轴旋转fEarthSpin角度,控制地球自转 glRotatef(fEarthSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.08f, 32, 32); // 地球球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.1f*sin(DEG_TO_RAD*angle),0,1.1f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制火星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fMarsOrbit角度,控制火星公转 glRotatef(fMarsOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(1.4f, 0.0f, 0.0f); // 将坐标系右移1.4f glBindTexture(GL_TEXTURE_2D, texture[6]); // 火星纹理 // 将坐标系绕Z轴旋转fMarsSpin角度,控制火星自转 glRotatef(fMarsSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.04f, 32, 32); // 火星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.4f*sin(DEG_TO_RAD*angle),0,1.4f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制木星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fJupiterOrbit角度,控制木星公转 glRotatef(fJupiterOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(1.7f, 0.0f, 0.0f); // 将坐标系右移1.7f glBindTexture(GL_TEXTURE_2D, texture[7]); // 木星纹理 // 将坐标系绕Z轴旋转fJupiterSpin角度,控制木星自转 glRotatef(fJupiterSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.13f, 32, 32); // 木星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.7f*sin(DEG_TO_RAD*angle),0,1.7f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制土星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fSaturnOrbit角度,控制土星公转 glRotatef(fSaturnOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(1.9f, 0.0f, 0.0f); // 将坐标系右移1.9f glBindTexture(GL_TEXTURE_2D, texture[8]); // 土星纹理 // 将坐标系绕Z轴旋转fSaturnSpin角度,控制土星自转 glRotatef(fSaturnSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.1f, 32, 32); // 土星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.9f*sin(DEG_TO_RAD*angle),0,1.9f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制天王星**********************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fUranusOrbit角度,控制天王星公转 glRotatef(fUranusOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(2.1f, 0.0f, 0.0f); // 将坐标系右移2.1f glBindTexture(GL_TEXTURE_2D, texture[9]); // 天王星纹理 // 将坐标系绕Z轴旋转fUranusSpin角度,控制天王星自转 glRotatef(fUranusSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.1f, 32, 32); // 天王星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(2.1f*sin(DEG_TO_RAD*angle),0,2.1f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制海王星**********************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fNeptuneOrbit角度,控制海王星公转 glRotatef(fNeptuneOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(2.3f, 0.0f, 0.0f); // 将坐标系右移2.3f glBindTexture(GL_TEXTURE_2D, texture[10]); // 海王星纹理 // 将坐标系绕Z轴旋转fNeptuneSpin角度,控制海王星自转 glRotatef(fNeptuneSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.08f, 32, 32); // 海王星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(2.3f*sin(DEG_TO_RAD*angle),0,2.3f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制月亮************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // glBindTexture(GL_TEXTURE_2D, texture[11]); // 月亮纹理 glPushMatrix (); // 将坐标系绕Y轴旋转fEarthOrbit角度,控制月亮跟随地球 glRotatef(fEarthOrbit , 0.0f, 1.0f, 0.0f); glTranslatef(1.1f, 0.0f, 0.0f); // 将坐标系右移1.1f // 将坐标系绕Y轴旋转fMoonOrbit角度,控制月亮公转 glRotatef(fMoonOrbit , 0.0f, 1.0f, 0.0f); glTranslatef(0.15f, 0.0f, 0.0f); // 将坐标系绕Y轴旋转fMoonSpin角度,控制月亮自转 glBindTexture(GL_TEXTURE_2D, texture[11]); glRotatef(fMoonSpin , 0.0f, 1.0f, 0.0f); gluSphere(quadric, 0.02, 32, 32); // 月亮球体 glPopMatrix (); // 控制各星球转动的速度 if( g_bOrbitOn == true ) { fSunSpin -= g_fSpeedmodifier * (g_fElpasedTime * 10.0f); fMercuSpin -= g_fSpeedmodifier * (g_fElpasedTime * 15.0f); fMercuOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 40.0f); fVenusSpin -= g_fSpeedmodifier * (g_fElpasedTime * 10.0f); fVenusOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 30.0f); fEarthSpin -= g_fSpeedmodifier * (g_fElpasedTime * 100.0f); fEarthOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 20.0f); fMarsSpin -= g_fSpeedmodifier * (g_fElpasedTime * 30.0f); fMarsOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 50.0f); fJupiterSpin -= g_fSpeedmodifier * (g_fElpasedTime * 90.0f); fJupiterOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 35.0f); fSaturnSpin -= g_fSpeedmodifier * (g_fElpasedTime * 90.0f); fSaturnOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 25.0f); fUranusSpin -= g_fSpeedmodifier * (g_fElpasedTime * 70.0f); fUranusOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 15.0f); fNeptuneSpin -= g_fSpeedmodifier * (g_fElpasedTime * 40.0f); fNeptuneOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 5.0f); fMoonSpin -= g_fSpeedmodifier * (g_fElpasedTime * 50.0f); fMoonOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 200.0f); } angle_Z += 0.01f; // 星空旋转 glutSwapBuffers(); // 交换双缓存 glFlush(); } void Reshape(int width, int height) { if (height==0) height=1; // 改变窗口 glViewport(0,0,width,height); // 设置视口 // 设置投影矩阵 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(viewer[0],viewer[1],viewer[2],viewer[3],viewer[4],-5,0,1,0); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 'r': case 'R': // 视点上下左右移动 if(viewer[0]=-6.0) viewer[0]-=0.5; break; case 'u': case 'U': if(viewer[1]=-6.0) viewer[1]-=0.1; break; case'+': case '=': // 加速,减速,暂停 g_fSpeedmodifier+=1.0f; glutPostRedisplay(); break; case ' ': g_bOrbitOn = !g_bOrbitOn; glutPostRedisplay(); break; case'-': //按'-'减小运行速度 g_fSpeedmodifier-=1.0f; glutPostRedisplay(); break; case VK_ESCAPE: // 按ESC键时退出 exit(0); break; default: break; } } void special_keys(int s_keys, int x, int y) { switch(s_keys) { case GLUT_KEY_F1: // 按F1键时切换窗口/全屏模式 if(isFullScreen) { glutReshapeWindow(WIN_WIDTH, WIN_HEIGHT); glutPositionWindow(30, 30); isFullScreen = FALSE; } else { glutFullScreen(); isFullScreen = TRUE; } break; case GLUT_KEY_RIGHT: // 视角上下左右旋转 if(viewer[3]=-3.0) viewer[3]-=0.1; break; case GLUT_KEY_UP: if(viewer[4]=-4.5) viewer[4]-=0.1; break; default: break; } } void mouse(int btn, int state, int x, int y) // 远近视角 { if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) viewer[2]+=0.3; if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN&&viewer;[2]>=-3.9) viewer[2]-=0.3; } void LoadBmp(char *filename, TEXTUREIMAGE *textureImg) // 载入图片 { int i, j; FILE *file; BMPFILEHEADER bmpFile; BMPINFOHEADER bmpInfo; int pixel_size; // 初始化纹理数据 textureImg->imgWidth = 0; textureImg->imgHeight = 0; if (textureImg->data != NULL) { delete []textureImg->data; } // 打开文件 file = fopen(filename, "rb"); if (file == NULL) { return; } // 获取文件头 rewind(file); fread(&bmpFile;, sizeof(BMPFILEHEADER), 1, file); fread(&bmpInfo;, sizeof(BMPINFOHEADER), 1, file); // 验证文件类型 if (bmpFile.bfType != 0x4D42) { return; } // 获取图像色彩数 pixel_size = bmpInfo.biBitCount >> 3; // 读取文件数据 textureImg->data = new unsigned char[bmpInfo.biWidth * bmpInfo.biHeight * pixel_size]; for(i = 0 ; i < bmpInfo.biHeight; i++) { fseek(file, bmpFile.bfOffBits + (bmpInfo.biHeight - i - 1) * bmpInfo.biWidth * pixel_size, SEEK_SET); for (j = 0; j data + (i * bmpInfo.biWidth + j) * pixel_size + 2, sizeof(unsigned char), 1, file); // 绿色分量 fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 1, sizeof(unsigned char), 1, file); // 蓝色分量 fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 0, sizeof(unsigned char), 1, file); // Alpha分量 if (pixel_size == 4) { fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 3, sizeof(unsigned char), 1, file); } } } // 记录图像相关参数 textureImg->imgWidth = bmpInfo.biWidth; textureImg->imgHeight = bmpInfo.biHeight; textureImg->byteCount = pixel_size; fclose(file); } // 程序主函数 void main(int argc, char** argv) { //读图片 LoadBmp("Picture//Sky.bmp" , &skyImg;); LoadBmp("Picture//Sun.bmp" , &sunImg;); LoadBmp("Picture//Ray.bmp" , &rayImg;); LoadBmp("Picture//Mercu.bmp" , &mercuImg;); LoadBmp("Picture//Venus.bmp" , &venusImg;); //金星 LoadBmp("Picture//Earth.bmp" , &earthImg;); LoadBmp("Picture//Mars.bmp" , &marsImg;); //火星 LoadBmp("Picture//Jupiter.bmp" , &jupiterImg;); //木星 LoadBmp("Picture//Saturn.bmp" , &saturnImg;); //土星 LoadBmp("Picture//Uranus.bmp" , &uranusImg;); //天王星 LoadBmp("Picture//Neptune.bmp" , &neptuneImg;); //海王星 LoadBmp("Picture//Moon.bmp" , &moonImg;); glutInit(&argc;, argv); // 初始化GLUT库 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); // 初始化显示模式 glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT); // 初始化窗口大小 glutInitWindowPosition(20,20); // 初始化窗口位置 GLuint window = glutCreateWindow(WIN_TITLE); // 建立窗口 InitGL(); // 初始化OpenGL glutDisplayFunc(Display); glutReshapeFunc(Reshape); glutKeyboardFunc(keyboard); glutSpecialFunc(special_keys); glutMouseFunc(mouse); glutIdleFunc(Display); // 设置窗口空闲时的处理函数 glutMainLoop(); // 进入事件处理循环 }
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值