OpenGL基本框架與三維對象繪制


上次我們介紹了OpenGL的環境構建和二維對象的繪制,這次我們來講講三維對象的繪制:

 繪制代碼如下:

Github代碼倉庫

// opengltest2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.1415926
//金字塔初始旋轉角度
GLfloat rtri = 0;
//用戶自定義三維空間的齊次坐標矩陣(4X4)——用於輸出查看變化矩陣的變化
typedef float Mat44[16];
//自定義初始化opengl 環境
void init(void)
{
    //設置背景色——用於填充背景
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    //設置多邊形填充模式為smooth 方式
    glShadeModel(GL_SMOOTH);
    //打開深度測試開關——用於檢測物體間的z 深度差異
    glEnable(GL_DEPTH_TEST);
    //線的抗鋸齒開關
    glEnable(GL_LINE_SMOOTH);
    //啟用抗鋸齒效果
    glHint(GL_LINE_SMOOTH,GL_NICEST);
    //指定混合函數
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    //啟用色彩混合狀態
    glEnable(GL_BLEND);
}
//輸出4X4 矩陣的結果
void outputmat(const Mat44 &mat) {
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 4; j++)
            printf("%.3f ", mat[i * 4 + j]);
        printf("\n");
    }
}

//自定義繪制圓函數
void glCircle()
{
    double n=50;//分段數
    float R=1.0;//半徑
    int i;
    //將繪圖前的模型變換矩陣壓入堆棧
    glPushMatrix();
    //設置顏色RGB 與透明度值(0.5)
    glColor4f(0.0,0.2,0.8, 0.5);
    //發出准備繪圖命令
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(0.0,0.0);
    for(i=0; i<=n; i++)
        glVertex2f(R*cos(2*PI/n*i), R*sin(2*PI/n*i));
    //發出結束繪圖命令
    glEnd();
    //繪圖后,恢復繪圖前的模型變換矩陣
    //這樣,對當前圖形的變換對后面圖形繪制不影響
    glPopMatrix();
}

//opengl 用戶自定義繪圖函數
void display(void)
{
    //清除顏色緩存和深度緩存
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //裝入單位轉換矩陣[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]
    glLoadIdentity();
    //平移變換命令——之后繪制的所有對象將沿Z 軸向屏幕內移動5 個單位
    glTranslatef(0.0f,0.0f,-5.0f);
    //旋轉變換命令——后繪制的所有對象將沿Y 軸正向旋轉rtri 個角度單位
    glRotatef(rtri,0.0f,1.0f,0.0f);
    //以下繪制的對象沿X 軸轉動10 度
    //glRotatef(10, 1, 0, 0);
    //查看當前的4X4 矩陣變量
    Mat44 mat;
    //取得模型-視圖變換矩陣
    glGetFloatv(GL_MODELVIEW_MATRIX, mat);
    //在DOS 控制台查看上述變換后的總變換矩陣結果
    outputmat(mat);
    //設置點元大小為5 個像素
    glPointSize(5);
    //發出命令:開始繪制點
    glBegin(GL_POINTS);
    glColor3f(1, 0, 0);//點的顏色為紅色
    glVertex3f(0.7, 0.5, 0.4);//頂點(vertex)位置:(0.7, 0.5, 0.4)
    glColor3f(1, 0, 0);
    glVertex3f(0.7, 0.5, -0.4);
    glEnd();//結束繪制點
    //繪制坐標軸--X,Y,Z
    glBegin(GL_LINES);
    glColor3f(1, 0, 0);
    glVertex3f(0, 0, 0);
    glVertex3f(3, 0, 0);
    glColor3f(0, 1, 0);
    glVertex3f(0,0,0);
    glVertex3f(0,3,0);
    glColor3f(0, 0, 1);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 0, 3);
    glEnd();
    //繪制2 個三角形
    glBegin(GL_TRIANGLES);
    glColor4f(0, 0, 1, 0.5);
    glVertex2f(-0.7, 0);
    glVertex2f(0.5, 0);
    glVertex2f(0, 0.5);
    glColor4f(0, 1, 1, 0.5);
    glVertex3f(-0.5, -0.2, 0);
    glVertex3f(0.8, -0.2, 0.3);
    glVertex3f(0, 0.2, -0.5);
    glEnd();
    //繪制實心的圓環——在原有變換基礎上,又增加了新的變換;
    //為了不影響后續對象的變換,采用壓棧的方式,保存當前變換矩陣
    glPushMatrix();
    {
        glTranslatef(0.0f, 0.0f, -3.0f);//用於實心圓環的變換
        glColor4f(1.0f, 0.0f, 0.0f, 0.5);
        glutSolidTorus(0.3, 0.7, 30.0f, 30.0f);//繪制實心圓環
    }
    glPopMatrix(); //從堆棧中恢復已壓棧的變換矩陣
    //繪制實心球
    glPushMatrix();
    {
        glTranslatef(1.0f, 1.0f, 3.0f);//增加了變換
        glColor4f(0.0f, 1.0f, 0.0f, 0.5);
        glTranslatef(0.5, 0, 0);
        glutSolidSphere(0.4f, 30.0f, 30.0f);//繪制球體
        glTranslatef(0, 0, -50);
        glutSolidSphere(0.4f, 30.0f, 30.0f);//繪制球體
    }
    glPopMatrix();
    //glScalef( 2.0, 2.0, 0.0 ); //比例變換
    //開始繪制直線段
    glBegin(GL_LINES);
    glColor3f(1, 0, 0);
    glVertex3f(0, 0, 0);
    glVertex3f(1, 0, 0);
    glColor3f(0, 1, 0);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 1, 0);
    glColor3f(0, 0, 1);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 0, 1);
    glEnd();
    //平移變換
    glTranslatef(-2, 0, 0);
    glCircle();
    //平移變換
    glTranslatef(2, 0, 0);
    //繪制立方體線框
    glColor4f(1, 1, 1, 0.5);
    glRotatef(30, 1, 0, 0);
    glutWireCube(1);
    rtri += 0.3;//全局的旋轉變量加0.3 度      
    //用緩沖區所繪制的對象替換窗口內容——適合於雙緩沖技術
    glutSwapBuffers();//交換雙緩存
}

