python 等腰三角形的性质_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!

importbpyclassHelloWorldOperator(bpy.types.Operator):

bl_idname= "wm.hello_world"bl_label= "Hello World"

defexecute(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)

>>> 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。

importbpyclassHelloWorldOperator(bpy.types.Operator):

bl_idname= "wm.hello_world"bl_label= "Hello World"bl_description= "This is an operator test."

defexecute(self, context):#print("Hello World!")

self.report({'INFO'}, "Hello World!")return {'FINISHED'}definvoke(self, context, event):

wm=context.window_managerreturnwm.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),顶点都是整数哦!

importbpyfrom math importsqrtfrom mathutils importVectorclassMakeTetrahedron(bpy.types.Operator):

bl_idname= "mesh.make_tetrahedron"bl_label= "Add Tetrahedron"

definvoke(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分子的棍棒模型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值