【Blender】客製化建立Mesh

帽捲
Maochinn
Published in
18 min readJul 9, 2024

本篇主要目的是快速方便建立一些簡單的Mesh,透過Blender既有功能跟腳本快速建模所需的模型,舉例來說,研究常常需要一些Grid的Mesh來做為基底去應用在其他專案,例如OpenGL、Unity等,如果要自己寫一個C++去建模再輸出obj顯然太花時間,如果要人工建模只要vertex一多也會浪費時間,但是透過Blender先產生正確的topology,再去用腳本去修改Vertex,最後直接透過Blender輸出顯然是更聰明的辦法。

舉例來說,目標要建立一個21*9的網格,同時我也已經有每個vertex對應的position了,他可能就是一個二維陣列或是一串數據,如果我們要一個一個點去複製貼上,或是專門寫一個小程式去建模顯然不划算,因此這篇先從這個最簡單的例子來介紹,至於Blender的其他進階操作這篇就不介紹了。

建立基本Mesh

首先,先生用內建的工具建立Grid,因為我們要建立21*9 = 189個Vertex的Mesh,因此X方向要細分出20格,Y方向要細分出8格,Size = 1表示長寬為1,也就是左下角是(-0.5, -0.5),右上角是(0.5, 0.5),但其實這個無所謂,之後vertex會被修改。

可以從object mode切到edit mode確認一下是不是符合預期是21*9

接著,我們要知道Blender是怎麼儲存這些vertex的,然後才能依序修改。先切到Script的Layout

在右上角View Layer中選擇Grid,然後在左下角Console輸入

C.active_object.data.vertices

active_object的意思就是目前選擇的物件,也就是Grid這個Mesh,Mesh這個data裡面有vertices,裡面存了所有的vertices的座標。

可以看到vertex一共有189個點,接著,我們可以一個點接一個點檢查,舉例第一個Vertex的XY座標,可以在console輸入以下

C.active_object.data.vertices[0].co.x
C.active_object.data.vertices[0].co.y

可以發現第一個點就是左下角,同時第二個點X稍微大一些,Y是相同的,表示第二個點在第一個點的右邊,以此類推可以往下一個一個看,直到第20個vertex的X為0.5,也就是第0~20個vertex表示最下面那排的點。

當然,不用每次都這樣看,也可以打開Geometry Node的Layout可以看到所有資訊

修改既有Mesh

接著,我們就要把每個Vertex的座標依照順序修改成我們要的,首先,在Script中增加一個腳本,然後複製下面的腳本進去,最後執行。

有個地方要注意是viewport要切到object mode執行,或者說,如果在edit mode執行的話會發現Mesh沒有變化,因為在edit mode使用者也可以調整vertex,系統在edit mode就不允許腳本去修改vertex,

腳本為了清楚,所以我把每個點都寫明了,實際上你可用個迴圈來填,總之就是照順序把每個vertex的XY coordinate改掉

import bpy

