o
    ۷iŘ                  	   @   s  d dl Z d dlmZ d dlZd dlZd dlm  mZ	 d dlmZ ddl
mZmZ ddlmZ ddlmZ dd	lmZ d
ejdedejfddZd>dejdededejfddZdd Zd?ddZdedefddZdd Zdd Zdejfd d!Zd"ejd#eeeef fd$d%ZG d&d' d'ej Z!eG d(d) d)Z"G d*d+ d+ej Z#G d,d- d-ej Z$G d.d/ d/ej Z%eG d0d1 d1eZ&G d2d3 d3ej Z'eG d4d5 d5eZ(G d6d7 d7eeZ)G d8d9 d9ej Z*G d:d; d;eeZ+G d<d= d=eeZ,dS )@    N)	dataclass)nn   )ConfigMixinregister_to_config)
ModelMixin)
BaseOutput   )create_pan_cameraspmf	n_samplesreturnc                 C   st   | j ^ }}}|dksJ tj| d|dd}t|tj|j d ||jd}|jg ||dR  d|d S )a>  
    Sample from the given discrete probability distribution with replacement.

    The i-th bin is assumed to have mass pmf[i].

    Args:
        pmf: [batch_size, *shape, n_samples, 1] where (pmf.sum(dim=-2) == 1).all()
        n_samples: number of samples

    Return:
        indices sampled with replacement
    r	   dimr   device)shapetorchcumsumviewsearchsortedrandr   clamp)r   r   r   support_sizelast_dimcdfinds r   Y/home/ubuntu/vllm_env/lib/python3.10/site-packages/diffusers/pipelines/shap_e/renderer.py
sample_pmf   s
    $r       xmin_degmax_degc                 C   s   ||kr| S dt j||| j| jd }| j^ }}| dd||ddd jg |dR  }|jd |||  ks<J t j||tj	d  gdd
 }t j| |gddS )z~
    Concatenate x and its positional encodings, following NeRF.

    Reference: https://huggingface.co/papers/2210.04628
    g       @)dtyper   r   r	   )axisr   )r   aranger%   r   r   reshaper   catmathpisin)r"   r#   r$   scalesr   r   xbembr   r   r   posenc_nerf4   s   , r0   c                 C   s   t | dddS )Nr   r!   r#   r$   )r0   positionr   r   r   encode_positionE   s   r4   c                 C   s*   |d u rt t| dddS t|dddS )Nr      r1   )r   
zeros_liker0   )r3   	directionr   r   r   encode_directionI   s   r8   c                 C   s   |  ddS )N.__)replacer"   r   r   r   _sanitize_nameP   s   r=   c              
   C   s   |  |\}}}|| }tj|dd}t|ddddf  }dt|  }	ttjt|dddddf |dddddf  gdd}
|	|
 }tj|| dd}|||fS )a  
    Function integrating the model output.

    Args:
        volume_range: Specifies the integral range [t0, t1]
        ts: timesteps
        density: torch.Tensor [batch_size, *shape, n_samples, 1]
        channels: torch.Tensor [batch_size, *shape, n_samples, n_channels]
    returns:
        channels: integrated rgb output weights: torch.Tensor [batch_size, *shape, n_samples, 1] (density
        *transmittance)[i] weight for each rgb output at [..., i, :]. transmittance: transmittance of this volume
    )
    r   .r   N      ?r	   )	partitionr   r   expr)   r6   sum)volume_rangetsdensitychannels_dtddensitymasstransmittancealphasTsweightsr   r   r   integrate_samplesT   s   D
