CASE 06: ANIMATION LOOP
Create seamless looping animation: abstract, mechanical, character, or environmental
📁 Кейсы ⭐⭐ полная 8 блоков кода обновлено 2026-11-12
ID: CASE-06 | Type: Motion Design / Looping Animation | Difficulty: ⭐⭐ | Time: 1-3 hours
🎯 GOAL
Create seamless looping animation: abstract, mechanical, character, or environmental
📋 LOOP TYPES & PIPELINES
| Type | Frames | Key Technique | Use Case |
|---|---|---|---|
| Perfect Loop | 60-240 | Frame 1 = Frame N+1 | Instagram, UI, Web |
| Ping-Pong | 30-120 | Forward + Reverse | UI, Loading |
| Procedural | ∞ | Math (sin/cos/noise) | Shaders, Backgrounds |
| Physics Loop | 120-500 | Cache → Loop Point | Cloth, Fluid, Particles |
| Character Cycle | 24-48 | Walk/Run/Idle | Games, Cinematics |
🔧 MCP COMMANDS BY TYPE
TYPE A: PERFECT GEOMETRIC LOOP (Abstract)
# Concept: Rotating/Morphing geometry, perfect frame match
# Geometry Nodes Loop
"GN: Grid 10x10 → Extrude by Noise(Frame) → Scale by Sin(Frame)
Frame 1 = Frame 241 (240 frames @ 30fps = 8 сек)
Noise Seed = Frame → Детерминированный лоб"
# Shader Loop (Material)
"Principled BSDF:
Color = HSV(Hue=Frame/240, Sat=0.8, Val=1.0)
Emission = Sin(Frame/30) * 5.0
Displacement = Noise(UV + Frame/60) * 0.1"
TYPE B: MECHANICAL LOOP (Gears, Machines)
# Gear System
"Driver Setup:
Gear_A (Driver) → Rotation Z = Frame * 6° (60 RPM @ 30fps)
Gear_B (Driven) → Ratio -1:2 (Driver * -2)
Gear_C (Driven) → Ratio 1:3 (Driver * -3)
# Piston Animation
Crank (Driver) → Rotation Z = Frame * 12°
Connecting Rod → Copy Rotation + Limit Distance
Piston → Locked Track + Limit Location Z
# Loop: Frame 1 = Frame 361 (6 оборотов = 12 сек @ 30fps)"
TYPE C: CHARACTER WALK CYCLE
# Rigify Rig Setup
"Meta-Rig → Generate Rig
Walk Cycle (24 frames @ 24fps = 1 сек):
Frame 1: Contact R (Right heel, Left toe)
Frame 7: Down (Right foot flat, Left passing)
Frame 13: Contact L (Left heel, Right toe)
Frame 19: Down (Left foot flat, Right passing)
Frame 25: = Frame 1 (Loop)
# Graph Editor: All curves Bezier, Cyclic Extrapolation
# NLA: Walk Action → Push Down → Repeat"
TYPE D: PHYSICS LOOP (Cloth/Particles)
# Cloth Flag Loop
"Plane 2x1м, Subdivide 50x25
Cloth Physics: Vertex Group 'Pin' (левый край)
Wind: Force Field → Noise Texture(Frame) → Strength 5-10
Cache: 240 фреймов → Найти Loop Point (похожее состояние)
Trim: Start=45, End=285 (240 фреймов плавный лоб)"
# Particle Loop
"Emitter: Circle 1м, Particles 1000
Velocity: Normal 2м/с + Random 0.5
Force: Vortex (Z) + Noise(Frame)
Lifetime: 120 фреймов
Loop: Emitter Rate = Frame % 120 → Бесшовный поток"
TYPE E: SHADER/COMPOSITING LOOP (Post)
# Compositor Loop (Background)
"Render Layers → Glare(Frame%60) → Hue Rotate(Frame/120)
Output: 60 фреймов = 2 сек @ 30fps → Perfect Loop
# Background Plate для UI
"Resolution: 1920x1080, 60 фреймов
Export: WebM VP9 (loop) + GIF fallback"
🔧 UNIVERSAL LOOP SETUP (MCP)
FRAME RANGE & RENDER SETTINGS
import bpy
def setup_perfect_loop(total_frames=240, fps=30):
scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = total_frames
scene.render.fps = fps
scene.render.fps_base = 1
# Cyclic extrapolation для всех fcurves
for obj in bpy.data.objects:
if obj.animation_data and obj.animation_data.action:
for fcurve in obj.animation_data.action.fcurves:
fcurve.extrapolation = 'CYCLIC'
# NLA Tracks → Cyclic
for track in obj.animation_data.nla_tracks:
for strip in track.strips:
strip.repeat = total_frames // int(strip.action_frame_end)
strip.use_repeat = True
print(f"Loop setup: {total_frames} frames @ {fps}fps = {total_frames/fps:.1f}s")
setup_perfect_loop(240, 30)
RENDER OUTPUT FOR LOOP
def setup_loop_output(format='FFMPEG', codec='H264', filepath="//renders/loop_"):
scene = bpy.context.scene
scene.render.filepath = filepath
scene.render.image_settings.file_format = format
if format == 'FFMPEG':
scene.render.ffmpeg.format = 'MPEG4'
scene.render.ffmpeg.codec = codec
scene.render.ffmpeg.constant_rate_factor = 'PERC_LOSSLESS'
scene.render.ffmpeg.ffmpeg_preset = 'GOOD'
scene.render.ffmpeg.gopsize = scene.frame_end # Keyframe каждые N кадров
# Для WebM (прозрачность)
# scene.render.ffmpeg.format = 'WEBM'
# scene.render.ffmpeg.codec = 'VP9'
LOOP VALIDATION
def validate_loop(obj_name, tolerance=0.001):
"""Проверить что Frame 1 == Frame N+1"""
obj = bpy.data.objects.get(obj_name)
if not obj:
return False
scene = bpy.context.scene
start_frame = scene.frame_start
end_frame = scene.frame_end
# Сохранить текущий фрейм
current = scene.frame_current
scene.frame_set(start_frame)
loc1, rot1, scale1 = obj.location.copy(), obj.rotation_euler.copy(), obj.scale.copy()
scene.frame_set(end_frame)
loc2, rot2, scale2 = obj.location.copy(), obj.rotation_euler.copy(), obj.scale.copy()
scene.frame_set(current)
diff_loc = (loc1 - loc2).length
diff_rot = sum(abs(a - b) for a, b in zip(rot1, rot2))
diff_scale = (scale1 - scale2).length
is_loop = diff_loc < tolerance and diff_rot < tolerance and diff_scale < tolerance
print(f"Loop validation for {obj_name}: {'✅ PASS' if is_loop else '❌ FAIL'}")
print(f" Loc diff: {diff_loc:.6f}, Rot diff: {diff_rot:.6f}, Scale diff: {diff_scale:.6f}")
return is_loop
# Проверить все анимированные объекты
for obj in bpy.data.objects:
if obj.animation_data:
validate_loop(obj.name)
📊 LOOP SPECS BY PLATFORM
| Platform | Format | Duration | Resolution | Loop Type |
|---|---|---|---|---|
| Instagram Reels | MP4 H.264 | 3-15s | 1080x1920 | Perfect |
| TikTok | MP4 H.264 | 5-60s | 1080x1920 | Perfect |
| Web (Hero) | WebM VP9 | ∞ | 1920x1080 | Seamless |
| UI Loader | Lottie JSON | 1-3s | 200x200 | Ping-Pong |
| Game Engine | FBX/Alembic | 1-4s | Any | Cyclic |
| LED Wall | ProRes/EXR | 10-60s | 4K-8K | Perfect |
🔗 СВЯЗИ
- Прочие в категории «Кейсы»: CASE 04: CHARACTER RIG & ANIMATION, CASE 01: ARCHVIZ INTERIOR, CASE 02: GAME PROPS PIPELINE, CASE 03: PRODUCT VISUALIZATION, CASE 05: PROCEDURAL CITY
- По темам: CASE 07: STYLIZED BARREL (HAND-PAINT), CASE 08: SCI-FI CORRIDOR MODULAR, CASE 09: ANIME HEAD BUST
- Теги: #animation, #case
Связанные материалы
Подобраны по тегам и категории.