"""Authored Phase 9 living wood: braided roots, bark lamellae, leaf veins, closed petal shells and fungal gills. No subdivision of the old models. Each rigid root has its own semantic animation joint; all geometry is editable. """ from math import sin, cos, pi import bpy from mathutils import Vector from common import ellipsoid, cylinder, mesh_object, srgb_to_linear from reference_geometry import r_lathe from reference_high_detail import hd_curve, hd_disc, hd_ring, hd_plate, hd_finish, hd_box, hd_rod, hd_materials def living_materials(m): colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), 'water':('65D6B5',.18,.65)} for key,(hexcolor,rough,emission) in colors.items(): name='SW_HD_W_'+key mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) mat.diffuse_color=(*c,1) node=mat.node_tree.nodes.get('Principled BSDF') node.inputs['Base Color'].default_value=(*c,1) node.inputs['Roughness'].default_value=rough if emission: node.inputs['Emission Color'].default_value=(*c,1) node.inputs['Emission Strength'].default_value=emission m[key]=mat return m def living_blob(name,loc,scale,mat): obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) if 'bark' in mat.name or 'moss' in mat.name: for v in obj.data.vertices: p=v.co p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) for face in obj.data.polygons:face.use_smooth=True return obj def living_leaf(name,start,end,width,m,key='leaf'): """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" a,b=Vector(start),Vector(end);d=b-a tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() if side.length<.1:side=Vector((1,0,0)) normal=side.cross(tangent).normalized() verts=[]; rows=9; sides=8 for j in range(rows): t=.005+.99*j/(rows-1) center=a+d*t+normal*(sin(t*pi)*width*.20) w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) for k in range(sides): angle=2*pi*k/sides verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) faces=[tuple(reversed(range(sides)))] for j in range(rows-1): for k in range(sides): n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) faces.append(tuple((rows-1)*sides+k for k in range(sides))) obj=mesh_object(name,verts,faces,m[key]) for face in obj.data.polygons:face.use_smooth=True points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) for j in range(3): t=.25+j*.20 center=a+d*t+normal*(sin(t*pi)*width*.39+.008) for sign in [-1,1]: tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) return obj def living_branch(name,points,radius,m,grooves=3): points=[Vector(p) for p in points] obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) for vertex in obj.data.vertices: p=vertex.co vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 for k in range(grooves): angle=2*pi*k/max(1,grooves) ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) def living_roots(m,count=4,spread=.43,height=.55,radius=.12): for k in range(count): a=2*pi*k/count+pi/4 group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') hip=Vector((.13*cos(a),.13*sin(a),height)) knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) foot=Vector((spread*cos(a),spread*sin(a),.12)) living_branch(group+'_Root',[hip,knee,foot],radius,m,5) for j in range(3): angle=a+(j-1)*.48 tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) def living_flower(name,loc,m,scale=1): center=Vector(loc) for k in range(5): angle=k*2*pi/5 p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) obj.rotation_euler.y=pi/2-angle living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) def living_trunk(m,height=.85,radius=.14,base=.35,count=4): for k in range(count): phase=2*pi*k/count points=[] for j in range(7): t=j/6;a=phase+t*pi*1.8 points.append((radius*cos(a),radius*sin(a),base+t*height)) living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) for k in range(8): a=k*2.4;z=base+.15+k*height*.08 start=(radius*cos(a),radius*sin(a),z) living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) def living_bark(name,loc,width,height,m,seed=0): outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) x,y,z=loc for j in range(4): dx=(j-1.5)*width*.19 hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) return obj def living_thorn(up,m): living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) if not up: living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) for k in range(6): a=k*pi/3 points=[] for j in range(6): t=j/5;radius=.18+.17*sin(t*pi) points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) living_branch('Body_WovenBark'+str(k),points,.037,m,2) for k in range(4): a=k*pi/2 living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) for k in range(9): a=k*2*pi/9 # Local bark plates turn as a whole, including their carved lines. before=set(bpy.context.scene.objects) living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) for o in set(bpy.context.scene.objects)-before: from mathutils import Matrix mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) for sign in [-1,1]: hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) living_flower('Body_Blossom',(-.24,-.20,1.11),m) else: living_trunk(m,.60,.23,.31,5) living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) for upper,z in [(True,1.13),(False,.72)]: name='Head_Upper' if upper else 'Head_Lower' living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) for row in range(3): hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) for k in range(9): a=pi+(k/8)*pi x=.35*cos(a);y=-.17+.34*sin(a) hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) for k in range(6): a=k*pi/3 living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) living_flower('Head_JawFlower',(-.32,-.20,1.26),m) def living_log(name,loc,r,m): hd_disc(name+'_Bark',loc,r,.15,m['bark']) x,y,z=loc cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) # Local UVs retain the centre of each log when parts are batched for Godot. uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') for loop in cut.data.loops: v=cut.data.vertices[loop.vertex_index].co uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) for j in range(6): radius=r*(.11+j*.127) verts=[];faces=[];segments=64;sides=6 for k in range(segments): a=k*2*pi/segments organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) for side in range(sides): b=side*2*pi/sides rr=radius*organic+.0019*cos(b) verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) for k in range(segments): for side in range(sides): a=k*sides+side;b=k*sides+(side+1)%sides c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side faces.append((a,b,c,d)) mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) for k in range(13): a=k*2*pi/13 hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) for k in range(3): a=k*2.7+r hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) def living_tank(up,m): living_roots(m,4,.44,.57,.14) living_trunk(m,.70,.20,.32,5) living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) if up: from mathutils import Matrix for row in range(3): for k in range(8): a=k*2*pi/8+row*.24 before=set(bpy.context.scene.objects) living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) rotation=Matrix.Rotation(a,4,'Z') for obj in set(bpy.context.scene.objects)-before: obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): living_log('Body_Log'+str(k),(x,y,z),r,m) else: for row in range(3): for k in range(7): a=k*2*pi/7+row*.45 from mathutils import Matrix before=set(bpy.context.scene.objects) living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) rotation=Matrix.Rotation(a,4,'Z') for obj in set(bpy.context.scene.objects)-before: obj.location=rotation@obj.location;obj.rotation_euler.z=a for k in range(11): a=k*2.4 z=1.22+(k%3)*.07 living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) for k in range(5): living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) def living_cup(name,loc,r,m,flower=False): x,y,z=loc material=m['petal'] if flower else m['moss'] obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) for p in obj.data.polygons:p.use_smooth=True hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) count=(12 if r > .2 else 5) if flower else 10 for k in range(count): a=k*2*pi/count hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) if flower: living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) def living_ranged(up,m): living_roots(m,4 if up else 2,.32,.48,.09) living_trunk(m,.77,.09,.32,4) living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) for k in range(7): a=k*2*pi/7 hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) for k in range(12 if up else 5): a=k*2*pi/(6 if up else 5) row=k//6 if up else 0 living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') for sign in [-1,1]: living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) def living_artillery(up,m): living_roots(m,4,.43,.56,.12) living_trunk(m,.92 if up else .65,.14,.32,4) positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] for k,(x,y,z,r) in enumerate(positions): living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) for j in range(5): a=j*2*pi/5 living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) for k in range(4 if up else 2): sign=-1 if k%2 else 1 living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) def living_support(up,m): living_roots(m,4 if up else 2,.39,.52,.105) if up: for sign in [-1,1]: for j in range(3): living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) for k in range(24): a=k*2.4;row=k//8 living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) else: living_trunk(m,.93,.09,.31,4) for k in range(5): a=k*2*pi/5 living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) r=.33 if up else .25; z=.79 living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) for k in range(3): hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) for sign,side in [(-1,'L'),(1,'R')]: living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) for k in range(6 if up else 3): a=k*2.4 living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) def build_high_wurzelbund(spec,m): living_materials(m) {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) def build_high_worker(spec,m): """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" hd_materials(m) for sign,side in [(-1,'L'),(1,'R')]: name='Leg'+side hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) for j in range(3): hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) for j in range(7): hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) for sign in [-1,1]: hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) for sign in [-1,1]: hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) for z in [.45,.79]: hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) for k in range(8): a=k*pi/4 hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) for sign,side in [(-1,'L'),(1,'R')]: a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) for j in range(3): hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) def build_high_core(spec,m): """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" hd_materials(m) team=int(spec.get('team',0)) crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True color=('65D9C1' if team==0 else 'EE9B82') c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 crystal.diffuse_color=(*c,1) for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) if team == 1: corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] for k in range(3): hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) else: hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) for k in range(12): a=k*pi/6 hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) for k in range(6): a=k*pi/3 hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) def shard(name,loc,r,height,tilt=0): vertices=[(0,0,-height*.45)] for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): for k in range(7): a=k*2*pi/7+.10*j vertices.append((radius*cos(a),radius*sin(a),z)) vertices.append((r*.16,0,height*.57));faces=[] for k in range(7):faces.append((0,1+(k+1)%7,1+k)) for j in range(2): for k in range(7): a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) for k in range(7):faces.append((15+k,15+(k+1)%7,22)) obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) hd_finish(obj,.006,2) shard('Core_CrystalMain',(0,0,1.41),.41,1.68) for k in range(5): a=k*2*pi/5 shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72)