如果有機會接觸3D建模,會發現它跟程式設計有很高的相似性,你得分而治之、擬出搭建模型的順序,雖然一開始手動繪製3D模型看似方便,然而沒多久就會開始覺得厭煩,這時身為程式設計者的優勢就派上用場了。
其實,接觸這不同的領域,同時也是訓練另一個思考方向的好機會。
分而治之的3D建模
我喜歡動手實現一些小物,正如先前專欄〈程式人與微控制器開發板〉中談過的,前陣子我玩上了Arduino等微控制板,也動手做了些東西,比較有趣的是〈廢材機器人〉,我對它賦予的製作概念在於,就算沒有3D列印機,在讓腦中想法化為現實世界具體事物時,也不至於構成障礙。當然,得發揮一下Maker不怕失敗的精神,付出較多的時間與耐心,跟竹筷、冰棒棍、飛機木等奮戰。
對Maker自造者來說,3D列印機確實是個神器,然而,事實就是,你不可能老是下載別人設計好的3D模型檔。
想讓3D列印機真正能實現腦中的想法,擁有自行建模能力是必要的,因此,在正式敗入3D列印機之前,我就開始學習一些簡單的3D建模了,雖然只是入門者,然而也馬上發現了,3D建模與程式設計,有著驚人的相似性。
正如架構軟體得先分而治之,將大任務分解為小任務,然後使用程式語言的基本元素、程式庫等,組合出流程、函式、物件等元件,然後讓這些元件再組合在一起,達到想要的功能;在實現3D建模時,對於心中的模型,也得先進行分解,然而使用建模軟體提供的基本元件,先完成分解出來的小模型,然後小模型之間進行交集、聯集等各種運算,組合出另一個較大的模型,接著這些模型再逐步搭配成為真正的成品。
說是這麼說,不過思考3D模型的分解時,牽涉到幾何圖形的問題,在分而治之的過程中,需要的會是另一個面向的觀摩與學習,不過,這樣的問題不算太大。
正如程式語言間多少都會有些不同的哲學,總得多看幾個實際程式碼,才能瞭解該語言的慣例與典範等;學習3D建模,也是要多看幾本3D建模的書,從中熟悉3D幾何的分解與組合邏輯,就程式設計的角度來看,這大概就跟閱讀程式碼一樣的重要吧!
從手繪到程式化
不過很快地,我就開始對3D建模軟體感到有些厭煩。手動繪製3D模型,在一開始看似直覺,然而,漸漸地就會發現,有許多重複性的動作出現;複製既有的小模型看似方便,然而組合時必須進行的微調還滿煩人的;使用滑鼠移動看似簡單,然而很難精準地對模型進行定位;對於一些比較複雜,例如涉及數學的幾何圖形,手繪根本就行不通;書本上使用一張張畫面擷圖,來解說實際上是連續操作的建模步驟,常常讓我困惑,這張圖與下張圖的效果,到底是怎麼做出來的?我常常懷疑圖與圖之間少了個步驟;更糟糕的是,要對一個已完成的模型進行修改,根本就是一場災難!
這也許可以歸因於我只是3D建模的入門者,對許多操作不熟而造成的,不過,自私一點的想法是,這是身為程式設計者的思維。我希望能做到的是,讓重複性動作元件化;對於可微調部份能參數化;能精確地指定相關座標,而不是苦命地使用滑鼠;能夠透過程式運算出相關數字,而不是手動計算;可以透過閱讀程式碼來瞭解建模過程,而不是看著分鏡般的圖片步驟;更重要的是,能夠輕易地透過修改原始碼,來達到修改3D模型的目的。
實際上,可以使用程式建模的選擇不少,像是SketchUp可以使用Ruby,Blender或Rhino可以使用Python,在經過一般搜尋之後,最後我決定使用OpenSCAD。
這有幾個理由:OpenSCA目前D完全使用了程式建模(沒有滑鼠介入的餘地),這表示它是完全採用程式設計的思維設計出來的工具;著名3D模型社交網站Thingiverse中,常常能看到使用OpenSCAD分享成果;官方網站文件很多,當然是必要考量;還有一點就是,它有一些熱門語言的Porting,像是SolidPython、RubyScad、JavaSCAD,以及使用JavaScript的OpenJSCAD等。
身為程式設計者,試著照著手上的範例,寫幾個OpenSCAD,應該馬上就能感受到程式建模的方便性,尤其是在滿足閱讀原始碼,以瞭解建模過程的需求這方面,更是打中了程式設計者的胃口,Thingiverse網站有幾個實用的OpenSCAD模型程式檔,下載回來,就能立即修改相關參數以符合需求,完全不會有手繪修改的痛苦!
事先規畫更顯重要
寫程式的人,都知道事先規畫的重要性,不過,相信更多的人,都是面對著電腦就直接開始打程式,我先前專欄〈紙上程式設計〉中談過的這類事先規畫,對許多人來說應該是陌生的;然而,在自行使用程式從無到進行3D建模時,這樣的想法可就不太能行得通了!
注意,我說的是從無到有建立3D模型,而不是下載別人的原始碼修改些參數。
對於後者,因為原作者已經規畫好相關幾何位置,在調整參數值時,相關幾何位置也會依作者的設計,而自動計算出來;然而,自行程式建模時,由於不再能使用滑鼠隨意地繪製或擺放模型,你得事先在紙上規畫好模型的相關幾何數據,像是座標、半徑、高度等,對於某些模型,你還得先找出它們的數學關係。
舉個例子來說,想要一個3D水滴模型嗎?手繪的話,可以在畫面中任何地方,產生一個圓球與一個圓錐(有一面半徑為零的圓柱體),然後用滑鼠慢慢移動,讓圓錐底部圓周剛好符合圓球某個剖面圓周(斜面正好相切於圓);使用程式的話沒辦法用滑鼠,因此你得知道圓球的圓心座標、半徑,使用圓錐半徑與高計算出圓錐角度,然後,用三角函式計算出圓錐底面與圓心間的距離。
3D建模是程式設計結合數學的一個例子,面對更複雜的模型,沒有紙筆先做事前的規畫,就直接開始想寫程式的話,根本就是浪費時間。
解決了數學方面的問題之後,要使用程式碼實現前,也是可以事先做好規畫,例如,想好哪些地方重複?哪些地方可以參數化?哪些地方可以做成元件模組?
因為,使用程式進行3D建模所面臨的一個事實就是,若沒有良好的規畫,一堆交集、減集、移動、旋轉指令,馬上就會讓程式碼膨脹到難以閱讀。
訓練另一個思考方向
儘管與程式設計概念有許多類似的地方,也突顯了事前規畫的重要性,然而,透過程式設計進行3D建模,除了流程之外,腦袋中還得有另一套幾何思考方向。
對我來說,過去對這樣的思考方向幾乎是陌生的,因而感覺到新奇而有趣,有時稍微加點既有的程式設計知識(像是迴圈、遞迴等),就能創造出優美的模型,上一次體會到這種不同思考方向的樂趣,大概是學習函數式設計那時候了!
如果你很久沒感受過程式設計帶來的樂趣,甚至因此對程式設計感到一成不變而覺得厭倦,或許也可以像我一樣,換個口味。
如果你覺得寫程式不用數學,或許可以找個會用上數學的任務來解解看;若你不覺得事先規畫很重要,那麼找看看,有沒有什麼是在缺少事先規畫的情況下,幾乎就寸步難行的應用;試著從另一個方向來思考看看,對於程式設計,或許就會有許多不同的體驗與樂趣喔!