
    j                    d   d Z ddlmZ ddlZddlZddlmZ ed         Zed         Z	ed         Z
ed	         Zed
         Zed         Zed         Zed         Zed         Zed         Zed         Zed         Zed         Zed         Zd6dZ	 d7d8d"Zd9d#Z	 	 	 	 d:d;d*Z	 	 	 	 d<d=d1Z	 	 	 	 d>d?d5ZdS )@ac  Natural eye motion: blinks + subtle iris tremor.

Final-pass post-processor for compiled blendshape targets. Adds:
  1. Periodic blinks (Poisson-distributed, suppressed during emotional eye peaks)
  2. Subtle iris drift (low-frequency smoothed noise on eye-look channels)

Deterministic per scenario: same scenario_id always produces the same eye motion.
    )annotationsN   )NAME_TO_IDXeyeBlinkLefteyeBlinkRighteyeLookDownLefteyeLookDownRighteyeLookInLefteyeLookInRighteyeLookOutLefteyeLookOutRighteyeLookUpLefteyeLookUpRighteyeSquintLefteyeSquintRighteyeWideLefteyeWideRightseed_strstrreturnnp.random.Generatorc                    t          j        |                     d                                                    }t          j                            t          |dd         d                    S )z;Deterministic RNG from arbitrary string (e.g. scenario_id).zutf-8N   )hashlibmd5encode	hexdigestnprandomdefault_rngint)r   hs     S/dataset/kemix-engine/package/face/animasync-face-v3/scripts/compiler/eye_motion.py_seeded_rngr$   !   sO    HOOG,,--7799A9  QssVR111          ?   Tr!   rngfreq_hzfloatfps
np.ndarrayc                   t          dt          ||z                      }|                    | |z             }t          j        t          j        |dd                    }||d         |d|          z
  |z  }|d|          }|                                }|dk    r||z  }|                    t          j                  S )u   Generate length-T noise band-limited around freq_hz.

    Method: white noise → moving average whose window matches the period.
    Result drifts smoothly at ~freq_hz, no high-frequency jitter.
       r   Ngư>)	maxr!   standard_normalr   cumsuminsertstdastypefloat32)	r(   r)   r*   r,   windowrawcssmoothedss	            r#   _smoothed_noiser<   '   s     Cg&&''F


a&j
)
)C	29S!Q''	(	(B677b6'l*f4H|HA4xxa<??2:&&&r%   c                 F    t          j        g dt           j                  S )uS  5-frame triangular blink shape, peak 0.70 at center frame.

    Was 0.95 (ARKit-standard "fully closed eye"). Visual review on the
    Ready Player Me / Wolf3D avatar showed 0.95 looked like squeezing the
    eyes shut tightly — not a natural blink. The avatar's visible blink
    lives on the `eyesClosed` morph; at 0.95 that morph is near its tight-
    closure end of travel. Peak 0.70 gives a relaxed natural blink shape
    that reads correctly on this avatar.

    Values scaled proportionally from the original [0.30, 0.75, 0.95,
    0.75, 0.30] by 0.70/0.95 = 0.737, then rounded.
    ))\(?皙?gffffff?r?   r>   )dtype)r   arrayr6    r%   r#   _blink_kernelrC   ;   s"     8222"*EEEEr%         @333333?targetmean_interval_swide_suppresssquint_suppressc                |   |                                  j        d         t          |dz             }t                      t	                    }|dz  ||z  }t          t          dz            t          d|z                      }	t          |                    t          dz   t          z
  dz
  |	                                        }
d}dfd}|
z
  k     ri ||
          r|dz  }|	                    |          }t          t          j        |d|z  d|z                      }|
t          |          z  }
|
z
  k     i|dk    r^t          d|z            k    rH|                    t          j        z
                      D ]} |t          |                    r nS )zAdd Poisson-distributed blinks. Only suppressed when the preset is
    holding the eyes very wide (strong surprise) or hard-squinted (peak
    anger/laughter). Moderate squint (anger ~0.6) still allows blinks.r   z::blink   333333?g       @r   centerr!   r   boolc                   t          d| 	z
            t          | 	z   dz             }}t          ||t          f                                          ||t          f                                                    }t          ||t          f                                          ||t
          f                                                    }|k     r|k     r}t          
          D ]k\  }}| 	z
  |z   }d|cxk    rk     rQn t          |t          f         |          |t          f<   t          |t          f         |          |t          f<   ldS dS )Nr   r   TF)	r0   min
