C

Cultiva Motion Studio — Script de Animacion Blender

animacion-blender-python · Generado por CULTIVA IA · Blender 3.6+ · Python bpy

PRODUCCION LISTA
cultiva_logo_anim.py — ejecutar con blender --background --python
"""
Cultiva Motion Studio — Logo Animation Script
Spot 3 segundos (90 frames @ 30fps) para redes sociales
Blender 3.6+ | Python bpy | Generado con skill animacion-blender-python
"""
import bpy, math

# ─── SETUP ESCENA ─────────────────────────────────────────────────────────────
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end   = 90
scene.render.fps   = 30

# ─── CREAR LOGO (cubo biselado como icono CULTIVA) ────────────────────────────
bpy.ops.mesh.primitive_cube_add(size=1.2, location=(0, 0, 0))
logo = bpy.context.active_object
logo.name = "CultivaLogo"

# Bevel para suavizar aristas del icono
bevel = logo.modifiers.new(name="Bevel", type='BEVEL')
bevel.width = 0.08
bevel.segments = 3

# ─── MATERIAL CULTIVA (#2D6A4F con emission animada) ─────────────────────────
mat = bpy.data.materials.new(name="CultivaGreen")
mat.use_nodes = True
nodes = mat.node_tree.nodes
bsdf  = nodes.get("Principled BSDF")
bsdf.inputs["Base Color"].default_value = (0.176, 0.416, 0.310, 1.0)  # #2D6A4F
bsdf.inputs["Roughness"].default_value   = 0.2
bsdf.inputs["Metallic"].default_value    = 0.7
logo.data.materials.append(mat)

# ─── FASE 1: SCALE-IN (frames 1–20) ─────────────────────────────────────────
# De (0,0,0) a (1,1,1) con ease-in BEZIER
logo.scale = (0.001, 0.001, 0.001)
logo.keyframe_insert(data_path="scale", frame=1)
logo.scale = (1.0, 1.0, 1.0)
logo.keyframe_insert(data_path="scale", frame=20)

# ─── FASE 2: BOUNCE OVERSHOOT (frames 20–35) ─────────────────────────────────
logo.scale = (1.18, 1.18, 1.18)  # overshoot 18%
logo.keyframe_insert(data_path="scale", frame=27)
logo.scale = (0.93, 0.93, 0.93)  # undershoot
logo.keyframe_insert(data_path="scale", frame=32)
logo.scale = (1.0, 1.0, 1.0)   # settle final
logo.keyframe_insert(data_path="scale", frame=37)

# ─── FASE 3: ROTACION 360° Y (frames 30–65) ──────────────────────────────────
logo.rotation_euler = (0, 0, 0)
logo.keyframe_insert(data_path="rotation_euler", frame=30)
logo.rotation_euler = (0, math.radians(360), 0)
logo.keyframe_insert(data_path="rotation_euler", frame=65)

# ─── FASE 4: PULSACION + NOISE ORGANICO (frames 60–90) ───────────────────────
action = logo.animation_data.action
scale_curves = [fc for fc in action.fcurves
                if fc.data_path == "scale"]

for fc in scale_curves:
    # Suavizar interpolacion de todos los keyframes
    for kp in fc.keyframe_points:
        kp.interpolation = 'BEZIER'
        kp.easing        = 'EASE_IN_OUT'
    # Noise organico para pulsacion en fase final
    noise = fc.modifiers.new(type='NOISE')
    noise.strength     = 0.04   # sutil, ±4% escala
    noise.scale        = 8.0    # frecuencia media
    noise.frame_start  = 60
    noise.frame_end    = 90

# ─── DRIVER: EMISSION basada en frame ────────────────────────────────────────
# Brillo va de 0 → max en fase scale-in, luego mantiene glow suave
drv = bsdf.inputs["Emission Strength"].driver_add("default_value").driver
drv.type       = 'SCRIPTED'
drv.expression = "min(frame/20.0, 1.0) * 0.8 + sin(frame*0.15)*0.2"

# ─── CAMARA Y LUZ ────────────────────────────────────────────────────────────
bpy.ops.object.camera_add(location=(0, -3.5, 1.5))
cam  = bpy.context.active_object
cam.rotation_euler = (math.radians(68), 0, 0)
scene.camera = cam

bpy.ops.object.light_add(type='AREA', location=(2, -1, 3))
key_light       = bpy.context.active_object
key_light.data.energy = 200
key_light.data.color  = (0.9, 1.0, 0.95)   # luz fria-verde

bpy.ops.object.light_add(type='POINT', location=(-1.5, 0.5, 0.5))
fill_light      = bpy.context.active_object
fill_light.data.energy = 40
fill_light.data.color  = (0.4, 0.8, 0.6)   # fill verde suave

# ─── RENDER CONFIG + EXPORT ──────────────────────────────────────────────────
scene.render.engine                   = 'CYCLES'
scene.render.resolution_x             = 1920
scene.render.resolution_y             = 1080
scene.cycles.samples                  = 128
scene.render.filepath                 = "/tmp/cultiva_logo_f45"
scene.frame_current                   = 45   # preview frame (mid-rotation)
bpy.ops.render.render(write_still=True)

bpy.ops.wm.save_as_mainfile(filepath="/tmp/cultiva_logo_anim.blend")
print("[OK] cultiva_logo_anim.blend guardado — frame preview en /tmp/cultiva_logo_f45.png")