
    +jL                        d Z ddlZddlZddlZddlmZmZmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZ ddlmZmZmZmZmZ ddlZdd	lmZ  ej        d
          Z ej        d          Zdej        dej        fdZdej        dej        fdZ  G d dej!                  Z" G d dej!                  Z# G d dej!                  Z$ G d dej!                  Z% G d dej!                  Z& G d de          Z'de'fdZ(dS )zNComfyUI nodes for the native MoGe (Monocular Geometry Estimation) integration.    N)ComfyExtensionTypesio)override)turbo)	MoGeModel)triangulate_grid_mesh)get_panorama_camerassplit_panorama_imagemerge_panorama_depthspherical_uv_to_directions_uv_grid)tqdm
MOGE_MODELMOGE_GEOMETRYpointsreturnc                    t          j        |                               d          }t          j        |                    d          | t          j        |                     }|dddddddf         |dddddddf         z
  }|dddddddf         |dddddddf         z
  }t           j        j                            |	                    ddd	d          d
          	                    dddd	          }t           j        j                            |	                    ddd	d          d          	                    dddd	          }t          j
        ||d          }t           j        j                            |d          }t          j        |                    d          |t          j        |                    S )zICamera-space surface normals from a (B, H, W, 3) point map (v1 fallback).dim.N   r         )r   r   r   r   )r   r   r   r   )torchisfiniteallwhere	unsqueeze
zeros_likenn
functionalpadpermutecross	normalize)r   finiteptsdxdyns         7/home/wildlama/comfy/ComfyUI/comfy_extras/nodes_moge.py_normals_from_pointsr.      s   ^F##''B'//F
+f&&r**FE4DV4L4L
M
MC	S!!!QRR]	c#qqq#2#qqq.1	1B	S!""aaa]	c#ssAAAqqq.1	1B			 	 Aq!Q!7!7	F	F	N	NqRSUVXY	Z	ZB			 	 Aq!Q!7!7	F	F	N	NqRSUVXY	Z	ZBB###A%%aR%00A;v''++Q0@0C0CDDD    depthc                 z   t          j        |           }t          | j        d                   D ]
}| |         }t          j        |          |dk    z  }|                                s;t          j        |d|                    d          z  t          j        |                    }||         }t          j        |d          }t          j        |d          }||z
                      d          }	||z
  |	z  	                    dd          }
t          j        ||
t          j        |
                    ||<   |S )zIPer-batch normalize 1/depth to [0, 1] using 0.1/99.9 percentile clipping.r         ?gư>gMbP?g+?        )
r   r!   rangeshaper   anyr   	clamp_minquantileclamp)r0   outidvaliddisp
disp_validlohiscalenorms              r-   _normalize_disparityrD   -   s   

5
!
!C5;q>"" B B!Hq!!QU+yy{{ 	{5#D(9(9"95;KA;N;NOO%[
^J..^J..b##D))e#**344UD%*:4*@*@AAAJr/   c                   J    e Zd Zed             Zedej        fd            ZdS )LoadMoGeModelc                     t          j        dddt           j                            dt	          j        d                    gt                                          g          S )NrF   zLoad MoGe Modelzmodel/loaders
model_namegeometry_estimation)options)node_iddisplay_namecategoryinputsoutputs)r   SchemaComboInputfolder_pathsget_filename_listMoGeModelTypeOutputclss    r-   define_schemazLoadMoGeModel.define_schema@   s^    y#*$|\5STi5j5jkk #))++,
 
 
 	
