Linux下應用OGRE開發3D
linux下應用OGRE開發3D的資料網上很少,今天抽空整理一下。
大部分內容參考OGRE主頁http://www.ogre3d.org/。
首先根據主頁提示,我們可以利用已有資源構建一個工程,具體步驟如下:
第一步,准備工作,確定你是在linux環境下,進入終端,輸入一下命令:
編譯和配置
sudo apt-get install build-essential automake libtool
需要的依賴
sudo apt-get install libfreetype6-dev libfreeimage-dev libzzip-dev libxrandr-dev libxaw7-
dev freeglut3-dev
下面是可選項,一般還是裝上比較穩妥,不然後面出現問題不易查找
sudo apt-get install nvidia-cg-toolkit libois-dev libboost-thread-dev
sudo apt-get install doxygen graphviz libcppunit-dev
至此我們的准備工作已完成。接下來就要下載工程源代碼,然後編譯。
第二步,下載並編譯工程:
下載工程源碼文件:http://www.ogre3d.org/download/source/OGRE 1.7.4 Source for Linux / OSX
解壓文件到/home目錄下:
tar xjf ogre_src_v1-7-4.tar.bz2
進入目錄:
cd ogre_src_v1-7-4
新建文件build,這個文件時用來存放編譯工程項目的,所有的編譯內容都將放在此目錄下:
mkdir build
進入此目錄:
cd build
由於此OGRE工程采用的CMake工具鏈進行編譯。所以使用CMake命令開始編譯:
cmake ..
編譯器會根據CMakeLists.txt產生一個新的CMakeFile文件,接下來的編譯就和Make編譯一樣:
make -j2
如過此處顯示拒絕情況可以加sudo:sudo make -j2
最後一步:
sudo make install
所有的編譯工作已完成,下面就是執行工程,看看3D效果的,這裡還是要說明一下,如果你的電腦不支
持3D那就郁悶吧,因為這直接影響3D的渲染,結果當然是沒辦法看到執行的結果。如果支持3D渲染就繼
續一下操作吧!
cd build (這步已經執行了,只是告訴一下是在這個目錄下)
cd bin
看到可執行文件了吧!
./Samplexxxxxxx 這個文件名記不全了,開頭那幾個字母的文件就這一個,執行後會彈出一個界面,然
後選擇rendersystem,按住不放選中下來菜單,接下來就可以進入了,這裡你會看到所有你編譯的例子
,3D的,太棒了!如果願意,你可以修改源文件參數,重新編譯。
========
Android+Unity3D簡單的物體運動
我們來了解一下Translate的使用
首先我們來看看場景的搭建:建一個立方體,加一個點光源。
我們要實現的就是讓場景中的立方體延X軸嗖嗖的移動
那麼我們在Project新建一個js腳本Creat->Javascript
鍵入代碼
function Update ()
{
transform.Translate(Vector3(1,0,0));
}
然後將js文件拖到Hierarchy面板的立方體上實現綁定。
運行一下,我們可以看到,立方體嗖的一聲不見了。它一定是肚子餓了趕去吃飯了。
好了,我們來修改代碼讓它慢一點。
function Update ()
{
transform.Translate(Vector3(1,0,0)*Time.deltaTime);
}
運行一下,這會它老實了,慢慢的移動了。
這是怎麼回事呢。接下來我們一步一步的分解代碼。
首先Update()沒什麼好講的了,一直在用,相信大家都明白怎麼回事。
接下來是
transform:場景中的每一個對象都有一個transform,用來儲存和控制物體的位置,旋轉和縮放。
Translate:是transform的函數,用來移動物體。它接受一個三維向量(Vector3)參數來移動。其
實它還有第二個參數,就是按照自身坐標軸移動還是按照世界坐標軸移動。這裡暫且不表。
Vector3:表示3D的向量和點。3個參數分別代表了向量x,y,z。
transform.Translate(Vector3(1,0,0));這句代碼的意思就是,讓被綁定的物體,也就是場景中的
立方體,向x軸的方向移動1個單位.
Time.deltaTime:是一個時間增量,我想應該是這一幀的時間。像flash中的一秒30幀,每幀多少秒
之類的。在這個程序中它的值是0.016左右。原本移動一個單位,現在乘以0.016,那肯定慢了。也就是
說,它的作用其實就是減慢移動的速度。
OK。
本文工程源碼下載:
免費下載地址在
用戶名與密碼都是
具體下載目錄在 /pub/Android源碼集錦/2011年/11月/Android+Unity3D簡單的物體運動/
========
Linux下的OpenGL編程
OpenGL是一個工業標准的三維計算機圖形軟件接口,它由SGI公司發布並廣泛應用於Unix、OS/2、
Windows/NT等多種平台,當然也包括Linux。在Windows/NT平台上,一般的開發工具如VC、BC、Fortran
Powerstation等都支持直接的OpenGL應用的開發;在商用Unix平台上,Motif同樣很好的支持OpenGL(畢
竟OpenGL最初是工作站上的東西);那麼在Linux上呢?
本文不著力於OpenGL編程的方法和技巧,而是把重點放在如何在Linux平台上開發OpenGL程序。介
紹支持OpenGL的幾個工具包,並輔以詳細的實例來闡述。
1. Linux下OpenGL編程環境簡介
OpenGL不是自由軟件,它的版權、商標(OpenGL這個名字)都歸SGI公司所有。但在Linux下有
OpenGL的取代產品:Mesa。Mesa提供和OpenGL幾乎完全一致的接口,對利用OpenGL API編程的人來說,
幾乎感覺不到任何差異。Mesa是遵循GPL協議(部分遵循LGPL協議)的自由軟件,而且,正是由於Mesa的
自由性,它在對新硬件的支持度等方面都超過了OpenGL。Mesa可以從www.mesa3d.org取得。得到Mesa後
,依照說明即可生成編寫程序所需要的動態、靜態連接庫和頭文件。
了解OpenGL的讀者都知道,OpenGL本身只提供三維圖形接口,不具備繪制窗口、接受響應、處理消
息等功能。這些功能必須由第三方的開發環境提供,如上面提及的VC等等。有人會想,既然在Motif下可
以開發OpenGL程序,那麼,使用Linux下的Lesstif也應該可以。是的,的確可以,但不幸的是,Linux下
的Lesstif是一個很不成熟的產品,而且也不具有可移植性,所以應用Lesstif開發的人很少。下面我們
簡單介紹幾個常用的工具包。
在Linux下開發OpenGL程序,最常用的工具是GLUT(The OpenGL Utility Toolkit)。它可以創建
一個或多個OpenGL窗口,響應、處理用戶的交互操作、簡單的彈出式菜單以及一些內置的繪圖和字體處
理功能。GLUT和OpenGL一樣,可以移植於多種平台。由於它良好的表現,現在它已經成為Mesa發布的標
准套件之一。
另一個很好的開發工具包是FLTK(Fast Light Tool Kit),這是一個用C++編寫的圖形界面開發工
具。和GTK++、KDE不同,它只關注於圖形界面的設計,而盡量不牽涉其他的實際應用。這個特點使得它
比其他許多開發工具簡練和高效。而且,它同樣也是一個具有良好移植性的開發工具。事實上,它現在
正引來越來越多人的興趣,許多商業軟件(尤其是致力於開發嵌入式桌面系統的軟件)都選用了它作為
圖形界面的開發工具。關於它的詳細情況參見作者的另一篇文章《FLTK---一個優秀的圖形界面開發工具
包》。在FLTK裡有一個組件:Fl_Gl_Window是專門的OpenGL窗口,利用它開發OpenGL程序相當方便。
最後要提的是GTK和KDE,它們是目前在Linux下用的最多的開發工具。GTK本身並不直接支持OpenGL
(新的版本是否支持,尚不太清楚),但有人開發了支持OpenGL的Widget,叫做GLAREA,需要的讀者可
以到網上去查找或者與本文作者聯系。KDE提供了對OpenGL的支持,但它的缺陷之一是KDE只運行於Linux
系統,不具有可移植性。在這裡,我將主要向大家介紹前面兩個工具包。
2. 用GLUT開發OpenGL程序
2.1 如何獲得
GLUT可以從Mesa中獲得,讀者也可以直接到它的主頁去下載它:
http://reality.sgi.com/employees/mjk_asd/glut3/glut3.html。按照說明安裝後在
OpenGL的頭文件GL目錄下將會有GLUT的頭文件glut.h,同時安裝的還有庫文件libglut.a或libglut.so。
有了它們以後,就可以用GLUT來編程了。
2.2 一個簡單的例子
下面,我們先看一個簡單的例子。這個例子畫一個立體的球。
/* light.c
此程序利用GLUT繪制一個OpenGL窗口,並顯示一個加以光照的球。
*/
/* 由於頭文件glut.h中已經包含了頭文件gl.h和glu.h,所以只需要include 此文件*/
# include < GL / glut.h >
# include < stdlib.h >
/* 初始化材料屬性、光源屬性、光照模型,打開深度緩沖區 */
void init ( void )
{
GLfloat mat_specular [ ] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess [ ] = { 50.0 };
GLfloat light_position [ ] = { 1.0, 1.0, 1.0, 0.0 };
glClearColor ( 0.0, 0.0, 0.0, 0.0 );
glShadeModel ( GL_SMOOTH );
glMaterialfv ( GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv ( GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv ( GL_LIGHT0, GL_POSITION, light_position);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable (GL_DEPTH_TEST);
}
/*調用GLUT函數,繪制一個球*/
void display ( void )
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutSolidSphere (1.0, 40, 50);
glFlush ();
}
/* 定義GLUT的reshape函數,w、h分別是當前窗口的寬和高*/
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ( );
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)
{
/*按Esc鍵退出*/
switch (key) {
case 27:
exit ( 0 );
break;
}
}
int main(int argc, char** argv)
{
/* GLUT環境初始化*/
glutInit (&argc, argv);
/* 顯示模式初始化 */
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
/* 定義窗口大小 */
glutInitWindowSize (300, 300);
/* 定義窗口位置 */
glutInitWindowPosition (100, 100);
/* 顯示窗口,窗口標題為執行函數名 */
glutCreateWindow ( argv [ 0 ] );
/* 調用OpenGL初始化函數 */
init ( );
/* 注冊OpenGL繪圖函數 */
glutDisplayFunc ( display );
/* 注冊窗口大小改變時的響應函數 */
glutReshapeFunc ( reshape );
/* 注冊鍵盤響應函數 */
glutKeyboardFunc ( keyboard );
/* 進入GLUT消息循環,開始執行程序 */
glutMainLoop( );
return 0;
}
從上面的例子中我們可以看出,GLUT采用一種函數注冊的機制來實現OpenGL繪圖。它的一般流程正
如我們上面的注釋所寫,先是初始化函數,定義窗口,然後執行OpenGL初始化程序,這主要是一些需要
全局設置的環境變量。接下來是注冊相應事件的函數,包括完成實際繪圖工作的繪制程序、改變OpenGL
窗口大小時的響應函數、鍵盤事件的響應函數和鼠標時間的響應函數。最後調用glutMainLoop()函數
,執行在glutReshapeFunc和glutDisplayFunc中注冊的函數,進入消息循環。當用戶通過鍵盤和鼠標進
行交互操作時,它即調用相應的函數。
我們編譯上面的名為light.c的源文件。假定頭文件(目錄GL)放在目錄/usr/local/include下,
庫文件(動態庫libGL.so.*、libGLU.so.*和libglut.so.*)在目錄/usr/local/lib目錄下,並已經運行
了ldconfig,則編譯命令為:
gcc -I/usr/local/include -L/usr/local/lib -L/usr/X11R6/lib -lglut -lGLU -lGL
-lX11 -lXext -lXmu -lXi -lm light.c -o light
其中的-lX11 -lXert -lXi -lm 是繪制窗口需要的X的庫,它們默認在 /usr/X11R6/lib目錄下。下
面的圖一即是運行light的結果,當按下ESC鍵時,程序會退出。調整窗口大小時,圖形自動重繪。注意
在上面reshape函數中,比較w和h的值給出的取景變換,這是一個常用的技巧。
圖一
2.3 GLUT簡介
GLUT常用的函數主要包括以下幾類:
· 初始化函數。主要就是上面例子中的幾個函數。
· 消息循環函數。即glutMainLoop函數。
· 窗口管理函數。包括窗口的創建、修改、刪除等。GLUT支持多個OpenGL窗口。
· Overlay管理函數。當用戶顯卡支持Overlay方式時,可以用這些函數來創建、管理、刪除GLUT
窗口的Overlay。
· 菜單管理函數。定制菜單以及定義菜單相應事件。
· 事件注冊函數。除了上面例子中提及的外,還有鼠標、空間球(提供三維操作的裝備)、特殊
鍵(Ctrl、Shift、F系列鍵、方向鍵)等設備的事件注冊函數。
· 字體繪制函數。用多種字體、字號供選擇。
· 簡單幾何體的繪制程序。包括球、立方體、錐體、圓環體、十二面體、八面體、四面體、二十
面體和茶壺。每種幾何體都有實體和虛線兩個選項。
· 取狀態函數。類似OpenGL的glGet系列函數,取得GLUT的各種狀態值。
· 顏色索引表函數。
這些函數極大的方便了用戶的OpenGL編程。下面我們簡略介紹一下幾個常用的函數。
· glutPostRedisplay()。發送消息給函數glutMainLoop,請求重繪本窗口。利用此函數可以實
現動畫。例如在上面的例子中,我們添加一個全局變量:float move=0.0。並定義函數MoveSphere如下
:
void MoveSphere ( void )
{
for(int i=0;i<100;i++){
if ( move<1.0) move+=0.1;
else move=0.0;
glutPostRedisplay ( );
}
}
同時修改函數display()為:
void display ( void )
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef ( move, 0.0, 0.0);
glutSolidSphere (1.0, 40, 50);
glFlush ();
}
這樣,當我們執行函數MoveSphere時,就會看到上面的球從中間向右移動一段距離,然後又回到中
心,繼續移動。
· glutIdleFunc()函數。這個函數注冊一個空閒程序一直在後台運行。我們將上面的
MoveSphere函數加以修改,去掉循環,然後在light.c程序的glutMainLoop()函數調用前添加一行代碼
:glutIdleFunc (MoveSphere);這樣我們不需要直接調用函數MoveSphere,程序一運行,它就被反復調
用直到我們退出程序為止,這和我們前一版本中它只能循環特定的步數不一樣。
· glutTimerFunc()函數。和前面的glutIdleFunc()函數類似,但不同的是它注冊的函數每隔
特定的事件發生。時間的單位是毫秒。
· glutBitmapCharacter()函數。用位圖方式按指定的字體繪制一個字符串。
· glutSolidSphere()函數。這是繪制幾何體類函數中的一個。此函數繪制一個球體。
2.4 一個更有代表性的例子
下面我們來看一個稍稍復雜的例子。我們繪制一個平面,用戶的左鍵點擊被自動連接成一個多邊形
。當用戶點擊右鍵,會彈出菜單供用戶選擇。用戶可以選擇清除、鑲嵌和退出。選擇清除將回到初始狀
態;選擇鑲嵌程序自動對多邊形進行三角剖分;選擇退出則終止程序。(見圖二、圖三和圖四)
圖二 圖三 圖四
/* tessdemo.c 多邊形鑲嵌的例子,使用函數gluTessCallback和函數gluTessVertex。*/
#include
#include
#include
#include
/* 定義允許的最大多邊形數、多邊形允許的最大頂點數和可鑲嵌的最大三角形數*/
#define MAX_POINTS 256
#define MAX_CONTOURS 32
#define MAX_TRIANGLES 256
/* 用於菜單選項的枚舉類型 */
typedef enum{ QUIT, TESSELATE, CLEAR } menu_entries;
static mode_type mode;
/* 定義繪制模式的枚舉類型 */
typedef enum{ DEFINE, TESSELATED } mode_type;
static int menu;
static GLsizei width, height; /* OpenGL窗口的大小 */
static GLuint contour_cnt; /* 記錄多邊形數目 */
static GLuint triangle_cnt; /* 記錄三角形數目 */
static GLuint list_start; /* 用於顯示列表 */
/* 多邊形結構 */
static struct {
GLfloat p[MAX_POINTS][2];
GLuint point_cnt;
} contours [ MAX_CONTOURS ] ;
/* 三角形結構 */
static struct {
GLsizei no;
GLfloat p [3] [2];
GLclampf color [3] [3];
} triangles [ MAX_TRIANGLES ];
/* 窗口大小改變時,設定width和height值,用於重新繪制網格 */
void set_screen_wh ( GLsizei w, GLsizei h )
{ width = w; height = h; }
void tesse ( void )
{ /* 鑲嵌函數,調用gluTess* 函數實現*/ }
/* 對點擊鼠標左鍵事件的響應函數:更新當前多邊形頂點數組,並重新繪制 */
void left_down ( int x1, int y1 )
{
GLfloat P[2];
GLuint point_cnt;
/* 將GLUT窗口坐標變換為GL坐標:前者(0,0)在左上角而後者在左下角*/
P[0] = x1; P[1] = height - y1;
/* 更新頂點數據 */
point_cnt = contours [ contour_cnt ] . point_cnt;
contours [ contour_cnt ] . p [ point_cnt ][ 0 ] = P [ 0 ];
contours [ contour_cnt ]. p [ point_cnt ] [ 1 ] = P [ 1 ];
/* 繪制新添加的邊,若為第一個點,則繪制一個點 */
glBegin ( GL_LINES );
if ( point_cnt ) {
glVertex2fv ( contours[contour_cnt].p[point_cnt-1] );
glVertex2fv ( P );
}
else {
glVertex2fv ( P );
glVertex2fv ( P );
}
glEnd();
glFinish();
contours[contour_cnt].point_cnt++;
}
/* 點擊鼠標中鍵的響應事件,有些系統可以用同時點擊左右鍵模擬:結束一個多邊形 */
void middle_down( int x1, int y1 )
{
GLuint point_cnt;
(void) x1;
(void) y1;
point_cnt = contours[contour_cnt].point_cnt;
/* 連接起始點和最後一個點,構成一個完整的多邊形 */
if ( point_cnt > 2 )
{
glBegin( GL_LINES );
glVertex2fv( contours[contour_cnt].p[0] );
glVertex2fv( contours[contour_cnt].p[point_cnt-1] );
contours[contour_cnt].p[point_cnt][0] = -1;
glEnd();
glFinish();
contour_cnt++;
contours[contour_cnt].point_cnt = 0;
}
}
/* 處理鼠標響應的函數,根據按鍵的類型調用不同的函數:左鍵和中鍵。 */
void mouse_clicked( int button, int state, int x, int y )
{
/* 將OpenGL的像素坐標換為背景的網格坐標,背景網格為邊長為10的小正方形 */
x -= x%10;
y -= y%10;
switch ( button ) {
case GLUT_LEFT_BUTTON: /* GLUT發現左鍵被點擊 */
if ( state == GLUT_DOWN ) {
left_down( x, y );
}
break;
case GLUT_MIDDLE_BUTTON: /* 中鍵被點擊 */
if ( state == GLUT_DOWN ) {
middle_down( x, y );
}
break;
}
}
/* OpenGL繪制函數,有兩種模式 */
void display( void )
{
GLuint i,j;
GLuint point_cnt;
glClear( GL_COLOR_BUFFER_BIT );
switch ( mode )
{
case DEFINE: /* 多邊形定義階段 */
/* 繪制網格,單個網格大小為10像素,網格數目取決於OpenGL窗口大小 */
glColor3f ( 0.6, 0.5, 0.5 );
glBegin ( GL_LINES );
for ( i = 0 ; i < width ; i += 10 ){
for ( j = 0 ; j < height ; j += 10 ) {
glVertex2i ( 0, j );
glVertex2i ( width, j );
glVertex2i ( i, height );
glVertex2i ( i, 0 );
}
}
/* 繪制多邊形 */
glColor3f( 1.0, 1.0, 0.0 );
for ( i = 0 ; i <= contour_cnt ; i++ ) {
point_cnt = contours[i].point_cnt;
glBegin( GL_LINES );
switch ( point_cnt ) {
case 0:
break;
case 1:
glVertex2fv ( contours[i].p[0] );
glVertex2fv ( contours[i].p[0] );
break;
case 2:
glVertex2fv( contours[i].p[0] );
glVertex2fv( contours[i].p[1] );
break;
default:
--point_cnt;
for ( j = 0 ; j < point_cnt ; j++ ) {
glVertex2fv ( contours [ i ]. p [ j ] );
glVertex2fv ( contours [ i ] .p [ j+1 ] );
}
if ( contours [ i ].p [ j+1 ] [ 0 ] == -1 )
{
glVertex2fv ( contours [ i ]. p [ 0 ] );
glVertex2fv ( contours [ i ] .p [ j ] );
}
break;
}
glEnd();
}
glFinish();
break;
case TESSELATED: /* 繪制鑲嵌後的多邊形,顯示列表由函數tesse()給出 */
glColor3f( 0.7, 0.7, 0.0 );
glCallList( list_start );
glLineWidth( 2.0 );
glCallList( list_start + 1 );
glLineWidth( 1.0 );
glFlush();
break;
}
glColor3f( 1.0, 1.0, 0.0 );
}
/* 菜單選項clear的響應函數,將所有變量清零,繪制模式設為DEFINE */
void clear( void )
{
contour_cnt = 0;
contours[0].point_cnt = 0;
triangle_cnt = 0;
mode = DEFINE;
glDeleteLists( list_start, 2 );
list_start = 0;
}
/* 菜單選項quit的響應函數,退出程序 */
void quit( void )
{
exit( 0 );
}
/* 定義菜單的響應函數 */
void menu_selected( int entry )
{
switch ( entry ) {
case CLEAR:
clear ( );
break;
case TESSELATE:
tesse ( );
break;
case QUIT:
quit ( );
break;
}
/* 選擇菜單後重繪OpenGL窗口 */
glutPostRedisplay();
}
/* 定義快捷鍵響應函數 */
void key_pressed( unsigned char key, int x, int y )
{
/* 在此例子中,不需要用表明鼠標位置的變量x和y */
( void ) x; ( void ) y;
/* 針對不同按鍵,定義動作 */
switch ( key ) {
case 'c':
case 'C':
clear();
break;
case 't':
case 'T':
tesse();
break;
case 'q':
case 'Q':
quit();
break;
}
/* 按鍵後重繪窗口 */
glutPostRedisplay();
}
/* 執行一些程序的初始化過程 */
void myinit( void )
{
/* 設置窗口背景顏色*/
glClearColor( 0.4, 0.4, 0.4, 0.0 );
glShadeModel( GL_FLAT );
glPolygonMode( GL_FRONT, GL_FILL );
/* 創建一個菜單,並定義菜單項及該菜單對應的響應函數 */
menu = glutCreateMenu( menu_selected );
glutAddMenuEntry( "clear", CLEAR );
glutAddMenuEntry( "tesselate", TESSELATE );
glutAddMenuEntry( "quit", QUIT );
/* 定義菜單動作方式:點擊右鍵彈出 */
glutAttachMenu( GLUT_RIGHT_BUTTON );
/* 注冊鼠標事件響應函數 */
glutMouseFunc( mouse_clicked );
/* 注冊鍵盤事件響應函數 */
glutKeyboardFunc( key_pressed );
contour_cnt = 0;
mode = DEFINE;
}
/* 定義窗口大小改變時的響應 */
static void reshape( GLsizei w, GLsizei h )
{
glViewport( 0, 0, w, h );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
set_screen_wh( w, h );
}
int main( int argc, char **argv )
{
/* 創建窗口 */
glutInit ( & argc, argv );
glutInitDisplayMode ( GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize ( 400, 400 );
glutCreateWindow( argv[0] );
myinit();
glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutMainLoop();
return 0;
}
3. 用FLTK開發OpenGL程序
從上面的例子我們不難看出,雖然GLUT為實現OpenGL編程提供了可能,但是作為應用程序,它是遠
遠不夠的。它只提供了原始、簡陋的控制和操作方式,沒有一般應用程序所需要的按鈕、菜單條、輸入
框等控件。事實上,GLUT並不是用來單獨開發應用程序的,它是用作介於OpenGL函數接口和一般的圖形
界面開發接口之間的過渡層。在這一點上,它無疑是成功的。Mesa選擇它作為標准套件分發,大多數圖
形界面開發工具也保持與它的兼容性。從而使得用GLUT開發的OpenGL程序有良好的可移植性。
和GLUT不同,FLTK本身是一個圖形界面開發工具,使用它完全可以開發實用的、商用的應用程序。
FLTK用C++編寫,使用面向對象的開發技術,它提供多種組件供用戶選用,每個組件有自己的屬性和事件
。在這裡,我們主要講述它的OpenGL窗口組件:Fl_Gl_Window,並充分使用C++的特性。
這一節裡,我們繪制一個可以自由旋轉、平移、放縮的小立方體。程序運行後如圖五所示。整個窗
口是一個由Fl_Window組件定義的一般窗口,中間是一個OpenGL窗口。我們使用了一些控制工具來調整小
立方體的屬性。上面的Zoom標尺調整它的大小,左邊和下邊各有一個平移標尺和一個旋轉標尺,調整小
立方體的位置和角度。這些標尺都是FLTK的標准組件,它們的作用是根據用戶的動作返回特定的整數或
符點數。
Fl_Gl_Window最重要的是兩個虛函數:draw()、handle()和成員函數redraw()。函數draw(
)中定義繪制內容,創建窗口和窗口大小改變是這個函數被自動調用。函數handle()中定義對各種鍵
盤、鼠標事件的響應。當有鍵盤、鼠標事件響應時,這個函數被自動調用,如何有響應事件的函數被定
義,則會執行此函數。函數redraw()重繪窗口。在這個叫做CubeView的例子中,我們派生
Fl_Gl_Window,得到繪制我們這個小立方體的OpenGL窗口。
// 文件CubeView.cxx,派生Fl_Gl_Window,得到繪制小立方體的OpenGL窗口
#include
#include
#include
#include
#include
// 派生類CubeView的定義
class CubeView : public Fl_Gl_Window {
public:
double size; // 定義小立方體的大小,供glScalef()函數使用
// 構造函數,派生自Fl_Gl_Window,定義窗口大小和標題
CubeView(int x,int y,int w,int h,const char *l=0);
// 設置和取得垂直方向的旋轉角度,供組件標尺調用
void v_angle(float angle){vAng=angle;};
float v_angle(){return vAng;};
// 設置和取得水平方向的旋轉角度,供組件標尺調用
void h_angle(float angle){hAng=angle;};
float h_angle(){return hAng;};
// 設置水平和垂直方向的偏移量
void panx(float x){xshift=x;};
void pany(float y){yshift=y;};
void draw();
private:
void drawCube();
float vAng,hAng;
float xshift,yshift;
float boxv0[3];float boxv1[3];
float boxv2[3];float boxv3[3];
float boxv4[3];float boxv5[3];
float boxv6[3];float boxv7[3];
};
// 構造函數的定義
CubeView::CubeView(int x,int y,int w,int h,const char *l)
: Fl_Gl_Window(x,y,w,h,l)
{
// 設置變換初值
vAng = 0.0;
hAng=0.0;
size=10.0;
// 設置小立方體頂點參數
boxv0[0] = -0.5; boxv0[1] = -0.5; boxv0[2] = -0.5;
boxv1[0] = 0.5; boxv1[1] = -0.5; boxv1[2] = -0.5;
boxv2[0] = 0.5; boxv2[1] = 0.5; boxv2[2] = -0.5;
boxv3[0] = -0.5; boxv3[1] = 0.5; boxv3[2] = -0.5;
boxv4[0] = -0.5; boxv4[1] = -0.5; boxv4[2] = 0.5;
boxv5[0] = 0.5; boxv5[1] = -0.5; boxv5[2] = 0.5;
boxv6[0] = 0.5; boxv6[1] = 0.5; boxv6[2] = 0.5;
boxv7[0] = -0.5; boxv7[1] = 0.5; boxv7[2] = 0.5;
};
void CubeView::drawCube() {
// 繪制一個半透明的立方體
#define ALPHA 0.5
glShadeModel(GL_FLAT);
// 用不同的顏色繪制六個面
glBegin(GL_QUADS);
glColor4f (0.0, 0.0, 1.0, ALPHA );
glVertex3fv ( boxv0 ); glVertex3fv ( boxv1 ); glVertex3fv ( boxv2 ); glVertex3fv( boxv3 );
glColor4f(1.0, 1.0, 0.0, ALPHA);
glVertex3fv ( boxv0 ); glVertex3fv ( boxv4 ); glVertex3fv ( boxv5 ); glVertex3fv ( boxv1 );
glColor4f(0.0, 1.0, 1.0, ALPHA);
glVertex3fv ( boxv2 ); glVertex3fv ( boxv6 ); glVertex3fv ( boxv7 ); glVertex3fv ( boxv3 );
glColor4f(1.0, 0.0, 0.0, ALPHA);
glVertex3fv ( boxv4 ); glVertex3fv ( boxv5 ); glVertex3fv ( boxv6 ); glVertex3fv ( boxv7 );
glColor4f(1.0, 0.0, 1.0, ALPHA);
glVertex3fv ( boxv0 ); glVertex3fv ( boxv3 ); glVertex3fv ( boxv7 ); glVertex3fv ( boxv4 );
glColor4f(0.0, 1.0, 0.0, ALPHA);
glVertex3fv ( boxv1 ); glVertex3fv ( boxv5 ); glVertex3fv ( boxv6 ); glVertex3fv ( boxv2 );
glEnd();
// 繪制立方體的輪廓線,一共12條
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex3fv ( boxv0 ); glVertex3fv ( boxv1 );
glVertex3fv ( boxv1 ); glVertex3fv ( boxv2 );
glVertex3fv ( boxv2 ); glVertex3fv ( boxv3 );
glVertex3fv ( boxv3 ); glVertex3fv ( boxv0 );
glVertex3fv ( boxv4 ); glVertex3fv ( boxv5 );
glVertex3fv ( boxv5 ); glVertex3fv ( boxv6 );
glVertex3fv ( boxv6 ); glVertex3fv ( boxv7 );
glVertex3fv ( boxv7 ); glVertex3fv ( boxv4 );
glVertex3fv ( boxv0 ); glVertex3fv ( boxv4 );
glVertex3fv ( boxv1 ); glVertex3fv ( boxv5 );
glVertex3fv ( boxv2 ); glVertex3fv ( boxv6 );
glVertex3fv ( boxv3 ); glVertex3fv ( boxv7 );
glEnd();
};
void CubeView::draw() {
if (!valid ( ) ) {
//valid()當窗口大小改變時改變,導致這一部分內容被執行,重新設置窗口
glLoadIdentity();
glViewport(0,0,w(),h());
glOrtho(-10,10,-10,10,-20000,10000);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix ( );
// 變換。參數繪被外部函數修改
glTranslatef ( xshift, yshift, 0);
glRotatef ( hAng, 0, 1, 0 ); glRotatef ( vAng, 1, 0, 0 );
glScalef ( float ( size ), float ( size ) , float ( size ) );
// 繪制立方體
drawCube ( );
glPopMatrix ( );
};
上面的類CubeView定義了一個繪制立方體的OpenGL窗口,外部函數可以調用它的成員函數v_angle、
h_angle、panx、pany等來修改這個小立方體的屬性,修改以後,可以調用函數redraw()來刷新窗口。
在下面的CubeViewUI.cxx中,我們定義類CubeViewUI,它繪制主窗口,並在其中定義了類CubeView的一
個實例:cube。它同時還定義了用來控制立方體屬性的5個標尺,當用戶操作標尺時,這些標尺調用
v_angle等函數來設置繪制立方體的一些參數。這一部分和我們的主題關系不大,不給出具體的代碼。最
後,我們定義main函數,它的內容相當的簡單。
#include "CubeViewUI.h"
int main(int argc, char **argv) {
// 定義類CubeViewUI的一個實例
CubeViewUI *cvui=new CubeViewUI;
// 設置FLTK窗口顯示模式
Fl::visual(FL_DOUBLE|FL_INDEX);
cvui->show();
// 進入消息循環
return Fl::run();
}
我們編譯、連接並執行程序,就可以得到如圖五所示的結果。從上面的例子我們可以看出使用FLTK編寫
OpenGL程序的一些優點,和GLUT它結構清晰,使用方便,而且它和GLUT是兼容的。除了glutInit()、
glutMainLoop()等少數函數外,大部分GLUT函數可以在FLTK中使用。FLTK本身也提供了許多OpenGL函
數,如繪制字符串的gl_draw()等。
4. 結束語
熟悉掌握了Linux下OpenGL的開發環境距離開發OpenGL程序還有很大的距離,畢竟問題的難點是如
何很好的使用OpenGL的API。本文為即將在Linux下開發OpenGL的讀者作一些鋪墊和准備工作,希望並相
信對大家有所幫助。
========
linux openGL "Hello world"
1. 安裝OpenGL相關工具
sudo apt-get install mesa-common-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev
note:
libgl1-mesa-de 對應 GL庫;
libglu1-mesa-dev對應GLU庫 TJe opengl utility library;
freeglut3-dev 對應glut庫
mesa-common-de :This package includes the specifications for the Mesa-specific
OpenGL extensions, the complete set of release release notes and the development header
files common to all Mesa packages.
2. example 上代碼:
#include
#define window_width 640
#define window_height 480
// Main loop
void main_loop_function()
{
// Z angle
static float angle;
// Clear color (screen)
// And depth (used internally to block obstructed objects)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Load identity matrix
glLoadIdentity();
// Multiply in translation matrix
glTranslatef(0, 0, -10);
// Multiply in rotation matrix
glRotatef(angle, 0, 0, 1);
// Render colored quad
glBegin(GL_QUADS);
glColor3ub(255, 000, 000);
glVertex2f(-1, 1);
glColor3ub(000, 255, 000);
glVertex2f(1, 1);
glColor3ub(000, 000, 255);
glVertex2f(1, -1);
glColor3ub(255, 255, 000);
glVertex2f(-1, -1);
glEnd();
// Swap buffers (color buffers, makes previous render visible)
glutSwapBuffers();
// Increase angle to rotate
angle += 0.25;
}
// Initialze OpenGL perspective matrix
void GL_Setup(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glEnable(GL_DEPTH_TEST);
gluPerspective(45, (float) width / height, .1, 100);
glMatrixMode(GL_MODELVIEW);
}
// Initialize GLUT and start main loop
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(window_width, window_height);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("GLUT Example!!!");
glutIdleFunc(main_loop_function);
GL_Setup(window_width, window_height);
glutMainLoop();
return 0;
}
3. 編譯:
gcc example.cpp -o example -lglut -lGL -lGLU
4. 運行:
./example
========
linux下基於eclipse的opengl開發環境搭建
博客分類: opengl
eclipseopenglubuntu
轉自:http://www.cnblogs.com/lycheng/archive/2011/09/13/2174831.html
1. 安裝OpenGL相關工具
sudo apt-get install mesa-common-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev
其中,
libgl1-mesa-de 對應 GL庫;
libglu1-mesa-dev對應GLU庫 TJe opengl utility library;
freeglut3-dev 對應glut庫
mesa-common-de :This package includes the specifications for the Mesa-specific
OpenGL extensions, the complete set of release release notes and the development header
files common to all Mesa packages.
2. 設置Eclipse
安裝eclipse cdt插件
8.0.0 下載地址: http://www.eclipse.org/cdt/downloads.php
Project -> properties -> C / C++ Build / Settings -> Tool Setting
然後選擇Cross G++ Linker 選擇 Libraries, 在Libraries 中插入: glut GL GLU
在Libraries Search Paths 中插入:
/usr/include/GL
3. 測試代碼 example.cpp
Java代碼 收藏代碼
#include
#define window_width 640
#define window_height 480
// Main loop
void main_loop_function()
{
// Z angle
static float angle;
// Clear color (screen)
// And depth (used internally to block obstructed objects)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Load identity matrix
glLoadIdentity();
// Multiply in translation matrix
glTranslatef(0, 0, -10);
// Multiply in rotation matrix
glRotatef(angle, 0, 0, 1);
// Render colored quad
glBegin(GL_QUADS);
glColor3ub(255, 000, 000);
glVertex2f(-1, 1);
glColor3ub(000, 255, 000);
glVertex2f(1, 1);
glColor3ub(000, 000, 255);
glVertex2f(1, -1);
glColor3ub(255, 255, 000);
glVertex2f(-1, -1);
glEnd();
// Swap buffers (color buffers, makes previous render visible)
glutSwapBuffers();
// Increase angle to rotate
angle += 0.25;
}
// Initialze OpenGL perspective matrix
void GL_Setup(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glEnable(GL_DEPTH_TEST);
gluPerspective(45, (float) width / height, .1, 100);
glMatrixMode(GL_MODELVIEW);
}
// Initialize GLUT and start main loop
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(window_width, window_height);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("GLUT Example!!!");
glutIdleFunc(main_loop_function);
GL_Setup(window_width, window_height);
glutMainLoop();
return 0;
}
Run All 之後, 會顯示旋轉的方型, 如果不需要IDE, 則可用命令行編譯。
4. 命令行編譯
gcc example.cpp -o example -lglut -lGL -lGLU
-o 表示輸出的文件名
-l 表示鏈接的庫
========