Linux 3D 编程学习总结

Linux下应用OGRE开发3D


linux下应用OGRE开发3D的资料网上非常少。今天抽出时间整理一下。



大部分内容參考OGRE主页http://www.ogre3d.org/。

首先依据主页提示,我们能够利用已有资源构建一个project。详细过程例如以下:

第一步,准备工作,确定你是在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

至此我们的准备工作已完毕。接下来就要下载project源码,然后编译。

第二步,下载并编译project:

下载project源代码文件: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。这个文件时用来存放编译project项目的。全部的编译内容都将放在此文件夹下:


mkdir build


进入此文件夹:


cd build


因为此OGREproject採用的CMake工具链进行编译。所以使用CMake命令開始编译:


cmake ..


编译器会依据CMakeLists.txt产生一个新的CMakeFile文件。接下来的编译就和Make编译一样:


make -j2


如过此处显示拒绝情况能够加sudo:sudo make -j2


最后一步:


sudo make install


全部的编译工作已完毕。以下就是运行project,看看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。
  本文project源代码下载:
  免费下载地址在
  username与password都是
  详细下载文件夹在 /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编程提供了可能,可是作为应用程序,它是远


远不够的。它仅仅提供了原始、简陋的控制和操作方式。没有一般应用程序所须要的button、菜单栏、输入


框等控件。其实,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 <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. 执行:
    ./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 <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 之后, 会显示旋转的方型, 假设不须要IDE, 则可用命令行编译。

 




4. 命令行编译 


  gcc example.cpp -o example -lglut -lGL -lGLU 


  -o 表示输出的文件名称 


  -l 表示链接的库
========

posted @ 2017-07-30 11:20  jzdwajue  阅读(1349)  评论(0编辑  收藏  举报