Ship the Quaternius npc_casual pilot base: rig-agnostic pose sync, five tint slots, unwrapped UVs and wrist-strap camera
This commit is contained in:
1 parent
68f49253fe
commit
cd285b3a39
12 files changed
+242
-74
No files matched your search
+22
-5
@@ -53,6 +53,12 @@ MANIFEST = OUT_DIR / "manifest.json"
|
||||
SLOTS = ["skin", "cloth", "pants", "accessory", "hair"]
|
||||
BONES = ["Head", "HipL", "HipR", "KneeL", "KneeR", "ShoulderL", "ShoulderR",
|
||||
"ElbowL", "ElbowR", "HandL", "HandR"]
|
||||
# ADR-0018: a Quaternius-derived character keeps the upstream 62-joint armature
|
||||
# instead of the 13-core skeleton, so these are the joints `NpcAvatar` maps onto
|
||||
# the animation proxies and the ones the audit requires.
|
||||
QUATERNIUS_BONES = ["Head", "UpperLeg.L", "UpperLeg.R", "LowerLeg.L", "LowerLeg.R",
|
||||
"UpperArm.L", "UpperArm.R", "LowerArm.L", "LowerArm.R",
|
||||
"Wrist.L", "Wrist.R"]
|
||||
# Character cap raised to 24000/24000 on 2026-11-05 for the MPFB body, the
|
||||
# accepted MakeHuman head and a seamless neck/shoulder junction. The required
|
||||
# 13 core bones stay, but optional extra bones (fingers, face, toes) are
|
||||
@@ -1555,9 +1561,13 @@ def build_gear(name):
|
||||
rot=(math.radians(90), 0, 0)))
|
||||
p.append(box("Prism", (0.05, 0.05, 0.03), (0, -0.04, 0.095), M("plastic_black"),
|
||||
bevel=0.006))
|
||||
p.append(tube("Strap", [(-0.065, -0.04, 0.06), (-0.10, 0.0, 0.25), (0.0, 0.05, 0.42),
|
||||
(0.10, 0.0, 0.25), (0.065, -0.04, 0.06)], 0.006,
|
||||
M("plastic_black"), seg=5))
|
||||
# The hand attach point hangs off the wrist, so a full neck strap would
|
||||
# float beside the head instead of resting on the neck. A short wrist
|
||||
# loop keeps every hand item self-contained and follows the hand.
|
||||
p.append(tube("WristStrap", [(-0.045, -0.02, 0.02), (-0.05, -0.035, 0.075),
|
||||
(0.0, -0.045, 0.10), (0.05, -0.035, 0.075),
|
||||
(0.045, -0.02, 0.02)], 0.005, M("plastic_black"),
|
||||
seg=5, caps=False))
|
||||
elif name == "protest_sign":
|
||||
p.append(box("Pole", (0.03, 0.03, 1.1), (0, 0, 0.35), M("wood")))
|
||||
p.append(box("Board", (0.62, 0.012, 0.42), (0, -0.025, 0.82), M("cardboard"),
|
||||
@@ -2164,7 +2174,8 @@ def audit_asset(category, name):
|
||||
nodes = gltf.get("nodes", [])
|
||||
bones = [nodes[j].get("name", "") for s in gltf.get("skins", [])
|
||||
for j in s.get("joints", [])]
|
||||
for b in BONES:
|
||||
required = QUATERNIUS_BONES if "UpperArm.L" in bones else BONES
|
||||
for b in required:
|
||||
if b not in bones:
|
||||
res["issues"].append(f"missing bone {b}")
|
||||
if not any(n.get("name") == "npc_base" and "mesh" in n for n in nodes):
|
||||
@@ -2326,7 +2337,13 @@ def analyse_inspection(stats: dict) -> dict:
|
||||
bones = list(stats.get("bones", []))
|
||||
materials = list(stats.get("materials", []))
|
||||
bones_ok = {b for b in BONES if b in bones}
|
||||
needed = set(BONES) | {"Hips", "Spine", "Neck"}
|
||||
# ADR-0018: a Quaternius-derived character keeps the 62-joint upstream
|
||||
# armature, so the required set is the joints `NpcAvatar` maps instead of the
|
||||
# 13-core skeleton.
|
||||
if "UpperArm.L" in bones:
|
||||
needed = set(QUATERNIUS_BONES)
|
||||
else:
|
||||
needed = set(BONES) | {"Hips", "Spine", "Neck"}
|
||||
|
||||
if not meshes:
|
||||
issues.append("no mesh objects")
|
||||
|
||||
Reference in new issue
Block a user