- autorig: landmark detection from vertex cloud (markers JSON override), mixamorig 22-bone skeleton fit, bone-heat weights + nearest-bone rescue - retarget: world-space quaternion delta transfer, hip-height scale compensation, fuzzy/explicit bone mapping (CMU map bundled) - smoke: procedural test humanoid + synthetic BVH -> rig -> retarget -> verify - deploy: push to gitea, pull + smoke on m3ultra and m1ultra Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
84 lines
2.7 KiB
Python
Executable File
84 lines
2.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Fetch free motion-capture libraries into library/downloads/.
|
|
|
|
Sources live in library/manifest.json. Entries marked "verified": false
|
|
have not been confirmed reachable yet — the script reports what it can and
|
|
skips what it can't, it never fails the whole run on one dead mirror.
|
|
|
|
Usage:
|
|
python3 library/fetch.py # fetch everything in the manifest
|
|
python3 library/fetch.py --only cmu_sample
|
|
python3 library/fetch.py --url https://... --name mypack # ad-hoc
|
|
"""
|
|
import argparse
|
|
import json
|
|
import os
|
|
import sys
|
|
import urllib.request
|
|
import zipfile
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
DOWNLOADS = os.path.join(HERE, "downloads")
|
|
|
|
|
|
def fetch_one(name, url, unpack):
|
|
os.makedirs(DOWNLOADS, exist_ok=True)
|
|
dest_dir = os.path.join(DOWNLOADS, name)
|
|
fname = os.path.join(DOWNLOADS, os.path.basename(url.split("?")[0]) or name)
|
|
if os.path.exists(dest_dir) and os.listdir(dest_dir):
|
|
print(f"[skip] {name}: already downloaded")
|
|
return True
|
|
print(f"[get ] {name}: {url}")
|
|
try:
|
|
req = urllib.request.Request(url, headers={"User-Agent": "mirpamo/0.1"})
|
|
with urllib.request.urlopen(req, timeout=60) as r, open(fname, "wb") as f:
|
|
while True:
|
|
chunk = r.read(1 << 20)
|
|
if not chunk:
|
|
break
|
|
f.write(chunk)
|
|
except Exception as e:
|
|
print(f"[fail] {name}: {e}")
|
|
return False
|
|
if unpack and fname.endswith(".zip"):
|
|
os.makedirs(dest_dir, exist_ok=True)
|
|
with zipfile.ZipFile(fname) as z:
|
|
z.extractall(dest_dir)
|
|
os.remove(fname)
|
|
print(f"[ok ] {name}: unpacked to {dest_dir}")
|
|
else:
|
|
os.makedirs(dest_dir, exist_ok=True)
|
|
os.rename(fname, os.path.join(dest_dir, os.path.basename(fname)))
|
|
print(f"[ok ] {name}")
|
|
return True
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--only")
|
|
ap.add_argument("--url")
|
|
ap.add_argument("--name", default="adhoc")
|
|
args = ap.parse_args()
|
|
|
|
if args.url:
|
|
ok = fetch_one(args.name, args.url, unpack=True)
|
|
sys.exit(0 if ok else 1)
|
|
|
|
with open(os.path.join(HERE, "manifest.json")) as f:
|
|
manifest = json.load(f)
|
|
|
|
results = []
|
|
for entry in manifest["sources"]:
|
|
if args.only and entry["name"] != args.only:
|
|
continue
|
|
if entry.get("url", "").startswith("TODO"):
|
|
print(f"[todo] {entry['name']}: no URL yet — {entry.get('notes','')}")
|
|
continue
|
|
results.append(fetch_one(entry["name"], entry["url"],
|
|
entry.get("unpack", True)))
|
|
print(f"\n{sum(results)}/{len(results)} sources fetched")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|