Files
animation/tools/edge_stretch.py
T

54 lines
2.1 KiB
Python
Raw Normal View History

"""Edge-stretch fin detector (pure python): posed OBJ edge lengths vs rest OBJ."""
import sys, os, math
def load_obj(path):
vs, faces = [], []
with open(path) as f:
for line in f:
if line.startswith('v '):
p = line.split()
vs.append((float(p[1]), float(p[2]), float(p[3])))
elif line.startswith('f '):
idx = [int(tok.split('/')[0]) - 1 for tok in line.split()[1:]]
for i in range(1, len(idx) - 1):
faces.append((idx[0], idx[i], idx[i + 1]))
return vs, faces
def edge_set(faces):
es = set()
for a, b, c in faces:
for u, v in ((a, b), (b, c), (c, a)):
es.add((u, v) if u < v else (v, u))
return sorted(es)
def dist(p, q):
return math.sqrt((p[0]-q[0])**2 + (p[1]-q[1])**2 + (p[2]-q[2])**2)
d = sys.argv[1]
for hand in ('l', 'r'):
rest_v, rest_f = load_obj(os.path.join(d, f'rest_hand_{hand}.obj'))
edges = edge_set(rest_f)
rest_len = [dist(rest_v[a], rest_v[b]) for a, b in edges]
for pose in ('flat', 'fist', 'grip'):
v, _ = load_obj(os.path.join(d, f'{pose}_hand_{hand}.obj'))
if len(v) != len(rest_v):
print(f'{pose}_hand_{hand}: VERTEX COUNT MISMATCH {len(v)} vs {len(rest_v)}')
continue
ratios = []
for (a, b), rl in zip(edges, rest_len):
if rl <= 1e-9:
continue
ratios.append((dist(v[a], v[b]) / rl, a, b))
ratios.sort(key=lambda t: t[0])
n = len(ratios)
mx = ratios[-1][0]
p999 = ratios[int(n * 0.999)][0]
n2 = sum(1 for r, _, _ in ratios if r > 2)
n3 = sum(1 for r, _, _ in ratios if r > 3)
n5 = sum(1 for r, _, _ in ratios if r > 5)
print(f'{pose}_hand_{hand}: edges={n} max={mx:.2f}x p99.9={p999:.2f}x >2x={n2} >3x={n3} >5x={n5}')
for r, a, b in ratios[-min(max(n3, 3), 8):][::-1]:
pa = [c * 100 for c in v[a]]
rl = dist(rest_v[a], rest_v[b]) * 100
print(f' {r:7.1f}x rest {rl:5.2f}cm -> {r*rl:7.1f}cm at posed ({pa[0]:.1f}, {pa[1]:.1f}, {pa[2]:.1f}) cm')