[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 only on the published visual outputs they can inspect: the interactive 3D scene and rendered presentation.

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 final published capture 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. The saved scene is also exported to GLB with geometry, materials, the contestant camera, and supported lights for interactive inspection. 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.

## Harness Instructions

You are operating Blender through the provided tools. The scene starts empty. Build what the user's prompt asks for in the current scene. Work step by step and verify your own work. Before you finish, set up a camera and lighting to frame a single, well-composed presentation image of your result — position and aim the camera, and add or adjust lights so the subject reads clearly. 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. The saved scene is also exported to GLB with geometry, materials, your camera, and supported lights for interactive inspection. When you are finished, reply with the single word DONE and no tool calls.

[User]
## Task

Complete the following Blender task:

<task>

A desk-mounted robotic arm with at least four articulated joints, posed mid-reach toward a small object on the desk — but not an industrial catalog part. This arm is generatively designed: its metal frame has the parametric, "AI-optimized" look of topology-optimized engineering — organic load-bearing branches, smooth bone-like transitions, lattice or voronoi-style cutouts where material was removed because the algorithm decided nothing needed to be there. Every strut should look grown to carry its exact load, not extruded.

Over that frame, a second material layer: woven technical fabric. Tensioned textile sleeves and panels — visible weave pattern, carbon-fiber or ballistic-cloth character — wrap sections of the segments over the optimized metal skeleton, so the arm reads as engineered musculature over engineered bone. The interplay of the two materials (taut woven fiber against machined/printed alloy) is the material centerpiece.

The manipulator: a three-clawed gripper at the wrist — three fingers in radial symmetry, each with the same optimized-lattice construction in miniature, posed partly open toward the target object. The gripper connects to the forearm through corrugated hose: flexible ribbed tubing gathered at the wrist, running back along the arm as its visible service umbilical (power, data, pneumatics), routed and clipped like it was engineered, not draped.

The mechanics must still look like they could actually work: visible rotation axes at every joint, with actuators, cable runs, or tendon-like elements explaining how each segment moves; segments tapering plausibly from a heavy base to the fine three-claw head. The pose must be believable for the joint layout: no segment intersecting another, no joint bent in a way its geometry couldn't allow.

</task>

[Tool] PolyHaven integration is disabled. Select it in the sidebar in BlenderMCP, then run it again.

[Tool]
{
  "name": "Scene",
  "object_count": 0,
  "objects": [],
  "materials_count": 2
}

[Tool] Code executed successfully: Scene cleared.

Get detailed information about the current Blender scene

    Parameters:
    - user_prompt: The original user prompt that led to this tool call (required for telemetry)

User Prompt

get_scene_infoArguments

    Get detailed information about a specific object in the Blender scene.

    Parameters:
    - object_name: The name of the object to get information about
    - user_prompt: The original user prompt that led to this tool call (for telemetry)

Object Name

User Prompt

get_object_infoArguments

    Capture a screenshot of the current Blender 3D viewport.

    Parameters:
    - max_size: Maximum size in pixels for the largest dimension (default: 800)
    - user_prompt: The original user prompt that led to this tool call (for telemetry)

    Returns the screenshot as an Image.

Max Size

User Prompt

get_viewport_screenshotArguments

    Execute arbitrary Python code in Blender. Make sure to do it step-by-step by breaking it into smaller chunks.

    Parameters:
    - code: The Python code to execute
    - user_prompt: The original user prompt that led to this tool call (for telemetry)

Code

User Prompt

execute_blender_codeArguments

    Get a list of categories for a specific asset type on Polyhaven.

    Parameters:
    - asset_type: The type of asset to get categories for (hdris, textures, models, all)
    - user_prompt: The original user prompt that led to this tool call (for telemetry)

Asset Type

User Prompt

get_polyhaven_categoriesArguments

    Search for assets on Polyhaven with optional filtering.

    Parameters:
    - asset_type: Type of assets to search for (hdris, textures, models, all)
    - categories: Optional comma-separated list of categories to filter by
    - user_prompt: The original user prompt that led to this tool call (for telemetry)

    Returns a list of matching assets with basic information.

Asset Type

Categories

User Prompt

search_polyhaven_assetsArguments

    Download and import a Polyhaven asset into Blender.

    Parameters:
    - asset_id: The ID of the asset to download
    - asset_type: The type of asset (hdris, textures, models)
    - resolution: The resolution to download (e.g., 1k, 2k, 4k)
    - file_format: Optional file format (e.g., hdr, exr for HDRIs; jpg, png for textures; gltf, fbx for models)
    - user_prompt: The original user prompt that led to this tool call (for telemetry)

    Returns a message indicating success or failure.

Asset Id

Asset Type

Resolution

File Format

User Prompt

download_polyhaven_assetArguments

    Apply a previously downloaded Polyhaven texture to an object.

    Parameters:
    - object_name: Name of the object to apply the texture to
    - texture_id: ID of the Polyhaven texture to apply (must be downloaded first)

    Returns a message indicating success or failure.

Object Name

Texture Id

User Prompt

set_textureArguments

    Check if PolyHaven integration is enabled in Blender.
    Returns a message indicating whether PolyHaven features are available.

User Prompt

get_polyhaven_statusArguments

    Check if Hyper3D Rodin integration is enabled in Blender.
    Returns a message indicating whether Hyper3D Rodin features are available.

User Prompt

    Check if Sketchfab integration is enabled in Blender.
    Returns a message indicating whether Sketchfab features are available.

User Prompt

get_sketchfab_statusArguments

    Search for models on Sketchfab with optional filtering.

    Parameters:
    - query: Text to search for
    - categories: Optional comma-separated list of categories
    - count: Maximum number of results to return (default 20)
    - downloadable: Whether to include only downloadable models (default True)

    Returns a formatted list of matching models.

Query

Categories

Count

Downloadable

User Prompt

search_sketchfab_modelsArguments

    Get a preview thumbnail of a Sketchfab model by its UID.
    Use this to visually confirm a model before downloading.

    Parameters:
    - uid: The unique identifier of the Sketchfab model (obtained from search_sketchfab_models)

    Returns the model's thumbnail as an Image for visual confirmation.

Uid

User Prompt

get_sketchfab_model_previewArguments

    Download and import a Sketchfab model by its UID.
    The model will be scaled so its largest dimension equals target_size.

    Parameters:
    - uid: The unique identifier of the Sketchfab model
    - target_size: REQUIRED. The target size in Blender units/meters for the largest dimension.
                  You must specify the desired size for the model.
                  Examples:
                  - Chair: target_size=1.0 (1 meter tall)
                  - Table: target_size=0.75 (75cm tall)
                  - Car: target_size=4.5 (4.5 meters long)
                  - Person: target_size=1.7 (1.7 meters tall)
                  - Small object (cup, phone): target_size=0.1 to 0.3

    Returns a message with import details including object names, dimensions, and bounding box.
    The model must be downloadable and you must have proper access rights.

Uid

Target Size

User Prompt

download_sketchfab_modelArguments

    Generate 3D asset using Hyper3D by giving description of the desired asset, and import the asset into Blender.
    The 3D asset has built-in materials.
    The generated model has a normalized size, so re-scaling after generation can be useful.

    Parameters:
    - text_prompt: A short description of the desired model in **English**.
    - bbox_condition: Optional. If given, it has to be a list of floats of length 3. Controls the ratio between [Length, Width, Height] of the model.

    Returns a message indicating success or failure.

Text Prompt

Bbox Condition

User Prompt

    Generate 3D asset using Hyper3D by giving images of the wanted asset, and import the generated asset into Blender.
    The 3D asset has built-in materials.
    The generated model has a normalized size, so re-scaling after generation can be useful.

    Parameters:
    - input_image_paths: The **absolute** paths of input images. Even if only one image is provided, wrap it into a list. Required if Hyper3D Rodin in MAIN_SITE mode.
    - input_image_urls: The URLs of input images. Even if only one image is provided, wrap it into a list. Required if Hyper3D Rodin in FAL_AI mode.
    - bbox_condition: Optional. If given, it has to be a list of ints of length 3. Controls the ratio between [Length, Width, Height] of the model.

    Only one of {input_image_paths, input_image_urls} should be given at a time, depending on the Hyper3D Rodin's current mode.
    Returns a message indicating success or failure.

Input Image Paths

Input Image Urls

Bbox Condition

User Prompt

    Check if the Hyper3D Rodin generation task is completed.

    For Hyper3D Rodin mode MAIN_SITE:
        Parameters:
        - subscription_key: The subscription_key given in the generate model step.

        Returns a list of status. The task is done if all status are "Done".
        If "Failed" showed up, the generating process failed.
        This is a polling API, so only proceed if the status are finally determined ("Done" or "Canceled").

    For Hyper3D Rodin mode FAL_AI:
        Parameters:
        - request_id: The request_id given in the generate model step.

        Returns the generation task status. The task is done if status is "COMPLETED".
        The task is in progress if status is "IN_PROGRESS".
        If status other than "COMPLETED", "IN_PROGRESS", "IN_QUEUE" showed up, the generating process might be failed.
        This is a polling API, so only proceed if the status are finally determined ("COMPLETED" or some failed state).

Subscription Key

Request Id

poll_rodin_job_statusArguments

    Import the asset generated by Hyper3D Rodin after the generation task is completed.

    Parameters:
    - name: The name of the object in scene
    - task_uuid: For Hyper3D Rodin mode MAIN_SITE: The task_uuid given in the generate model step.
    - request_id: For Hyper3D Rodin mode FAL_AI: The request_id given in the generate model step.

    Only give one of {task_uuid, request_id} based on the Hyper3D Rodin Mode!
    Return if the asset has been imported successfully.

Name

Task Uuid

Request Id

import_generated_assetArguments

    Check if Hunyuan3D integration is enabled in Blender.
    Returns a message indicating whether Hunyuan3D features are available.

User Prompt

    Generate 3D asset using Hunyuan3D by providing either text description, image reference,
    or both for the desired asset, and import the asset into Blender.
    The 3D asset has built-in materials.

    Parameters:
    - text_prompt: (Optional) A short description of the desired model in English/Chinese.
    - input_image_url: (Optional) The local or remote url of the input image. Accepts None if only using text prompt.

    Returns:
    - When successful, returns a JSON with job_id (format: "job_xxx") indicating the task is in progress
    - When the job completes, the status will change to "DONE" indicating the model has been imported
    - Returns error message if the operation fails

Text Prompt

Input Image Url

User Prompt

    Check if the Hunyuan3D generation task is completed.

    For Hunyuan3D:
        Parameters:
        - job_id: The job_id given in the generate model step.

        Returns the generation task status. The task is done if status is "DONE".
        The task is in progress if status is "RUN".
        If status is "DONE", returns ResultFile3Ds, which is the generated ZIP model path
        When the status is "DONE", the response includes a field named ResultFile3Ds that contains the generated ZIP file path of the 3D model in OBJ format.
        This is a polling API, so only proceed if the status are finally determined ("DONE" or some failed state).

Job Id

poll_hunyuan_job_statusArguments

    Import the asset generated by Hunyuan3D after the generation task is completed.

    Parameters:
    - name: The name of the object in scene
    - zip_file_url: The zip_file_url given in the generate model step.

    Return if the asset has been imported successfully.

Name

Zip File Url

import_generated_asset_hunyuanArguments

[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 only on the published visual outputs they can inspect: the interactive 3D scene and rendered presentation.

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 final published capture 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. The saved scene is also exported to GLB with geometry, materials, the contestant camera, and supported lights for interactive inspection. 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.

## Harness Instructions

You are operating Blender through the provided tools. The scene starts empty. Build what the user's prompt asks for in the current scene. Work step by step and verify your own work. Before you finish, set up a camera and lighting to frame a single, well-composed presentation image of your result — position and aim the camera, and add or adjust lights so the subject reads clearly. 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. The saved scene is also exported to GLB with geometry, materials, your camera, and supported lights for interactive inspection. When you are finished, reply with the single word DONE and no tool calls.

[User]
## Task

Complete the following Blender task:

<task>

A desk-mounted robotic arm with at least four articulated joints, posed mid-reach toward a small object on the desk — but not an industrial catalog part. This arm is generatively designed: its metal frame has the parametric, "AI-optimized" look of topology-optimized engineering — organic load-bearing branches, smooth bone-like transitions, lattice or voronoi-style cutouts where material was removed because the algorithm decided nothing needed to be there. Every strut should look grown to carry its exact load, not extruded.

Over that frame, a second material layer: woven technical fabric. Tensioned textile sleeves and panels — visible weave pattern, carbon-fiber or ballistic-cloth character — wrap sections of the segments over the optimized metal skeleton, so the arm reads as engineered musculature over engineered bone. The interplay of the two materials (taut woven fiber against machined/printed alloy) is the material centerpiece.

The manipulator: a three-clawed gripper at the wrist — three fingers in radial symmetry, each with the same optimized-lattice construction in miniature, posed partly open toward the target object. The gripper connects to the forearm through corrugated hose: flexible ribbed tubing gathered at the wrist, running back along the arm as its visible service umbilical (power, data, pneumatics), routed and clipped like it was engineered, not draped.

The mechanics must still look like they could actually work: visible rotation axes at every joint, with actuators, cable runs, or tendon-like elements explaining how each segment moves; segments tapering plausibly from a heavy base to the fine three-claw head. The pose must be believable for the joint layout: no segment intersecting another, no joint bent in a way its geometry couldn't allow.

</task>

[Tool] PolyHaven integration is disabled. Select it in the sidebar in BlenderMCP, then run it again.

[Tool]
{
  "name": "Scene",
  "object_count": 0,
  "objects": [],
  "materials_count": 2
}

[Tool] Code executed successfully: Scene cleared.

User Prompt

get_scene_infoArguments

Object Name

User Prompt

get_object_infoArguments

Max Size

User Prompt

get_viewport_screenshotArguments

Code

User Prompt

execute_blender_codeArguments

Asset Type

User Prompt

get_polyhaven_categoriesArguments

Asset Type

Categories

User Prompt

search_polyhaven_assetsArguments

Asset Id

Asset Type

Resolution

File Format

User Prompt

download_polyhaven_assetArguments

Object Name

Texture Id

User Prompt

set_textureArguments

User Prompt

get_polyhaven_statusArguments

User Prompt

User Prompt

get_sketchfab_statusArguments

Query

Categories

Count

Downloadable

User Prompt

search_sketchfab_modelsArguments

Uid

User Prompt

get_sketchfab_model_previewArguments

Uid

Target Size

User Prompt

download_sketchfab_modelArguments

Text Prompt

Bbox Condition

User Prompt

Input Image Paths

Input Image Urls

Bbox Condition

User Prompt

Subscription Key

Request Id

poll_rodin_job_statusArguments

Name

Task Uuid

Request Id

import_generated_assetArguments

User Prompt

Text Prompt

Input Image Url

User Prompt

Job Id

poll_hunyuan_job_statusArguments

Name

Zip File Url

import_generated_asset_hunyuanArguments

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-1784091655-uyV6C63xXRirbMjRXd6M","object":"chat.completion","created":1784091655,"model":"google/gemini-3.5-flash","provider":"Google","system_fingerprint":null,"service_tier":"provisioned","choices":[{"index":0,"logprobs":null,"finish_reason":"tool_calls","native_finish_reason":"STOP","message":{"role":"assistant","content":null,"refusal":null,"reasoning":"**Designing Robotic Arm**\n\nI am currently focusing on the generative design of the robotic arm's frame. My aim is to achieve a topology-optimized aesthetic, characterized by organic, load-bearing structures and smooth, bone-like transitions, all rendered with an AI-optimized metal finish. I'm also working on posing the arm mid-reach towards a target object.\n\n**Developing Robotic Arm Aesthetics**\n\nI'm now exploring material layering for the arm, envisioning a tensioned, woven technical fabric overlaying the metal skeleton. I'm also detailing the three-clawed gripper and planning a corrugated service umbilical, ensuring the mechanics like rotation axes and cable runs are visible and plausible.\n\n**Refining Structural Design**\n\nI'm refining the frame's aesthetic, leaning towards organic, load-bearing branches with lattice cutouts. My current exploration involves generating base meshes with apertures and branching, then applying subdivision for a bone-like appearance. Bezier curves, converted and remeshed, are proving effective for achieving these intricate structures.\n\n**Generating Organic Arm Segments**\n\nI'm now focused on procedural generation of the arm's segments using Python, aiming for perfect organic transitions and bone-like lattice structures. I'll be exploring voxel remeshing and subdivision techniques to achieve these complex forms.\n\n**Constructing Bone Segments**\n\nI'm now focusing on a procedural approach to generating individual bone-like arm segments. My current strategy involves defining a spine between two points, then elaborating this with branching struts and carved-out, Voronoi-esque apertures, aiming for a topology-optimized, organic structure.\n\n**Generating Curve-Based Structures**\n\nI'm now detailing a curve-based generator in Python. My aim is to define struts and lattice structures using curves, bevel them, and convert them to a mesh, creating topology-optimized, 3D-printed metal aesthetics. I'll also add joint caps and explore a tensioned textile sleeve overlay for added realism.\n\n**Scripting Generative Arm**\n\nI'm now focused on developing a Python script to procedurally generate the entire robotic arm. My approach is to build it block by block, starting with detailing the desk surface and its PBR material, followed by the base mounting with its chamfered edges and visible motor housing.\n\n**Modeling Corrugated Hose**\n\nI am now focusing on generating the ribbed, corrugated service umbilical. My plan is to define a Bezier curve path through custom-placed guide points on the arm segments, then apply a specific profile to create the corrugated texture. I'll also be detailing the joint caps and the tensioned textile sleeve.\n\n**Modeling Corrugated Hose**\n\nI'm exploring efficient methods to generate the corrugated service umbilical. My current thoughts lean towards using a procedural shader with a sine wave displacement mapped to a cylinder, or alternatively, creating actual geometry by extruding and scaling rings along a curve. Either approach should yield excellent results for the ribbed texture.\n\n**Scripting Generative Arm Components**\n\nI am now focused on scripting the generation of individual arm components. My initial steps involve developing procedural shaders for optimized metal and a technical fabric weave. I am also exploring the creation of a blue emissive sphere, all designed to be buildable via Python.\n\n","tool_calls":[{"type":"function","index":0,"id":"tool_execute_blender_code_gg1nUF0u5fBeIX6wbDNv","function":{"name":"execute_blender_code","arguments":"{\"code\":\"import bpy\\n\\ndef create_procedural_materials():\\n    materials = {}\\n    \\n    # 1. Topology-Optimized Metals (Titanium)\\n    mat_metal = bpy.data.materials.new(name=\\\"Optimized_Metal\\\")\\n    mat_metal.use_nodes = True\\n    nodes = mat_metal.node_tree.nodes\\n    links = mat_metal.node_tree.links\\n    \\n    # Clean default nodes\\n    for n in nodes:\\n        nodes.remove(n)\\n        \\n    # Output node\\n    node_out = nodes.new(type='ShaderNodeOutputMaterial')\\n    node_out.location = (400, 0)\\n    \\n    # Principled BSDF\\n    node_bsdf = nodes.new(type='ShaderNodeBsdfPrincipled')\\n    node_bsdf.location = (100, 0)\\n    node_bsdf.inputs['Metallic'].default_value = 1.0\\n    node_bsdf.inputs['Roughness'].default_value = 0.35\\n    # Warm titanium grey\\n    node_bsdf.inputs['Base Color'].default_value = (0.4, 0.41, 0.43, 1.0)\\n    links.new(node_bsdf.outputs['BSDF'], node_out.inputs['Surface'])\\n    \\n    # Add a bit of noise bump for 3D printed look\\n    node_noise = nodes.new(type='ShaderNodeTexNoise')\\n    node_noise.location = (-300, -100)\\n    node_noise.inputs['Scale'].default_value = 400.0\\n    node_noise.inputs['Detail'].default_value = 6.0\\n    node_noise.inputs['Roughness'].default_value = 0.7\\n    \\n    node_bump = nodes.new(type='ShaderNodeBump')\\n    node_bump.location = (-100, -100)\\n    node_bump.inputs['Strength'].default_value = 0.05\\n    node_bump.inputs['Distance'].default_value = 0.01\\n    \\n    links.new(node_noise.outputs['Fac'], node_bump.inputs['Height'])\\n    links.new(node_bump.outputs['Normal'], node_bsdf.inputs['Normal'])\\n    \\n    materials['metal'] = mat_metal\\n    \\n    # 2. Technical Woven Fabric (Carbon Fiber / Ballistic Nylon)\\n    # Let's do a stunning procedural weave in orange or high-viz tech yellow, or classic dark grey carbon fiber\\n    mat_fabric = bpy.data.materials.new(name=\\\"Tech_Fabric\\\")\\n    mat_fabric.use_nodes = True\\n    nodes_f = mat_fabric.node_tree.nodes\\n    links_f = mat_fabric.node_tree.links\\n    \\n    for n in nodes_f:\\n        nodes_f.remove(n)\\n        \\n    node_out_f = nodes_f.new(type='ShaderNodeOutputMaterial')\\n    node_out_f.location = (400, 0)\\n    \\n    node_bsdf_f = nodes_f.new(type='ShaderNodeBsdfPrincipled')\\n    node_bsdf_f.location = (100, 0)\\n    node_bsdf_f.inputs['Roughness'].default_value = 0.5\\n    # Dark carbon-blackish base\\n    node_bsdf_f.inputs['Base Color'].default_value = (0.1, 0.12, 0.14, 1.0)\\n    links_f.new(node_bsdf_f.outputs['BSDF'], node_out_f.inputs['Surface'])\\n    \\n    # Procedural carbon weave pattern using Wave Textures\\n    # We create two perpendicular wave textures to simulate warp and weft\\n    node_coord = nodes_f.new(type='ShaderNodeTexCoord')\\n    node_coord.location = (-700, 100)\\n    \\n    node_mapping = nodes_f.new(type='ShaderNodeMapping')\\n    node_mapping.location = (-500, 100)\\n    node_mapping.inputs['Scale'].default_value[0] = 300.0\\n    node_mapping.inputs['Scale'].default_value[1] = 300.0\\n    links_f.new(node_coord.outputs['UV'], node_mapping.inputs['Vector'])\\n    \\n    node_wave_x = nodes_f.new(type='ShaderNodeTexWave')\\n    node_wave_x.location = (-300, 200)\\n    node_wave_x.wave_type = 'BANDS'\\n    node_wave_x.bands_direction = 'X'\\n    node_wave_x.inputs['Scale'].default_value = 1.0\\n    node_wave_x.inputs['Distortion'].default_value = 0.5\\n    links_f.new(node_mapping.outputs['Vector'], node_wave_x.inputs['Vector'])\\n    \\n    node_wave_y = nodes_f.new(type='ShaderNodeTexWave')\\n    node_wave_y.location = (-300, -50)\\n    node_wave_y.wave_type = 'BANDS'\\n    node_wave_y.bands_direction = 'Y'\\n    node_wave_y.inputs['Scale'].default_value = 1.0\\n    node_wave_y.inputs['Distortion'].default_value = 0.5\\n    links_f.new(node_mapping.outputs['Vector'], node_wave_y.inputs['Vector'])\\n    \\n    node_mix = nodes_f.new(type='ShaderNodeMixRGB')\\n    node_mix.location = (-100, 100)\\n    node_mix.blend_type = 'MIX'\\n    node_mix.inputs['Factor'].default_value = 0.5\\n    links_f.new(node_wave_x.outputs['Color'], node_mix.inputs['Color1'])\\n    links_f.new(node_wave_y.outputs['Color'], node_mix.inputs['Color2'])\\n    \\n    # Set Weave highlights\\n    node_color_mix = nodes_f.new(type='ShaderNodeValToRGB')\\n    node_color_mix.location = (100, 250)\\n    node_color_mix.color_ramp.elements[0].position = 0.4\\n    node_color_mix.color_ramp.elements[0].color = (0.05, 0.05, 0.06, 1.0) # Dark carbon\\n    node_color_mix.color_ramp.elements[1].position = 0.6\\n    node_color_mix.color_ramp.elements[1].color = (0.2, 0.22, 0.25, 1.0) # Lighter weave highlight\\n    links_f.new(node_mix.outputs['Color'], node_color_mix.inputs['Fac'])\\n    links_f.new(node_color_mix.outputs['Color'], node_bsdf_f.inputs['Base Color'])\\n    \\n    # Weave bump map\\n    node_bump_f = nodes_f.new(type='ShaderNodeBump')\\n    node_bump_f.location = (100, -150)\\n    node_bump_f.inputs['Strength'].default_value = 0.15\\n    node_bump_f.inputs['Distance'].default_value = 0.1\\n    links_f.new(node_mix.outputs['Color'], node_bump_f.inputs['Height'])\\n    links_f.new(node_bump_f.outputs['Normal'], node_bsdf_f.inputs['Normal'])\\n    \\n    # Make woven material slightly anisotropic/shiny in the specular\\n    node_bsdf_f.inputs['Roughness'].default_value = 0.4\\n    \\n    materials['fabric'] = mat_fabric\\n    \\n    # 3. Gold / Cooper Accents for tendons/conductors\\n    mat_copper = bpy.data.materials.new(name=\\\"Accents_Copper\\\")\\n    mat_copper.use_nodes = True\\n    nodes_c = mat_copper.node_tree.nodes\\n    mat_copper.node_tree.links.new(nodes_c['Principled BSDF'].outputs['BSDF'], nodes_c['Material Output'].inputs['Surface'])\\n    nodes_c['Principled BSDF'].inputs['Metallic'].default_value = 1.0\\n    nodes_c['Principled BSDF'].inputs['Roughness'].default_value = 0.15\\n    nodes_c['Principled BSDF'].inputs['Base Color'].default_value = (0.8, 0.45, 0.25, 1.0) # copper\\n    materials['copper'] = mat_copper\\n    \\n    # 4. Hose Material (Dark Matte Ribbed Ribs)\\n    mat_hose = bpy.data.materials.new(name=\\\"Hose_Material\\\")\\n    mat_hose.use_nodes = True\\n    nodes_h = mat_hose.node_tree.nodes\\n    mat_hose.node_tree.links.new(nodes_h['Principled BSDF'].outputs['BSDF'], nodes_h['Material Output'].inputs['Surface'])\\n    nodes_h['Principled BSDF'].inputs['Metallic'].default_value = 0.1\\n    nodes_h['Principled BSDF'].inputs['Roughness'].default_value = 0.4\\n    nodes_h['Principled BSDF'].inputs['Base Color'].default_value = (0.05, 0.05, 0.06, 1.0) # Dark rich rubber\\n    materials['hose'] = mat_hose\\n\\n    # 5. Desk Material (Rich Walnut Wood)\\n    mat_desk = bpy.data.materials.new(name=\\\"Desk_Wood\\\")\\n    mat_desk.use_nodes = True\\n    nodes_d = mat_desk.node_tree.nodes\\n    nodes_d.clear()\\n    \\n    d_out = nodes_d.new(type='ShaderNodeOutputMaterial')\\n    d_out.location = (400, 0)\\n    d_bsdf = nodes_d.new(type='ShaderNodeBsdfPrincipled')\\n    d_bsdf.location = (100, 0)\\n    nodes_d.new(type='ShaderNodeTexNoise') # just a quick organic base\\n    \\n    # Create simple procedural wood shader\\n    # Coordinates -> Mapping (squashed on z) -> Noise -> ColorRamp -> BaseColor, Roughness, Bump\\n    d_coord = nodes_d.new(type='ShaderNodeTexCoord')\\n    d_map = nodes_d.new(type='ShaderNodeMapping')\\n    d_map.inputs['Scale'].default_value[0] = 5.0\\n    d_map.inputs['Scale'].default_value[1] = 0.2 # stretched along Y\\n    d_map.inputs['Scale'].default_value[2] = 0.2\\n    \\n    d_noise = nodes_d.new(type='ShaderNodeTexNoise')\\n    d_noise.inputs['Scale'].default_value = 3.0\\n    d_noise.inputs['Detail'].default_value = 4.0\\n    d_noise.inputs['Distortion'].default_value = 1.5\\n    \\n    d_ramp = nodes_d.new(type='ShaderNodeValToRGB')\\n    d_ramp.color_ramp.elements[0].position = 0.0\\n    d_ramp.color_ramp.elements[0].color = (0.1, 0.05, 0.02, 1.0) # Dark walnut\\n    d_ramp.color_ramp.elements[1].position = 1.0\\n    d_ramp.color_ramp.elements[1].color = (0.28, 0.16, 0.09, 1.0) # Rich mid brown\\n    \\n    d_bump = nodes_d.new(type='ShaderNodeBump')\\n    d_bump.inputs['Strength'].default_value = 0.04\\n    \\n    mat_desk.node_tree.links.new(d_coord.outputs['Generated'], d_map.inputs['Vector'])\\n    mat_desk.node_tree.links.new(d_map.outputs['Vector'], d_noise.inputs['Vector'])\\n    mat_desk.node_tree.links.new(d_noise.outputs['Fac'], d_ramp.inputs['Fac'])\\n    mat_desk.node_tree.links.new(d_ramp.outputs['Color'], d_bsdf.inputs['Base Color'])\\n    mat_desk.node_tree.links.new(d_noise.outputs['Fac'], d_bump.inputs['Height'])\\n    mat_desk.node_tree.links.new(d_bump.outputs['Normal'], d_bsdf.inputs['Normal'])\\n    d_bsdf.inputs['Roughness'].default_value = 0.25\\n    \\n    mat_desk.node_tree.links.new(d_bsdf.outputs['BSDF'], d_out.inputs['Surface'])\\n    materials['desk'] = mat_desk\\n\\n    # 6. Glowing Target Artifact\\n    mat_glow = bpy.data.materials.new(name=\\\"Artifact_Glow\\\")\\n    mat_glow.use_nodes = True\\n    nodes_g = mat_glow.node_tree.nodes\\n    nodes_g.clear()\\n    g_out = nodes_g.new(type='ShaderNodeOutputMaterial')\\n    g_bsdf = nodes_g.new(type='ShaderNodeBsdfPrincipled')\\n    g_bsdf.inputs['Base Color'].default_value = (0.05, 0.4, 0.8, 1.0) # Cyber teal\\n    g_bsdf.inputs['Emission'].default_value = (0.02, 0.3, 0.6, 1.0)\\n    g_bsdf.inputs['Emission Strength'].default_value = 5.0\\n    mat_glow.node_tree.links.new(g_bsdf.outputs['BSDF'], g_out.inputs['Surface'])\\n    materials['glow'] = mat_glow\\n\\n    return materials\\n\\nmaterials = create_procedural_materials()\\nprint(\\\"Materials successfully configured:\\\", list(materials.keys()))\\n\",\"user_prompt\":\"Set up procedural materials including metal, technical woven fabric, copper accents, hose material, desk wood, and glowing artifact shader.\"}"}}],"reasoning_details":[{"type":"reasoning.text","text":"**Designing Robotic Arm**\n\nI am currently focusing on the generative design of the robotic arm's frame. My aim is to achieve a topology-optimized aesthetic, characterized by organic, load-bearing structures and smooth, bone-like transitions, all rendered with an AI-optimized metal finish. I'm also working on posing the arm mid-reach towards a target object.\n\n**Developing Robotic Arm Aesthetics**\n\nI'm now exploring material layering for the arm, envisioning a tensioned, woven technical fabric overlaying the metal skeleton. I'm also detailing the three-clawed gripper and planning a corrugated service umbilical, ensuring the mechanics like rotation axes and cable runs are visible and plausible.\n\n**Refining Structural Design**\n\nI'm refining the frame's aesthetic, leaning towards organic, load-bearing branches with lattice cutouts. My current exploration involves generating base meshes with apertures and branching, then applying subdivision for a bone-like appearance. Bezier curves, converted and remeshed, are proving effective for achieving these intricate structures.\n\n**Generating Organic Arm Segments**\n\nI'm now focused on procedural generation of the arm's segments using Python, aiming for perfect organic transitions and bone-like lattice structures. I'll be exploring voxel remeshing and subdivision techniques to achieve these complex forms.\n\n**Constructing Bone Segments**\n\nI'm now focusing on a procedural approach to generating individual bone-like arm segments. My current strategy involves defining a spine between two points, then elaborating this with branching struts and carved-out, Voronoi-esque apertures, aiming for a topology-optimized, organic structure.\n\n**Generating Curve-Based Structures**\n\nI'm now detailing a curve-based generator in Python. My aim is to define struts and lattice structures using curves, bevel them, and convert them to a mesh, creating topology-optimized, 3D-printed metal aesthetics. I'll also add joint caps and explore a tensioned textile sleeve overlay for added realism.\n\n**Scripting Generative Arm**\n\nI'm now focused on developing a Python script to procedurally generate the entire robotic arm. My approach is to build it block by block, starting with detailing the desk surface and its PBR material, followed by the base mounting with its chamfered edges and visible motor housing.\n\n**Modeling Corrugated Hose**\n\nI am now focusing on generating the ribbed, corrugated service umbilical. My plan is to define a Bezier curve path through custom-placed guide points on the arm segments, then apply a specific profile to create the corrugated texture. I'll also be detailing the joint caps and the tensioned textile sleeve.\n\n**Modeling Corrugated Hose**\n\nI'm exploring efficient methods to generate the corrugated service umbilical. My current thoughts lean towards using a procedural shader with a sine wave displacement mapped to a cylinder, or alternatively, creating actual geometry by extruding and scaling rings along a curve. Either approach should yield excellent results for the ribbed texture.\n\n**Scripting Generative Arm Components**\n\nI am now focused on scripting the generation of individual arm components. My initial steps involve developing procedural shaders for optimized metal and a technical fabric weave. I am also exploring the creation of a blue emissive sphere, all designed to be buildable via Python.\n\n","format":"google-gemini-v1","index":0},{"type":"reasoning.encrypted","data":"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","format":"google-gemini-v1","id":"tool_execute_blender_code_gg1nUF0u5fBeIX6wbDNv","index":1}]}}],"usage":{"prompt_tokens":3950,"completion_tokens":5914,"total_tokens":9864,"cost":0.059151,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"cache_write_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":0.059151,"upstream_inference_prompt_cost":0.005925,"upstream_inference_completions_cost":0.053226},"completion_tokens_details":{"reasoning_tokens":2484,"image_tokens":0,"audio_tokens":0}}}

