{"id":11912,"date":"2026-01-05T19:11:00","date_gmt":"2026-01-06T00:11:00","guid":{"rendered":"https:\/\/www.rushworth.us\/lisa\/?p=11912"},"modified":"2026-01-21T12:19:48","modified_gmt":"2026-01-21T17:19:48","slug":"blender-python-script-to-build-bases-for-chess-pieces","status":"publish","type":"post","link":"https:\/\/www.rushworth.us\/lisa\/?p=11912","title":{"rendered":"Blender &#8211; Python Script to Build Bases for Chess Pieces"},"content":{"rendered":"\n<p>Originally, I wanted to sculpt the entire thing in python, but it appears that the programmatic interface only works in defined shapes. I <em>guess<\/em> I could construct millions of tiny triangles? polygons? to create cats &#8230; but I suspect that using the actual sculpting tools is going to be the easier approach.<\/p>\n\n\n\n<p><em>However<\/em>, the <em>base<\/em> of each piece seems perfect for a script. This will ensure consistency in my chess pieces (and let me play around with the Python approach since I think it is really cool that Blender takes Python code!). I am making decorated cylinders onto which my figures will sit.  <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nimport bpy\nimport bmesh\nimport math\n\nINCH = 0.0254  # meters per inch\n\nparams = {\n    # Cylinder base size\n    &quot;base_diameter_in&quot;: 1.75,\n    &quot;base_height_in&quot;: 0.25,\n\n    # Wreath hemispheres\n    &quot;hemi_count&quot;: 24,\n    &quot;hemi_radius_in&quot;: 0.05,\n    &quot;hemi_offset_in&quot;: 0.125,  # inward from base outer edge\n\n    # Collection\n    &quot;collection_name&quot;: &quot;Chess_Base&quot;,\n}\n\ndef inch(v): \n    return v * INCH\n\ndef ensure_collection(name):\n    if name in bpy.data.collections:\n        return bpy.data.collections&#x5B;name]\n    col = bpy.data.collections.new(name)\n    bpy.context.scene.collection.children.link(col)\n    return col\n\nCOL = ensure_collection(params&#x5B;&quot;collection_name&quot;])\n\ndef build_base():\n    base_r = inch(params&#x5B;&quot;base_diameter_in&quot;]) \/ 2.0\n    base_h = inch(params&#x5B;&quot;base_height_in&quot;])\n    # Place the base so its top is at Z = base_h (sitting on Z=0 plane)\n    bpy.ops.mesh.primitive_cylinder_add(radius=base_r, depth=base_h, location=(0, 0, base_h \/ 2.0))\n    base = bpy.context.active_object\n    base.name = &quot;Chess_Base_Cylinder&quot;\n    # Link explicitly to target collection (in case active collection differs)\n    if base.name not in COL.objects:\n        COL.objects.link(base)\n    return base\n\ndef make_hemisphere_mesh(radius_m, segments=32, rings=16):\n    bpy.ops.mesh.primitive_uv_sphere_add(radius=radius_m, segments=segments, ring_count=rings, location=(0, 0, 0))\n    sph = bpy.context.active_object\n    bm = bmesh.new()\n    bm.from_mesh(sph.data)\n    # Keep the top hemisphere: delete vertices with z &lt; 0 (tolerance to avoid floating error)\n    to_delete = &#x5B;v for v in bm.verts if v.co.z &lt; -1e-7]\n    if to_delete:\n        bmesh.ops.delete(bm, geom=to_delete, context=&#039;VERTS&#039;)\n    bm.to_mesh(sph.data)\n    bm.free()\n    hemi_mesh = sph.data\n    hemi_mesh.name = &quot;Hemisphere_Mesh&quot;\n    # Remove the temporary object but keep the mesh datablock\n    bpy.data.objects.remove(sph, do_unlink=True)\n    return hemi_mesh\n\ndef build_wreath_hemispheres(hemi_mesh):\n    base_r = inch(params&#x5B;&quot;base_diameter_in&quot;]) \/ 2.0\n    base_h = inch(params&#x5B;&quot;base_height_in&quot;])\n    ring_r = base_r - inch(params&#x5B;&quot;hemi_offset_in&quot;])\n    count = params&#x5B;&quot;hemi_count&quot;]\n\n    hemis = &#x5B;]\n    for i in range(count):\n        theta = (i \/ count) * 2.0 * math.pi\n        cx = ring_r * math.cos(theta)\n        cy = ring_r * math.sin(theta)\n        obj = bpy.data.objects.new(f&quot;Hemi_{i:02d}&quot;, hemi_mesh)\n        # Flat face of hemisphere (its equator at local Z=0) sits on base top (Z=base_h)\n        obj.location = (cx, cy, base_h)\n        COL.objects.link(obj)\n        hemis.append(obj)\n\n    # Join hemispheres into a single object\n    bpy.ops.object.select_all(action=&#039;DESELECT&#039;)\n    for o in hemis:\n        o.select_set(True)\n    bpy.context.view_layer.objects.active = hemis&#x5B;0]\n    bpy.ops.object.join()\n    wreath = bpy.context.active_object\n    wreath.name = &quot;Wreath_Hemispheres&quot;\n    return wreath\n\ndef build_all():\n    base = build_base()\n    hemi_mesh = make_hemisphere_mesh(inch(params&#x5B;&quot;hemi_radius_in&quot;]))\n    wreath = build_wreath_hemispheres(hemi_mesh)\n    print(&quot;Built:&quot;, base.name, wreath.name)\n\nbuild_all()\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"<p>Originally, I wanted to sculpt the entire thing in python, but it appears that the programmatic interface only works in defined shapes. I guess I could construct millions of tiny triangles? polygons? to create cats &#8230; but I suspect that using the actual sculpting tools is going to be the easier approach. However, the base &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2163],"tags":[2166,243,1106,2158,51,2164],"class_list":["post-11912","post","type-post","status-publish","format-standard","hentry","category-blender-3d-printing","tag-3d-modeling","tag-3d-printing","tag-art","tag-blender","tag-crafts","tag-design"],"_links":{"self":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/11912","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11912"}],"version-history":[{"count":1,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/11912\/revisions"}],"predecessor-version":[{"id":11913,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/11912\/revisions\/11913"}],"wp:attachment":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11912"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11912"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11912"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}