rO   c                 C   s   t j|d | jjd}|| }t j||dd| }t j||d dd| }t j|||gdd}| |d  | j| j  | j S )Nr   r   trunc)rounding_mode   r	   r   )r   r'   bbox_minr   divstackfloatbbox_max)volume	grid_sizeindiceszsysxscombinedr   r   r   volume_query_pointsv   s   "r_   uc                 C   s"   t | dk| d | d d d S )Ng?ܵ?gףp=
)@g)\(?gzG?g333333@r   where)r`   r   r   r   _convert_srgb_to_linear   s   "rc   flat_cube_indicesrY   c                 C   s  |d d |d  |d  }|}|d |d d  |d  }|| }t j| d d df |d  |d  | d d df |d   | d d df  | d d df |d  |d  | d d df d |d   | d d df  | d d df |d  |d  | d d df |d   | d d df  d | d d df |d  |d  | d d df d |d   | d d df  d || d d df |d d  |d   | d d df |d   | d d df  || d d df d |d d  |d   | d d df |d   | d d df  || d d df |d d  |d   | d d df |d   | d d df  d || d d df d |d d  |d   | d d df |d   | d d df  d || d d df |d  |d d   | d d df |d d   | d d df  || d d df d |d  |d d   | d d df |d d   | d d df  || d d df |d  |d d   | d d df d |d d   | d d df  || d d df d |d  |d d   | d d df d |d d   | d d df  gddS )Nr   r	   rR   r   r   )r   rU   )rd   rY   num_xsy_offsetnum_ysz_offsetr   r   r   _create_flat_edge_indices   s   "&"&"&"&Eri   c                       s*   e Zd ZdZd fdd	Zdd Z  ZS )VoidNeRFModelz`
    Implements the default empty space model where all queries are rendered as background.
         o@c                    s>   t    ttt|jtj	d| }| 
d| d S )Nr%   
background)super__init__r   	Parameterr   
from_numpynparraytofloat32register_buffer)selfrm   channel_scale	__class__r   r   ro      s   
$zVoidNeRFModel.__init__c                 C   sl   | j d  |j}|jd d }dgt|d  }|jd }t|j|jd g||R  g ||}|S )Nr   r	   r   )rm   rt   r   r   lenr   broadcast_tor   )rw   r3   rm   r   ones
n_channelsr   r   r   forward   s   
,zVoidNeRFModel.forward)rk   )__name__
__module____qualname____doc__ro   r   __classcell__r   r   ry   r   rj      s    rj   c                   @   s<   e Zd ZU ejed< ejed< ejed< dd Zdd ZdS )	VolumeRanget0t1intersectedc                 C   s,   | j j| jj  kr| jjksJ  J d S N)r   r   r   r   )rw   r   r   r   __post_init__   s   ,zVolumeRange.__post_init__c                 C   s   |dddddf |dddddf  d }t j| jddddf |gdd}t j|| jddddf gdd}|| }|j|j  krR|j  krR|jksUJ  J |||fS )ar  
        Partitions t0 and t1 into n_samples intervals.

        Args:
            ts: [batch_size, *shape, n_samples, 1]

        Return:

            lower: [batch_size, *shape, n_samples, 1] upper: [batch_size, *shape, n_samples, 1] delta: [batch_size,
            *shape, n_samples, 1]

        where
            ts \in [lower, upper] deltas = upper - lower
        .r	   Nr         ?r>   r   )r   r)   r   r   r   )rw   rD   midslowerupperdeltar   r   r   r@      s   0"".
zVolumeRange.partitionN)r   r   r   r   Tensor__annotations__r   r@   r   r   r   r   r      s   
 


r   c                       sX   e Zd ZdZddddedef fddZ			
ddejdejdejd	B fddZ  Z	S )BoundingBoxVolumezH
    Axis-aligned bounding box defined by the two opposite corners.
            MbP?)min_distmin_t_ranger   r   c                   sn   t    || _|| _t|| _t|| _t| j| jg| _	| j	j
dks)J |dks/J |dks5J dS )z
        Args:
            bbox_min: the left/bottommost corner of the bounding box
            bbox_max: the other corner of the bounding box
            min_dist: all rays should start at least this distance away from the origin.
        rR   r   r   N)rn   ro   r   r   r   tensorrS   rW   rU   bboxr   )rw   rS   rW   r   r   ry   r   r   ro     s   
