Add sunrise Threads automation and improve capture and character interactions

This commit is contained in:
2026-11-02 03:28:58 +09:00
parent ff86bdb5b5
commit 850ac84ef7
34 changed files with 900 additions and 34 deletions
+18 -11
View File
@@ -1,5 +1,5 @@
"""Run with Blender MCP. Separate cartoon rain gear for the rounded v10 sheep."""
import bpy, bmesh, math, json, struct
import bpy, bmesh, math, json, struct, sys
from mathutils import Vector, Matrix
ROOT='D:/project/sunrise'
with bpy.data.libraries.load(ROOT+'/assets/characters/ivory-lamb-v10.blend',link=False) as (src,dst):
@@ -54,27 +54,34 @@ def sphere(name,location,scale,mat,parent):
umbrella=empty('Umbrella')
# The grip is in the raised right hoof; the tilted shaft centers the canopy above the head.
grip=Vector((.58,-.40,.82)); top=Vector((0,-.05,3.03))
grip=Vector((.58,-.40,.82)); top=Vector((0,-.05,3.18))
stroke('Umbrella shaft',[grip,top],.022,ink,umbrella)
def canopy_point(radius,sector,across):
# Taut fabric curves inward between the eight projecting rib tips.
scallop=math.sin(math.pi*across)
r=1.20*radius*(1-.10*scallop*radius**3)
a=(sector+across)*math.pi/4
return (r*math.cos(a),-.05+r*math.sin(a),3.18-.65*radius**1.4+.10*scallop*radius**3)
for sector in range(8):
vertices=[];faces=[]
for row in range(9):
theta=(math.pi/2)*row/8
for col in range(5):
a=(sector+col/4)*math.pi/4
vertices.append((1.28*math.sin(theta)*math.cos(a),-.05+1.28*math.sin(theta)*math.sin(a),2.53+.50*math.cos(theta)))
vertices.append(canopy_point(row/8,sector,col/4))
for row in range(8):
for col in range(4):
i=row*5+col;faces.append((i,i+1,i+6,i+5))
panel=mesh('Canopy panel',vertices,faces,red if sector%2==0 else cream,umbrella)
panel=mesh('Canopy panel',vertices,faces,red,umbrella)
bpy.context.view_layer.objects.active=panel
solid=panel.modifiers.new('Canopy thickness','SOLIDIFY');solid.thickness=.018
bpy.ops.object.modifier_apply(modifier=solid.name)
a=sector*math.pi/4
stroke('Canopy rib',[(1.28*math.sin(t)*math.cos(a),-.05+1.28*math.sin(t)*math.sin(a),2.54+.50*math.cos(t)) for t in [i*math.pi/32 for i in range(17)]],.009,ink,umbrella)
stroke('Canopy rim',[(1.28*math.cos(a),-.05+1.28*math.sin(a),2.53) for a in [i*math.tau/96 for i in range(97)]],.016,ink,umbrella)
sphere('Umbrella tip',(0,-.05,3.055),(.04,.04,.07),ink,umbrella)
stroke('Canopy rib',[canopy_point(i/16,sector,0) for i in range(17)],.009,ink,umbrella)
stroke('Canopy rim',[canopy_point(1,sector,i/12) for i in range(13)],.012,ink,umbrella)
sphere('Rib tip',canopy_point(1,sector,0),(.025,.025,.025),ink,umbrella)
stroke('Umbrella tip',[(0,-.05,3.17),(0,-.05,3.33)],.022,ink,umbrella)
sphere('Grip',grip,(.052,.052,.12),red,umbrella)
stroke('Hook handle',[grip,(grip.x,grip.y,grip.z-.16)]+[
(grip.x-.10+.10*math.cos(a),grip.y,grip.z-.16-.10*math.sin(a))
for a in [i*math.pi/16 for i in range(17)]],.033,red,umbrella)
coat=empty('Raincoat')
for joint_name in ('Body','ArmLeft','ArmRight'):
@@ -174,6 +181,6 @@ def export(root,path):
f.write(struct.pack('<III',0x46546C67,2,20+len(encoded)+len(binary)))
f.write(struct.pack('<II',len(encoded),0x4E4F534A));f.write(encoded);f.write(binary)
export(umbrella,ROOT+'/public/characters/umbrella.glb')
export(coat,ROOT+'/public/characters/raincoat.glb')
if '--umbrella-only' not in sys.argv:export(coat,ROOT+'/public/characters/raincoat.glb')
bpy.data.libraries.write(ROOT+'/assets/characters/rain-gear.blend',{scene})
print('Umbrella and articulated raincoat exported')