To create line-based renderings, such as blueprints or 3D to 2D stylizations, an additional “Freestyle” render engine is usually used with the main render engine. Edges that should be clearly outlined in the final render must be marked as “freestyle” so that the Freestyle render engine can process them.
As with almost all mesh structure in Blender, “freestyle” marked edges can be processed using the Blender Python API.
Each mesh edge has a “use_freestyle_mark” property, which determines whether the edge is marked as “freestyle” – the value is True, or not – False.
We can check the value of this property for one edge of the active mesh:
1 2 3 |
print(bpy.context.object.data.edges[82].use_freestyle_mark) # True |
Or get a list of all its edges marked as “freestyle”:
1 2 3 4 |
freestyle_edges = [edge for edge in bpy.context.object.data.edges if edge.use_freestyle_mark] print(freestyle_edges) #[bpy.data.meshes['Suzanne'].edges[82], bpy.data.meshes['Suzanne'].edges[83], ...] |
To mark an edge as “freestyle”, we can simply change the value of this property. For example, let’s mark “freestyle” all edges with indices from 100 to 300. The mesh must be in Object mode.
1 2 3 |
for edge in bpy.context.object.data.edges: if 300 >= edge.index >= 100: edge.use_freestyle_mark = True |
Working with the “freestyle” edge property using a bmesh object presents some challenges.
Although the bmesh object has a “freestyle” layer for edges, and we can get a separate data layer for “freestyle”,
1 2 3 4 5 6 7 8 |
bm.edges.layers.freestyle # <BMLayerCollection object at 0x0000029DAD1B9950> freestyle_layer = bm.edges.layers.freestyle.verify() print(freestyle_layer) # <BMLayerItem object at 0x0000029DAD1BB150> |
the data structure returns us a NotImplemented error.
1 2 3 |
bm.edges[0][freestyle_layer] # NotImplemented |
We can control whether an edge is marked as “freestyle” when working with a bmesh object by relating the edge indices of the base mesh and the bmesh.
First, we get the indexes of the edges marked “freestyle” from the base mesh:
1 |
freestyle_edges_ids = [edge.index for edge in bpy.context.object.data.edges if edge.use_freestyle_mark] |
Then, in the bmesh object, we can check whether the index of the current edge matches the resulting set of edge indices.
1 2 3 4 5 6 7 8 |
bm = bmesh.from_edit_mesh(bpy.context.object.data) bm.edges.ensure_lookup_table() for edge in bm.edges: if edge.index in freestyle_edges_ids: print('bmedge:', edge) bm.free() |