zBoundingBoxVolume.__init__Nư>originr7   t0_lowerc                 C   sH  |j ^}}}dgt| }| jjdg|ddR  |j}	ddd}
|
|	|ddddf  |ddddf |d	}|jd
djjdddj	| j
}|jd
djjdddj}|j |j   krm|g|dR kspJ  J |dur|j |j ks|J t||}|| j |k }t||t|}t||t|}t|||dS )a  
        Args:
            origin: [batch_size, *shape, 3]
            direction: [batch_size, *shape, 3]
            t0_lower: Optional [batch_size, *shape, 1] lower bound of t0 when intersecting this volume.
            params: Optional meta parameters in case Volume is parametric
            epsilon: to stabilize calculations

        Return:
            A tuple of (t0, t1, intersected) where each has a shape [batch_size, *shape, 1]. If a ray intersects with
            the volume, `o + td` is in the volume for all t in [t0, t1]. If the volume is bounded, t1 is guaranteed to
            be on the boundary of the volume.
        r	   rR   r   r   c                 S   s   | t |dk || ||  S Nr   ra   )abepsilonr   r   r   _safe_divideD  s   z1BoundingBoxVolume.intersect.<locals>._safe_divide.N)r   r>   r   r   Tr   keepdim)r   r   r   )r   )r   r{   r   r   rt   r   minvaluesmaxr   r   r   maximumr   rb   r6   	ones_liker   )rw   r   r7   r   r   
batch_sizer   rG   r}   r   r   rD   r   r   r   r   r   r   	intersect+  s   $
.",zBoundingBoxVolume.intersect)Nr   )
r   r   r   r   rV   ro   r   r   r   r   r   r   ry   r   r     s$    	r   c                   @   sH   e Zd ZdZddefddZ	ddejdejd	ed
e	dejf
ddZ
dS )StratifiedRaySamplerz_
    Instead of fixed intervals, a sample is drawn uniformly at random from each interval.
    linear
depth_modec                 C   s   || _ | j dv s
J dS )z
        :param depth_mode: linear samples ts linearly in depth. harmonic ensures
            closer points are sampled more densely.
        )r   	geometricharmonicN)r   )rw   r   r   r   r   ro   e  s   zStratifiedRaySampler.__init__r   r   r   r   r   r   c                 C   sF  dgt |jd  }tdd|jg ||R  |j|j}| jdkr1|d|  ||  }n7| jdkrM|	|
 d|  |	|
 |   }n| jdkrhdd|	| d|  d|	| |   }d|ddd	f |dd	d
f   }tj||gd
d}tj||gd
d}	td t|}
|	||	 |
  }|d
S )  
        Args:
            t0: start time has shape [batch_size, *shape, 1]
            t1: finish time has shape [batch_size, *shape, 1]
            n_samples: number of ts to sample
        Return:
            sampled ts of shape [batch_size, *shape, n_samples, 1]
        r	   r   r   r?   r   r   r   .Nr   r   )r{   r   r   linspacer   rt   r%   r   r   r   logrA   r)   manual_seed	rand_like	unsqueeze)rw   r   r   r   r   r}   rD   r   r   r   t_randr   r   r   samplem  s   .

.
,$


zStratifiedRaySampler.sampleN)r   )r   )r   r   r   r   strro   r   r   intrV   r   r   r   r   r   r   `  s    r   c                   @   s`   e Zd ZdZ		ddedejdejdedef
d	d
Z	e
 dejdejdedejfddZdS )ImportanceRaySamplerzp
    Given the initial estimate of densities, this samples more from regions/bins expected to have objects.
    Fh㈵>rC   rD   rN   	blur_poolalphac                 C   s2   || _ |  | _|  | _|| _|| _dS )am  
        Args:
            volume_range: the range in which a ray intersects the given volume.
            ts: earlier samples from the coarse rendering step
            weights: discretized version of density * transmittance
            blur_pool: if true, use 2-tap max + 2-tap blur filter from mip-NeRF.
            alpha: small value to add to weights.
        N)rC   clonedetachrD   rN   r   r   )rw   rC   rD   rN   r   r   r   r   r   ro     s
   
