1. 程式人生 > 其它 >Blender繪製基本網格物件(轉)

Blender繪製基本網格物件(轉)

網格定義

網格是由點、線、面進行連線繪製的幾何圖形物件,Blender中將點、線、面的三維座標資訊儲存在陣列中。

繪製網格

為了使用Blender繪製,我們首先要引入Blender Python庫bpy。

import bpy

要進行最簡單的繪製,將建立三個空陣列,分別命名為verts,edges,faces代表點、線、面。

# 定義三個空列表分別用於儲存點、線、面的幾何資訊
verts = []
edges = []
faces = []

這其中,verts用於儲存點的三維空間座標,現在我們來繪製一個五面體。

# 定義各個點的座標
verts = [(2, 0, 4), (4, 1, 4), (4, 5, 4), (1, 4, 4), (3, 3, 7)]

在定義了各個點的座標之後,就可以開始定義線和麵了。

線和麵非常類似,都是通過點的連線繪製而成,這裡以面的定義舉例,具體程式碼實現如下。

# 確定面的繪製方法
faces = [(0, 1, 2, 3), (0, 1, 4), (1, 2, 4), (2, 3, 4), (0, 3, 4)]

這裡需要注意的一點是,faces[]中的座標實際上指的是點的連線順序,faces[]中每一個元組代表一個面,而元組中的數代表verts[]中點的序數。

比如,(0,1,2,3)表示verts[]中第1、2、3、4個點依次連線。注意,(0,1,2,3)與(3,2,1,0)雖然最終顯示結果不會有什麼區別,但是在數學上,其正向應當是相反的,而在Blender中,兩種情況下,法線方向確實相反,這裡後續可能會開展一點工作,不過現在不是重心。

定義好點線面之後就可以建立網格物件並將之連結到當前工作空間中了,最後使用之前定義好的座標資料將網格物件繪製並顯示在工作空間中。

# 首先新建一個視窗
bpy.ops.scene.new(type='NEW')

# 建立網格與物件
fivemesh = bpy.data.meshes.new("fivemesh")
fiveobj = bpy.data.objects.new("fivemeshes", fivemesh)

# 將物件連結到當前場景集合中
fiveobj.location = bpy.context.scene.cursor_location
bpy.context.scene.collection.objects.link(fiveobj)

# 根據python資料繪製實體
fivemesh.from_pydata(verts, edges, faces)
fivemesh.update(calc_edges=True)

在Blender中執行程式碼顯示結果如下。


關於點、線、面數組是否使用時的繪製差異

在上文的程式碼中,相信細心的人已經發現了,edges[]陣列為空,我們只定義了verts[]與faces[]。

verts[]無疑是不可或缺的,它是edges[]與faces[]的基礎,那麼,在faces[]為空或三者均不為空的時候,會有什麼有趣結果出現呢?

下面通過一個例項來具體說明。

實現程式碼如下。

import bpy

# 分別設定線列表與面列表為空,顯示結果不同,最後再與點線面三組屬性設定均不為空的情況進行輸出比較

# 分別定義三組列表用於儲存三種不同情況下幾何體的空間資訊
verts_1 = [(0, 0, 0), (3, 0, 0), (3, 3, 0), (0, 3, 0), (1.5, 1.5, 3)]
edges_1 = []
faces_1 = [(0, 1, 4), (1, 2, 4), (2, 3, 4), (0, 3, 4)]

verts_2 = [(5, 0, 0), (8, 0, 0), (8, 3, 0), (5, 3, 0), (6.5, 1.5, 3)]
edges_2 = [(0, 1), (1, 2), (2, 3), (3, 0), (0, 4), (1, 4), (2, 4), (3, 4)]
faces_2 = []

verts_3 = [(0, 5, 0), (3, 5, 0), (3, 8, 0), (0, 8, 0), (1.5, 6.5, 3)]
edges_3 = [(0, 1), (1, 2), (2, 3), (3, 0), (0, 4), (1, 4), (2, 4), (3, 4)]
faces_3 = [(0, 1, 4), (1, 2, 4), (2, 3, 4), (0, 3, 4)]

# 開始圖形的繪製
# 首先開啟一個新圖層
bpy.ops.scene.new(type="NEW")

# 分別建立三個網格和物件
mesh_1 = bpy.data.meshes.new("mesh_1")
obj_1 = bpy.data.objects.new("mesh_1", mesh_1)
mesh_2 = bpy.data.meshes.new("mesh_2")
obj_2 = bpy.data.objects.new("mesh_2", mesh_2)
mesh_3 = bpy.data.meshes.new("mesh_3")
obj_3 = bpy.data.objects.new("mesh_3", mesh_3)

# 將這三個物件連結到當前場景集合中
obj_1.location = bpy.context.scene.cursor_location
bpy.context.scene.collection.objects.link(obj_1)
obj_2.location = bpy.context.scene.cursor_location
bpy.context.scene.collection.objects.link(obj_2)
obj_3.location = bpy.context.scene.cursor_location
bpy.context.scene.collection.objects.link(obj_3)

# 根據python資料分別繪製實體
mesh_1.from_pydata(verts_1, edges_1, faces_1)
mesh_2.from_pydata(verts_2, edges_2, faces_2)
mesh_3.from_pydata(verts_3, edges_3, faces_3)

# 設定法線可見
bpy.context.view_layer.objects.active = obj_1
bpy.ops.object.mode_set(mode='EDIT')
for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        bpy.context.space_data.overlay.show_face_normals = True
        bpy.context.space_data.overlay.normals_length = 2

mesh_1.update(calc_edges=True)
mesh_2.update(calc_edges=True)
mesh_3.update(calc_edges=True)

輸出結果如下。


可以看到,在faces[]為空的時候,繪製的是一個線框,而在三者均不為空時,在圖形表面出現了線框。