Smooth the NPC neck and shoulder transition
This commit is contained in:
1 parent
ab9c67d266
commit
15ab8c686d
29 files changed
+85
-53
No files matched your search
+28
-8
@@ -535,15 +535,18 @@ def _skin_body(spec):
|
||||
((0, 0, 0.96), 0.150 * w * bulk, 0.105 * d * bulk), # 1 waist
|
||||
((0, 0.0, 1.18), 0.170 * w * bulk, 0.115 * d * bulk), # 2 chest
|
||||
((0, 0.0, 1.355), 0.172 * w * bulk, 0.108 * d * bulk), # 3 upper chest
|
||||
((0, 0, 1.44), 0.058, 0.058), # 4 neck base
|
||||
((0, -0.005, 1.53), 0.052, 0.052), # 5 neck top
|
||||
# A slightly fuller neck base and a lower shoulder root give the
|
||||
# head/neck/shoulder line a trapezius slope instead of a thin post on
|
||||
# a hanger. The head and collar still sit above this band.
|
||||
((0, 0, 1.43), 0.074, 0.072), # 4 neck base
|
||||
((0, -0.005, 1.53), 0.060, 0.060), # 5 neck top
|
||||
]
|
||||
edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
|
||||
for s in (-1.0, 1.0):
|
||||
base = len(nodes)
|
||||
nodes += [
|
||||
((0.20 * s * w, 0, 1.39), 0.075 * t * sleeve, 0.07 * t * sleeve), # shoulder
|
||||
((0.27 * s * w, 0, 1.24), 0.058 * t * sleeve, 0.058 * t * sleeve), # upper arm
|
||||
((0.20 * s * w, 0, 1.37), 0.080 * t * sleeve, 0.074 * t * sleeve), # shoulder
|
||||
((0.27 * s * w, 0, 1.23), 0.058 * t * sleeve, 0.058 * t * sleeve), # upper arm
|
||||
((0.275 * s * w, 0.005, 1.06), 0.046 * t * sleeve, 0.048 * t * sleeve), # elbow
|
||||
((0.275 * s * w, -0.01, 0.80), 0.034 * t, 0.030 * t), # wrist
|
||||
]
|
||||
@@ -929,6 +932,23 @@ def build_character(name):
|
||||
rest.append(cl)
|
||||
|
||||
mesh = join(rest, "npc_base")
|
||||
# The fuller neck/shoulder skin graph can leave a few collinear triangles
|
||||
# after the decimate step. Remove them before UV/export; Godot warns about
|
||||
# zero-area faces during LOD generation and `audit` rejects them.
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(mesh.data)
|
||||
bmesh.ops.dissolve_degenerate(bm, dist=2e-4, edges=bm.edges)
|
||||
# Skin-modifier branch cleanup can still leave a handful of zero-area
|
||||
# faces; Godot's LOD generator treats them as malformed. Triangulate first
|
||||
# because a degenerate quad can become a zero-area triangle on export, then
|
||||
# drop the tiny faces explicitly.
|
||||
bmesh.ops.triangulate(bm, faces=bm.faces[:], quad_method="BEAUTY",
|
||||
ngon_method="BEAUTY")
|
||||
bad = [face for face in bm.faces if face.calc_area() < 1e-10]
|
||||
if bad:
|
||||
bmesh.ops.delete(bm, geom=bad, context="FACES_ONLY")
|
||||
bm.to_mesh(mesh.data)
|
||||
bm.free()
|
||||
# Every contract slot must exist even if a variant does not paint with it.
|
||||
present = {m.name for m in mesh.data.materials if m}
|
||||
for slot in SLOTS:
|
||||
@@ -1019,10 +1039,10 @@ def build_gear(name):
|
||||
# torso front (Godot z≈0.21). The old chest/waist points sat at
|
||||
# z≈0.13 inside the body, so only thin tube fragments read as two
|
||||
# rigid black bars from the front.
|
||||
p.append(tube("Strap", [(0.09 * s, 0.13, 0.27), (0.10 * s, -0.02, 0.29),
|
||||
(0.105 * s, -0.06, 0.25),
|
||||
(0.11 * s, -0.19, 0.18), (0.12 * s, -0.19, -0.08)],
|
||||
0.018, M("plastic_black"), seg=8, width_scale=1.35,
|
||||
p.append(tube("Strap", [(0.09 * s, 0.13, 0.27), (0.11 * s, -0.02, 0.29),
|
||||
(0.12 * s, -0.06, 0.25),
|
||||
(0.14 * s, -0.19, 0.18), (0.145 * s, -0.19, -0.08)],
|
||||
0.016, M("denim_bag"), seg=8, width_scale=1.35,
|
||||
thickness_scale=0.42))
|
||||
elif name == "shoulder_bag":
|
||||
# Keep the bag's inner face outside the widest skirt flare (dress = 0.26):
|
||||
|
||||
Reference in new issue
Block a user