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 \n", 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\n");
        glutPostRedisplay();
    }
    if (state == GLUT_UP && button == GLUT_WHEEL_DOWN)
    {
        //滾輪向下,表示縮小,減少縮放比例
        if (zoom > 0.02)
        {
            printf("Mouse Wheel Down\n");
            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

運行:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM