You are participating in Blender-Bench, a public benchmark where AI models complete the same Blender task.

Your result will be compared head-to-head with another model. Anyone on the internet can vote based on two equally important published views: a 2D rendered presentation and an interactive 3D scene exported to GLB. Treat neither view as optional; make the result clear and compelling in both.

Complete the request as well as you can. The benchmark does not prescribe a workflow or visual style; use whichever Blender techniques you consider appropriate. Make the important requirements evident in the published result, save a complete scene, and present the work clearly in every requested output.

The 2D presentation is rendered by the benchmark from your saved scene using Cycles at 1536 x 1536, 64 samples, denoising enabled, and GPU acceleration when available with a CPU fallback. It is the native-fidelity view of the Blender scene, so you may use Blender's full feature set. Preview and validate your materials, lighting, color management, and camera composition in Cycles, and do not rely on EEVEE-only effects for the final appearance.

The interactive 3D view is a best-effort GLB export containing geometry, compatible materials, the contestant camera, and supported lights. Because glTF cannot represent every Blender feature, native effects such as particles, hair or curves, volumes, simulations, and some procedural geometry may appear only in the 2D render. The benchmark may also generate a separate preview GLB by baking supported procedural material inputs to textures; this does not convert unsupported geometry or guarantee exact parity with Blender. When practical, keep the core form and scene readable in the 3D view while using the 2D presentation to show native Blender features faithfully.

## Harness Instructions

You are writing a single Python script for Blender 5.1 using the bpy API. The scene starts empty. Your script must build everything the user's prompt asks for.

You are building a real three-dimensional scene, and evaluators judge the whole scene and your final render side by side — an interactive 3D view and a benchmark-generated 360° camera orbit rendered in Cycles from your saved scene appear next to your presentation render, so forms that only read correctly from one angle will show. Build genuine 3D first, then present it well: before you finish, set up a camera and lighting to frame a single, well-composed presentation image of your result — a good scene that happens to have a well-placed camera and lights. The final benchmark capture overrides the scene render settings and renders in Cycles at 1536x1536, 64 samples, with denoising and GPU acceleration (CPU fallback). Preview and validate materials, lighting, color management, and composition in Cycles; do not rely on EEVEE-only effects. Use whatever Blender features best serve the result; a best-effort GLB export is also provided for interactive inspection, and features glTF cannot represent are not expected to survive it.

You get one attempt: the script runs once, headless, with no feedback and no chance to iterate, so write robust code. Reply with exactly one fenced Python code block containing the complete script and nothing else.


## Task

Complete the following Blender task:

<task>

A classical head bust in the Greco-Roman tradition — the kind of plaster cast after the antique that sits in every drawing atelier — presented alone on a pedestal under studio light. This is a pure sculpting test: no costume, no scene, no story to hide behind. The face is the whole assignment.

The head. An idealized classical head in the manner of the great antique casts (a David, an Apollo, a Doryphoros — the specific reference is free, the idiom is not): calm, symmetric, youthful-heroic features with the canonical structure that atelier casts exist to teach. The planes of the face must be right — brow ridge stepping to the nose, clear cheekbone structure, the philtrum and the strong classical mouth, eyes with sculpted (not textured) iris-and-pupil suggestion or the blank antique eye — choose one convention and hold it. Hair in sculpted classical curls or waves with real clumped mass, not a smooth cap and not noise. The head sits on a neck cut off in the traditional bust termination — a clean geometric truncation into a small integral socle, or shoulders ending in the classic broken-edge cut.

Anatomy is judged mercilessly here. A slightly stylized but structurally correct head beats an uncanny near-likeness. Asymmetry from sculpting is human and fine; collapsed eye sockets, pasted-on ears, or a rubber jawline are not.

Material — plaster or marble, committed. Either: matte white atelier plaster with the subtlest subsurface scattering, faint seam lines from the casting mold, small chips at the socle edge, and a whisper of dust-grey in the recesses; or white statuary marble with soft SSS depth and delicate grey veining that follows the form. Pick one and make it convincing at close range. No pure-white shadeless material — the render must prove the material has depth.

Pedestal & setting. A simple column pedestal or plinth, a neutral studio backdrop, nothing else. One soft key light placed to rake the facial planes the way a drawing instructor would set it — form shadow down one side of the nose and cheek, a clear terminator, gentle bounce fill so the shadow side keeps its planes. The classic atelier lighting is part of the brief.

Composition. Camera at the bust's eye level, three-quarter view, head filling most of the frame. The final image should look like a photograph from a cast collection catalogue.

</task>


[System]
You are participating in Blender-Bench, a public benchmark where AI models complete the same Blender task.

Your result will be compared head-to-head with another model. Anyone on the internet can vote based on two equally important published views: a 2D rendered presentation and an interactive 3D scene exported to GLB. Treat neither view as optional; make the result clear and compelling in both.

Complete the request as well as you can. The benchmark does not prescribe a workflow or visual style; use whichever Blender techniques you consider appropriate. Make the important requirements evident in the published result, save a complete scene, and present the work clearly in every requested output.

The 2D presentation is rendered by the benchmark from your saved scene using Cycles at 1536 x 1536, 64 samples, denoising enabled, and GPU acceleration when available with a CPU fallback. It is the native-fidelity view of the Blender scene, so you may use Blender's full feature set. Preview and validate your materials, lighting, color management, and camera composition in Cycles, and do not rely on EEVEE-only effects for the final appearance.

The interactive 3D view is a best-effort GLB export containing geometry, compatible materials, the contestant camera, and supported lights. Because glTF cannot represent every Blender feature, native effects such as particles, hair or curves, volumes, simulations, and some procedural geometry may appear only in the 2D render. The benchmark may also generate a separate preview GLB by baking supported procedural material inputs to textures; this does not convert unsupported geometry or guarantee exact parity with Blender. When practical, keep the core form and scene readable in the 3D view while using the 2D presentation to show native Blender features faithfully.

## Harness Instructions

You are writing a single Python script for Blender 5.1 using the bpy API. The scene starts empty. Your script must build everything the user's prompt asks for.

You are building a real three-dimensional scene, and evaluators judge the whole scene and your final render side by side — an interactive 3D view and a benchmark-generated 360° camera orbit rendered in Cycles from your saved scene appear next to your presentation render, so forms that only read correctly from one angle will show. Build genuine 3D first, then present it well: before you finish, set up a camera and lighting to frame a single, well-composed presentation image of your result — a good scene that happens to have a well-placed camera and lights. The final benchmark capture overrides the scene render settings and renders in Cycles at 1536x1536, 64 samples, with denoising and GPU acceleration (CPU fallback). Preview and validate materials, lighting, color management, and composition in Cycles; do not rely on EEVEE-only effects. Use whatever Blender features best serve the result; a best-effort GLB export is also provided for interactive inspection, and features glTF cannot represent are not expected to survive it.

You get one attempt: the script runs once, headless, with no feedback and no chance to iterate, so write robust code. Reply with exactly one fenced Python code block containing the complete script and nothing else.

[User]
## Task

Complete the following Blender task:

<task>

A classical head bust in the Greco-Roman tradition — the kind of plaster cast after the antique that sits in every drawing atelier — presented alone on a pedestal under studio light. This is a pure sculpting test: no costume, no scene, no story to hide behind. The face is the whole assignment.

The head. An idealized classical head in the manner of the great antique casts (a David, an Apollo, a Doryphoros — the specific reference is free, the idiom is not): calm, symmetric, youthful-heroic features with the canonical structure that atelier casts exist to teach. The planes of the face must be right — brow ridge stepping to the nose, clear cheekbone structure, the philtrum and the strong classical mouth, eyes with sculpted (not textured) iris-and-pupil suggestion or the blank antique eye — choose one convention and hold it. Hair in sculpted classical curls or waves with real clumped mass, not a smooth cap and not noise. The head sits on a neck cut off in the traditional bust termination — a clean geometric truncation into a small integral socle, or shoulders ending in the classic broken-edge cut.

Anatomy is judged mercilessly here. A slightly stylized but structurally correct head beats an uncanny near-likeness. Asymmetry from sculpting is human and fine; collapsed eye sockets, pasted-on ears, or a rubber jawline are not.

Material — plaster or marble, committed. Either: matte white atelier plaster with the subtlest subsurface scattering, faint seam lines from the casting mold, small chips at the socle edge, and a whisper of dust-grey in the recesses; or white statuary marble with soft SSS depth and delicate grey veining that follows the form. Pick one and make it convincing at close range. No pure-white shadeless material — the render must prove the material has depth.

Pedestal & setting. A simple column pedestal or plinth, a neutral studio backdrop, nothing else. One soft key light placed to rake the facial planes the way a drawing instructor would set it — form shadow down one side of the nose and cheek, a clear terminator, gentle bounce fill so the shadow side keeps its planes. The classic atelier lighting is part of the brief.

Composition. Camera at the bust's eye level, three-quarter view, head filling most of the frame. The final image should look like a photograph from a cast collection catalogue.

</task>

[System]
You are participating in Blender-Bench, a public benchmark where AI models complete the same Blender task.

Your result will be compared head-to-head with another model. Anyone on the internet can vote based on two equally important published views: a 2D rendered presentation and an interactive 3D scene exported to GLB. Treat neither view as optional; make the result clear and compelling in both.

