Add head subdivision variants and pick s48 after 1.5m/1.85m comparison
Full build / Import + headless tests (push) Successful in 43s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-04 14:42:13 +01:00
1 parent b386a21173
commit f0f609fe1b
3 files changed
+28 -7

No files matched your search

+9 -6
View File
@@ -93,18 +93,19 @@ def _export_obj(obj, path):
return path
def _head_proto(mats, spec):
def _head_proto(mats, spec, subdiv=48):
"""Connected head shell with sculpted sockets, nose, lips, ears and brow/cheek/jaw.
This is the §3 prototype: the skin features are displaced out of one head
mesh instead of floating spheres, so the face is a single connected surface
with loop-based eye sockets and protruding nose/lip/ear volumes. The eyeballs
(sclera/iris/lids) stay separate — they are not skin. Blender Z-up, face
front −Y.
front −Y. `subdiv` is the UV-sphere u-segments (24/48/64 variants).
"""
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,
rings = max(14, subdiv // 2 + 2)
head = ba.sphere("HeadShell", 0.155, (0, 0, 1.635), skin, seg=subdiv, rings=rings,
scale=(0.90, 0.96, 1.08))
ba._shape_head_mesh(head) # brow ridge + cheekbone + jaw/chin planes
bm = ba.bmesh.new()
@@ -204,7 +205,7 @@ def _head_proto(mats, spec):
return parts
def build_part(name, variant, out):
def build_part(name, variant, out, subdiv=48):
"""Build one part fresh from the current builders (Blender-only)."""
mats, spec = _mats_and_spec(variant)
if name == "head":
@@ -214,7 +215,7 @@ def build_part(name, variant, out):
elif name == "face":
obj = ba.join(ba._face(mats, spec), "face")
elif name == "head_proto":
obj = ba.join(_head_proto(mats, spec), "head_proto")
obj = ba.join(_head_proto(mats, spec, subdiv=subdiv), "head_proto")
else:
side = -1.0 if name == "hand_l" else 1.0
hs = ba._hands_and_shoes(mats, spec)
@@ -378,6 +379,8 @@ def main(argv=None):
s.add_argument("--part", required=True, choices=PART_NAMES)
s.add_argument("--variant", default=PROTOTYPE)
s.add_argument("--out", required=True)
s.add_argument("--subdiv", type=int, default=48,
help="head_proto UV-sphere u-segments (24/48/64 variants)")
asm = sub.add_parser("assemble")
asm.add_argument("--variant", default=PROTOTYPE)
@@ -411,7 +414,7 @@ def main(argv=None):
return code
ba.reset_scene()
if args.cmd == "build":
build_part(args.part, args.variant, args.out)
build_part(args.part, args.variant, args.out, subdiv=args.subdiv)
print(f"built part {args.part} -> {args.out}")
elif args.cmd == "extract":
extract_part(args.part, args.variant, args.out)