繪制順序(draw order)是如何影響 grasshopper 的計算順序的
一般情況下,grasshopper 的計算是沿著連接線從左至右進行的。首先被計算的是左邊的組件,然後觸發下遊組件,直到 canvas 全部計算完成為止。在你使用 grasshopper 幾個月之後,想都不用想就知道這是當然的。
直到有一天你想用 grasshopper 違反這個基本邏輯。我最近接到一個任務,需要用 Honybee 計算強光。強光計算組件使用了一個 Rhino 相機,這意味著當強光將要被正確計算的時候,相機要移動到正確的位置。
我決定使用霍斯特相機控制(Horseter camera control)來調整相機,於是就有了這麽個東西:
這個計算取決於相機 已經 被放置到正確的位置上。換句話來說,相機 必須
Grasshopper 首先計算的是哪一個組件?
首先講一點基礎知識。當 Grasshopper 計算組件的時候,有一個屬性叫做 expired(終止)。如果一個組件需要計算,它就會被標上 expired=true。如果組件已經更新了,不再需要計算,它就會被標上 expired=false。當你更改一個組件的時候(比如修改了它的輸入值),它就會被打上 expired 標誌。並且當一個組件被標誌為 expired,所有下遊組件(也就是右邊的組件)都會被標誌為 expired。
簡單來說,“expired”表明這個組件正在等待重算。
當 Grasshopper 有了一個已終止組件列表的時候,它必須決定以什麽方式去重算。Grasshopper 是從左至右進行重算的,從一個沒有已終止的輸入的組件開始。
對於大多數 Grasshopper 文件來說,這個解釋已經夠清楚了。但事實是,有更多復雜的算法在等著它。註意,在我的圖中,可以計算組件的有效順序不止一種:
- Building, setCam, Docals, result
- Building, Docals, setCam, result
所以 Grasshopper 有兩種選擇來確定首先計算的組件,它總歸會選一個的,所以背後肯定有它選擇計算順序的更深層次的原因。我並沒有多做其他探索,就去了 Grasshopper 論壇,看到了這篇文章,提問了一個問題。
不會影響計算順序的東西:
Grasshopper 的計算順序不會被下列因素影響:
- 組件位置(也就是x,y坐標)
- 輸入或輸出的順序
- 組件內的數據
- 組件的類型*
那麽會被哪些因素影響呢?
Grasshopper 的繪制順序
計算順序被一個關鍵性的因素左右:繪制順序(draw order)。在後臺, Grasshopper 把你的文件中的所有組件復制到一個列表中,列表的順序就是繪制的順序。
被稱為“繪制順序”是因為它決定了哪一個組件被“繪制”時能覆蓋其他組件。請看下圖 panel 是如何覆蓋其他 panel 的,這就是“繪制順序”的具體實現。
你可以通過快捷鍵輕易地更改繪制順序:
- CTRL+B 把組件送到下面
- CTRL+F 把組件送到上面
Grasshopper 是如何利用繪制順序來計算的?
繪制順序不僅僅是幫助你美化 Grasshopper 畫布— 它也同樣左右著計算順序。當 Grasshopper 在處理畫布的時候,基本上是這樣的情況:
- Grasshopper 根據你的畫布中的所有組件,生成了一個列表。它的順序和繪制順序是一樣的,0 號元素被繪制在所有元素的下面,其他元素則根據列表的順序依次繪制在上面。
- Grasshopper 找到繪制在最後面的已終止的組件,要求它重算自身。
- 在這個組件真正開始計算任何東西之前,首先它會去檢查有沒有已終止的輸入。如果有,就讓這些輸入也重算自身。
- 同樣,這些組件在它們開始計算之前也會檢查輸入,直到找到一個沒有已終止輸入,但是自身已終止的組件為止,這個組件會重算自身並設置為非終止。
- 回到步驟 2,重復直到沒有已終止的組件。
如何確定繪制順序?
最簡單的確定繪制順序,同時也是確定計算順序的方法,是通過拖拽組件來看看哪個覆蓋在上面。最底下的組件會被首先計算。如果我們不滿意這個順序,可以通過 CTRL+B 和CTRL+F 來更改。
看起來是 setCam 先被計算,耶!
等等 —— 並沒有那麽簡單! 如果 setCam 組件在 DoCals 下面,但是 result 組件在 setCam 和 DoCals 的下面呢?“result”會被 Grasshopper 首先觸發,它也會接著觸發 DoCals。所以即使 setCam 是在 DoCals 的下面,由於 results 的願原因,setCam 也會在 DoCals 之後計算。
我們需要確保 setCam 在所有組件之前計算,而不僅僅是 DoCals。我們可以用 CTRL+B 快捷鍵實現,但是怎麽確定它正確運行了呢?沒有視覺上的反饋是否快捷鍵已經把組件送到了最下面,我們只有手動地去確認每個組件。
如何確定繪制順序 —— 給極客
再一次,C# 拯救世界!用一個 C# 組件,我們可以得到 Grasshopper 文件中所有對象的一個列表 —— 以繪制順序。用一個 timer 和一個連接的 panel,我們可以加一些額外的功能 —— 點擊任何一個組件,在 panel 中會顯示“selected”。
你可以復制以下代碼到一個 C# 組件中,並且在圖中設置好。啟動 timer,選擇任何一個組件(或多個組件)。
1 var rtnlsit = new List<string>(); 2 3 foreach (IGH_DocumentObject obj in GrasshopperDocument.Objects) 4 { 5 if(obj.Attributes.Selected) rtnlist.Add(obj.NickName + "(" + obj.Name + ")SELECTED"); 6 else rtnlist.Add(obj.NickName + "(" + obj.Name + ")"); 7 A = rtnlist; 8 }
使用這個組件, 可以驗證我們成功地把 setCam 設置到了繪制順序列表的最底層。
我們選擇的組件是列表中的 0 號元素,所以確實被放到了畫布中所有組件的最下面。 太好了!
繪制順序(draw order)是如何影響 grasshopper 的計算順序的