//用戶自定義窗口調整大小事件的處理函數
//在這個函數中要求設置視口、投影、透視變換的相關參數
void reshape (int w, int h)
{
    //設置視口參數為整個窗口范圍內
    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
    //設置投影參數:投影矩陣初始為單位陣
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity();
    //設置透視參數: 眼睛或攝像機的視角參數為60 度,視景體的寬度和高度比,視距(焦距)
    //(near)和視徑(far)參數
    //near = 1, far = 100, Z 軸負向順着視線方向指向屏幕內
    //X 軸正向向右,Y 軸正向向上,坐標原點在屏幕中心處
    gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 100.0);
    //設置攝像機的位置及姿態參數:
    //攝像機位置(cX, cY, cZ)
    //視點所觀察中心位置Ow(oX, oY, oZ)
    //攝像機位姿參數——攝像機頂部矢量
    gluLookAt(0, 0, 5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    //設置矩陣模式為模型-視圖變換模式,以便於后面的自定義顯示函數繼續本模式
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

//用戶自定義鍵盤事件處理函數
void keyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
        case 'x':
        case 27: //ESC 鍵盤
        exit(0);
        break;
        default:
        break;
    }
}

int main(int argc, char** argv)
{
    //用命令行參數初始化OpenGL
    glutInit(&argc, argv);
    //使用RGB 色彩、雙緩存和深度模式
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    //初始化繪圖窗口大小參數
    glutInitWindowSize(1024, 768);
    //窗口左上角坐標參數
    glutInitWindowPosition(0, 0);
    //創建窗口
    glutCreateWindow("OpenGL HelloWorld");
    //用戶自定義初始化繪圖環境函數
    init();
    //用戶指定的繪圖函數,display 名可變
    glutDisplayFunc(display);
    //窗口調整大小事件的處理函數
    glutReshapeFunc(reshape);
    //窗口鍵盤處理事件的處理函數
    glutKeyboardFunc(keyboard);
    //設置窗口空閑時調用的函數
    glutIdleFunc(display);
    //進入glut 函數庫的主循環
    glutMainLoop();
    return 0;
}

 

 效果如下:

 

記得搭建好OpenGL的環境,可以參照這篇文章:http://www.cnblogs.com/OctoptusLian/p/6834669.html

祝Coding愉快~~~

 


免責聲明!

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



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