Avatar: tune Roblox proportions + walk cycle from real rendered screenshots
checkpoint / checkpoint (push) Successful in 1m47s

Now that cloudbison can render (Radeon GPU via Xvfb, or llvmpipe software),
added scripts/tools/screenshot_rig.gd + scenes/dev/ so a scene can be booted,
run a few frames, and its rendered frame saved to PNG -- caught three things
the headless smoke never could:

- limbs floated detached from the torso: widened the torso and overlapped the
  arm/leg boxes into it, and pulled limb depth in behind the torso front so
  they stop z-fighting.
- proportions were scrawny: reworked to Roblox R6 ratios (2-stud torso, 2-stud
  arms/legs, 1-stud head) with the head clearly pegged on top.
- the walk swing was a 40-deg lunge: STRIDE 0.7->0.42 rad, separate 0.32 arm
  swing, KNEE 1.0->0.5. Reads as a walk now, not a crouch.

test_level lighting was near-black on the shaded side (ambient was disabled) --
colour ambient at 0.8 + a stronger key light, so the avatar reads in-world.

avatar_preview.tscn (AGP_PREVIEW_WALK=1) renders the assembled avatar walking
in place for quick visual checks.

Verified: avatar smoke 14/14 source + exported pack; fresh-clone boot PASS;
eyeballed in rendered screenshots (game scene + walk sequence).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015jtxAiu5dAW4WxCNdGkrkJ
This commit is contained in:
2026-09-06 14:06:46 +00:00
parent 1b1260f371
commit 3fb45f0ef2
10 changed files with 197 additions and 41 deletions
+33 -33
View File
@@ -19,29 +19,29 @@ const OUT_DIR := "res://assets/avatars/"
# name -> [parent_name, global_rest_position] (A-pose, arms down, Y-up, metres)
const BONES := {
"Root": ["", Vector3(0.00, 0.00, 0.00)],
"Hips": ["Root", Vector3(0.00, 0.80, 0.00)],
"Hips": ["Root", Vector3(0.00, 0.76, 0.00)],
"Spine": ["Hips", Vector3(0.00, 1.00, 0.00)],
"Chest": ["Spine", Vector3(0.00, 1.22, 0.00)],
"Neck": ["Chest", Vector3(0.00, 1.36, 0.00)],
"Head": ["Neck", Vector3(0.00, 1.44, 0.00)],
"HeadTop": ["Head", Vector3(0.00, 1.92, 0.00)],
"Jaw": ["Head", Vector3(0.00, 1.54, 0.14)],
"LeftEye": ["Head", Vector3(0.12, 1.66, 0.28)],
"RightEye": ["Head", Vector3(-0.12, 1.66, 0.28)],
"LeftShoulder": ["Chest", Vector3(0.22, 1.34, 0.00)],
"LeftUpperArm": ["LeftShoulder", Vector3(0.45, 1.30, 0.00)],
"LeftLowerArm": ["LeftUpperArm", Vector3(0.45, 1.02, 0.00)],
"LeftHand": ["LeftLowerArm", Vector3(0.45, 0.74, 0.00)],
"RightShoulder": ["Chest", Vector3(-0.22, 1.34, 0.00)],
"RightUpperArm": ["RightShoulder", Vector3(-0.45, 1.30, 0.00)],
"RightLowerArm": ["RightUpperArm", Vector3(-0.45, 1.02, 0.00)],
"RightHand": ["RightLowerArm", Vector3(-0.45, 0.74, 0.00)],
"LeftUpperLeg": ["Hips", Vector3(0.17, 0.78, 0.00)],
"LeftLowerLeg": ["LeftUpperLeg", Vector3(0.17, 0.40, 0.00)],
"LeftFoot": ["LeftLowerLeg", Vector3(0.17, 0.05, 0.05)],
"RightUpperLeg": ["Hips", Vector3(-0.17, 0.78, 0.00)],
"RightLowerLeg": ["RightUpperLeg", Vector3(-0.17, 0.40, 0.00)],
"RightFoot": ["RightLowerLeg", Vector3(-0.17, 0.05, 0.05)],
"Chest": ["Spine", Vector3(0.00, 1.30, 0.00)],
"Neck": ["Chest", Vector3(0.00, 1.50, 0.00)],
"Head": ["Neck", Vector3(0.00, 1.58, 0.00)],
"HeadTop": ["Head", Vector3(0.00, 2.00, 0.00)],
"Jaw": ["Head", Vector3(0.00, 1.64, 0.16)],
"LeftEye": ["Head", Vector3(0.12, 1.76, 0.27)],
"RightEye": ["Head", Vector3(-0.12, 1.76, 0.27)],
"LeftShoulder": ["Chest", Vector3(0.42, 1.50, 0.00)],
"LeftUpperArm": ["LeftShoulder", Vector3(0.60, 1.44, 0.00)],
"LeftLowerArm": ["LeftUpperArm", Vector3(0.60, 1.14, 0.00)],
"LeftHand": ["LeftLowerArm", Vector3(0.60, 0.82, 0.00)],
"RightShoulder": ["Chest", Vector3(-0.42, 1.50, 0.00)],
"RightUpperArm": ["RightShoulder", Vector3(-0.60, 1.44, 0.00)],
"RightLowerArm": ["RightUpperArm", Vector3(-0.60, 1.14, 0.00)],
"RightHand": ["RightLowerArm", Vector3(-0.60, 0.82, 0.00)],
"LeftUpperLeg": ["Hips", Vector3(0.21, 0.74, 0.00)],
"LeftLowerLeg": ["LeftUpperLeg", Vector3(0.21, 0.38, 0.00)],
"LeftFoot": ["LeftLowerLeg", Vector3(0.21, 0.05, 0.06)],
"RightUpperLeg": ["Hips", Vector3(-0.21, 0.74, 0.00)],
"RightLowerLeg": ["RightUpperLeg", Vector3(-0.21, 0.38, 0.00)],
"RightFoot": ["RightLowerLeg", Vector3(-0.21, 0.05, 0.06)],
}
# Order matters: parents before children.
@@ -64,16 +64,16 @@ const C_FACE := Color(0.05, 0.05, 0.06) # near-black (eyes + smile)
# weighted to its bone -- so the rig still drives it, but it reads as a clean
# solid block (no banding, no capsule taper).
const PARTS := [
["Head", Vector3(0.00, 1.62, 0.00), Vector3(0.60, 0.56, 0.56), C_SKIN],
["Spine", Vector3(0.00, 1.06, 0.00), Vector3(0.74, 0.64, 0.38), C_SHIRT],
["LeftUpperArm", Vector3(0.45, 1.04, 0.00), Vector3(0.27, 0.66, 0.31), C_SKIN],
["RightUpperArm", Vector3(-0.45, 1.04, 0.00), Vector3(0.27, 0.66, 0.31), C_SKIN],
["LeftUpperLeg", Vector3(0.17, 0.39, 0.00), Vector3(0.31, 0.80, 0.33), C_PANTS],
["RightUpperLeg", Vector3(-0.17, 0.39, 0.00), Vector3(0.31, 0.80, 0.33), C_PANTS],
["Head", Vector3(0.00, 1.74, 0.00), Vector3(0.58, 0.56, 0.56), C_SKIN],
["Spine", Vector3(0.00, 1.14, 0.00), Vector3(0.90, 0.80, 0.48), C_SHIRT],
["LeftUpperArm", Vector3(0.58, 1.14, 0.00), Vector3(0.34, 0.78, 0.40), C_SKIN],
["RightUpperArm", Vector3(-0.58, 1.14, 0.00), Vector3(0.34, 0.78, 0.40), C_SKIN],
["LeftUpperLeg", Vector3(0.21, 0.38, 0.00), Vector3(0.40, 0.78, 0.40), C_PANTS],
["RightUpperLeg", Vector3(-0.21, 0.38, 0.00), Vector3(0.40, 0.78, 0.40), C_PANTS],
# painted-on face -- thin plates on the front of the head (+Z), rigged to Head
["Head", Vector3(0.12, 1.66, 0.285), Vector3(0.07, 0.10, 0.02), C_FACE],
["Head", Vector3(-0.12, 1.66, 0.285), Vector3(0.07, 0.10, 0.02), C_FACE],
["Head", Vector3(0.00, 1.52, 0.285), Vector3(0.26, 0.05, 0.02), C_FACE],
["Head", Vector3(0.13, 1.78, 0.28), Vector3(0.09, 0.12, 0.02), C_FACE],
["Head", Vector3(-0.13, 1.78, 0.28), Vector3(0.09, 0.12, 0.02), C_FACE],
["Head", Vector3(0.00, 1.64, 0.28), Vector3(0.32, 0.05, 0.02), C_FACE],
]
# Attachments: id -> [Mesh, local_offset_from_mount_bone, colour]
@@ -90,8 +90,8 @@ const ATTACHMENTS := {
"right_hand_glove_01": ["blob", Vector3(0, 0.0, 0.0), Color(0.15, 0.15, 0.18)],
"left_foot_boot_01": ["boot", Vector3(0, -0.02, 0.05), Color(0.12, 0.10, 0.09)],
"right_foot_boot_01": ["boot", Vector3(0, -0.02, 0.05), Color(0.12, 0.10, 0.09)],
"accessory_belt_01": ["belt", Vector3(0, 0.80, 0.0), Color(0.20, 0.18, 0.12)],
"accessory_necklace_01": ["necklace", Vector3(0, 1.30, 0.06), Color(0.85, 0.75, 0.20)],
"accessory_belt_01": ["belt", Vector3(0, 0.74, 0.0), Color(0.20, 0.18, 0.12)],
"accessory_necklace_01": ["necklace", Vector3(0, 1.34, 0.10), Color(0.85, 0.75, 0.20)],
}
var _fail := 0