import bpy

def create_procedural_materials():
    materials = {}

    # 1. Topology-Optimized Metals (Titanium)
    mat_metal = bpy.data.materials.new(name="Optimized_Metal")
    mat_metal.use_nodes = True
    nodes = mat_metal.node_tree.nodes
    links = mat_metal.node_tree.links

    # Clean default nodes
    for n in nodes:
        nodes.remove(n)

    # Output node
    node_out = nodes.new(type='ShaderNodeOutputMaterial')
    node_out.location = (400, 0)

    # Principled BSDF
    node_bsdf = nodes.new(type='ShaderNodeBsdfPrincipled')
    node_bsdf.location = (100, 0)
    node_bsdf.inputs['Metallic'].default_value = 1.0
    node_bsdf.inputs['Roughness'].default_value = 0.35
    # Warm titanium grey
    node_bsdf.inputs['Base Color'].default_value = (0.4, 0.41, 0.43, 1.0)
    links.new(node_bsdf.outputs['BSDF'], node_out.inputs['Surface'])

    # Add a bit of noise bump for 3D printed look
    node_noise = nodes.new(type='ShaderNodeTexNoise')
    node_noise.location = (-300, -100)
    node_noise.inputs['Scale'].default_value = 400.0
    node_noise.inputs['Detail'].default_value = 6.0
    node_noise.inputs['Roughness'].default_value = 0.7

    node_bump = nodes.new(type='ShaderNodeBump')
    node_bump.location = (-100, -100)
    node_bump.inputs['Strength'].default_value = 0.05
    node_bump.inputs['Distance'].default_value = 0.01

    links.new(node_noise.outputs['Fac'], node_bump.inputs['Height'])
    links.new(node_bump.outputs['Normal'], node_bsdf.inputs['Normal'])

    materials['metal'] = mat_metal

    # 2. Technical Woven Fabric (Carbon Fiber / Ballistic Nylon)
    # Let's do a stunning procedural weave in orange or high-viz tech yellow, or classic dark grey carbon fiber
    mat_fabric = bpy.data.materials.new(name="Tech_Fabric")
    mat_fabric.use_nodes = True
    nodes_f = mat_fabric.node_tree.nodes
    links_f = mat_fabric.node_tree.links

    for n in nodes_f:
        nodes_f.remove(n)

    node_out_f = nodes_f.new(type='ShaderNodeOutputMaterial')
    node_out_f.location = (400, 0)

    node_bsdf_f = nodes_f.new(type='ShaderNodeBsdfPrincipled')
    node_bsdf_f.location = (100, 0)
    node_bsdf_f.inputs['Roughness'].default_value = 0.5
    # Dark carbon-blackish base
    node_bsdf_f.inputs['Base Color'].default_value = (0.1, 0.12, 0.14, 1.0)
    links_f.new(node_bsdf_f.outputs['BSDF'], node_out_f.inputs['Surface'])

    # Procedural carbon weave pattern using Wave Textures
    # We create two perpendicular wave textures to simulate warp and weft
    node_coord = nodes_f.new(type='ShaderNodeTexCoord')
    node_coord.location = (-700, 100)

    node_mapping = nodes_f.new(type='ShaderNodeMapping')
    node_mapping.location = (-500, 100)
    node_mapping.inputs['Scale'].default_value[0] = 300.0
    node_mapping.inputs['Scale'].default_value[1] = 300.0
    links_f.new(node_coord.outputs['UV'], node_mapping.inputs['Vector'])

    node_wave_x = nodes_f.new(type='ShaderNodeTexWave')
    node_wave_x.location = (-300, 200)
    node_wave_x.wave_type = 'BANDS'
    node_wave_x.bands_direction = 'X'
    node_wave_x.inputs['Scale'].default_value = 1.0
    node_wave_x.inputs['Distortion'].default_value = 0.5
    links_f.new(node_mapping.outputs['Vector'], node_wave_x.inputs['Vector'])

    node_wave_y = nodes_f.new(type='ShaderNodeTexWave')
    node_wave_y.location = (-300, -50)
    node_wave_y.wave_type = 'BANDS'
    node_wave_y.bands_direction = 'Y'
    node_wave_y.inputs['Scale'].default_value = 1.0
    node_wave_y.inputs['Distortion'].default_value = 0.5
    links_f.new(node_mapping.outputs['Vector'], node_wave_y.inputs['Vector'])

    node_mix = nodes_f.new(type='ShaderNodeMixRGB')
    node_mix.location = (-100, 100)
    node_mix.blend_type = 'MIX'
    node_mix.inputs['Factor'].default_value = 0.5
    links_f.new(node_wave_x.outputs['Color'], node_mix.inputs['Color1'])
    links_f.new(node_wave_y.outputs['Color'], node_mix.inputs['Color2'])

    # Set Weave highlights
    node_color_mix = nodes_f.new(type='ShaderNodeValToRGB')
    node_color_mix.location = (100, 250)
    node_color_mix.color_ramp.elements[0].position = 0.4
    node_color_mix.color_ramp.elements[0].color = (0.05, 0.05, 0.06, 1.0) # Dark carbon
    node_color_mix.color_ramp.elements[1].position = 0.6
    node_color_mix.color_ramp.elements[1].color = (0.2, 0.22, 0.25, 1.0) # Lighter weave highlight
    links_f.new(node_mix.outputs['Color'], node_color_mix.inputs['Fac'])
    links_f.new(node_color_mix.outputs['Color'], node_bsdf_f.inputs['Base Color'])

    # Weave bump map
    node_bump_f = nodes_f.new(type='ShaderNodeBump')
    node_bump_f.location = (100, -150)
    node_bump_f.inputs['Strength'].default_value = 0.15
    node_bump_f.inputs['Distance'].default_value = 0.1
    links_f.new(node_mix.outputs['Color'], node_bump_f.inputs['Height'])
    links_f.new(node_bump_f.outputs['Normal'], node_bsdf_f.inputs['Normal'])

    # Make woven material slightly anisotropic/shiny in the specular
    node_bsdf_f.inputs['Roughness'].default_value = 0.4

    materials['fabric'] = mat_fabric

    # 3. Gold / Cooper Accents for tendons/conductors
    mat_copper = bpy.data.materials.new(name="Accents_Copper")
    mat_copper.use_nodes = True
    nodes_c = mat_copper.node_tree.nodes
    mat_copper.node_tree.links.new(nodes_c['Principled BSDF'].outputs['BSDF'], nodes_c['Material Output'].inputs['Surface'])
    nodes_c['Principled BSDF'].inputs['Metallic'].default_value = 1.0
    nodes_c['Principled BSDF'].inputs['Roughness'].default_value = 0.15
    nodes_c['Principled BSDF'].inputs['Base Color'].default_value = (0.8, 0.45, 0.25, 1.0) # copper
    materials['copper'] = mat_copper

    # 4. Hose Material (Dark Matte Ribbed Ribs)
    mat_hose = bpy.data.materials.new(name="Hose_Material")
    mat_hose.use_nodes = True
    nodes_h = mat_hose.node_tree.nodes
    mat_hose.node_tree.links.new(nodes_h['Principled BSDF'].outputs['BSDF'], nodes_h['Material Output'].inputs['Surface'])
    nodes_h['Principled BSDF'].inputs['Metallic'].default_value = 0.1
    nodes_h['Principled BSDF'].inputs['Roughness'].default_value = 0.4
    nodes_h['Principled BSDF'].inputs['Base Color'].default_value = (0.05, 0.05, 0.06, 1.0) # Dark rich rubber
    materials['hose'] = mat_hose

    # 5. Desk Material (Rich Walnut Wood)
    mat_desk = bpy.data.materials.new(name="Desk_Wood")
    mat_desk.use_nodes = True
    nodes_d = mat_desk.node_tree.nodes
    nodes_d.clear()

    d_out = nodes_d.new(type='ShaderNodeOutputMaterial')
    d_out.location = (400, 0)
    d_bsdf = nodes_d.new(type='ShaderNodeBsdfPrincipled')
    d_bsdf.location = (100, 0)
    nodes_d.new(type='ShaderNodeTexNoise') # just a quick organic base

    # Create simple procedural wood shader
    # Coordinates -> Mapping (squashed on z) -> Noise -> ColorRamp -> BaseColor, Roughness, Bump
    d_coord = nodes_d.new(type='ShaderNodeTexCoord')
    d_map = nodes_d.new(type='ShaderNodeMapping')
    d_map.inputs['Scale'].default_value[0] = 5.0
    d_map.inputs['Scale'].default_value[1] = 0.2 # stretched along Y
    d_map.inputs['Scale'].default_value[2] = 0.2

    d_noise = nodes_d.new(type='ShaderNodeTexNoise')
    d_noise.inputs['Scale'].default_value = 3.0
    d_noise.inputs['Detail'].default_value = 4.0
    d_noise.inputs['Distortion'].default_value = 1.5

    d_ramp = nodes_d.new(type='ShaderNodeValToRGB')
    d_ramp.color_ramp.elements[0].position = 0.0
    d_ramp.color_ramp.elements[0].color = (0.1, 0.05, 0.02, 1.0) # Dark walnut
    d_ramp.color_ramp.elements[1].position = 1.0
    d_ramp.color_ramp.elements[1].color = (0.28, 0.16, 0.09, 1.0) # Rich mid brown

    d_bump = nodes_d.new(type='ShaderNodeBump')
    d_bump.inputs['Strength'].default_value = 0.04

    mat_desk.node_tree.links.new(d_coord.outputs['Generated'], d_map.inputs['Vector'])
    mat_desk.node_tree.links.new(d_map.outputs['Vector'], d_noise.inputs['Vector'])
    mat_desk.node_tree.links.new(d_noise.outputs['Fac'], d_ramp.inputs['Fac'])
    mat_desk.node_tree.links.new(d_ramp.outputs['Color'], d_bsdf.inputs['Base Color'])
    mat_desk.node_tree.links.new(d_noise.outputs['Fac'], d_bump.inputs['Height'])
    mat_desk.node_tree.links.new(d_bump.outputs['Normal'], d_bsdf.inputs['Normal'])
    d_bsdf.inputs['Roughness'].default_value = 0.25

    mat_desk.node_tree.links.new(d_bsdf.outputs['BSDF'], d_out.inputs['Surface'])
    materials['desk'] = mat_desk

    # 6. Glowing Target Artifact
    mat_glow = bpy.data.materials.new(name="Artifact_Glow")
    mat_glow.use_nodes = True
    nodes_g = mat_glow.node_tree.nodes
    nodes_g.clear()
    g_out = nodes_g.new(type='ShaderNodeOutputMaterial')
    g_bsdf = nodes_g.new(type='ShaderNodeBsdfPrincipled')
    g_bsdf.inputs['Base Color'].default_value = (0.05, 0.4, 0.8, 1.0) # Cyber teal
    g_bsdf.inputs['Emission'].default_value = (0.02, 0.3, 0.6, 1.0)
    g_bsdf.inputs['Emission Strength'].default_value = 5.0
    mat_glow.node_tree.links.new(g_bsdf.outputs['BSDF'], g_out.inputs['Surface'])
    materials['glow'] = mat_glow

    return materials

