2011-02-23 80 views
5

所以我在玩OpenGL並試圖弄清楚如何繪製一些有趣的形狀。沿着路徑的OpenGL管道

現在,我正在試管。我可以得出一個直管只是罰款:

void tube(GLfloat radius, GLfloat segment_length) { 
    glPolygonMode(GL_BACK, GL_NONE); 
    glPolygonMode(GL_FRONT, GL_FILL); 

    glPushMatrix(); { 
     GLfloat z1 = 0.0; 
     GLfloat z2 = segment_length; 

     GLfloat y_offset = 0.0; 
     GLfloat y_change = 0.00; 

     int i = 0; 
     int j = 0; 
     for (j = 0; j < 20; j++) { 
      glPushMatrix(); { 
       glBegin(GL_TRIANGLE_STRIP); { 
        for (i = 360; i >= 0; i--) { 
         GLfloat theta = i * pi/180; 
         GLfloat x = radius * cos(theta); 
         GLfloat y = radius * sin(theta) + y_offset; 

         glVertex3f(x, y, z1); 
         glVertex3f(x, y, z2); 
        } 
       } glEnd(); 
      } glPopMatrix(); 

      // attach the front of the next segment to the back of the previous 
      z1 = z2; 
      z2 += segment_length; 

      // make some other adjustments 
      y_offset += y_change; 
     } 
    } glPopMatrix(); 
} 

不過,我還沒有想出如何使管跟隨像螺旋,甚至一個簡單的行中的任何預定義的路徑。如果將y_change更改爲0.01之類的值,則會在y方向上將每個管段偏移量再增加0.01。那很好,但是我怎樣才能使每個細分點朝着這個方向發展呢?換句話說,現在每個線段都被繪製成它們都面向相同的方向,並且方向不是管的方向(因爲y_change = 0.01,方向稍微向上)。

我不確定如何繼續。我通過獲取上一部分和當前部分之間的矢量來玩矢量,但我不確定該如何處理它。

+1

你看着(對於一個例子)紅皮書的圓環的例子嗎? http://www.opengl.org/resources/code/samples/redbook/torus.c –

回答

17

這個想法被稱爲路徑控制擠壓,即你有一個基本的n維形狀,並沿n + 1維曲線擠壓它。我可以讀你的臉:「呃,他在說什麼?」

所以這裏是一個粗略的輪廓。首先,您需要一個將通常稱爲t的值映射到空間中連續,平滑的曲線的函數。例如螺絲:

path(t): R → R³, t ↦ (a·sin(k·t), b·cos(k·t), c·t) 

的想法是,找一個局部座標基地有關定義到該路徑的頂點位置 - 它是有道理的,即座標一個平行對齊路徑,所以你想找到它的切線。在曲線的點t

tangent(t): R → R³, t ↦ (k·a·cos(k·t), -k·b·sin(k·t), c) = d/dt path(t) 

所以這就是會沿曲線指向當地的基本載體,與局部座標系的原點:這是通過查找它的梯度完成。

但是我們需要兩個其他向量來構成一個完整的3d基礎。它通常是一個不錯的選擇爲第二基點垂直曲率,您可以通過找到切線的捲曲得到:

normal(t): R → R³, t ↦ (-k²·a·sin(k·t), -k²·b·cos(k·t), 0) = d/dt tangent(t) = d²/dt² path(t) 

這就是所謂的正常。

可以得到第三個基矢量,取法線和切線的叉積,得到副法線。我會讓你把這一個看作是一個練習。

現在要沿着曲線擠出一個形狀,只需將t迭代到選定的範圍內,即可將路徑分割爲多個段,從而爲您提供本地原點。你的擠出形狀的點是相對於這個原點路徑(t)。比方說,你的形狀包括在隨後的X-Y平面P_N的要點:

for t in [k..l]: 
    for p in P_n: 
     yield_vertex(path(t).x + binormal(t).x * p.x, 
         path(t).y + normal(t).y * p.y, 
         path(t).z) 

我要把它留給你,找出如何將這些適應OpenGL的,畢竟你應該學會思考一些東西。如果直到明天才能解決問題,我會很樂意爲您提供解決方案,但通常您會更樂於通過自己的方式來解決問題。

+1

+1:優秀的答案。如果你對分段線性函數感興趣,你可以找到切線作爲v(n)(從最後一個點到這個向量)和v(n + 1)的平均值(從這個點開始的向量到下一個)。 –

+0

真棒,感謝這個答案。我將花一些時間來解決這個問題。我會告訴你我取得的進展(儘管學校和工作可能會消耗我爲此留出的一些娛樂時間)。 – gregghz

+0

是的,恐怕我的數學技能不符合這個(部分問題可能是我不完全理解你的符號)。我似乎無法將其轉換爲OpenGL,似乎無所謂,管段總是面向一個方向。 – gregghz