zImportanceRaySampler.__init__r   r   r   r   c                 C   s|  | j | j\}}}| jj^}}}	}| j}
| jretj|
dddddf |
|
dddddf gdd}t|dddddf |dddddf }d|dddddf |dddddf   }
|
| j	 }
|
|
j
ddd	 }t||}|j|g||dR ksJ |d
k r||	k  sJ tj|j|jd}t|d|}t|d|}||| |  }tj|ddj}|S )r   .Nr	   r   r>   r   r   Tr   r   r   )rC   r@   rD   r   rN   r   r   r)   r   r   rB   r    allr   r   gathersortr   )rw   r   r   r   r   r   rG   r   r   n_coarse_samplesrN   paddedmaxesr   r   r   lower_upper_rD   r   r   r   r     s$   
800

zImportanceRaySampler.sampleN)Fr   )r   r   r   r   r   r   r   boolrV   ro   no_gradr   r   r   r   r   r   r     s"    	
&r   c                   @   s8   e Zd ZU dZejed< ejed< eeejf ed< dS )MeshDecoderOutputax  
    A 3D triangle mesh with optional data at the vertices and faces.

    Args:
        verts (`torch.Tensor` of shape `(N, 3)`):
            array of vertext coordinates
        faces (`torch.Tensor` of shape `(N, 3)`):
            array of triangles, pointing to indices in verts.
        vertext_channels (Dict):
            vertext coordinates for each color channel
    vertsfacesvertex_channelsN)	r   r   r   r   r   r   r   dictr   r   r   r   r   r     s
   
 

r   c                       s<   e Zd ZdZ fddZdejdejdejfddZ  ZS )	MeshDecoderz\
    Construct meshes from Signed distance functions (SDFs) using marching cubes method
    c                    sL   t    tjdddtjd}tjddtjd}| d| | d| d S )N      r   rl   casesmasks)rn   ro   r   zeroslongr   rv   )rw   r   r   ry   r   r   ro     s
   
zMeshDecoder.__init__field	min_pointsizec               	   C   s4  t |jdksJ d|j}| j|}| j|}||}||}|j}t||}|dktj}	|	ddddddf |	ddddddf d> B }	|	ddddddf |	ddddddf d> B }	|	ddddddf |	ddddddf d> B }	tj	g |dR ||j
d	}
tj|d ||j
d	ddddf |
t|d dddddf< tj|d ||j
d	dddf |
ddt|d dddf< tj|d ||j
d	|
ddddt|d df< tj|
dd |
dd  d dd|
ddddf |
ddddf  d dd|
ddddddf |
ddddddf  d ddgdd
}tj|d d |d d |d d d|tjd	}tj|d d |dddddf |t|d d dddddf< tj|d d |ddddf |ddt|d d dddf< tj|d d |d|ddddt|d d df< |dd}t||}|	d }|| }|| }t|d||jd d|j}|dd|d }t|d}|| }tjt ||tjd	}tjt ||tjd	||< t|d|d|j}t|tj}t|tj}||dddf |dddf |dddf f }||dddf |dddf |dddf f }| |d  | | }| |d  | | }|||  dddf }|| d| |  }t||ddS )aI  
        For a signed distance field, produce a mesh using marching cubes.

        :param field: a 3D tensor of field values, where negative values correspond
                    to the outside of the shape. The dimensions correspond to the x, y, and z directions, respectively.
        :param min_point: a tensor of shape [3] containing the point corresponding
                        to (0, 0, 0) in the field.
        :param size: a tensor of shape [3] containing the per-axis distance from the
                    (0, 0, 0) field corner and the (-1, -1, -1) field corner.
        r   zinput must be a 3D scalar fieldr   Nr   r	   rR      r   r%   r   r   )r   r   r   )r{   r   r   r   rt   r   r   r   uint8emptyr%   r'   ranger)   r(   r   r   ri   r   uniquer   floorceilrV   r   ) rw   r   r   r   devr   r   rY   grid_size_tensorbitmaskscorner_coordsedge_midpointscube_indicesrd   edge_indicesflat_bitmasks
local_trislocal_masksglobal_trisselected_trisused_vertex_indicesused_edge_midpointsold_index_to_new_indexr   v1v2s1s2p1p2tr   r   r   r   r     st   

888 
 2"2>
&DB6

22zMeshDecoder.forward)	r   r   r   r   ro   r   r   r   r   r   r   ry   r   r     s    $r   c                   @   s6   e Zd ZU ejed< ejed< ejed< ejed< dS )MLPNeRFModelOutputrE   signed_distancerF   rD   N)r   r   r   r   r   r   r   r   r   r   r   X  s
   
 


