=== WHAT'S BEEN DONE (Recent) === MCP Pipeline Factory: - 38 MCP servers tracked across 7 pipeline stages - 31 servers at Stage 16 (Website Built) — ready to deploy - All 30 production servers patched to 100/100 protocol compliance - Built complete testing infra: mcp-jest, mcp-validator, mcp-add, MCP Inspector - 702 auto-generated test cases ready for live API testing - Autonomous pipeline operator system w/ 7 Discord channels + cron jobs - Dashboard live at 192.168.0.25:8888 (drag-drop kanban) CloseBot MCP: - 119 tools, 4,656 lines TypeScript, compiles clean - 14 modules (8 tool groups + 6 UI apps) GHL MCP: - Stage 11 (Edge Case Testing) — 42 failing tests identified Sub-agent _meta Labels: - All 643 tools across 5 MCPs tagged (GHL, Google Ads, Meta Ads, Google Console, Twilio) OpenClaw Upwork Launch: - 15 graphics, 6 mockups, 2 PDFs, 90-sec Remotion video - 3-tier pricing: $2,499 / $7,499 / $24,999 - First $20k deal closed + $2k/mo retainer (hospice) Other: - Surya Blender animation scripts (7 tracks) - Clawdbot architecture deep dive doc - Pipeline state.json updates === TO-DO (Open Items) === BLOCKERS: - [ ] GHL MCP: Fix 42 failing edge case tests (Stage 11) - [ ] Expired Anthropic API key in localbosses-app .env.local - [ ] Testing strategy decision: structural vs live API vs hybrid NEEDS API KEYS (can't progress without): - [ ] Meta Ads MCP — needs META_ADS_API_KEY for Stage 8→9 - [ ] Twilio MCP — needs TWILIO_API_KEY for Stage 8→9 - [ ] CloseBot MCP — needs CLOSEBOT_API_KEY for live testing - [ ] 702 test cases across all servers need live API credentials PIPELINE ADVANCEMENT: - [ ] Stage 7→8: CloseBot + Google Console need design approval - [ ] Stage 6→7: 22 servers need UI apps built - [ ] Stage 5→6: 5 servers need core tools built (FreshBooks, Gusto, Jobber, Keap, Lightspeed) - [ ] Stage 1→5: 3 new MCPs need scaffolding (Compliance GRC, HR People Ops, Product Analytics) PENDING REVIEW: - [ ] Jake review OpenClaw video + gallery → finalize Upwork listing - [ ] LocalBosses UI redesign (Steve Jobs critique delivered, recs available) QUEUED PROJECTS: - [ ] SongSense AI music analysis product (architecture done, build not started) - [ ] 8-Week Agent Study Plan execution (curriculum posted, Week 1 not started)
181 lines
6.0 KiB
Python
181 lines
6.0 KiB
Python
"""
|
|
Track 08: IDK - Lorenz Attractor with Trailing Particle
|
|
"""
|
|
|
|
import bpy
|
|
import math
|
|
import sys
|
|
import os
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
from utils import *
|
|
|
|
|
|
def generate_lorenz_points(num_points=8000, scale=0.12):
|
|
"""Generate points along a Lorenz attractor."""
|
|
sigma, rho, beta = 10, 28, 8/3
|
|
dt = 0.005
|
|
|
|
x, y, z = 0.1, 0, 0
|
|
points = []
|
|
|
|
for _ in range(num_points):
|
|
dx = sigma * (y - x) * dt
|
|
dy = (x * (rho - z) - y) * dt
|
|
dz = (x * y - beta * z) * dt
|
|
|
|
x += dx
|
|
y += dy
|
|
z += dz
|
|
|
|
points.append((x * scale, y * scale, (z - 25) * scale))
|
|
|
|
return points
|
|
|
|
|
|
def create_idk_animation():
|
|
"""Create the full Track 08 animation."""
|
|
clear_scene()
|
|
setup_scene(background_color=(0.12, 0.04, 0.18, 1.0)) # Dark purple
|
|
|
|
# Create camera
|
|
camera = create_camera(location=(0, -12, 5), rotation=(1.15, 0, 0))
|
|
animate_camera_orbit(camera, center=(0, 0, 0), radius=12, height=5,
|
|
start_frame=1, end_frame=TOTAL_FRAMES, revolutions=0.5)
|
|
|
|
# Generate Lorenz attractor points
|
|
points = generate_lorenz_points(num_points=8000, scale=0.12)
|
|
|
|
# Create curve from points (sample every 4th point for performance)
|
|
sampled_points = points[::4]
|
|
|
|
curve_data = bpy.data.curves.new(name="LorenzCurve", type='CURVE')
|
|
curve_data.dimensions = '3D'
|
|
curve_data.bevel_depth = 0.015
|
|
curve_data.bevel_resolution = 4
|
|
|
|
spline = curve_data.splines.new('NURBS')
|
|
spline.points.add(len(sampled_points) - 1)
|
|
|
|
for i, point in enumerate(sampled_points):
|
|
spline.points[i].co = (point[0], point[1], point[2], 1)
|
|
|
|
spline.use_endpoint_u = True
|
|
spline.order_u = 4
|
|
|
|
attractor = bpy.data.objects.new("LorenzAttractor", curve_data)
|
|
bpy.context.collection.objects.link(attractor)
|
|
|
|
# Add material
|
|
mat = create_emission_material("LorenzMat", COLORS["idk"], strength=2.0)
|
|
attractor.data.materials.append(mat)
|
|
|
|
# Animate the curve drawing (using bevel factor)
|
|
curve_data.bevel_factor_start = 0.0
|
|
curve_data.bevel_factor_end = 0.0
|
|
curve_data.keyframe_insert(data_path="bevel_factor_end", frame=1)
|
|
|
|
curve_data.bevel_factor_end = 1.0
|
|
curve_data.keyframe_insert(data_path="bevel_factor_end", frame=450)
|
|
|
|
# Set linear interpolation for smooth drawing
|
|
if curve_data.animation_data:
|
|
for fc in curve_data.animation_data.action.fcurves:
|
|
for kf in fc.keyframe_points:
|
|
kf.interpolation = 'LINEAR'
|
|
|
|
# Create trailing particle
|
|
bpy.ops.mesh.primitive_ico_sphere_add(radius=0.15, subdivisions=2, location=points[0])
|
|
particle = bpy.context.active_object
|
|
particle.name = "TrailingParticle"
|
|
|
|
particle_mat = create_emission_material("ParticleMat", COLORS["white"], strength=5.0)
|
|
particle.data.materials.append(particle_mat)
|
|
|
|
# Animate particle along the last portion of the attractor
|
|
particle_start_frame = 460
|
|
particle_points = points[-200:]
|
|
frames_per_point = max(1, (TOTAL_FRAMES - particle_start_frame - 30) // len(particle_points))
|
|
|
|
# Hide particle initially
|
|
keyframe_scale(particle, 1, 0.01)
|
|
keyframe_scale(particle, particle_start_frame - 1, 0.01)
|
|
keyframe_scale(particle, particle_start_frame, 1.0)
|
|
|
|
for i, point in enumerate(particle_points):
|
|
frame = particle_start_frame + i * frames_per_point
|
|
if frame <= TOTAL_FRAMES - 30:
|
|
keyframe_location(particle, frame, point)
|
|
|
|
# Add some chaos visualization - secondary attractor trails
|
|
colors = [
|
|
(0.8, 0.35, 0.6, 1.0), # Lighter pink
|
|
(0.6, 0.25, 0.5, 1.0), # Darker pink
|
|
]
|
|
|
|
for idx, color in enumerate(colors):
|
|
# Generate with slightly different initial conditions
|
|
alt_points = []
|
|
x, y, z = 0.1 + idx * 0.01, 0.01 * idx, 0.01 * idx
|
|
sigma, rho, beta = 10, 28, 8/3
|
|
dt = 0.005
|
|
|
|
for _ in range(6000):
|
|
dx = sigma * (y - x) * dt
|
|
dy = (x * (rho - z) - y) * dt
|
|
dz = (x * y - beta * z) * dt
|
|
x += dx
|
|
y += dy
|
|
z += dz
|
|
alt_points.append((x * 0.12, y * 0.12, (z - 25) * 0.12))
|
|
|
|
# Create secondary curve
|
|
alt_sampled = alt_points[::6]
|
|
|
|
alt_curve_data = bpy.data.curves.new(name=f"LorenzAlt_{idx}", type='CURVE')
|
|
alt_curve_data.dimensions = '3D'
|
|
alt_curve_data.bevel_depth = 0.008
|
|
|
|
alt_spline = alt_curve_data.splines.new('NURBS')
|
|
alt_spline.points.add(len(alt_sampled) - 1)
|
|
|
|
for i, point in enumerate(alt_sampled):
|
|
alt_spline.points[i].co = (point[0], point[1], point[2], 1)
|
|
|
|
alt_spline.use_endpoint_u = True
|
|
|
|
alt_attractor = bpy.data.objects.new(f"LorenzAlt_{idx}", alt_curve_data)
|
|
bpy.context.collection.objects.link(alt_attractor)
|
|
|
|
alt_mat = create_emission_material(f"LorenzAltMat_{idx}", color, strength=1.0)
|
|
alt_attractor.data.materials.append(alt_mat)
|
|
|
|
# Animate drawing
|
|
alt_curve_data.bevel_factor_end = 0.0
|
|
alt_curve_data.keyframe_insert(data_path="bevel_factor_end", frame=1)
|
|
|
|
alt_curve_data.bevel_factor_end = 1.0
|
|
alt_curve_data.keyframe_insert(data_path="bevel_factor_end", frame=400 + idx * 30)
|
|
|
|
return attractor, particle
|
|
|
|
|
|
if __name__ == "__main__":
|
|
create_idk_animation()
|
|
|
|
output_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(output_dir, "exports", "track08_idk.blend"))
|
|
|
|
bpy.ops.export_scene.gltf(
|
|
filepath=os.path.join(output_dir, "exports", "track08_idk.gltf"),
|
|
export_animations=True,
|
|
export_format='GLTF_SEPARATE'
|
|
)
|
|
|
|
bpy.ops.wm.alembic_export(
|
|
filepath=os.path.join(output_dir, "exports", "track08_idk.abc"),
|
|
start=1, end=TOTAL_FRAMES
|
|
)
|
|
|
|
print("Track 08 - IDK: Export complete!")
|