"""The convict's body, version 2: sculpted base bodies with shaped armour plates laid on them. Lore (GameLore.txt): both arms and both legs are machine limbs, the rest stays human, a feeding port in his side, he breathes from a tank in the water. body_torso the man: torso and neck in an insulated suit. Always worn. limb bases the machine limbs: synthetic muscle, built per stage (they get thicker), carrying the plates. plates shaped shells projected onto those bodies, so they follow the anatomy under them. All four stages share one skeleton. Limb frames: local X = lateral (hinge axis), Y = front, Z = toward the hand/foot. The left side is built; the right side is its mirror. """ from math import sin, cos, radians, pi from mathutils import Vector, Matrix from lib_geo import V, K, P, T, RX, RY, RZ, Prof, MeshProf, frame, shell, plate, organic, lin DARK, STEEL, RED, SUIT, RUB, VIS, GLOW, CER, GREY, MATTE, FIBER, CHROME = ('Dark', 'Steel', 'Red', 'Suit', 'Rubber', 'Visor', 'Glow', 'Ceramic', 'Grey', 'Matte', 'Fiber', 'Chrome') MATS = [SUIT, DARK, STEEL, RED, RUB, VIS, GLOW, CER, GREY, MATTE, FIBER, CHROME] STAGE_NAMES = {1: 'Issue', 2: 'Refit', 3: 'Deepframe', 4: 'Abyssal'} I4 = Matrix.Identity(4) ARM_G = {1: .98, 2: 1.10, 3: 1.18, 4: 1.40} # girth of the limb bodies per stage LEG_G = {1: .96, 2: 1.06, 3: 1.12, 4: 1.32} # ----------------------------------------------------------------------------------------------- skeleton def make_joints(): A = radians(40); J = {} SH = V((.205, 0, 1.435)); du = V((sin(A), 0, -cos(A))); h = V((cos(A), 0, sin(A))); fr = V((0, -1, 0)) LU, LF = .30, .27 EL = SH + LU * du; b = radians(10); df = (cos(b) * du + sin(b) * fr).normalized(); WR = EL + LF * df J.update(SH=SH, EL=EL, WR=WR, LU=LU, LF=LF, DU=du, DF=df, HX=h, FU=frame(SH, du, h), FF=frame(EL, df, h), FH=frame(WR, df, h)) fing = dict(index=(.0285, .094, 5, (.042, .026, .022)), middle=(.0085, .099, 0, (.046, .029, .023)), ring=(-.0115, .095, -5, (.042, .027, .022)), pinky=(-.0305, .086, -11, (.033, .021, .019))) curl = (8, 14, 10); F = {} for nme, (y, z, sp, lens) in fing.items(): M = J['FH'] @ T(0, y, z) @ RX(-sp) @ RY(-curl[0]); frs = [M] for k in (1, 2): M = M @ T(0, 0, lens[k - 1]) @ RY(-curl[k]); frs.append(M) F[nme] = (frs, lens) Mt = J['FH'] @ T(-.006, .034, .030) @ frame((0, 0, 0), (-.30, .62, .72), (.5, .6, -.3)); tl = (.040, .032, .027); frs = [Mt] for k in (1, 2): Mt = Mt @ T(0, 0, tl[k - 1]) @ RY(-10); frs.append(Mt) F['thumb'] = (frs, tl); J['F'] = F HIP = V((.095, 0, .935)); KNEE = V((.10, -.012, .505)); ANK = V((.10, .02, .085)) FFT = Matrix(((1, 0, 0, ANK.x), (0, 0, -1, ANK.y), (0, 1, 0, 0), (0, 0, 0, 1))) # X lateral, Y up, Z toe-ward J.update(HIP=HIP, KNEE=KNEE, ANK=ANK, LT=(KNEE - HIP).length, LC=(ANK - KNEE).length, DC=(ANK - KNEE).normalized(), FT=frame(HIP, KNEE - HIP, (1, 0, 0)), FC=frame(KNEE, ANK - KNEE, (1, 0, 0)), FFT=FFT, BALL=FFT @ V((0, .02, .145)), TOE=FFT @ V((0, .02, .228))) return J def bone_table(J): """(name, parent, head, tail), UE mannequin names. Left side listed, right mirrored.""" c = [('root', None, (0, 0, 0), (0, .12, 0)), ('pelvis', 'root', (0, 0, .975), (0, 0, 1.06)), ('spine_01', 'pelvis', (0, 0, 1.06), (0, 0, 1.165)), ('spine_02', 'spine_01', (0, 0, 1.165), (0, 0, 1.29)), ('spine_03', 'spine_02', (0, 0, 1.29), (0, 0, 1.50)), ('neck_01', 'spine_03', (0, 0, 1.50), (0, 0, 1.575)), ('head', 'neck_01', (0, 0, 1.575), (0, 0, 1.80))] s = [('clavicle', 'spine_03', V((.02, -.01, 1.455)), J['SH']), ('upperarm', 'clavicle', J['SH'], J['EL']), ('lowerarm', 'upperarm', J['EL'], J['WR']), ('hand', 'lowerarm', J['WR'], J['WR'] + .09 * J['DF'])] for nme, (frs, lens) in J['F'].items(): for k in range(3): tail = frs[k + 1].translation if k < 2 else frs[2] @ V((0, 0, lens[2])) s.append((f'{nme}_0{k + 1}', 'hand' if k == 0 else f'{nme}_0{k}', frs[k].translation, tail)) s += [('thigh', 'pelvis', J['HIP'], J['KNEE']), ('calf', 'thigh', J['KNEE'], J['ANK']), ('foot', 'calf', J['ANK'], J['BALL']), ('ball', 'foot', J['BALL'], J['TOE'])] side_names = {b[0] for b in s}; out = [(n, p, tuple(h), tuple(t)) for n, p, h, t in c] for sfx, m in (('_l', 1), ('_r', -1)): for n, p, h, t in s: out.append((n + sfx, p + sfx if p in side_names else p, (m * h[0], h[1], h[2]), (m * t[0], t[1], t[2]))) return out _BLEND = [('pelvis', 'spine_01', 1.00, 1.07), ('spine_01', 'spine_02', 1.10, 1.18), ('spine_02', 'spine_03', 1.21, 1.30), ('spine_03', 'neck_01', 1.485, 1.52), ('neck_01', 'head', 1.55, 1.58)] def spine_w(co): z = co.z; last = 'pelvis' for a, b, z0, z1 in _BLEND: if z < z0: return (a, a, 0.0) if z <= z1: t = (z - z0) / (z1 - z0); return (a, b, t * t * (3 - 2 * t)) last = b return (last, last, 0.0) def hinge_w(B, origin, axis, a, b, half=.04): """Weights for a limb body: bone a above the joint, bone b below, blended across the joint. Works for the mirrored side too.""" sfx = B.sfx; o = Vector(origin); ax = Vector(axis) def w(co): q = Vector((-co.x, co.y, co.z)) if sfx == '_r' else co t = min(max(((q - o).dot(ax) + half) / (2 * half), 0.0), 1.0) return (a + sfx, b + sfx, t * t * (3 - 2 * t)) return w # ----------------------------------------------------------------------------------------------- sculpted bodies def torso_volumes(B): """An athletic male torso as overlapping muscle volumes (x = his left, y = back, z = up).""" e = B.ell e((0, .012, 1.290), (.172, .110, .205)) # ribcage e((0, .004, 1.425), (.202, .080, .058)) # shoulder girdle e((0, .006, 1.110), (.120, .084, .175)) # abdomen e((0, -.060, 1.135), (.068, .028, .150)) # abdominal wall e((0, .008, .975), (.146, .098, .095)) # pelvis e((0, -.026, .894), (.064, .066, .056)) # groin B.cyl((0, .012, 1.44), (0, .0, 1.615), .060, seg=16) # neck for s in (1, -1): e((s * .084, -.072, 1.356), (.100, .030, .070), RZ(s * 6) @ RY(-s * 8)) # pectoral e((s * .142, .045, 1.275), (.048, .068, .150), RY(s * 8)) # lat e((s * .072, .034, 1.468), (.098, .056, .044), RY(s * 20)) # trapezius e((s * .088, .088, 1.375), (.078, .036, .088)) # shoulder blade e((s * .036, .090, 1.170), (.036, .030, .200)) # spinal erector e((s * .100, .0, 1.075), (.034, .072, .105)) # flank e((s * .074, .046, .944), (.074, .052, .080)) # glute e((s * .196, .0, 1.435), (.052, .058, .058)) # shoulder stump, where the arm is fitted def arm_volumes(B, J, g): LU, LF = J['LU'], J['LF']; e = B.ell; o = .03 * (g - 1) # heavier arms grow outward, not into the ribs with B.at(J['FU']): e((.012 + o, 0, .036), (.058 * g, .062 * g, .082)) # deltoid shell(B, Prof([K(.0, .044 * g, .048 * g, 2, o), K(.13, .050 * g, .056 * g, 2, o), K(.25, .043 * g, .046 * g, 2, o * .6), K(LU + .01, .041 * g, .043 * g, 2, o * .4)]), seg=16, dz=.03) e((-.002 + o, .024 * g, .150), (.036 * g, .034 * g, .092)) # biceps e((.006 + o, -.026 * g, .135), (.038 * g, .034 * g, .108)) # triceps with B.at(J['FF']): e((o * .4, 0, 0), (.041 * g, .044 * g, .042)) # elbow shell(B, Prof([K(-.012, .040 * g, .042 * g, 2, o * .4), K(.06, .048 * g, .052 * g, 2, o * .3), K(.15, .041 * g, .043 * g, 2, o * .2), K(.235, .031 * g, .034 * g), K(LF - .002, .029 * g, .032 * g)]), seg=16, dz=.03) e((.016 * g + o * .3, .010, .078), (.030 * g, .034 * g, .078)) # extensors e((-.014 * g + o * .3, .004, .088), (.030 * g, .034 * g, .088)) # flexors def leg_volumes(B, J, g): LT, LC = J['LT'], J['LC']; e = B.ell; o = .085 * (g - 1) # heavier legs grow outward, so the thighs never meet with B.at(J['FT']): shell(B, Prof([K(-.03, .072 * g, .084 * g, 2, o + .004), K(.06, .084 * g, .094 * g, 2, o + .004), K(.2, .078 * g, .087 * g, 2, o * .9 + .003), K(.34, .062 * g, .066 * g, 2, o * .7), K(LT + .01, .056 * g, .060 * g, 2, o * .6)]), seg=18, dz=.03) e((.004 + o, .040 * g, .19), (.050 * g, .046 * g, .175)) # rectus femoris e((.042 * g + o, .012, .22), (.040 * g, .050 * g, .165)) # vastus lateralis e((-.036 * g + o * .8, .028 * g, .335), (.036 * g, .036 * g, .078)) # vastus medialis e((o, -.045 * g, .2), (.058 * g, .046 * g, .175)) # hamstrings e((-.040 * g + o, -.005, .11), (.042 * g, .056 * g, .125)) # adductors e((.022 * g + o, -.02, .02), (.056 * g, .068 * g, .070)) # hip with B.at(J['FC']): e((o * .6, .012, 0), (.053 * g, .057 * g, .052)) # knee e((o * .6, .048 * g, -.004), (.030 * g, .020 * g, .036)) # kneecap shell(B, Prof([K(-.012, .054 * g, .058 * g, 2, o * .6), K(.09, .054 * g, .062 * g, 2, o * .5, -.008), K(.24, .042 * g, .046 * g, 2, o * .4), K(.35, .033 * g, .036 * g, 2, o * .3), K(LC - .01, .034 * g, .037 * g, 2, o * .3)]), seg=16, dz=.03) e((-.020 * g + o * .5, -.034 * g, .115), (.036 * g, .040 * g, .098)) # calf, inner head e((.022 * g + o * .5, -.030 * g, .105), (.033 * g, .038 * g, .092)) # calf, outer head e((.020 * g + o * .5, .022 * g, .15), (.022 * g, .022 * g, .125)) # shin muscle _CACHE = {} def body(kind, J, g=1.0): """Sculpted body of one kind ('torso', 'arm', 'leg') at girth g: (bvh, low mesh). Built once and reused for the mirror side.""" key = (kind, round(g, 3)) if key not in _CACHE: if kind == 'torso': _CACHE[key] = organic('torso', torso_volumes, voxel=.007, smooth=14, faces=2200) elif kind == 'arm': _CACHE[key] = organic(f'arm{g}', lambda B: arm_volumes(B, J, g), voxel=.005, smooth=12, faces=800) else: _CACHE[key] = organic(f'leg{g}', lambda B: leg_volumes(B, J, g), voxel=.006, smooth=12, faces=1000) return _CACHE[key] TF = T(0, .012, 0) # torso axis: straight up through the middle of the ribcage def amap(kind, J, g, which): """Radial map of a sculpted body around one of its bones (cached); plates are laid on it.""" key = (kind, round(g, 3), which) if key not in _CACHE: bvh = body(kind, J, g)[0]; oa = .03 * (g - 1); ol = .085 * (g - 1) if which == 'upper': _CACHE[key] = MeshProf(bvh, J['FU'], -.06, J['LU'] + .02, axis=(oa, 0)) elif which == 'fore': _CACHE[key] = MeshProf(bvh, J['FF'], -.04, J['LF'] - .004, axis=(oa * .3, 0)) elif which == 'thigh': _CACHE[key] = MeshProf(bvh, J['FT'], -.02, J['LT'] + .03, axis=(ol + .004, 0)) elif which == 'calf': _CACHE[key] = MeshProf(bvh, J['FC'], -.07, J['LC'] - .012, axis=(ol * .5, 0)) else: _CACHE[key] = MeshProf(bvh, TF, .875, 1.60, front=-90, pdir=1, nphi=160) return _CACHE[key] # ----------------------------------------------------------------------------------------------- style per stage # off = how far a plate stands off the body, thick > off so its back sinks into the body, cut/point shape the plate ends, # cap = how far the shoulder dome stands off the deltoid ST = {1: dict(body=DARK, plate=DARK, trim=STEEL, off=.004, thick=.010, rim=.003, cut=.012, point=.014, cap=.012, sharp=0.0), 2: dict(body=MATTE, plate=MATTE, trim=STEEL, off=.008, thick=.015, rim=.004, cut=.016, point=.008, cap=.030, sharp=0.0), 3: dict(body=GREY, plate=RED, trim=STEEL, off=.008, thick=.014, rim=.0035, cut=.024, point=.034, cap=.028, sharp=.004), 4: dict(body=DARK, plate=GREY, trim=STEEL, off=.022, thick=.030, rim=.006, cut=.030, point=.016, cap=.050, sharp=.005)} HAND = {1: dict(fw=.0130, ft=.0115, pt=.021, pw=.076), 2: dict(fw=.0158, ft=.0145, pt=.028, pw=.084), 3: dict(fw=.0166, ft=.0155, pt=.030, pw=.086), 4: dict(fw=.0190, ft=.0185, pt=.037, pw=.094)} FOOT = {1: (.044, .95), 2: (.050, 1.05), 3: (.053, 1.10), 4: (.068, 1.30)} def shape(point=0.0, cut=0.0, cw=.24): """One end of a plate as [(across 0..1, outward distance)]: cut clips both corners back, point pushes the middle out.""" return [(0, -cut), (cw, 0), (.5, point), (1 - cw, 0), (1, -cut)] def pl(B, prof, z0, z1, c, w0, w1, wm=None, skew=0.0, a=None, b=None, **kw): """Plate centred on angle c, w0 wide at z0 and w1 at z1 (wm in the middle). a / b = shape() of the z0 / z1 end.""" L = [(0, c - w0 / 2), (1, c - w1 / 2 + skew)]; R = [(0, c + w0 / 2), (1, c + w1 / 2 + skew)] if wm is not None: L.insert(1, (.5, c - wm / 2 + skew / 2)); R.insert(1, (.5, c + wm / 2 + skew / 2)) return plate(B, prof, z0, z1, L, R, [(u, -d) for u, d in a] if a else None, b, **kw) def joint_disc(B, p, axis, r, t, seg=16, name='joint_disc'): """Hinge cap: a stepped disc with a recessed hub, growing from p along axis by t.""" ax = Vector(axis); xh = Vector((0, 1, 0)) if abs(ax.normalized().y) < .9 else Vector((1, 0, 0)) with B.at(frame(p, ax, xh)): B.lathe([(0, 0), (0, r * .97), (t * .55, r), (t * .72, r * .93), (t * .72, r * .74), (t, r * .70), (t, r * .34), (t * .78, r * .30), (t * .78, 0)], seg, name) def button(B, prof, phi, z, r=.008, off=.004, glow=False, mat=CHROME): """Small fitting on a plate: a bright ring, optionally with a light in it.""" p = prof.pt(phi, z, off - .002); n = prof.nrm(phi, z); old = B.mat with B.at(frame(p, n, (0, 0, 1) if abs(n.z) < .9 else (1, 0, 0))): B.mat = mat; B.lathe([(0, 0), (0, r), (.004, r), (.0056, r * .86), (.0056, r * .62), (.003, r * .56), (.003, 0)], 10, 'button') if glow: B.mat = GLOW; B.lathe([(.0028, 0), (.0028, r * .5), (.0044, r * .44), (.0044, 0)], 8, 'button_light') B.mat = old def slots(a0, a1, z0, n, pitch=.02, w=.006, h=-.003, mat=RUB): return [P(a0, a1, z0 + i * pitch, z0 + i * pitch + w, h, mat) for i in range(n)] # ----------------------------------------------------------------------------------------------- arm def arm(B, st, J): s = B.sfx; ua, la = 'upperarm' + s, 'lowerarm' + s c = ST[st]; g = ARM_G[st]; LU, LF = J['LU'], J['LF']; o = .03 * (g - 1) off, tk, rim, pm = c['off'], c['thick'], c['rim'], c['plate']; kw = dict(thick=tk, off=off, rim=rim, sharp=c['sharp']) B.L = I4; B.mat = FIBER; B.wfn = hinge_w(B, J['EL'], J['DF'], 'upperarm', 'lowerarm') B.add_mesh(body('arm', J, g)[1], 'arm_base', J['FU']); B.wfn = None pu, pf = amap('arm', J, g, 'upper'), amap('arm', J, g, 'fore') B.L = J['FU']; B.bone = ua; B.mat = pm # shoulder dome: carried by the upper arm, covers its outer half only, so it clears the torso when the arm hangs R = .012 + .062 * g + c['cap']; q = {1: 2.0, 2: 2.0, 3: 2.5, 4: 3.0}[st]; cxp = o + .006 pd = Prof([K(-.056, R * .46, R * .5, q, cxp), K(-.034, R * .84, R * .88, q, cxp), K(.01, R, R * 1.04, q, cxp), K(.07, R * .97, R, q, cxp), K(.118, R * .88, R * .92, q, cxp)]) pp = [P(.14, .86, -.025, .09, .003)] if st == 2: pp.append(P(0, 1, .05, .066, 0, CER)) if st == 4: pp += [P(.26, .74, 0, .075, .005), P(.3, .7, .094, .1, 0, GLOW)] pl(B, pd, -.056, .118, 90, 204, 150, wm=204, b=shape(c['point'], c['cut']), panels=pp, seg=6, dz=.03, thick=tk, off=0, rim=rim, sharp=c['sharp'], name='pauldron') for a_, z_ in ((22, .0), (158, .0), (90, -.03)): button(B, pd, a_, z_, .007 if st < 4 else .010, .002) z0 = .132 if st == 3: # a second, lower tier under the dome pl(B, pu, .095, .178, 90, 168, 124, b=shape(.02, .018), panels=[P(.16, .84, .11, .165, .0025)], seg=5, dz=.03, thick=tk, off=off + .007, rim=rim, sharp=.004, name='pauldron_tier') z0 = .19 pl(B, pu, z0, LU - .05, 80, 196, 160, a=shape(0, c['cut']), b=shape(c['point'], c['cut']), panels=[P(.14, .86, z0 + .02, LU - .075, .0025), P(.495, .505, z0 + .03, LU - .085, -.002, RUB)], seg=6, dz=.035, name='upperarm_plate', **kw) pl(B, pu, .12, LU - .06, 232, 78, 58, a=shape(0, c['cut'] * .6), b=shape(c['point'] * .5, c['cut'] * .6), seg=3, dz=.04, name='triceps_plate', **kw) button(B, pu, 80, z0 + .035, .008, off + .004, glow=True) we = .042 * g + .003 for sg in (1, -1): B.mat = STEEL; joint_disc(B, (o * .4 + sg * we, 0, LU), (sg, 0, 0), .031 * g, .010 * g, name='elbow_disc') B.L = J['FF']; B.bone = la; B.mat = pm pv = [P(.16, .84, .07, LF - .07, .003)] if st == 3: pv += slots(.34, .66, .10, 4, .022, .006) if st == 4: pv += [P(.3, .7, .09, LF - .09, .005)] + slots(.38, .62, .11, 4, .024, .010, -.007) pl(B, pf, .044, LF - .034, 95, 236, 186, wm=240, a=shape(0, c['cut']), b=shape(c['point'], c['cut']), panels=pv, seg=7, dz=.035, name='vambrace', **kw) pl(B, pf, .06, LF - .06, -85, 104, 80, a=shape(0, c['cut'] * .7), b=shape(0, c['cut'] * .7), seg=3, dz=.04, name='forearm_plate', **kw) if st >= 3: pl(B, pf, -.036, .05, 180, 112, 92, a=shape(c['point'] * .4, c['cut'] * .6), b=shape(0, c['cut'] * .6), seg=3, dz=.03, thick=tk, off=off + .006, rim=rim, name='elbow_guard') button(B, pf, 95, .075, .010, off + .004, glow=True) for z_ in (.13, .17): button(B, pf, 40, z_, .0055, off + .003) B.mat = c['trim']; B.tube(LF - .032, LF - .008, .033 * g + .006, seg=16, ch=.003, name='wrist_cuff') if st == 4: B.mat = STEEL for sg in (1, -1): B.cyl((0, sg * (.052 * g + off), .07), (0, sg * (.036 * g + off), .2), .012, seg=8, ch=.002, name='gauntlet_piston') if st >= 2: B.L = I4; FU, FF = J['FU'], J['FF']; B.mat = RUB; rb = .058 * g B.hose([FU @ V((o - .016, -(rb + .006), .2)), FU @ V((o * .6 - .012, -(rb + .03), LU - .035)), FF @ V((o * .3 - .01, -(rb + .028), .035)), FF @ V((o * .3 - .008, -(.05 * g + .008), .1))], .010 if st == 4 else .007, seg=6, sub=4, bones=[ua, ua, la, la], rib=.12, name='elbow_hose') hand(B, st, J) def hand(B, st, J): s = B.sfx; hd = 'hand' + s; h = HAND[st]; c = ST[st]; fw, ft, pt, pw = h['fw'], h['ft'], h['pt'], h['pw'] B.L = J['FH']; B.bone = hd B.mat = STEEL; B.ball((0, 0, 0), pt * .62, seg=10, rings=6, name='wrist_ball') B.crease = .45 # the hand stays machined: its edges are held when the mesh is subdivided # the thumb side of the palm stops at y = .028 near the wrist, so wider palms never run into the thumb (its joint is the same in every stage) hw = (.029 + pw * .5) / 2; cyy = (.027 - pw * .5) / 2 pp = Prof([K(.010, pt * .42, hw * .72, 3.4, 0, cyy), K(.036, pt * .5, hw, 3.4, 0, cyy), K(.072, pt * .5, pw * .5, 3.4, 0, -.001), K(.088, pt * .44, pw * .5, 3.4, 0, -.001)]) pn = [P(-140, -40, .03, .08, .0015, RUB), P(40, 140, .022, .082, .003, c['plate'] if st >= 3 else None)] if st == 4: pn.append(P(62, 118, .034, .074, .003, GREY)) if st == 2: pn.append(P(60, 120, .058, .068, 0, CER)) B.mat = c['body']; shell(B, pp, pn, seg=16, dz=.02, eps=.0018, name='palm') if st == 1: B.mat = CHROME for nme in ('index', 'middle', 'ring', 'pinky'): kp = J['FH'].inverted() @ J['F'][nme][0][0].translation B.cyl((pt * .5 + .0028, kp.y * .45, .018), (pt * .5 + .0028, kp.y, kp.z - .012), .0022, seg=6, name='tendon') if st >= 3: B.mat = c['plate']; B.rbox((pt * .5 + .003, -.001, .089), (.008, pw * .92, .02), n=4, ch=.002, seg=8, name='knuckle_guard') button(B, pp, 90, .05, .0075, .003, glow=True, mat=c['trim']) for nme, (frs, lens) in J['F'].items(): thumb = nme == 'thumb' for k in range(3): B.L = frs[k]; B.bone = f'{nme}_0{k + 1}{s}' ln = lens[k]; w = fw * (1.12 if thumb else 1.0) * (1 - .06 * k); t = ft * (1.08 if thumb else 1.0) * (1 - .07 * k) B.crease = .6; B.mat = CHROME if st == 1 else STEEL; B.cyl((0, -w * .53, 0), (0, w * .53, 0), t * .56, seg=6, ch=.001, name='knuckle') gp = min(t * .64, ln * .3); z0 = gp; z1 = ln - gp if k < 2 else ln; e = min(.004, (z1 - z0) * .3) if k < 2: ks = [K(z0, t * .42, w * .44, 3.2), K(z0 + e, t * .5, w * .5, 3.2), K(z1 - e, t * .48, w * .48, 3.2), K(z1, t * .40, w * .42, 3.2)] else: ks = [K(z0, t * .42, w * .44, 3.2), K(z0 + e, t * .5, w * .5, 3.2), K(ln - .008, t * .46, w * .46, 3.0), K(ln - .002, t * .34, w * .36, 2.6), K(ln + .0015, t * .16, w * .2, 2.2)] pn = [] if k == 0: pn.append(P(38, 142, z0 + .005, z1 - .005, .002, c['plate'] if st >= 3 else None)) if k == 2: pn.append(P(-140, -40, ln * .3, ln * .86, .0012, RUB)) B.crease = .5; B.mat = c['body']; shell(B, Prof(ks, lin=True), pn, seg=8, dz=.03, eps=.0012, name='phalanx') B.crease = 0.0 # ----------------------------------------------------------------------------------------------- leg def leg(B, st, J): s = B.sfx; th, cf, ft = 'thigh' + s, 'calf' + s, 'foot' + s c = ST[st]; g = LEG_G[st]; LT, LC = J['LT'], J['LC']; o = .085 * (g - 1) off, tk, rim, pm = c['off'], c['thick'], c['rim'], c['plate']; kw = dict(thick=tk, off=off, rim=rim, sharp=c['sharp']) B.L = I4; B.mat = FIBER; B.wfn = hinge_w(B, J['KNEE'], J['DC'], 'thigh', 'calf', .045) B.add_mesh(body('leg', J, g)[1], 'leg_base', J['FT']); B.wfn = None pt, pc = amap('leg', J, g, 'thigh'), amap('leg', J, g, 'calf') B.L = J['FT']; B.bone = th if st in (2, 4): B.mat = STEEL; joint_disc(B, (o + .072 * g, -.02, .022), (1, 0, 0), .040 * g, .012, name='hip_disc') # the hip actuator shows on the heavier builds B.mat = pm pv = [P(.14, .86, .115, LT - .11, .003)] if st == 2: pv.append(P(0, 1, LT - .135, LT - .118, 0, CER)) if st == 3: pv += slots(.36, .64, .17, 4, .024, .007) if st == 4: pv += [P(.26, .74, .14, LT - .14, .006)] + slots(.36, .64, .17, 4, .026, .012, -.008) pl(B, pt, .088, LT - .084, 48, 190, 140, wm=200, a=shape(0, c['cut']), b=shape(c['point'], c['cut']), panels=pv, seg=7, dz=.04, name='thigh_plate', **kw) pl(B, pt, .11, LT - .09, 205, 104, 80, a=shape(0, c['cut'] * .7), b=shape(c['point'] * .5, c['cut'] * .7), seg=4, dz=.045, name='hamstring_plate', **kw) if st == 3: pl(B, pt, .10, .27, 48, 96, 70, a=shape(0, .02), b=shape(.03, .02), seg=4, dz=.04, thick=tk, off=off + .008, rim=rim, sharp=.004, name='thigh_tier') button(B, pt, 100, .13, .010, off + .004, glow=True) for z_ in (.2, .25): button(B, pt, 112, z_, .006, off + .003) wk = .055 * g + .003 for sg in (1, -1): B.mat = STEEL; joint_disc(B, (o * .6 + sg * wk, .008, LT), (sg, 0, 0), .036 * g, .011 * g, name='knee_disc') B.L = J['FC']; B.bone = cf; B.mat = pm pl(B, pc, -.05, .062, 0, 92, 78, a=shape(c['point'] * .5, c['cut'] * .6), b=shape(0, c['cut'] * .6), panels=[P(.2, .8, -.03, .045, .003)], seg=4, dz=.03, thick=tk + .003, off=off + .004, rim=rim, sharp=c['sharp'], name='knee_cap') pv = [P(.18, .82, .105, LC - .095, .003)] if st == 3: pv += slots(.38, .62, .15, 4, .024, .007) if st == 4: pv += [P(.3, .7, .13, LC - .12, .006)] + slots(.38, .62, .16, 4, .026, .012, -.008) pl(B, pc, .078, LC - .064, 0, 150, 106, a=shape(0, c['cut']), b=shape(c['point'], c['cut']), panels=pv, seg=6, dz=.04, name='shin_plate', **kw) pl(B, pc, .058, .30, 180, 170, 116, wm=172, a=shape(0, c['cut']), b=shape(c['point'], c['cut']), panels=[P(.2, .8, .08, .27, .0025)], seg=6, dz=.04, name='calf_plate', **kw) button(B, pc, 62, .11, .008, off + .004) fw, hs = FOOT[st]; up = hs - 1 # taller boots: the cuff sits higher so it clears the boot top B.mat = c['trim']; B.tube(LC - .066 - up * .02, LC - .04 - up * .025, .037 * g + .007, seg=16, ch=.003, name='ankle_cuff') B.bone = ft; B.mat = STEEL B.ball((0, 0, LC), .03 * hs, seg=12, rings=6, name='ankle_ball') foot(B, st, J) def foot(B, st, J): s = B.sfx; ft, bl = 'foot' + s, 'ball' + s; B.L = J['FFT']; c = ST[st] w, hs = FOOT[st]; so = .012 B.bone = ft; B.mat = c['body'] pb = Prof([K(-.08, w * .55, .022 * hs, 3.2, 0, .022 * hs + so), K(-.05, w * .9, .037 * hs, 3.2, 0, .037 * hs + so), K(0, w, .041 * hs, 3.2, 0, .041 * hs + so), K(.07, w * 1.06, .033 * hs, 3.2, 0, .033 * hs + so), K(.14, w * 1.06, .026 * hs, 3.2, 0, .026 * hs + so)]) shell(B, pb, [P(-62, 62, -.02, .125, .004, c['plate']), P(-28, 28, .0, .11, .003, c['plate'])], seg=16, dz=.035, name='boot') B.mat = RUB shell(B, Prof([K(-.084, w * .6, .009, 4, 0, .009), K(-.05, w * .95, .009, 4, 0, .009), K(.07, w * 1.1, .009, 4, 0, .009), K(.142, w * 1.1, .009, 4, 0, .009)]), seg=16, dz=.06, name='sole') B.mat = STEEL; B.cyl((-w * .95, so + .016, .1435), (w * .95, so + .016, .1435), .012 * hs, seg=8, ch=.002, name='toe_hinge_pin') with B.at(T(0, .085, 0)): for sg in (1, -1): B.mat = c['body']; B.rbox((sg * (w * .78), -.03, 0), (.012, .06, .044), seg=8, name='ankle_lug') B.mat = STEEL; joint_disc(B, (sg * (w * .78 - .002), 0, 0), (sg, 0, 0), .024 * hs, .011, seg=12, name='ankle_disc') if st == 4: B.mat = GREY; B.rbox((0, .05, -.092), (w * 1.5, .07, .03), n=4, seg=8, name='heel_spur') B.bone = bl; B.mat = c['body'] ptoe = Prof([K(.148, w * 1.05, .025 * hs, 3.2, 0, .025 * hs + so), K(.19, w * .98, .022 * hs, 3.2, 0, .022 * hs + so), K(.222, w * .8, .017 * hs, 3.0, 0, .017 * hs + so), K(.236, w * .5, .010 * hs, 2.6, 0, .010 * hs + so)]) shell(B, ptoe, [P(-70, 70, .16, .226, .004, c['plate'])], seg=16, dz=.03, name='toe') B.mat = RUB shell(B, Prof([K(.147, w * 1.1, .009, 4, 0, .009), K(.2, w * 1.0, .009, 4, 0, .009), K(.236, w * .6, .008, 3, 0, .008)]), seg=16, dz=.05, name='toe_sole') # ----------------------------------------------------------------------------------------------- torso def core(B, J): """The part of him that is still a man: torso and neck in an insulated suit. Always worn; every stage sits on it.""" B.L = I4; B.mat = SUIT; B.wfn = spine_w; B.add_mesh(body('torso', J)[1], 'torso_base', TF, uv_scale=.12); B.wfn = None tm = amap('torso', J, 1.0, 'torso'); B.L = TF p = tm.pt(-104, 1.09); n = tm.nrm(-104, 1.09); B.bone = 'spine_01' # the feeding port, in his right side with B.at(frame(p - n * .007, n, (0, 0, 1))): B.mat = CHROME; B.lathe([(0, 0), (0, .034), (.009, .034), (.012, .030), (.012, .023), (.005, .021), (.005, 0)], 18, 'feed_port_flange') B.mat = VIS; B.cyl((0, 0, .004), (0, 0, .0075), .0195, seg=12, name='feed_port_socket') B.mat = CHROME for k in range(4): a = pi / 4 + k * pi / 2; B.cyl((.011 * cos(a), .011 * sin(a), .007), (.011 * cos(a), .011 * sin(a), .0105), .0028, seg=6, name='feed_port_pin') B.mat = GLOW; B.cyl((0, .0285, .0085), (0, .0285, .0125), .0028, seg=6, name='feed_port_led') SH = J['SH'] for sg in (1, -1): # the fittings the machine arms are plugged into with B.side(sg): B.bone = 'clavicle' + B.sfx; B.mat = STEEL B.cyl((SH.x - .040, 0, SH.z), (SH.x - .014, 0, SH.z), .068, seg=18, ch=.004, name='shoulder_socket') def chest_light(B, tm, z, w, h, off=0.0, frame_mat=DARK): p = tm.pt(0, z, off); n = tm.nrm(0, z); B.bone = 'spine_03' with B.at(frame(p - n * .004, n, (1, 0, 0))): B.mat = frame_mat; B.rbox((0, 0, .006), (w + .016, h + .016, .012), n=6, ch=.003, name='light_housing') B.mat = GLOW; B.rbox((0, 0, .0125), (w, h, .004), n=8, ch=.001, name='light_lens') def torso_kit(B, st, J): c = ST[st]; tm = amap('torso', J, 1.0, 'torso'); off, tk, rim, pm = c['off'], c['thick'], c['rim'], c['plate'] kw = dict(thick=tk, off=off, rim=rim, sharp=c['sharp']); cut, point = c['cut'], c['point'] B.wfn = None; B.L = TF; B.bone = 'spine_03'; B.mat = pm if st == 3: # chest in two angular halves with a raised tier for sg in (1, -1): pv = [P(.16, .84, 1.318, 1.43, .003)] + slots(.34, .66, 1.345, 3, .022, .006) pl(B, tm, 1.292, 1.452, sg * 34, 60, 44, a=shape(0, cut), b=shape(0, cut * .6), panels=pv, seg=4, dz=.035, name='pec_plate', **kw) pl(B, tm, 1.305, 1.40, sg * 52, 26, 20, a=shape(.02, .012), seg=3, dz=.035, thick=tk, off=off + .008, rim=rim, sharp=.004, name='pec_tier') B.mat = c['trim']; pl(B, tm, 1.305, 1.448, 0, 6.5, 5.5, seg=2, dz=.04, thick=tk, off=off + .002, rim=.002, name='sternum') else: # one broad chest plate z0 = {1: 1.268, 2: 1.255, 4: 1.24}[st] pv = [P(.06, .44, z0 + .05, 1.43, {1: .003, 2: .005, 4: .010}[st], sym=True), P(.488, .512, z0 + .01, 1.45, -.003, RUB)] if st == 4: pv += [P(.13, .37, z0 + .075, 1.41, .006, sym=True)] pl(B, tm, z0, 1.455, 0, 130, 98, a=shape(.02 if st == 1 else .028, cut), b=shape(0, cut * .5), panels=pv, seg=8, dz=.035, name='chest_plate', **kw) for a_, z_ in ((-46, 1.425), (46, 1.425), (-52, z0 + .03), (52, z0 + .03)): button(B, tm, a_, z_, {1: .006, 2: .008, 4: .011}[st], off + .004) chest_light(B, tm, 1.372, {1: .04, 2: .04, 3: .028, 4: .052}[st], {1: .02, 2: .022, 3: .03, 4: .028}[st], off + (.004 if st == 3 else .002), frame_mat=c['trim'] if st == 3 else pm) B.mat = pm r0 = 1.205 if st == 3 else 1.165 # the broad chest plates reach lower, so the ribs sit lower under them rc, rw0, rw1 = (54, 42, 48) if st == 4 else (62, 52, 60) # stage 4 plates are thick: kept off the flanks so the hanging arms clear them for sg in (1, -1): # ribs and flanks; each plate rides one vertebra so the waist can bend B.bone = 'spine_02' pl(B, tm, r0, r0 + .078, sg * rc, rw0, rw1, a=shape(0, cut * .6), b=shape(0, cut * .6), skew=sg * 4, seg=3, dz=.04, name='rib_plate', **kw) if st >= 3: pl(B, tm, r0 - .087, r0 - .013, sg * (rc - 4), rw0 - 6, rw1 - 8, a=shape(0, cut * .6), b=shape(0, cut * .6), skew=sg * 4, seg=3, dz=.04, name='rib_plate', **kw) for i, bn in enumerate(('spine_01', 'spine_01', 'spine_02')): # abdomen in three bands B.bone = bn pl(B, tm, 1.062 + .05 * i, 1.104 + .05 * i, 0, 54 + 4 * i, 56 + 4 * i, a=shape(0, .008, .2), b=shape(0, .008, .2), panels=[P(.485, .515, None, None, -.003, RUB)], seg=6, dz=.05, name='ab_plate', **kw) B.bone = 'spine_03' # back pl(B, tm, 1.262, 1.455, 180, 132, 100, a=shape(point, cut), b=shape(0, cut * .5), panels=[P(.12, .88, 1.29, 1.43, .003), P(.485, .515, 1.27, 1.45, -.003, RUB)], seg=8, dz=.035, name='back_plate', **kw) B.bone = 'spine_02'; pl(B, tm, 1.115, 1.215, 180, 84, 104, a=shape(0, cut * .6), b=shape(0, cut * .6), seg=5, dz=.04, name='loin_plate', **kw) B.bone = 'pelvis' # belt and groin B.mat = c['trim']; pl(B, tm, .985, 1.035, 0, 40, 40, a=shape(.008, .006), b=shape(.004, .006), seg=3, dz=.03, thick=tk, off=off + .002, rim=.0025, name='buckle') B.mat = pm for sg in (1, -1): pl(B, tm, .978, 1.04, sg * 70, 92, 92, a=shape(0, .008), b=shape(0, .008), seg=5, dz=.03, name='belt_plate', **kw) pl(B, tm, .978, 1.04, 180, 108, 108, a=shape(0, .008), b=shape(0, .008), seg=5, dz=.03, name='belt_plate', **kw) pl(B, tm, .882, .972, 0, 38, 56, a=shape(.014, .008), seg=3, dz=.03, name='groin_plate', **kw) pl(B, tm, .895, .972, 180, 96, 112, a=shape(.012, .01), panels=[P(.488, .512, None, None, -.003, RUB)], seg=6, dz=.03, name='seat_plate', **kw) B.bone = 'spine_03'; B.mat = c['trim'] # collar with B.at(T(0, -.006, 1.492)): r = .084 if st < 4 else .096 B.lathe([(0, 0), (0, r), (.012, r * 1.04), (.036, r * .92), (.042, r * .84), (.042, 0)], 20, 'collar') {1: _kit1, 2: _kit2, 3: _kit3, 4: _kit4}[st](B, J, tm, c) def _tank(B, x, y, z, r, ln, mat=STEEL, seg=14): with B.at(T(x, y, z)): B.mat = mat; B.lathe([(0, 0), (.006, r * .5), (.022, r * .86), (.05, r), (ln - .05, r), (ln - .024, r * .86), (ln - .008, r * .56), (ln, r * .32), (ln, 0)], seg, 'air_tank') def _kit1(B, J, tm, c): """Stage 1: one air tank on a back frame, regulator hose to the helmet, thin cables down the flanks.""" B.L = I4; B.bone = 'spine_03'; B.mat = DARK; B.rbox((0, .150, 1.285), (.16, .022, .25), n=5, seg=8, name='tank_frame') _tank(B, 0, .208, 1.10, .054, .34) B.mat = DARK with B.at(T(0, .208, 1.10)): for z in (.08, .235): B.tube(z, z + .02, .057, seg=14, ch=.003, name='tank_band') B.mat = RED; B.tube(.338, .356, .021, seg=10, ch=.003, name='tank_valve'); B.cyl((0, 0, .348), (-.04, 0, .348), .008, seg=8, ch=.002, name='tank_knob') B.mat = RUB B.hose([V((-.02, .208, 1.455)), V((-.085, .18, 1.515)), V((-.135, .06, 1.55)), V((-.118, -.035, 1.585)), V((-.068, -.086, 1.606))], .0105, seg=8, sub=5, rib=.12, bones=['spine_03', 'spine_03', 'spine_03', 'head', 'head'], name='regulator_hose') B.L = TF for sg in (1, -1): B.mat = RUB B.hose([tm.pt(sg * 58, 1.24, .012), tm.pt(sg * 76, 1.15, .028), tm.pt(sg * 84, 1.06, .03), tm.pt(sg * 78, 1.0, .016)], .0032, seg=6, sub=5, bones=['spine_03', 'spine_02', 'spine_01', 'pelvis'], name='side_cable') def _kit2(B, J, tm, c): """Stage 2: twin tanks in a pack, air hoses to the ear caps, neck cables, hip pouches.""" B.L = I4; B.bone = 'spine_03'; B.mat = MATTE; B.rbox((0, .168, 1.30), (.21, .07, .29), n=5, ch=.006, seg=8, name='pack') for sg in (1, -1): _tank(B, sg * .066, .222, 1.14, .045, .31) B.mat = RUB B.hose([V((sg * .06, .19, 1.455)), V((sg * .112, .14, 1.545)), V((sg * .114, .05, 1.628)), V((sg * .104, .012, 1.674))], .0115, seg=8, sub=5, rib=.12, bones=['spine_03', 'spine_03', 'head', 'head'], name='air_hose') for k in range(3): B.hose([V((sg * (.05 + .016 * k), .09, 1.505)), V((sg * (.062 + .018 * k), .118 - .01 * k, 1.565)), V((sg * (.05 + .02 * k), .092 - .012 * k, 1.63))], .0065, seg=6, sub=4, bones=['spine_03', 'spine_03', 'head'], name='neck_cable') B.L = TF; B.bone = 'pelvis'; B.mat = MATTE for sg in (1, -1): B.rbox(tm.pt(sg * 48, 1.0, .028), (.06, .036, .07), n=5, seg=8, rot=RZ(sg * 48), name='hip_pouch') def _kit3(B, J, tm, c): """Stage 3: a raised guard behind the neck, a vented pack, plates over the hips.""" B.L = TF; B.bone = 'spine_03'; B.mat = RED pl(B, Prof([K(1.49, .108, .1), K(1.575, .114, .108)], front=-90, pdir=1, lin=True), 1.49, 1.575, 180, 150, 116, b=shape(.012, .014), panels=[P(.14, .86, 1.505, 1.56, .003)], seg=6, dz=.03, thick=.009, off=0, rim=.003, sharp=.004, name='neck_guard') B.L = I4; B.mat = GREY; B.rbox((0, .172, 1.30), (.22, .08, .31), n=5, ch=.006, seg=8, t1=(.8, 1), name='pack') B.mat = RED; B.rbox((0, .216, 1.32), (.13, .014, .2), n=5, ch=.003, seg=8, name='pack_cover') B.mat = RUB for i in range(4): B.rbox((0, .224, 1.26 + i * .04), (.09, .006, .012), n=4, ch=.001, seg=8, name='pack_vent') for sg in (1, -1): _tank(B, sg * .092, .218, 1.17, .028, .21, seg=12) B.mat = RUB B.hose([V((sg * .07, .19, 1.46)), V((sg * .128, .15, 1.565)), V((sg * .118, .06, 1.64)), V((sg * .104, .012, 1.678))], .011, seg=8, sub=5, rib=.12, bones=['spine_03', 'spine_03', 'head', 'head'], name='air_hose') B.L = TF; B.bone = 'pelvis'; B.mat = RED ph = Prof([K(.90, .234, .15, 2.6), K(.99, .226, .15, 2.6)], front=-90, pdir=1, lin=True) for sg in (1, -1): pl(B, ph, .90, .99, sg * 90, 74, 86, a=shape(.018, .014), panels=[P(.16, .84, .915, .975, .003)], seg=4, dz=.03, thick=.009, off=0, rim=.003, sharp=.004, name='tasset') def _kit4(B, J, tm, c): """Stage 4: gorget, yoke blocks, power pack, hip blocks.""" B.L = I4; B.bone = 'spine_03' with B.at(T(0, 0, 1.462)): B.mat = GREY; B.lathe([(0, 0), (0, .118), (.03, .134), (.108, .130), (.118, .122), (.118, .104), (.065, .100), (.065, 0)], 24, 'gorget') for sg in (1, -1): B.mat = GREY; B.rbox((sg * .112, .008, 1.51), (.07, .15, .05), n=5, ch=.006, seg=8, rot=RY(sg * 18), name='yoke_block') B.mat = RUB for i in range(3): B.rbox((sg * .112, -.04 + i * .04, 1.5355), (.045, .012, .006), n=4, ch=.001, seg=8, rot=RY(sg * 18), name='yoke_vent') B.mat = DARK; B.rbox((0, .225, 1.29), (.30, .13, .40), n=5, ch=.01, seg=8, t1=(.86, .9), name='power_pack') B.mat = GREY; B.rbox((0, .295, 1.32), (.16, .016, .24), n=5, ch=.004, seg=8, name='pack_cover') for sg in (1, -1): _tank(B, sg * .1, .31, 1.09, .052, .35) B.mat = GREY; B.rbox((sg * .1, .24, 1.525), (.085, .1, .06), n=5, ch=.006, seg=8, name='intake_box') B.mat = RUB; B.hose([V((sg * .1, .196, 1.525)), V((sg * .095, .166, 1.53)), V((sg * .078, .132, 1.52))], .014, seg=8, sub=4, rib=.12, name='collar_hose') B.L = TF; B.bone = 'pelvis' for sg in (1, -1): B.mat = GREY; B.rbox(tm.pt(sg * 88, 1.035, .034), (.05, .11, .075), n=5, ch=.006, seg=8, name='hip_block') # ----------------------------------------------------------------------------------------------- head HM = Matrix(((0, 0, 1, 0), (-1, 0, 0, -.012), (0, -1, 0, 1.692), (0, 0, 0, 1))) # helmet frame: X front, Y down, Z his left def helmet_prof(W, rx, ry, n, p=2.3): ts = [-1, -.985, -.94, -.85, -.7, -.5, -.25, 0, .25, .5, .7, .85, .94, .985, 1] sc = lambda t: (1 - abs(t) ** p) ** (1 / p) if abs(t) < 1 else 0.0 return Prof([K(t * W, max(rx * sc(t), 1e-5), max(ry * sc(t), 1e-5), n) for t in ts], front=0, pdir=-1) def ear_caps(B, W, r, t): for sg in (1, -1): joint_disc(B, (-.005, .012, sg * (W - .012)), (0, 0, sg), r, t, name='ear_cap') def filters(B, hp, phi, z, r, t): """Breather cans low on the cheeks.""" for sg in (1, -1): joint_disc(B, hp.pt(phi, sg * z, -.004), hp.nrm(phi, sg * z), r, t, seg=12, name='filter_can') def head(B, st, J): """Helmet. Lofted ear to ear, so the two poles of the mesh sit under the ear caps. Angles: 0 = face, +90 = crown, -90 = chin.""" B.L = I4; B.wfn = None; B.bone = 'head'; c = ST[st] B.mat = c['trim']; B.tube(1.556, 1.584, .078, seg=20, ch=.004, name='neck_ring') B.L = HM if st == 1: hp = helmet_prof(.094, .114, .122, 2.15) pn = [P(-30, 40, -.06, .06, -.003, VIS), P(46, 172, -.011, .011, .003), P(-76, -36, -.03, .03, .005)] B.mat = DARK; shell(B, hp, pn, seg=28, dz=.024, name='helmet') B.mat = CHROME; ear_caps(B, .094, .026, .011) B.cyl((.052, .062, -.062), (.072, .086, -.068), .014, seg=10, ch=.002, name='regulator_inlet') elif st == 2: hp = helmet_prof(.095, .115, .123, 2.4) pn = [P(-52, 76, -.064, .064, .006, CER), P(3, 9, -.052, .052, -.0045, VIS), P(36, 60, -.007, .007, 0, RED), P(-30, -27, -.04, .04, -.003, DARK)] B.mat = MATTE; shell(B, hp, pn, seg=28, dz=.024, name='helmet') ear_caps(B, .095, .04, .02) B.cyl((0, -.01, -.113), (.075, -.014, -.113), .0155, seg=10, ch=.003, name='sensor_pod') B.mat = GLOW; B.cyl((.074, -.014, -.113), (.078, -.014, -.113), .010, seg=8, name='sensor_lens') B.mat = STEEL; B.cyl((-.05, -.11, .05), (-.062, -.168, .05), .004, seg=6, name='antenna') B.mat = MATTE; filters(B, hp, -50, .05, .021, .014) elif st == 3: hp = helmet_prof(.095, .117, .123, 2.4) pn = [P(22, 165, -.022, .022, .009, RED), P(-50, 2, -.044, .044, .010, GREY), P(7, 9.5, .014, .046, -.003, GLOW), P(7, 9.5, -.046, -.014, -.003, GLOW), P(20, 118, .046, .08, .005, RED), P(20, 118, -.08, -.046, .005, RED), P(-28, -25, -.036, .036, -.003, DARK)] B.mat = GREY; shell(B, hp, pn, seg=28, dz=.024, name='helmet') B.mat = STEEL; ear_caps(B, .095, .032, .014) filters(B, hp, -52, .048, .02, .014) B.mat = RED for sg in (1, -1): with B.at(frame((-.012, -.035, sg * .085), (-.70, -.70, sg * .16), (.7, -.7, 0))): B.rbox((0, 0, .085), (.055, .009, .17), n=4, ch=.002, seg=8, t1=(.22, .7), name='fin') else: hp = helmet_prof(.09, .108, .116, 2.3) pn = [P(16, 176, -.076, .076, 0, VIS), P(-56, 12, -.05, .05, .007, GREY), P(3, 5.5, -.036, .036, -.0035, GLOW)] pn += [P(-46, -20, zc - .002, zc + .002, -.004, DARK) for zc in (-.024, 0, .024)] B.mat = DARK; shell(B, hp, pn, seg=28, dz=.024, name='helmet') B.mat = GREY; ear_caps(B, .09, .036, .016) for sg in (1, -1): B.rbox((.04, .08, sg * .06), (.05, .03, .03), n=4, seg=8, name='jaw_guard')