1
$\begingroup$

This looks cool and all, but it's beveled in the wrong direction. How can I flip the direction it bevels, so it looks more like a rounded cube, rather than a rounded plus-sign?

import bpy
import bmesh

from bpy.props import (
        BoolProperty,
        BoolVectorProperty,
        FloatProperty,
        FloatVectorProperty,
        IntProperty,
        )

#Returns all edges parallel to x-axis:
def get_x_parallel_edges(bm):
    #The returned list of edges:
    e_list = []

    #Look for all the edges that
    #run parallel to the x-axis:
    for f in bm.faces:
        for e in f.edges:
            #Rename the coords:
            ey0 = e.verts[0].co.y
            ey1 = e.verts[1].co.y
            ez0 = e.verts[0].co.z
            ez1 = e.verts[1].co.z
            #Check them:
            if ey0 == ey1 and ez0 == ez1:
                #Check for duplicates:
                is_duplicate = False
                for el in e_list:
                    if el == e:
                        is_duplicate = True
                if not is_duplicate:
                    e_list += [e]

    return e_list

#Break a list of edges
#into a list of verts:
def get_v_from_e(edges):
    #The returned list of verts:
    v_list = []

    #Break apart the edges into verts:
    for e in edges:
        for v in e.verts:
            #Check for duplicates:
            is_duplicate = False
            for vl in v_list:
                if vl == v:
                    is_duplicate = True
            if not is_duplicate:
                v_list += [v]
    return v_list

class AddBevCube(bpy.types.Operator):
    bl_idname = "mesh.primitive_bev_cube_add"
    bl_label = "Add Beveled Cube"
    bl_options = {'REGISTER', 'UNDO'}

    length = FloatProperty(
            name="Length",
            description="Box Length",
            min=0.01, max=100.0,
            default=4.0,
            )
    width = FloatProperty(
            name="Width",
            description="Box Width",
            min=0.01, max=100.0,
            default=3.0,
            )
    height = FloatProperty(
            name="Height",
            description="Box Height",
            min=0.01, max=100.0,
            default=2.0,
            )
    bev_seg = IntProperty(
            name="Segments",
            description="Bevel Segments",
            min=1, max=100,
            default=3,
            )
    bev_offset = FloatProperty(
            name="Offset",
            description="Bevel Offset",
            min=0.01, max=100.0,
            default=0.125,
            )

    def execute(self, context):

        #Rename the variables:
        l = self.length
        w = self.width
        h = self.height
        seg = self.bev_seg
        b_offset = self.bev_offset

        #Make the cube object stuff:
        mesh = bpy.data.meshes.new("cube")
        cube_obj = bpy.data.objects.new("Cube_Obj", mesh)

        scene = bpy.context.scene
        scene.objects.link(cube_obj)
        bm = bmesh.new()

        #Add the cube:
        bmesh.ops.create_cube(bm, size=0.5)
        #Apply size:
        bmesh.ops.scale(bm, vec=(l, w, h))

        #First, get the verts and edges:
        e_geom = get_x_parallel_edges(bm)
        v_geom = get_v_from_e(e_geom)
        #Now bevel:
        bmesh.ops.bevel(bm, 
                        geom=v_geom[:] + e_geom[:], 
                        offset=b_offset, 
                        offset_type=0, 
                        segments=seg,
                        clamp_overlap=True)

        bm.to_mesh(mesh)
        mesh.update()

        return {'FINISHED'}


def menu_func(self, context):
    self.layout.operator(AddBevCube.bl_idname, icon='MESH_CUBE')


def register():
    bpy.utils.register_class(AddBevCube)
    bpy.types.INFO_MT_mesh_add.append(menu_func)


def unregister():
    bpy.utils.unregister_class(AddBevCube)
    bpy.types.INFO_MT_mesh_add.remove(menu_func)

if __name__ == "__main__":
    register()
$\endgroup$
3
$\begingroup$

Set the profile

enter image description here

