54 lines
2.1 KiB
Python
54 lines
2.1 KiB
Python
|
|
"""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')
|