U
    h(                     @   sv   d Z ddlmZ ddlmZ ddlmZ ddlZddlmZ dd Zd	d
 Z	dd Z
dddZdddZdddZdS )a  
functions about rendering mesh(from 3d obj to 2d image).
only use rasterization render here.
Note that:
1. Generally, render func includes camera, light, raterize. Here no camera and light(I write these in other files)
2. Generally, the input vertices are normalized to [-1,1] and cetered on [0, 0]. (in world space)
   Here, the vertices are using image coords, which centers on [w/2, h/2] with the y-axis pointing to oppisite direction.
Means: render here only conducts interpolation.(I just want to make the input flexible)

Preparation knowledge:
z-buffer: https://cs184.eecs.berkeley.edu/lecture/pipeline

Author: Yao Feng 
Mail: yaofeng1995@gmail.com
    )absolute_import)division)print_functionN)timec                 C   s  |}|dddf |dddf  }|dddf |dddf  }| |dddf  }t |j|}t |j|}t |j|}t |j|}	t |j|}
||	 ||  dkrd}nd||	 ||   }|	| ||
  | }||
 ||  | }|dk|dk@ || dk @ S )a#   Judge whether the point is in the triangle
    Method:
        http://blackpawn.com/texts/pointinpoly/
    Args:
        point: (2,). [u, v] or [x, y] 
        tri_points: (3 vertices, 2 coords). three vertices(2d points) of a triangle. 
    Returns:
        bool: true for in triangle
       Nr      npdotT)point
tri_pointstpv0v1v2dot00dot01dot02dot11dot12	inverDenouv r   S/tmp/pip-unpacked-wheel-5oclok7i/insightface/thirdparty/face3d/mesh_numpy/render.pyisPointInTri   s    
  r   c                 C   s  |}|dddf |dddf  }|dddf |dddf  }| |dddf  }t |j|}t |j|}t |j|}t |j|}	t |j|}
||	 ||  dkrd}nd||	 ||   }|	| ||
  | }||
 ||  | }d| | }|}|}|||fS )a0   Get the weights of the position
    Methods: https://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates
     -m1.compute the area of the triangles formed by embedding the point P inside the triangle
     -m2.Christer Ericson's book "Real-Time Collision Detection". faster.(used)
    Args:
        point: (2,). [u, v] or [x, y] 
        tri_points: (3 vertices, 2 coords). three vertices(2d points) of a triangle. 
    Returns:
        w0: weight of v0
        w1: weight of v1
        w2: weight of v3
     r   Nr   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   w0w1w2r   r   r   get_point_weight;   s$      r    c              
   C   s  t ||gd }t j||gt jdd }t j||dgt jd}t|jd D ]}||ddf }ttt t 	| |df d}	t	tt 
t | |df |d }
ttt t 	| |df d}t	tt 
t | |df |d }|
|	k sN||k rqNt|	|
d D ]}t||d D ]}t||g| |ddf sLq(t||g| |ddf \}}}|| |d df  || |d df   || |d df   }||||f kr(||||f< ||||f< t |||g|||ddf< q(qqN|||fS )a   
    Args:
        vertices: [nver, 3]
        triangles: [ntri, 3]
        h: height
        w: width
    Returns:
        depth_buffer: [h, w] saves the depth, here, the bigger the z, the fronter the point.
        triangle_buffer: [h, w] saves the tri id(-1 for no triangle). 
        barycentric_weight: [h, w, 3] saves corresponding barycentric weight.

    # Each triangle has 3 vertices & Each vertex has 3 coordinates x, y, z.
    # h, w is the size of rendering
        ~.A)Zdtyper      r   Nr   )r	   zerosint32Zfloat32rangeshapemaxintceilminfloorr   r    array)vertices	triangleshwdepth_buffertriangle_bufferbarycentric_weightitriuminumaxvminvmaxr   r   r   r   r   point_depthr   r   r   rasterize_trianglesd   s,    "&"& <(r;   r"   c                 C   s   | j d |j d kstt| |||\}}}t|dg}	t|d|g}
|
ddddtjf }|||	ddf ddf }|| }t|d}t||||g}|S )a   render mesh with colors(rasterize triangle first)
    Args:
        vertices: [nver, 3]
        triangles: [ntri, 3] 
        colors: [nver, 3]
        h: height
        w: width    
        c: channel
    Returns:
        image: [h, w, c]. rendering.
    r   Nr   )r&   AssertionErrorr;   r	   ZreshapeZnewaxissum)r-   r.   colorsr/   r0   cr1   r2   r3   Ztriangle_buffer_flatZbarycentric_weight_flatZweightZcolors_flatimager   r   r   render_colors_ras   s    rB   c              
   C   s&  | j d |j d kstt|||f}t||gd }t|j d D ]}||ddf }	tttt| |	df d}