r/   r   c                     t          j        d|          }t          j                            |d          }t          j        t          |                    S )NrI   T)	safe_load)rS   get_full_path_or_raisecomfyutilsload_torch_filer   
NodeOutputr   )rX   rH   pathsds       r-   executezLoadMoGeModel.executeL   sE    23H*UU[(((>>}Yr]]+++r/   N__name__
__module____qualname__classmethodrY   r   r`   rc    r/   r-   rF   rF   ?   sV        	
 	
 [	
 ,BM , , , [, , ,r/   rF   c                   N    e Zd ZdZed             Zedej        fd            ZdS )MoGePanoramaInferencea  Equirectangular panorama inference: split into 12 perspective views, run
    MoGe at fov_x=90 on each, merge via multi-scale Poisson + gradient solve.
    v2's predicted normals and metric scale are ignored (per-view scales would not align across seams).
    c                    t          j        dg ddddt                              d          t           j                            dd	          t           j                            d
dddd          t           j                            ddddd          t           j                            ddddd          t           j                            ddddd          gt                              d          g          S ) Nrk   )mogepanoramar0   geometrydepth estimationgeometry estimationzRun MoGe Panorama Inferenceimage/geometry estimationzRun MoGe on an equirectangular panorama by splitting it into 12 perspective views, running inference on each, and merging the results into a single depth map.
moge_modelimagez&Equirectangular panorama (any aspect).)tooltipresolution_level	   r   z1Per-view detail (0 = fastest, 9 = most detailed).defaultminmaxru   split_resolutioni      i   z%Resolution of each perspective split.merge_resolutioni  i    z9Long-side resolution of the merged equirect distance map.
batch_size   r      z,Views per inference batch (12 splits total).moge_geometryrL   )rK   search_aliasesrL   rM   descriptionrN   rO   )r   rP   rU   rR   ImageIntMoGeGeometryrV   rW   s    r-   rY   z#MoGePanoramaInference.define_schemaY   s   y+ooo60 y##L11w0XYY/q%X  Z Z/#4%L  N N/3D%`  b b\1!%S  U U "((o(FFG%
 
 
 	
r/   r   c                   ()*+ |j         d         dk    rt          d|j         d          d          |dd df         }t          |j         d                   t          |j         d                   }}t          |t	          ||          z  d          }	t	          t          ||	z            d	          t	          t          ||	z            d	          }}
t                      \  }}t          j                            |j	                   |j
        }|d                             d
d                              ||j                  }t          ||||          }|j         d         }g }||
}}	 |                    ||f           t	          ||          dk    rn|dz  |dz  }}7|                                 d t#          |          D             *|t%          |          z  }t'          *                                          }t          j                            ||z   |z             )d(g }g }t/          |d          5 +t1          d||          D ]%}||||z            }|                    ||dddd          }|                    t7          |d                                                             d
                                                                                               |                    t7          |d                                                                                              |j         d         }(|z  ()                     (           +!                    |           '	 d d d            n# 1 swxY w Y   t/          ||z   d          5 +()+fd}+fd}()*+fd}tE          ||
||t7          |          ||||	  	        \  } }!d d d            n# 1 swxY w Y   tG          j$        |           } tG          j$        |!          }!|
|f||fk    rtF          j%        j&        '                    | d         ||fdd          (                                } tF          j%        j&        '                    |!d                                         ||fd !          (                                dk    }!|!)                                rH|!*                                s4tG          j+        | |!         d"          d#z  }"tG          j,        |!| |"          } tG          j$        t[          t]          ||                              }#|#| d$         z  /                    d          }$| /                    d          }%|!/                    d          }&|$|%|&|                                d%}'ta          j1        |'          S )&Nr   r   z9MoGePanoramaInference takes a single image (got batch of ).r   r   r2       r   devicedtypeTr}   c                      i | ]\  }}|d |z  S )r   ri   ).0r;   whs      r-   
<dictcomp>z1MoGePanoramaInference.execute.<locals>.<dictcomp>   s"    HHHuq"AFHHHr/   zMoGe panorama inferencetotaldescg     V@F)rv   fov_xforce_projection
apply_maskapply_metric_scaler   r   maskMoGe panorama merge: viewsc                  f     dz                                                        d           d S )Nr   )update_absoluteupdate)donepbartqs   r-   _on_merge_viewz5MoGePanoramaInference.execute.<locals>._on_merge_view   s3    	$$T***		!r/   c                 >                         d|  d|            d S )NzMoGe panorama merge: solving x)set_description)whr   s     r-   _on_solve_startz6MoGePanoramaInference.execute.<locals>._on_solve_start   s.    ""#J1#J#Jq#J#JKKKKKr/   c                     | |f         }|z                                                      |                               d           d S )Nr   )r   r   r   )r   r   weightr   r   solve_weightr   s      r-   _on_solve_endz4MoGePanoramaInference.execute.<locals>._on_solve_end   s[    %q!f-$$T***		&!!!""#?@@@@@r/   )on_viewon_solve_starton_solve_end)NNbilinear)sizemodealign_cornersnearest)r   r   gffffff?g      @).N)r   r0   r   rt   )2r5   
ValueErrorintrz   r{   r
   r]   model_managementload_model_gpupatcherload_devicemovedimtor   r   appendreverse	enumeratelensumvaluesr^   ProgressBarr   r4   inferextendlistfloatrC   cpunumpyr   r   r   r   