basically your issue was using the default value of 0.0 for the profile property of the bevel operator. I have set it to 0.5 below. Might be a contender for another operator property.

Test code including, what I believe are simpler, routines for finding parallel edges and the vertices they contain. also added some notes re upgrading to 2.8

import bpy
import bmesh
from mathutils import Vector

from bpy.props import (
        BoolProperty,
        BoolVectorProperty,
        FloatProperty,
        FloatVectorProperty,
        IntProperty,
        )

#Test if edge e parallel to vector v:
def parallel(e, v, eps=1e-6):
    # normalized edge direction vector
    d = (e.verts[1].co - e.verts[0].co).normalized()
    return abs(v.normalized().dot(d)) >= 1 - eps


class MESH_OT_primitive_bev_cube_add(bpy.types.Operator):
    '''Add Beveled Cube'''
    bl_idname = "mesh.primitive_bev_cube_add"
    bl_label = "Add Beveled Cube"
    bl_options = {'REGISTER', 'UNDO'}

    length = FloatProperty(
            name="Length",
            description="Box Length",
            min=0.01, max=100.0,
            default=4.0,
            )
    width = FloatProperty(
            name="Width",
            description="Box Width",
            min=0.01, max=100.0,
            default=3.0,
            )
    height = FloatProperty(
            name="Height",
            description="Box Height",
            min=0.01, max=100.0,
            default=2.0,
            )
    bev_seg = IntProperty(
            name="Segments",
            description="Bevel Segments",
            min=1, max=100,
            default=3,
            )
    bev_offset = FloatProperty(
            name="Offset",
            description="Bevel Offset",
            min=0.01, max=100.0,
            default=0.125,
            )

    def execute(self, context):

        #Make the cube object stuff:
        mesh = bpy.data.meshes.new("cube")
        cube_obj = bpy.data.objects.new("Cube_Obj", mesh)

        scene = context.scene
        scene.objects.link(cube_obj)
        #scene.collection.objects.link(cube_obj)
        bm = bmesh.new()

        #Add the cube:
        bmesh.ops.create_cube(bm, size=0.5)
        #Apply size:
        bmesh.ops.scale(bm, 
                verts=bm.verts,
                vec=(self.length, self.width, self.height))

        #First, get the verts and edges:
        x_axis = Vector((1, 0, 0))
        e_geom = [e for e in bm.edges if parallel(e, x_axis)]
        v_geom = set(v for e in e_geom for v in e.verts)
        #Now bevel:
        bmesh.ops.bevel(bm, 
                        geom=list(v_geom) + e_geom[:], 
                        offset=self.bev_offset, 
                        offset_type=0,
                        # offset_type='OFFSET', 
                        profile=0.5,
                        segments=self.bev_seg,
                        clamp_overlap=True)

        bm.to_mesh(mesh)
        mesh.update()

        return {'FINISHED'}


def menu_func(self, context):
    self.layout.operator(MESH_OT_primitive_bev_cube_add.bl_idname, icon='MESH_CUBE')


def register():
    bpy.utils.register_class(MESH_OT_primitive_bev_cube_add)
    bpy.types.INFO_MT_mesh_add.append(menu_func)
    #bpy.types.VIEw3D_MT_mesh_add.append(menu_func)

def unregister():
    bpy.utils.unregister_class(MESH_OT_primitive_bev_cube_add)
    bpy.types.INFO_MT_mesh_add.remove(menu_func)
    #bpy.types.VIEw3D_MT_mesh_add.remove(menu_func)

if __name__ == "__main__":
    register()

Please note it is standard practice to set the newly created object to active and selected, as well as selecting the new geometry created.

2.7x https://blender.stackexchange.com/a/102239/15543

2.8 https://blender.stackexchange.com/a/133880/15543

$\endgroup$
  • $\begingroup$ My issue was that I thought the profile defaulted to 0.5! I was trying to set it to -0.5 at one point, too (which I realize would have clamped it to 0). Thank you! $\endgroup$ – Perregrinne May 14 at 15:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.