[AI Collaboration] Learning English through AI-Driven 3D Modeling: Crafting a Tabby Chonk

Learning English through AI-Driven 3D Modeling: Crafting a Tabby Chonk

The Story

Capturing the endearing essence of a "chonky" tabby cat in 3D requires a blend of procedural material generation and precise hierarchical placement. By analyzing the reference image, Gemini developed a Python script that constructs this character using a series of UV spheres and cylinders. This project serves as a practical medium to master English terms related to geometry manipulation and procedural shading in Blender.

Cat Reference

Reference Image

Cat 3D Model

3D Model Render


AI's Explanation

  1. Procedural Texturing: "To create the iconic tabby pattern, I utilized wave textures combined with mix nodes, allowing for dynamic color transitions across the cat's mesh."
  2. Geometry Instancing: "Components such as the legs and whiskers were generated using iterative loops, ensuring uniform placement and efficient scaling."
  3. Transform Application: "I applied transformations to the spheres and cylinders to maintain consistent proportions before final material assignment."

Key Words and Phrases

wave texture

A procedural shader node that produces repeating bands of color, essential for creating striped patterns like those on tabby cats.

Context: "I used wave textures to simulate the stripes."

iterative loop

A programming construct that repeats a set of instructions, used here to automate the creation of identical parts like legs.

Context: "Legs were generated via an iterative loop."

apply

The act of changing an object's location, rotation, or scale in 3D space.

Context: "I applied the final scale transformation."

Script Preview

Copy the code below into Blender's Text Editor to generate your own tabby chonk.

Python
import bpy
import math