ttt	t| |	df |d }tttt| |	df d}ttt	t| |	df |d }||
k sH||k rqHt|
|d D ]}t||d D ]}t
||g| |	ddf sHq$t||g| |	ddf \}}}|| |	d df  || |	d df   || |	d df   }||||f kr$||||f< |||	d ddf  |||	d ddf   |||	d ddf   |||ddf< q$qqH|S )z render mesh with colors
    Args:
        vertices: [nver, 3]
        triangles: [ntri, 3] 
        colors: [nver, 3]
        h: height
        w: width    
    Returns:
        image: [h, w, c]. 
    r   r!   Nr   r   )r&   r=   r	   r#   r%   r'   r(   r)   r*   r+   r   r    )r-   r.   r?   r/   r0   r@   rA   r1   r4   r5   r6   r7   r8   r9   r   r   r   r   r   r:   r   r   r   render_colors   s*    "&"& <`rC   nearestc	           #   
   C   s  |j d |j d kst|j \}	}
}t|||f}t||gd }t|j d D ]}||ddf }||ddf }tttt| |df d}ttt	t| |df |d }tttt| |df d}ttt	t| |df |d }||k sT||k rqTt||d D ]}t||d D ]}t
||g| |ddf sfq@t||g| |ddf \}}}|| |d df  || |d df   || |d df   }||||f kr@||||f< |||d ddf  |||d ddf   |||d ddf   }tt|d t|
d d|d< tt|d t|	d d|d< |dkrt|tj}||d |d ddf }n.|dkr|tt	|d tt	|d ddf }|tt	|d tt|d ddf }|tt|d tt	|d ddf }|tt|d tt|d ddf } |d t	|d  }!|d t	|d  }"|d|"  d|!  ||" d|!   |d|"  |!  | |" |!  }||||ddf< q@q,qT|S )	aK   render mesh with texture map
    Args:
        vertices: [nver], 3
        triangles: [ntri, 3]
        texture: [tex_h, tex_w, 3]
        tex_coords: [ntexcoords, 3]
        tex_triangles: [ntri, 3]
        h: height of rendering
        w: width of rendering
        c: channel
        mapping_type: 'bilinear' or 'nearest'
    r   r!   Nr   r   g        rD   Zbilinear)r&   r=   r	   r#   r%   r'   r(   r)   r*   r+   r   r    floatroundZastyper$   )#r-   r.   ZtextureZ
tex_coordsZtex_trianglesr/   r0   r@   Zmapping_typeZtex_hZtex_w_rA   r1   r4   r5   Ztex_trir6   r7   r8   r9   r   r   r   r   r   r:   Ztex_xyZ	tex_valueulurdlZdrZydZxdr   r   r   render_texture   sJ    "&"& <H  

....@rK   )r"   )r"   )r"   rD   )__doc__
__future__r   r   r   Znumpyr	   r   r   r    r;   rB   rC   rK   r   r   r   r   <module>   s   $)/

+