IDX_WIDE_L
IDX_WIDE_RIDX_SQUINT_LIDX_SQUINT_R	enumerateIDX_BLINK_LIDX_BLINK_R)rM   lohiwidesquintikfir(   halfkerneloutrI   rH   s           r#   
_try_blinkzadd_blinks.<locals>._try_blinka   sY   Q&&Av}q/@(A(AB3r"uj()--//RUJ5F1G1K1K1M1MNNSB,-1133SB9L5M5Q5Q5S5STT-F_$<$<!&)) H H1d]Q&;;;;Q;;;;;+.s2{?/CQ+G+GCK(+.s2{?/CQ+G+GCK(4ur%   r&   g       @)rM   r!   r   rN   )copyshaper$   rC   lenr0   r!   integersrP   exponentialr+   r   clippermutationarange)rF   r   r,   rG   rH   rI   r)   klenmean_frames	first_maxtblink_countrb   gaprM   r(   r_   r`   ra   s       ``         @@@@r#   
add_blinksrq   K   s    ++--C	!A
h*
+
+C__Fv;;D19D!C'KCaLL#cCi..11ICLLs4!8STAy-I-IJJKKLLAK           a$h,,:a== 	1Kook**BGCsC#I6677	SXX a$h,, aAS3Y//oobia$h&?&?@@ 	 	Fz#f++&&  Jr%   ~jt?Mb?rL   	horiz_ampvert_ampdrift_hzc                   |                                  }|j        d         }t          |dz             }t          ||||          |z  }	t          ||||          |z  }
t	          j        |	dd          }t	          j        |	 dd          }t	          j        |
dd          }t	          j        |
 dd          }t	          j        |ddt          f         |          |ddt          f<   t	          j        |ddt          f         |          |ddt          f<   t	          j        |ddt          f         |          |ddt          f<   t	          j        |ddt          f         |          |ddt          f<   t	          j        |ddt          f         |          |ddt          f<   t	          j        |ddt          f         |          |ddt          f<   t	          j        |ddt          f         |          |ddt          f<   t	          j        |ddt          f         |          |ddt          f<   t	          j        |dd                              t          j                  S )zAdd subtle continuous iris drift on the eyeLook channels.

    Both eyes stay synchronized (no cross-eyed). Amplitude is intentionally
    small (~0.04 of [0,1] range) so it reads as life, not as looking around.
    r   z::iris)r*   r,   Ng        g      ?)rc   rd   r$   r<   r   rh   maximumIDX_LOOK_IN_LIDX_LOOK_OUT_RIDX_LOOK_OUT_LIDX_LOOK_IN_RIDX_LOOK_UP_LIDX_LOOK_UP_RIDX_LOOK_DOWN_LIDX_LOOK_DOWN_Rr5   r6   )rF   r   r,   rt   ru   rv   ra   r(   r)   r"   vh_posh_negv_posv_negs                  r#   add_iris_tremorr      sD    ++--C	!A
h)
*
*C3c:::YFA3c:::XEAGAq$EGQB4  EGAq$EGQB4  E
 Js111m+;'<eDDC=ZAAA~,=(>FFC>ZAAA~,=(>FFC>Js111m+;'<eDDC= Js111m+;'<eDDC=Js111m+;'<eDDC= jQQQ-?)@%HHC? jQQQ-?)@%HHC?73S!!((444r%   blink_interval_siris_horiz_ampiris_vert_ampc                T    t          | |||          }t          |||||          }|S )z6Convenience wrapper: blinks + iris tremor in one pass.)r,   rG   )r,   rt   ru   )rq   r   )rF   r   r,   r   r   r   ra   s          r#   apply_eye_motionr      sB    
 VX3@P
Q
Q
QC
#xS$2]L L LCJr%   )r   r   r   r   )r&   r'   )
r(   r!   r)   r   r*   r+   r,   r!   r   r-   )r   r-   )r'   rD   rE   rE   )rF   r-   r   r   r,   r!   rG   r+   rH   r+   rI   r+   r   r-   )r'   rr   rs   rL   )rF   r-   r   r   r,   r!   rt   r+   ru   r+   rv   r+   r   r-   )r'   rD   rr   rs   )rF   r-   r   r   r,   r!   r   r+   r   r+   r   r+   r   r-   )__doc__
__future__r   r   numpyr   	constantsr   rV   rW   r   r   ry   r|   r{   rz   r}   r~   rS   rT   rQ   rR   r$   r<   rC   rq   r   r   rB   r%   r#   <module>r      s    # " " " " "      " " " " " " .)/*/001O,,--../O,,-?++,'
(
2 2 2 2 79' ' ' ' '(F F F F  >@(+&*(,3 3 3 3 3l CE',&+&)#5 #5 #5 #5 #5L DF03.3-2      r%   