# How to avoid pinching on concave shapes with the bevel modifier and subsurf?

How can I setup the Bevel modifier to only work on 30 degrees angle and avoid pinching at the same time on convex shapes?

I want to avoid pinching generated on concave shapes to replace the manual edge loops or sharp edges workflow for hard surface models:

It's interesting to have a look at why this happens. This is a transition from 2x Simple subdiv to Catmull-Clark subdiv on a corner beveled with one segment.

It's not 'pinching' in the same sense as the pinching you get at say, the poles of a UV Sphere. It's more like 'leapfrogging'. Under the CC algorithm,the edges of small faces that were next to large faces in their own plane move further than small faces that were next to small faces at an angle to them, to the point that they overtake. This effect is compounded with each iteration, and the smaller the bevel by comparison with surrounding faces, the worse it gets.

I've never been able to think of a solution to fully automate away the need for hand-modified holding loops, or using creases to pin vertices and prevent them from being moved by CC.

Personally I tend to think in 3's, (put in a bevel with 2 segments) and not restrict by angle. Then the extra edge-loops an be 'tied off' (reduced from 3 to 1) elsewhere on the model, if needed. But that's still hand work.

• This probably the best answer you're going to get. Dec 8 '18 at 21:23

The angles of concave and convex edges have a different sign. The bevel modifier just ignores it.

Luckily, the bmesh module has both, a calc_face_angle and a calc_face_angle_signed function. For concave edges, the latter will return a negative angle.

1. Go into edit mode and switch to edge selection.
2. Execute the script. (see below)
3. Now that the concave edges are selected press CtrlE and choose Edge Bevel Weight, then enter 1Enter.
4. In the bevel modifier, choose weights as the delimiting input.
import bpy
import bmesh
import math

return deg / 180 * math.pi

obj = bpy.context.object

if obj.mode != 'EDIT':
raise Exception("Go in edge selection edit mode!")
bm = bmesh.new()
bm = bmesh.from_edit_mesh(obj.data)
bm.edges.ensure_lookup_table()

for edge in bm.edges:
edge.select = False
if not edge.is_boundary:
angle = edge.calc_face_angle_signed()
edge.select = True

bmesh.update_edit_mesh(obj.data)


The first import check in the script is edge.is_boundary, where we assure that the current edge is in fact between to face and will have an angle.

The angle is compared in the snippet if (angle < deg_to_rad(0)). You can also modify this line to accept whatever condition.

• It would be great if all the select-by-angle features of the Blender interface included a min and max entry, making the distinction between positive and negative angles. Mar 23 '19 at 6:33

I get around this procedurally using two bevel modifiers (with vertex groups), one for convex and one for concave edges. Adding some edge loops may be needed, just enough so that the vertices assigned to the groups define only the edges wanted.

AFAIK, there are no ways to tell a bevel modifier to work only on a specific angle, he only works on an "equal or greater than X° angle". Maybe mark by hand the edges you need to bevel, go in edit mode, select the edges, increase their edge bevel weight, then set the bevel modifier to weight mode.

• Also, Bevel modifier is being reworked for 2.8. Maybe this issue will not occur anymore: devtalk.blender.org/t/gsoc-2018-bevel-improvements Nov 28 '18 at 9:22
• I know this post is from two years ago but I'm still having trouble with it. From what I can find the other posts on this topic are giving the same solutions as here. Apr 15 '20 at 19:03

What you need to do is to set the bevel weight to one (blue edges in the picture below) on one edge or edgeloop that originates from the problematic area. This will make the geometry around the edge flow to a new direction, preventing the subsurf modifier to pull geometry over the concave edge's vertices. If the edge you mark lays on a flat surface you don't need to select it's entire edge loop (blue dotted line).

Try adding edge split after beveling. That usually works for me