Complete the request as well as you can. The benchmark does not prescribe a workflow or visual style; use whichever Blender techniques you consider appropriate. Make the important requirements evident in the published result, save a complete scene, and present the work clearly in every requested output.

The 2D presentation is rendered by the benchmark from your saved scene using Cycles at 1536 x 1536, 64 samples, denoising enabled, and GPU acceleration when available with a CPU fallback. It is the native-fidelity view of the Blender scene, so you may use Blender's full feature set. Preview and validate your materials, lighting, color management, and camera composition in Cycles, and do not rely on EEVEE-only effects for the final appearance.

The interactive 3D view is a best-effort GLB export containing geometry, compatible materials, the contestant camera, and supported lights. Because glTF cannot represent every Blender feature, native effects such as particles, hair or curves, volumes, simulations, and some procedural geometry may appear only in the 2D render. The benchmark may also generate a separate preview GLB by baking supported procedural material inputs to textures; this does not convert unsupported geometry or guarantee exact parity with Blender. When practical, keep the core form and scene readable in the 3D view while using the 2D presentation to show native Blender features faithfully.

## Harness Instructions

You are writing a single Python script for Blender 5.1 using the bpy API. The scene starts empty. Your script must build everything the user's prompt asks for.

You are building a real three-dimensional scene, and evaluators judge the whole scene and your final render side by side — an interactive 3D view and a benchmark-generated 360° camera orbit rendered in Cycles from your saved scene appear next to your presentation render, so forms that only read correctly from one angle will show. Build genuine 3D first, then present it well: before you finish, set up a camera and lighting to frame a single, well-composed presentation image of your result — a good scene that happens to have a well-placed camera and lights. The final benchmark capture overrides the scene render settings and renders in Cycles at 1536x1536, 64 samples, with denoising and GPU acceleration (CPU fallback). Preview and validate materials, lighting, color management, and composition in Cycles; do not rely on EEVEE-only effects. Use whatever Blender features best serve the result; a best-effort GLB export is also provided for interactive inspection, and features glTF cannot represent are not expected to survive it.

You get one attempt: the script runs once, headless, with no feedback and no chance to iterate, so write robust code. Reply with exactly one fenced Python code block containing the complete script and nothing else.

[User]
## Task

Complete the following Blender task:

<task>

A classical head bust in the Greco-Roman tradition — the kind of plaster cast after the antique that sits in every drawing atelier — presented alone on a pedestal under studio light. This is a pure sculpting test: no costume, no scene, no story to hide behind. The face is the whole assignment.

The head. An idealized classical head in the manner of the great antique casts (a David, an Apollo, a Doryphoros — the specific reference is free, the idiom is not): calm, symmetric, youthful-heroic features with the canonical structure that atelier casts exist to teach. The planes of the face must be right — brow ridge stepping to the nose, clear cheekbone structure, the philtrum and the strong classical mouth, eyes with sculpted (not textured) iris-and-pupil suggestion or the blank antique eye — choose one convention and hold it. Hair in sculpted classical curls or waves with real clumped mass, not a smooth cap and not noise. The head sits on a neck cut off in the traditional bust termination — a clean geometric truncation into a small integral socle, or shoulders ending in the classic broken-edge cut.

Anatomy is judged mercilessly here. A slightly stylized but structurally correct head beats an uncanny near-likeness. Asymmetry from sculpting is human and fine; collapsed eye sockets, pasted-on ears, or a rubber jawline are not.

Material — plaster or marble, committed. Either: matte white atelier plaster with the subtlest subsurface scattering, faint seam lines from the casting mold, small chips at the socle edge, and a whisper of dust-grey in the recesses; or white statuary marble with soft SSS depth and delicate grey veining that follows the form. Pick one and make it convincing at close range. No pure-white shadeless material — the render must prove the material has depth.

Pedestal & setting. A simple column pedestal or plinth, a neutral studio backdrop, nothing else. One soft key light placed to rake the facial planes the way a drawing instructor would set it — form shadow down one side of the nose and cheek, a clear terminator, gentle bounce fill so the shadow side keeps its planes. The classic atelier lighting is part of the brief.

Composition. Camera at the bust's eye level, three-quarter view, head filling most of the frame. The final image should look like a photograph from a cast collection catalogue.

</task>

payment=(self "https://checkout.stripe.com" "https://connect-js.stripe.com" "https://js.stripe.com" "https://*.js.stripe.com" "https://hooks.stripe.com")

