在OpenGL中如何根據空間兩點繪製圓柱

這幾天做項目時需要根據已知的兩個空間點AB繪製圓柱,琢磨了兩天,昨晚終於大功告成,貼出來跟大家分享分享,請大家多多指教!


如圖所示:

 

 

下面來介紹我們主要使用的幾個OpenGL函數:


auxSolidCylinder(GLfloat radius,GLfloat length)

繪製的圓柱的上底面是固定的,而且是固定在當前座標系中y=1.0f的平面上,以y軸爲軸,隨着指定高度的不同不斷地向y軸負方向延伸.(從上圖C點開始繪製)


glTranslatef(GLfloat x,GLfloat y,GLfloat z)

把當前矩陣和一個表示移動物體的矩陣相乘。三個參數分別表示了在三個座標上的位移值。


glRotatef(GLfloat angle,GLfloat x,GLfloat y,GLfloat z)

把當前矩陣和一個表示旋轉物體的矩陣相乘。物體將繞着(0,0,0)到(x,y,z)的直線以逆時針旋轉,參數angle表示旋轉的角度。

注意:glRotatef()只使物體繞過原點的直線旋轉,所以首先要把座標系移到這個側面的旋轉軸上.

 

 

 


 

 

 


 

// 起始線段:以C(0,1,0)爲起點,它的長度D(distance)通過目標線段計算,

//           終點座標爲(0,1-distance,0)

// 目標線段:以A(x1,y1,z1)爲起點,以B(x2,y2,z2)爲終點

 

 

 

目的:通過變換矩陣將起始線段CD平移、旋轉到目標線段AB

步驟:

      1.根據A、B兩點的座標求出圓柱長度distance,然後就可以求出D點的座標


 

      2.計算CD向量與AB向量的法向量(fx,fy,fz)以及CD與AB的夾角angle

        (1).求C'D',其中C'D'//CD,C'與A重合(這樣C'D'和AB就在一個平面上,這兩個空間線段的公共頂點是(2,4,5))

        (2).求C'D'和AB表示的“起始向量(sx,sy,sz)”和“目標向量(dx,dy,dz)”

        (3).由向量的叉積公式求出向量C'D'和向量AB的法向量(fx,fy,fz)

        (4).求出D'B的長度,這樣,三角形AD'B每條邊的長度都已知,根據三角形的餘弦定理,求出角D'AB的度


 

      3.將起始線段CD的起點移動到原點(0,0,0) 


 

      4.使用glRotatef將CD繞着法向量(fx,fy,fz)旋轉angle度,使CD與AB平行,即glRotatef(angel,fx,fy,fz)


 

 

      5.使用glTranslatef將旋轉後的CD平移到AB位置,平移量爲A點的座標,即glTranslatef(x1,y1,z1)


 

 


 

 

  1. // 根據空間兩點繪製圓柱  
  2. void   CPipeLineView::DrawChannel(GLfloat   x1, GLfloat   y1, GLfloat   z1,   GLfloat   x2,   GLfloat   y2,   GLfloat   z2   )   
  3. {   
  4.     // 起始線段:以(0,1,0)爲起點,它的長度(distance)通過目標線段計算,  
  5.     //           終點座標爲(0,1-distance,0)  
  6.     // 目標線段:以(x1,y1,z1)爲起點,以(x2,y2,z2)爲終點  
  7.     // 計算目標向量  
  8.     GLfloat   dx   =   x2   -   x1;   
  9.     GLfloat   dy   =   y2   -   y1;   
  10.     GLfloat   dz   =   z2   -   z1;  
  11.     // 算出目標向量模(即AB長度)  
  12.     GLfloat   distance  =  sqrt(dx*dx + dy*dy + dz*dz);   
  13.     // 計算平移量  
  14.     GLfloat  px = x1;  
  15.     GLfloat  py = y1 - 1;  
  16.     GLfloat  pz = z1;  
  17.     // 起始線段的末端點  
  18.     GLfloat  bx = px;    
  19.     GLfloat  by = (1-distance) + py;  
  20.     GLfloat  bz = pz;  
  21.     // 計算起始向量  
  22.     GLfloat  sx = bx - x1;  
  23.     GLfloat  sy = by - y1;  
  24.     GLfloat  sz = bz - z1;  
  25.     // 計算向量(sx,sy,sz)與向量(dx,dy,dz)的法向量(sy*dz - dy*sz,sz*dx - sx*dz,sx*dy - dx*sy)  
  26.     GLfloat fx = sy*dz - dy*sz;  
  27.     GLfloat fy = sz*dx - sx*dz;  
  28.     GLfloat fz = sx*dy - dx*sy;  
  29.     // 求兩向量間的夾角  
  30.     // 計算第三條邊的長度  
  31.     GLfloat ax = fabs(x2 - bx);  
  32.     GLfloat ay = fabs(y2 - by);  
  33.     GLfloat az = fabs(z2 - bz);  
  34.     GLfloat length = sqrt(ax*ax + ay*ay + az*az);  
  35.     // 根據餘弦定理計算夾角  
  36.     GLfloat angle = acos((distance*distance*2 - length*length)/(2*distance*distance))*180.0f/3.14159;  
  37.     // 繪製第一個點A   
  38.     glPushMatrix();   
  39.         glTranslatef(x1,y1,z1);   
  40.         auxSolidSphere(1);     
  41.     glPopMatrix();   
  42.     // 繪製圓柱   
  43.     glPushMatrix();   
  44.         // 變換的順序與函數書寫的順序相反,  
  45.         // 即先平移(0,-1,0),再繞法向量旋轉,最後再平移  
  46.         glTranslatef(x1,y1,z1);  
  47.         glRotatef(angle,fx,fy,fz);    
  48.         glTranslatef(0,-1,0);  
  49.         auxSolidCylinder(0.5,distance);  
  50.     glPopMatrix();  
  51.     // 繪製第二個點B  
  52.     glPushMatrix();   
  53.             glTranslatef(x2,y2,z2);   
  54.             auxSolidSphere(1);       
  55.     glPopMatrix();   
  56. };  


調用方法:

 


  1. DrawChannel(2,4,5,12,5,15);  

 

 

運行效果:

 

 

 

 

OK,OpenGL剛入門不久,請大家多多指教!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章