U
    8j                     @  s   d Z ddlmZ ddlZddlmZmZmZm	Z	m
Z
mZmZmZmZmZmZ ddddddd	d
ZddddddZdddddZddddddZdddddZdS )u  Parametric layer: emotion + VAD → 52 blendshapes via closed-form functions.

Implementation of docs/research/vad-to-arkit-blendshape-mapping.md §4 & §5.

VAD convention: [-1, 1] scale (native anchor convention).
  V⁺ = max(0, V), V⁻ = max(0, -V), same for A, D.
    )annotationsN   )LIPSYNC_ONLYGAMMA_MOUTH_SMILE_FROWN	GAMMA_EYE
GAMMA_BROW
GAMMA_NOSEVALENCE_EXCLUSION_THRESHOLDDOMINANCE_BROW_CONFLICT_HIGHDOMINANCE_BROW_CONFLICT_LOWAROUSAL_VISIBILITY_GATEAROUSAL_EXTREME_AMP_THRESHOLDAROUSAL_EXTREME_AMP_COEFF皙?float)x	thresholdwidthreturnc                 C  s   t t| | | d ddS )uD   Smooth step from 0 → 1 around `threshold` with `width` transition.      ?              ?)r   npclip)r   r   r    r   _/home/ubuntu/service/kemix-engine/package/face/animasync-face-v3/scripts/compiler/parametric.py
_soft_gate   s    r   )r   gammar   c                 C  s"   | dkrt ttd| |S dS )z4Raise to power only if positive, return 0 otherwise.r   r   )r   r   powermax)r   r   r   r   r   	_pow_safe    s    r    z
np.ndarray)vadr   c           !      C  s  t | d }t | d }t | d }td|}td| }td|}td| }td|}td| }	tjdtjd}
dt|t t|d dt|t |d	krd
nd  }||
d< ||
d< dt|t dt|t d
d|    dt|	t  }t	d
||
d< dt|t dt|	t  }||
d< ||
d< dt|d t|d |dkrZ|dk rZd
nd |
d< dt|t
 t|d	 }||
d< ||
d< dt|d
 }||
d< ||
d< d	t|	t t| d }||
d< ||
d< dt|t t|d }d	t|t }dt|d
 t|d	k rd
nd }t|||}||
d< ||
d< d t|d! }d	t|	t t|d }t	d
|| }||
d"< ||
d#< d$d%t|d
 |d	krd
nd  |
d&< dt|t
 }||
d'< ||
d(< d)t|t
 }||
d*< ||
d+< t	d
dt|t d	t|t |dkrd
nd  }||
d,< ||
d-< dt|t d.t|t  }||
d/< ||
d0< d1t|t
 }||
d2< ||
d3< dt|t |d4k rd
nd }dt|t }d.t|t |d)krd
nd }t	d
t||| } | |
d5< | |
d6< t|
dd
tjS )7zCompute 52 blendshape values from VAD via parametric rules.

    vad: np.ndarray shape (3,) in [-1, 1]
    Returns: np.ndarray shape (52,) in [0, 1]
    r   r      r   4   )dtypeg?皙?g333333?r   g?r   g333333?g?gffffff?      r   g       @gٿ   g?      g      ?   	   
            gffffff?g      ?      g{Gz?gQ?         g      ?      #   $   g333333?)   *   g333333?+   ,   g333333ӿ1   2   )r   r   r   zerosfloat32r    r   r   r   minr   absr   r   astype)!r!   VADZVpZVnZApZAnZDpZDnoutZ	brow_downZbrow_inner_upZbrow_outer_upZcheek_squintZ	eye_blinkZeye_look_downZeye_squint_duchenneZeye_squint_dominanceZeye_squint_relaxZ
eye_squintZeye_wide_arousalZeye_wide_fearZeye_wideZmouth_dimpleZmouth_frownZmouth_pressZmouth_shrugZmouth_smileZnose_disgustZnose_dominanceZnose_arousalZ
nose_sneerr   r   r   parametric_layer%   s    


$(  rI   )bsr!   r   c                 C  sN  t |d }t |d }t |d }|  }|tkrhtdd|t  }|d  |9  < |d  |9  < n>|t krtdd| t  }|d  |9  < |d	  |9  < |tkrtd|t d
 }|d  d| 9  < n|tk rd|d< d|d< |tk rtd|d dt  }	||	9 }|tkr8d|t t	  }
||
9 }t
|ddt
jS )uD   Apply §5.4 conflict resolution rules to a 52-dim blendshape vector.r   r   r"   r   r   r6   r7   r<   r=   r%   )r   copyr	   r   r
   rB   r   r   r   r   r   r   rD   rA   )rJ   r!   rE   rF   rG   rH   Zfrown_scaleZsmile_scaleblendscaleZampr   r   r   apply_conflict_resolution   s2    


rN   )rJ   r   c                 C  s   |   }tD ]}d||< q|S )z;Zero out LIPSYNC_ONLY channels (compiler doesn't own them).r   )rK   r   )rJ   rH   idxr   r   r   apply_channel_mask   s    
rP   )r   )__doc__
__future__r   numpyr   	constantsr   r   r   r   r   r	   r
   r   r   r   r   r   r    rI   rN   rP   r   r   r   r   <module>   s   4 
'