{"id":"gen-1784252240-fj0y3NbmCqqLD7p09CuR","object":"chat.completion","created":1784252240,"model":"openai/gpt-5.6-luna","provider":"OpenAI","system_fingerprint":null,"service_tier":"default","choices":[{"index":0,"logprobs":null,"finish_reason":"stop","native_finish_reason":"completed","message":{"role":"assistant","content":"```python\nimport bpy, math\nfrom mathutils import Vector\n\n# ------------------------------------------------------------\n# Classical atelier bust: sculptural plaster, neutral studio\n# ------------------------------------------------------------\n\n# Clear scene\nbpy.ops.object.select_all(action='SELECT')\nbpy.ops.object.delete(use_global=False)\nfor datablocks in (bpy.data.meshes, bpy.data.curves, bpy.data.materials, bpy.data.cameras, bpy.data.lights):\n    pass\n\n# Materials\ndef mat(name, color, rough=0.72, spec=0.22, subsurface=0.0):\n    m = bpy.data.materials.new(name)\n    m.diffuse_color = (*color, 1)\n    m.use_nodes = True\n    bs = m.node_tree.nodes.get(\"Principled BSDF\")\n    bs.inputs[\"Base Color\"].default_value = (*color, 1)\n    bs.inputs[\"Roughness\"].default_value = rough\n    bs.inputs[\"Specular IOR Level\"].default_value = spec\n    if \"Subsurface Weight\" in bs.inputs:\n        bs.inputs[\"Subsurface Weight\"].default_value = subsurface\n        bs.inputs[\"Subsurface Radius\"].default_value = (1.0, 0.72, 0.52)\n    return m\n\nplaster = mat(\"Warm ivory atelier plaster\", (0.72, 0.695, 0.625), 0.78, 0.18, 0.035)\nplaster_light = mat(\"Freshly worn plaster highlights\", (0.81, 0.785, 0.71), 0.75, 0.2, 0.025)\nhairmat = mat(\"Slightly darker plaster in hair recesses\", (0.49, 0.47, 0.42), 0.88, 0.12, 0.015)\nrecess = mat(\"Dust-grey recess\", (0.25, 0.24, 0.22), 0.94, 0.05, 0.0)\neye_mat = mat(\"Blank antique eye\", (0.64, 0.625, 0.56), 0.82, 0.12, 0.0)\nbackmat = mat(\"Studio warm grey\", (0.105, 0.11, 0.105), 0.92, 0.05, 0.0)\npedmat = mat(\"Pedestal plaster\", (0.57, 0.55, 0.50), 0.83, 0.15, 0.02)\nedge_mat = mat(\"Old cut edge\", (0.30, 0.285, 0.25), 0.91, 0.08, 0.0)\n\ndef smooth(obj):\n    if obj.type == 'MESH':\n        for p in obj.data.polygons:\n            p.use_smooth = True\n\ndef uv(name, loc, scale, material=plaster, seg=48, rings=32):\n    bpy.ops.mesh.primitive_uv_sphere_add(segments=seg, ring_count=rings, location=loc)\n    o = bpy.context.object\n    o.name = name\n    o.scale = scale\n    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)\n    smooth(o)\n    o.data.materials.append(material)\n    return o\n\ndef cyl(name, loc, radius, depth, material=plaster, vertices=64, bevel=0.04):\n    bpy.ops.mesh.primitive_cylinder_add(vertices=vertices, radius=radius, depth=depth, location=loc)\n    o=bpy.context.object; o.name=name\n    o.data.materials.append(material)\n    if bevel:\n        mod=o.modifiers.new(\"soft carved edge\",\"BEVEL\"); mod.width=bevel; mod.segments=3\n    smooth(o)\n    return o\n\ndef torus(name, loc, major, minor, material=hairmat, rot=(math.pi/2,0,0)):\n    bpy.ops.mesh.primitive_torus_add(major_radius=major, minor_radius=minor,\n                                    major_segments=40, minor_segments=12,\n                                    location=loc, rotation=rot)\n    o=bpy.context.object; o.name=name; o.data.materials.append(material); smooth(o)\n    return o\n\ndef curve_tube(name, pts, bevel, material=plaster, resolution=3):\n    cu=bpy.data.curves.new(name, 'CURVE')\n    cu.dimensions='3D'; cu.resolution_u=2; cu.bevel_depth=bevel; cu.bevel_resolution=resolution\n    sp=cu.splines.new('BEZIER'); sp.bezier_points.add(len(pts)-1)\n    for b,p in zip(sp.bezier_points,pts):\n        b.co=p; b.handle_left_type='AUTO'; b.handle_right_type='AUTO'\n    ob=bpy.data.objects.new(name,cu); bpy.context.collection.objects.link(ob)\n    ob.data.materials.append(material)\n    return ob\n\n# Ground and pedestal\ncyl(\"Pedestal lower plinth\", (0,0,0.32), 1.18, 0.32, pedmat, bevel=0.055)\ncyl(\"Pedestal upper step\", (0,0,0.57), 0.98, 0.20, plaster, bevel=0.035)\ncyl(\"Square-ish classical shaft\", (0,0,1.38), 0.72, 1.45, pedmat, bevel=0.045)\ncyl(\"Pedestal capital\", (0,0,2.10), 0.88, 0.18, plaster, bevel=0.035)\ncyl(\"Bust socle\", (0,0,2.30), 0.68, 0.28, plaster, bevel=0.05)\n\n# Socle cut edge / subtle casting line\nbpy.ops.mesh.primitive_torus_add(major_radius=0.61, minor_radius=0.012,\n                                  major_segments=64, minor_segments=8,\n                                  location=(0,0,2.445))\nsocline=bpy.context.object; socline.name=\"Faint mold seam at socle\"; socline.data.materials.append(edge_mat)\n\n# Neck and shoulder termination\nuv(\"Neck column\", (0,0.02,2.73), (0.47,0.43,0.72), plaster)\nuv(\"Left shoulder broken termination\", (-0.48,0.03,2.48), (0.62,0.46,0.28), plaster)\nuv(\"Right shoulder broken termination\", (0.48,0.03,2.48), (0.62,0.46,0.28), plaster)\n\n# Head mass, jaw, chin\nuv(\"Main idealized cranium\", (0,0.0,3.68), (0. ninety if False else 0.91,0.73,1.16), plaster)\nuv(\"Angular lower face\", (0,-0.08,3.18), (0.73,0.62,0.70), plaster)\nuv(\"Strong classical chin\", (0,-0.63,3.03), (0.36,0.20,0.24), plaster_light)\n\n# Ears, deliberately integrated into skull\nfor x in (-0.86,0.86):\n    uv(\"Sculpted ear\", (x,-0.02,3.60), (0.16,0.11,0. thirty if False else 0.30), plaster)\n    uv(\"Ear concha shadow\", (x, -0.125, 3.60), (0.075,0.025,0.15), recess)\n\n# Brow ridge and forehead planes\nfor x in (-0.30,0.30):\n    uv(\"Projected brow ridge\", (x,-0.665,3.98), (0.30,0.105,0.105), plaster_light)\n# central glabella\nuv(\"Glabella plane\", (0,-0.675,3.94), (0.16,0.10,0.19), plaster)\n\n# Blank antique eyes, inset almond forms\nfor x in (-0.30,0.30):\n    uv(\"Blank almond eye\", (x,-0.735,3.78), (0.205,0.045,0.095), eye_mat)\n    # upper and lower lid as sculpted arcs\n    curve_tube(\"Upper eyelid\", [(x-0.20,-0.775,3.78),(x,-0.80,3.875),(x+0.20,-0.775,3.79)], 0.026, plaster_light)\n    curve_tube(\"Lower eyelid\", [(x-0.18,-0.768,3.75),(x,-0.79,3.695),(x+0.18,-0.768,3.75)], 0.018, plaster)\n# tear ducts\nuv(\"Left tear duct\", (-0.105,-0.78,3.77), (0.045,0.025,0.04), plaster_light)\nuv(\"Right tear duct\", (0.105,-0.78,3.77), (0.045,0.025,0.04), plaster_light)\n\n# Nose: bridge, planes, tip and nostril recesses\nuv(\"Nose bridge\", (0,-0.70,3.62), (0.16,0.18,0.48), plaster_light)\nuv(\"Nose lower plane\", (0,-0.82,3.34), (0.22,0.18,0.18), plaster_light)\nuv(\"Nose tip\", (0,-0.89,3.28), (0.18,0.15,0.15), plaster_light)\nuv(\"Left alar wing\", (-0.16,-0.83,3.31), (0.13,0.11,0.10), plaster)\nuv(\"Right alar wing\", (0.16,-0.83,3.31), (0.13,0.11,0.10), plaster)\nfor x in (-0.095,0.095):\n    uv(\"Nostril shadow\", (x,-0.925,3.295), (0.055,0.018,0.027), recess)\n\n# Cheekbones and under-cheek planes\nuv(\"Left high cheekbone\", (-0.48,-0.56,3.54), (0.30,0.14,0.19), plaster_light)\nuv(\"Right high cheekbone\", (0.48,-0.56,3.54), (0.30,0.14,0.19), plaster_light)\nuv(\"Left under cheek plane\", (-0.48,-0.48,3.28), (0.33,0.11,0.20), plaster)\nuv(\"Right under cheek plane\", (0.48,-0.48,3.28), (0.33,0.11,0.20), plaster)\n\n# Philtrum, mouth, classical firm lips\ncurve_tube(\"Philtrum left ridge\", [(-0.045,-0.835,3.30),(-0.055,-0.85,3.12)], 0.022, plaster_light)\ncurve_tube(\"Philtrum right ridge\", [(0.045,-0.835,3.30),(0.055,-0.85,3.12)], 0.022, plaster_light)\ncurve_tube(\"Upper classical lip\", [(-0.27,-0.83,3.105),(-0.12,-0.88,3.145),(0,-0.90,3.115),(0.12,-0.88,3.145),(0.27,-0.83,3.105)], 0.052, plaster_light)\ncurve_tube(\"Mouth incision\", [(-0.245,-0.895,3.075),(0,-0.915,3.055),(0.245,-0.895,3.075)], 0.018, recess)\ncurve_tube(\"Lower classical lip\", [(-0.22,-0.855,3.02),(0,-0.90,2.985),(0.22,-0.855,3.02)], 0.062, plaster_light)\nuv(\"Mouth corner left\", (-0.26,-0.86,3.08), (0.06,0.035,0.045), plaster)\nuv(\"Mouth corner right\", (0.26,-0.86,3.08), (0.06,0.035,0.045), plaster)\n\n# Hair cap behind curls\nuv(\"Massed sculpted hair\", (0,0.08,4.35), (0.91,0.68,0.56), hairmat)\n# Hairline curls in rows, toroidal carved locks\ncurl_positions = [\n    (-0.72,-0.52,4.10),(-0.48,-0.64,4.20),(-0.23,-0.70,4.27),(0,-0.72,4.30),\n    (0.23,-0.70,4.27),(0.48,-0.64,4.20),(0.72,-0.52,4.10),\n    (-0.82,-0.38,3.88),(-0.86,-0.28,3.65),(0.82,-0.38,3.88),(0.86,-0.28,3.65),\n    (-0.67,-0.30,4.38),(-0.35,-0.43,4.52),(0,-0.48,4.57),(0.35,-0.43,4.52),(0.67,-0.30,4.38),\n    (-0.62,0.00,4.58),(-0.30,0.02,4.72),(0,0.04,4.76),(0.30,0.02,4.72),(0.62,0.00,4.58)\n]\nfor i,p in enumerate(curl_positions):\n    torus(\"Individual carved hair curl\", p, 0.105 if p[2]<4.4 else 0.115, 0.043, hairmat)\n\n# A few directional carved locks to unify the mass\nfor side in (-1,1):\n    curve_tube(\"Temple swept lock\", [(side*0.77,-0.40,4.17),(side*0.83,-0.18,4.38),(side*0.72,-0.05,4.56)], 0.065, hairmat)\n\n# Small authentic chips on socle edge\nfor x,y,s in [(-0.49,-0.50,0.055),(0.41,-0.52,0.042),(-0.20,-0.62,0.028)]:\n    uv(\"Tiny plaster chip\", (x,y,2.44), (s,0.018,s*0.7), edge_mat, 16, 8)\n\n# Backdrop: large curved-feeling wall and floor\nbpy.ops.mesh.primitive_plane_add(size=30, location=(0,3,5), rotation=(math.pi/2,0,0))\nwall=bpy.context.object; wall.name=\"Neutral studio backdrop\"; wall.data.materials.append(backmat)\nbpy.ops.mesh.primitive_plane_add(size=30, location=(0,0,0.08))\nfloor=bpy.context.object; floor.name=\"Studio floor\"; floor.data.materials.append(backmat)\n\n# Lighting\ndef area(name, loc, energy, size, color):\n    data=bpy.data.lights.new(name,'AREA'); data.energy=energy; data.shape='DISK'; data.size=size; data.color=color\n    ob=bpy.data.objects.new(name,data); bpy.context.collection.objects.link(ob); ob.location=loc\n    return ob\ndef point_at(obj, target):\n    obj.rotation_euler=(Vector(target)-obj.location).to_track_quat('-Z','Y').to_euler()\n\nkey=area(\"Large raking atelier key\", (-4.5,-5.5,7.2), 1050, 4.0, (1.0,0.88,0.72)); point_at(key,(0,0,3.55))\nfill=area(\"Gentle shadow-side bounce\", (4.5,-3.0,4.7), 380, 5.0, (0.68,0.75,1.0)); point_at(fill,(0,0,3.5))\nrim=area(\"Very soft rear separation\", (-1.5,2.5,6.0), 450, 3.0, (1.0,0.82,0.62)); point_at(rim,(0,0,4.0))\n\n# Camera, eye-level three-quarter catalogue view\ncamdata=bpy.data.cameras.new(\"Catalogue camera\")\ncam=bpy.data.objects.new(\"Catalogue camera\",camdata); bpy.context.collection.objects.link(cam)\nbpy.context.scene.camera=cam\ncam.location=(5.25,-10.8,4.72)\ncamdata.lens=72\ncamdata.sensor_width=36\npoint_at(cam,(0,-0.10,3.45))\n\n# Render / color management\nscene=bpy.context.scene\nscene.render.engine='BLENDER_EEVEE_NEXT'\nscene.render.resolution_x=1536\nscene.render.resolution_y=1536\nscene.render.resolution_percentage=100\nscene.render.image_settings.file_format='PNG'\nscene.render.film_transparent=False\nscene.render.filepath=\"/tmp/classical_bust.png\"\nscene.world.color=(0.035,0.035,0.035)\nscene.view_settings.look='AgX - Medium High Contrast'\nscene.render.image_settings.color_mode='RGBA'\n\n# Ensure camera clipping\ncamdata.clip_start=0.05\ncamdata.clip_end=100\n\n# Organize\nfor ob in bpy.context.scene.objects:\n    if ob.type == 'MESH':\n        ob.select_set(False)\n\n# Save\nbpy.ops.wm.save_as_mainfile(filepath=\"/tmp/classical_atelier_bust.blend\")\n```","refusal":null,"reasoning":"**Creating a script for Blender**\n\nI need to write a script for Blender, focusing on creating a compelling head with UV spheres and sculpted facial features. The script will involve one code block.\n\nI want the bust to face the camera, positioning the head with specific coordinates. The materials I’m using will be a rough off-white plaster for the face and perhaps a darker material for recesses. For the hair, I’ll create curls using torus-like curves or UV spheres. It’s all about achieving that classic look!**Designing head geometry**\n\nI'm working on creating the head geometry with a focus on avoiding obvious blobs. I’ll use UV spheres for the mesh, positioning the head correctly with defined dimensions. The head base could be a sphere, while the jaw might be an ellipsoid shape. \n\nI’ll set the camera for a 3/4 view to ensure visibility. The facial features will protrude toward negative y, and I need to pay careful attention to symmetrical alignment. For the hair, I’m considering coiled tubes arranged around the forehead, using curves to shape the curls.**Refining hair curls**\n\nI want to create better curls using torus rings that are oriented to face the camera. Each ring will be combined with a central sphere to form a more complex shape on the crown of the head. This will help me achieve a fuller, more dynamic look for the hair. I think I’ll use a plaster gray material for the tubes to provide a realistic texture. It's all about getting that visual appeal just right!","reasoning_details":[{"type":"reasoning.summary","summary":"**Creating a script for Blender**\n\nI need to write a script for Blender, focusing on creating a compelling head with UV spheres and sculpted facial features. The script will involve one code block.\n\nI want the bust to face the camera, positioning the head with specific coordinates. The materials I’m using will be a rough off-white plaster for the face and perhaps a darker material for recesses. For the hair, I’ll create curls using torus-like curves or UV spheres. It’s all about achieving that classic look!**Designing head geometry**\n\nI'm working on creating the head geometry with a focus on avoiding obvious blobs. I’ll use UV spheres for the mesh, positioning the head correctly with defined dimensions. The head base could be a sphere, while the jaw might be an ellipsoid shape. \n\nI’ll set the camera for a 3/4 view to ensure visibility. The facial features will protrude toward negative y, and I need to pay careful attention to symmetrical alignment. For the hair, I’m considering coiled tubes arranged around the forehead, using curves to shape the curls.**Refining hair curls**\n\nI want to create better curls using torus rings that are oriented to face the camera. Each ring will be combined with a central sphere to form a more complex shape on the crown of the head. This will help me achieve a fuller, more dynamic look for the hair. I think I’ll use a plaster gray material for the tubes to provide a realistic texture. It's all about getting that visual appeal just right!","format":"openai-responses-v1","index":0},{"type":"reasoning.encrypted","data":"gAAAAABqWYdYcFTIQaMq-Ia21zBWKVKhabqEWtWm8XNtW7McBPjUo6ze_09tvVNv7nrbnkBrtd1ZGyfp0wsZGFdZkh1P6UVwJV2-v2hXcaeyfnXTSf2bq7q-F1kUYMFVN0Tu-grC69hnF_k_4SaB-3fhY5oR5vD2Y-94L4IHiof0aih7FWBBPMN5zLINtsdRpxMnGsrq2fRe9EYAN2GLtw0RQK3CYOmOvlhGtpxn0TzXaVpkwpz8xKCGtbIWqw42nVw9r2I4CwQkM7uGx-SB4QESA3rukKXjUsTHsD3DlYHOYxN_13EPc4eFBZOn2Yrz6yTsYcJT7t-pm352rSRnEVWKLOMGwEcorNzL0N1ZkrRvbBazPNWdlEtnFXwigUFM4rrPWxMSpXU8QQizbW6XVlVlqNLu44Ox9fPsef_2x6mHbjyQXHCmkrhmfJBsrMI_gKotrvoN-ejiStY1JjEpc7orMzuvOT1FFsqz4QOepzwgmqVJmkkyOMGFRgbATfN8qIYx4APTWEmg8t22WDP7w02A5_SbhomRH5pcK9ScxeGfWU5i5EKtf3Zf57AjtGKXIeG4Iyy1QYWEi_9LWL8TYpWDMLs39aS3N6WkIDynsyFgLNkABWg99Erw2q4ob2s8MyxyKvQ8Ynk-JkRyV3rz1vSkM23SMHxJjdRUe2PczNxj_L0vMe7bB-KvSiHLPQU-IK1a9cPmQRF_3M2aHfVzXiPCTmtQ222IWE5_mJlU3OXi89oeZkbVfRG4ChHz21_hyPDosvcD2R0jXiKUfJRtk8Yt3_whGGiaG2eEHT9IrThcGqGYZEli9AjZKzG_-dmDdX8jB2T3qFY4QXgJ_nbjAd1wZVjhwHBo3XAJgIsjiUeFeQK4btAE5OSpNxxeEicaqgoT5xw3Q1kfKo_s7cHD1n_1nfiF0soypWuRf_YJ9vMBIXygIAMT6AacpcOQUGDnCn24nCLHCV_PKBT0U1PHpRAe-YNGU9UDMoqAVkxq9KPzxibvut2aRgf6hofNng5wAlYTOBs3i0XxGznySCD-nB3heYsRpKnPGPG1xWLeJR3bWSBUffy4uvmj42M06W6uYvS-FQI0lr5dPkuY0R9_wZxMNDkG_9jtaVveHcfK5UR0xLvoak2T13KKDK-kWGNmmEMatpU0Gy_QO9-aJLlDYC8GuvNGrEA1VBlXaiqlmXb8xA_MYBUuAkubZYri-5U0WFnpf9tXytZE8KFnBTR3Yu9X77f2VschacZGJz1U6GPBW1fQPNSbe-Dls2USwv09HTe33jlCxVP5ZussitUapT5x8ICcQT1U0halbom-Lvfpk-j9XGrKdoc7R9Eiu8B1xlpb70jDDof_GXa1FKiL6kxHMkYq6MBp4IuQhjWeeJNCDmpjNW0BFkxlb9wePhgEszZ_S2Z2rnDq1pbnltXNInaWINZx2eP25BvSFo-fWdrxyEYR3fhTuAG_ZIkfXALtSdVHNwOuZf9TgMpw6-gd4Ve5CMpHi_TsAv_x8YJn3J70IV_Y-XgGOtHVb06Hp969YuEfVJaXHmt2N3jlmxCBg1MqZ2pax8lB6394J1emjGOZjOC1hTnYabQkXU8SUR1LnyfjKUw2ssj_YULcIF-YXYaRpWtvU3YOqxoGd9JLZxHXbvub8Ud-2vvGXSZJekD7or-XaSOK7mfExMOdg1b3bTc1usMvxVLTrl7ry0n9gBLLEV5myq3hvsAZJgsPzMh3ODr32mmDXbmiSCwv5euo01jUulFjXvtHAyfD7vg1pc8sNSK055asWsdbzSG7Y78obOVDdXKxm5T_z69uYWF82HgSS4YrTAxNeOMGnfO5uEqkSwwDRjBUp4xS7mueqqYDkp1EE_ArU0_imgrqG0h4pGtyJfUCMhBtmgueWA21vOgcMUhTbCYbuE9HIfEcdTlpghRrhrrFuXknSwEMxB-Z5cF4VRpvFSloHF7z5Tzn1KqOGoBHT-2erlAMPSHp77Azt0NKxCnH564jjE7d8sPgiWydqojVqc5y56XdrWOKDkt4PoykopVd62cvbgMgBMBD3RdIRqo1o1u8d59OGtzh5g1sbnEPgaLBHDqzbQaBuwPBQ1wZjfhoLyWKrU8FfVe8u_eVyDuSf8vMgZQl7BIoZyh5s3mN-ui2l_CACigkPeUifAxxspdMlk6k2q64UjudOgCrc-L6Tj5d018iRKGabTIIL7qRyVQR8IeI9xn4YTep5l1jT9rA8XXjSBylrlSWmTt-LXNCK_3eu5V9AVExQAGhjajfFaKlUiRLbw52MzjJUjonQXbPP5yxFf_09XqvRH9I667zAS3SMrcL0PsKau6E4460_t9iYhXfipT8oHpMD_EX-1_Hfg2DJRYl2hUBXfwcSNGwTjW0Kf4U0w6gaXDU_ie3L3wa9eRCQ5r4NflsPSWnwKX237G9c25HwjjBCJcJPrrYaOMC_2O3_QGbb9dvsK5asFGIEh7tk7f5831_9QvBzGco41Ev4Nu_1oEs0IZqd8opj7amCw_XiXKgLRjvnEq5LasYGrltWkUDr6eAQIKzPuHzT2n-GugY2aUhuML92noWRJfP6m9hzlCKqsrC1fyV6qYfom1rXI5Gys_kHIfT_aCvfMaZpDyq7AJSGMHv1X7UZ4c-wdY4ekzE61DCAzZfDukmtJI1SalKJydNaBrWLeWPHODAyFxz0a23lbvguD4_8BkM5rxGueGmUg5THHf5Ise9npbrJr7JOH22r_85-vU7dglaJMPy8Wb8RQf1dtDSjSOsY_h1G8AHtPcP0vOIibX7Uviq7uL_KBRjG0cjaE6Zn5mFu_sOFxxc7t5h2mnQpex1VfzoY1hFLXGEHPzZZI31hnONWWVCxO9PJumAZZUqUNpcCQWaYz5lz46XEtXXSZW4zh_AO9qlHUUKADXGpfels0XdRo-bq9-JnnqjiRJO4d48wGh3OVDneO2dehQflGqHHbbttdEKCBwK5_IEQ_K_6Rnk7dOZGdf4v5YmT-XLku0vHqksjd87QY3HDyq5flFEp7_G6Nyf8Up6h00XNU5i8Fv_AHbHp6-Pw7LnDFSs2T7y8ceOPyKWR489CLtloo2JBfpZEffEh11VjRnSJdoYiH1TabEU_M52JLnSz25uSINGlvxhEYX83gJ2llOyxbEtBcE5SAT3WnxGSBmrMQb_gkpsJ8fSwEsPvsnHqRGw83b53G7naUlFQ6sFCoDaOdnNnHzFdzbs0bzJBzSBaXppdI0QP3D9JYvqlN9znawGg1DV4FkGG3K0l6Mcb92l1FFNerlSzk1cH24OHd6Xu7PqcufR3rTyZveGjF5u8m1kV2wf1risW0OwsIKNu0Gxl_YXhhptl4R2kbGWV5eT5xHNQw98go8K-bzmsF8L-DlzvxmfS4L1-dqC4V_I09TywgteIvyRL2oDhhQoR6FmZGvCkQF8i-ISAbW2-fuCQSyaGpmatocL4IljYAnuCARwwk2ifdja_zf2WwcneK2h_-gJ_YUJXr43eYbEzbRer7R9InTpXD3LB8xR73HqV30_bscG8y1s9jbyW2rg09qVRqeCdMuZxjtUNK35AyPKAp1aI9nY0KxltuL9UOZH9REfJWwkYKCSyZGsmO5Ay9hWWJ-XS2zC-rccInrLDYBdfxVhC5BHebF_u66B54HkoC8jhF3Tu55nHDeqs0ixbYaLE_zd-KAd2LZmapEG6_slg5Ejwbz9PFZjTB2Ij_DIQAIktxL8-biNCyDPpabxTcrqvuht3yECb6TkLAFZgdztYe03UfHcN4Na2u_R4K62i_37cn9Cj9RirAzaGa_XFcNPRjuSJiVJZaI6ot5zFtU6fCS2kieEKSBhyRg3yqkOYTdcaHFoWoOY6UuLJzv6CHmY2G6xCA==gAAAAABqWYdZGB12rH6oQXcb56GnHD8b2FATdFuqCDQth6gwAeai9yG9q9l7vp4UFfiEfhadhFMRueDfa1QUKLq6-uiQc0SUDNtEu9FZ1I3tHepiWeM9Yr5V8dvpsSYifRHdj1shXYFd_RjCds2TJYrtdC6jI3yI7RaMXdXieJqyGl8F0tm1CnUkM19scbyQaUy2IYKdjjIscEfGVKPcYl_JPvtXjPG_T3N90imoDKpRnqXWqksHReLwpwVYOYfok2fl72Hu0QllrSPVbGQN-vY6qZioK-TRGC4mHjuhsbEa-VWZo-nqbOvsVj8m-yZq2RMge97-PSb-0uQD1G__Fa_d_YBrJuzNcThVaJTNEARcFnQiUZziw1KQbZBtz6ve-4kYZ4rQDb_Dk28gll6TNvYazhG9iD9V4R8VkxIXdMnEftx3nW47xqIKdxmbSX-JCjM7yQ8H_MqNMvti8dsCNpakI3LnZfUdEYOh99dcZX80eUNtmM5Ng1sdh-Db_IAvXhXGk3QKsGIk34UBYa4i2J1WhMjCza-L9kGLxRmrgPUboQS3zh6J37XEspnThKqEhE5q-fHh_khm9gd2xhdA9BpcR_b2q2cyS4mV6PxaibziR56sB65MlzY0KeC5jgN0M9iqerSIir_te2OxAVxAagsEEdoxa4Zlssnlyflw6WpqWbgmtZ-6eSuCI6VUvorZU5dqvTUQXFsFFBeteXekda38TmjmyFXokHG_zDOUWuV5Eq_KMa6jcYtaNPJkrghQsjpWJ_iFYdU_KAK8m93pG0CG9bmmCvKv3kaeE_QS7GOw9jbLe91dSEIMOh3howptySZAuoyQzUWQpEcjyENb4fh_C9zN1O00hgE-JxZI8tS1R2gLX3gwObWBDSFr37VsqgFummetO4D_rjPXP4v7hET1drNwcoorPZwm9HEbhF4gNguhOX-1oA2q21UrcMc5JU6R9oC1ZTX7hmBfAWpq66EtjQ7aHr-vP4ciybg62l8LFJdYtGHda7_I8lZGcu2w8LYdAHcHTJcxycrNbUspRVusoIOr58ma6CFUceWp2rn4GTnQXJPL1MTStn7nZ3SIBFJPC0nWsXmXq5A8ye3CTQbqRBPH2cv14MyrwtYlDZ-MFjDh842XLKNHBK6RxJ6NL94xYNSk9CS_z45lNC1zqEEkfl4yBtjiV2OIXjOtOQOQDxyZMacfGlwVCHvFgcP1qWPt7P_PFWwWW7IBN8lRlabV8_Vqg_06MaJH2KOhw2yBmEuRF7Zu5okHw2bBizHXUAUvbfhNG2umZFQkenhyQXkrycqxXC5XKgAM2z_5wI6KNSQ43Bm2T1hZvDH_iybp6LFULb0JhJBiJyRV3hZFV9F96KKsrUb88nObcLsuk4w3UXyImYfr0nMqey5E9vCskW0zJwT3UIPl0-miyKYoygGh1_XLf2B2wUeMmkFfcKFcn5R2cKrFPKcOcTIU3Z2Pntt-CaWq-ni2zXuNBugGcOfk_xgweF1EAklvm8ZWbopRNYQaoadHob75jUxA35OPC9ELHW5oivgu1YRiWw5qW1p6gAiD5bR3cf-9sg_ejeK-VABINvWS6KadykDMoxMfxPGskZ6MEmw-K9tHIuChbuvjd_P9rz93dMoZcBYU3aBupwfc-TjipzcGhLKTTWOwR-UrVSp2haYwU_i39JVfvBT9p5FAZq3OdklLdqlxgLLhbwfKs282OY1yxx5aztkpehSvdd7OR25_44N9Zu8dPhu98avCf5ihPbko9oQx4lhvlZUvCDZynk5lDj5AILztPwatWM37yAr_eIZQcSU6XjSuBCggPXum3h-H_aR9-oYkgODtw4CSR__s_IXzefx5QysV8iyCSoZMOizcYW1ltEBzymacy7ylvXiaMaEwU1T00Q_GiDQR5D0-r3abOhTReyJstmbbZO1lzYl0NyPstk1N7pe_41geXE5DrHHpMSbWktYALyiN1nHJqvjA4bjVONEIykZSOOvi-KWwlJUmtukRv2V0zyq3CVMbJkU9olODFDTLIt_R3UHAu-lMBalmMB0IlcH1MQtCGOU2xzkON-g4hdPQMAAg-SmhHDqdI4ts-DJjThUbOkaI1OWWZ9hymPTbIXYIQtHpjN6r2QAYrpBGjW8lCZAkos_hrqPQigcLysobd5uxiO1-D7c6HluiAbBXppYLWrP7Ns5Bh2WQYTlm-KmNghZ1iqIOcNfmy3f9Lt1v8jtieaJ1ILMCzlfHHF7uVwFvGEmLgiVGkRyM19_3PaInqxVEhZIJq7aqNHsdOKxVc_Y3SOyhYRCWkAwVDS7yXA8FOBLq","format":"openai-responses-v1","id":"rs_0df71db64a56be5c016a5987509c5881979954f441f098cefe","index":1}]}}],"usage":{"prompt_tokens":1183,"completion_tokens":4654,"total_tokens":5837,"cost":0.028045,"is_byok":false,"prompt_tokens_details":{"cached_tokens":1180,"cache_write_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":0.028045,"upstream_inference_prompt_cost":0.000121,"upstream_inference_completions_cost":0.027924},"completion_tokens_details":{"reasoning_tokens":740,"image_tokens":0,"audio_tokens":0}}}

