Blender:Geometry Node 應用於營造法式生成大木作構件初探-斗篇

摘要

本文進一步探索 Blender 客製化 Geometry Node,包含呼叫其他 Geometry Node 的功能,能夠將原本的 Node Graph 轉為單一 Node。

前言

繼上一篇處理完卷殺折線的程序化生成後,原本想要進一步處理栱的部分,不過發現栱與抖有依賴的關係,栱的一部分數據需要來自枓,主要是枓底的尺寸。

製作這些枓的程序化生成模型,首先要看看這些枓有沒有共通點?

枓的規則

枓的構成與尺寸示意

《營造法式》所有枓基本上都可以分成從上到下三個部位耳、平、欹,形狀上可以分為方或圓(現實實例的話則不只)。
基本上變化除了榫卯(包含包耳)以外還有尺寸的差異,而尺寸依然使用材分決定。整體尺寸上各種枓長寬高不同,會以相對比例決定耳、平、欹的尺寸,但在高度上耳、平、欹比例均各為 2:1:2 分配。欹䫜也不同。

 

枓的參數

從上面大致上整理一下,可以得到幾個可能的參數:

  • 枓的種類:角櫨枓(方圓)、櫨枓(方圓)、散枓、交互枓、齊心枓、平盤枓
  • 幾等材(U)
  • 斗的長寬高:可從枓的種類求得
  • 欹䫜的深度:可從枓的種類求得 
  • 包耳與開口的尺寸 :可從枓的種類求得,但開口寬為固定一栔(栱或枋寬)
  • 底部尺寸:可從枓的種類求得 

附註

我在翻閱營造法式相關文獻時發現有對包耳功用的討論,有相關文獻指出可能是對斗耳的拉結加固,然而相關論文我目前上無法取得,不過的確是有趣的論點。

 

轉換成 Geometry Node

枓的模型會以 Geometry Node 來生成,為了介面方便會使用客製化的 Node。

Node 輸入輸出與屬性(Property)

這個 Node 有屬性,主要是因為沒有想要透過輸入的方式修改枓的類別,另外使用屬性儲存類別,可以依照條件顯示輸入輸出的 Port 和屬性,在此會來開關顯示選項。

輸入:
Unit(cm)          : Float (單位公分)
Quality Level     : UInt
Has Joinery       : Boolean (不勾選則不開榫)

輸出:
枓      : Geometry

枓平中心
: Vector3 (用來定位栱,相對於枓的原點)

屬性:
種類    : Enum
轉角   
: Boolean (僅限櫨枓)
十字    : Boolean (平盤枓除外)

Node 參考範本

由於有屬性來切換類別,於是我參考了一個近似功能的節點:

node_geo_curve_primitive_quadrilateral.cc

Node 功能試作-無榫卯版本的枓

因為目前還不確定生成枓的模型步驟為何,所以先使用 Geometry Node 編輯器試作一個版本,之後再實作成客製化的 Geometry Node。

下圖是目前生成枓的模型的步驟,榫卯則留到下一階段製作。由於節點數量多請參考 github 專案。 

圖中主要有五個部分:

  1. 參數:分(U,單位公分)、長寬高(幾U)、品質
  2. 枓平的矩形繪製
  3. 枓欹曲面繪製:
    主要利用起點終點計算出中點,透過三點放樣剖面的弧線,並且使用枓平的矩形掃過生成曲面,另外由於生成曲面時起始點在端點上(轉角),然而繪製的剖面線並不是供轉角起始使用的,導致投影的時候會拉扁,因此剖面線的寬需要額外拉伸根號 2 倍以糾正
  4. 將枓平的矩形推出來生成枓平和枓耳的面,高度為枓平和枓耳高。然後生成枓底的面
  5. 將各個面接合併設定平滑

使用節點生成枓的步驟(詳情參見 github)

在開始實作客製化的 Geometry Node有一件事需要處理,就是要怎麼在 Geometry Node 的程式碼中呼叫其他 Geometry Node。

在 Geometry Node 中呼叫其他 Geometry Node

在過去的篇章中,客製化的節點並沒有牽涉到呼叫其他 Geometry Node 的方法,這邊開始探索如何呼叫其他 Geometry Node 的方法。

首先要先查看其他 Geometry Node,看看這些 Node 的功能有沒有可以直接使用的方法,通常這些方法從 node_geo_exec 方法可以找到。

以 node_geo_mesh_primitive_cube.cc 為例子,從 node_geo_exec 方法可以看到該節點的功能主要實現在 create_cube_mesh 方法裡,所以只要呼叫該方法即可以在客製化的 Geometry Node 中達成相同功能。基本上步驟有以下:

  1. 移除 create_cube_mesh 方法的 static 關鍵字,解除 internal linkage,這樣才可以在其他 .cc 檔中呼叫
  2. 添加 header 檔,在其宣告 create_cube_mesh 方法
  3. 在客製化的 Geometry Node 即可以呼叫該方法

客製化的 Geometry Node 功能實作與成果

首先是實作 DNA 和 RNA 儲存節點的屬性資料與方法,DNA 必須對齊為 4 位元。如同教學所示,RNA 的方法必須定義在 rna_nodetree.cc ,否則似乎有些屬性再被修改的時候會沒有觸發更新。一些基礎的處裡可以詳見上一篇提到的此文章

基本上實作就是在程式碼中重複這些節點的呼叫,並傳回類型為 GeometrySet 的成果,詳情可見 github。

試做成果

Node 功能試作-有榫卯版本的枓

一開始依然是先嘗試使用 Geometry Node 編輯器試作開榫版本的枓,將原先無榫版本傳入後開榫。

 

使用節點將枓開榫的步驟(詳情參見 github)
 

客製化的 Geometry Node 功能實作與成果

接續前面無榫卯版本的成果,會得到無榫卯枓的模型(類別為 GeometrySet),為了處理榫卯於是寫了另一個方法將這個無榫卯的模型為參數傳入將模型開榫。

處理榫卯使用的是 Mesh Boolean 節點,原始碼在node_geo_boolean.cc,如果仔細看會發現這個節點的功能實現在 node_geo_exec 裡,使用到 GeoNodeExecParams 來取得各項參數。也許可以將功能實現的部分抽取出方法,不過這將會更動到原始碼,看過程式碼後發現功能實現主要分成四個部分:

  1. 從各個 Input 取得參數,包含取得 Mesh
  2. 掃描輸入的 Mesh 的材質球並記錄映射的 index,所有輸入的 Mesh 其材質球 index 會重新映射到第一個 Mesh 的 index
  3. 在 Attributes 裡記錄 Intersecting edges 的 id
  4. 將 Boolean 運算後的 Mesh 封裝成 GeometrySet 後回傳。

由於目前有很多功能是不需要使用到的,於是寫了一個簡單布林運算的方法 process_boolean_operation。

然後便可以開始實作開榫的方法,主要分成兩部分,生成開榫時挖去的部分與執行布林運算。最後如圖及事實作成果。

試做成果





留言

這個網誌中的熱門文章

Unity:嘗試製作可相交的視差遮蔽貼圖Shader (Parallax Occlusion Mapping Shader with Pixel Depth Offset)

Blender:Geometry Node 應用於營造法式生成大木作構件初探-梭柱篇

Blender:Geometry Node 應用於營造法式生成大木作構件初探-卷殺折線標準化篇