diff --git a/assets/models/blender/manifest.json b/assets/models/blender/manifest.json index f826199..6bf90fc 100644 --- a/assets/models/blender/manifest.json +++ b/assets/models/blender/manifest.json @@ -466,8 +466,8 @@ "accessory", "hair" ], - "triangles": 5038, - "vertices": 4756 + "triangles": 5034, + "vertices": 4607 }, "npc_coat": { "bounds_godot": { @@ -507,8 +507,8 @@ "accessory", "hair" ], - "triangles": 6030, - "vertices": 5802 + "triangles": 6046, + "vertices": 5645 }, "npc_crowd_a": { "bounds_godot": { @@ -547,8 +547,8 @@ "accessory", "hair" ], - "triangles": 5200, - "vertices": 4734 + "triangles": 5284, + "vertices": 4908 }, "npc_crowd_b": { "bounds_godot": { @@ -587,8 +587,8 @@ "accessory", "hair" ], - "triangles": 4734, - "vertices": 4353 + "triangles": 4812, + "vertices": 4550 }, "npc_crowd_c": { "bounds_godot": { @@ -627,8 +627,8 @@ "accessory", "hair" ], - "triangles": 5674, - "vertices": 5440 + "triangles": 5690, + "vertices": 5510 }, "npc_crowd_d": { "bounds_godot": { @@ -667,8 +667,8 @@ "accessory", "hair" ], - "triangles": 5814, - "vertices": 5300 + "triangles": 5810, + "vertices": 5444 }, "npc_dress": { "bounds_godot": { @@ -706,8 +706,8 @@ "accessory", "hair" ], - "triangles": 5456, - "vertices": 5128 + "triangles": 5540, + "vertices": 5073 }, "npc_firefighter": { "bounds_godot": { @@ -747,8 +747,8 @@ "accessory", "hair" ], - "triangles": 5900, - "vertices": 5902 + "triangles": 5888, + "vertices": 5785 }, "npc_guard": { "bounds_godot": { @@ -791,8 +791,8 @@ "accessory", "hair" ], - "triangles": 5602, - "vertices": 5684 + "triangles": 5670, + "vertices": 5671 }, "npc_hoodie": { "bounds_godot": { @@ -832,8 +832,8 @@ "accessory", "hair" ], - "triangles": 5860, - "vertices": 5492 + "triangles": 5864, + "vertices": 5325 }, "npc_jacket": { "bounds_godot": { @@ -873,8 +873,8 @@ "accessory", "hair" ], - "triangles": 5428, - "vertices": 5071 + "triangles": 5432, + "vertices": 5225 }, "npc_vest": { "bounds_godot": { @@ -914,8 +914,8 @@ "accessory", "hair" ], - "triangles": 5536, - "vertices": 5375 + "triangles": 5532, + "vertices": 5195 }, "palm_tree": { "bounds_godot": { diff --git a/assets/models/blender/npc/npc_casual.glb b/assets/models/blender/npc/npc_casual.glb index 82e876c..d51b152 100644 Binary files a/assets/models/blender/npc/npc_casual.glb and b/assets/models/blender/npc/npc_casual.glb differ diff --git a/assets/models/blender/npc/npc_casual_ao.png b/assets/models/blender/npc/npc_casual_ao.png index 3d97b5b..975d087 100644 Binary files a/assets/models/blender/npc/npc_casual_ao.png and b/assets/models/blender/npc/npc_casual_ao.png differ diff --git a/assets/models/blender/npc/npc_coat.glb b/assets/models/blender/npc/npc_coat.glb index f19541c..7be0357 100644 Binary files a/assets/models/blender/npc/npc_coat.glb and b/assets/models/blender/npc/npc_coat.glb differ diff --git a/assets/models/blender/npc/npc_coat_ao.png b/assets/models/blender/npc/npc_coat_ao.png index 289c464..9beb4d5 100644 Binary files a/assets/models/blender/npc/npc_coat_ao.png and b/assets/models/blender/npc/npc_coat_ao.png differ diff --git a/assets/models/blender/npc/npc_crowd_a.glb b/assets/models/blender/npc/npc_crowd_a.glb index 67d257b..116aa78 100644 Binary files a/assets/models/blender/npc/npc_crowd_a.glb and b/assets/models/blender/npc/npc_crowd_a.glb differ diff --git a/assets/models/blender/npc/npc_crowd_a_ao.png b/assets/models/blender/npc/npc_crowd_a_ao.png index 23a2084..30cabad 100644 Binary files a/assets/models/blender/npc/npc_crowd_a_ao.png and b/assets/models/blender/npc/npc_crowd_a_ao.png differ diff --git a/assets/models/blender/npc/npc_crowd_b.glb b/assets/models/blender/npc/npc_crowd_b.glb index 812ffae..d937422 100644 Binary files a/assets/models/blender/npc/npc_crowd_b.glb and b/assets/models/blender/npc/npc_crowd_b.glb differ diff --git a/assets/models/blender/npc/npc_crowd_b_ao.png b/assets/models/blender/npc/npc_crowd_b_ao.png index 4ddf6d9..88f3fc0 100644 Binary files a/assets/models/blender/npc/npc_crowd_b_ao.png and b/assets/models/blender/npc/npc_crowd_b_ao.png differ diff --git a/assets/models/blender/npc/npc_crowd_c.glb b/assets/models/blender/npc/npc_crowd_c.glb index aeb29f4..f516fa2 100644 Binary files a/assets/models/blender/npc/npc_crowd_c.glb and b/assets/models/blender/npc/npc_crowd_c.glb differ diff --git a/assets/models/blender/npc/npc_crowd_c_ao.png b/assets/models/blender/npc/npc_crowd_c_ao.png index 01b38f6..57cf8bf 100644 Binary files a/assets/models/blender/npc/npc_crowd_c_ao.png and b/assets/models/blender/npc/npc_crowd_c_ao.png differ diff --git a/assets/models/blender/npc/npc_crowd_d.glb b/assets/models/blender/npc/npc_crowd_d.glb index b76cc5b..26db046 100644 Binary files a/assets/models/blender/npc/npc_crowd_d.glb and b/assets/models/blender/npc/npc_crowd_d.glb differ diff --git a/assets/models/blender/npc/npc_crowd_d_ao.png b/assets/models/blender/npc/npc_crowd_d_ao.png index 134ca38..b38f11b 100644 Binary files a/assets/models/blender/npc/npc_crowd_d_ao.png and b/assets/models/blender/npc/npc_crowd_d_ao.png differ diff --git a/assets/models/blender/npc/npc_dress.glb b/assets/models/blender/npc/npc_dress.glb index cc68b10..da5c8a2 100644 Binary files a/assets/models/blender/npc/npc_dress.glb and b/assets/models/blender/npc/npc_dress.glb differ diff --git a/assets/models/blender/npc/npc_dress_ao.png b/assets/models/blender/npc/npc_dress_ao.png index e888303..1806c34 100644 Binary files a/assets/models/blender/npc/npc_dress_ao.png and b/assets/models/blender/npc/npc_dress_ao.png differ diff --git a/assets/models/blender/npc/npc_firefighter.glb b/assets/models/blender/npc/npc_firefighter.glb index f4ba31c..7b4903b 100644 Binary files a/assets/models/blender/npc/npc_firefighter.glb and b/assets/models/blender/npc/npc_firefighter.glb differ diff --git a/assets/models/blender/npc/npc_firefighter_ao.png b/assets/models/blender/npc/npc_firefighter_ao.png index eeef45c..e1482c6 100644 Binary files a/assets/models/blender/npc/npc_firefighter_ao.png and b/assets/models/blender/npc/npc_firefighter_ao.png differ diff --git a/assets/models/blender/npc/npc_guard.glb b/assets/models/blender/npc/npc_guard.glb index a868a6d..f73b29f 100644 Binary files a/assets/models/blender/npc/npc_guard.glb and b/assets/models/blender/npc/npc_guard.glb differ diff --git a/assets/models/blender/npc/npc_guard_ao.png b/assets/models/blender/npc/npc_guard_ao.png index 6c01bd5..a7ae64f 100644 Binary files a/assets/models/blender/npc/npc_guard_ao.png and b/assets/models/blender/npc/npc_guard_ao.png differ diff --git a/assets/models/blender/npc/npc_hoodie.glb b/assets/models/blender/npc/npc_hoodie.glb index 80ae5c1..5ab7544 100644 Binary files a/assets/models/blender/npc/npc_hoodie.glb and b/assets/models/blender/npc/npc_hoodie.glb differ diff --git a/assets/models/blender/npc/npc_hoodie_ao.png b/assets/models/blender/npc/npc_hoodie_ao.png index 6a258df..8843579 100644 Binary files a/assets/models/blender/npc/npc_hoodie_ao.png and b/assets/models/blender/npc/npc_hoodie_ao.png differ diff --git a/assets/models/blender/npc/npc_jacket.glb b/assets/models/blender/npc/npc_jacket.glb index a2a6b23..814d9e3 100644 Binary files a/assets/models/blender/npc/npc_jacket.glb and b/assets/models/blender/npc/npc_jacket.glb differ diff --git a/assets/models/blender/npc/npc_jacket_ao.png b/assets/models/blender/npc/npc_jacket_ao.png index af85d01..33c7801 100644 Binary files a/assets/models/blender/npc/npc_jacket_ao.png and b/assets/models/blender/npc/npc_jacket_ao.png differ diff --git a/assets/models/blender/npc/npc_vest.glb b/assets/models/blender/npc/npc_vest.glb index 63d6d1d..c63c795 100644 Binary files a/assets/models/blender/npc/npc_vest.glb and b/assets/models/blender/npc/npc_vest.glb differ diff --git a/assets/models/blender/npc/npc_vest_ao.png b/assets/models/blender/npc/npc_vest_ao.png index bcdaae8..b16e38a 100644 Binary files a/assets/models/blender/npc/npc_vest_ao.png and b/assets/models/blender/npc/npc_vest_ao.png differ diff --git a/tools/blender_assets.py b/tools/blender_assets.py index cf5e40d..f4b27ba 100644 --- a/tools/blender_assets.py +++ b/tools/blender_assets.py @@ -566,7 +566,7 @@ def _skin_body(spec): ((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 + ((0.275 * s * w, -0.01, 0.78), 0.034 * t, 0.030 * t), # wrist ] edges += [(3, base), (base, base + 1), (base + 1, base + 2), (base + 2, base + 3)] hb = len(nodes) @@ -666,9 +666,15 @@ def _auto_weights(obj, layout, rigid=None): groups[bone].add([v.index], 1.0, "REPLACE") continue if abs(p.x) > 0.19 and p.z > 0.74 and p.z < 1.42: - allowed = ["Spine", f"Shoulder{side}", f"Elbow{side}", f"Hand{side}"] - if abs(p.x) > 0.23: - allowed.remove("Spine") + if p.z < 0.82: + # Wrist: track the Hand bone fully so the forearm-end moves with + # the rigid hand (the old Hand+Elbow blend left a visible gap at + # the wrist when the hand rotated). + allowed = [f"Hand{side}"] + else: + allowed = ["Spine", f"Shoulder{side}", f"Elbow{side}", f"Hand{side}"] + if abs(p.x) > 0.23: + allowed.remove("Spine") elif p.z < 0.80: allowed = ["Hips", f"Hip{side}", f"Knee{side}"] if p.z < 0.66: @@ -848,26 +854,26 @@ def _hands_and_shoes(mats, spec): for s in (-1.0, 1.0): x = 0.275 * s * w # Wider and shallower than the old ball: a palm, not a wrist knob. - parts.append(sphere("Palm", 0.046, (x, -0.012, 0.742), skin, seg=10, rings=6, + parts.append(sphere("Palm", 0.046, (x, -0.012, 0.762), skin, seg=10, rings=6, scale=(0.80, 0.62, 0.88))) # Four bent, tapering fingers with rounded tips. The two segments keep # the hand readable at conversation distance without adding a full # finger skeleton; the outer fingers are slightly shorter. for index, offset in enumerate((-0.024, -0.008, 0.008, 0.024)): fx = x + offset * s - tip_z = (0.692, 0.681, 0.684, 0.694)[index] + tip_z = (0.712, 0.701, 0.704, 0.714)[index] radius = 0.0115 if index in (1, 2) else 0.0105 - parts.append(tube("Finger", [(fx, -0.018, 0.758), - (fx, -0.030, 0.726), + parts.append(tube("Finger", [(fx, -0.018, 0.778), + (fx, -0.030, 0.746), (fx, -0.042, tip_z)], radius, skin, seg=6, caps=False)) parts.append(sphere("Fingertip", radius, (fx, -0.042, tip_z), skin, seg=6, rings=4)) - parts.append(tube("Thumb", [(x - 0.010 * s, -0.018, 0.758), - (x - 0.028 * s, -0.040, 0.740), - (x - 0.034 * s, -0.055, 0.718)], + parts.append(tube("Thumb", [(x - 0.010 * s, -0.018, 0.778), + (x - 0.028 * s, -0.040, 0.760), + (x - 0.034 * s, -0.055, 0.738)], 0.012, skin, seg=6, caps=False)) - parts.append(sphere("ThumbTip", 0.012, (x - 0.034 * s, -0.055, 0.718), skin, + parts.append(sphere("ThumbTip", 0.012, (x - 0.034 * s, -0.055, 0.738), skin, seg=6, rings=4)) parts.append(box("Shoe", (0.10, 0.25, 0.075), (0.12 * s, -0.045, 0.04), shoe, bevel=0.028, segs=1)) @@ -1012,7 +1018,9 @@ def build_character(name): return "Head" if p.z > 1.55 else "Neck" side = "L" if p.x < 0 else "R" if abs(p.x) > 0.26 and p.z > 0.8: - return f"Elbow{side}" + # Sleeve: the cuff follows the hand, the upper sleeve the elbow, + # so the sleeve does not separate from the hand at the wrist. + return f"Hand{side}" if p.z < 1.06 else f"Elbow{side}" if p.z < 0.25: return f"Knee{side}" return None