OpenLuGl V1.0 使用说明
目 录
1 概述 2 OpenGl简介 3 OpenLuGl的图形输出及坐标系统 4 OpenLuGl的源程序基本格式 5 例子 6 显示列表与实体模块 |
7 函数概述 8 gl函数 9 glu函数 10 gle函数 11 lg函数 |
OpenLuGl32.dll是一个基于OpenGL的Lu扩展动态库,需要MLu32.dll的支持。OpenLuGl来源于OpenFcGl,OpenFcGl是基于Forcal的扩展库。
OpenLuGl试图输出OpenGl的大部分函数并加以扩展(目前仅进行了部分工作),使之能方便地绘制三维图形。
OpenLuGl中的函数目前有四种:以gl开头的是OpenGl32中的标准OpenGl函数;以glu开头的是glu32中的辅助OpenGl函数;以gle开头的是为方便与OpenGl和绘图窗口交互而扩展的函数;以lg开头的是OpenLuGl扩展的实用绘图函数,目前主要是一些绘制数学函数图形的函数。OpenLuGl努力保证这些函数在运行时的安全性,即无论以何种顺序使用这些函数,程序都不会崩溃(这也是所有Lu函数应具有的特点),但用户应该知道:只有正确地使用这些函数,才能充分发挥它们的性能。充分了解每一个要使用的函数的性能是非常必要的。
OpenLuGl中绝大多数的OpenGl函数(以gl或glu开头)的用法与在OpenGl中完全相同,但也有少数函数不一样,在使用中要主要这些差别。
OpenLuGl中的函数参数通常为整数或实数,在使用中需要加以区分。
OpenGL是近几年发展起来的一个性能卓越的三维图形标准,它是在SGI等多家世界闻名的计算机公司的倡导下,以SGI的GL三维图形库为基础制定的一个通用共享的开放式三维图形标准。目前,包括Microsoft、SGI、IBM、DEC、SUN、HP等大公司都采用了OpenGL做为三维图形标准,许多软件厂商也纷纷以OpenGL为基础开发出自己的产品,其中比较著名的产品包括动画制作软件Soft Image和3D Studio MAX、仿真软件Open Inventor、VR软件World Tool Kit、CAM软件ProEngineer、GIS软ARC/INFO等等。值得一提的是,随着Microsoft公司在Windows中提供了OpenGL标准及OpenGL三维图形加速卡的推出,OpenGL已在微机中有广泛地应用,同时也为广大用户提供了在微机上使用以前只能在高性能图形工作站上运行的各种软件的机会。
3.1 OpenGL的屏幕坐标与函数自变量的变化范围
坐标的中心在屏幕中心,X轴由左向右,Y轴由下向上,Z轴由里向外(屏幕以里为负值,屏幕以外为正值),三个坐标轴组成右手坐标系。注意:图象必须被绘制在屏幕里面才能够看到。
通常,屏幕坐标与函数自变量的变化范围并不一致,例如函数:z(x,y)=x+y,x取[-3.0,3.0],y取[-3.0,3.0],则z的取值范围为[-6.0,6.0]。可以将该函数的图象绘制在屏幕的任何位置,例如:X[0.0,10.0],Y[0.0,10.0],Z[-10.0,-20.0]。
3.2 用键盘移动屏幕坐标
→:坐标原点沿X轴正向向右移动;
←:坐标原点沿X轴负向向左移动;
↑:坐标原点沿Y轴正向向上移动;
↓:坐标原点沿Y轴负向向下移动;
PageUp: 坐标原点沿Z轴负向向里移动;
PageDown:坐标原点沿Z轴正向向外移动;
Home:坐标复位。
3.3 用键盘使图象旋转
在OpenLuGl中设置了三个可由键盘操纵的数,这三个数可由函数gleAngle[i]获得,使用这三个数并与函数glRotated[...]配合可使图象产生旋转。
Shift + →: 使gleAngle[1]值增加;
Shift + ←: 使gleAngle[1]值减少;
Shift + ↑: 使gleAngle[2]值增加;
Shift + ↓: 使gleAngle[2]值减少;
Shift + PageUp: 使gleAngle[3]值减少;
Shift + PageDown: 使gleAngle[3]值增加;
Shift + Home: 使gleAngle[i]值为0。
在每一个绘图单元前加上以下代码,可用键盘操纵图象沿X、Y、Z轴旋转:
glRotated[gleAngle(1),1.0,0.0,0.0]; //使图象沿X轴旋转
glRotated[gleAngle(2),0.0,1.0,0.0]; //使图象沿Y轴旋转
glRotated[gleAngle(3),0.0,0.0,1.0]; //使图象沿Z轴旋转
3.4 看不到绘制的图象怎么办
连续按PageUp键,使图象往屏幕里移动,即可看到图象。
4 OpenLuGl的源程序基本格式 [返回页首]
通常,使用MLu的源程序格式书写OpenLuGl的源程序。建议使用以下基本格式:
gleDrawScene(HFor("Draw")),stop(); //(1)启动场景绘制,就退出
//... ... //(2)一些函数定义
initScene()= //(3)定义初始化函数
{
gleClear() //(4)清理已经不再使用的空间
//在这里放置初始化代码
};
Draw()= //(5)场景绘制函数
{
if[gleIsInitScene(),initScene()], //(6)需要初始化场景时,就执行初始化函数
glClear[], //(7)清除屏幕以及深度缓存
glLoadIdentity[], //(8)重置视图
glTranslated[0.0,0.0,-20.0], //(9)移动坐标,向屏幕里移动20个单元
glColor3d[1.0,0.0,0.0], //(10)设置颜色
glePrint["Hello OpenLuGl !"] //(11)绘制英文字符串
};
说明:
(1)先通过函数gleDrawScene(HFor("Draw"))将场景绘制函数"Draw"的句柄告诉OpenLuGl,然后用stop()结束该模块的执行。通过场景绘制函数,OpenLuGl会执行该模块的其余部分。
(2)可以在这里定义一些要用到的函数。
(3)自定义初始化函数initScene(),仅在需要时定义该函数。
(4)清理已经不再使用的空间,这些空间是以前绘图时申请的,重新绘图时,这些空间已经成为垃圾。如果有此语句,必须为初始化函数代码的第一个语句。
(5)自定义场景绘制函数Draw(),该函数的代码会被OpenLuGl循环执行。
(6)这句仅在设置了初始化函数时添加,如果有此语句,必须为场景绘制代码的第一个语句。其中gleIsInitScene()用于判断是否需要对场景进行初始化。
(7)从这一句开始,场景绘制才真正开始。此语句不可缺少,必须放在真正场景绘制代码的最前面。注意glClear()与前面的gleClear()是不一样的。
(8)、(9)、(10)、(11)语句组成了一个绘图单元。第(8)语句通常为每一个绘图单元的第一句,其功能是将绘图的起点重新设置到预定的初始位置。其余各句请参考源代码中的说明,不赘述。
5.1 一元函数图象
gleDrawScene[HFor("Scene")],stop(); //设置场景绘制函数后退出
f(x)=x*sin[x]; //一元函数定义
Scene()=
{
glClear[], //清除屏幕以及深度缓存
glLoadIdentity[], //重置视图
glTranslated[0.0,0.0,-10.0], //移动坐标,向屏幕里移动10个单元
glColor3d[1.0,0.0,0.0], //设置颜色
lgPlot[@f,-10.0,10.0,LG_AXES,-3.0,3.0,-2.0,2.0] //绘制一元函数图象
};
5.2 二元函数图象
gleDrawScene[HFor("Scene")],stop(); //设置场景绘制函数后退出
f(x,y)=(x^2-2*x)*exp(-(x^2)-y^2-x*y);
Scene(:static,Rot)=
{
glClear[],
glLoadIdentity[],
glTranslated[0.0,0.0,-20.0],
glColor3d[0.0,1.0,0.0], //设置颜色
glRotated[1.0*Rot++,1.0,1.0,1.0], //使图象连续旋转
lgPlot3d[@f,-3.0,3.0,-3.0,3.0]
};
5.3 可用键盘移动、旋转的二元函数图象
gleDrawScene[HFor("Scene")],stop(); //设置场景绘制函数后退出
f(x,y)=sin[sqrt(x*x+y*y)];
initScene()= //定义初始化函数
{
gleAngle(90.0,180.0,90.0) //设置重置视图初始位置
};
Scene()= //场景绘制函数
{
if[gleIsInitScene(),initScene()], //需要初始化场景时,就执行初始化函数
glClear[],
glColor3d[1.0,0.0,0.0], //设置颜色
gleAxesAngle[], //显示坐标和旋转角度
glLoadIdentity[],
glTranslated[0.0,0.0,-20.0],
glColor3d[0.0,1.0,0.0], //设置颜色
glRotated[gleAngle(1),1.0,0.0,0.0], //使图象沿X轴旋转
glRotated[gleAngle(2),0.0,1.0,0.0], //使图象沿Y轴旋转
glRotated[gleAngle(3),0.0,0.0,1.0], //使图象沿Z轴旋转
lgPlot3d[@f,-5.0,5.0,-5.0,5.0,LG_NOMESH]
};
5.4 制作彩色旋转的金字塔和正方体
gleDrawScene[HFor("Scene")],stop(); // 设置场景绘制函数后退出
Scene(:static,yRot,xyzRot)=
{
glClear[], // 清屏和清除深度缓冲区
glLoadIdentity(), // 重置当前Modelview矩阵
glTranslated(-1.5,0.0,-6.0), // 向左移动1.5个单元、向屏幕里移动6.0个单元
glRotated(1.0*yRot,0.0,1.0,0.0), // 在Y轴旋转金字塔
glBegin(GL_TRIANGLES), // 开始绘制一个三角形
glColor3d(1.0,0.0,0.0), // 红
glVertex3d( 0.0, 1.0, 0.0), // 顶(前面)
glColor3d(0.0,1.0,0.0), // 绿
glVertex3d(-1.0,-1.0, 1.0), // 左(前面)
glColor3d(0.0,0.0,1.0), // 蓝
glVertex3d( 1.0,-1.0, 1.0), // 右(前面)
glColor3d(1.0,0.0,0.0), // 红
glVertex3d( 0.0, 1.0, 0.0), // 顶(右面)
glColor3d(0.0,0.0,1.0), // 蓝
glVertex3d( 1.0,-1.0, 1.0), // 左(右面)
glColor3d(0.0,1.0,0.0), // 绿
glVertex3d( 1.0,-1.0, -1.0), // 右(右面)
glColor3d(1.0,0.0,0.0), // 红
glVertex3d( 0.0, 1.0, 0.0), // 顶(后面)
glColor3d(0.0,1.0,0.0), // 绿
glVertex3d( 1.0,-1.0, -1.0), // 左(后面)
glColor3d(0.0,0.0,1.0), // 蓝
glVertex3d(-1.0,-1.0, -1.0), // 右(后面)
glColor3d(1.0,0.0,0.0), // 红
glVertex3d( 0.0, 1.0, 0.0), // 顶(左面)
glColor3d(0.0,0.0,1.0), // 蓝
glVertex3d(-1.0,-1.0,-1.0), // 左(左面)
glColor3d(0.0,1.0,0.0), // 绿
glVertex3d(-1.0,-1.0, 1.0), // 右(左面)
glEnd(), // 完成金字塔的绘制
glLoadIdentity(), // 重置当前Modelview矩阵
glTranslated(1.5,0.0,-7.0), // 向右移动个1.5单元向屏幕里移动7个单元
glRotated(1.0*xyzRot,1.0,1.0,1.0), // 在X、Y、Z轴转动正方体
glBegin(GL_QUADS), // 绘制一个正方体
glColor3d(0.0,1.0,0.0), // 设置蓝色
glVertex3d( 1.0, 1.0,-1.0), // 右上(顶面)
glVertex3d(-1.0, 1.0,-1.0), // 左上(顶面)
glVertex3d(-1.0, 1.0, 1.0), // 左下(顶面)
glVertex3d( 1.0, 1.0, 1.0), // 右下(顶面)
glColor3d(1.0,0.5,0.0), // 设置橘红色
glVertex3d( 1.0,-1.0, 1.0), // 右上(底面)
glVertex3d(-1.0,-1.0, 1.0), // 左上(底面)
glVertex3d(-1.0,-1.0,-1.0), // 左下(底面)
glVertex3d( 1.0,-1.0,-1.0), // 右下(底面)
glColor3d(1.0,0.0,0.0), // 设置红色
glVertex3d( 1.0, 1.0, 1.0), // 右上(前面)
glVertex3d(-1.0, 1.0, 1.0), // 左上(前面)
glVertex3d(-1.0,-1.0, 1.0), // 左下(前面)
glVertex3d( 1.0,-1.0, 1.0), // 右下(前面)
glColor3d(1.0,1.0,0.0), // 设置黄色
glVertex3d( 1.0,-1.0,-1.0), // 右上(后面)
glVertex3d(-1.0,-1.0,-1.0), // 左上(后面)
glVertex3d(-1.0, 1.0,-1.0), // 左下(后面)
glVertex3d( 1.0, 1.0,-1.0), // 右下(后面)
glColor3d(0.0,0.0,1.0), // 设置蓝色
glVertex3d(-1.0, 1.0, 1.0), // 右上(左面)
glVertex3d(-1.0, 1.0,-1.0), // 左上(左面)
glVertex3d(-1.0,-1.0,-1.0), // 左下(左面)
glVertex3d(-1.0,-1.0, 1.0), // 右下(左面)
glColor3d(1.0,0.0,1.0), // 设置紫蓝色
glVertex3d( 1.0, 1.0,-1.0), // 右上(右面)
glVertex3d( 1.0, 1.0, 1.0), // 左上(右面)
glVertex3d( 1.0,-1.0, 1.0), // 左下(右面)
glVertex3d( 1.0,-1.0,-1.0), // 右下(右面)
glEnd(), // 完成正方体绘制
yRot=yRot+0.2, // 增加三角形的旋转变量
xyzRot=xyzRot-0.15 // 减小矩形的旋转变量
};
5.5 晶体
/
/// 请修改用户定义部分。若没有特殊的需要,其他部分无需修改
/
//#LOAD{"dll\OpenLugl32"} //本程序由OpenLuGl32.dll提供支持
gleDrawScene(HFor("Scene")),stop(); //启动场景绘制,就退出
//让图形随鼠标移动。factor为比例因子,factor越大则移动幅度越大。factor=0进行初始化。
fcglFollowMouse(factor:x,y,xx,yy,xxx,yyy,static,fcglFollowMouse,xMouse,yMouse)=
{
if[!factor,fcglFollowMouse=0,return(0)],
if[gleGetMouseMsg(WM_LBUTTONDOWN,&x,&y),fcglFollowMouse=1,xMouse=x,yMouse=y],
gleGetWindowSize[&xxx,&yyy],
if[fcglFollowMouse,gleGetMouseMsg(WM_MOUSEMOVE,&xx,&yy),gleAngle[1,gleAngle(1)+(yy-yMouse)/yyy*factor],gleAngle[2,gleAngle(2)+(xx-xMouse)/xxx*factor]],
if[gleGetMouseMsg(WM_LBUTTONUP,&xx,&yy),fcglFollowMouse=0],
glRotated[gleAngle(1),1.0,0.0,0.0], //使图象沿X轴旋转
glRotated[gleAngle(2),0.0,1.0,0.0], //使图象沿Y轴旋转
glRotated[gleAngle(3),0.0,0.0,1.0] //使图象沿Z轴旋转
};
//x,y,z为要获得的屏幕坐标,需要引用参数&调用。
//i,j,k为点阵坐标。
//a,b,c,Alpha,Beta,Gamma为点阵的6个参数。
//规定:点阵原点即屏幕原点,点阵a轴即屏幕x轴,点阵b轴在屏幕x,y轴决定的平面内。
fcglTransCrystalAxis(x,y,z,i,j,k,a,b,c,Alpha,Beta,Gamma:_Alpha,_Beta,_Gamma,m)=
{
_Alpha=Alpha/180*3.1415926, _Beta=Beta/180*3.1415926, _Gamma=Gamma/180*3.1415926,
x=i*a+j*b*cos(_Gamma)+k*c*cos(_Beta),
m=[cos(_Alpha)^2+cos(_Beta)^2]/[1+cos(_Gamma)],
y=j*b*sin(_Gamma)+k*c*sqrt[m-cos(_Beta)^2],
z=k*c*sqrt[1-m]
};
//绘制连接两个点阵点的线段。
fcglCrystalLine(i1,j1,k1,i2,j2,k2,a,b,c,Alpha,Beta,Gamma:x,y,z)=
{
glBegin(GL_LINES),
fcglTransCrystalAxis(&x,&y,&z,i1,j1,k1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,i2,j2,k2,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
glEnd()
};
//绘制点阵平面,按逆时针输入坐标。
fcglCrystalQuads(i1,j1,k1,i2,j2,k2,i3,j3,k3,i4,j4,k4,a,b,c,Alpha,Beta,Gamma:x,y,z)=
{
glBegin(GL_QUADS),
fcglTransCrystalAxis(&x,&y,&z,i1,j1,k1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,i2,j2,k2,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,i3,j3,k3,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,i4,j4,k4,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
glEnd()
};
///
// 用 户 定 义 开 始
///
DrawCellEdge(a,b,c,Alpha,Beta,Gamma,EdgeR,EdgeG,EdgeB)= //绘制晶胞晶棱的函数
{
glColor3d[EdgeR,EdgeG,EdgeB],
fcglCrystalLine(0,0,0,0,1,0,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(0,1,0,0,1,1,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(0,1,1,0,0,1,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(0,0,1,0,0,0,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(0,0,0,1,0,0,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(1,0,0,1,0,1,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(1,0,1,0,0,1,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(1,0,0,1,1,0,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(1,1,0,0,1,0,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(1,1,0,1,1,1,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(1,0,1,1,1,1,a,b,c,Alpha,Beta,Gamma),
fcglCrystalLine(1,1,1,0,1,1,a,b,c,Alpha,Beta,Gamma)
};
DrawCellDot(::Ball)= //绘制顶点的函数
{
gluSphere[Ball,0.1,10,10]
};
DrawCellApex(a,b,c,Alpha,Beta,Gamma,ApexR,ApexG,ApexB:x,y,z)= //绘制晶胞顶点
{
glColor3d[ApexR,ApexG,ApexB],
fcglTransCrystalAxis(&x,&y,&z,0,0,0,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,0,0,1,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,0,1,0,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,0,1,1,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,1,0,0,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,1,0,1,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,1,1,0,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,1,1,1,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z]
};
//绘制晶胞(晶棱及顶点)。不要在绘制晶棱及顶点的函数中使用显示列表。
//a,b,c,Alpha,Beta,Gamma:晶胞参数。EdgeR,EdgeG,EdgeB:晶棱颜色。ApexR,ApexG,ApexB:顶点颜色。
//该函数在显示列表中绘制图形,返回一个显示列表序号。
//在初始化场景时调用该函数,在场景绘制代码中执行该函数返回的显示列表。
DrawCrystalCell(a,b,c,Alpha,Beta,Gamma,EdgeR,EdgeG,EdgeB,ApexR,ApexG,ApexB:x,y,z,list)=
{
list=glGenLists[1],
glNewList[list,GL_COMPILE],
DrawCellEdge(a,b,c,Alpha,Beta,Gamma,EdgeR,EdgeG,EdgeB), //绘制晶胞晶棱
DrawCellApex(a,b,c,Alpha,Beta,Gamma,ApexR,ApexG,ApexB), //绘制晶胞顶点
glEndList[],
list
};
initScene(::MouseSpeed,Centre,CellX,CellY,CellZ, //初始化函数
CellA,CellB,CellC,CellAlpha,CellBeta,CellGamma,EdgeR,EdgeG,EdgeB,ApexR,ApexG,ApexB,Ball)=
{
gleClear(),
Ball=gluNewQuadric[], gluQuadricDrawStyle[Ball,GLU_FILL],gluQuadricNormals[Ball,GLU_SMOOTH],
gleAxis(0.0,0.0,-12.0),gleAngle(0.0,0.0,0.0), //设置图形初始位置
MouseSpeed=2.0, //鼠标移动速度
Centre=0, //0:点阵原点在屏幕中心;其他值:点阵中心在屏幕中心
CellX=3, CellY=3, CellZ=3, //X,Y,Z方向晶胞个数
ApexR=1.0, ApexG=0.0, ApexB=1.0, //晶胞顶点颜色
CellA=1.0, CellB=1.0 ,CellC=1.0, CellAlpha=90.0, CellBeta=90.0, CellGamma=120.0, //晶胞参数
EdgeR=0.0, EdgeG=1.0, EdgeB=0.0 //晶胞晶棱颜色
};
///
// 用 户 定 义 结 束
///
Scene(:i,j,k,x,y,z:listDrawCrystalCell,MouseSpeed,Centre,CellX,CellY,CellZ,
CellA,CellB,CellC,CellAlpha,CellBeta,CellGamma,EdgeR,EdgeG,EdgeB,ApexR,ApexG,ApexB)=
{
if{ gleIsInitScene(), //需要初始化场景时,就执行初始化函数
initScene(),
listDrawCrystalCell=DrawCrystalCell(CellA,CellB,CellC,CellAlpha,CellBeta,CellGamma,EdgeR,EdgeG,EdgeB,ApexR,ApexG,ApexB),
fcglFollowMouse(0)
},
if{ gleVirtualKey(116), //按F5时,重置参数
gleVirtualKey(116,false),
gleReSetPara
{ "鼠标移动速度", &MouseSpeed,
"0:点阵原点在屏幕中心;其他值:点阵中心在屏幕中心", &Centre,
"X方向晶胞个数", &CellX,
"Y方向晶胞个数", &CellY,
"Z方向晶胞个数", &CellZ,
"晶胞参数之 a", &CellA,
"晶胞参数之 b", &CellB,
"晶胞参数之 c", &CellC,
"晶胞参数之 α", &CellAlpha,
"晶胞参数之 β", &CellBeta,
"晶胞参数之 γ", &CellGamma,
"晶胞晶棱颜色之 Red", &EdgeR,
"晶胞晶棱颜色之 Green", &EdgeG,
"晶胞晶棱颜色之 Blue", &EdgeB,
"晶胞顶点颜色之 Red", &ApexR,
"晶胞顶点颜色之 Green", &ApexG,
"晶胞顶点颜色之 Blue", &ApexB
},
glDeleteLists(listDrawCrystalCell,1),
listDrawCrystalCell=DrawCrystalCell(CellA,CellB,CellC,CellAlpha,CellBeta,CellGamma,EdgeR,EdgeG,EdgeB,ApexR,ApexG,ApexB)
},
glClear[], //清除屏幕以及深度缓存
glColor3d[1.0,0.0,0.0],
gleAxesAngle[], //显示屏幕坐标及旋转角度
glLoadIdentity[], //重置视图
fcglFollowMouse(MouseSpeed), //鼠标跟随
//按F4时,显示帮助
if[gleVirtualKey(115),gleVirtualKey(115,false),gleMessageBox("按下鼠标左键,图形将随鼠标移动,放开鼠标左键,图形停止移动。\r\n按F5进行参数设置。","图形演示说明",64)],
if[Centre,glTranslated(-CellX/2.0,-CellY/2.0,-CellZ/2.0)],
i=0,
while{ i<CellX,j=0,
while{ j<CellY,k=0,
while{ k<CellZ,
fcglTransCrystalAxis(&x,&y,&z,i,j,k,CellA,CellB,CellC,CellAlpha,CellBeta,CellGamma),
glTranslated[x,y,z], //移动坐标
glCallList[listDrawCrystalCell], //绘制图形
glTranslated[-x,-y,-z], //恢复坐标
k++
},
j++
},
i++
}
};
OpenGl显示列表是一组预先存储起来的OpenGl命令。显示列表可以在任何地方被调用,并按顺序立即执行。显示列表是经过编译的,因而执行效率比较高。
要应用显示列表,首先应创建一个显示列表(创建显示列表要在初始化函数中进行),由glNewList()函数和glEndList()函数来完成。执行显示列表的函数是glCallList()函数或glCallLists()函数。管理和使用显示列表的函数还有glListBase()、glGenLists()和glDeleteLists()等函数。
尽管显示列表给应用程序提供了一个提高整体性能的机制,但并不能任意使用显示列表。因为启动显示列表需要一定的开销,如果这种开销不能被执行命令的开销所抵消,那就适得其反了。显示列表可以应用于:
第一,由大量的数据构造的几何模型,且是多次被调用或是几何模型要发生运行。
第二,较高维数的矩阵操作。在图形学算法中,需要涉及大量的矩阵运算,特别是矩阵求逆运算。
第三,光栅位图、图像和纹理操作。应用显示列表可调整像素数据,使其适合硬件处理的格式。
第四,光照计算。光照具有十分复杂的数学运算,如果场景中不同材质的物体较多且需要变化,把材质放入显示列表中,能发挥显示列表的优势。
第五,OpenGl使用库中标准二次曲面、Bezier曲线及曲面、NURBS曲线及曲面的绘制等等。
使用显示列表要注意以下事项:
第一,显示列表中所有函数的参数是当前的,不会受今后变化的影响。
第二,封装在显示列表中的变换操作会对后继绘图产生影响。
第三,显示列表不可对其进行外部干预。
第四,显示列表需要精心管理。
第五,不能在显示列表中使用的函数有:glIsList(),glGenLists(),glDeleteLists(),glFeedbackBuffer(),glSelectBuffer(),glRenderMode(),glFlush(),glFinish(),glIsEnabled(),glGet()。
实体模块是用OpenGl命令绘制任意实体的MLu的模块源程序。模块写好后,一般不需改动,仅在需要时调用即可。显然,在模块中使用显示列表创建实体是非常方便的。
例如,下面的程序可作为模块来使用,可在任意的场景绘制单元中加入鼠标支持:
//让图形随鼠标移动。factor为比例因子,factor越大则移动幅度越大。factor=0进行初始化。
fcglFollowMouse(factor:x,y,xx,yy,xxx,yyy,static,fcglFollowMouse,xMouse,yMouse)=
{
if[!factor,fcglFollowMouse=0,return(0)],
if[gleGetMouseMsg(WM_LBUTTONDOWN,&x,&y),fcglFollowMouse=1,xMouse=x,yMouse=y],
gleGetWindowSize[&xxx,&yyy],
if[fcglFollowMouse,gleGetMouseMsg(WM_MOUSEMOVE,&xx,&yy),gleAngle[1,gleAngle(1)+(yy-yMouse)/yyy*factor],gleAngle[2,gleAngle(2)+(xx-xMouse)/xxx*factor]],
if[gleGetMouseMsg(WM_LBUTTONUP,&xx,&yy),fcglFollowMouse=0],
glRotated[gleAngle(1),1.0,0.0,0.0], //使图象沿X轴旋转
glRotated[gleAngle(2),0.0,1.0,0.0], //使图象沿Y轴旋转
glRotated[gleAngle(3),0.0,0.0,1.0] //使图象沿Z轴旋转
};
再如,下面的模块可用在晶体图的绘制中:
//x,y,z为要获得的屏幕坐标,需要引用参数&调用。
//i,j,k为点阵坐标。
//a,b,c,Alpha,Beta,Gamma为点阵的6个参数。
//规定:点阵原点即屏幕原点,点阵a轴即屏幕x轴,点阵b轴在屏幕x,y轴决定的平面内。
fcglTransCrystalAxis(x,y,z,i,j,k,a,b,c,Alpha,Beta,Gamma:_Alpha,_Beta,_Gamma,m)=
{
_Alpha=Alpha/180*3.1415926, _Beta=Beta/180*3.1415926, _Gamma=Gamma/180*3.1415926,
x=i*a+j*b*cos(_Gamma)+k*c*cos(_Beta),
m=[cos(_Alpha)^2+cos(_Beta)^2]/[1+cos(_Gamma)],
y=j*b*sin(_Gamma)+k*c*sqrt[m-cos(_Beta)^2],
z=k*c*sqrt[1-m]
};
//绘制连接两个点阵点的线段。
fcglCrystalLine(i1,j1,k1,i2,j2,k2,a,b,c,Alpha,Beta,Gamma:x,y,z)=
{
glBegin(GL_LINES),
fcglTransCrystalAxis(&x,&y,&z,i1,j1,k1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,i2,j2,k2,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
glEnd()
};
//绘制点阵平面,按逆时针输入坐标。
fcglCrystalQuads(i1,j1,k1,i2,j2,k2,i3,j3,k3,i4,j4,k4,a,b,c,Alpha,Beta,Gamma:x,y,z)=
{
glBegin(GL_QUADS),
fcglTransCrystalAxis(&x,&y,&z,i1,j1,k1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,i2,j2,k2,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,i3,j3,k3,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,i4,j4,k4,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
glEnd()
};
//绘制简单晶胞(晶棱及顶点)。顶点由自定义函数DrawCellDot()绘制,该函数在调用模块中定义,被自动调用,不要在该函数中使用显示列表。
//a,b,c,Alpha,Beta,Gamma:晶胞参数。EdgeR,EdgeG,EdgeB:晶棱颜色。ApexR,ApexG,ApexB:顶点颜色。
//该函数在显示列表中绘制图形,返回一个显示列表序号。
//在初始化场景时调用该函数,在场景绘制代码中执行该函数返回的显示列表。
fcglDrawCrystalPCell(a,b,c,Alpha,Beta,Gamma,EdgeR,EdgeG,EdgeB,ApexR,ApexG,ApexB:x,y,z,list)=
{
list=glGenLists[1],
glNewList[list,GL_COMPILE],
//绘制点阵单元
glColor3d[EdgeR,EdgeG,EdgeB],
glBegin(GL_LINES),
fcglTransCrystalAxis(&x,&y,&z,0,0,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,1,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,1,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,1,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,1,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,0,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,0,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,0,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,0,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,0,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,0,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,0,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,0,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,0,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,0,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,1,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,1,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,1,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,1,0,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,1,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,0,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,1,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,1,1,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
fcglTransCrystalAxis(&x,&y,&z,0,1,1,a,b,c,Alpha,Beta,Gamma),glVertex3d(x,y,z),
glEnd(),
//绘制顶点
glColor3d[ApexR,ApexG,ApexB],
fcglTransCrystalAxis(&x,&y,&z,0,0,0,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,0,0,1,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,0,1,0,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,0,1,1,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,1,0,0,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,1,0,1,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,1,1,0,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
fcglTransCrystalAxis(&x,&y,&z,1,1,1,a,b,c,Alpha,Beta,Gamma),glTranslated[x,y,z],DrawCellDot(),glTranslated[-x,-y,-z],
glEndList[],
list
};
OpenLuGl试图输出OpenGl的绝大部分函数并加以扩展(目前仅进行了部分工作),使之能方便地绘制三维图形。
OpenLuGl中的函数目前有四种:以gl开头的是OpenGl32中的标准OpenGl函数;以glu开头的是glu32中的辅助OpenGl函数;以gle开头的是为方便与OpenGl和绘图窗口交互而扩展的函数;以lg开头的是OpenLuGl扩展的实用绘图函数,目前主要是一些绘制数学函数图形的函数。OpenLuGl努力保证这些函数在运行时的安全性,即无论以何种顺序使用这些函数,程序都不会崩溃(这也是所有Lu二级函数应具有的特点),但用户应该知道:只有正确地使用这些函数,才能充分发挥它们的性能。充分了解每一个要使用的函数的性能是非常必要的。
根据函数的使用位置,OpenLuGl函数可分为三类:进行场景绘制的函数,用于初始化场景的函数,可在任意位置使用的函数。场景绘制函数具有循环执行的特点,显然可用于场景的初始化;而初始化函数仅在切换场景时执行一次,通常不能用在场景绘制函数之中。
OpenLuGl中绝大多数的OpenGl函数(以gl或glu开头)的用法及功能与在OpenGl中完全相同,但也有少数函数不一样,在使用中要主要这些差别。其中,函数列表中标记为“有扩展”的函数为与OpenGl函数的用法及功能完全相同且有所扩展;标记为“有区别”的函数与OpenGl函数的功能完全相同,但用法有区别。
8 gl函数 :OpenGl32函数 [返回页首]
类别 | 函数 | 用途 | 使用位置 | 与OpenGl函数相比 |
gl | glClear | 清除屏幕以及深度缓存 | 场景绘制函数 | 有扩展 |
gl | glLoadiDentity | 重置视图 | 场景绘制函数 | 完全相同 |
gl | glTranslated | 移动坐标 | 场景绘制函数 | 完全相同 |
gl | glColor3d | 设置颜色 | 场景绘制函数 | 完全相同 |
gl | glBegin | 开始绘图 | 场景绘制函数 | 完全相同 |
gl | glEnd | 结束绘图 | 场景绘制函数 | 完全相同 |
gl | glVertex3d | 设置三维绘图点 | 场景绘制函数 | 完全相同 |
gl | glRotated | 使对象围绕轴进行旋转 | 场景绘制函数 | 完全相同 |
gl | glPointSize | 定义点的尺寸 | 场景绘制函数 | 有扩展 |
gl | glLineWidth | 设置线宽 | 场景绘制函数 | 有扩展 |
gl | glLineStipple | 设置线的虚点模式 | 场景绘制函数 | 完全相同 |
gl | glEnable | 设置OpenGL的各种功能 | 场景绘制函数 | 完全相同 |
gl | glDisable | 取消OpenGL的各种功能 | 场景绘制函数 | 完全相同 |
gl | glPolygonMode | 多边形模式设置 | 场景绘制函数 | 完全相同 |
gl | glClearColor | 设置屏幕清屏的颜色 | 初始化函数 | 完全相同 |
gl | glCallList | 执行显示列表 | 场景绘制函数 | 完全相同 |
gl | glListBase | 设置显示列表序列的基序号 | 场景绘制函数 | 完全相同 |
gl | glCallLists | 执行显示列表序列 | 场景绘制函数 | 有区别 |
gl | glGenLists | 创建一个或多个连续的显示列表,返回显示列表的基序号 | 初始化函数 | 完全相同 |
gl | glNewList | 建立显示列表,并编译和执行显示列表 | 初始化函数 | 完全相同 |
gl | glEndList | 结束建立显示列表 | 初始化函数 | 完全相同 |
gl | glVertex2d | 设置二维绘图点 | 场景绘制函数 | 完全相同 |
gl | glEdgeFlag | 设置边的可见性 | 场景绘制函数 | 有区别 |
gl | glPushMatrix | 将当前矩阵压入堆栈 | 场景绘制函数 | 完全相同 |
gl | glPopMatrix | 将当前矩阵弹出堆栈 | 场景绘制函数 | 完全相同 |
gl | glScaled | 缩放变换 | 场景绘制函数 | 完全相同 |
gl | glDeleteLists | 删除一组连续的显示列表 | 场景绘制函数 | 完全相同 |
[返回本类函数列表] [返回页首] glClear[]或glClear[Mask]:清除屏幕以及深度缓存
Mask:整数,工作方式。
- Bitwise OR operators of masks that indicate t