from_numpyr"   r#   interpolatesqueezer6   r   r8   r   r   r   r    r   r`   ),rX   rs   rt   rv   r|   r~   r   HWrB   merge_hmerge_w
extrinsics
intrinsicsr   img_chwsplitsn_viewsmerge_levelsw_h_n_merge_view_unitsn_merge_solve_unitsdistance_mapsmasksr;   batchresultr,   r   r   r   
pano_depth	pano_maskfar
directionsr   r0   r   r   r   r   r   r   s,                                           @@@@r-   rc   zMoGePanoramaInference.executep   s    ;q>QjY^YdefYgjjjkkkc2A2g5;q>""CA$7$71$s1ayy0#66s1u9~~r22CAI4K4K!5!7!7
J--j.@AAA'(""2r**--V:CS-TT%gz:GWXX,q/ /1'B	&R)))2r{{c!!1WbAgB		&
 	HH	,0G0GHHH$s<'8'88!,"5"5"7"788{&&w1C'CFY'YZZ &?@@@ 	B1gz22  qZ/0#))%BR04t5:u * V V $$T&*:*@*@*B*B*G*GB*G*O*O*S*S*U*U*[*[*]*]%^%^___T&."4"4"6"6"<"<">">??@@@KN	$$T***		!	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 *-@@Gcddd 	dhj      L L L L LA A A A A A A A %9-Z8H8H*&Ub%d %d %d!J	%	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d 	d, %j11
$Y//	W!Q'',88J9OWXZ[V\cm  ~C8  D  D  L  L  N  NJ+77	*8M8S8S8U8U]^`a\bir7ss{{}}  AB  BI ==?? 	A9==?? 	A.I!6==CCY
C@@J%&@!Q&P&PQQ
z)44??BB$$Q''""1%% $*E4RWR[R[R]R]^^}]+++s%    D9NN
N
%=O..O25O2N	re   rf   rg   __doc__rh   rY   r   r`   rc   ri   r/   r-   rk   rk   S   sk         
 
 
 [
, ],momz ], ], ], [], ], ],r/   rk   c                   J    e Zd Zed             Zedej        fd            ZdS )MoGeInferencec                 :   t          j        dg ddddt                              d          t           j                            d          t           j                            dd	d
d	d          t           j                            ddddddd          t           j                            ddddd          t           j                            ddd          t           j                            dddd          gt          	                    d          g           S )!Nr   )rm   r0   ro   rp   rq   zRun MoGe Inferencez:Run MoGe on a single image to estimate depth and geometry.rr   rs   rt   rv   rw   r   z0 = fastest, 9 = most detail.rx   fov_x_degreesr3   g     @e@g?TzHorizontal field of view of the source camera. Sets the focal length used to unproject the depth map into 3D. 0 = auto-recover from the predicted points.)ry   rz   r{   stepadvancedru   r   r   r   @   zHImages per inference call. Lower if you OOM on a long video / image set.r   )ry   r   r   zSet masked-out (sky / invalid) pixels to inf in points and depth so meshing culls them. Disable to keep the raw predicted geometry everywhere; the mask is still returned separately.)ry   r   ru   r   r   rK   r   rL   r   rM   rN   rO   )
r   rP   rU   rR   r   r   FloatBooleanr   rV   rW   s    r-   rY   zMoGeInference.define_schema   s,   y#ccc-T0##L11w''/q%D  F F%VYdh (C  D D\1!%o  q q
  !3TD QQ
  td *a ! b b "((o(FFG'
 
 
 	
r/   r   c                    |dd df         }|                     dd                                          }|j        d         }	|dk    rd nt          |          }
t          j                            |	          }g t          |	d          5 }t          d|	|          D ]}||||z            }	                    |
                    |||
||                     |                    t          ||z   |	                     |                    |j        d                    	 d d d            n# 1 swxY w Y   fd	}d
|                                i}dD ]} ||          }||||<   t          j        |          S )N.r   r   r   r   zMoGe inferencer   )rv   r   r   r   c                 V      fdD             }|rt          j        |d          nd S )Nc                 (    g | ]}|v |         S ri   ri   )r   cfields     r-   
<listcomp>z8MoGeInference.execute.<locals>.stack.<locals>.<listcomp>   s"    ;;;

AeH


r/   r   r   )r   cat)r   valschunkss   ` r-   stackz$MoGeInference.execute.<locals>.stack   s<    ;;;;f;;;D-1;59Tq))))t;r/   rt   )r   r0   r   r   normal)r   
contiguousr5   r   r]   r^   r   r   r4   r   r   r   rz   r   r   r   r`   )rX   rs   rt   rv   r   r   r   r   bchwBfovr   r   r;   chunkr   r   r   vr   s                      @r-   rc   zMoGeInference.execute   s    c2A2g}}R$$//11JqM#q((ddeM.B.B{&&q)) 0111 	*R1a,, * *Qq:~-.j..uGW_b@P]g / i i j j j$$SZ%;%;<<<		%+a.))))*	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	*	< 	< 	< 	< 	< !%))++.H 	) 	)EeA}'(e$}]+++s   BD..D25D2Nrd   ri   r/   r-   r   r      s\        
 
 [
. ,vx  wD , , , [, , ,r/   r   c                   N    e Zd ZdZed             Zedej        fd            ZdS )
MoGeRenderz;Render a visualization or mask from a MOGE_GEOMETRY packet.c                     t          j        dg ddddt                              d          t           j                            dg dd	d
          gt           j                                        g          S )Nr  )rm   renderro   r0   r   zRender MoGe Geometryz3Render a depth map or normal map from geometry datarr   r   output)r0   depth_colorednormal_openglnormal_directxr   r0   zDirectX vs OpenGL controls the normal-map green-channel convention. DirectX: green = -Y down (Unreal). OpenGL: green = +Y up (Blender, Substance, Unity, glTF).)rJ   ry   ru   r   )r   rP   r   rR   rQ   r   rV   rW   s    r-   rY   zMoGeRender.define_schema  s    y LLL/M0""?33x1v1v1v  AH ~   
 X__&&'
 
 
 	
r/   r   c                    |dv }|                     d          }|dv rd|vrt          d          |d         }n_|r)d|v r	|d         }nPd|v r	|d         }nCt          d          |d	k    rd	|vrt          d
          |d	         }nt          d|           |j        d         }t          j                            |          }g }t          |d|           5 }	t          |          D ]~}
||
|
dz                                            }|dv rqt          |          }|
                    |dk    rt          |          n8 |                    d          j        g |j        dR                                             n|rfd|v r|nt          |          }|rdnd}||                    d|dg          z  }|
                    |dz  dz                       dd                     nR|d	k    rL|
                     |                    d          j        g |j        dR                                             |                    |
dz              |	                    d           	 d d d            n# 1 swxY w Y   t)          j        |d                              t          j                                        t          j                                                  }t5          j        |          S )N)r  r  _opengl)r0   r  r0   z"moge_geometry has no depth output.r   r   zDmoge_geometry has neither normals nor points to derive normals from.r   z!moge_geometry has no mask output.zUnknown output mode: r   zMoGe render: r   r   r  r   r         r2   g      ?r3   r   r   )endswithr   r5   r]   r^   r   r   r4   r   rD   r   _turbor    expandr   r.   
new_tensorr9   r   r   r   r   r   r   intermediate_deviceintermediate_dtyper   r`   )rX   r   r  	is_normalopenglsrcr   r   r:   r   r;   slcr<   r,   y_signr   s                   r-   rc   zMoGeRender.execute  s   AA	++ ///m++ !EFFF(CC 	?=((#H-]**#H- !ghhhv]** !DEEE'CC=V==>>>IaL{&&q))"$ 8 8 8999 	R1XX  !AE'l((**777,S11AJJFo,E,Evayyy$:AKKOO$:$GAG$GQ$G$G$G$R$R$T$TV V V V U'=88>RSV>W>WA%+4TTFALL#vt)<===AJJC#44S#>>????v%%JJ7s}}R007FFAFFFQQSSTTT$$QU+++		!	 	 	 	 	 	 	 	 	 	 	 	 	 	 	" 3A&&&))1G1[1[1]1]eje{  fO  fO  fQ  fQ)  R  R}V$$$s   FI88I<?I<Nr   ri   r/   r-   r  r    s\        EE
 
 [
 ,%r} ,% ,% ,% [,% ,% ,%r/   r  c                   N    e Zd ZdZed             Zedej        fd            ZdS )MoGePointMapToMeshzLTriangulate one image of a MoGe point map into a Types.MESH (UVs + texture).c                    t          j        dg ddddt                              d          t           j                            dddd	d
          t           j                            ddddd          t           j                            dddddd          t           j                            ddd          gt           j                                        g          S )Nr  )rm   meshro   z	point mapzConvert MoGe Point Map to Meshz(Convert a MoGe point map into a 3D mesh.rr   r   batch_indexr   i   zWhich image of a batched MoGe geometry to mesh. Per-image vertex counts differ, so batches can't be stacked into a single MESH.rx   
decimationr      z#Vertex stride; 1 = full resolution.discontinuity_thresholdg{Gz?r3   r2   g{Gz?z@Drop pixels whose 3x3 depth span exceeds this fraction. 0 = off.)ry   rz   r{   r   ru   textureTz8Carry the source image through as the baseColor texture.)ry   ru   r   )	r   rP   r   rR   r   r   r   MeshrV   rW   s    r-   rY   z MoGePointMapToMesh.define_schemaN  s    y(DDD9B0""?33]A1$&_  ` ` \1!%J  L L8$CUX_c'i  k k
  D)c ! e e W^^%%&%
 
 
 	