r   c                       sZ   e Zd Ze					ddededed	ed
ef
 fddZdd ZdddddZ  Z	S )MLPNeRSTFModelr         swishr   d_hiddenn_outputn_hidden_layersact_fninsert_direction_atc                    s   t    tdd}t|djd }t|djd }|g| }	|g|	 }
|	|g }|d ur6|
|  |7  < tdd t	|
|D | _
|dkrNdd	 | _ntd
| tj| _tjjj| _tj| _d S )Nr	   r   r2   r   c                 S   s   g | ]
\}}t ||qS r   )r   Linear).0d_ind_outr   r   r   
<listcomp>z  s    z+MLPNeRSTFModel.__init__.<locals>.<listcomp>r   c                 S   s
   t | S r   )Fsilur<   r   r   r   <lambda>  s   
 z)MLPNeRSTFModel.__init__.<locals>.<lambda>z Unsupported activation function )rn   ro   r   eyer4   r   r8   r   
ModuleListzipmlp
activation
ValueErrortanhsdf_activation
functionalreludensity_activationsigmoidchannel_activation)rw   r   r   r   r   r  dummyd_posenc_posd_posenc_dir
mlp_widthsinput_widthsoutput_widthsry   r   r   ro   a  s    
	


zMLPNeRSTFModel.__init__c                    s,   ddddddd} fdd	|  D }|S )
N)r   r	   )r	   rR   r   )r   r   )r   	   )r  r   )sdfdensity_coarsedensity_finestfnerf_coarse	nerf_finec                    s&   i | ]\}\}}| d ||f qS ).r   )r  kstartendoutputr   r   
<dictcomp>  s   & z6MLPNeRSTFModel.map_indices_to_keys.<locals>.<dictcomp>)items)rw   r(  h_mapmapped_outputr   r'  r   map_indices_to_keys  s   	z"MLPNeRSTFModel.map_indices_to_keyscoarsenerf)
nerf_levelrendering_modec                C   s  t |}|}d }t| jD ]/\}	}
|	| jjkr(|}t||d}tj||gdd}|
|}|}|	t| jd k r<| 	|}q|}|d u rE|}| 
|}|dkrS|d }n|d }|dkri|dkrd|d	 }n|d
 }n|dkrq|d }| |}| |d }| |}t||||dS )N)r7   r   r   r	   r.  r  r   r/  r"  r#  r!  r  )rE   r   rF   rD   )r4   	enumerater  configr  r8   r   r)   r{   r  r-  r  r  r  r   )rw   r3   r7   rD   r0  r1  hh_preacth_directionlessilayerh_directionh_finalr  	h_density
h_channelsrE   r   rF   r   r   r   r     s<   






