zoukankan      html  css  js  c++  java
  • 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

    运行:

  • 相关阅读:
    MSSQl分布式查询
    欲善其事,必利其器 Librame Utility R1 实用工具包(.NET Framework 3.5)
    可复用的WPF或者Silverlight应用程序和组件设计(3)——控件级别
    Asp.Net 网站优化 数据库优化措施 使用主从库
    .NET独有的精巧泛型设计模式
    Javascript 使用 "大杂烩"
    淘宝下单高并发解决方案
    时间戳(timestamp)
    MSSQL锁机制
    maven开发过程实践
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/12143790.html
Copyright © 2011-2022 走看看