list = []
list.append((0.0000, 0.0000))
list.append((45.0000, 0.0000))
list.append((90.0000, 0.0000))
list.append((135.0000, 0.0000))
list.append((180.0000, 0.0000))
list.append((225.0000, 0.0000))
list.append((270.0000, 0.0000))
list.append((315.0000, 0.0000))
list.append((360.0000, 0.0000))
list.append((405.0000, 0.0000))
list.append((450.0000, 0.0000))
list.append((495.0000, 0.0000))
list.append((540.0000, 0.0000))
list.append((585.0000, 0.0000))
list.append((630.0000, 0.0000))
list.append((675.0000, 0.0000))
list.append((720.0000, 0.0000))
list.append((765.0000, 0.0000))
list.append((810.0000, 0.0000))
list.append((855.0000, 0.0000))
list.append((900.0000, 0.0000))
list.append((0.0000, 50.0000))
list.append((45.0000, 50.0000))
list.append((90.0000, 50.0000))
list.append((135.0000, 50.0000))
list.append((180.0000, 50.0000))
list.append((225.0000, 50.0000))
list.append((270.0000, 50.0000))
list.append((315.0000, 50.0000))
list.append((360.0000, 50.0000))
list.append((405.0000, 50.0000))
list.append((450.0000, 50.0000))
list.append((495.0000, 50.0000))
list.append((540.0000, 50.0000))
list.append((585.0000, 50.0000))
list.append((630.0000, 50.0000))
list.append((675.0000, 50.0000))
list.append((720.0000, 50.0000))
list.append((765.0000, 50.0000))
list.append((810.0000, 50.0000))
list.append((855.0000, 50.0000))
list.append((900.0000, 50.0000))
list.append((0.0000, 100.0000))
list.append((45.0000, 100.0000))
list.append((90.0000, 100.0000))
list.append((135.0000, 100.0000))
list.append((180.0000, 100.0000))
list.append((225.0000, 100.0000))
list.append((270.0000, 100.0000))
list.append((315.0000, 100.0000))
list.append((360.0000, 100.0000))
list.append((405.0000, 100.0000))
list.append((450.0000, 100.0000))
list.append((495.0000, 100.0000))
list.append((540.0000, 100.0000))
list.append((585.0000, 100.0000))
list.append((630.0000, 100.0000))
list.append((675.0000, 100.0000))
list.append((720.0000, 100.0000))
list.append((765.0000, 100.0000))
list.append((810.0000, 100.0000))
list.append((855.0000, 100.0000))
list.append((900.0000, 100.0000))
list.append((0.0000, 150.0000))
list.append((45.0000, 150.0000))
list.append((90.0000, 150.0000))
list.append((135.0000, 150.0000))
list.append((180.0000, 150.0000))
list.append((225.0000, 150.0000))
list.append((270.0000, 150.0000))
list.append((315.0000, 150.0000))
list.append((360.0000, 150.0000))
list.append((405.0000, 150.0000))
list.append((450.0000, 150.0000))
list.append((495.0000, 150.0000))
list.append((540.0000, 150.0000))
list.append((585.0000, 150.0000))
list.append((630.0000, 150.0000))
list.append((675.0000, 150.0000))
list.append((720.0000, 150.0000))
list.append((765.0000, 150.0000))
list.append((810.0000, 150.0000))
list.append((855.0000, 150.0000))
list.append((900.0000, 150.0000))
list.append((0.0000, 200.0000))
list.append((45.0000, 200.0000))
list.append((90.0000, 200.0000))
list.append((135.0000, 200.0000))
list.append((180.0000, 200.0000))
list.append((225.0000, 200.0000))
list.append((270.0000, 200.0000))
list.append((315.0000, 200.0000))
list.append((360.0000, 200.0000))
list.append((405.0000, 200.0000))
list.append((450.0000, 200.0000))
list.append((495.0000, 200.0000))
list.append((540.0000, 200.0000))
list.append((585.0000, 200.0000))
list.append((630.0000, 200.0000))
list.append((675.0000, 200.0000))
list.append((720.0000, 200.0000))
list.append((765.0000, 200.0000))
list.append((810.0000, 200.0000))
list.append((855.0000, 200.0000))
list.append((900.0000, 200.0000))
list.append((0.0000, 250.0000))
list.append((45.0000, 250.0000))
list.append((90.0000, 250.0000))
list.append((135.0000, 250.0000))
list.append((180.0000, 250.0000))
list.append((225.0000, 250.0000))
list.append((270.0000, 250.0000))
list.append((315.0000, 250.0000))
list.append((360.0000, 250.0000))
list.append((405.0000, 250.0000))
list.append((450.0000, 250.0000))
list.append((495.0000, 250.0000))
list.append((540.0000, 250.0000))
list.append((585.0000, 250.0000))
list.append((630.0000, 250.0000))
list.append((675.0000, 250.0000))
list.append((720.0000, 250.0000))
list.append((765.0000, 250.0000))
list.append((810.0000, 250.0000))
list.append((855.0000, 250.0000))
list.append((900.0000, 250.0000))
list.append((0.0000, 300.0000))
list.append((45.0000, 300.0000))
list.append((90.0000, 300.0000))
list.append((135.0000, 300.0000))
list.append((180.0000, 300.0000))
list.append((225.0000, 300.0000))
list.append((270.0000, 300.0000))
list.append((315.0000, 300.0000))
list.append((360.0000, 300.0000))
list.append((405.0000, 300.0000))
list.append((450.0000, 300.0000))
list.append((495.0000, 300.0000))
list.append((540.0000, 300.0000))
list.append((585.0000, 300.0000))
list.append((630.0000, 300.0000))
list.append((675.0000, 300.0000))
list.append((720.0000, 300.0000))
list.append((765.0000, 300.0000))
list.append((810.0000, 300.0000))
list.append((855.0000, 300.0000))
list.append((900.0000, 300.0000))
list.append((0.0000, 350.0000))
list.append((45.0000, 350.0000))
list.append((90.0000, 350.0000))
list.append((135.0000, 350.0000))
list.append((180.0000, 350.0000))
list.append((225.0000, 350.0000))
list.append((270.0000, 350.0000))
list.append((315.0000, 350.0000))
list.append((360.0000, 350.0000))
list.append((405.0000, 350.0000))
list.append((450.0000, 350.0000))
list.append((495.0000, 350.0000))
list.append((540.0000, 350.0000))
list.append((585.0000, 350.0000))
list.append((630.0000, 350.0000))
list.append((675.0000, 350.0000))
list.append((720.0000, 350.0000))
list.append((765.0000, 350.0000))
list.append((810.0000, 350.0000))
list.append((855.0000, 350.0000))
list.append((900.0000, 350.0000))
list.append((0.0000, 400.0000))
list.append((45.0000, 400.0000))
list.append((90.0000, 400.0000))
list.append((135.0000, 400.0000))
list.append((180.0000, 400.0000))
list.append((225.0000, 400.0000))
list.append((270.0000, 400.0000))
list.append((315.0000, 400.0000))
list.append((360.0000, 400.0000))
list.append((405.0000, 400.0000))
list.append((450.0000, 400.0000))
list.append((495.0000, 400.0000))
list.append((540.0000, 400.0000))
list.append((585.0000, 400.0000))
list.append((630.0000, 400.0000))
list.append((675.0000, 400.0000))
list.append((720.0000, 400.0000))
list.append((765.0000, 400.0000))
list.append((810.0000, 400.0000))
list.append((855.0000, 400.0000))
list.append((900.0000, 400.0000))

mesh = bpy.data.objects['Grid']

N = len(mesh.data.vertices.values())
for i in range(0, N):
vertex = mesh.data.vertices[i]

vertex.co.x = list[i][0]
vertex.co.y = list[i][1]

結果如下圖,其實也可以在edit mode下檢查每個vertex的座標,例如右上角的座標就是(900, 400)。

以此只要有各種數據、table就可以產生不同的形狀,例如開頭的結果,然後就可以用Blender幫你輸出成各種檔案格式。當然,這邊的前提都是你在你自己的程式中知道怎麼作為前題,Blender只是提供一個讓你可以人工調整,同時也能夠用程式修改的平台,換言之,上述這種操作需要人工跟腳本協作,並不是一個全自動的方式,所以當然不是用來大量產生模型,純粹是提供一個有彈性的快速建模,這對於作一些小實驗或是prototype非常實用。

否則,如果需要類似這樣的Mesh通常就會直接寫死在程式碼裡面,或者要單獨開一個C++專案去compile一個程式,可能還要include其他lib用來輸出Mesh,例如.obj, .fbx,但這些繁瑣的事情Blender都內建了,甚至也可以import OpenCV之類的工具,因此對於許多需要快速驗證的東西非常方便。

--

--