Linux 3D 编程学习总结
生活随笔
收集整理的這篇文章主要介紹了
Linux 3D 编程学习总结
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Linux下應(yīng)用OGRE開發(fā)3D
linux下應(yīng)用OGRE開發(fā)3D的資料網(wǎng)上很少,今天抽空整理一下。
大部分內(nèi)容參考OGRE主頁http://www.ogre3d.org/。
首先根據(jù)主頁提示,我們可以利用已有資源構(gòu)建一個(gè)工程,具體步驟如下:
第一步,準(zhǔn)備工作,確定你是在linux環(huán)境下,進(jìn)入終端,輸入一下命令:
編譯和配置
sudo apt-get install build-essential automake libtool
需要的依賴
sudo apt-get install libfreetype6-dev libfreeimage-dev libzzip-dev libxrandr-dev libxaw7-
dev freeglut3-dev
下面是可選項(xiàng),一般還是裝上比較穩(wěn)妥,不然后面出現(xiàn)問題不易查找
sudo apt-get install nvidia-cg-toolkit libois-dev libboost-thread-dev
sudo apt-get install doxygen graphviz libcppunit-dev
至此我們的準(zhǔn)備工作已完成。接下來就要下載工程源代碼,然后編譯。
第二步,下載并編譯工程:
下載工程源碼文件:http://www.ogre3d.org/download/source/OGRE 1.7.4 Source for Linux / OSX
解壓文件到/home目錄下:
tar xjf ogre_src_v1-7-4.tar.bz2
進(jìn)入目錄:
cd ogre_src_v1-7-4
新建文件build,這個(gè)文件時(shí)用來存放編譯工程項(xiàng)目的,所有的編譯內(nèi)容都將放在此目錄下:
mkdir build
進(jìn)入此目錄:
cd build
由于此OGRE工程采用的CMake工具鏈進(jìn)行編譯。所以使用CMake命令開始編譯:
cmake ..
編譯器會根據(jù)CMakeLists.txt產(chǎn)生一個(gè)新的CMakeFile文件,接下來的編譯就和Make編譯一樣:
make -j2
如過此處顯示拒絕情況可以加sudo:sudo make -j2
最后一步:
sudo make install
所有的編譯工作已完成,下面就是執(zhí)行工程,看看3D效果的,這里還是要說明一下,如果你的電腦不支
持3D那就郁悶吧,因?yàn)檫@直接影響3D的渲染,結(jié)果當(dāng)然是沒辦法看到執(zhí)行的結(jié)果。如果支持3D渲染就繼
續(xù)一下操作吧!
cd build (這步已經(jīng)執(zhí)行了,只是告訴一下是在這個(gè)目錄下)
cd bin
看到可執(zhí)行文件了吧!
./Samplexxxxxxx ?這個(gè)文件名記不全了,開頭那幾個(gè)字母的文件就這一個(gè),執(zhí)行后會彈出一個(gè)界面,然
后選擇rendersystem,按住不放選中下來菜單,接下來就可以進(jìn)入了,這里你會看到所有你編譯的例子
,3D的,太棒了!如果愿意,你可以修改源文件參數(shù),重新編譯。
========
Android+Unity3D簡單的物體運(yùn)動
我們來了解一下Translate的使用
首先我們來看看場景的搭建:建一個(gè)立方體,加一個(gè)點(diǎn)光源。
我們要實(shí)現(xiàn)的就是讓場景中的立方體延X軸嗖嗖的移動
那么我們在Project新建一個(gè)js腳本Creat->Javascript
鍵入代碼
function Update ()?
{
? ? ? ? transform.Translate(Vector3(1,0,0));
}
然后將js文件拖到Hierarchy面板的立方體上實(shí)現(xiàn)綁定。
運(yùn)行一下,我們可以看到,立方體嗖的一聲不見了。它一定是肚子餓了趕去吃飯了。
好了,我們來修改代碼讓它慢一點(diǎn)。
function Update ()?
{
? ? ? ? transform.Translate(Vector3(1,0,0)*Time.deltaTime);
}
運(yùn)行一下,這會它老實(shí)了,慢慢的移動了。
這是怎么回事呢。接下來我們一步一步的分解代碼。
首先Update()沒什么好講的了,一直在用,相信大家都明白怎么回事。
接下來是
transform:場景中的每一個(gè)對象都有一個(gè)transform,用來儲存和控制物體的位置,旋轉(zhuǎn)和縮放。
Translate:是transform的函數(shù),用來移動物體。它接受一個(gè)三維向量(Vector3)參數(shù)來移動。其
實(shí)它還有第二個(gè)參數(shù),就是按照自身坐標(biāo)軸移動還是按照世界坐標(biāo)軸移動。這里暫且不表。
Vector3:表示3D的向量和點(diǎn)。3個(gè)參數(shù)分別代表了向量x,y,z。
transform.Translate(Vector3(1,0,0));這句代碼的意思就是,讓被綁定的物體,也就是場景中的
立方體,向x軸的方向移動1個(gè)單位.
Time.deltaTime:是一個(gè)時(shí)間增量,我想應(yīng)該是這一幀的時(shí)間。像flash中的一秒30幀,每幀多少秒
之類的。在這個(gè)程序中它的值是0.016左右。原本移動一個(gè)單位,現(xiàn)在乘以0.016,那肯定慢了。也就是
說,它的作用其實(shí)就是減慢移動的速度。
OK。
本文工程源碼下載:
免費(fèi)下載地址在
用戶名與密碼都是
具體下載目錄在 /pub/Android源碼集錦/2011年/11月/Android+Unity3D簡單的物體運(yùn)動/
========
Linux下的OpenGL編程
? ? OpenGL是一個(gè)工業(yè)標(biāo)準(zhǔn)的三維計(jì)算機(jī)圖形軟件接口,它由SGI公司發(fā)布并廣泛應(yīng)用于Unix、OS/2、
Windows/NT等多種平臺,當(dāng)然也包括Linux。在Windows/NT平臺上,一般的開發(fā)工具如VC、BC、Fortran?
Powerstation等都支持直接的OpenGL應(yīng)用的開發(fā);在商用Unix平臺上,Motif同樣很好的支持OpenGL(畢
竟OpenGL最初是工作站上的東西);那么在Linux上呢??
本文不著力于OpenGL編程的方法和技巧,而是把重點(diǎn)放在如何在Linux平臺上開發(fā)OpenGL程序。介
紹支持OpenGL的幾個(gè)工具包,并輔以詳細(xì)的實(shí)例來闡述。?
1. Linux下OpenGL編程環(huán)境簡介?
OpenGL不是自由軟件,它的版權(quán)、商標(biāo)(OpenGL這個(gè)名字)都?xì)wSGI公司所有。但在Linux下有
OpenGL的取代產(chǎn)品:Mesa。Mesa提供和OpenGL幾乎完全一致的接口,對利用OpenGL API編程的人來說,
幾乎感覺不到任何差異。Mesa是遵循GPL協(xié)議(部分遵循LGPL協(xié)議)的自由軟件,而且,正是由于Mesa的
自由性,它在對新硬件的支持度等方面都超過了OpenGL。Mesa可以從www.mesa3d.org取得。得到Mesa后
,依照說明即可生成編寫程序所需要的動態(tài)、靜態(tài)連接庫和頭文件。?
了解OpenGL的讀者都知道,OpenGL本身只提供三維圖形接口,不具備繪制窗口、接受響應(yīng)、處理消
息等功能。這些功能必須由第三方的開發(fā)環(huán)境提供,如上面提及的VC等等。有人會想,既然在Motif下可
以開發(fā)OpenGL程序,那么,使用Linux下的Lesstif也應(yīng)該可以。是的,的確可以,但不幸的是,Linux下
的Lesstif是一個(gè)很不成熟的產(chǎn)品,而且也不具有可移植性,所以應(yīng)用Lesstif開發(fā)的人很少。下面我們
簡單介紹幾個(gè)常用的工具包。?
在Linux下開發(fā)OpenGL程序,最常用的工具是GLUT(The OpenGL Utility Toolkit)。它可以創(chuàng)建
一個(gè)或多個(gè)OpenGL窗口,響應(yīng)、處理用戶的交互操作、簡單的彈出式菜單以及一些內(nèi)置的繪圖和字體處
理功能。GLUT和OpenGL一樣,可以移植于多種平臺。由于它良好的表現(xiàn),現(xiàn)在它已經(jīng)成為Mesa發(fā)布的標(biāo)
準(zhǔn)套件之一。?
另一個(gè)很好的開發(fā)工具包是FLTK(Fast Light Tool Kit),這是一個(gè)用C++編寫的圖形界面開發(fā)工
具。和GTK++、KDE不同,它只關(guān)注于圖形界面的設(shè)計(jì),而盡量不牽涉其他的實(shí)際應(yīng)用。這個(gè)特點(diǎn)使得它
比其他許多開發(fā)工具簡練和高效。而且,它同樣也是一個(gè)具有良好移植性的開發(fā)工具。事實(shí)上,它現(xiàn)在
正引來越來越多人的興趣,許多商業(yè)軟件(尤其是致力于開發(fā)嵌入式桌面系統(tǒng)的軟件)都選用了它作為
圖形界面的開發(fā)工具。關(guān)于它的詳細(xì)情況參見作者的另一篇文章《FLTK---一個(gè)優(yōu)秀的圖形界面開發(fā)工具
包》。在FLTK里有一個(gè)組件:Fl_Gl_Window是專門的OpenGL窗口,利用它開發(fā)OpenGL程序相當(dāng)方便。?
最后要提的是GTK和KDE,它們是目前在Linux下用的最多的開發(fā)工具。GTK本身并不直接支持OpenGL
(新的版本是否支持,尚不太清楚),但有人開發(fā)了支持OpenGL的Widget,叫做GLAREA,需要的讀者可
以到網(wǎng)上去查找或者與本文作者聯(lián)系。KDE提供了對OpenGL的支持,但它的缺陷之一是KDE只運(yùn)行于Linux
系統(tǒng),不具有可移植性。在這里,我將主要向大家介紹前面兩個(gè)工具包。?
2. 用GLUT開發(fā)OpenGL程序?
2.1 如何獲得?
GLUT可以從Mesa中獲得,讀者也可以直接到它的主頁去下載它:
http://reality.sgi.com/employees/mjk_asd/glut3/glut3.html。按照說明安裝后在
OpenGL的頭文件GL目錄下將會有GLUT的頭文件glut.h,同時(shí)安裝的還有庫文件libglut.a或libglut.so。
有了它們以后,就可以用GLUT來編程了。?
2.2 一個(gè)簡單的例子?
下面,我們先看一個(gè)簡單的例子。這個(gè)例子畫一個(gè)立體的球。?
/* light.c?
此程序利用GLUT繪制一個(gè)OpenGL窗口,并顯示一個(gè)加以光照的球。?
*/?
/* 由于頭文件glut.h中已經(jīng)包含了頭文件gl.h和glu.h,所以只需要include 此文件*/?
# include < GL / glut.h >?
# include < stdlib.h >?
/* 初始化材料屬性、光源屬性、光照模型,打開深度緩沖區(qū) */?
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);?
}?
/*調(diào)用GLUT函數(shù),繪制一個(gè)球*/?
void display ( void )?
{?
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);?
glutSolidSphere (1.0, 40, 50);?
glFlush ();?
}?
/* 定義GLUT的reshape函數(shù),w、h分別是當(dāng)前窗口的寬和高*/?
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 ( ) ;?
}?
/* 定義對鍵盤的響應(yīng)函數(shù) */?
void keyboard ( unsigned char key, int x, int y)?
{?
/*按Esc鍵退出*/?
switch (key) {?
case 27:?
exit ( 0 );?
break;?
}?
}?
int main(int argc, char** argv)?
{?
/* GLUT環(huán)境初始化*/?
glutInit (&argc, argv);?
/* 顯示模式初始化 */?
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);?
/* 定義窗口大小 */?
glutInitWindowSize (300, 300);?
/* 定義窗口位置 */?
glutInitWindowPosition (100, 100);?
/* 顯示窗口,窗口標(biāo)題為執(zhí)行函數(shù)名 */?
glutCreateWindow ( argv [ 0 ] );?
/* 調(diào)用OpenGL初始化函數(shù) */?
init ( );?
/* 注冊O(shè)penGL繪圖函數(shù) */?
glutDisplayFunc ( display );?
/* 注冊窗口大小改變時(shí)的響應(yīng)函數(shù) */?
glutReshapeFunc ( reshape );?
/* 注冊鍵盤響應(yīng)函數(shù) */?
glutKeyboardFunc ( keyboard );?
/* 進(jìn)入GLUT消息循環(huán),開始執(zhí)行程序 */?
glutMainLoop( );?
return 0;?
}?
從上面的例子中我們可以看出,GLUT采用一種函數(shù)注冊的機(jī)制來實(shí)現(xiàn)OpenGL繪圖。它的一般流程正
如我們上面的注釋所寫,先是初始化函數(shù),定義窗口,然后執(zhí)行OpenGL初始化程序,這主要是一些需要
全局設(shè)置的環(huán)境變量。接下來是注冊相應(yīng)事件的函數(shù),包括完成實(shí)際繪圖工作的繪制程序、改變OpenGL
窗口大小時(shí)的響應(yīng)函數(shù)、鍵盤事件的響應(yīng)函數(shù)和鼠標(biāo)時(shí)間的響應(yīng)函數(shù)。最后調(diào)用glutMainLoop()函數(shù)
,執(zhí)行在glutReshapeFunc和glutDisplayFunc中注冊的函數(shù),進(jìn)入消息循環(huán)。當(dāng)用戶通過鍵盤和鼠標(biāo)進(jìn)
行交互操作時(shí),它即調(diào)用相應(yīng)的函數(shù)。?
我們編譯上面的名為light.c的源文件。假定頭文件(目錄GL)放在目錄/usr/local/include下,
庫文件(動態(tài)庫libGL.so.*、libGLU.so.*和libglut.so.*)在目錄/usr/local/lib目錄下,并已經(jīng)運(yùn)行
了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的庫,它們默認(rèn)在 /usr/X11R6/lib目錄下。下
面的圖一即是運(yùn)行l(wèi)ight的結(jié)果,當(dāng)按下ESC鍵時(shí),程序會退出。調(diào)整窗口大小時(shí),圖形自動重繪。注意
在上面reshape函數(shù)中,比較w和h的值給出的取景變換,這是一個(gè)常用的技巧。?
圖一?
2.3 GLUT簡介?
GLUT常用的函數(shù)主要包括以下幾類:?
· 初始化函數(shù)。主要就是上面例子中的幾個(gè)函數(shù)。?
· 消息循環(huán)函數(shù)。即glutMainLoop函數(shù)。?
· 窗口管理函數(shù)。包括窗口的創(chuàng)建、修改、刪除等。GLUT支持多個(gè)OpenGL窗口。?
· Overlay管理函數(shù)。當(dāng)用戶顯卡支持Overlay方式時(shí),可以用這些函數(shù)來創(chuàng)建、管理、刪除GLUT
窗口的Overlay。?
· 菜單管理函數(shù)。定制菜單以及定義菜單相應(yīng)事件。?
· 事件注冊函數(shù)。除了上面例子中提及的外,還有鼠標(biāo)、空間球(提供三維操作的裝備)、特殊
鍵(Ctrl、Shift、F系列鍵、方向鍵)等設(shè)備的事件注冊函數(shù)。?
· 字體繪制函數(shù)。用多種字體、字號供選擇。?
· 簡單幾何體的繪制程序。包括球、立方體、錐體、圓環(huán)體、十二面體、八面體、四面體、二十
面體和茶壺。每種幾何體都有實(shí)體和虛線兩個(gè)選項(xiàng)。?
· 取狀態(tài)函數(shù)。類似OpenGL的glGet系列函數(shù),取得GLUT的各種狀態(tài)值。?
· 顏色索引表函數(shù)。?
這些函數(shù)極大的方便了用戶的OpenGL編程。下面我們簡略介紹一下幾個(gè)常用的函數(shù)。?
· glutPostRedisplay()。發(fā)送消息給函數(shù)glutMainLoop,請求重繪本窗口。利用此函數(shù)可以實(shí)
現(xiàn)動畫。例如在上面的例子中,我們添加一個(gè)全局變量:float move=0.0。并定義函數(shù)MoveSphere如下
:?
void MoveSphere ( void )?
{?
for(int i=0;i<100;i++){?
if ( move<1.0) move+=0.1;?
else move=0.0;?
glutPostRedisplay ( );?
}?
}?
同時(shí)修改函數(shù)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 ();?
}?
這樣,當(dāng)我們執(zhí)行函數(shù)MoveSphere時(shí),就會看到上面的球從中間向右移動一段距離,然后又回到中
心,繼續(xù)移動。?
· glutIdleFunc()函數(shù)。這個(gè)函數(shù)注冊一個(gè)空閑程序一直在后臺運(yùn)行。我們將上面的
MoveSphere函數(shù)加以修改,去掉循環(huán),然后在light.c程序的glutMainLoop()函數(shù)調(diào)用前添加一行代碼
:glutIdleFunc (MoveSphere);這樣我們不需要直接調(diào)用函數(shù)MoveSphere,程序一運(yùn)行,它就被反復(fù)調(diào)
用直到我們退出程序?yàn)橹?#xff0c;這和我們前一版本中它只能循環(huán)特定的步數(shù)不一樣。?
· glutTimerFunc()函數(shù)。和前面的glutIdleFunc()函數(shù)類似,但不同的是它注冊的函數(shù)每隔
特定的事件發(fā)生。時(shí)間的單位是毫秒。?
· glutBitmapCharacter()函數(shù)。用位圖方式按指定的字體繪制一個(gè)字符串。?
· glutSolidSphere()函數(shù)。這是繪制幾何體類函數(shù)中的一個(gè)。此函數(shù)繪制一個(gè)球體。?
2.4 一個(gè)更有代表性的例子?
下面我們來看一個(gè)稍稍復(fù)雜的例子。我們繪制一個(gè)平面,用戶的左鍵點(diǎn)擊被自動連接成一個(gè)多邊形
。當(dāng)用戶點(diǎn)擊右鍵,會彈出菜單供用戶選擇。用戶可以選擇清除、鑲嵌和退出。選擇清除將回到初始狀
態(tài);選擇鑲嵌程序自動對多邊形進(jìn)行三角剖分;選擇退出則終止程序。(見圖二、圖三和圖四)?
圖二 圖三 圖四?
/* tessdemo.c 多邊形鑲嵌的例子,使用函數(shù)gluTessCallback和函數(shù)gluTessVertex。*/?
#include?
#include?
#include?
#include?
/* 定義允許的最大多邊形數(shù)、多邊形允許的最大頂點(diǎn)數(shù)和可鑲嵌的最大三角形數(shù)*/?
#define MAX_POINTS 256?
#define MAX_CONTOURS 32?
#define MAX_TRIANGLES 256?
/* 用于菜單選項(xiàng)的枚舉類型 */?
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; /* 記錄多邊形數(shù)目 */?
static GLuint triangle_cnt; /* 記錄三角形數(shù)目 */?
static GLuint list_start; /* 用于顯示列表 */?
/* 多邊形結(jié)構(gòu) */?
static struct {?
GLfloat p[MAX_POINTS][2];?
GLuint point_cnt;?
} contours [ MAX_CONTOURS ] ;?
/* 三角形結(jié)構(gòu) */?
static struct {?
GLsizei no;?
GLfloat p [3] [2];?
GLclampf color [3] [3];?
} triangles [ MAX_TRIANGLES ];?
/* 窗口大小改變時(shí),設(shè)定width和height值,用于重新繪制網(wǎng)格 */?
void set_screen_wh ( GLsizei w, GLsizei h )?
{ width = w; height = h; }?
void tesse ( void )?
{ /* 鑲嵌函數(shù),調(diào)用gluTess* 函數(shù)實(shí)現(xiàn)*/ }?
/* 對點(diǎn)擊鼠標(biāo)左鍵事件的響應(yīng)函數(shù):更新當(dāng)前多邊形頂點(diǎn)數(shù)組,并重新繪制 */?
void left_down ( int x1, int y1 )?
{?
GLfloat P[2];?
GLuint point_cnt;?
/* 將GLUT窗口坐標(biāo)變換為GL坐標(biāo):前者(0,0)在左上角而后者在左下角*/?
P[0] = x1; P[1] = height - y1;?
/* 更新頂點(diǎn)數(shù)據(jù) */?
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 ];?
/* 繪制新添加的邊,若為第一個(gè)點(diǎn),則繪制一個(gè)點(diǎn) */?
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++;?
}?
/* 點(diǎn)擊鼠標(biāo)中鍵的響應(yīng)事件,有些系統(tǒng)可以用同時(shí)點(diǎn)擊左右鍵模擬:結(jié)束一個(gè)多邊形 */?
void middle_down( int x1, int y1 )?
{?
GLuint point_cnt;?
(void) x1;?
(void) y1;?
point_cnt = contours[contour_cnt].point_cnt;?
/* 連接起始點(diǎn)和最后一個(gè)點(diǎn),構(gòu)成一個(gè)完整的多邊形 */?
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;?
}?
}?
/* 處理鼠標(biāo)響應(yīng)的函數(shù),根據(jù)按鍵的類型調(diào)用不同的函數(shù):左鍵和中鍵。 */?
void mouse_clicked( int button, int state, int x, int y )?
{?
/* 將OpenGL的像素坐標(biāo)換為背景的網(wǎng)格坐標(biāo),背景網(wǎng)格為邊長為10的小正方形 */?
x -= x%10;?
y -= y%10;?
switch ( button ) {?
case GLUT_LEFT_BUTTON: /* GLUT發(fā)現(xiàn)左鍵被點(diǎn)擊 */?
if ( state == GLUT_DOWN ) {?
left_down( x, y );?
}?
break;?
case GLUT_MIDDLE_BUTTON: /* 中鍵被點(diǎn)擊 */?
if ( state == GLUT_DOWN ) {?
middle_down( x, y );?
}?
break;?
}?
}?
/* OpenGL繪制函數(shù),有兩種模式 */?
void display( void )?
{?
GLuint i,j;?
GLuint point_cnt;?
glClear( GL_COLOR_BUFFER_BIT );?
switch ( mode )?
{?
case DEFINE: /* 多邊形定義階段 */?
/* 繪制網(wǎng)格,單個(gè)網(wǎng)格大小為10像素,網(wǎng)格數(shù)目取決于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: /* 繪制鑲嵌后的多邊形,顯示列表由函數(shù)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 );?
}?
/* 菜單選項(xiàng)clear的響應(yīng)函數(shù),將所有變量清零,繪制模式設(shè)為DEFINE */?
void clear( void )?
{?
contour_cnt = 0;?
contours[0].point_cnt = 0;?
triangle_cnt = 0;?
mode = DEFINE;?
glDeleteLists( list_start, 2 );?
list_start = 0;?
}?
/* 菜單選項(xiàng)quit的響應(yīng)函數(shù),退出程序 */?
void quit( void )?
{?
exit( 0 );?
}?
/* 定義菜單的響應(yīng)函數(shù) */?
void menu_selected( int entry )?
{?
switch ( entry ) {?
case CLEAR:?
clear ( );?
break;?
case TESSELATE:?
tesse ( );?
break;?
case QUIT:?
quit ( );?
break;?
}?
/* 選擇菜單后重繪OpenGL窗口 */?
glutPostRedisplay();?
}?
/* 定義快捷鍵響應(yīng)函數(shù) */?
void key_pressed( unsigned char key, int x, int y )?
{?
/* 在此例子中,不需要用表明鼠標(biāo)位置的變量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();?
}?
/* 執(zhí)行一些程序的初始化過程 */?
void myinit( void )?
{?
/* 設(shè)置窗口背景顏色*/?
glClearColor( 0.4, 0.4, 0.4, 0.0 );?
glShadeModel( GL_FLAT );?
glPolygonMode( GL_FRONT, GL_FILL );?
/* 創(chuàng)建一個(gè)菜單,并定義菜單項(xiàng)及該菜單對應(yīng)的響應(yīng)函數(shù) */?
menu = glutCreateMenu( menu_selected );?
glutAddMenuEntry( "clear", CLEAR );?
glutAddMenuEntry( "tesselate", TESSELATE );?
glutAddMenuEntry( "quit", QUIT );?
/* 定義菜單動作方式:點(diǎn)擊右鍵彈出 */?
glutAttachMenu( GLUT_RIGHT_BUTTON );?
/* 注冊鼠標(biāo)事件響應(yīng)函數(shù) */?
glutMouseFunc( mouse_clicked );?
/* 注冊鍵盤事件響應(yīng)函數(shù) */?
glutKeyboardFunc( key_pressed );?
contour_cnt = 0;?
mode = DEFINE;?
}?
/* 定義窗口大小改變時(shí)的響應(yīng) */?
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 )?
{?
/* 創(chuàng)建窗口 */?
glutInit ( & argc, argv );?
glutInitDisplayMode ( GLUT_SINGLE | GLUT_RGB );?
glutInitWindowSize ( 400, 400 );?
glutCreateWindow( argv[0] );?
myinit();?
glutDisplayFunc( display );?
glutReshapeFunc( reshape );?
glutMainLoop();?
return 0;?
}?
3. 用FLTK開發(fā)OpenGL程序?
從上面的例子我們不難看出,雖然GLUT為實(shí)現(xiàn)OpenGL編程提供了可能,但是作為應(yīng)用程序,它是遠(yuǎn)
遠(yuǎn)不夠的。它只提供了原始、簡陋的控制和操作方式,沒有一般應(yīng)用程序所需要的按鈕、菜單條、輸入
框等控件。事實(shí)上,GLUT并不是用來單獨(dú)開發(fā)應(yīng)用程序的,它是用作介于OpenGL函數(shù)接口和一般的圖形
界面開發(fā)接口之間的過渡層。在這一點(diǎn)上,它無疑是成功的。Mesa選擇它作為標(biāo)準(zhǔn)套件分發(fā),大多數(shù)圖
形界面開發(fā)工具也保持與它的兼容性。從而使得用GLUT開發(fā)的OpenGL程序有良好的可移植性。?
和GLUT不同,FLTK本身是一個(gè)圖形界面開發(fā)工具,使用它完全可以開發(fā)實(shí)用的、商用的應(yīng)用程序。
FLTK用C++編寫,使用面向?qū)ο蟮拈_發(fā)技術(shù),它提供多種組件供用戶選用,每個(gè)組件有自己的屬性和事件
。在這里,我們主要講述它的OpenGL窗口組件:Fl_Gl_Window,并充分使用C++的特性。?
這一節(jié)里,我們繪制一個(gè)可以自由旋轉(zhuǎn)、平移、放縮的小立方體。程序運(yùn)行后如圖五所示。整個(gè)窗
口是一個(gè)由Fl_Window組件定義的一般窗口,中間是一個(gè)OpenGL窗口。我們使用了一些控制工具來調(diào)整小
立方體的屬性。上面的Zoom標(biāo)尺調(diào)整它的大小,左邊和下邊各有一個(gè)平移標(biāo)尺和一個(gè)旋轉(zhuǎn)標(biāo)尺,調(diào)整小
立方體的位置和角度。這些標(biāo)尺都是FLTK的標(biāo)準(zhǔn)組件,它們的作用是根據(jù)用戶的動作返回特定的整數(shù)或
符點(diǎn)數(shù)。?
Fl_Gl_Window最重要的是兩個(gè)虛函數(shù):draw()、handle()和成員函數(shù)redraw()。函數(shù)draw(
)中定義繪制內(nèi)容,創(chuàng)建窗口和窗口大小改變是這個(gè)函數(shù)被自動調(diào)用。函數(shù)handle()中定義對各種鍵
盤、鼠標(biāo)事件的響應(yīng)。當(dāng)有鍵盤、鼠標(biāo)事件響應(yīng)時(shí),這個(gè)函數(shù)被自動調(diào)用,如何有響應(yīng)事件的函數(shù)被定
義,則會執(zhí)行此函數(shù)。函數(shù)redraw()重繪窗口。在這個(gè)叫做CubeView的例子中,我們派生
Fl_Gl_Window,得到繪制我們這個(gè)小立方體的OpenGL窗口。?
// 文件CubeView.cxx,派生Fl_Gl_Window,得到繪制小立方體的OpenGL窗口?
#include?
#include?
#include?
#include?
#include?
// 派生類CubeView的定義?
class CubeView : public Fl_Gl_Window {?
public:?
double size; // 定義小立方體的大小,供glScalef()函數(shù)使用?
// 構(gòu)造函數(shù),派生自Fl_Gl_Window,定義窗口大小和標(biāo)題?
CubeView(int x,int y,int w,int h,const char *l=0);?
// 設(shè)置和取得垂直方向的旋轉(zhuǎn)角度,供組件標(biāo)尺調(diào)用?
void v_angle(float angle){vAng=angle;};?
float v_angle(){return vAng;};?
// 設(shè)置和取得水平方向的旋轉(zhuǎn)角度,供組件標(biāo)尺調(diào)用?
void h_angle(float angle){hAng=angle;};?
float h_angle(){return hAng;};?
// 設(shè)置水平和垂直方向的偏移量?
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];?
};?
// 構(gòu)造函數(shù)的定義?
CubeView::CubeView(int x,int y,int w,int h,const char *l)?
: Fl_Gl_Window(x,y,w,h,l)?
{?
// 設(shè)置變換初值?
vAng = 0.0;?
hAng=0.0;?
size=10.0;?
// 設(shè)置小立方體頂點(diǎn)參數(shù)?
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() {?
// 繪制一個(gè)半透明的立方體?
#define ALPHA 0.5?
glShadeModel(GL_FLAT);?
// 用不同的顏色繪制六個(gè)面?
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()當(dāng)窗口大小改變時(shí)改變,導(dǎo)致這一部分內(nèi)容被執(zhí)行,重新設(shè)置窗口?
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 ( );?
// 變換。參數(shù)繪被外部函數(shù)修改?
glTranslatef ( xshift, yshift, 0);?
glRotatef ( hAng, 0, 1, 0 ); glRotatef ( vAng, 1, 0, 0 );?
glScalef ( float ( size ), float ( size ) , float ( size ) );?
// 繪制立方體?
drawCube ( );?
glPopMatrix ( );?
};?
上面的類CubeView定義了一個(gè)繪制立方體的OpenGL窗口,外部函數(shù)可以調(diào)用它的成員函數(shù)v_angle、
h_angle、panx、pany等來修改這個(gè)小立方體的屬性,修改以后,可以調(diào)用函數(shù)redraw()來刷新窗口。
在下面的CubeViewUI.cxx中,我們定義類CubeViewUI,它繪制主窗口,并在其中定義了類CubeView的一
個(gè)實(shí)例:cube。它同時(shí)還定義了用來控制立方體屬性的5個(gè)標(biāo)尺,當(dāng)用戶操作標(biāo)尺時(shí),這些標(biāo)尺調(diào)用
v_angle等函數(shù)來設(shè)置繪制立方體的一些參數(shù)。這一部分和我們的主題關(guān)系不大,不給出具體的代碼。最
后,我們定義main函數(shù),它的內(nèi)容相當(dāng)?shù)暮唵巍?
#include "CubeViewUI.h"?
int main(int argc, char **argv) {?
// 定義類CubeViewUI的一個(gè)實(shí)例?
CubeViewUI *cvui=new CubeViewUI;?
// 設(shè)置FLTK窗口顯示模式?
Fl::visual(FL_DOUBLE|FL_INDEX);?
cvui->show();?
// 進(jìn)入消息循環(huán)?
return Fl::run();?
}?
我們編譯、連接并執(zhí)行程序,就可以得到如圖五所示的結(jié)果。從上面的例子我們可以看出使用FLTK編寫
OpenGL程序的一些優(yōu)點(diǎn),和GLUT它結(jié)構(gòu)清晰,使用方便,而且它和GLUT是兼容的。除了glutInit()、
glutMainLoop()等少數(shù)函數(shù)外,大部分GLUT函數(shù)可以在FLTK中使用。FLTK本身也提供了許多OpenGL函
數(shù),如繪制字符串的gl_draw()等。?
4. 結(jié)束語?
熟悉掌握了Linux下OpenGL的開發(fā)環(huán)境距離開發(fā)OpenGL程序還有很大的距離,畢竟問題的難點(diǎn)是如
何很好的使用OpenGL的API。本文為即將在Linux下開發(fā)OpenGL的讀者作一些鋪墊和準(zhǔn)備工作,希望并相
信對大家有所幫助。
========
linux openGL "Hello world"
1. 安裝OpenGL相關(guān)工具?
sudo apt-get install mesa-common-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev?
note:
? ? ? ?libgl1-mesa-de 對應(yīng) GL庫;?
? ? ? ?libglu1-mesa-dev對應(yīng)GLU庫 TJe opengl utility ?library;?
? ? ? freeglut3-dev 對應(yīng)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 <GL/glut.h>
#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. 運(yùn)行:
? ? ./example
========
linux下基于eclipse的opengl開發(fā)環(huán)境搭建
博客分類: opengl
eclipseopenglubuntu?
轉(zhuǎn)自:http://www.cnblogs.com/lycheng/archive/2011/09/13/2174831.html?
1. 安裝OpenGL相關(guān)工具?
sudo apt-get install mesa-common-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev?
? ? ? ?其中,?
? ? ? ?libgl1-mesa-de 對應(yīng) GL庫;?
? ? ? ?libglu1-mesa-dev對應(yīng)GLU庫 TJe opengl utility ?library;?
? ? ? freeglut3-dev 對應(yīng)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. 設(shè)置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 <GL/glut.h> ?
#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 之后, 會顯示旋轉(zhuǎn)的方型, 如果不需要IDE, 則可用命令行編譯。?
4. 命令行編譯?
gcc example.cpp -o example -lglut -lGL -lGLU?
-o 表示輸出的文件名?
-l 表示鏈接的庫
========
總結(jié)
以上是生活随笔為你收集整理的Linux 3D 编程学习总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop学习总结
- 下一篇: Linux安全学习总结