Refine the head prototype: flatten face plane, taper jaw, nose/chin relief, fix ear-displacement sign
Full build / Import + headless tests (push) Successful in 42s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-04 14:36:53 +01:00
1 parent 4f1eb1f5bf
commit 00bd197173
3 files changed
+55 -26

No files matched your search

+38 -17
View File
@@ -105,11 +105,22 @@ def _head_proto(mats, spec):
skin, acc, hair = mats["skin"], mats["accessory"], mats["hair"]
white = ba.material("eye_white", textured_solid=True)
head = ba.sphere("HeadShell", 0.155, (0, 0, 1.635), skin, seg=48, rings=26,
scale=(0.92, 1.0, 1.12))
scale=(0.90, 0.96, 1.08))
ba._shape_head_mesh(head) # brow ridge + cheekbone + jaw/chin planes
bm = ba.bmesh.new()
bm.from_mesh(head.data)
# Pass 1: skull shape — flatten the face plane and taper the jaw/chin so the
# head stops reading as an egg.
for v in bm.verts:
x, y, z = v.co
if y < -0.03 and 1.44 < z < 1.76:
v.co.y = -0.13 + (y + 0.13) * 0.10 # flatten the forward bulge
if z < 1.58:
taper = max(0.0, 1.0 - (1.58 - z) / 0.12)
v.co.x *= 1.0 - 0.16 * taper # narrow the lower face
# Pass 2: features on the flattened face.
for v in bm.verts:
x, y, z = v.co
ax = abs(x)
@@ -120,16 +131,26 @@ def _head_proto(mats, spec):
v.co.y += 0.018 * (1.0 - r / 0.036) # recess inward (+y)
elif r < 0.046:
v.co.y -= 0.010 * (1.0 - (r - 0.036) / 0.010) # rim forward
# --- nose: bridge/tip protrusion plus ala wings ---
if y < 0 and ax < 0.048:
band = max(0.0, 1.0 - abs(z - 1.628) / 0.052) # 1.576..1.680
# --- nose: a wide bridge/tip with ala wings, not a spike ---
if y < 0 and ax < 0.075:
band = max(0.0, 1.0 - abs(z - 1.632) / 0.055) # 1.577..1.687
if band > 0:
tip = max(0.0, 1.0 - abs(z - 1.615) / 0.022)
v.co.y -= (0.035 * tip + 0.012 * (band - tip)) * (1.0 - ax / 0.048)
tip = max(0.0, 1.0 - abs(z - 1.615) / 0.032)
v.co.y -= (0.060 * tip + 0.018 * max(0.0, band - tip)) \
* (1.0 - ax / 0.075)
for s in (-1.0, 1.0):
ar = math.hypot((x - 0.017 * s) / 0.011, (z - 1.606) / 0.011)
ar = math.hypot((x - 0.024 * s) / 0.014, (z - 1.604) / 0.013)
if ar < 1.0:
v.co.y -= 0.018 * (1.0 - ar)
v.co.y -= 0.022 * (1.0 - ar)
# --- chin: a distinct forward bump below the mouth ---
if y < 0 and ax < 0.040:
chin = max(0.0, 1.0 - abs(z - 1.548) / 0.022)
if chin > 0:
v.co.y -= 0.030 * chin
# jaw step: recess just below the chin so it reads as a chin-to-neck
step = max(0.0, 1.0 - abs(z - 1.516) / 0.014)
if step > 0:
v.co.y += 0.012 * step
# --- mouth: recessed line + upper/lower lip volumes ---
if y < 0 and ax < 0.030:
if abs(z - 1.583) < 0.012:
@@ -138,17 +159,17 @@ def _head_proto(mats, spec):
v.co.y -= 0.014 # upper lip
if abs(z - 1.577) < 0.010:
v.co.y -= 0.018 # fuller lower lip
# --- ears: extrude outward with a concha recess ---
# --- ears: extrude outward with a concha recess, lower (brow-to-nose band) ---
for v in bm.verts:
x, y, z = v.co
for s in (-1.0, 1.0):
r = math.hypot((z - 1.63) / 0.055, (y - 0.008) / 0.045)
near = abs(x) - 0.140
if -0.02 < near < 0.05 and r < 1.0:
if r < 0.35:
v.co.x -= 0.014 * (1.0 - r / 0.35) * s # concha recess (inward)
else:
v.co.x += 0.028 * (1.0 - r) * s # helix rim outward
r = math.hypot((z - 1.60) / 0.055, (y - 0.002) / 0.045)
near = abs(x) - 0.138
sign = 1.0 if x >= 0 else -1.0
if -0.02 < near < 0.055 and r < 1.0:
if r < 0.35:
v.co.x -= 0.016 * (1.0 - r / 0.35) * sign # concha recess (inward)
else:
v.co.x += 0.034 * (1.0 - r) * sign # helix rim outward
bm.normal_update()
bm.to_mesh(head.data)
bm.free()