r/   r   c                    d|vrt          d          |d         }|j        d         }||k    rt          d| d| d          d|v r|d         |         nd }t          ||         |||          \  }	}
}|	j        d         dk    s|
j        d         dk    rt          d	          d
|vr!|	d d g df                                         }	n@|	t	          j        g d|	j                  z  }	|
d d g df                                         }
|r|d         ||dz            nd }t          j        |		                    d          |
	                    d          |	                    d          |          }t          j        |          S )Nr   z#moge_geometry has no points output.r   zbatch_index z, out of range; moge_geometry has batch size .r0   )r  r  r0   zOMoGe produced an empty mesh; try discontinuity_threshold=0 or apply_mask=False.r   )r   r   r   )r2   r  r  )r   )r   r   r   rt   r   )verticesfacesuvsr  )r   r5   r	   r   r   tensorr   r   MESHr    r   r`   )rX   r   r  r  r  r  r   r   
edge_depthvertsr$  r%  texr  s                 r-   rc   zMoGePointMapToMesh.executee  s   =((BCCCx(LO!iKiiefiiijjj =D}<T<T]7+K88Z^
1;J$;:
 
 
uc ;q>Q%+a.A"5"5nooo},,!!!YYY,'2244EE EL):):):%+NNNNE!!!YYY,'2244EELVmG$[q%@AARVz__Q''//!$$a  	
 
 
 }T"""r/   Nr   ri   r/   r-   r  r  K  s^        VV
 
 [
, !#bdbo !# !# !# [!# !# !#r/   r  c                   L    e Zd Zedeeej                          fd            ZdS )MoGeExtensionr   c                 F   K   t           t          t          t          t          gS N)rF   r   rk   r  r  )selfs    r-   get_node_listzMoGeExtension.get_node_list  s      }.CZQcddr/   N)	re   rf   rg   r   r   typer   	ComfyNoder0  ri   r/   r-   r,  r,    sL        eT$r|*<%= e e e Xe e er/   r,  c                  "   K   t                      S r.  )r,  ri   r/   r-   comfy_entrypointr4    s      ??r/   ))r   r   comfy.utilsr]   rS   comfy_api.latestr   r   r   typing_extensionsr   comfy.ldm.colormapr   r  comfy.ldm.moge.modelr   comfy.ldm.moge.geometryr	   comfy.ldm.moge.panoramar
   r   r   r   r   comfy.model_management	tqdm.autor   CustomrU   r   Tensorr.   rD   r2  rF   rk   r   r  r  r,  r4  ri   r/   r-   <module>r@     s   T T          6 6 6 6 6 6 6 6 6 6 & & & & & & . . . . . . * * * * * * 9 9 9 9 9 9 K  K  K  K  K  K  K  K  K  K  K  K  K  K          	,''ry))E E%, E E E E     $, , , , ,BL , , ,({, {, {, {, {,BL {, {, {,|4, 4, 4, 4, 4,BL 4, 4, 4,n@% @% @% @% @% @% @% @%F<# <# <# <# <# <# <# <#~e e e e eN e e e      r/   