Blender 腳本之 Operator 初探



  addon(插件)用來擴展 Blender 的功能,跟其他軟件里的 plugin(插件)一樣,去掉不會影響軟件的運行。插件可以加到 Blender 的用戶偏好設置目錄里,或者就在你所編輯的.blend文件里。前者需要你手動開啟才能使用;后者勾選 Text Editor 里的 Register 選框后會 Blender 在加載的時候啟用,或者通過點擊 Register 選框旁邊的 Run Script(快捷鍵Alt + P)運行。

  Blender 插件的路徑是 C:\Program Files\Blender Foundation\Blender\2.76\scripts\addons,我假設你用的也是64位的2.76版本Blender軟件,而且沒有修改安裝路徑。比如常用的圖片作為平面加載的插件對應文件:io_import_images_as_planes.py,啟用的話進入用戶偏好設置(快捷鍵Ctrl + Alt + U)的 Add-ons Tab,搜索過濾,勾選后面的選框,在菜單的 File > Import 里多出了一行 Images as Planes。

  插件里定義了一個或多個operator,恕我沒有翻譯成數學里的算子、C++ 里面的操作符。Blender 的所有 UI 功能是通過 operator 完成的,operator 可綁定到菜單、按鈕或快捷鍵上供調用。operator 的基類是 bpy.types.Operator,自定義 operator 時需要繼承自它。

 

  好了,我們學習寫插件吧!
  打開 Blender 的 Text Editor ,我假設你對 Blender 的界面布局有了初步了解。Text Editor 可當 README 使用,程序員在接觸新的項目工程時,通過 README 大概了解其功能,同樣,Blender 工程在退出時會保存當前界面,其他人打開時,文字簡介第一眼就看得到。你可以寫入自己的博客地址和大名讓旁人圍觀學習。

  我們的第一個Operator,say hello to Blender!

import bpy class HelloWorldOperator(bpy.types.Operator):   bl_idname = "wm.hello_world"   bl_label = "Hello World"

  def execute(self, context):     print("Hello World!")     return {'FINISHED'} bpy.utils.register_class(HelloWorldOperator)

  operator 使用前必須注冊,bl_idname 顧名思義,就是 operator 的名字,寫法像包名,用點號分割,點號左邊的名必須屬於 bpy.ops 之一,在 Blender 內部的 Python 控制台下,dir(bpy.ops) 列出所有的名字。bl_idname 對內使用,唯一標識符;bl_label 對外可見,UI文本,可以空格搜索;bl_description 是提示信息,鼠標指針停放其上可見,如果bl_label意思明了,也可以不用填寫。Python 不區分單引號與雙引號,都可以括字符串。或者說,C/C++ 用單引號與雙引號區分字符與字符串,但 Python 統一解釋成字符串。

>>> type(bpy.ops)
<class 'bpy.ops.BPyOps'>

>>> dir(bpy.ops)
['action', 'anim', 'armature', 'boid', 'brush', 'buttons', 'camera', 'clip', 'cloth', 'console', 'constraint', 'curve', 'cycles', 'dpaint', 'ed', 'export_anim', 'export_mesh', 'export_scene', 'file', 'fluid', 'font', 'gpencil', 'graph', 'group', 'image', 'import_anim', 'import_curve', 'import_image', 'import_mesh', 'import_scene', 'info', 'lamp', 'lattice', 'logic', 'marker', 'mask', 'material', 'mball', 'mesh', 'nla', 'node', 'object', 'outliner', 'paint', 'paintcurve', 'palette', 'particle', 'pose', 'poselib', 'ptcache', 'render', 'rigidbody', 'safe_areas', 'scene', 'screen', 'script', 'sculpt', 'sequencer', 'sketch', 'sound', 'surface', 'text', 'texture', 'time', 'transform', 'ui', 'uv', 'view2d', 'view3d', 'wm', 'world']

>>> print("Hello World!")
Hello World!

>>> bpy.ops.wm.hello_world()
Hello World!
{'FINISHED'}

>>>

  腳本里的一行 print("Hello World!") 一行,輸出 Hello World! 信息到控制台,直接運行是看不到輸出結果的。你可以像上面一樣,在控制台輸入 bpy.ops.wm.hello_world() 測試,注意不要有前導空格。


  下面稍微修改一下,來一個 UI 版的 HelloWorld。

import bpy class HelloWorldOperator(bpy.types.Operator):   bl_idname = "wm.hello_world"   bl_label = "Hello World"   bl_description = "This is an operator test."

  def execute(self, context):     #print("Hello World!")
    self.report({'INFO'}, "Hello World!")     return {'FINISHED'}   def invoke(self, context, event):     wm = context.window_manager     return wm.invoke_props_dialog(self) bpy.utils.register_class(HelloWorldOperator)

  上面命令行版的 HelloWorld,替換一下 self.report({'INFO'}, "Hello World!")
  在3D視圖里敲擊空格鍵,輸入 Hello World 就可以搜索到,注意是實時搜索,輸入幾個字母就可以看見條目了。鼠標點擊這個條目,會彈出一個對話框,標題就是bl_label,點擊OK后消失,Blender 界面菜單一行 logo 附近會 toast 顯示 "Hello World!" 消息。你也可以在 Python 控制台輸入 bpy.ops.wm.hello_world() 測試新定義的 operator。

>>> bpy.ops.wm.hello_world()
Info: Hello World!
{'FINISHED'}