materials = create_procedural_materials()
print("Materials successfully configured:", list(materials.keys()))

Set up procedural materials including metal, technical woven fabric, copper accents, hose material, desk wood, and glowing artifact shader.

{"code":"import bpy\n\ndef create_procedural_materials():\n    materials = {}\n    \n    # 1. Topology-Optimized Metals (Titanium)\n    mat_metal = bpy.data.materials.new(name=\"Optimized_Metal\")\n    mat_metal.use_nodes = True\n    nodes = mat_metal.node_tree.nodes\n    links = mat_metal.node_tree.links\n    \n    # Clean default nodes\n    for n in nodes:\n        nodes.remove(n)\n        \n    # Output node\n    node_out = nodes.new(type='ShaderNodeOutputMaterial')\n    node_out.location = (400, 0)\n    \n    # Principled BSDF\n    node_bsdf = nodes.new(type='ShaderNodeBsdfPrincipled')\n    node_bsdf.location = (100, 0)\n    node_bsdf.inputs['Metallic'].default_value = 1.0\n    node_bsdf.inputs['Roughness'].default_value = 0.35\n    # Warm titanium grey\n    node_bsdf.inputs['Base Color'].default_value = (0.4, 0.41, 0.43, 1.0)\n    links.new(node_bsdf.outputs['BSDF'], node_out.inputs['Surface'])\n    \n    # Add a bit of noise bump for 3D printed look\n    node_noise = nodes.new(type='ShaderNodeTexNoise')\n    node_noise.location = (-300, -100)\n    node_noise.inputs['Scale'].default_value = 400.0\n    node_noise.inputs['Detail'].default_value = 6.0\n    node_noise.inputs['Roughness'].default_value = 0.7\n    \n    node_bump = nodes.new(type='ShaderNodeBump')\n    node_bump.location = (-100, -100)\n    node_bump.inputs['Strength'].default_value = 0.05\n    node_bump.inputs['Distance'].default_value = 0.01\n    \n    links.new(node_noise.outputs['Fac'], node_bump.inputs['Height'])\n    links.new(node_bump.outputs['Normal'], node_bsdf.inputs['Normal'])\n    \n    materials['metal'] = mat_metal\n    \n    # 2. Technical Woven Fabric (Carbon Fiber / Ballistic Nylon)\n    # Let's do a stunning procedural weave in orange or high-viz tech yellow, or classic dark grey carbon fiber\n    mat_fabric = bpy.data.materials.new(name=\"Tech_Fabric\")\n    mat_fabric.use_nodes = True\n    nodes_f = mat_fabric.node_tree.nodes\n    links_f = mat_fabric.node_tree.links\n    \n    for n in nodes_f:\n        nodes_f.remove(n)\n        \n    node_out_f = nodes_f.new(type='ShaderNodeOutputMaterial')\n    node_out_f.location = (400, 0)\n    \n    node_bsdf_f = nodes_f.new(type='ShaderNodeBsdfPrincipled')\n    node_bsdf_f.location = (100, 0)\n    node_bsdf_f.inputs['Roughness'].default_value = 0.5\n    # Dark carbon-blackish base\n    node_bsdf_f.inputs['Base Color'].default_value = (0.1, 0.12, 0.14, 1.0)\n    links_f.new(node_bsdf_f.outputs['BSDF'], node_out_f.inputs['Surface'])\n    \n    # Procedural carbon weave pattern using Wave Textures\n    # We create two perpendicular wave textures to simulate warp and weft\n    node_coord = nodes_f.new(type='ShaderNodeTexCoord')\n    node_coord.location = (-700, 100)\n    \n    node_mapping = nodes_f.new(type='ShaderNodeMapping')\n    node_mapping.location = (-500, 100)\n    node_mapping.inputs['Scale'].default_value[0] = 300.0\n    node_mapping.inputs['Scale'].default_value[1] = 300.0\n    links_f.new(node_coord.outputs['UV'], node_mapping.inputs['Vector'])\n    \n    node_wave_x = nodes_f.new(type='ShaderNodeTexWave')\n    node_wave_x.location = (-300, 200)\n    node_wave_x.wave_type = 'BANDS'\n    node_wave_x.bands_direction = 'X'\n    node_wave_x.inputs['Scale'].default_value = 1.0\n    node_wave_x.inputs['Distortion'].default_value = 0.5\n    links_f.new(node_mapping.outputs['Vector'], node_wave_x.inputs['Vector'])\n    \n    node_wave_y = nodes_f.new(type='ShaderNodeTexWave')\n    node_wave_y.location = (-300, -50)\n    node_wave_y.wave_type = 'BANDS'\n    node_wave_y.bands_direction = 'Y'\n    node_wave_y.inputs['Scale'].default_value = 1.0\n    node_wave_y.inputs['Distortion'].default_value = 0.5\n    links_f.new(node_mapping.outputs['Vector'], node_wave_y.inputs['Vector'])\n    \n    node_mix = nodes_f.new(type='ShaderNodeMixRGB')\n    node_mix.location = (-100, 100)\n    node_mix.blend_type = 'MIX'\n    node_mix.inputs['Factor'].default_value = 0.5\n    links_f.new(node_wave_x.outputs['Color'], node_mix.inputs['Color1'])\n    links_f.new(node_wave_y.outputs['Color'], node_mix.inputs['Color2'])\n    \n    # Set Weave highlights\n    node_color_mix = nodes_f.new(type='ShaderNodeValToRGB')\n    node_color_mix.location = (100, 250)\n    node_color_mix.color_ramp.elements[0].position = 0.4\n    node_color_mix.color_ramp.elements[0].color = (0.05, 0.05, 0.06, 1.0) # Dark carbon\n    node_color_mix.color_ramp.elements[1].position = 0.6\n    node_color_mix.color_ramp.elements[1].color = (0.2, 0.22, 0.25, 1.0) # Lighter weave highlight\n    links_f.new(node_mix.outputs['Color'], node_color_mix.inputs['Fac'])\n    links_f.new(node_color_mix.outputs['Color'], node_bsdf_f.inputs['Base Color'])\n    \n    # Weave bump map\n    node_bump_f = nodes_f.new(type='ShaderNodeBump')\n    node_bump_f.location = (100, -150)\n    node_bump_f.inputs['Strength'].default_value = 0.15\n    node_bump_f.inputs['Distance'].default_value = 0.1\n    links_f.new(node_mix.outputs['Color'], node_bump_f.inputs['Height'])\n    links_f.new(node_bump_f.outputs['Normal'], node_bsdf_f.inputs['Normal'])\n    \n    # Make woven material slightly anisotropic/shiny in the specular\n    node_bsdf_f.inputs['Roughness'].default_value = 0.4\n    \n    materials['fabric'] = mat_fabric\n    \n    # 3. Gold / Cooper Accents for tendons/conductors\n    mat_copper = bpy.data.materials.new(name=\"Accents_Copper\")\n    mat_copper.use_nodes = True\n    nodes_c = mat_copper.node_tree.nodes\n    mat_copper.node_tree.links.new(nodes_c['Principled BSDF'].outputs['BSDF'], nodes_c['Material Output'].inputs['Surface'])\n    nodes_c['Principled BSDF'].inputs['Metallic'].default_value = 1.0\n    nodes_c['Principled BSDF'].inputs['Roughness'].default_value = 0.15\n    nodes_c['Principled BSDF'].inputs['Base Color'].default_value = (0.8, 0.45, 0.25, 1.0) # copper\n    materials['copper'] = mat_copper\n    \n    # 4. Hose Material (Dark Matte Ribbed Ribs)\n    mat_hose = bpy.data.materials.new(name=\"Hose_Material\")\n    mat_hose.use_nodes = True\n    nodes_h = mat_hose.node_tree.nodes\n    mat_hose.node_tree.links.new(nodes_h['Principled BSDF'].outputs['BSDF'], nodes_h['Material Output'].inputs['Surface'])\n    nodes_h['Principled BSDF'].inputs['Metallic'].default_value = 0.1\n    nodes_h['Principled BSDF'].inputs['Roughness'].default_value = 0.4\n    nodes_h['Principled BSDF'].inputs['Base Color'].default_value = (0.05, 0.05, 0.06, 1.0) # Dark rich rubber\n    materials['hose'] = mat_hose\n\n    # 5. Desk Material (Rich Walnut Wood)\n    mat_desk = bpy.data.materials.new(name=\"Desk_Wood\")\n    mat_desk.use_nodes = True\n    nodes_d = mat_desk.node_tree.nodes\n    nodes_d.clear()\n    \n    d_out = nodes_d.new(type='ShaderNodeOutputMaterial')\n    d_out.location = (400, 0)\n    d_bsdf = nodes_d.new(type='ShaderNodeBsdfPrincipled')\n    d_bsdf.location = (100, 0)\n    nodes_d.new(type='ShaderNodeTexNoise') # just a quick organic base\n    \n    # Create simple procedural wood shader\n    # Coordinates -> Mapping (squashed on z) -> Noise -> ColorRamp -> BaseColor, Roughness, Bump\n    d_coord = nodes_d.new(type='ShaderNodeTexCoord')\n    d_map = nodes_d.new(type='ShaderNodeMapping')\n    d_map.inputs['Scale'].default_value[0] = 5.0\n    d_map.inputs['Scale'].default_value[1] = 0.2 # stretched along Y\n    d_map.inputs['Scale'].default_value[2] = 0.2\n    \n    d_noise = nodes_d.new(type='ShaderNodeTexNoise')\n    d_noise.inputs['Scale'].default_value = 3.0\n    d_noise.inputs['Detail'].default_value = 4.0\n    d_noise.inputs['Distortion'].default_value = 1.5\n    \n    d_ramp = nodes_d.new(type='ShaderNodeValToRGB')\n    d_ramp.color_ramp.elements[0].position = 0.0\n    d_ramp.color_ramp.elements[0].color = (0.1, 0.05, 0.02, 1.0) # Dark walnut\n    d_ramp.color_ramp.elements[1].position = 1.0\n    d_ramp.color_ramp.elements[1].color = (0.28, 0.16, 0.09, 1.0) # Rich mid brown\n    \n    d_bump = nodes_d.new(type='ShaderNodeBump')\n    d_bump.inputs['Strength'].default_value = 0.04\n    \n    mat_desk.node_tree.links.new(d_coord.outputs['Generated'], d_map.inputs['Vector'])\n    mat_desk.node_tree.links.new(d_map.outputs['Vector'], d_noise.inputs['Vector'])\n    mat_desk.node_tree.links.new(d_noise.outputs['Fac'], d_ramp.inputs['Fac'])\n    mat_desk.node_tree.links.new(d_ramp.outputs['Color'], d_bsdf.inputs['Base Color'])\n    mat_desk.node_tree.links.new(d_noise.outputs['Fac'], d_bump.inputs['Height'])\n    mat_desk.node_tree.links.new(d_bump.outputs['Normal'], d_bsdf.inputs['Normal'])\n    d_bsdf.inputs['Roughness'].default_value = 0.25\n    \n    mat_desk.node_tree.links.new(d_bsdf.outputs['BSDF'], d_out.inputs['Surface'])\n    materials['desk'] = mat_desk\n\n    # 6. Glowing Target Artifact\n    mat_glow = bpy.data.materials.new(name=\"Artifact_Glow\")\n    mat_glow.use_nodes = True\n    nodes_g = mat_glow.node_tree.nodes\n    nodes_g.clear()\n    g_out = nodes_g.new(type='ShaderNodeOutputMaterial')\n    g_bsdf = nodes_g.new(type='ShaderNodeBsdfPrincipled')\n    g_bsdf.inputs['Base Color'].default_value = (0.05, 0.4, 0.8, 1.0) # Cyber teal\n    g_bsdf.inputs['Emission'].default_value = (0.02, 0.3, 0.6, 1.0)\n    g_bsdf.inputs['Emission Strength'].default_value = 5.0\n    mat_glow.node_tree.links.new(g_bsdf.outputs['BSDF'], g_out.inputs['Surface'])\n    materials['glow'] = mat_glow\n\n    return materials\n\nmaterials = create_procedural_materials()\nprint(\"Materials successfully configured:\", list(materials.keys()))\n","user_prompt":"Set up procedural materials including metal, technical woven fabric, copper accents, hose material, desk wood, and glowing artifact shader."}


