C语言使用OpenGL制作旋转地球

前置步骤(安装依赖库):

  • sudo apt-get update
  • sudo apt-get install build-essential
  • sudo apt-get install libgl1-mesa-dev
  • sudo apt-get install libglu1-mesa-dev 
  • $sudo apt-get install freeglut3-dev 
  • sudo apt-get install libfreeimage3 sudo apt-get install libfreeimage-dev

 1.测试OpenGL环境

#include<GL/glut.h>

void init()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glOrtho(-5, 5, -5, 5, 5, 15);
    gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
    return ;
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0, 0);
    glutWireTeapot(3);
    glFlush();
    return;
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(300, 300);
    glutCreateWindow("OpenGL #D View");
    init();
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}

编译:

gcc test.c -o test -lGL -lGLU -lglut 

运行:

如果能出现这个图片,证明环境配置成功。

2.旋转地球模型

#include<stdio.h>
#include<stdlib.h>
#include<GL/glut.h>
#include<GL/gl.h>
#include<GL/glu.h>
#include<FreeImage.h>

#define GLUT_WHEEL_UP 3
#define GLUT_WHEEL_DOWN 4

struct _AUX_RGBImageRec
{
    unsigned long sizeX;
    unsigned long sizeY;
    unsigned char *data;
};

typedef struct _AUX_RGBImageRec AUX_RGBImageRec;

GLuint texture[1];    //存储一个纹理
GLfloat rtri;        //存储旋转变量,不断改变器值
GLfloat zoom = 1.0f;    //缩放程度,默认位1,用于放大或缩小
GLfloat xpos = 0.f;        //x方向移动
GLfloat ypos = 0.f;        //y方向移动

void init();
void display(void);
void reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);
void processMouse(int button, int state, int x, int y);
void changeParam();
int LoadGLTextures();
GLboolean LoadBmp(const char *filename, AUX_RGBImageRec* texture_image);

int main(int argc, char **argv)
{
    glutInit(&argc, argv);    //GLUT环境初始化
    
    //显示模式初始化
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    
    //定义窗口daxiao
    glutInitWindowSize(600, 600);
    
    //定义窗口位置
    glutInitWindowPosition(400, 600);
    
    //显示窗口位置,窗口标题为执行函数名
    glutCreateWindow("EarthDemo");

    //调用OpenGL初始化函数
    init();
    
    //注册OpenGL绘图函数
    glutDisplayFunc(display);
    
    //注册窗口大小改变时的响应函数
    glutReshapeFunc(reshape);
    
    //注册键盘响应事件
    glutKeyboardFunc(keyboard);
    
    //注册鼠标响应事件
    glutMouseFunc(processMouse);
    
    ////注册自动旋转的函数
    glutIdleFunc(changeParam);
    
    //进入GLUT消息循环,开始执行函数
    glutMainLoop();
    return 0;
}

/*初始化openGL*/
void init()
{
    LoadGLTextures();        //载入纹理
    glEnable(GL_TEXTURE_2D);                //启动纹路映射
    glShadeModel(GL_SMOOTH);                //启用阴影平滑
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    //黑色背景
    glClearDepth(1.0f);                        //设置深度缓存
    glClearDepth(GL_DEPTH_TEST);            //启用深度测试
    glDepthFunc(GL_LEQUAL);                    //所作深度测试的类型
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    //真正精细的透视修正
}

/*载入位图(调用上面的代码)转换成纹理*/
int LoadGLTextures()
{
    int Status = FALSE;        //状态指示器
    AUX_RGBImageRec *textureImage;    //创建纹理的存储空间
    textureImage = malloc(sizeof(AUX_RGBImageRec));

    //载入位图,检查有无错误,如果位图没找到则退出
    if (LoadBmp("earth.bmp", textureImage))
    {
        Status = TRUE;
        glGenTextures(1, &texture[0]);    //创建纹理的存储空间
        
        /*使用来自位图数据生成的典型纹理*/
        glBindTexture(GL_TEXTURE_2D, texture[0]);
        /*生成纹理*/
        glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage->sizeX, textureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage->data);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    }

    //纹理是否存在
    if (textureImage)
    {
        //纹理图像是否存在
        if (textureImage->data)
        {
            free(textureImage->data);    //释放纹理图像占用的内存
        }
        free(textureImage);    //释放图像结构
    }

    return Status;
}