zMLPNeRSTFModel.forward)r   r   r   r   r   )
r   r   r   r   r   r   ro   r-  r   r   r   r   ry   r   r   `  s(    %r   c                       s@   e Zd Zdededef fddZdejdejfdd	Z  ZS )
ChannelsProjvectorsrF   d_latentc                   s>   t    t||| | _t|| _|| _|| _|| _	d S r   )
rn   ro   r   r  proj	LayerNormnormr?  r>  rF   )rw   r>  rF   r?  ry   r   r   ro     s   

zChannelsProj.__init__r"   r   c                 C   sV   |}| j j| j| j| j}| j jd| j| j}td||}| 	|}|| }|S )Nr	   zbvd,vcd->bvc)
r@  weightr   r>  rF   r?  biasr   einsumrB  )rw   r"   x_bvdw_vcdb_vcr4  r   r   r   r     s   
zChannelsProj.forward)	r   r   r   r   ro   r   r   r   r   r   r   ry   r   r=    s    r=  c                       sX   e Zd ZdZedddddee deee  def fd	d
Zde	j
fddZ  ZS )ShapEParamsProjModelz
    project the latent representation of a 3D asset to obtain weights of a multi-layer perceptron (MLP).

    For more details, see the original paper:
    znerstf.mlp.0.weightznerstf.mlp.1.weightznerstf.mlp.2.weightznerstf.mlp.3.weight)r   ]   r   r   rM  rM     param_namesparam_shapesr?  rP  rQ  r?  c                   sb   t    t|t|krtdti | _t||D ]\}\}}t|||d| jt	|< qd S )Nz;Must provide same number of `param_names` as `param_shapes`)r>  rF   r?  )
rn   ro   r{   r  r   
ModuleDictprojectionsr  r=  r=   )rw   rP  rQ  r?  r$  r>  rF   ry   r   r   ro     s   
zShapEParamsProjModel.__init__r"   c           
      C   sx   i }d}t | jj| jjD ],\}}|\}}|| }|d d ||f }	| jt| |	jt|g|R  ||< |}q|S r   )r  r3  rP  rQ  rS  r=   r(   r{   )
rw   r"   outr%  r$  r   r>  rG   r&  rF  r   r   r   r     s   (zShapEParamsProjModel.forward)r   r   r   r   r   tupler   r   ro   r   r   r   r   r   r   ry   r   rI    s    
	rI  c                       s   e Zd Zeddddddddd	d
	dee deee  dededededededee f fddZe	
 d'ddZe	
 				d(dedefdd Ze	
 			!d)d"ed#ed$efd%d&Z  ZS )*ShapERendererrJ  rK  rN  r   r   r   r   r   )rk   rk   rk   )	rP  rQ  r?  r   r   r   r   r  rm   rP  rQ  r?  r   r   r   r   r  rm   c       	   
         s\   t    t|||d| _t|||||| _t|	dd| _tg dg dd| _	t
 | _d S )NrO  rk   )rm   rx   )r?   r?   r?   )      rW  rW  )rW   rS   )rn   ro   rI  params_projr   r  rj   voidr   rX   r   mesh_decoder)
rw   rP  rQ  r?  r   r   r   r   r  rm   ry   r   r   ro     s   
zShapERenderer.__init__NFc                 C   s  |ddddf |ddddf }}| j j||dd}||j|j|}	|	|j}	|dur?tjtj	|	|j
gddddj}	|jj^}
}}|	j^}}}t|d|
g|d}|d|	|  }|| jj}|| jj}|rw|nd}| j|||	|du rd	nd
d}t||j
|j|j\}}}t|j|t|}t|j|t|}||| |  }t||j
|d}|||fS )a|  
        Perform volumetric rendering over a partition of possible t's in the union of rendering volumes (written below
        with some abuse of notations)

            C(r) := sum(
                transmittance(t[i]) * integrate(
                    lambda t: density(t) * channels(t) * transmittance(t), [t[i], t[i + 1]],
                ) for i in range(len(parts))
            ) + transmittance(t[-1]) * void_model(t[-1]).channels

        where

        1) transmittance(s) := exp(-integrate(density, [t[0], s])) calculates the probability of light passing through
        the volume specified by [t[0], s]. (transmittance of 1 means light can pass freely) 2) density and channels are
        obtained by evaluating the appropriate part.model at time t. 3) [t[i], t[i + 1]] is defined as the range of t
        where the ray intersects (parts[i].volume \ union(part.volume for part in parts[:i])) at the surface of the
        shell (if bounded). If the ray does not intersect, the integral over this segment is evaluated as 0 and
        transmittance(t[i + 1]) := transmittance(t[i]). 4) The last term is integration to infinity (e.g. [t[-1],
        math.inf]) that is evaluated by the void_model (i.e. we consider this space to be empty).

        Args:
            rays: [batch_size x ... x 2 x 3] origin and direction. sampler: disjoint volume integrals. n_samples:
            number of ts to sample. prev_model_outputs: model outputs from the previous rendering step, including

        :return: A tuple of
            - `channels`
            - A importance samplers for additional fine-grained rendering
            - raw model output
        .r   Nr	   )r   r>   r   r   r.  fine)r3   r7   rD   r0  )rD   rN   )rX   r   r   r   r   rt   r%   r   r   r)   rD   r   r   r|   r   r  rO   rE   rF   rb   r   r   r6   rY  r   )rw   rayssamplerr   prev_model_outrender_with_directionr   r7   vrangerD   r   _shape_t0_dimrG   ts_shape_ts_dim
directions	positionsoptional_directions	model_outrF   rN   rK   weighted_samplerr   r   r   render_rays8  s6   & 

zShapERenderer.render_rays@         r   ray_batch_sizec                 C   s  |  |}| j  D ]\}}	d| | v r&|	|d|  d qt|}
|
j}|	|}|j
d | }t }g }t|D ]-}|d d || |d | f }| |||\}}}| j||||d\}}}|| qCtj|dd}|jg |
j
|
j|
jdR  d}|S )Nnerstf.r   r	   )r^  r   r   )rX  r  
state_dictr*  keyscopy_squeezer
   camera_raysrt   r   r   r   rj  appendr   r)   r   heightwidth)rw   latentsr   r   rn  r   n_fine_samplesprojected_paramsnameparamcamerar\  	n_batchescoarse_samplerimagesidx
rays_batchrG   fine_samplercoarse_model_outrF   r   r   r   decode_to_image  s*   

 (zShapERenderer.decode_to_imageRGBrY   query_batch_sizetexture_channelsc                    s  |  |}| j  D ]\}}d| | v r&||d|  d qt| j|}	|	d  	dddj
|| jjd}
g }td|
jd |D ]}|
d d ||| f }| j|d d ddd}||j qHtj|dd}| }t|jd	kr|jd
 dksJ d|j |jdg|gd	 R  }tjd|d |d |d |j|jd}|d ||d d dd
dd
dd
f< |}g }g }|D ]}| || jj| jj| jj }|d || qtj||jd}tdd |D  tj fdd|D dd}|j
|| jjd}g }td|jd |D ]}|d d ||| f }| j|d d ddd}||j qtj|dd}t|}| }t|jd	krT|jd
 t|ks\J d|j t ||D ]\}}|d t|j! }t"t ||#d
|_$qa|d S )Nro  r   r	   r   r[  r!  )r3   r7   rD   r0  r1  r   r   r   z9expected [meta_batch x inner_batch] SDF results, but got rR   rW  Tr   c                 s   s    | ]}t |jV  qd S r   )r{   r   r  mr   r   r   	<genexpr>  s    z/ShapERenderer.decode_to_mesh.<locals>.<genexpr>c                    s(   g | ]}|j td  t|j   qS )r   )r   r   r'   r{   r  max_verticesr   r   r    s   ( z0ShapERenderer.decode_to_mesh.<locals>.<listcomp>zNexpected [meta_batch x inner_batch x texture_channels] field results, but got )%rX  r  rp  r*  rq  rr  rs  r_   rX   repeatrt   r%   r   r   ru  r   r   r)   rV   r{   r(   r   r   fill_rZ  rS   rW   r   r   rU   rF   rc   r  r   r   unbindr   )rw   rx  r   rY   r  r  rz  r{  r|  query_pointsquery_positionsfieldsr  query_batchrh  	full_grid
raw_meshes	mesh_maskr   raw_meshtexture_query_positionstexturestexture_model_outr  texturer   r  r   decode_to_mesh  sz   

 


 

&
zShapERenderer.decode_to_mesh)NF)rk  rl  rk  rm  )rm  rl  r  )r   r   r   r   rU  r   r   rV   ro   r   r   rj  r  r  r   r   r   ry   r   rV    sj    
	'N,rV  )r   r!   r   )-r*   dataclassesr   numpyrr   r   torch.nn.functionalr   r  r  configuration_utilsr   r   modelsr   utilsr   r}  r
   r   r   r    r0   r4   r8   r   r=   rO   r_   rc   rU  ri   Modulerj   r   r   r   r   r   r   r   r   r=  rI  rV  r   r   r   r   <module>   sL    
"	
R T4=tc2