openGL一课 

2007-02-06 11:12 发布

4159 6 0

也许对使用MAYA的你没什么用处,当然在编写插件代码时确实几乎不可缺少的,而且也会加深对MAYA处理机制的了解
写这个贴是一是为了让大家对偶们使用的图形软件更深入的了解,二是可以强迫偶自己学习这门课程。废话少说,开始
现在的几乎所有OPENGL教材都是先对其做些介绍,然后再由浅入深的介绍功能。但是偶认为这并不是一个好的学习方法。因为即使是在刚开始的入门课程中的简单的程序示例所包含的OPENGL函数对于那些不了解OPENGL的菜鸟来说也不得不边翻找后面的相关函数的介绍,边顾及该程序的意义。所以偶开始先介绍一些基本的OPENGL函数,作为有核心数学情节的偶更喜欢先介绍实现建模的功能,以后还会陆续介绍模型变换,渲染和基于鼠标和键盘的屏幕交互操作。
在此之前首先做一些规定:对于数据类型short,int,float,double,byte这些经常作为OPENGL特定类型的函数后缀均取第一个字母.
《1》曲线和曲面
1标准的OPENGL曲线和曲面功能实现函数
void glMap1<f/d>(GLenum procType,GL<float/double> su,GL<float/double> eu,GLint stride,GLint order,const GL<float/double> *pointer);
这个函数用来定义一个一维求值器,是procTYPE求值器产生的值的类型,包括:GL_MAP1_VERTEX_3,GL_MAP1_VERTEX_4,GL_MAP1_INDEX,GL_MAP1_COLOR_4,GL_MAP1_NORMAL,GL_MAP1_TEXTURE_COORD_1,GL_MAP1_TEXTURE_COORD_2,GL_MAP1_TEXTURE_COORD_3,GL_MAP1_TEXTURE_COORD_4;su是求值器所要求的参数的起始值;eu是末值;stride指定了求值器将要产生的值的个数;order而指定了该参数方向的控制点个数。
void glMapGrid1<f/d>(GLint un,GL<float/double> su,GL<float/double> eu);
该函数用来在参数值su与eu之间建立un块等间距的网格。
void glEvalCoord1<f/d><v>(GL<float/double> u);
该函数使用已经定义并启用的求值器根据所给参数的参数方程计算得到顶点,颜色,法线以及纹理坐标值。
void glEvalMesh1<f/d>(GLenum mode,GL<float/double> su,GL<float/double> eu);
这个函数从参数的始值su到末值eu使用模式mode渲染已经启动的求值器的目标.模式类型包括:GL_POINT,GL_LINE,GL_FILL.
下面是响应的2维求值器,其参数的意义与上面类同,只不过加了一个维度.
void glMap2<f/d>(GLenum procTypeU,GL<float/double> su,GL<float/double> eu,GLint ustride,GLint uorder,GLenum procTypeV,GL<float/double> sv,GL<float/double> ev,GLint vstride,GLint vorder);

void glMapGrid2<f/d><v>(GLint un,GL<float/double> su,GL<float/double> eu,GLint vn,GL<float/double> sv,GL<float/double> ev);

