OpenGL 二次曲面

來源:互聯網
上載者:User

原 文:Lesson 18: Quadrics
譯 者:sakura

  二次曲面是一種畫綜合物件的方法,這種方法通常並不需要很多的三角形。我們將要使用第七課的代碼。我們將要增加7個變數以及修改紋理以增加一些變化 :

  #include <windows.h>               // Header File For Windows
  #include <stdio.h>                // Header File For Standard Input/Output
  #include <gl/gl.h>                // Header File For The OpenGL32 Library
  #include <gl/glu.h>                // Header File For The GLu32 Library
  #include <gl/glaux.h>               // Header File For The GLaux Library

  HDC    hDC=NULL;               // Private GDI Device Context
  HGLRC   hRC=NULL;               // Permanent Rendering Context
  HWND    hWnd=NULL;               // Holds Our Window Handle
  HINSTANCE hInstance;               // Holds The Instance Of The Application

  bool  keys[256];                // Array Used For The Keyboard Routine
  bool  active=TRUE;               // Window Active Flag Set To TRUE By Default
  bool  fullscreen=TRUE;         // Fullscreen Flag Set To Fullscreen Mode By Default
  bool  light;                  // Lighting ON/OFF
  bool  lp;                    // L Pressed?
  bool  fp;                    // F Pressed?
  bool  sp;                    // Spacebar Pressed? ( NEW )

  int   part1;                  // Start Of Disc ( NEW )
  int   part2;                  // End Of Disc ( NEW )
  int   p1=0;                   // Increase 1 ( NEW )
  int   p2=1;                   // Increase 2 ( NEW )

  GLfloat xrot;                   // X Rotation
  GLfloat yrot;                   // Y Rotation
  GLfloat xspeed;                  // X Rotation Speed
  GLfloat yspeed;                  // Y Rotation Speed

  GLfloat z=-5.0f;                 // Depth Into The Screen

  GLUquadricObj *quadratic;             // Storage For Our Quadratic Objects ( NEW )

  GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };  // Ambient Light Values
  GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };  // Diffuse Light Values
  GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };  // Light Position

  GLuint filter;                     // Which Filter To Use
  GLuint texture[3];                   // Storage for 3 textures
  GLuint object=0;                    // Which Object To Draw ( NEW )

  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc

  好了我們現在開始搞InitGL()函數。我們打算增加3行代碼用來初始化我們的二次曲面。這3行代碼將在你使1號光源有效後增加,但是要在返回之前。第一行代碼將初始化二次曲面並且建立一個指向改二次曲面的指標,如果改二次曲面不能被建立的話,那麼該指標就是NULL。第二行代碼將在二次曲面的表面建立平滑的法向量,這樣當燈光照上去的時候將會好看些。另外一些可能的取值是:GLU_NONE和GLU_FLAT。最後我們使在二次曲面表面的紋理映射有效。

  quadratic=gluNewQuadric();          // Create A Pointer To The Quadric Object ( NEW )
  gluQuadricNormals(quadratic, GLU_SMOOTH);   // Create Smooth Normals ( NEW )
  gluQuadricTexture(quadratic, GL_TRUE);    // Create Texture Coords ( NEW )

  現在我決定在本課裡保留立方體,這樣你可以看到紋理是如何映射到二次曲面對象上的。而且我打算將繪製立方體的代碼定義為一個單獨的函數,這樣我們在定義函數Draw()的時候它將會變的不那麼淩亂。每個人都應該記住這些代碼:

  GLvoid glDrawCube()                          // Draw A Cube
  {
    glBegin(GL_QUADS);                         // Start Drawing Quads
      // Front Face
      glNormal3f( 0.0f, 0.0f, 1.0f);                // Normal Facing Forward
      glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);  // Bottom Left Of The Texture and Quad
      glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);  // Bottom Right Of The Texture and Quad
      glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);   // Top Right Of The Texture and Quad
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);   // Top Left Of The Texture and Quad
      // Back Face
      glNormal3f( 0.0f, 0.0f,-1.0f);                // Normal Facing Away
      glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Bottom Right Of The Texture and Quad
      glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);  // Top Right Of The Texture and Quad
      glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);  // Top Left Of The Texture and Quad
      glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Bottom Left Of The Texture and Quad
      // Top Face
      glNormal3f( 0.0f, 1.0f, 0.0f);                // Normal Facing Up
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);  // Top Left Of The Texture and Quad
      glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
      glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
      glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);  // Top Right Of The Texture and Quad
      // Bottom Face
      glNormal3f( 0.0f,-1.0f, 0.0f);                // Normal Facing Down
      glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Top Right Of The Texture and Quad
      glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Top Left Of The Texture and Quad
      glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);  // Bottom Left Of The Texture and Quad
      glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);  // Bottom Right Of The Texture and Quad
      // Right face
      glNormal3f( 1.0f, 0.0f, 0.0f);                // Normal Facing Right
      glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Bottom Right Of The Texture and Quad
      glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);  // Top Right Of The Texture and Quad
      glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);   // Top Left Of The Texture and Quad
      glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);  // Bottom Left Of The Texture and Quad
      // Left Face
      glNormal3f(-1.0f, 0.0f, 0.0f);                // Normal Facing Left
      glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Bottom Left Of The Texture and Quad
      glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);  // Bottom Right Of The Texture and Quad
      glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);   // Top Right Of The Texture and Quad
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);  // Top Left Of The Texture and Quad
    glEnd();                             // Done Drawing Quads
  }

  接下來就是情境繪製函數了,在這裡我唯寫一個簡單的例子。並且當我繪製一個部分的盤子的時候,我將使用一個靜態變數(一個局部的變數,該變數可以保留他的值不論你任何時候調用他)來表達一個非常酷的效果。為了清晰起見我將要重寫DrawGLScene函數。
  你們將會注意到當我討論這些正在使用的參數時我忽略了當前函數的第一個參數(quadratic)。這個參數將被除立方體外的所有對象使用。所以當我討論這些參數的時候我忽略了它。

  int DrawGLScene(GLvoid)                  // Here's Where We Do All The Drawing
  {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // Clear The Screen And The Depth Buffer
    glLoadIdentity();                   // Reset The View
    glTranslatef(0.0f,0.0f,z);               // Translate Into The Screen

    glRotatef(xrot,1.0f,0.0f,0.0f);            // Rotate On The X Axis
    glRotatef(yrot,0.0f,1.0f,0.0f);            // Rotate On The Y Axis

    glBindTexture(GL_TEXTURE_2D, texture[filter]);     // Select A Filtered Texture

    // This Section Of Code Is New ( NEW )
    switch(object)                     // Check object To Find Out What To Draw
    {
    case 0:                        // Drawing Object 1
      glDrawCube();                   // Draw Our Cube
      break;

  我們建立的第2個對象是一個圓柱體。參數1(1.0F)是圓柱體的底面半徑,參數2(1.0F)是圓柱體的餓頂面半徑,參數3(3.0F)是圓柱體的高度。參數4(32)是緯線(環繞Z軸有多少細分),參數5(32)是經線(沿著Z軸有多少細分)。細分越多該對象就越細緻。我們可以用增加細分的方法來增加對象的多邊形數。因此你可以犧牲速度換回品質(以時間換品質),大多數的時候我們都可以很容易的找到一個合適的“度”。

    case 1:                        // Drawing Object 2
      glTranslatef(0.0f,0.0f,-1.5f);           // Center The Cylinder
      gluCylinder(quadratic,1.0f,1.0f,3.0f,32,32);    // Draw Our Cylinder
      break;                       // Done

  對象3將會建立一個CD樣子的盤子。參數1(0.5F)是盤子的內圓半徑,該參數可以為0,則表示在盤子中間沒孔,內圓半徑越大孔越大。參數2(1.5F)表示外圓半徑,這個參數必須比內圓半徑大。參數3(32)是組成該盤子的切片的數量,這個數量可以想象成披薩餅中的切片的數量。切片越多,外圓邊緣就越平滑。最後一個參數(32)是組成盤子的環的數量。環很像唱片上的軌跡,一環套一環。這些環從內圓半徑細分到外圓半徑。再說一次,細分越多,速度越慢。

    case 2:                        // Drawing Object 3
      gluDisk(quadratic,0.5f,1.5f,32,32);        // Draw A Disc (CD Shape)
      break;                       // Done

  我們的第4個對象我知道你們為描述它耗盡精力。就是球。繪製球將會變的非常簡單。參數1是球的半徑。如果你無法理解半徑/直徑等等的話,可以理解成物體中心到物體外部的距離,在這裡我們使用1.3F作為半徑。接下來兩個參數就是細分了,和圓柱體一樣,參數2是緯線,參數3是經線。細分越多球看起來就越平滑,通常球需要多一些的細分以使他們看起來平滑。

    case 3:                        // Drawing Object 4
      gluSphere(quadratic,1.3f,32,32);          // Draw A Sphere
      break;                       // Done

  我們建立的第4個對象使用與我們曾經建立的圓柱體一樣的命令來建立,如果你還記得的話,我們可以通過控制參數2和參數3來控制頂面半徑和地面半徑。因此我們可以使頂面半徑為0來繪製一個圓錐體,頂面半徑為0將會在頂面上建立一個點。因此在下面的代碼中,我們使頂面半徑等於0,這將會建立一個點,同時也就建立了我們的圓錐。

    case 4:                        // Drawing Object 5
      glTranslatef(0.0f,0.0f,-1.5f);           // Center The Cone
      gluCylinder(quadratic,1.0f,0.0f,3.0f,32,32);    // A Cone With A Bottom Radius Of .5 And A Height Of 2
      break;                       // Done

  我們的第6個對象將被gluPartialDisk函數建立。我們打算建立的這個對象使用了一些命令,這些命令在我們建立對象之前,你將會清楚的看到。但是命令gluPartialDisk擁有兩個新的參數。第5個參數是我們想要繪製的部分盤子的開始角度,參數6是旋轉角,也就是轉過的角度。我們將要增加旋轉角,這將引起盤子沿順時針方向緩慢的被繪製在螢幕上。一旦旋轉角達到360度我們將開始增加開始角度,這樣盤子看起來就想是被逐漸的抹去一樣。我們將重複這些過程。

    case 5:                        // Drawing Object 6
      part1+=p1;                     // Increase Start Angle
      part2+=p2;                     // Increase Sweep Angle

      if(part1>359)                   // 360 Degrees
      {
        p1=0;                     // Stop Increasing Start Angle
        part1=0;                    // Set Start Angle To Zero
        p2=1;                     // Start Increasing Sweep Angle
        part2=0;                    // Start Sweep Angle At Zero
      }
      if(part2>359)                   // 360 Degrees
      {
        p1=1;                     // Start Increasing Start Angle
        p2=0;                     // Stop Increasing Sweep Angle
      }
      gluPartialDisk(quadratic,0.5f,1.5f,32,32,part1,part2-part1); // A Disk Like The One Before
      break;                       // Done
    };

    xrot+=xspeed;                     // Increase Rotation On X Axis
    yrot+=yspeed;                     // Increase Rotation On Y Axis
    return TRUE;                      // Keep Going
  }

  在最後,我給出鍵盤輸入代碼。僅僅增加一些對剩餘鍵的檢查。

  if (keys[' '] && !sp)                   // Is Spacebar Being Pressed?
  {
    sp=TRUE;                       // If So, Set sp To TRUE
    object++;                       // Cycle Through The Objects
    if(object>5)                     // Is object Greater Than 5?
      object=0;                     // If So, Set To Zero
  }
  if (!keys[' '])                      // Has The Spacebar Been Released?
  {
    sp=FALSE;                       // If So, Set sp To FALSE
  }

  這就是全部了。現在你可以在OpenGL中繪製二次曲面了。最後放上我的網站和Email(譯者:還是訪問我的網站或給我寫信吧)。

 

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/lovetangtang/archive/2006/01/16/580606.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.