def create_named_tabby_chonk_refined_eyes():
    # Clear existing objects
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete()

    # --- Materials ---
    def create_tabby_material():
        mat = bpy.data.materials.new(name="TabbyMaterial")
        mat.use_nodes = True
        nodes = mat.node_tree.nodes
        links = mat.node_tree.links
        for n in nodes: nodes.remove(n)
        
        output = nodes.new('ShaderNodeOutputMaterial')
        bsdf = nodes.new('ShaderNodeBsdfPrincipled')
        mix = nodes.new('ShaderNodeMixRGB')
        wave = nodes.new('ShaderNodeTexWave')
        coord = nodes.new('ShaderNodeTexCoord')
        mapping = nodes.new('ShaderNodeMapping')
        
        wave.wave_type = 'BANDS'
        wave.wave_profile = 'SIN'
        wave.inputs['Scale'].default_value = 2.0
        wave.inputs['Distortion'].default_value = 1.2
        
        mix.inputs['Color1'].default_value = (0.8, 0.3, 0.05, 1)
        mix.inputs['Color2'].default_value = (0.3, 0.1, 0.01, 1)
        
        mapping.inputs['Rotation'].default_value[2] = math.radians(90)
        
        links.new(coord.outputs['Object'], mapping.inputs['Vector'])
        links.new(mapping.outputs['Vector'], wave.inputs['Vector'])
        links.new(wave.outputs['Color'], mix.inputs['Fac'])
        links.new(mix.outputs['Color'], bsdf.inputs['Base Color'])
        links.new(bsdf.outputs['BSDF'], output.inputs['Surface'])
        return mat

    def create_simple_mat(name, color):
        mat = bpy.data.materials.new(name=name)
        mat.use_nodes = True
        mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
        return mat

    tabby_mat = create_tabby_material()
    white_mat = create_simple_mat("WhiteFur", (1, 1, 1, 1))
    eye_mat = create_simple_mat("EyeColor", (0.4, 0.8, 0.6, 1))
    pupil_mat = create_simple_mat("PupilColor", (0, 0, 0, 1))
    nose_mat = create_simple_mat("NosePink", (1.0, 0.5, 0.5, 1))

    def setup_obj(obj, name, material):
        obj.name = name
        if isinstance(material, list):
            for m in material: obj.data.materials.append(m)
        else:
            obj.data.materials.append(material)
        for poly in obj.data.polygons:
            poly.use_smooth = True

    # --- Body & Head ---
    bpy.ops.mesh.primitive_uv_sphere_add(radius=1, location=(0, 0, 1))
    torso = bpy.context.active_object
    torso.scale = (0.85, 1.4, 0.95)
    setup_obj(torso, "Torso", tabby_mat)

    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.55, location=(0, 1.4, 1.6))
    head = bpy.context.active_object
    setup_obj(head, "Head", tabby_mat)

    # --- Muzzle & Nose ---
    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.3, location=(0, 1.8, 1.45))
    muzzle = bpy.context.active_object
    muzzle.scale = (1.2, 0.8, 0.8)
    setup_obj(muzzle, "Muzzle", white_mat)

    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.05, location=(0, 2.05, 1.55))
    nose = bpy.context.active_object
    setup_obj(nose, "Nose", nose_mat)

    # --- Ears ---
    for i, side in enumerate([-1, 1]):
        bpy.ops.mesh.primitive_cone_add(radius1=0.25, depth=0.55, location=(0.35 * side, 1.3, 2.1))
        ear = bpy.context.active_object
        ear.scale = (0.9, 0.2, 1.3)
        ear.rotation_euler = (math.radians(-15), math.radians(5 * side), math.radians(25 * -side))
        setup_obj(ear, f"Ear_{'L' if side==-1 else 'R'}", tabby_mat)

    # --- Tail ---
    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.2, location=(0, -1.4, 1.8))
    tail = bpy.context.active_object
    tail.scale = (1, 1, 3.5)
    tail.rotation_euler = (math.radians(50), math.radians(5), 0)
    setup_obj(tail, "Tail", [tabby_mat, white_mat])
    for poly in tail.data.polygons:
        if poly.center.z > 0.5: poly.material_index = 1

    # --- Legs & Paws ---
    leg_pos = [(-0.4, 0.8, 0.5), (0.4, 0.8, 0.5), (-0.4, -0.8, 0.5), (0.4, -0.8, 0.5)]
    for i, loc in enumerate(leg_pos):
        bpy.ops.mesh.primitive_cylinder_add(radius=0.18, depth=0.8, location=loc)
        setup_obj(bpy.context.active_object, f"Leg_{i}", tabby_mat)
        bpy.ops.mesh.primitive_uv_sphere_add(radius=0.2, location=(loc[0], loc[1], 0.1))
        paw = bpy.context.active_object
        paw.scale = (1.1, 1.2, 0.6)
        setup_obj(paw, f"Paw_{i}", white_mat)

    # --- Eyes ---
    for side in [-1, 1]:
        bpy.ops.mesh.primitive_uv_sphere_add(radius=0.085, location=(0.28 * side, 1.8157, 1.75))
        eye = bpy.context.active_object
        eye.scale = (1.1, 0.5, 1.3)
        eye.rotation_euler = (math.radians(19.806), math.radians(-2.3051 * side), math.radians(-34.482 * side))
        setup_obj(eye, f"Eye_{'L' if side==-1 else 'R'}", eye_mat)
        
        bpy.ops.mesh.primitive_uv_sphere_add(radius=0.035, location=(0.28 * side, 1.8499, 1.75))
        pupil = bpy.context.active_object
        pupil.scale = (1.0, 1.0, 1.5)
        setup_obj(pupil, f"Pupil_{'L' if side==-1 else 'R'}", pupil_mat)

    # --- Whiskers ---
    for side in [-1, 1]:
        for j in range(3): 
            bpy.ops.mesh.primitive_cylinder_add(radius=0.004, depth=1.0, location=(0.28 * side, 1.88, 1.42 + (j * 0.05)))
            whisker = bpy.context.active_object
            whisker.rotation_euler = (math.radians(90), math.radians(15 * (j - 1)), math.radians(105 * side))
            setup_obj(whisker, f"Whisker_{'L' if side==-1 else 'R'}_{j}", white_mat)

if __name__ == "__main__":
    create_named_tabby_chonk_refined_eyes()

Comments

Popular posts from this blog

シャキシャキ美味しい!スナップエンドウ、英語でどう言う?

[AI & Seasonal English]: 半夏生編 -「半夏生」で日本の美しい暦と英語を学ぼう!

[AI & Seasonal English] 【スパイス香る】ドイツのクリスマスパン「シュトーレン(Stollen)」の歴史と「しっとり感」を語る英語