```python
import bpy, math
from mathutils import Vector

# ------------------------------------------------------------
# Classical atelier bust: sculptural plaster, neutral studio
# ------------------------------------------------------------

# Clear scene
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
for datablocks in (bpy.data.meshes, bpy.data.curves, bpy.data.materials, bpy.data.cameras, bpy.data.lights):
    pass

# Materials
def mat(name, color, rough=0.72, spec=0.22, subsurface=0.0):
    m = bpy.data.materials.new(name)
    m.diffuse_color = (*color, 1)
    m.use_nodes = True
    bs = m.node_tree.nodes.get("Principled BSDF")
    bs.inputs["Base Color"].default_value = (*color, 1)
    bs.inputs["Roughness"].default_value = rough
    bs.inputs["Specular IOR Level"].default_value = spec
    if "Subsurface Weight" in bs.inputs:
        bs.inputs["Subsurface Weight"].default_value = subsurface
        bs.inputs["Subsurface Radius"].default_value = (1.0, 0.72, 0.52)
    return m

plaster = mat("Warm ivory atelier plaster", (0.72, 0.695, 0.625), 0.78, 0.18, 0.035)
plaster_light = mat("Freshly worn plaster highlights", (0.81, 0.785, 0.71), 0.75, 0.2, 0.025)
hairmat = mat("Slightly darker plaster in hair recesses", (0.49, 0.47, 0.42), 0.88, 0.12, 0.015)
recess = mat("Dust-grey recess", (0.25, 0.24, 0.22), 0.94, 0.05, 0.0)
eye_mat = mat("Blank antique eye", (0.64, 0.625, 0.56), 0.82, 0.12, 0.0)
backmat = mat("Studio warm grey", (0.105, 0.11, 0.105), 0.92, 0.05, 0.0)
pedmat = mat("Pedestal plaster", (0.57, 0.55, 0.50), 0.83, 0.15, 0.02)
edge_mat = mat("Old cut edge", (0.30, 0.285, 0.25), 0.91, 0.08, 0.0)

def smooth(obj):
    if obj.type == 'MESH':
        for p in obj.data.polygons:
            p.use_smooth = True

def uv(name, loc, scale, material=plaster, seg=48, rings=32):
    bpy.ops.mesh.primitive_uv_sphere_add(segments=seg, ring_count=rings, location=loc)
    o = bpy.context.object
    o.name = name
    o.scale = scale
    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    smooth(o)
    o.data.materials.append(material)
    return o

def cyl(name, loc, radius, depth, material=plaster, vertices=64, bevel=0.04):
    bpy.ops.mesh.primitive_cylinder_add(vertices=vertices, radius=radius, depth=depth, location=loc)
    o=bpy.context.object; o.name=name
    o.data.materials.append(material)
    if bevel:
        mod=o.modifiers.new("soft carved edge","BEVEL"); mod.width=bevel; mod.segments=3
    smooth(o)
    return o

def torus(name, loc, major, minor, material=hairmat, rot=(math.pi/2,0,0)):
    bpy.ops.mesh.primitive_torus_add(major_radius=major, minor_radius=minor,
                                    major_segments=40, minor_segments=12,
                                    location=loc, rotation=rot)
    o=bpy.context.object; o.name=name; o.data.materials.append(material); smooth(o)
    return o

def curve_tube(name, pts, bevel, material=plaster, resolution=3):
    cu=bpy.data.curves.new(name, 'CURVE')
    cu.dimensions='3D'; cu.resolution_u=2; cu.bevel_depth=bevel; cu.bevel_resolution=resolution
    sp=cu.splines.new('BEZIER'); sp.bezier_points.add(len(pts)-1)
    for b,p in zip(sp.bezier_points,pts):
        b.co=p; b.handle_left_type='AUTO'; b.handle_right_type='AUTO'
    ob=bpy.data.objects.new(name,cu); bpy.context.collection.objects.link(ob)
    ob.data.materials.append(material)
    return ob

# Ground and pedestal
cyl("Pedestal lower plinth", (0,0,0.32), 1.18, 0.32, pedmat, bevel=0.055)
cyl("Pedestal upper step", (0,0,0.57), 0.98, 0.20, plaster, bevel=0.035)
cyl("Square-ish classical shaft", (0,0,1.38), 0.72, 1.45, pedmat, bevel=0.045)
cyl("Pedestal capital", (0,0,2.10), 0.88, 0.18, plaster, bevel=0.035)
cyl("Bust socle", (0,0,2.30), 0.68, 0.28, plaster, bevel=0.05)

# Socle cut edge / subtle casting line
bpy.ops.mesh.primitive_torus_add(major_radius=0.61, minor_radius=0.012,
                                  major_segments=64, minor_segments=8,
                                  location=(0,0,2.445))
socline=bpy.context.object; socline.name="Faint mold seam at socle"; socline.data.materials.append(edge_mat)

# Neck and shoulder termination
uv("Neck column", (0,0.02,2.73), (0.47,0.43,0.72), plaster)
uv("Left shoulder broken termination", (-0.48,0.03,2.48), (0.62,0.46,0.28), plaster)
uv("Right shoulder broken termination", (0.48,0.03,2.48), (0.62,0.46,0.28), plaster)

# Head mass, jaw, chin
uv("Main idealized cranium", (0,0.0,3.68), (0. ninety if False else 0.91,0.73,1.16), plaster)
uv("Angular lower face", (0,-0.08,3.18), (0.73,0.62,0.70), plaster)
uv("Strong classical chin", (0,-0.63,3.03), (0.36,0.20,0.24), plaster_light)

# Ears, deliberately integrated into skull
for x in (-0.86,0.86):
    uv("Sculpted ear", (x,-0.02,3.60), (0.16,0.11,0. thirty if False else 0.30), plaster)
    uv("Ear concha shadow", (x, -0.125, 3.60), (0.075,0.025,0.15), recess)

# Brow ridge and forehead planes
for x in (-0.30,0.30):
    uv("Projected brow ridge", (x,-0.665,3.98), (0.30,0.105,0.105), plaster_light)
# central glabella
uv("Glabella plane", (0,-0.675,3.94), (0.16,0.10,0.19), plaster)

# Blank antique eyes, inset almond forms
for x in (-0.30,0.30):
    uv("Blank almond eye", (x,-0.735,3.78), (0.205,0.045,0.095), eye_mat)
    # upper and lower lid as sculpted arcs
    curve_tube("Upper eyelid", [(x-0.20,-0.775,3.78),(x,-0.80,3.875),(x+0.20,-0.775,3.79)], 0.026, plaster_light)
    curve_tube("Lower eyelid", [(x-0.18,-0.768,3.75),(x,-0.79,3.695),(x+0.18,-0.768,3.75)], 0.018, plaster)
# tear ducts
uv("Left tear duct", (-0.105,-0.78,3.77), (0.045,0.025,0.04), plaster_light)
uv("Right tear duct", (0.105,-0.78,3.77), (0.045,0.025,0.04), plaster_light)

# Nose: bridge, planes, tip and nostril recesses
uv("Nose bridge", (0,-0.70,3.62), (0.16,0.18,0.48), plaster_light)
uv("Nose lower plane", (0,-0.82,3.34), (0.22,0.18,0.18), plaster_light)
uv("Nose tip", (0,-0.89,3.28), (0.18,0.15,0.15), plaster_light)
uv("Left alar wing", (-0.16,-0.83,3.31), (0.13,0.11,0.10), plaster)
uv("Right alar wing", (0.16,-0.83,3.31), (0.13,0.11,0.10), plaster)
for x in (-0.095,0.095):
    uv("Nostril shadow", (x,-0.925,3.295), (0.055,0.018,0.027), recess)

# Cheekbones and under-cheek planes
uv("Left high cheekbone", (-0.48,-0.56,3.54), (0.30,0.14,0.19), plaster_light)
uv("Right high cheekbone", (0.48,-0.56,3.54), (0.30,0.14,0.19), plaster_light)
uv("Left under cheek plane", (-0.48,-0.48,3.28), (0.33,0.11,0.20), plaster)
uv("Right under cheek plane", (0.48,-0.48,3.28), (0.33,0.11,0.20), plaster)

# Philtrum, mouth, classical firm lips
curve_tube("Philtrum left ridge", [(-0.045,-0.835,3.30),(-0.055,-0.85,3.12)], 0.022, plaster_light)
curve_tube("Philtrum right ridge", [(0.045,-0.835,3.30),(0.055,-0.85,3.12)], 0.022, plaster_light)
curve_tube("Upper classical lip", [(-0.27,-0.83,3.105),(-0.12,-0.88,3.145),(0,-0.90,3.115),(0.12,-0.88,3.145),(0.27,-0.83,3.105)], 0.052, plaster_light)
curve_tube("Mouth incision", [(-0.245,-0.895,3.075),(0,-0.915,3.055),(0.245,-0.895,3.075)], 0.018, recess)
curve_tube("Lower classical lip", [(-0.22,-0.855,3.02),(0,-0.90,2.985),(0.22,-0.855,3.02)], 0.062, plaster_light)
uv("Mouth corner left", (-0.26,-0.86,3.08), (0.06,0.035,0.045), plaster)
uv("Mouth corner right", (0.26,-0.86,3.08), (0.06,0.035,0.045), plaster)

# Hair cap behind curls
uv("Massed sculpted hair", (0,0.08,4.35), (0.91,0.68,0.56), hairmat)
# Hairline curls in rows, toroidal carved locks
curl_positions = [
    (-0.72,-0.52,4.10),(-0.48,-0.64,4.20),(-0.23,-0.70,4.27),(0,-0.72,4.30),
    (0.23,-0.70,4.27),(0.48,-0.64,4.20),(0.72,-0.52,4.10),
    (-0.82,-0.38,3.88),(-0.86,-0.28,3.65),(0.82,-0.38,3.88),(0.86,-0.28,3.65),
    (-0.67,-0.30,4.38),(-0.35,-0.43,4.52),(0,-0.48,4.57),(0.35,-0.43,4.52),(0.67,-0.30,4.38),
    (-0.62,0.00,4.58),(-0.30,0.02,4.72),(0,0.04,4.76),(0.30,0.02,4.72),(0.62,0.00,4.58)
]
for i,p in enumerate(curl_positions):
    torus("Individual carved hair curl", p, 0.105 if p[2]<4.4 else 0.115, 0.043, hairmat)

# A few directional carved locks to unify the mass
for side in (-1,1):
    curve_tube("Temple swept lock", [(side*0.77,-0.40,4.17),(side*0.83,-0.18,4.38),(side*0.72,-0.05,4.56)], 0.065, hairmat)

# Small authentic chips on socle edge
for x,y,s in [(-0.49,-0.50,0.055),(0.41,-0.52,0.042),(-0.20,-0.62,0.028)]:
    uv("Tiny plaster chip", (x,y,2.44), (s,0.018,s*0.7), edge_mat, 16, 8)

# Backdrop: large curved-feeling wall and floor
bpy.ops.mesh.primitive_plane_add(size=30, location=(0,3,5), rotation=(math.pi/2,0,0))
wall=bpy.context.object; wall.name="Neutral studio backdrop"; wall.data.materials.append(backmat)
bpy.ops.mesh.primitive_plane_add(size=30, location=(0,0,0.08))
floor=bpy.context.object; floor.name="Studio floor"; floor.data.materials.append(backmat)

# Lighting
def area(name, loc, energy, size, color):
    data=bpy.data.lights.new(name,'AREA'); data.energy=energy; data.shape='DISK'; data.size=size; data.color=color
    ob=bpy.data.objects.new(name,data); bpy.context.collection.objects.link(ob); ob.location=loc
    return ob
def point_at(obj, target):
    obj.rotation_euler=(Vector(target)-obj.location).to_track_quat('-Z','Y').to_euler()

key=area("Large raking atelier key", (-4.5,-5.5,7.2), 1050, 4.0, (1.0,0.88,0.72)); point_at(key,(0,0,3.55))
fill=area("Gentle shadow-side bounce", (4.5,-3.0,4.7), 380, 5.0, (0.68,0.75,1.0)); point_at(fill,(0,0,3.5))
rim=area("Very soft rear separation", (-1.5,2.5,6.0), 450, 3.0, (1.0,0.82,0.62)); point_at(rim,(0,0,4.0))

# Camera, eye-level three-quarter catalogue view
camdata=bpy.data.cameras.new("Catalogue camera")
cam=bpy.data.objects.new("Catalogue camera",camdata); bpy.context.collection.objects.link(cam)
bpy.context.scene.camera=cam
cam.location=(5.25,-10.8,4.72)
camdata.lens=72
camdata.sensor_width=36
point_at(cam,(0,-0.10,3.45))

# Render / color management
scene=bpy.context.scene
scene.render.engine='BLENDER_EEVEE_NEXT'
scene.render.resolution_x=1536
scene.render.resolution_y=1536
scene.render.resolution_percentage=100
scene.render.image_settings.file_format='PNG'
scene.render.film_transparent=False
scene.render.filepath="/tmp/classical_bust.png"
scene.world.color=(0.035,0.035,0.035)
scene.view_settings.look='AgX - Medium High Contrast'
scene.render.image_settings.color_mode='RGBA'

# Ensure camera clipping
camdata.clip_start=0.05
camdata.clip_end=100

# Organize
for ob in bpy.context.scene.objects:
    if ob.type == 'MESH':
        ob.select_set(False)

# Save
bpy.ops.wm.save_as_mainfile(filepath="/tmp/classical_atelier_bust.blend")
```