void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);    //清楚平面和深度缓存
    glLoadIdentity();                //重置当前的模型观察矩阵

    //加上xpos,ypos产生移动效果
    glTranslatef(0.0f+xpos, 0.0f+ypos, -5.0f);    //移入屏幕5个单位
    //此处进行缩放, x,y,z,方向均按此比例缩放
    glScalef(zoom, zoom, zoom);
    
    glRotatef(rtri, 0.0f, 1.0f, 0.0f);            //绕Y轴旋转
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    glBegin(GL_QUADS);                            //绘制四边形
    GLUquadric* quadricObj = gluNewQuadric();    //gluNewQuadric创建一个新的二次曲面对象
    gluQuadricTexture(quadricObj, GL_TRUE);
    
    /*参数1:二次曲面对象指针
    **参数2:球半径
    **参数3:Z轴方向片数,经度方向
    **参数4:Y周方向片数,纬度方向
    */
    gluSphere(quadricObj, 1, 100, 100);
    
    //gluDeleteQuadric删除一个二次曲面对象
    gluDeleteQuadric(quadricObj);
    glEnd();

    //通知硬件绘制图像
    glFinish();
    return ;
}

/*窗口大小发生变化时调用*/
void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //利用glOrtho创建一个正交平行的视景体
    if (w <= h)
    {

        glOrtho(-1.5, 1.5, -1.5*(GLfloat)h / (GLfloat)w, 
                1.5 *(GLfloat)h / (GLfloat)w, -10.0, 10.0);
    }
    else
    {

        glOrtho(-1.5*(GLfloat)w / (GLfloat)h, 1.5*(GLfloat)w / (GLfloat)h,
                -1.5, 1.5, -10.0, 10.0);
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();    
}

/*定义对键盘的响应函数*/
void keyboard(unsigned char key, int x, int y)
{
    switch ((key))
    {
        /*ESC键退出*/
        case 27:
            exit(0);
            break;
        case '+':    //放大
            zoom += 0.03;
            break;
        case '-':    //缩小
            zoom -= 0.03;
            break;     
        case 'w':    //上移
            ypos += 0.03;
            break; 
        case 's':    //下移
            ypos -= 0.03;
            break; 
        case 'a':    //左移
            xpos -= 0.03;
            break; 
        case 'd':    //右移
            xpos += 0.03;
            break;              
        default:
            break;
    }

    printf("Enter Key %c zoom = %lf, xpos = %lf, ypos = %lf 
", key, zoom, xpos, ypos);
}

//处理鼠标事件
void processMouse(int button, int state, int x, int y)
{
    if (state == GLUT_UP && button == GLUT_WHEEL_UP)
    {
        //滚轮向上,表示放大,增大缩放比例
        zoom += 0.02;
        printf("Mouse Wheel UP
");
        glutPostRedisplay();
    }
    if (state == GLUT_UP && button == GLUT_WHEEL_DOWN)
    {
        //滚轮向下,表示缩小,减少缩放比例
        if (zoom > 0.02)
        {
            printf("Mouse Wheel Down
");
            zoom -= 0.02;
        }

        glutPostRedisplay();
    }
}

// 自动旋转函数,用于修改绘制时所需要的参数
void changeParam()
{
    rtri += 0.05f;
    glutPostRedisplay();
}

/*
*利用freeimage加载bmp图像
*此函数在Linux系统上可以作为util调用
*/
GLboolean LoadBmp(const char *filename, AUX_RGBImageRec* texture_image)
{
    FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(filename, 0);

    FIBITMAP *dib = FreeImage_Load(fifmt, filename, 0);
    dib = FreeImage_ConvertTo24Bits(dib);

    int width = FreeImage_GetWidth(dib);
    int height = FreeImage_GetHeight(dib);

    BYTE *pixels = (BYTE*) FreeImage_GetBits(dib);
    int pix = 0;

    if (texture_image == NULL)
    {
        return FALSE;
    }

    texture_image->data = (BYTE*) malloc(width * height * 3);
    texture_image->sizeX = width;
    texture_image->sizeY = height;

    for (pix = 0; pix < width * height; pix++)
    {
        texture_image->data[pix*3 + 0] = pixels[pix * 3 + 2];
        texture_image->data[pix*3 + 1] = pixels[pix * 3 + 1];
        texture_image->data[pix*3 + 2] = pixels[pix * 3 + 0];
    }

    FreeImage_Unload(dib);

    return TRUE;
}

编译:

gcc main.c -o main -lGL -lGLU -lglut -lfreeimage

运行:

原文地址:https://www.cnblogs.com/wanghao-boke/p/12143790.html