void glEvalCoord2<f/d><v>(GL<float/double> <u/*u>,GL<float/double> <v/*v>);

void glEvalMesh2<f/d>(GLenum mode,GL<float/double> su,GL<float/double> eu,GL<float/double> sv,GL<float/double> ev);
在我们使用某种类型的求值器前,必须使用函数glEnable()开启该类型的求值器功能。例如:glEnable(GL_MAP2_NORMAL);

作者:炙墨追零

假如我们想建立一个在U方向DIVISION为10,而在V方向DIVISION为20的网状曲面,那么偶们就可以通过下面的代码实现:
GLdouble(su)=GLdouble(sv);将
GLdouble(eu)=GLdouble(ev);
glMap2(GL_MAP2_VERTEX_4,su,eu,9,10,GL_MAP2_VERTEX_4,sv,ev,19,20);//定义一个2维求值器
glEnable(GL_MAP2_VERTEX_3);//开启2维顶点型求值器的功能
glBegin(GL_LINE_STRIP);//通过调用已经启动的求值器计算得到所需顶点
for(i=0,j=0;i<10,j<20,;i++,j++)
{
glEvalCoord2d(su+i*(eu-su)/10,sv+i*(sv-ev)/20);
}
glEnd();
glMap2(GL_MAP2_COLOR_4,su,eu,9,10,GL_MAP2_COLOR_4,sv,ev,19,20);//定义顶点颜色
glEnable(GL_MAP2_COLOR_4);//开启渲染顶点颜色功能
上面的glBegin()和glEnd()之间的代码还可以用下面更为简单的代码代替:

glMapGrid2d(10,su,eu,20,sv,ev);
glEvalMesh2(GL_LINE,su,eu,sv,ev);//用LINE模式绘制模型

[此贴子已经被作者于2007-2-6 11:14:18编辑过]
B Color Smilies

全部评论6

  • 前腐后继
    前腐后继 2007-2-6 11:13:00
    <2 >GLU和GLUT对象
    GLUO是包含在GL工具库里的函数,算不上真正的OPENGL函数。但是却可以在OPENGL编程中直接使用,当然必须在VC++或其他平台上安装了相应的头文件。
    下面是几个用于创建简单的2次曲面的GLU函数:
    GLUquadricObj* gluNewQuadric();
    //创建一个新的2次曲面对象,并返回一个指向该对象的指针
    void gluDeleteQuadric(GLUquadricObj*);
    //删除又2次对象指针指定的2次曲面
    void gluSphere(GLUquadricObj* pobj,GLdouble radius,GLint silces,GLint stacks);
    //创建球体
    void gluCylinder(GLUquadricObj* pobj,GLdouble baseRadius,GLdouble topRadius,GLint slices,GLint stacks);
    //创建圆柱体
    void gluDisk(GLUquadricObj* pobj,GLdouble innerRadius,GLdouble outerRadius,GLint slices,GLint stacks);
    //创建圆环盘,innerRadius,outerRadius分别指定了内径和外径
    让偶们来举个创建2次对象的简单e.g:
    //创建一个半径为5,在经线和纬线方向细分数为10的球体
    GLUquadricObj *pobj;
    pobj=gluNewQuadric();
    gluQuadricDrawStyle(pobj,GLU_LINE);//确定几何体的绘制模式(GLU_LINE)
    gluSphere(pobj,5,10,10);
    下面几个是创建GLUT对象的函数,是对GLU的补充
    void glutWireSphere(GLdouble radius,GLint slices,GLint stacks);
    //创建线框球体
    void glutSolidSphere(GLdouble radius,GLint slices,GLint stacks);
    //创建实心球体
    void glutWireCone(GLdouble baseRadius,GLdouble height,GLint slices,GLint stacks);
    void glutSolidCone(GLdouble baseRadius,GLdouble height,GLint slices,GLint stacks);
    void glutWireTorus(GLdouble innerRadius,GLdouble outerRadius,GLint slices,GLint stacks);
    void glutSolidTorus(GLdouble innerRadius,GLdouble outerRadius,GLint slices,GLint stacks);
    //
    //下面的几个函数是用来创建柏拉图(即正多面体),所有的顶点都定义在一个单位员上,由于这些都是确定类型的多面体,因此顶点数已经定义于内部,因此不需要指定参数
    void glutWireTetrahedron();
    void glutSolidTetrahedron();
    void glutWireOctahedron();
    void glutSolidOctahedron();
    void glutWireDodecahedron();
    void glutSolidDodecahedron();
    void glutWireIcosahedron();
    void glutSolidIcosahedron();
    OK,today over at now. See again tomorrow!

  • 前腐后继
    前腐后继 2007-2-6 11:13:00
    Begin again

    此课开始之前还是介绍以下OPENGL中的数据类型,对于C语言绑定的OPENGL来说,它采用标准的C数据类型,只不过在前面加上“GL”例如:GLboolean,GLflaot,GLenum,GLbyte,GLshort.而这些类型前面加“u”的说明是无符号类型,e.g:
    GLushort,GLubyte,GLuint.
    <3>
    openGL中的NURBS对象
    在OPENGL中创建NURBS对象很容易,只需下面几个GLU函数就可以起用NURBS的功能:
    GLUnurbsObj* gluNewNurbsRenderer(void);
    //创建一个NURBS对象
    void gluDeleteNurbsRenderer(GLUnurbsObj*);
    //...
    void gluNurbsCurve(GLUnurbsObj*,GLint knots,GLfloat *knotArray,GLint stride,GLfloat *cvArray,GLint order,GLenum type);
    //定义一条NURBS曲线的形状(注意,是“形状”,含义等同于MAYA中形状的概念)。由nkont确定的结的数量;knotArray:结值数组;stride控制点之间的偏移量;cvArray用来定义控制点的值的数组(可以是3或4维的顶点,例如:GL_VERTEX_3,GL_VERTEX_4,在OPENGL内部使用的是4-类型,至于为什么,涉及数学中的"齐次坐标",而这中表示又涉及到OPENGL的效率问题,偶对此随了解些.但这不是偶们的主题,暂不鏖述);type是dD(d=1,2)求值器的类型,可用类型有:GL_MAPd_VERTEX_x(x=3,4),GL_MAPd_NORMAL,GL_MAPd_INDEX,GL_MAPd_TEXTURE_COORD_x(x=1,2,3,4).
    GL_MAP1_COLOR4(使用RGBA模式)
    void gluBeginCurve(GLUnurbsObj*);
    //开始一个NURBS形状的定义,上面的函数必须包含在该函数和下面的结束函数之间
    //
    e.g:
    GLfloat knot[]={
    {1,0,0,1},
    {0,1,0,1},
    {0,0,1,1},
    {0,1,1,1},
    {1,0,1,1},
    {1,1,0,1},
    {1,1,1,1},
    };
    GLfloat cvArray=knot[0];
    GLUnurbsObj* pobj=gluNewNurbsRenderer();
    gluBeginCurve(pobj);
    gluNurbsCurve(pobj,7,knot,1,cvArray,4,GL_MAP1_VERTEX_4);
    gluEndCurve(pobj);
    //
    gluBeginCurve(
    void gluEndCurve(GLUnurbsObj*);
    //...
    void gluNurbsSurface(GLUnurbsObj*,GLint nkontu,GLfloat * knotu,GLint strideu,...);
    //参数设置和gluNurbsCurve()中的类似,只要再将除GLUnurbsObj*之外的重复一次并"u"把该成"v"即可
    void glubBeginSurface(GLUnurbsObj*);
    //...
    void gluEndSurgace(GLUnurbsObj*);
    //...
    OK一次讲太多对学习也没多大益处,所以今天就讲到这里
  • 前腐后继
    前腐后继 2007-2-6 11:13:00
    接下来讲一下如何在OPENGL中生成最基本的点,并由此而产生线和面
    很简单,首先通过启用OPENGL中的点模式就可以使生成的点,线或面以点的形式在视图窗口中显示:
    //绘制一个3维坐标为(1.0,0.5,2.0)的点,记住:OPENGL内部采用齐次坐标的形式表示点,坐标的第4个分量表示从4维空间向3维空间投射的缩放系数.从而很容易联想到用3维空间的齐次坐标表示2维空间的坐标,E.G:(2,6,4)~=(0.5,1.5)
    glEnable(GL_POINTS);
    glBegin(GL_POINTS);//我们还可以通过来glPointSize(GLfloat)设置点的大小,但不能放在之间。总之与下面的线和面的特征的设置函数也是如此
    glVertex4f(2.0,1.0,4.0,2.0);//等价与glVertex3f(1.0,0.5,2.0)
    glEnd();
    同样的任何一个3维点都可以表示成为一个齐次点,而第4个分量为1,e.g:
    (1,1,2)~(1,1,2,1).更广泛的形式:(x,y,z)~(x,y,z,1);
    类似于点画模式,OPENGL还支持线模式和面模式;此外线模式分为:GL_LINES,GL_LINE_STRIP,GL_LINE_LOOP.而面模式支持:GL_POLYGON,GL_TRIANGLES,GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN,GL_QUADS,GL_QUAD_STRIP.而这些都是基于控制点的,对于线模式,至少需要定义2个顶点,而对于面模式至少需要定义3个顶点(这是需要启用三角模式中的一种).对于各个模式类型的区别,偶们通过程序示例来解释:
    在所有绘制的实际定义开始之前,都必须首先通过glEnable()启用OPENGL的相应功能,并可以通过glDisable()禁用某项功能.
    glEnable(GL_LINE_STRIP);//GL_LINE_STRIP模式下,每条线段的终点都是下一条线段的起点并最终被定义为一条线,而GL_LINES模式只是从第一个顶点的定义的顺序开始,没一对顶点定义一条线段,没有端点之间的重复,若顶点数为奇数,则最后定义的顶点不被使用。而对于2个点的情况,这2种模式会产生相同的结果。但模式却隐含了一个未定义或将来有可能定义的顶点的起点(偶个人的理解)
    glBegin(GL_LINE_STRIP);
    glVertex3d(1,1,1);
    glVertex3d(2,2,4);
    glVertex3d(1,4,5);
    glVertex3d(6,4,6);
    glEnd();
    若偶们用GL_LINE_LOOP模式代替GL_LINE_STRIP,则会生成一个闭合的线圈.它和GL_LINE_STRIP的区别仅仅是最后一个顶点自动连接到第一个顶点.这样偶有了一个有意思的想法,即:"均权性"或"周期性".也就是每个顶点都既是起点也是终点.
    可以通过void glLineWidth(GLfloat)和void glLineStipple(GLint,GLushort)函数分别设置线的宽度和条纹图案。glLineStipple()的第一个参数是第二个参数的重复次数,而第二个参数是是否绘制像素的“0”,“1”序列。
    对于面模式之间的区别和线模式类似:GL_POLYGON通过glBegin(),glEnd()之间定义的一系列点绘制“一个”多变形;GL_TRIANGLES每三个连续的顶点绘制三角形,但顶点不重复;GL_TRIANGLE_STRIP模式和线做同类理解;而模式GL_TRIANGLE_FAN是前3个顶点定义一个三角形,之后每个顶点都和第一个顶点和前一个顶点组合,这样会生成类似于折扇投影的三角多边扇形;其余的就是绘制4边形,这些都是多边形的基础。
    That`s will leave now,so get`t over.Get flash^-^
  • 前腐后继
    前腐后继 2007-2-6 11:14:00
    又要开始了。
    前面讲了一些基本的功能,在继续位完成的基本功能讲解之前看来有必要将一下开发OPENGL程序的开发环境。这里特定于WINDOWS平台,因为偶用的就是WIN,当然也可以用于UNIX,LINUX,MACRO等任何具有图形卡的计算机(记住,OPENGL与平台无关)。但对于现在WINDOWS 机上常用的DIRECTX,却仅仅适用于WINDOWS;这也是偶为什么学的是OPENGL而不是它
    OPENGL绑定除了C之外还有VB以及非正式的JAVA。我门这里仅对于VC++而言。首先插入带有OpenGL32.dlL和glu32.dll文件的光盘(当然如果系统已经有了就不用了)对应的库文件应该包含在...\VC\lib中("..."包容你的VC文件的路径,如:C:\program File\microsoft Visual Studio.), 包容文件应该在...VC\include\GL中。GLUT文件需要从网上获得。然后你就可以用VC++6。0开发你自己的OPENGL程序(只要你安装了VC++)。
    下面介绍一下创建窗口的函数,然后你就可以利用前面学过的函数编写简单的OPENGL程序。
    glutCreateWindow(GLbyte*);
    GLbyte*相当与C的数据类型char*,也就是接收一个字符串,该字符串定义了窗口的标题。
    //
    //这个函数用来显示回调,当窗口大小或从覆盖状态恢复时,总之窗口需要重绘时都会条用该函数。
    void glutDisplayFunc(userRenderFunc)
    //
    //导致事件的处理循环。几乎必须放在程序的最后,每个程序一次只能调用一次该函数,而且该函数调用以后不再返回只到程序结束
    void glutMainLoop()
    //
    //这2个函数用来设置窗口的清除色,对于第2中类型的参数可以选择GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT或者你也可以对2者使用按位或操作符:GL_COLOR_BUFFER_BIT/GL_DEPTH_BUFFER_BIT.用来清除颜色缓冲区和深度缓冲区的,也既释放该缓冲区的内存.
    void glClearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)
    void glClearColor(byte)
    好了精彩的节目就要开始,先写到 这里,等一会就来继续
  • f145
    f145 2007-2-7 12:52:00
    不错啊
  • lovemaxmax
    lovemaxmax 2007-5-5 06:03:00
    [em04]慢慢看~~

你可能喜欢

openGL一课 
联系
我们
快速回复 返回顶部 返回列表