Beginner - Verification request

The script below does what I wanted (which isn’t so bad…). Could you tell me if there are any notable improvements to be made to it (just in the spirit of learning).

Thank you so much !

import bpy
import bmesh
from mathutils import *

name = "cylinder"
mesh_data = bpy.data.meshes.new(f"{name}_data")
cyl_obj = bpy.data.objects.new(name, mesh_data)
bpy.context.scene.collection.objects.link(cyl_obj)

bm = bmesh.new()
bm.from_mesh(cyl_obj.data)

bmesh.ops.create_cone(bm,
                cap_ends=True,
                cap_tris=False,
                segments=72,
                radius1=1,
                radius2=1,
                depth=2,
                matrix=Matrix.Identity(4),
                calc_uvs=False)
bm.to_mesh(cyl_obj.data)
cyl_obj.data.update()
bm.free()

name = "sphere"
mesh_data = bpy.data.meshes.new(f"{name}_data")
sph_obj = bpy.data.objects.new(name, mesh_data)
bpy.context.scene.collection.objects.link(sph_obj)
bm = bmesh.new()
bm.from_mesh(sph_obj.data)

mat = Matrix.Translation((0,0,1))
bmesh.ops.create_uvsphere(bm,u_segments=36, v_segments=36, radius=1,matrix=mat)
bm.to_mesh(sph_obj.data)
sph_obj.data.update()
bm.free()

# add the modifier and change settings

cyl_obj.modifiers.new(name = "Boolean", type = 'BOOLEAN')

# DIFFERENCE UNION or INTERSECT
cyl_obj.modifiers.get("Boolean").operation = "DIFFERENCE"
cyl_obj.modifiers.get("Boolean").object = sph_obj


sph_obj.hide_viewport = True

I don’t know of any specific ways to improve your script, but I thought it might be fun to look at the end result, and see if I could create it using a different method.

I usually try to avoid booleans if I can, as I find they can be intensive operations, but there’s nothing wrong with using them.

There’s usually a few different ways to accomplish the same thing in Blender, so, in the spirit of learning, here is an alternate method that involves operators and toggling between modes to refresh data:

import bpy

bpy.ops.mesh.primitive_uv_sphere_add(enter_editmode=True)

vertices = bpy.context.object.data.vertices

bpy.ops.mesh.select_all(action='DESELECT')

bpy.ops.object.editmode_toggle()

for vert in vertices:
    vert.select = True if vert.co[2] > 0.1 else False

bpy.ops.object.editmode_toggle()
        
bpy.ops.mesh.delete(type='VERT')

bpy.ops.object.editmode_toggle()

for vert in vertices:
    vert.select = True if vert.co[2] > -0.1 else False
           
bpy.ops.object.editmode_toggle()

bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value":(-0, -0, -2)})

bpy.ops.mesh.edge_face_add()

bpy.ops.object.editmode_toggle()

bpy.ops.transform.translate(value=(0, 0, 1))
1 Like

Hi,
thank you very much.

I’tried to do some variation using your approach but with bmesh library:

    name = "my_shape"
    mesh_data = bpy.data.meshes.new(f"{name}_data")
    my_obj = bpy.data.objects.new(name, mesh_data)
    bpy.context.scene.collection.objects.link(my_obj)
    bm = bmesh.new()
    bm.from_mesh(my_obj.data)
    bmesh.ops.create_uvsphere(bm,u_segments=36, v_segments=36, radius=1)
    verts_select = set()
    for v in bm.verts:
        if v.co.z>0.1:
            verts_select.add(v)
    bmesh.ops.delete(bm, geom=list(verts_select), context="VERTS")
    ring_select= set()
    for e in bm.edges:
        if e.is_boundary:
            ring_select.add(e)
    ring_edges = [ele for ele in ring_select
                   if isinstance(ele, bmesh.types.BMEdge)]  
    ret = bmesh.ops.extrude_edge_only(bm,edges=ring_edges)
    geom_extrude = ret["geom"]
    verts_extrude = [ele for ele in geom_extrude if isinstance(ele, bmesh.types.BMVert)]
    edges_extrude = [ele for ele in geom_extrude if isinstance(ele, bmesh.types.BMVert)]
    bmesh.ops.translate(bm,verts=verts_extrude,vec=(0.0, 0.0, -2.0))
    bm.faces.new(edges_extrude)
    bmesh.ops.translate(bm,verts=bm.verts,vec=(0.0, 0.0, 1.0))
    bm.to_mesh(my_obj.data)
    my_obj.data.update()
    bm.free()

I learned a lot by doing this exercise. Thanks a lot.
If you have other ideas or if anyone else sees another way to achieve the same result, don’t hesitate!

However, it seems that the result is not quite the same and I don’t understand why?

spectralvectors version:
image

bmesh version
image

I didn’t realize that you were using more segments and rings than the default UV Sphere.

Changing the second line to:

bpy.ops.mesh.primitive_uv_sphere_add(enter_editmode=True, segments=36, ring_count=36)

will produce a result with the same number of Triangles. (though the rest of the stats won’t line up).

My best guess at the discrepancy is that the Boolean operation creates faces on both sides of the sphere/cylinder at intersection points, but my method only creates a single face per side when it extrudes down, so they end up looking more or less the same, but the face count is slightly different.