• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            OpenGL復(fù)雜物體建模

             目 錄
              13.1 圖元擴(kuò)展
              13.2 法向計(jì)算
              13.3 曲線生成
              13.4 曲面構(gòu)造

             

              在前面的章節(jié)中已經(jīng)講述了最基本的幾何圖元建模,但在實(shí)際應(yīng)用中只有這些圖元是很不夠的,要生成一個(gè)稍微復(fù)雜點(diǎn)的曲線、曲面或一些不規(guī)則的物體(例如山脈等)相當(dāng)費(fèi)事。令人比較高興的是,OpenGL基本庫(kù)(gl庫(kù))和功能庫(kù)(glu庫(kù))為我們提供了很大的方便,這一章將詳細(xì)介紹圖元擴(kuò)展、法向計(jì)算、曲線生成和曲面構(gòu)造等內(nèi)容。

            13.1 圖元擴(kuò)展

              13.1.1 點(diǎn)和線
              下面分別介紹點(diǎn)和線的擴(kuò)展形式及用法。
              1)點(diǎn)。OpenGL中定義的點(diǎn)可以有不同的尺寸,其函數(shù)形式為:
             
            void glPointSize(GLfloat size);

             設(shè)置點(diǎn)的寬度(以象素為單位)。參數(shù)size必須大于0.0,缺省時(shí)為1.0。

              2)線。OpenGL能指定線的各種寬度和繪制不同的虛點(diǎn)線,如點(diǎn)線、虛線等。相應(yīng)的函數(shù)形式如下:
             

            void glLineWidth(GLfloat width);

            設(shè)置線寬(以象素為單位)。參數(shù)width必須大于0.0,缺省時(shí)為1.0。
             

            void glLineStipple(GLint factor,GLushort pattern);

              設(shè)置線為當(dāng)前的虛點(diǎn)模式。參數(shù)pattern是一系列的16位數(shù)(0或1),它重復(fù)地賦給所指定的線。其中每一位代表一個(gè)象素,且從低位開(kāi)始,1表示用當(dāng)前顏色繪制一個(gè)象素(或比例因子指定的個(gè)數(shù)),0表示當(dāng)前不繪制,只移動(dòng)一個(gè)象素位(或比例因子指定的個(gè)數(shù))。參數(shù)factor是個(gè)比例因子,它用來(lái)拉伸pattern中的元素,即重復(fù)繪制1或移動(dòng)0,比如,factor為2,則碰到1時(shí)就連續(xù)繪制2次,碰到0時(shí)連續(xù)移動(dòng)2個(gè)單元。factor的大小范圍限制在1到255之間。在繪制虛點(diǎn)線之前必須先啟動(dòng)一下,即調(diào)用函數(shù)glEnable(GL_LINE_STIPPLE);若不用,則調(diào)用glDisable(GL_LINE_STIPPLE)關(guān)閉。下面舉出一個(gè)點(diǎn)線擴(kuò)展應(yīng)用實(shí)例:

              例13-1 點(diǎn)線擴(kuò)展應(yīng)用例程expntlin.c
             

            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
             
            void myinit(void);
            void line2i(GLint x1,GLint y1,GLint x2,GLint y2);
            void CALLBACK display(void); void myinit (void)
            {
              glClearColor (0 , 0.0, 0.0, 0.0);
              glShadeModel (GL_FLAT);
            }
             
            void line2i(GLint x1,GLint y1,GLint x2,GLint y2)
            {
              glBegin(GL_LINES);
              glVertex2f(x1,y1);
              glVertex2f(x2,y2);
              glEnd();
            }
             
            void CALLBACK display(void)
            {
              int i;
             
              glClear (GL_COLOR_BUFFER_BIT);
             
              /* 第一行繪制的是一系列大小尺寸不同的點(diǎn)(以象素為基本擴(kuò)展單元) */
              glColor3f(0.8,0.6,0.4);
              for (i = 1; i <= 10; i++)
              {
                glPointSize(i*2);
                glBegin (GL_POINTS);
                glVertex2f (30.0 + ((GLfloat) i * 50.0), 330.0);
                glEnd ();
              }
             
              /* 第二行繪制的是三條不同線型的線段 */
             
              glEnable (GL_LINE_STIPPLE);
             
              glLineStipple (1, 0x0101); /* 點(diǎn)線 */
              glColor3f(1.0 ,0.0,0.0);
              line2i (50, 250, 200, 250);
             
              glLineStipple (1, 0x00FF); /* 虛線 */
              glColor3f(1.0,1.0,0.0);
              line2i (250 , 250 , 400, 250 );
             
              glLineStipple (1, 0x1C47); /* 虛點(diǎn)線 */
              glColor3f(0.0,1.0,0.0);
              line2i (450 , 250 , 600 , 250 );
             
              /* 第三行繪制的是三條不同寬度的線段 */
             
              glLineWidth (5.0);
              glLineStipple (1, 0x0101);
              glColor3f(1.0 ,0.0,0.0);
              line2i (50 , 200 , 200 , 200 );
             
              glLineWidth (3.0);
              glLineStipple (1, 0x00FF);
              glColor3f(1.0 ,1.0,0.0);
              line2i (250 , 200 , 400 , 200 );
             
              glLineWidth (2.0);
              glLineStipple (1, 0x1C47);
              glColor3f(0.0 ,1.0,0.0);
              line2i (450 , 200 , 600 , 200 );
             
              /* 設(shè)置以下線段的寬度為 1 */
              glLineWidth(1);
             
              /* 第四行繪制的是一條虛點(diǎn)線 */
             
              glLineStipple (1, 0xff0c);
              glBegin (GL_LINE_STRIP);
              glColor3f(0.0 ,1.0,1.0);
              for (i = 0; i < 12; i++)
                glVertex2f (50.0 + ((GLfloat) i * 50.0), 150.0);
              glEnd ();
             
              /* 第五行繪制的是十條獨(dú)立的虛點(diǎn)斜線 */
             
              glColor3f(0.4 ,0.3,0.8);
              for (i = 0; i < 10; i++)
              {
                line2i (50 + ( i * 50), 70, 75 + ((i+1) * 50), 100);
              }
             
              /* 第六行繪制的是一條虛點(diǎn)線,其中線型模式每個(gè)元素被重復(fù)操作5次 */
             
              glLineStipple (5, 0x1C47);
              glColor3f(1.0 ,0.0,1.0);
              line2i (50 , 25 , 600 , 25 );
             
              glFlush ();
            }
             
            void main(void)
            {
              auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
              auxInitPosition (0, 0, 650, 450);
              auxInitWindow ("External Points and Lines");
              myinit ();
              auxMainLoop(display);
            }
              以上程序運(yùn)行結(jié)果是顯示不同尺寸的點(diǎn)及不同線型和寬度的線的繪制方式。

             
            圖13-1 擴(kuò)展點(diǎn)線

              13.1.2 多邊形
              多邊形的繪制模式包含有好幾種:全填充式、輪廓點(diǎn)式、輪廓線式以及圖案填充式。下面分別介紹相應(yīng)的OpenGL函數(shù)形式。
              1)多邊形模式設(shè)置。其函數(shù)為:
            void glPolygonMode(GLenum face,GLenum mode);

              控制多邊形指定面的繪制模式。參數(shù)face為GL_FRONT、GL_BACK或GL_FRONT_AND_BACK;參數(shù)mode為GL_POINT、GL_LINE或GL_FILL,分別表示繪制輪廓點(diǎn)式多邊形、輪廓線式多邊形或全填充式多邊形。缺省時(shí),繪制的是正反面全填充式多邊形。

              2)設(shè)置圖案填充式多邊形。其函數(shù)為:

            void glPolygonStipple(const GLubyte *mask);

              為當(dāng)前多邊形定義填充圖案模式。參數(shù)mask是一個(gè)指向32x32位圖的指針。與虛點(diǎn)線繪制的道理一樣,某位為1時(shí)繪制,為0時(shí)什么也不繪。注意,在調(diào)用這個(gè)函數(shù)前,必須先啟動(dòng)一下,即用glEnable(GL_POLYGON_STIPPLE);不用時(shí)用glDisable(GL_POLYGON_STIPPLE)關(guān)閉。下面舉出一個(gè)多邊形擴(kuò)展繪制實(shí)例:

              例 13-2 多邊形圖案填充例程polystpl.c
             

             
            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
             
            void myinit(void);
            void CALLBACK display(void);
             
            void myinit (void)
            {
              glClearColor (0.0, 0.0, 0.0, 0.0);
              glShadeModel (GL_FLAT);
            }
             
            void CALLBACK display(void)
            {
             
              /* 填充模式定義 (32x32) */
              GLubyte pattern[]= {
                0x00, 0x01, 0x80, 0x00,
                  0x00, 0x03, 0xc0, 0x00,
                  0x00, 0x07, 0xe0, 0x00,
                  0x00, 0x0f, 0xf0, 0x00,
                  0x00, 0x1f, 0xf8, 0x00,
                  0x00, 0x3f, 0xfc, 0x00,
                  0x00, 0x7f, 0xfe, 0x00,
                  0x00, 0xff, 0xff, 0x00,
                  0x01, 0xff, 0xff, 0x80,
                  0x03, 0xff, 0xff, 0xc0,
                  0x07, 0xff, 0xff, 0xe0,
                  0x0f, 0xff, 0xff, 0xf0,
                  0x1f, 0xff, 0xff, 0xf8,
                  0x3f, 0xff, 0xff, 0xfc,
                  0x7f, 0xff, 0xff, 0xfe,
                  0xff, 0xff, 0xff, 0xff,
                  0xff, 0xff, 0xff, 0xff,
                  0x7f, 0xff, 0xff, 0xfe,
                  0x3f, 0xff, 0xff, 0xfc,
                  0x1f, 0xff, 0xff, 0xf8,
                  0x0f, 0xff, 0xff, 0xf0,
                  0x07, 0xff, 0xff, 0xe0,
                  0x03, 0xff, 0xff, 0xc0,
                  0x01, 0xff, 0xff, 0x80,
                  0x00, 0xff, 0xff, 0x00,
                  0x00, 0x7f, 0xfe, 0x00,
                  0x00, 0x3f, 0xfc, 0x00,
                  0x00, 0x1f, 0xf8, 0x00,
                  0x00, 0x0f, 0xf0, 0x00,
                  0x00, 0x07, 0xe0, 0x00,
                  0x00, 0x03, 0xc0, 0x00,
                  0x00, 0x01, 0x80, 0x00
              };
             
              glClear (GL_COLOR_BUFFER_BIT);
             
              /* 繪制一個(gè)指定圖案填充的矩形 */
             
              glColor3f(0.1,0.8,0.7);
              glEnable (GL_POLYGON_STIPPLE);
              glPolygonStipple (pattern);
              glRectf (48.0, 80.0, 210.0, 305.0);
             
              /* 繪制一個(gè)指定圖案填充的三角形 */
              glColor3f(0.9,0.86,0.4);
              glPolygonStipple (pattern);
              glBegin(GL_TRIANGLES);
              glVertex2i(310,310);
              glVertex2i(220,80);
              glVertex2i(405,80);
              glEnd();
             
              glDisable (GL_POLYGON_STIPPLE);
             
              glFlush ();
            }
             
            void main(void)
            {
              auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
              auxInitPosition (0, 0, 500, 400);
              auxInitWindow ("Polygon Stippling");
              myinit ();
              auxMainLoop(display);
            }
            圖13-2 圖案填充多邊形

            13.2、法向計(jì)算
              法向,又稱法向量(Mormal Vector)。對(duì)于一個(gè)平面,其上各點(diǎn)的法向的一樣,統(tǒng)一為這個(gè)平面的法向,所以稱為平面法向。對(duì)于一個(gè)曲面,雖然它在計(jì)算機(jī)圖形中是由許多片小的平面多邊形逼近,但是每個(gè)頂點(diǎn)的法向都不一樣,因此曲面上每個(gè)點(diǎn)的法向計(jì)算就可以根據(jù)不同的應(yīng)用有不同的算法,則最后效果也不相同。OpenGL有很大的靈活性,它只提供賦予當(dāng)前頂點(diǎn)法向的函數(shù),并不在內(nèi)部具體計(jì)算其法向量,這個(gè)值由編程者自己根據(jù)需要計(jì)算。下面介紹一下法向基本計(jì)算方法和OpenGL法向定義。

              13.2.1 法向基本計(jì)算方法
              首先,講述平面法向的計(jì)算方法。在一個(gè)平面內(nèi),有兩條相交的線段,假設(shè)其中一條為矢量W,另一條為矢量V,且平面法向?yàn)镹,如圖13-3所示,則平面法向就等于兩個(gè)矢量的叉積(遵循右手定則),即N=WxV。

             
            圖13-3 平面法向計(jì)算

              比如計(jì)算一個(gè)三角形平面的法向,就可以用它的三個(gè)頂點(diǎn)來(lái)計(jì)算,如圖13-4所示。

             
            圖13-4 三角形平面法向計(jì)算

              設(shè)三個(gè)頂點(diǎn)分別為P0、P1、P2,相應(yīng)兩個(gè)向量為W、V,則三角平面法向的計(jì)算方式見(jiàn)下列一段代碼:
            /* ------ get value of N (normal vector) ---------- */
            void getNormal(GLfloat gx[3],GLfloat gy[3],GLfloat gz[3],GLfloat *ddnv)
            {
              GLfloat w0,w1,w2,v0,v1,v2,nr,nx,ny,nz;
             
              w0=gx[0]-gx[1]; w1=gy[0]-gy[1]; w2=gz[0]-gz[1];
              v0=gx[2]-gx[1]; v1=gy[2]-gy[1]; v2=gz[2]-gz[1];
              nx=(w1*v2-w2*v1);
              ny=(w2*v0-w0*v2);
              nz=(w0*v1-w1*v0);
              nr=sqrt(nx*nx+ny*ny+nz*nz);
              ddnv[0]=nx/nr; ddnv[1]=ny/nr; ddnv[2]=nz/nr;
            }
              以上函數(shù)的輸出參數(shù)為指針ddnv,它指向法向的三個(gè)分量,并且程序中已經(jīng)將法向單位化(或歸一化)了。
              此外,對(duì)于曲面各頂點(diǎn)的法向計(jì)算有很多種,最常用的是平均平面法向法,如圖15-5 所示。在圖中,曲面頂點(diǎn)P的法向就等于其相鄰的四個(gè)平面的法向平均值,即:

             
            Np = (N1+N2+N3+N4)/4

             
            圖13-5 曲面頂點(diǎn)的平均法向計(jì)算

              13.2.2 法向定義
              OpenGL法向定義函數(shù)為:

              void glNormal3{bsifd}(TYPE nx,TYPE ny,TYPE nz);
              void glNormal3{bsifd}v(const TYPE *v);


              設(shè)置當(dāng)前法向值。非向量形式定義法向采用第一種方式,即在函數(shù)中分別給出法向三個(gè)分量值nx、ny和nz;向量形式定義采用第二種,即將v設(shè)置為一個(gè)指向擁有三個(gè)元素的指針,例如v[3]={nx,ny,nz}。因?yàn)榉ㄏ虻母鞣至恐抵欢x法向的方向,因此它的大小不固定,但建議最好將各值限制在[-1.0,1.0]之間,即法向歸一化;若法向不歸一化,則在定義法向之前必須啟動(dòng)法向歸一,即調(diào)用函數(shù)glEnable(GL_NORMALIZE),這樣會(huì)降低整個(gè)程序運(yùn)行性能。下面舉出一個(gè)自己定義法向的例子:

              例13-3 自定義顏色立方體法向例程nmlcolr.c
             
            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
             
            static GLfloat p1[]={0.5,-0.5,-0.5}, p2[]={0.5,0.5,-0.5},
              p3[]={0.5,0.5,0.5},  p4[]={0.5,-0.5,0.5},
                p5[]={-0.5,-0.5,0.5}, p6[]={-0.5,0.5,0.5},
                p7[]={-0.5,0.5,-0.5}, p8[]={-0.5,-0.5,-0.5};
             
            static GLfloat m1[]={1.0,0.0,0.0},  m2[]={-1.0,0.0,0.0},
              m3[]={0.0,1.0,0.0},  m4[]={0.0,-1.0,0.0},
                m5[]={0.0,0.0,1.0},  m6[]={0.0,0.0,-1.0};
             
            static GLfloat c1[]={0.0,0.0,1.0},  c2[]={0.0,1.0,1.0},
              c3[]={1.0,1.0,1.0},  c4[]={1.0,0.0,1.0},
                c5[]={1.0,0.0,0.0},  c6[]={1.0,1.0,0.0},
                c7[]={0.0,1.0,0.0},  c8[]={1.0,1.0,1.0};
             
            void myinit(void);
            void CALLBACK myReshape(GLsizei w, GLsizei h);
            void CALLBACK display(void);
            void DrawColorBox(void);
             
            void myinit(void)
            {
              GLfloat light_ambient[]={0.3,0.2,0.5};
              GLfloat light_diffuse[]={1.0,1.0,1.0};
              GLfloat light_position[] = { 2.0, 2.0, 2.0, 1.0 };
             
              GLfloat light1_ambient[]={0.3,0.3,0.2};
              GLfloat light1_diffuse[]={1.0,1.0,1.0};
              GLfloat light1_position[] = { -2.0, -2.0, -2.0, 1.0 };
             
              glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
              glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
              glLightfv(GL_LIGHT0, GL_POSITION, light_position);
             
              glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
              glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
              glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
             
              glEnable(GL_LIGHTING);
              glEnable(GL_LIGHT0);
              glEnable(GL_LIGHT1);
             
              glDepthFunc(GL_LESS);
              glEnable(GL_DEPTH_TEST);
             
              glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
              glEnable(GL_COLOR_MATERIAL);
            }
             
            void CALLBACK display(void)
            {
              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             
              glPushMatrix();
              glRotatef(45,0.0,1.0,0.0);
              glRotatef(315,0.0,0.0,1.0);
              DrawColorBox();
              glPopMatrix();
             
              glFlush();
            }
             
            void CALLBACK myReshape(GLsizei w, GLsizei h)
            {
              glViewport(0, 0, w, h);
              glMatrixMode(GL_PROJECTION);
              glLoadIdentity();
              if (w <= h)
                glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,1.50*(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 DrawColorBox(void)
            {
              glBegin (GL_QUADS);
              glColor3fv(c1);
              glNormal3fv(m1);
              glVertex3fv(p1);
              glColor3fv(c2);
              glVertex3fv(p2);
              glColor3fv(c3);
              glVertex3fv(p3);
              glColor3fv(c4);
              glVertex3fv(p4);
             
              glColor3fv(c5);
              glNormal3fv(m5);
              glVertex3fv(p5);
              glColor3fv(c6);
              glVertex3fv(p6);
              glColor3fv(c7);
              glVertex3fv(p7);
              glColor3fv(c8);
              glVertex3fv(p8);
             
              glColor3fv(c5);
              glNormal3fv(m3);
              glVertex3fv(p5);
              glColor3fv(c6);
              glVertex3fv(p6);
              glColor3fv(c3);
              glVertex3fv(p3);
              glColor3fv(c4);
              glVertex3fv(p4);
             
              glColor3fv(c1);
              glNormal3fv(m4);
              glVertex3fv(p1);
              glColor3fv(c2);
              glVertex3fv(p2);
              glColor3fv(c7);
              glVertex3fv(p7);
              glColor3fv(c8);
              glVertex3fv(p8);
             
              glColor3fv(c2);
              glNormal3fv(m5);
              glVertex3fv(p2);
              glColor3fv(c3);
              glVertex3fv(p3);
              glColor3fv(c6);
              glVertex3fv(p6);
              glColor3fv(c7);
              glVertex3fv(p7);
             
              glColor3fv(c1);
              glNormal3fv(m6);
              glVertex3fv(p1);
              glColor3fv(c4);
              glVertex3fv(p4);
              glColor3fv(c5);
              glVertex3fv(p5);
              glColor3fv(c8);
             
              glEnd();
            }
             
            void main(void)
            {
              auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
              auxInitPosition (0, 0, 500,400);
              auxInitWindow ("ColorBox");
              myinit();
              auxReshapeFunc (myReshape);
              auxMainLoop(display);
            }
             以上程序運(yùn)行結(jié)果是一個(gè)自定義法向的彩色正方體,其中每個(gè)頂點(diǎn)的顏色值不一樣,且為光滑的明暗處理模式。

             
            圖13-6 自定義法向的彩色立方體

            13.3、曲線生成
              計(jì)算機(jī)圖形學(xué)中,所有的光滑曲線都采用線段逼近來(lái)模擬,而且許多有用的曲線在數(shù)學(xué)上只用少數(shù)幾個(gè)參數(shù)(如控制點(diǎn)等)來(lái)描述。本節(jié)簡(jiǎn)要地介紹一下OpenGL中Bezier曲線的繪制方法。

              13.3.1 曲線繪制舉例
              下面我們來(lái)看一個(gè)簡(jiǎn)單的例子,這是用四個(gè)控制頂點(diǎn)來(lái)畫一條三次Bezier曲線。程序如下:

              例13-4 Bezier曲線繪制例程bzcurve.c
            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
             
            void myinit(void);
            void CALLBACK myReshape(GLsizei w, GLsizei h);
            void CALLBACK display(void);
             
            GLfloat ctrlpoints[4][3] = {
              { -4.0, -4.0, 0.0 }, { -2.0, 4.0, 0.0 },
              { 2.0, -4.0, 0.0 }, { 4.0, 4.0, 0.0 }
            };
             
            void myinit(void)
            {
              glClearColor(0.0, 0.0, 0.0, 1.0);
              glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
              glEnable(GL_MAP1_VERTEX_3);
              glShadeModel(GL_FLAT);
            }
             
            void CALLBACK display(void)
            {
              int i;
             
              glClear(GL_COLOR_BUFFER_BIT);
              glColor3f(1.0, 1.0, 1.0);
              glBegin(GL_LINE_STRIP);
              for (i = 0; i <= 30; i++)
                glEvalCoord1f((GLfloat) i/30.0);
              glEnd();
             
              /* 顯示控制點(diǎn) */
              glPointSize(5.0);
              glColor3f(1.0, 1.0, 0.0);
              glBegin(GL_POINTS);
              for (i = 0; i < 4; i++)
                glVertex3fv(&ctrlpoints[i][0]);
              glEnd();
              glFlush();
            }
             
            void CALLBACK myReshape(GLsizei w, GLsizei h)
            {
              glViewport(0, 0, w, h);
              glMatrixMode(GL_PROJECTION);
              glLoadIdentity();
              if (w <= h)
                glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w, 5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
              else
                glOrtho(-5.0*(GLfloat)w/(GLfloat)h, 5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
              glMatrixMode(GL_MODELVIEW);
              glLoadIdentity();
            }
             
            void main(void )
            {
              auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
              auxInitPosition (0, 0, 500, 500);
              auxInitWindow ("Bezier Curves");
              myinit();
              auxReshapeFunc (myReshape);
              auxMainLoop(display);
            }
            圖13-7 一條光滑的Bezier曲線

              13.3.2 曲線定義和啟動(dòng)
              OpenGL中曲線定義的函數(shù)為:
            void glMap1{fd}(GLenum target,TYPE u1,TYPE u2,GLint stride, GLint order,const TYPE *points);
              函數(shù)的第一個(gè)參數(shù)target指出控制頂點(diǎn)的意義以及在參數(shù)points中需要提供多少值,具體值見(jiàn)表13-1所示。參數(shù)points指針可以指向控制點(diǎn)集、RGBA顏色值或紋理坐標(biāo)串等。例如若target是GL_MAP1_COLOR_4,則就能在RGBA四維空間中生成一條帶有顏色信息的曲線,這在數(shù)據(jù)場(chǎng)可視化中應(yīng)用極廣。參數(shù)u1和u2,指明變量U的范圍,U一般從0變化到1。參數(shù)stride是跨度,表示在每塊存儲(chǔ)區(qū)內(nèi)浮點(diǎn)數(shù)或雙精度數(shù)的個(gè)數(shù),即兩個(gè)控制點(diǎn)間的偏移量,比如上例中的控制點(diǎn)集ctrpoint[4][3]的跨度就為3,即單個(gè)控制點(diǎn)的坐標(biāo)元素個(gè)數(shù)。函數(shù)參數(shù)order是次數(shù)加1,叫階數(shù),與控制點(diǎn)數(shù)一致。

             
            參數(shù) 意義
            GL_MAP1_VERTEX_3 x,y,z 頂點(diǎn)坐標(biāo)
            GL_MAP1_VERTEX_4 x,y,z,w 頂點(diǎn)坐標(biāo)
            GL_MAP1_INDEX 顏色表
            GL_MAP1_COLOR_4 R,G,B,A
            GL_MAP1_NORMAL 法向量
            GL_MAP1_TEXTURE_COORD_1 s    紋理坐標(biāo)
            GL_MAP1_TEXTURE_COORD_2 s,t   紋理坐標(biāo)
            GL_MAP1_TEXTURE_COORD_3 s,t,r  紋理坐標(biāo)
            GL_MAP1_TEXTURE_COORD_4 s,t,r,q 紋理坐標(biāo)
            表13-1 用于glMap1*()控制點(diǎn)的數(shù)據(jù)類型

              曲線定義后,必須要啟動(dòng),才能進(jìn)行下一步的繪制工作。啟動(dòng)函數(shù)仍是glEnable(),其中參數(shù)與glMap1*()的第一個(gè)參數(shù)一致。同樣,關(guān)閉函數(shù)為glDisable(),參數(shù)也一樣。

              13.3.3 曲線坐標(biāo)計(jì)算
              這里提到的坐標(biāo)概念是廣義的,與以前定義的有點(diǎn)不同,具體地說(shuō)就是表13-1所對(duì)應(yīng)的類型值。OpenGL曲線坐標(biāo)計(jì)算的函數(shù)形式如下:
            void glEvalCoord1{fd}[v](TYPE u);

              產(chǎn)生曲線坐標(biāo)值并繪制。參數(shù)u是定義域內(nèi)的值,這個(gè)函數(shù)調(diào)用一次只產(chǎn)生一個(gè)坐標(biāo)。

              13.3.4 定義均勻間隔曲線坐標(biāo)值
              在使用glEvalCoord1*()計(jì)算坐標(biāo),因?yàn)閡可取定義域內(nèi)的任意值,所以由此計(jì)算出的坐標(biāo)值也是任意的。但是,目前用得最普遍的仍是取等間隔值。要獲得等間隔值,OpenGL提供了兩個(gè)函數(shù),即先調(diào)用glMapGrid1*()定義一個(gè)一維網(wǎng)格,然后用glEvalMesh1()計(jì)算響應(yīng)的坐標(biāo)值。下面詳細(xì)解釋這兩個(gè)函數(shù):
             

            void glMapGrid1{fd}(GLint n,TYPE u1,TYPE u2);

             定義一個(gè)網(wǎng)格,從u1到u2分為n步,它們是等間隔的。實(shí)際上,這個(gè)函數(shù)定義的是參數(shù)空間網(wǎng)格。
             

            void glEvalMesh1(GLenum mode,GLint p1,GLint p2);

              計(jì)算并繪制坐標(biāo)點(diǎn)。參數(shù)mode可以是GL_POINT或GL_LINE,即沿曲線繪制點(diǎn)或沿曲線繪制相連的線段。這個(gè)函數(shù)的調(diào)用效果同在p1和p2之間的每一步給出一個(gè)glEvalCoord1()的效果一樣。從編程角度來(lái)說(shuō),除了當(dāng)i=0或i=n,它準(zhǔn)確以u(píng)1或u2作為參數(shù)調(diào)用glEvalCoord1()之外,它等價(jià)于一下代碼:

            glBegin(GL_POINT);/* glBegin(GL_LINE_STRIP); */
            for(i=p1;i<=p2;i++)
               glEvalCoord1(u1+i*(u2-u1)/n);
            glEnd();

            13.4、曲面構(gòu)造
              同樣,計(jì)算機(jī)圖形學(xué)中的所有光滑曲面也都采用多邊形逼近來(lái)繪制,而且許多有用的曲面在數(shù)學(xué)上也只用少數(shù)幾個(gè)參數(shù)(如控制點(diǎn)或網(wǎng)等)來(lái)描述。通常,若用16個(gè)控制點(diǎn)描述一個(gè)曲面,要比用1000多個(gè)三角形和每個(gè)頂點(diǎn)的法向信息要節(jié)省很多內(nèi)存。而且,1000個(gè)三角形僅僅只逼近曲面,而控制點(diǎn)可以精確地描述實(shí)際曲面,且可自動(dòng)計(jì)算法向。本節(jié)簡(jiǎn)要地介紹一下OpenGL中Bezier曲面的繪制方法,所有相關(guān)的函數(shù)都與曲線的情況類似,只是二維空間而已。

              13.4.1 曲面定義和坐標(biāo)計(jì)算
              曲面定義函數(shù)為:
             

            void glMap2{fd}(GLenum target,TYPE u1,TYPE u2,GLint ustride,GLint uorder,
            TYPE v1,TYPE v2,GLint vstride,GLint vorder,TYPE points);

              參數(shù)target可以是表13-1中任意值,不過(guò)需將MAP1改為MAP2。同樣,啟動(dòng)曲面的函數(shù)仍是glEnable(),關(guān)閉是glDisable()。u1、u2為u的最大值和最小值;v1、v2為v的最大值和最小值。參數(shù)ustride和vstride指出在控制點(diǎn)數(shù)組中u和v向相鄰點(diǎn)的跨度,即可從一個(gè)非常大的數(shù)組中選擇一塊控制點(diǎn)長(zhǎng)方形。例如,若數(shù)據(jù)定義成如下形式:

             

            GLfloat ctlpoints[100][100][3];

              并且,要用從ctlpoints[20][30]開(kāi)始的4x4子集,選擇ustride為100*3,vstride為3,初始點(diǎn)設(shè)置為ctlpoints[20][30][0]。最后的參數(shù)都是階數(shù),uorder和vorder,二者可以不同。曲面坐標(biāo)計(jì)算函數(shù)為:
             

            void glEvalCoord2{fd}[v](TYPE u,TYPE v);

              產(chǎn)生曲面坐標(biāo)并繪制。參數(shù)u和v是定義域內(nèi)的值。下面看一個(gè)繪制Bezier曲面的例子:

              例13-5 Bezier網(wǎng)狀曲面繪制例程bzwiresf.c
             

            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
             
            void myinit(void);
            void CALLBACK myReshape(GLsizei w, GLsizei h);
            void CALLBACK display(void);
             
            /* 控制點(diǎn)的坐標(biāo) */
            GLfloat ctrlpoints[4][4][3] = {
              {{-1.5, -1.5, 2.0}, {-0.5, -1.5, 2.0},
              {0.5, -1.5, -1.0}, {1.5, -1.5, 2.0}},
              {{-1.5, -0.5, 1.0}, {-0.5, 1.5, 2.0},
              {0.5, 0.5, 1.0}, {1.5, -0.5, -1.0}},
              {{-1.5, 0.5, 2.0}, {-0.5, 0.5, 1.0},
              {0.5, 0.5, 3.0}, {1.5, -1.5, 1.5}},
              {{-1.5, 1.5, -2.0}, {-0.5, 1.5, -2.0},
              {0.5, 0.5, 1.0}, {1.5, 1.5, -1.0}}
            };
             
            void myinit(void)
            {
              glClearColor (0.0, 0.0, 0.0, 1.0);
              glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlpoints[0][0][0]);
              glEnable(GL_MAP2_VERTEX_3);
              glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);
              glEnable(GL_DEPTH_TEST);
            }
             
            void CALLBACK display(void)
            {
              int i, j;
             
              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             
              glColor3f(0.3, 0.6, 0.9);
              glPushMatrix ();
              glRotatef(35.0, 1.0, 1.0, 1.0);
              for (j = 0; j <= 8; j++)
              {
                glBegin(GL_LINE_STRIP);
                for (i = 0; i <= 30; i++)
                  glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/8.0);
                glEnd();
             
                glBegin(GL_LINE_STRIP);
                for (i = 0; i <= 30; i++)
                  glEvalCoord2f((GLfloat)j/8.0, (GLfloat)i/30.0);
                glEnd();
              }
              glPopMatrix ();
              glFlush();
            }
             
            void CALLBACK myReshape(GLsizei w, GLsizei h)
            {
              glViewport(0, 0, w, h);
              glMatrixMode(GL_PROJECTION);
              glLoadIdentity();
              if (w <= h)
                glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0);
              else
                glOrtho(-4.0*(GLfloat)w/(GLfloat)h, 4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);
              glMatrixMode(GL_MODELVIEW);
              glLoadIdentity();
            }
             
            void main(void)
            {
              auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
              auxInitPosition (0, 0, 500, 500);
              auxInitWindow ("Wireframe Bezier Surface");
              myinit();
              auxReshapeFunc (myReshape);
              auxMainLoop(display);
            }
              以上程序運(yùn)行結(jié)果是一個(gè)網(wǎng)狀的曲面。

             
            圖13-8 Bezier網(wǎng)狀曲面

              13.4.2 定義均勻間隔的曲面坐標(biāo)值
              OpenGL中定義均勻間隔的曲面坐標(biāo)值的函數(shù)與曲線的類似,其函數(shù)形式為:
             
            void glMapGrid2{fd}(GLenum nu,TYPE u1,TYPE u2, GLenum nv,TYPE v1,TYPE v2);
            void glEvalMesh2(GLenum mode,GLint p1,GLint p2,GLint q1,GLint q2);

              第一個(gè)函數(shù)定義參數(shù)空間的均勻網(wǎng)格,從u1到u2分為等間隔的nu步,從v1到v2分為等間隔的nv步,然后glEvalMesh2()把這個(gè)網(wǎng)格應(yīng)用到已經(jīng)啟動(dòng)的曲面計(jì)算上。第二個(gè)函數(shù)參數(shù)mode除了可以是GL_POINT和GL_LINE外,還可以是GL_FILL,即生成填充空間曲面。下面舉出一個(gè)用網(wǎng)格繪制一個(gè)經(jīng)過(guò)光照和明暗處理的Bezier曲面的例程:

              例13-6 加光照的均勻格網(wǎng)Bezier曲面繪制例程bzmesh.c
             

            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
             
            void myinit(void);
            void initlights(void);
            void CALLBACK myReshape(GLsizei w, GLsizei h);
            void CALLBACK display(void);
             
            /* 控制點(diǎn)坐標(biāo) */
             
            GLfloat ctrlpoints[4][4][3] = {
              {{-1.5, -1.5, 2.0}, {-0.5, -1.5, 2.0},
              {0.5, -1.5, -1.0}, {1.5, -1.5, 2.0}},
              {{-1.5, -0.5, 1.0}, {-0.5, 1.5, 2.0},
              {0.5, 0.5, 1.0}, {1.5, -0.5, -1.0}},
              {{-1.5, 0.5, 2.0}, {-0.5, 0.5, 1.0},
              {0.5, 0.5, 3.0}, {1.5, -1.5, 1.5}},
              {{-1.5, 1.5, -2.0}, {-0.5, 1.5, -2.0},
              {0.5, 0.5, 1.0}, {1.5, 1.5, -1.0}}
            };
             
            void initlights(void)
            {
              GLfloat ambient[] = { 0.4, 0.6, 0.2, 1.0 };
              GLfloat position[] = { 0.0, 1.0, 3.0, 1.0 };
              GLfloat mat_diffuse[] = { 0.2, 0.4, 0.8, 1.0 };
              GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
              GLfloat mat_shininess[] = { 80.0 };
             
              glEnable(GL_LIGHTING);
              glEnable(GL_LIGHT0);
             
              glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
              glLightfv(GL_LIGHT0, GL_POSITION, position);
             
              glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
              glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
              glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
            }
             
            void CALLBACK display(void)
            {
              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
              glPushMatrix();
              glRotatef(35.0, 1.0, 1.0, 1.0);
              glEvalMesh2(GL_FILL, 0, 20, 0, 20);
              glPopMatrix();
              glFlush();
            }
             
            void myinit(void)
            {
              glClearColor (0.0, 0.0, 0.0, 1.0);
              glEnable (GL_DEPTH_TEST);
              glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlpoints[0][0][0]);
              glEnable(GL_MAP2_VERTEX_3);
              glEnable(GL_AUTO_NORMAL);
              glEnable(GL_NORMALIZE);
              glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);
              initlights();
            }
             
            void CALLBACK myReshape(GLsizei w, GLsizei h)
            {
              glViewport(0, 0, w, h);
              glMatrixMode(GL_PROJECTION);
              glLoadIdentity();
              if (w <= h)
                glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0);
              else
                glOrtho(-4.0*(GLfloat)w/(GLfloat)h, 4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);
              glMatrixMode(GL_MODELVIEW);
              glLoadIdentity();
            }
             
            void main(void)
            {
              auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
              auxInitPosition (0, 0, 500, 500);
              auxInitWindow ("Lighted and Filled Bezier Surface");
              myinit();
              auxReshapeFunc (myReshape);
              auxMainLoop(display);
            }
              以上程序運(yùn)行結(jié)果是一個(gè)加上光影的曲面。

             
            圖13-9 帶光影的曲面

              13.4.3 紋理曲面
              在前面我們已經(jīng)講過(guò)紋理的用法,這一節(jié)將結(jié)合曲面的生成試試紋理的應(yīng)用。下面我們先看一個(gè)例子:

              例13-17 紋理曲面例程繪制texsurf.c
            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
            #include <math.h>
             
            void myinit(void);
            void makeImage(void);
            void CALLBACK display(void);
            void CALLBACK myReshape(GLsizei w, GLsizei h);
             
            GLfloat ctrlpoints[4][4][3] = {
              {{-1.5, -1.5, 2.0}, {-0.5, -1.5, 2.0},
              {0.5, -1.5, -1.0}, {1.5, -1.5, 2.0}},
              {{-1.5, -0.5, 1.0}, {-0.5, 1.5, 2.0},
              {0.5, 0.5, 1.0}, {1.5, -0.5, -1.0}},
              {{-1.5, 0.5, 2.0}, {-0.5, 0.5, 1.0},
              {0.5, 0.5, 3.0}, {1.5, -1.5, 1.5}},
              {{-1.5, 1.5, -2.0}, {-0.5, 1.5, -2.0},
              {0.5, 0.5, 1.0}, {1.5, 1.5, -1.0}} };
             
              GLfloat texpts[2][2][2] = {{{0.0, 0.0}, {0.0, 1.0}}, {{1.0, 0.0}, {1.0, 1.0}}};
             
              void CALLBACK display(void)
              {
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                glColor3f(1.0, 1.0, 1.0);
                glEvalMesh2(GL_FILL, 0, 20, 0, 20);
                glFlush();
              }
             
            #define imageWidth 64
            #define imageHeight 64
              GLubyte image[3*imageWidth*imageHeight];
             
              void makeImage(void)
              {
                int i, j;
                float ti, tj;
             
                for (i = 0; i < imageWidth; i++)
                {
                  ti = 2.0*3.14159265*i/imageWidth;
                  for (j = 0; j < imageHeight; j++)
                  {
                    tj = 2.0*3.14159265*j/imageHeight;
             
                    image[3*(imageHeight*i+j)] = (GLubyte) 127*(1.0+sin(ti));
                    image[3*(imageHeight*i+j)+1] = (GLubyte) 127*(1.0+cos(2*tj));
                    image[3*(imageHeight*i+j)+2] = (GLubyte) 127*(1.0+cos(ti+tj));
                  }
                }
              }
             
              void myinit(void)
              {
                glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlpoints[0][0][0]);
                glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, &texpts[0][0][0]);
                glEnable(GL_MAP2_TEXTURE_COORD_2);
                glEnable(GL_MAP2_VERTEX_3);
                glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);
                makeImage();
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                glTexImage2D(GL_TEXTURE_2D, 0, 3, imageWidth, imageHeight, 0,
                  GL_RGB, GL_UNSIGNED_BYTE, image);
                glEnable(GL_TEXTURE_2D);
                glEnable(GL_DEPTH_TEST);
                glEnable(GL_NORMALIZE);
                glShadeModel (GL_FLAT);
              }
             
              void CALLBACK myReshape(GLsizei w, GLsizei h)
              {
                glViewport(0, 0, w, h);
                glMatrixMode(GL_PROJECTION);
                glLoadIdentity();
                if (w <= h)
                  glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0);
                else
                  glOrtho(-4.0*(GLfloat)w/(GLfloat)h, 4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);
                glMatrixMode(GL_MODELVIEW);
                glLoadIdentity();
                glRotatef(35.0, 1.0, 1.0, 1.0);
              }
             
              void main(void)
              {
                auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
                auxInitPosition (0, 0, 500, 400);
                auxInitWindow ("Texture Surface");
                myinit();
                auxReshapeFunc (myReshape);
                auxMainLoop(display);
              }
             
              以上程序運(yùn)行結(jié)果是一個(gè)帶紋理的曲面。

             
            圖13-10 帶紋理的曲面

              13.4.4 NURBS曲面
              OpenGL的功能庫(kù)提供了一系列NURBS曲面(非均勻有理B樣條曲面)的函數(shù)。本節(jié)不具體講各函數(shù)的用法,僅舉出一個(gè)應(yīng)用例子,其余的讀者可以參考有關(guān)手冊(cè)。例程如下:

              例13-8 NURBS曲面繪制例程nurbsurf.c
            #include "glos.h"
            #include <GL/gl.h>
            #include <GL/glu.h>
            #include <GL/glaux.h>
             
            void myinit(void);
            void init_surface(void);
            void CALLBACK display(void);
            void CALLBACK myReshape(GLsizei w, GLsizei h);
             
            GLfloat ctlpoints[4][4][3];
             
            GLUnurbsObj *theNurb;
             
            /* 初始化控制點(diǎn)坐標(biāo),x,y,z范圍從-3到3 */
             
            void init_surface(void)
            {
              int u, v;
              for (u = 0; u < 4; u++)
              {
                for (v = 0; v < 4; v++)
                {
                  ctlpoints[u][v][0] = 2.0*((GLfloat)u - 1.5);
                  ctlpoints[u][v][1] = 2.0*((GLfloat)v - 1.5);
             
                  if ( (u == 1 || u == 2) && (v == 1 || v == 2))
                    ctlpoints[u][v][2] = 3.0;
                  else
                    ctlpoints[u][v][2] = -3.0;
                }
              }
            }
             
            /* 定義曲面材質(zhì) (金色) */
             
            void myinit(void)
            {
              GLfloat mat_diffuse[] = { 0.88, 0.66, 0.22, 1.0 };
              GLfloat mat_specular[] = { 0.92, 0.9, 0.0, 1.0 };
              GLfloat mat_shininess[] = { 80.0 };
             
              glClearColor (0.0, 0.0, 0.0, 1.0);
              glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
              glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
              glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glEnable(GL_LIGHTING);
             
              glEnable(GL_LIGHT0);
              glDepthFunc(GL_LESS);
              glEnable(GL_DEPTH_TEST);
              glEnable(GL_AUTO_NORMAL);
              glEnable(GL_NORMALIZE);
             
              init_surface();
             
              theNurb = gluNewNurbsRenderer();
              gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 25.0);
              gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
            }
             
            void CALLBACK display(void)
            {
              GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
             
              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             
              glPushMatrix();
              glRotatef(330.0, 1.,0.,0.);
              glScalef (0.5, 0.5, 0.5);
             
              gluBeginSurface(theNurb);
              gluNurbsSurface(theNurb,
                8,
                knots,
                8,
                knots,
                4 * 3,
                3,
                &ctlpoints[0][0][0],
                4, 4,
                GL_MAP2_VERTEX_3);
              gluEndSurface(theNurb);
             
              glPopMatrix();
              glFlush();
            }
             
            void CALLBACK myReshape(GLsizei w, GLsizei h)
            {
              glViewport(0, 0, w, h);
              glMatrixMode(GL_PROJECTION);
              glLoadIdentity();
              gluPerspective (45.0, (GLdouble)w/(GLdouble)h, 3.0, 8.0);
             
              glMatrixMode(GL_MODELVIEW);
              glLoadIdentity();
              glTranslatef (0.0, 1.0, -5.0);
            }
             
            void main(void)
            {
              auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
              auxInitPosition (0, 0, 500, 500);
              auxInitWindow ("NURBS Surface");
              myinit();
              auxReshapeFunc (myReshape);
              auxMainLoop(display);
            }
              以上程序運(yùn)行結(jié)果是一個(gè)銀白色的NURBS曲面。

             
            圖13-11 NURBS曲面

            posted on 2006-01-17 01:08 zmj 閱讀(4808) 評(píng)論(5)  編輯 收藏 引用

            評(píng)論

            # re: OpenGL復(fù)雜物體建模 2008-03-15 09:19 Nico

            怎么現(xiàn)在cppblog 上所有的圖片都不能顯示了?
            網(wǎng)站的問(wèn)題? 還是我的瀏覽器到問(wèn)題?
            這兩天正在看OpenGL相關(guān)的東西,在這里學(xué)到了很多了!
            這些博主太敬業(yè)了,感動(dòng),感謝!
              回復(fù)  更多評(píng)論   

            # re: OpenGL復(fù)雜物體建模 2008-03-22 13:36 李瑞坤

            我也看不到  回復(fù)  更多評(píng)論   

            # re: OpenGL復(fù)雜物體建模 2009-01-02 14:38 chensavvy

            請(qǐng)問(wèn)glos.h頭文件的作用,可以提夠么?  回復(fù)  更多評(píng)論   

            # re: OpenGL復(fù)雜物體建模 2009-07-13 10:43 lyf

            是啊,圖片都看不到,不知道什么效果。  回復(fù)  更多評(píng)論   

            # re: OpenGL復(fù)雜物體建模 2012-02-13 22:59 qq253857838

            為什么不做圖形學(xué)?why???  回復(fù)  更多評(píng)論   


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            久久99精品久久久久久动态图| 成人a毛片久久免费播放| 色婷婷噜噜久久国产精品12p| 久久国产三级无码一区二区| 久久亚洲色一区二区三区| 亚洲精品无码久久久久去q | 91久久精一区二区三区大全| 国产精品九九久久免费视频| 久久精品国产99国产精品亚洲 | 欧美精品福利视频一区二区三区久久久精品 | 国内精品久久久久久久亚洲| 亚洲欧洲久久av| 国产精品一区二区久久精品无码 | 久久精品亚洲一区二区三区浴池| 青青青青久久精品国产h| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 久久久久亚洲精品男人的天堂| 国产激情久久久久影院| 亚洲国产美女精品久久久久∴ | 青青青青久久精品国产h| 欧美色综合久久久久久| 99久久精品国产高清一区二区 | 精品久久久久久国产| 久久精品成人免费观看97| 人妻无码中文久久久久专区| 亚洲性久久久影院| 久久天天躁狠狠躁夜夜av浪潮| 欧美伊香蕉久久综合类网站| 2021少妇久久久久久久久久| 日韩人妻无码精品久久免费一| 中文字幕无码av激情不卡久久| 久久久99精品成人片中文字幕| 精品亚洲综合久久中文字幕| 99久久超碰中文字幕伊人| 欧美va久久久噜噜噜久久| 中文字幕热久久久久久久| 77777亚洲午夜久久多人| 97久久国产露脸精品国产| 久久国产欧美日韩精品| 亚洲女久久久噜噜噜熟女| 蜜臀av性久久久久蜜臀aⅴ麻豆|