>>>

  invoke 方法完成后需要返回字符串集合,即用{}括起,表示一個set。告訴 Blender operator 在運行狀態 {'RUNNING_MODAL'},還是取消了操作 {'CANCELLED'} 等,return {"FINISHED"} 則表示成功執行。

 

  第二個operator,添加一個正四面體(regular tetrahedron)。
  漢語與英語比的一個優勢是——星期一到日、一月到十二月、正四面體到正二十面體都是用數字表示的,記住數字就會寫;而英語撇開了數字,光月份就有十二個單詞,英語的詞匯量就是這么增加上去的。
  四面體其實就是三棱錐,但正三棱錐不一定是正四面體!正三棱錐要求側面是等腰三角形,正四面體要求是等邊三角形。關於正四面體的幾何性質,希望大家還記得。正四面體是三維空間最簡單的幾何體,甲烷CH4的分子模型可以當成正四面體來講解,碳原子作為外界面的圓心。二面角的角度為arccos(1/3),取碳原子為坐標原點,則四個氫原子的坐標為,任兩個氫原子距離為2。
  正四面體可以從圓錐體構造,添加圓錐 (Shift + A 后選擇Cone),左邊面板的 vertices 選擇3,得到三菱錐后,用球形化(Shift + Alt + S) 或通過菜單 Object > Transform >  To Sphere 就可以了。

  正四面體也很容易從正方體構造出,選取正方體的對面上交叉的對角線,連接這四個頂點,就可以構成正四面體。像這樣:


  Blender采用BU(Blender Unit)單位,正四面體的邊長為1,頂點(0, -1 / math.sqrt(3),0),(0.5, 1 / (2 * math.sqrt(3)), 0), (-0.5, 1 / (2 * math.sqrt(3)), 0),(0, 0, math.sqrt(2 / 3))。上面用系統的正方體(邊長為2BU)構造的話,邊長為2*sqrt(2),頂點(1, 1, 1),(-1, -1, 1), (1, -1, -1),(-1, 1, -1),頂點都是整數哦!

import bpy from math import sqrt from mathutils import Vector class MakeTetrahedron(bpy.types.Operator): bl_idname = "mesh.make_tetrahedron" bl_label = "Add Tetrahedron"

    def invoke(self, context, event): vertices = \ [ Vector((0, -1/sqrt(3),0)), Vector((0.5, 1/(2 * sqrt(3)), 0)), Vector((-0.5, 1/(2 * sqrt(3)), 0)), Vector((0, 0, sqrt(2/3))), ] edges = [] faces = [[0, 1, 2], [0, 1, 3], [1, 2, 3], [2, 0, 3]] tetrahedron = bpy.data.meshes.new("Tetrahedron") tetrahedron.from_pydata(vertices, edges, faces) tetrahedron.update() object = bpy.data.objects.new("Tetrahedron", tetrahedron) context.scene.objects.link(object) return {"FINISHED"} #end invoke #end MakeTetrahedron
 bpy.utils.register_class(MakeTetrahedron)

 

  內容多一行寫不下的話,個人喜歡括號列對齊,需要在行尾添加反斜杠,表示續行,不寫會報錯的。如果不喜歡這種寫法,可以下一行的括號拿上來就成。
  Python 支持 UTF-8 編碼,也就是說類名、方法名、變量名可以用 Unicode 字符,當然包括中文。如果你不知道正四面體的英文是tetrahedron,請不要用拼音代替。我見過一些新手寫Java代碼,不懂的單詞懶得查字典,就用拼音(比如階乘函數寫成 jiecheng),看着就想揍人,你寫中文,編譯器又不會怪你。不過話又說回來,最好用 ASCII 字符,注意下代碼工程是用美式英語還是英式英語,其他字符可出現在注釋里。

  上面的代碼中,先給出了正四面體的數據(如果僅僅是要一個四面體,可以 Mesh > Add Cone,Vertices 選擇3就可以了),vertices/edges/faces。Mesh.from_pydata函數利用 V/E/F 這些數據構造出網面。Python 跟 C/C++/Java一樣,索引從0開始計數,MATLAB/Lua 從1開始計數。從0開始計數是有很多好處的。上面提供 faces 數據,edges 留空,表示實體(Solid)模型,如果提供以下數據,則會得到正四面體的線框(wireframe)模型。faces的第一個面[0, 1, 2] 表示由線段 [0, 1], [1, 2], [2, 0] 構成的面,最后一個線段用來封閉面。注意面不一定得是三角形。而且索引的順序需要保持一致,要么都順時針,要么都逆時針,否則后期需要翻轉法線(Ctrl + N)。

    vertices = ... # same as above
    edges = [[0, 1], [0, 2], [0, 3], [1, 2], [2, 3], [3, 1]]
    faces = []

 

  注意要么提供 edges 數據,要么提供 faces 數據,兩者都提供的話很可能導致 Blender 崩潰。(好吧,我告訴了你一種讓Blender崩潰的方法。)你可以用數學公式生成頂點、邊、面的數據,賦值給上面的 vertices、edges、faces 變量,在導入這些數據后,Mesh 數據有變,需 update() 一下。
  網面創建了,接下來 mesh 附屬到 object datablock,最后鏈接到場景里。好了,我們完成了。最后一句的注冊 register_class 時有必要的,不然按空格是搜索不到的。上面只能通過空格鍵搜索使用,如果想在UI界面調用話,需要讓 bpy.types.Panel 登場了。

  我假設你熟悉 Python 語言,知道類繼承的寫法,知道縮進的意思。如果你在運行的時候出現語法錯誤,Blender 會彈出窗口顯示出來,可能是混用了tab和空格,也可能是其他小錯誤,修改正確后重新執行即可。

 

  用上我們的operator,下面創建了甲烷CH4分子的棍棒模型。

 

參考:
Operators (bpy.ops)
Operator (bpy.struct)
Blender interface with Python scripts


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM