Implementing surface subdivision schemes with BMesh

Hi all,

In order to get familiar with BMesh, I just started translating my MATLAB implementations of surface subdivision schemes to Blender, using the Python console. Since I couldn’t find a comprehensive tutorial on how to use BMesh (I did find the Python API though), I’m not entirely sure whether my approach is correct. Concisely described:

I work in Edit Mode, so therefore I use from_edit_mesh(). Next, I use the components from this current BMesh to create a new BMesh from scratch. My approach in MATLAB was to first create all new vertices, then the (half)edges and finally the faces. But it seems that in Blender/BMesh I only need to create the new verts and faces, since the edges and loops are added automatically?

More to the point, once this new BMesh is finished, how can I then display it? The function update_edit_mesh() requires a Mesh type, not a BMesh type. And when I try to use to_mesh() to convert my new BMesh to an existing Mesh, it says “Mesh is in edit mode”. How should I handle this?

The idea is to start with the implementation of Catmull-Clark (I know it is already available in Blender) and Loop subdivision, including the rules for boundaries and creases, using some improved stencils. I noticed that an edge in a BMesh doesn’t have a crease property, why not? This might slightly complicate the support for creases in the surface. Additionally, it should also be possible to mark a vertex as a sharp/corner vertex - there doesn’t seem to be a property for this yet.

Finally, I also implemented the limit surface in MATLAB, i.e. the parametrization of the resulting surface after virtually applying the subdivision scheme an infinite number of times. Would this be useful for Blender somehow? Apart from NURBS/B-Splines I’m not sure whether it is possible to use parametric surfaces (i.e. using basis functions) in Blender?

Interesting project. I was playing around with subdivision in python too for a bit, to experiment with how to do rounded vertex bevel (which is implemented using a version of subdivision that keeps the borders where they are).

Yes.

More to the point, once this new BMesh is finished, how can I then display it? The function update_edit_mesh() requires a Mesh type, not a BMesh type. And when I try to use to_mesh() to convert my BMesh to an existing Mesh, it says “Mesh is in edit mode”. How should I handle this?

Use

bmesh.update_edit_mesh(context.active_object.data, tessface=True, destructive=True)

The idea is to start with the implementation of Catmull-Clark (I know it is already there) and Loop subdivision, including the rules for boundaries and creases, using some improved stencils. I noticed that an edge in a BMesh doesn’t have a crease property, why not?

You have to get the crease property from a custom data layer in the bmesh. See http://www.blender.org/documentation/blender_python_api_2_65_9/bmesh.html#customdata-access

Thanks for your answer! I’m not quite sure how the bmesh.update_edit_mesh works — how does it know which BMesh instance to use? To illustrate, my current workflow is as follows:

:: Open a (previously modeled) simple object
:: Switch to Edit Mode
:: Create a pointer to the current (regular) mesh:

CurrentMesh = bpy.context.edit_object.data

:: Convert this regular mesh to a BMesh instance:

CurrentBMesh = bmesh.from_edit_mesh(CurrentMesh)

:: Create a new BMesh instance:

NewBMesh = bmesh.new()

:: Edit this new BMesh instance (i.e. add components like verts and faces)
:: Now, how to display this new BMesh?

from_edit_mesh() gives you a bmesh object, which is “linked” to that edit mesh. You could move verts or something similar in PyConsole, then click in the 3d view to force an update. The changes will magically appear. Instead of clicking inside the viewport, you can also use Mesh.update()

However, the appropriate method to use is apparently bmesh.update_edit_mesh. As there is this “magic” connection between a bmesh object and an edit mesh, you don’t call this function on a bmesh object, nor is it a bmesh object method. Instead, you supply the edit mesh that is “linked” to the bmesh and it will receive the changes made to the bmesh.

http://www.blender.org/documentation/blender_python_api_2_65_9/bmesh.html#bmesh.update_edit_mesh

me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
#do something with bm
bmesh.update_edit_mesh(me) # me, not bm

If you wanna create a new mesh using bmesh, there’s no need for from_edit_mesh(), see this example:

# Create new mesh datablock
me = bpy.data.meshes.new("BMesh")

# bmesh to mesh
NewBMesh.to_mesh(me)
me.update() # not sure if you could use update_edit_mesh() here as me isn't in edit mode...

# Link to scene
ob = bpy.data.objects.new("BMesh", me)
bpy.context.scene.objects.link(ob)
bpy.context.scene.update()