U
    hN                     @   sX   d Z ddlmZ ddlmZ ddlmZ ddlZdd Zdd	 Zdd
dZ	dddZ
dS )am  
Functions about lighting mesh(changing colors/texture of mesh).
1. add light to colors/texture (shade each vertex)
2. fit light according to colors/texture & image.

Preparation knowledge:
lighting: https://cs184.eecs.berkeley.edu/lecture/pipeline
spherical harmonics in human face: '3D Face Reconstruction from a Single Image Using a Single Reference Face Shape'
    )absolute_import)division)print_functionNc           
      C   s  | |dddf ddf }| |dddf ddf }| |dddf ddf }t || || }t | }t|jd D ]}|||df ddf ||ddf  |||df ddf< |||df ddf ||ddf  |||df ddf< |||df ddf ||ddf  |||df ddf< qt |d d}|dk}	d||	< t t |	||	df< |t |ddt jf  }|S )z calculate normal direction in each vertex
    Args:
        vertices: [nver, 3]
        triangles: [ntri, 3]
    Returns:
        normal: [nver, 3]
    Nr         )	npZcross
zeros_likerangeshapesumonessqrtnewaxis)
vertices	trianglesZpt0Zpt1Zpt2Z
tri_normalnormaliZmagZzero_ind r   R/tmp/pip-unpacked-wheel-5oclok7i/insightface/thirdparty/face3d/mesh_numpy/light.py
get_normal   s    
<<>r   c           	      C   s  | j d |j d kst| j d }t| |}tt|tdddf tdddf tdddf tdddf tdddf  tdddf tdddf  tdddf tdddf  tdddf d tdddf d  dtdddf d  d f	}||}|| }|S )a   
    In 3d face, usually assume:
    1. The surface of face is Lambertian(reflect only the low frequencies of lighting)
    2. Lighting can be an arbitrary combination of point sources
    --> can be expressed in terms of spherical harmonics(omit the lighting coefficients)
    I = albedo * (sh(n) x sh_coeff)
    
    albedo: n x 1
    sh_coeff: 9 x 1
    Y(n) = (1, n_x, n_y, n_z, n_xn_y, n_xn_z, n_yn_z, n_x^2 - n_y^2, 3n_z^2 - 1)': n x 9 
    # Y(n) = (1, n_x, n_y, n_z)': n x 4

    Args:
        vertices: [nver, 3]
        triangles: [ntri, 3]
        colors: [nver, 3] albedo
        sh_coeff: [9, 1] spherical harmonics coefficients

    Returns:
        lit_colors: [nver, 3]
    r   Nr   r      )r
   AssertionErrorr   r   arrayr   ndot)	r   r   colorsZsh_coeffnverr   shref
lit_colorsr   r   r   add_light_sh/   s    


r    c                 C   s  | j d }t| |}| tjddddf |ddtjddf  }ttj|d dd}||ddddtjf  }|tjddddf | }	tj|	dd}	|tjddddf |	ddddtjf  |ddtjddf  }
tj|
dd}
|
}tt|dd}|S )a	   Gouraud shading. add point lights.
    In 3d face, usually assume:
    1. The surface of face is Lambertian(reflect only the low frequencies of lighting)
    2. Lighting can be an arbitrary combination of point sources
    3. No specular (unless skin is oil, 23333)

    Ref: https://cs184.eecs.berkeley.edu/lecture/pipeline    
    Args:
        vertices: [nver, 3]
        triangles: [ntri, 3]
        light_positions: [nlight, 3] 
        light_intensities: [nlight, 3]
    Returns:
        lit_colors: [nver, 3]
    r   Nr   )Zaxisr   )r
   r   r   r   r   r   minimummaximum)r   r   r   Zlight_positionsZlight_intensitiesr   ZnormalsZdirection_to_lightsZdirection_to_lights_nZnormals_dot_lightsZdiffuse_outputr   r   r   r   	add_lightN   s    

0Hr#   
   r   c           "      C   s(  | j \}}}	t||}
|j d }|d dd d f }tt|dd d f d|d |dd d f< tt|dd d f d|d |dd d f< t|tj}| |dd d f |dd d f d d f }|j}d}|
dd d f }|
dd d f }|
dd d f }t	||f}tj
}tdd|  t|f |d d df< tdd|  | |d d df< tdd|  | |d d df< tdd|  | |d d df< dtdd|   d|d  |d  |d   |d d df< dtdd	|   ||  |d d df< dtdd	|   ||  |d d d
f< dtdd	|   ||  |d d df< dtdd	|   || ||   |d d df< t|}||	 }t	|df}t	|df}t	d}t|	D ]}|||f d d tjf ||| |d | d d f< t||f d d tjf ||d d f  ||| |d | d d f< t||f d d tjf }|||f d d tjf }|j||j| ||< qt|D ]}| }t|	D ]2}||| |d | d d f  ||   < qt|j||t|  }t|j|}ttj||}t|	D ]h}||| |d | d d f |}||| |d | d d f }|j||j| ||< qDqtt} t|	D ]J}t|t|d d f d d tjf  |||  }!|!j| |d d f< qtt| dd} | S )Nr   r   r   	      r   g      ?            g      ?   )r   r   )r
   r   r   r!   r"   roundZastypeZint32Tzerospir   r   lenr	   r   Ztexturer   copyZeyeZlinalginvr   )"imager   r   r   Zvis_indZlambZmax_iterhwcZnormr   Zpt2dZimage_pixelZharmonic_dimZnxnyZnzZharmonicr/   Z	n_vis_indr   YAlightkZAcZYcr   Zequation_leftZequation_rightalphaZ
appearancetmpr   r   r   	fit_light{   sh    

00**""">***2
6F 0& $
2r>   )r   r   )r$   r   )__doc__
__future__r   r   r   Znumpyr   r   r    r#   r>   r   r   r   r   <module>   s   

-