路徑擠出(二)


在〈路徑擠出(一)〉中的實作,看來蠻合理的,有什麼問題嗎?有的!〈路徑擠出(一)〉中第一個範例的 path,如果繞 x 軸轉 90 度,也就是路徑在 xz 平面上就會出包!

那些斷裂處是怎麼回事呢?把圖放大一點來看:

路徑擠出(二)

仔細觀察斷裂處的線,應該可以看出切面的頂點幾乎連接至另一切面 180 度方向的頂點去了,想解釋這個原因很簡單,用來作為切面計算基礎的 circlePoints,它建立的圓是從 x 軸開始,繞著 z 軸逆時針排列而成,之後轉為面向 x 軸方向,來觀察索引 0 的點:

路徑擠出(二)

如果將繞 z 軸轉 180 度會如何?索引 0 會跑到另一側:

路徑擠出(二)

如果你為這兩個切面建立頂點索引,就會發生像是斷裂的圖案,當然,如果給的路徑是連續曲線,切面法向量不會直接繞 z 軸轉 180 度,上面的圖只是比較容易理解,真正的問題是法向量的 x 分量剛好是改變 180 度,例如,若前一個面是如下:

路徑擠出(二)

下個切面可能其實在方向上沒差太多,然而因為先轉 phi,再轉 theta 的關係,x 分量方向會是相反,也就會如下:

路徑擠出(二)

這時繪製出來的圖就會像是斷裂狀,這並不是實作有問題,也不是原理有問題,記得嗎?你只提供了路徑上每個點,並沒有提供如何翻轉切面的資訊,你只能猜想一種轉動切面的方式。

就目前的原理與實作而言,是將每個切面獨立處理,不考慮前後切面間的關係,才會發生這個問題,這確實是個缺點,然而也有優點,因為是獨立處理切面,也就可以保證,只要切面法向量相同,切面計算後就一定相同,對於封閉曲線,像是環面扭結(Torus knot),你會想要擠出後頭尾銜接,就會需要這種實作。

(〈路徑擠出(一)〉其實沒有針對封閉曲線做處理,記得嗎?第一個面的法向量與下個面的法向量是相同的,實際上環面扭結繞了一圈後,最後一個切面與第一個切面會有些偏差,但不會差太多就是了,如果想更精準,第一個面的法向量,可以由環面扭結路徑的最後一個點與第一個點來計算,這就交給你來試了,或許加個 closed 參數,來決定是不是構造封閉曲線的擠出,例如我的 dotSCADpath_extrude 模組就是這麼做的!)

就目前的實作方式,若路徑上連續兩個向量的 x 分量正好相反,就會發生這個問題,就許多曲線來說,這種情況不常發生,然而要是發生了,可以試著轉動整個路徑,讓路徑上連續兩個向量的 x 分量正好相反的情況消失,繪製完後再轉回來。

例如,假設你一開始是如上在 xz 平面上繪製路徑,若翻轉路徑使之在 xy 平面上,就沒有這個問題,也就是〈路徑擠出(一)〉中的第一個範例的結果了。

要記得!你只提供了路徑上每個點,並沒有提供如何翻轉切面的資訊,你只能猜想一種轉動切面的方式,若是用來畫出以下的螺旋,你覺得它是對的還是錯的繪製結果呢?

有時你猜想的轉動切面方式,正好對上了使用者想要的結果,使用者就會覺得它是對的,這只能說你腦補的結果正好對上,就路徑是螺旋而言,目前的路徑擠出實作方式,可能會符合大多數使用者對螺旋擠出時的想法,這也是目前實作方式的優點,也就是我說目前實作方式的原理並沒有錯的原因。

你可能會想,有沒有可能猜想的轉動切面方式,可以考量連續兩個切面間的關係,有的!這是下篇文件會看到的,它可以解決以上繪製結果可能發生斷裂狀的問題,然而,如果你用它來對螺旋路徑擠出又會如何呢?到時你會不會覺得,螺旋路徑擠出的結果不符合你想像,因而它的原理是錯的呢?