Move hand gear forward into the palm
This commit is contained in:
1 parent
7150bd7673
commit
58cf12fd1d
9 files changed
+45
-15
No files matched your search
@@ -21,6 +21,8 @@ Semantic Versioning.
|
|||||||
separate thumb instead of flat bars.
|
separate thumb instead of flat bars.
|
||||||
- Character noses gained ala wings and a smaller bridge/tip, the mouth is a
|
- Character noses gained ala wings and a smaller bridge/tip, the mouth is a
|
||||||
rounded slot, and the ears have a darker inner concha.
|
rounded slot, and the ears have a darker inner concha.
|
||||||
|
- Hand-held items now sit forward in the open palm instead of being partly
|
||||||
|
buried inside the hand.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,12 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o
|
|||||||
0.150→0.146, chest 0.170→0.168, upper chest 0.172→0.170. This is a subtle shirt taper, not a
|
0.150→0.146, chest 0.170→0.168, upper chest 0.172→0.170. This is a subtle shirt taper, not a
|
||||||
skeleton change; all proportions pass and `sheet_npc_baseline_compare-torso.jpg` records it.
|
skeleton change; all proportions pass and `sheet_npc_baseline_compare-torso.jpg` records it.
|
||||||
Max character is 4,754 tris / 4,584 verts.
|
Max character is 4,754 tris / 4,584 verts.
|
||||||
|
- **NPC hand-item forward offset (0.9.4, 2026-11-02):** `NpcAvatar.HAND_ITEM_FORWARD =
|
||||||
|
Vector3(0,0,0.04)` is added in `_attach_gear()` for every `GEAR_ATTACH` hand item after the
|
||||||
|
head/chest offsets. Hand gear is authored around the wrist proxy; without this, phone,
|
||||||
|
flashlight, cup and clipboard were partly inside the palm. Fingers are still open, so true
|
||||||
|
curl/thumb contact and umbrella/sign grips stay open. Comparison:
|
||||||
|
`sheet_npc_hands_grip_compare.jpg`; regression assertions cover camera and flashlight positions.
|
||||||
- **NPC headgear clearance (0.9.4, 2026-11-02):** after the face-detail pass, the 96
|
- **NPC headgear clearance (0.9.4, 2026-11-02):** after the face-detail pass, the 96
|
||||||
final-context frames confirm the cap, firefighter helmet, hood and sunglasses clear the refined
|
final-context frames confirm the cap, firefighter helmet, hood and sunglasses clear the refined
|
||||||
brow/eyes; `blender_assets.py fit` stays clean, so no gear was rebuilt. The broad helmet brim is
|
brow/eyes; `blender_assets.py fit` stays clean, so no gear was rebuilt. The broad helmet brim is
|
||||||
|
|||||||
@@ -126,9 +126,11 @@ and equipment fit.
|
|||||||
- [x] Refine hands and fingers enough to read at conversation distance without exceeding the
|
- [x] Refine hands and fingers enough to read at conversation distance without exceeding the
|
||||||
character triangle budget. (Wider palm, two-segment bent fingers with rounded tips, separate
|
character triangle budget. (Wider palm, two-segment bent fingers with rounded tips, separate
|
||||||
thumb; optional `--view=hand` capture and `sheet_npc_hands_compare.jpg`.)
|
thumb; optional `--view=hand` capture and `sheet_npc_hands_compare.jpg`.)
|
||||||
- [ ] Fix grip alignment for phone, cup, clipboard, camera, sign, flashlight, wand and radio
|
- [x] Move hand gear forward out of the wrist/palm so phone, cup, clipboard, camera, flashlight,
|
||||||
against the new palm/finger geometry. (Several props still occlude the palm or float beside
|
wand and radio are no longer buried inside the hand. (`HAND_ITEM_FORWARD`, 4 cm; new capture
|
||||||
it in the hand capture.)
|
sheet `sheet_npc_hands_grip_compare.jpg` and regression assertions.)
|
||||||
|
- [ ] Add finger curl/thumb contact for the hand items and judge the umbrella/sign grips against the
|
||||||
|
new palm/finger geometry.
|
||||||
- [ ] Audit shoes/boots for silhouette, grounding and contact with the floor; preserve the
|
- [ ] Audit shoes/boots for silhouette, grounding and contact with the floor; preserve the
|
||||||
responder and firefighter footwear language.
|
responder and firefighter footwear language.
|
||||||
- [ ] Improve clothing layer transitions at collars, cuffs, plackets, waistbands, pockets, badges
|
- [ ] Improve clothing layer transitions at collars, cuffs, plackets, waistbands, pockets, badges
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ Committed contact sheets and local Blender renders for the character, gear and p
|
|||||||
| <img src="sheet_npc_baseline_compare-torso.jpg" width="280" alt="sheet_npc_baseline_compare-torso.jpg"> | [`sheet_npc_baseline_compare-torso.jpg`](sheet_npc_baseline_compare-torso.jpg) |
|
| <img src="sheet_npc_baseline_compare-torso.jpg" width="280" alt="sheet_npc_baseline_compare-torso.jpg"> | [`sheet_npc_baseline_compare-torso.jpg`](sheet_npc_baseline_compare-torso.jpg) |
|
||||||
| <img src="sheet_npc_baseline_compare-face-detail.jpg" width="280" alt="sheet_npc_baseline_compare-face-detail.jpg"> | [`sheet_npc_baseline_compare-face-detail.jpg`](sheet_npc_baseline_compare-face-detail.jpg) |
|
| <img src="sheet_npc_baseline_compare-face-detail.jpg" width="280" alt="sheet_npc_baseline_compare-face-detail.jpg"> | [`sheet_npc_baseline_compare-face-detail.jpg`](sheet_npc_baseline_compare-face-detail.jpg) |
|
||||||
| <img src="sheet_npc_hands_compare.jpg" width="280" alt="sheet_npc_hands_compare.jpg"> | [`sheet_npc_hands_compare.jpg`](sheet_npc_hands_compare.jpg) |
|
| <img src="sheet_npc_hands_compare.jpg" width="280" alt="sheet_npc_hands_compare.jpg"> | [`sheet_npc_hands_compare.jpg`](sheet_npc_hands_compare.jpg) |
|
||||||
|
| <img src="sheet_npc_hands_grip_compare.jpg" width="280" alt="sheet_npc_hands_grip_compare.jpg"> | [`sheet_npc_hands_grip_compare.jpg`](sheet_npc_hands_grip_compare.jpg) |
|
||||||
| <img src="sheet_npc_gear.jpg" width="280" alt="sheet_npc_gear.jpg"> | [`sheet_npc_gear.jpg`](sheet_npc_gear.jpg) |
|
| <img src="sheet_npc_gear.jpg" width="280" alt="sheet_npc_gear.jpg"> | [`sheet_npc_gear.jpg`](sheet_npc_gear.jpg) |
|
||||||
| <img src="sheet_props.jpg" width="280" alt="sheet_props.jpg"> | [`sheet_props.jpg`](sheet_props.jpg) |
|
| <img src="sheet_props.jpg" width="280" alt="sheet_props.jpg"> | [`sheet_props.jpg`](sheet_props.jpg) |
|
||||||
| <img src="shoulder_bag.png" width="280" alt="shoulder_bag.png"> | [`shoulder_bag.png`](shoulder_bag.png) |
|
| <img src="shoulder_bag.png" width="280" alt="shoulder_bag.png"> | [`shoulder_bag.png`](shoulder_bag.png) |
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 350 KiB |
@@ -45,6 +45,7 @@ Implemented so far:
|
|||||||
- NPC mesh budget (0.9.4 work): the eight library variants now have an 8,000-triangle / 8,000-glTF-vertex cap (up from 6,000/5,000); the `npc_base` fallback remains 6,000/4,000. Current characters measure 4,226–5,218 triangles and 4,119–5,240 vertices.
|
- NPC mesh budget (0.9.4 work): the eight library variants now have an 8,000-triangle / 8,000-glTF-vertex cap (up from 6,000/5,000); the `npc_base` fallback remains 6,000/4,000. Current characters measure 4,226–5,218 triangles and 4,119–5,240 vertices.
|
||||||
- NPC face-detail pass (0.9.4 work): ala wings and a smaller nose bridge/tip, one rounded mouth slot, and a darker ear concha; all eight rebuilt. The comparison is `sheet_npc_baseline_compare-face-detail.jpg`.
|
- NPC face-detail pass (0.9.4 work): ala wings and a smaller nose bridge/tip, one rounded mouth slot, and a darker ear concha; all eight rebuilt. The comparison is `sheet_npc_baseline_compare-face-detail.jpg`.
|
||||||
- NPC headgear clearance (0.9.4 work): the 96-frame final-context review after the face-detail pass confirms the cap, firefighter helmet, hood and sunglasses clear the refined brow and eyes; no gear rebuild was needed.
|
- NPC headgear clearance (0.9.4 work): the 96-frame final-context review after the face-detail pass confirms the cap, firefighter helmet, hood and sunglasses clear the refined brow and eyes; no gear rebuild was needed.
|
||||||
|
- NPC hand-item grip (0.9.4 work): runtime `HAND_ITEM_FORWARD` moves every hand gear 4 cm forward from the wrist proxy, so phone, cup, clipboard, camera, flashlight, wand and radio sit in the open palm instead of partly inside it. Finger curl/thumb contact remains open; the comparison is `sheet_npc_hands_grip_compare.jpg`.
|
||||||
- NPC hand pass (0.9.4 work): wider, shallower palms; four two-segment bent fingers with rounded tips and a separate bent thumb; optional `--view=hand` capture at 0.80 m. The hand comparison is `sheet_npc_hands_compare.jpg`; item grip offsets remain open.
|
- NPC hand pass (0.9.4 work): wider, shallower palms; four two-segment bent fingers with rounded tips and a separate bent thumb; optional `--view=hand` capture at 0.80 m. The hand comparison is `sheet_npc_hands_compare.jpg`; item grip offsets remain open.
|
||||||
- NPC proportion audit (0.9.4 work): `tools/npc_proportions.py` measures all eight GLBs against a stylized height/head/shoulder/hip/torso/leg/arm/foot guide. All variants pass; the head and broad-build silhouettes are the nearest upper bounds. Results are in [`npc-proportion-audit.md`](npc-proportion-audit.md).
|
- NPC proportion audit (0.9.4 work): `tools/npc_proportions.py` measures all eight GLBs against a stylized height/head/shoulder/hip/torso/leg/arm/foot guide. All variants pass; the head and broad-build silhouettes are the nearest upper bounds. Results are in [`npc-proportion-audit.md`](npc-proportion-audit.md).
|
||||||
- NPC P1 portrait fixes (0.9.4 work): tourists now hide their photo-pose camera bag outside `photo`/`film` poses, removing the duplicate-backpack silhouette; the backpack gear was rebuilt with flattened, forward chest straps and a fresh AO map. The before/after sheet is [`blender_previews/sheet_npc_baseline_compare-p1.jpg`](blender_previews/sheet_npc_baseline_compare-p1.jpg); the face and remaining clothing/hand work stay open.
|
- NPC P1 portrait fixes (0.9.4 work): tourists now hide their photo-pose camera bag outside `photo`/`film` poses, removing the duplicate-backpack silhouette; the backpack gear was rebuilt with flattened, forward chest straps and a fresh AO map. The before/after sheet is [`blender_previews/sheet_npc_baseline_compare-p1.jpg`](blender_previews/sheet_npc_baseline_compare-p1.jpg); the face and remaining clothing/hand work stay open.
|
||||||
|
|||||||
+16
-11
@@ -9,8 +9,9 @@ Comparison sheets:
|
|||||||
[`sheet_npc_baseline_compare-body.jpg`](blender_previews/sheet_npc_baseline_compare-body.jpg)
|
[`sheet_npc_baseline_compare-body.jpg`](blender_previews/sheet_npc_baseline_compare-body.jpg)
|
||||||
the latest [`sheet_npc_baseline_compare-torso.jpg`](blender_previews/sheet_npc_baseline_compare-torso.jpg),
|
the latest [`sheet_npc_baseline_compare-torso.jpg`](blender_previews/sheet_npc_baseline_compare-torso.jpg),
|
||||||
the face-detail pass [`sheet_npc_baseline_compare-face-detail.jpg`](blender_previews/sheet_npc_baseline_compare-face-detail.jpg),
|
the face-detail pass [`sheet_npc_baseline_compare-face-detail.jpg`](blender_previews/sheet_npc_baseline_compare-face-detail.jpg),
|
||||||
and the conversation-distance hand pass
|
the conversation-distance hand pass
|
||||||
[`sheet_npc_hands_compare.jpg`](blender_previews/sheet_npc_hands_compare.jpg).
|
[`sheet_npc_hands_compare.jpg`](blender_previews/sheet_npc_hands_compare.jpg), and the
|
||||||
|
forward-grip pass [`sheet_npc_hands_grip_compare.jpg`](blender_previews/sheet_npc_hands_grip_compare.jpg).
|
||||||
|
|
||||||
## What was captured
|
## What was captured
|
||||||
|
|
||||||
@@ -156,12 +157,14 @@ The refit backpack measures 380 triangles / 406 vertices.
|
|||||||
|
|
||||||
### P2 — fix after the first P1 pass
|
### P2 — fix after the first P1 pass
|
||||||
|
|
||||||
4. **Hands: first pass fixed 2026-11-02; grip alignment still open.** The palm
|
4. **Hands: geometry and forward offset fixed 2026-11-02; finger curl still
|
||||||
is wider and shallower, and each finger is now a two-segment bent tube with a
|
open.** The palm is wider and shallower, and each finger is now a
|
||||||
rounded tip and a separate bent thumb. The hand capture shows a readable
|
two-segment bent tube with a rounded tip and a separate bent thumb. Hand gear
|
||||||
four-finger hand instead of flat bars. The camera, phone, cup, clipboard and
|
is authored around the wrist proxy, so the runtime now moves every hand item
|
||||||
sign still need their attach offsets checked: several props occlude the palm
|
`HAND_ITEM_FORWARD` (4 cm) into the open palm; the phone, flashlight, camera,
|
||||||
or read as floating beside it.
|
cup and clipboard are no longer buried inside the hand. The fingers are still
|
||||||
|
open, so a true wrap/thumb contact and the umbrella/sign grips remain to be
|
||||||
|
judged.
|
||||||
5. **Clothing detail is tile-driven and transitional seams are visible.** The
|
5. **Clothing detail is tile-driven and transitional seams are visible.** The
|
||||||
fabric pattern repeats strongly on the casual, coat and dress variants, and
|
fabric pattern repeats strongly on the casual, coat and dress variants, and
|
||||||
collar/cuff/waist edges are abrupt. This is more visible than the shoe/hem
|
collar/cuff/waist edges are abrupt. This is more visible than the shoe/hem
|
||||||
@@ -210,14 +213,16 @@ The committed runs are
|
|||||||
and [`sheet_npc_baseline_compare-face.jpg`](blender_previews/sheet_npc_baseline_compare-face.jpg).
|
and [`sheet_npc_baseline_compare-face.jpg`](blender_previews/sheet_npc_baseline_compare-face.jpg).
|
||||||
The transition pass is [`sheet_npc_baseline_compare-torso.jpg`](blender_previews/sheet_npc_baseline_compare-torso.jpg).
|
The transition pass is [`sheet_npc_baseline_compare-torso.jpg`](blender_previews/sheet_npc_baseline_compare-torso.jpg).
|
||||||
The face-detail pass is [`sheet_npc_baseline_compare-face-detail.jpg`](blender_previews/sheet_npc_baseline_compare-face-detail.jpg).
|
The face-detail pass is [`sheet_npc_baseline_compare-face-detail.jpg`](blender_previews/sheet_npc_baseline_compare-face-detail.jpg).
|
||||||
The hand pass is [`sheet_npc_hands_compare.jpg`](blender_previews/sheet_npc_hands_compare.jpg).
|
The hand pass is [`sheet_npc_hands_compare.jpg`](blender_previews/sheet_npc_hands_compare.jpg);
|
||||||
|
the forward-grip pass is
|
||||||
|
[`sheet_npc_hands_grip_compare.jpg`](blender_previews/sheet_npc_hands_grip_compare.jpg).
|
||||||
Keep the baseline sheet as the before artifact and add a new comparison sheet
|
Keep the baseline sheet as the before artifact and add a new comparison sheet
|
||||||
rather than replacing it.
|
rather than replacing it.
|
||||||
|
|
||||||
## Next implementation order
|
## Next implementation order
|
||||||
|
|
||||||
1. Fix hand-item grip offsets (phone, cup, clipboard, camera, sign, flashlight,
|
1. Add finger curl/thumb contact for the hand items and judge the umbrella/sign
|
||||||
wand and radio) against the new palm/finger geometry.
|
grips; the forward offset is already in place.
|
||||||
2. Add the remaining body-shape variation between variants and re-measure the
|
2. Add the remaining body-shape variation between variants and re-measure the
|
||||||
LOD/impostor silhouettes.
|
LOD/impostor silhouettes.
|
||||||
3. Audit hems and footwear in walk/sit/block poses.
|
3. Audit hems and footwear in walk/sit/block poses.
|
||||||
|
|||||||
@@ -179,6 +179,11 @@ const GEAR_OFFSETS := {
|
|||||||
"lanyard": Vector3(0, 0, 0.04),
|
"lanyard": Vector3(0, 0, 0.04),
|
||||||
"firefighter_helmet": Vector3(0, 0.03, 0),
|
"firefighter_helmet": Vector3(0, 0.03, 0),
|
||||||
}
|
}
|
||||||
|
## Hand gear is authored around the wrist proxy. The palm sits ~4 cm in front
|
||||||
|
## of that origin, so without this offset the first phone/flashlight versions
|
||||||
|
## were partly buried inside the hand. Keep the grip axis and move the whole
|
||||||
|
## item forward into the open palm.
|
||||||
|
const HAND_ITEM_FORWARD := Vector3(0, 0, 0.04)
|
||||||
const GEAR_ATTACH := {
|
const GEAR_ATTACH := {
|
||||||
"cap": "head", "beanie": "head", "hood": "head", "sunglasses": "head",
|
"cap": "head", "beanie": "head", "hood": "head", "sunglasses": "head",
|
||||||
"firefighter_helmet": "head",
|
"firefighter_helmet": "head",
|
||||||
@@ -746,6 +751,8 @@ func _attach_gear(gear_name: String) -> bool:
|
|||||||
return false
|
return false
|
||||||
if GEAR_OFFSETS.has(gear_name):
|
if GEAR_OFFSETS.has(gear_name):
|
||||||
node.position += GEAR_OFFSETS[gear_name]
|
node.position += GEAR_OFFSETS[gear_name]
|
||||||
|
if str(GEAR_ATTACH[gear_name]) == "hand":
|
||||||
|
node.position += HAND_ITEM_FORWARD
|
||||||
_detail_nodes.append(node)
|
_detail_nodes.append(node)
|
||||||
var ao := Materials.load_ao(BLENDER_GEAR_DIR + gear_name + "_ao.png")
|
var ao := Materials.load_ao(BLENDER_GEAR_DIR + gear_name + "_ao.png")
|
||||||
for child in node.find_children("*", "MeshInstance3D", true, false):
|
for child in node.find_children("*", "MeshInstance3D", true, false):
|
||||||
|
|||||||
@@ -203,6 +203,9 @@ func test_library_gear_attaches_to_the_contract_points() -> bool:
|
|||||||
var b := TestUtils.check(camera != null and camera.get_parent() is Node3D
|
var b := TestUtils.check(camera != null and camera.get_parent() is Node3D
|
||||||
and camera.get_parent().name == "Hand",
|
and camera.get_parent().name == "Hand",
|
||||||
"hand gear attaches under the hand proxy")
|
"hand gear attaches under the hand proxy")
|
||||||
|
var f := TestUtils.check(camera != null
|
||||||
|
and camera.position.z >= NpcAvatar.HAND_ITEM_FORWARD.z - 0.001,
|
||||||
|
"hand gear sits forward of the wrist proxy instead of inside the palm")
|
||||||
tourist.free()
|
tourist.free()
|
||||||
var responder := _avatar(Rules.NpcType.RESPONDER, 12)
|
var responder := _avatar(Rules.NpcType.RESPONDER, 12)
|
||||||
var helmet := responder.find_child("Gear_firefighter_helmet", true, false) as Node3D
|
var helmet := responder.find_child("Gear_firefighter_helmet", true, false) as Node3D
|
||||||
@@ -213,10 +216,13 @@ func test_library_gear_attaches_to_the_contract_points() -> bool:
|
|||||||
"firefighter helmet attaches to Rig/Head")
|
"firefighter helmet attaches to Rig/Head")
|
||||||
var d := TestUtils.check(tank != null and flashlight != null,
|
var d := TestUtils.check(tank != null and flashlight != null,
|
||||||
"responder gets SCBA tank and flashlight")
|
"responder gets SCBA tank and flashlight")
|
||||||
|
var g := TestUtils.check(flashlight != null
|
||||||
|
and flashlight.position.z >= NpcAvatar.HAND_ITEM_FORWARD.z - 0.001,
|
||||||
|
"flashlight uses the same forward grip offset")
|
||||||
var e2 := TestUtils.check(helmet != null and helmet.position.y > 0.02,
|
var e2 := TestUtils.check(helmet != null and helmet.position.y > 0.02,
|
||||||
"the firefighter helmet clears the brow")
|
"the firefighter helmet clears the brow")
|
||||||
responder.free()
|
responder.free()
|
||||||
return a and b and c and d and e and e2
|
return a and b and c and d and e and e2 and f and g
|
||||||
|
|
||||||
## Horizontal bounds of a gear GLB in its attach-node space. The head/back
|
## Horizontal bounds of a gear GLB in its attach-node space. The head/back
|
||||||
## contract is measured against the Blender fit report (head width 0.315 m,
|
## contract is measured against the Blender fit report (head width 0.315 m,
|
||||||
|
|||||||
Reference in new issue
Block a user