Refine the NPC nose, mouth and ears
Full build / Import + headless tests (push) Successful in 35s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-02 19:29:19 +01:00
1 parent 7dc3d3c873
commit 12e70357c5
26 files changed
+80 -62

No files matched your search

+13 -6
View File
@@ -774,14 +774,19 @@ def _face(mats, spec):
# nose: bridge and ball (nostrils were cut to stay inside the vertex budget)
parts.append(cyl("NoseBridge", 0.016, 0.022, 0.06, (0, -0.145, 1.652), skin, seg=8,
rot=(math.radians(-72), 0, 0), smooth=True))
parts.append(sphere("NoseTip", 0.024, (0, -0.163, 1.616), skin, seg=10, rings=6,
scale=(1.0, 0.9, 0.85)))
parts.append(sphere("NoseTip", 0.022, (0, -0.162, 1.615), skin, seg=10, rings=6,
scale=(1.0, 0.85, 0.80)))
for s in (-1.0, 1.0):
# ear with a lobe, and one crease so it is not a flat disc
# Ala widen the nose base into a small triangle rather than a ball.
parts.append(sphere("NoseWing", 0.011, (0.015 * s, -0.160, 1.606), skin,
seg=6, rings=4, scale=(1.0, 0.65, 0.75)))
# Ear with a lobe and a darker concha; the old disc had no depth cue.
parts.append(sphere("Ear", 0.036, (0.143 * s, 0.008, 1.63), skin, seg=8, rings=5,
scale=(0.42, 1.0, 1.35)))
parts.append(sphere("EarLobe", 0.018, (0.142 * s, -0.005, 1.605), skin, seg=8,
rings=5, scale=(0.45, 1.0, 0.9)))
parts.append(sphere("EarInner", 0.013, (0.149 * s, -0.003, 1.633), acc,
seg=6, rings=4, scale=(0.28, 0.65, 0.90)))
# Eye: recess the sclera into the socket, then wrap it with skin lids.
# The old white ball sat ~1 cm proud of the head; this keeps the iris
# readable without the doll-like bulge.
@@ -798,9 +803,11 @@ def _face(mats, spec):
parts.append(box("Brow", (0.055, 0.014, 0.012), (0.052 * s, -0.143, 1.699), hair,
rot=(0, 0.14 * s, 0.0)))
# lips: upper and lower instead of a single bar
parts.append(box("LipUpper", (0.052, 0.012, 0.008), (0, -0.156, 1.588), acc,
rot=(math.radians(6), 0, 0)))
parts.append(box("LipLower", (0.046, 0.012, 0.009), (0, -0.154, 1.578), acc))
# One rounded mouth slot instead of two flat boxes. Two dark lip blobs read
# as a moustache at portrait distance; a single shallow oval keeps the mouth
# line without adding a second dark mass.
parts.append(sphere("Mouth", 0.028, (0, -0.158, 1.583), acc, seg=8, rings=5,
scale=(1.0, 0.28, 0.12)))
if spec.get("beard"):
parts.append(sphere("Beard", 0.105, (0, -0.06, 1.55), hair, seg=12, rings=8,
scale=(1.0, 0.9, 0.75), cut_below=-0.2))