```python
import bpy, math
from mathutils import Vector

# ------------------------------------------------------------
# Classical atelier bust: sculptural plaster, neutral studio
# ------------------------------------------------------------

# Clear scene
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
for datablocks in (bpy.data.meshes, bpy.data.curves, bpy.data.materials, bpy.data.cameras, bpy.data.lights):
    pass

# Materials
def mat(name, color, rough=0.72, spec=0.22, subsurface=0.0):
    m = bpy.data.materials.new(name)
    m.diffuse_color = (*color, 1)
    m.use_nodes = True
    bs = m.node_tree.nodes.get("Principled BSDF")
    bs.inputs["Base Color"].default_value = (*color, 1)
    bs.inputs["Roughness"].default_value = rough
    bs.inputs["Specular IOR Level"].default_value = spec
    if "Subsurface Weight" in bs.inputs:
        bs.inputs["Subsurface Weight"].default_value = subsurface
        bs.inputs["Subsurface Radius"].default_value = (1.0, 0.72, 0.52)
    return m

plaster = mat("Warm ivory atelier plaster", (0.72, 0.695, 0.625), 0.78, 0.18, 0.035)
plaster_light = mat("Freshly worn plaster highlights", (0.81, 0.785, 0.71), 0.75, 0.2, 0.025)
hairmat = mat("Slightly darker plaster in hair recesses", (0.49, 0.47, 0.42), 0.88, 0.12, 0.015)
recess = mat("Dust-grey recess", (0.25, 0.24, 0.22), 0.94, 0.05, 0.0)
eye_mat = mat("Blank antique eye", (0.64, 0.625, 0.56), 0.82, 0.12, 0.0)
backmat = mat("Studio warm grey", (0.105, 0.11, 0.105), 0.92, 0.05, 0.0)
pedmat = mat("Pedestal plaster", (0.57, 0.55, 0.50), 0.83, 0.15, 0.02)
edge_mat = mat("Old cut edge", (0.30, 0.285, 0.25), 0.91, 0.08, 0.0)

def smooth(obj):
    if obj.type == 'MESH':
        for p in obj.data.polygons:
            p.use_smooth = True

def uv(name, loc, scale, material=plaster, seg=48, rings=32):
    bpy.ops.mesh.primitive_uv_sphere_add(segments=seg, ring_count=rings, location=loc)
    o = bpy.context.object
    o.name = name
    o.scale = scale
    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    smooth(o)
    o.data.materials.append(material)
    return o

def cyl(name, loc, radius, depth, material=plaster, vertices=64, bevel=0.04):
    bpy.ops.mesh.primitive_cylinder_add(vertices=vertices, radius=radius, depth=depth, location=loc)
    o=bpy.context.object; o.name=name
    o.data.materials.append(material)
    if bevel:
        mod=o.modifiers.new("soft carved edge","BEVEL"); mod.width=bevel; mod.segments=3
    smooth(o)
    return o

def torus(name, loc, major, minor, material=hairmat, rot=(math.pi/2,0,0)):
    bpy.ops.mesh.primitive_torus_add(major_radius=major, minor_radius=minor,
                                    major_segments=40, minor_segments=12,
                                    location=loc, rotation=rot)
    o=bpy.context.object; o.name=name; o.data.materials.append(material); smooth(o)
    return o

def curve_tube(name, pts, bevel, material=plaster, resolution=3):
    cu=bpy.data.curves.new(name, 'CURVE')
    cu.dimensions='3D'; cu.resolution_u=2; cu.bevel_depth=bevel; cu.bevel_resolution=resolution
    sp=cu.splines.new('BEZIER'); sp.bezier_points.add(len(pts)-1)
    for b,p in zip(sp.bezier_points,pts):
        b.co=p; b.handle_left_type='AUTO'; b.handle_right_type='AUTO'
    ob=bpy.data.objects.new(name,cu); bpy.context.collection.objects.link(ob)
    ob.data.materials.append(material)
    return ob

# Ground and pedestal
cyl("Pedestal lower plinth", (0,0,0.32), 1.18, 0.32, pedmat, bevel=0.055)
cyl("Pedestal upper step", (0,0,0.57), 0.98, 0.20, plaster, bevel=0.035)
cyl("Square-ish classical shaft", (0,0,1.38), 0.72, 1.45, pedmat, bevel=0.045)
cyl("Pedestal capital", (0,0,2.10), 0.88, 0.18, plaster, bevel=0.035)
cyl("Bust socle", (0,0,2.30), 0.68, 0.28, plaster, bevel=0.05)

# Socle cut edge / subtle casting line
bpy.ops.mesh.primitive_torus_add(major_radius=0.61, minor_radius=0.012,
                                  major_segments=64, minor_segments=8,
                                  location=(0,0,2.445))
socline=bpy.context.object; socline.name="Faint mold seam at socle"; socline.data.materials.append(edge_mat)

# Neck and shoulder termination
uv("Neck column", (0,0.02,2.73), (0.47,0.43,0.72), plaster)
uv("Left shoulder broken termination", (-0.48,0.03,2.48), (0.62,0.46,0.28), plaster)
uv("Right shoulder broken termination", (0.48,0.03,2.48), (0.62,0.46,0.28), plaster)

# Head mass, jaw, chin
uv("Main idealized cranium", (0,0.0,3.68), (0. ninety if False else 0.91,0.73,1.16), plaster)
uv("Angular lower face", (0,-0.08,3.18), (0.73,0.62,0.70), plaster)
uv("Strong classical chin", (0,-0.63,3.03), (0.36,0.20,0.24), plaster_light)

# Ears, deliberately integrated into skull
for x in (-0.86,0.86):
    uv("Sculpted ear", (x,-0.02,3.60), (0.16,0.11,0. thirty if False else 0.30), plaster)
    uv("Ear concha shadow", (x, -0.125, 3.60), (0.075,0.025,0.15), recess)

# Brow ridge and forehead planes
for x in (-0.30,0.30):
    uv("Projected brow ridge", (x,-0.665,3.98), (0.30,0.105,0.105), plaster_light)
# central glabella
uv("Glabella plane", (0,-0.675,3.94), (0.16,0.10,0.19), plaster)

# Blank antique eyes, inset almond forms
for x in (-0.30,0.30):
    uv("Blank almond eye", (x,-0.735,3.78), (0.205,0.045,0.095), eye_mat)
    # upper and lower lid as sculpted arcs
    curve_tube("Upper eyelid", [(x-0.20,-0.775,3.78),(x,-0.80,3.875),(x+0.20,-0.775,3.79)], 0.026, plaster_light)
    curve_tube("Lower eyelid", [(x-0.18,-0.768,3.75),(x,-0.79,3.695),(x+0.18,-0.768,3.75)], 0.018, plaster)
# tear ducts
uv("Left tear duct", (-0.105,-0.78,3.77), (0.045,0.025,0.04), plaster_light)
uv("Right tear duct", (0.105,-0.78,3.77), (0.045,0.025,0.04), plaster_light)

# Nose: bridge, planes, tip and nostril recesses
uv("Nose bridge", (0,-0.70,3.62), (0.16,0.18,0.48), plaster_light)
uv("Nose lower plane", (0,-0.82,3.34), (0.22,0.18,0.18), plaster_light)
uv("Nose tip", (0,-0.89,3.28), (0.18,0.15,0.15), plaster_light)
uv("Left alar wing", (-0.16,-0.83,3.31), (0.13,0.11,0.10), plaster)
uv("Right alar wing", (0.16,-0.83,3.31), (0.13,0.11,0.10), plaster)
for x in (-0.095,0.095):
    uv("Nostril shadow", (x,-0.925,3.295), (0.055,0.018,0.027), recess)

# Cheekbones and under-cheek planes
uv("Left high cheekbone", (-0.48,-0.56,3.54), (0.30,0.14,0.19), plaster_light)
uv("Right high cheekbone", (0.48,-0.56,3.54), (0.30,0.14,0.19), plaster_light)
uv("Left under cheek plane", (-0.48,-0.48,3.28), (0.33,0.11,0.20), plaster)
uv("Right under cheek plane", (0.48,-0.48,3.28), (0.33,0.11,0.20), plaster)

# Philtrum, mouth, classical firm lips
curve_tube("Philtrum left ridge", [(-0.045,-0.835,3.30),(-0.055,-0.85,3.12)], 0.022, plaster_light)
curve_tube("Philtrum right ridge", [(0.045,-0.835,3.30),(0.055,-0.85,3.12)], 0.022, plaster_light)
curve_tube("Upper classical lip", [(-0.27,-0.83,3.105),(-0.12,-0.88,3.145),(0,-0.90,3.115),(0.12,-0.88,3.145),(0.27,-0.83,3.105)], 0.052, plaster_light)
curve_tube("Mouth incision", [(-0.245,-0.895,3.075),(0,-0.915,3.055),(0.245,-0.895,3.075)], 0.018, recess)
curve_tube("Lower classical lip", [(-0.22,-0.855,3.02),(0,-0.90,2.985),(0.22,-0.855,3.02)], 0.062, plaster_light)
uv("Mouth corner left", (-0.26,-0.86,3.08), (0.06,0.035,0.045), plaster)
uv("Mouth corner right", (0.26,-0.86,3.08), (0.06,0.035,0.045), plaster)

# Hair cap behind curls
uv("Massed sculpted hair", (0,0.08,4.35), (0.91,0.68,0.56), hairmat)
# Hairline curls in rows, toroidal carved locks
curl_positions = [
    (-0.72,-0.52,4.10),(-0.48,-0.64,4.20),(-0.23,-0.70,4.27),(0,-0.72,4.30),
    (0.23,-0.70,4.27),(0.48,-0.64,4.20),(0.72,-0.52,4.10),
    (-0.82,-0.38,3.88),(-0.86,-0.28,3.65),(0.82,-0.38,3.88),(0.86,-0.28,3.65),
    (-0.67,-0.30,4.38),(-0.35,-0.43,4.52),(0,-0.48,4.57),(0.35,-0.43,4.52),(0.67,-0.30,4.38),
    (-0.62,0.00,4.58),(-0.30,0.02,4.72),(0,0.04,4.76),(0.30,0.02,4.72),(0.62,0.00,4.58)
]
for i,p in enumerate(curl_positions):
    torus("Individual carved hair curl", p, 0.105 if p[2]<4.4 else 0.115, 0.043, hairmat)

# A few directional carved locks to unify the mass
for side in (-1,1):
    curve_tube("Temple swept lock", [(side*0.77,-0.40,4.17),(side*0.83,-0.18,4.38),(side*0.72,-0.05,4.56)], 0.065, hairmat)

# Small authentic chips on socle edge
for x,y,s in [(-0.49,-0.50,0.055),(0.41,-0.52,0.042),(-0.20,-0.62,0.028)]:
    uv("Tiny plaster chip", (x,y,2.44), (s,0.018,s*0.7), edge_mat, 16, 8)

# Backdrop: large curved-feeling wall and floor
bpy.ops.mesh.primitive_plane_add(size=30, location=(0,3,5), rotation=(math.pi/2,0,0))
wall=bpy.context.object; wall.name="Neutral studio backdrop"; wall.data.materials.append(backmat)
bpy.ops.mesh.primitive_plane_add(size=30, location=(0,0,0.08))
floor=bpy.context.object; floor.name="Studio floor"; floor.data.materials.append(backmat)

# Lighting
def area(name, loc, energy, size, color):
    data=bpy.data.lights.new(name,'AREA'); data.energy=energy; data.shape='DISK'; data.size=size; data.color=color
    ob=bpy.data.objects.new(name,data); bpy.context.collection.objects.link(ob); ob.location=loc
    return ob
def point_at(obj, target):
    obj.rotation_euler=(Vector(target)-obj.location).to_track_quat('-Z','Y').to_euler()

key=area("Large raking atelier key", (-4.5,-5.5,7.2), 1050, 4.0, (1.0,0.88,0.72)); point_at(key,(0,0,3.55))
fill=area("Gentle shadow-side bounce", (4.5,-3.0,4.7), 380, 5.0, (0.68,0.75,1.0)); point_at(fill,(0,0,3.5))
rim=area("Very soft rear separation", (-1.5,2.5,6.0), 450, 3.0, (1.0,0.82,0.62)); point_at(rim,(0,0,4.0))

# Camera, eye-level three-quarter catalogue view
camdata=bpy.data.cameras.new("Catalogue camera")
cam=bpy.data.objects.new("Catalogue camera",camdata); bpy.context.collection.objects.link(cam)
bpy.context.scene.camera=cam
cam.location=(5.25,-10.8,4.72)
camdata.lens=72
camdata.sensor_width=36
point_at(cam,(0,-0.10,3.45))

# Render / color management
scene=bpy.context.scene
scene.render.engine='BLENDER_EEVEE_NEXT'
scene.render.resolution_x=1536
scene.render.resolution_y=1536
scene.render.resolution_percentage=100
scene.render.image_settings.file_format='PNG'
scene.render.film_transparent=False
scene.render.filepath="/tmp/classical_bust.png"
scene.world.color=(0.035,0.035,0.035)
scene.view_settings.look='AgX - Medium High Contrast'
scene.render.image_settings.color_mode='RGBA'

# Ensure camera clipping
camdata.clip_start=0.05
camdata.clip_end=100

# Organize
for ob in bpy.context.scene.objects:
    if ob.type == 'MESH':
        ob.select_set(False)

# Save
bpy.ops.wm.save_as_mainfile(filepath="/tmp/classical_atelier_bust.blend")
```