import bpy

def create_procedural_materials():
    materials = {}

    # 1. Topology-Optimized Metals (Titanium)
    mat_metal = bpy.data.materials.new(name="Optimized_Metal")
    mat_metal.use_nodes = True
    nodes = mat_metal.node_tree.nodes
    links = mat_metal.node_tree.links

    # Clean default nodes
    for n in nodes:
        nodes.remove(n)

    # Output node
    node_out = nodes.new(type='ShaderNodeOutputMaterial')
    node_out.location = (400, 0)

    # Principled BSDF
    node_bsdf = nodes.new(type='ShaderNodeBsdfPrincipled')
    node_bsdf.location = (100, 0)
    node_bsdf.inputs['Metallic'].default_value = 1.0
    node_bsdf.inputs['Roughness'].default_value = 0.35
    # Warm titanium grey
    node_bsdf.inputs['Base Color'].default_value = (0.4, 0.41, 0.43, 1.0)
    links.new(node_bsdf.outputs['BSDF'], node_out.inputs['Surface'])

    # Add a bit of noise bump for 3D printed look
    node_noise = nodes.new(type='ShaderNodeTexNoise')
    node_noise.location = (-300, -100)
    node_noise.inputs['Scale'].default_value = 400.0
    node_noise.inputs['Detail'].default_value = 6.0
    node_noise.inputs['Roughness'].default_value = 0.7

    node_bump = nodes.new(type='ShaderNodeBump')
    node_bump.location = (-100, -100)
    node_bump.inputs['Strength'].default_value = 0.05
    node_bump.inputs['Distance'].default_value = 0.01

    links.new(node_noise.outputs['Fac'], node_bump.inputs['Height'])
    links.new(node_bump.outputs['Normal'], node_bsdf.inputs['Normal'])

    materials['metal'] = mat_metal

    # 2. Technical Woven Fabric (Carbon Fiber / Ballistic Nylon)
    # Let's do a stunning procedural weave in orange or high-viz tech yellow, or classic dark grey carbon fiber
    mat_fabric = bpy.data.materials.new(name="Tech_Fabric")
    mat_fabric.use_nodes = True
    nodes_f = mat_fabric.node_tree.nodes
    links_f = mat_fabric.node_tree.links

    for n in nodes_f:
        nodes_f.remove(n)

    node_out_f = nodes_f.new(type='ShaderNodeOutputMaterial')
    node_out_f.location = (400, 0)

    node_bsdf_f = nodes_f.new(type='ShaderNodeBsdfPrincipled')
    node_bsdf_f.location = (100, 0)
    node_bsdf_f.inputs['Roughness'].default_value = 0.5
    # Dark carbon-blackish base
    node_bsdf_f.inputs['Base Color'].default_value = (0.1, 0.12, 0.14, 1.0)
    links_f.new(node_bsdf_f.outputs['BSDF'], node_out_f.inputs['Surface'])

    # Procedural carbon weave pattern using Wave Textures
    # We create two perpendicular wave textures to simulate warp and weft
    node_coord = nodes_f.new(type='ShaderNodeTexCoord')
    node_coord.location = (-700, 100)

    node_mapping = nodes_f.new(type='ShaderNodeMapping')
    node_mapping.location = (-500, 100)
    node_mapping.inputs['Scale'].default_value[0] = 300.0
    node_mapping.inputs['Scale'].default_value[1] = 300.0
    links_f.new(node_coord.outputs['UV'], node_mapping.inputs['Vector'])

    node_wave_x = nodes_f.new(type='ShaderNodeTexWave')
    node_wave_x.location = (-300, 200)
    node_wave_x.wave_type = 'BANDS'
    node_wave_x.bands_direction = 'X'
    node_wave_x.inputs['Scale'].default_value = 1.0
    node_wave_x.inputs['Distortion'].default_value = 0.5
    links_f.new(node_mapping.outputs['Vector'], node_wave_x.inputs['Vector'])

    node_wave_y = nodes_f.new(type='ShaderNodeTexWave')
    node_wave_y.location = (-300, -50)
    node_wave_y.wave_type = 'BANDS'
    node_wave_y.bands_direction = 'Y'
    node_wave_y.inputs['Scale'].default_value = 1.0
    node_wave_y.inputs['Distortion'].default_value = 0.5
    links_f.new(node_mapping.outputs['Vector'], node_wave_y.inputs['Vector'])

    node_mix = nodes_f.new(type='ShaderNodeMixRGB')
    node_mix.location = (-100, 100)
    node_mix.blend_type = 'MIX'
    node_mix.inputs['Factor'].default_value = 0.5
    links_f.new(node_wave_x.outputs['Color'], node_mix.inputs['Color1'])
    links_f.new(node_wave_y.outputs['Color'], node_mix.inputs['Color2'])

    # Set Weave highlights
    node_color_mix = nodes_f.new(type='ShaderNodeValToRGB')
    node_color_mix.location = (100, 250)
    node_color_mix.color_ramp.elements[0].position = 0.4
    node_color_mix.color_ramp.elements[0].color = (0.05, 0.05, 0.06, 1.0) # Dark carbon
    node_color_mix.color_ramp.elements[1].position = 0.6
    node_color_mix.color_ramp.elements[1].color = (0.2, 0.22, 0.25, 1.0) # Lighter weave highlight
    links_f.new(node_mix.outputs['Color'], node_color_mix.inputs['Fac'])
    links_f.new(node_color_mix.outputs['Color'], node_bsdf_f.inputs['Base Color'])

    # Weave bump map
    node_bump_f = nodes_f.new(type='ShaderNodeBump')
    node_bump_f.location = (100, -150)
    node_bump_f.inputs['Strength'].default_value = 0.15
    node_bump_f.inputs['Distance'].default_value = 0.1
    links_f.new(node_mix.outputs['Color'], node_bump_f.inputs['Height'])
    links_f.new(node_bump_f.outputs['Normal'], node_bsdf_f.inputs['Normal'])

    # Make woven material slightly anisotropic/shiny in the specular
    node_bsdf_f.inputs['Roughness'].default_value = 0.4

    materials['fabric'] = mat_fabric

    # 3. Gold / Cooper Accents for tendons/conductors
    mat_copper = bpy.data.materials.new(name="Accents_Copper")
    mat_copper.use_nodes = True
    nodes_c = mat_copper.node_tree.nodes
    mat_copper.node_tree.links.new(nodes_c['Principled BSDF'].outputs['BSDF'], nodes_c['Material Output'].inputs['Surface'])
    nodes_c['Principled BSDF'].inputs['Metallic'].default_value = 1.0
    nodes_c['Principled BSDF'].inputs['Roughness'].default_value = 0.15
    nodes_c['Principled BSDF'].inputs['Base Color'].default_value = (0.8, 0.45, 0.25, 1.0) # copper
    materials['copper'] = mat_copper

    # 4. Hose Material (Dark Matte Ribbed Ribs)
    mat_hose = bpy.data.materials.new(name="Hose_Material")
    mat_hose.use_nodes = True
    nodes_h = mat_hose.node_tree.nodes
    mat_hose.node_tree.links.new(nodes_h['Principled BSDF'].outputs['BSDF'], nodes_h['Material Output'].inputs['Surface'])
    nodes_h['Principled BSDF'].inputs['Metallic'].default_value = 0.1
    nodes_h['Principled BSDF'].inputs['Roughness'].default_value = 0.4
    nodes_h['Principled BSDF'].inputs['Base Color'].default_value = (0.05, 0.05, 0.06, 1.0) # Dark rich rubber
    materials['hose'] = mat_hose

    # 5. Desk Material (Rich Walnut Wood)
    mat_desk = bpy.data.materials.new(name="Desk_Wood")
    mat_desk.use_nodes = True
    nodes_d = mat_desk.node_tree.nodes
    nodes_d.clear()

    d_out = nodes_d.new(type='ShaderNodeOutputMaterial')
    d_out.location = (400, 0)
    d_bsdf = nodes_d.new(type='ShaderNodeBsdfPrincipled')
    d_bsdf.location = (100, 0)
    nodes_d.new(type='ShaderNodeTexNoise') # just a quick organic base

    # Create simple procedural wood shader
    # Coordinates -> Mapping (squashed on z) -> Noise -> ColorRamp -> BaseColor, Roughness, Bump
    d_coord = nodes_d.new(type='ShaderNodeTexCoord')
    d_map = nodes_d.new(type='ShaderNodeMapping')
    d_map.inputs['Scale'].default_value[0] = 5.0
    d_map.inputs['Scale'].default_value[1] = 0.2 # stretched along Y
    d_map.inputs['Scale'].default_value[2] = 0.2

    d_noise = nodes_d.new(type='ShaderNodeTexNoise')
    d_noise.inputs['Scale'].default_value = 3.0
    d_noise.inputs['Detail'].default_value = 4.0
    d_noise.inputs['Distortion'].default_value = 1.5

    d_ramp = nodes_d.new(type='ShaderNodeValToRGB')
    d_ramp.color_ramp.elements[0].position = 0.0
    d_ramp.color_ramp.elements[0].color = (0.1, 0.05, 0.02, 1.0) # Dark walnut
    d_ramp.color_ramp.elements[1].position = 1.0
    d_ramp.color_ramp.elements[1].color = (0.28, 0.16, 0.09, 1.0) # Rich mid brown

    d_bump = nodes_d.new(type='ShaderNodeBump')
    d_bump.inputs['Strength'].default_value = 0.04

    mat_desk.node_tree.links.new(d_coord.outputs['Generated'], d_map.inputs['Vector'])
    mat_desk.node_tree.links.new(d_map.outputs['Vector'], d_noise.inputs['Vector'])
    mat_desk.node_tree.links.new(d_noise.outputs['Fac'], d_ramp.inputs['Fac'])
    mat_desk.node_tree.links.new(d_ramp.outputs['Color'], d_bsdf.inputs['Base Color'])
    mat_desk.node_tree.links.new(d_noise.outputs['Fac'], d_bump.inputs['Height'])
    mat_desk.node_tree.links.new(d_bump.outputs['Normal'], d_bsdf.inputs['Normal'])
    d_bsdf.inputs['Roughness'].default_value = 0.25

    mat_desk.node_tree.links.new(d_bsdf.outputs['BSDF'], d_out.inputs['Surface'])
    materials['desk'] = mat_desk

    # 6. Glowing Target Artifact
    mat_glow = bpy.data.materials.new(name="Artifact_Glow")
    mat_glow.use_nodes = True
    nodes_g = mat_glow.node_tree.nodes
    nodes_g.clear()
    g_out = nodes_g.new(type='ShaderNodeOutputMaterial')
    g_bsdf = nodes_g.new(type='ShaderNodeBsdfPrincipled')
    g_bsdf.inputs['Base Color'].default_value = (0.05, 0.4, 0.8, 1.0) # Cyber teal
    g_bsdf.inputs['Emission'].default_value = (0.02, 0.3, 0.6, 1.0)
    g_bsdf.inputs['Emission Strength'].default_value = 5.0
    mat_glow.node_tree.links.new(g_bsdf.outputs['BSDF'], g_out.inputs['Surface'])
    materials['glow'] = mat_glow

    return materials

materials = create_procedural_materials()
print("Materials successfully configured:", list(materials.keys()))

Set up procedural materials including metal, technical woven fabric, copper accents, hose material, desk wood, and glowing artifact shader.


Error executing code: Communication error with Blender: Code execution error: 'bpy_prop_collection[key]: key "Emission" not found'