diff --git a/data-pipeline/scripts/mannequin-asset/repose_and_export.py b/data-pipeline/scripts/mannequin-asset/repose_and_export.py index 894ac9c..3aef207 100644 --- a/data-pipeline/scripts/mannequin-asset/repose_and_export.py +++ b/data-pipeline/scripts/mannequin-asset/repose_and_export.py @@ -39,32 +39,44 @@ def repose_arms(obj): centerline_x = sum(v.co.x for v in mesh.vertices) / len(mesh.vertices) shoulder_z = z_min + 0.84 * height - # comfortably above o alargamento do pe/tornozelo, abaixo de onde a mao - # fica nesta pose relaxada — deixa uma folga clara entre perna e braço - arm_low_z = z_min + 0.30 * height + # A mao termina de forma bem abrupta por volta de z=0.705-0.71 nesta + # escala (medido amostrando a malha por fatias de altura — ver + # diagnose2.py no historico) — abaixo disso so existe coxa. Uma janela + # mais larga aqui (ex: baseada só numa fracao generica da altura) pega + # vertice de coxa por engano e deforma a perna inteira, porque eles + # entram na rotacao rigida em torno do pivo do OMBRO. + arm_hand_low_z = z_min + 0.417 * height # ~0.705 pra este mesh especifico torso_half_width = 0.20 # metade da largura biacromial aproximada, nesta escala + # Angulo residual: parar EXATAMENTE na vertical faz a mao encostar (ou + # atravessar) a coxa. Deixar uma pequena abducao residual dá uma folga + # natural, como nas referências de posição anatômica. + residual = math.radians(5.0) for side in (1, -1): - pivot_x = centerline_x + side * torso_half_width * 0.85 + pivot_x = centerline_x + side * torso_half_width * 0.95 candidates = [ v for v in mesh.vertices if side * (v.co.x - centerline_x) > torso_half_width - and arm_low_z < v.co.z < shoulder_z - 0.02 + and arm_hand_low_z < v.co.z < shoulder_z - 0.02 ] far = max( candidates, key=lambda v: (v.co.x - pivot_x) ** 2 + (v.co.z - shoulder_z) ** 2, ) - angle = math.atan2(far.co.x - pivot_x, -(far.co.z - shoulder_z)) + measured_angle = math.atan2(far.co.x - pivot_x, -(far.co.z - shoulder_z)) + angle = measured_angle - side * residual for v in mesh.vertices: dx = v.co.x - centerline_x if side * dx <= 0 or v.co.z >= shoulder_z + 0.03: continue weight_x = smoothstep(torso_half_width * 0.7, torso_half_width * 1.15, abs(dx)) - weight_z = smoothstep(arm_low_z - 0.08, arm_low_z + 0.07, v.co.z) + # janela estreita: cheia bem em cima da mao, zero já na coxa — + # a transição real na malha é abrupta (não gradual), então uma + # rampa larga aqui é o que causava a contaminação da perna. + weight_z = smoothstep(arm_hand_low_z - 0.015, arm_hand_low_z + 0.005, v.co.z) weight = weight_x * weight_z if weight <= 0.001: continue diff --git a/frontend/public/mannequin/body-male-realistic.glb b/frontend/public/mannequin/body-male-realistic.glb index 79f4ea5..5bb837c 100644 Binary files a/frontend/public/mannequin/body-male-realistic.glb and b/frontend/public/mannequin/body-male-realistic.glb differ