From eb77b59441173e5034fc40ef1df02a21efcb5032 Mon Sep 17 00:00:00 2001 From: Mirco Mazzoni Date: Mon, 27 Jul 2026 05:10:08 -0700 Subject: [PATCH] Internal changes. PiperOrigin-RevId: 954565492 --- gnm/shape/data/versions/v3_0/gnm_head.npz | Bin 53305389 -> 53305389 bytes gnm/shape/gnm_common.py | 8 ++-- gnm/shape/gnm_xnp.py | 46 +++++++++++++++++----- gnm/shape/visualization/render_gnm.py | 4 +- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/gnm/shape/data/versions/v3_0/gnm_head.npz b/gnm/shape/data/versions/v3_0/gnm_head.npz index 1ddcb04c27d8eb7dc2d3f82bdca1dd335c9fd29b..f76d97e659c33afdc4c084c06246134bbf72d680 100644 GIT binary patch delta 5644 zcmajjcXW;S1IO{)+=Q4xh6Eu*jKq!DF+zgcBWe?SZ)&gFLW3YG6(eS?rbZAuwnmNE zyJqdZwdn8jc2Dl<&!af!{W|&M^L+1da`PnjiQl!+GhSs3t8I30wR3WEvg=r8M#d^` zmX2Mzr?>OA(`OWRH}%20PtNF41-JxX+l{)Lz3|rM@&wsA5{{rCIdL+(iw$ zuznN&b>KE;>+-uq=kj(oOhan@d+HJ0!#j-m4sX9NO%t5+E;L(@&1cvJ`uzWqF1~e{ zw)ZXkrD;Nf@5xT=CPfx9?7ZJiNc|5boQn)9&o0|Ri($8L?|9p;%fSG9b}`8X|6_N2 zx4X%8-0kFu+sP(nuguCpIVRptPLtxV>tnXOOq1VmfOq7$)EA0ye3eF}O>}(aRBkC( zgvO@xFy0Rffc=u^GEB=Bl?9GI<-Wn(oh4AKw}gp~0CFLxVGq zTgUpqqs;z>b>GWlQrC%|k2CLDqGjB*1@0z~nCCN{vm5qdQMNsAyqFr%&V2V{Vxyf4 zd}Zu0dzSM+j?Xg3-Q?xdzFq%r{R4XU9oo2&qn+u~H+V=_+v`Len&qsrsH`fRa#60z zO}VS=%0qdo94e>ErMy&bl}CB2yegmaQTdgxDxeCgLaMOxQ~s)mvZw%6R0XPHs<ZZD@9;&D6rFyGA zs;}y&zEl0x05wnzQiIhHHB=2#!_^2iQhl#RsnKeT8mq>s@oIvas3O!PHCg?jBGnW% zRZUY-YPy=CW~yj4OZ}*3s~Gi@nxkUXTs2S4R|`~}TBsJO#cGLKs+Osr)pE5$tyHVj zYW0hXSHG$?YOPwQ)~f`yL2XoRtv33XDPQm54!byl5I=hX#uQC(7()gS7Lx~i_J>*|KOss2>A z)NOS~-BtJ0ef2;+RFBkS^+Y{Y&(w4ELcLV4)NA!dy;XmyztubSUVTviL>`)Dic(+? zW^e#UNCRoX3DQA&$N(836J!Qw$O2g*8@PZgxS5i4Q!rI^NWIngyA}E5w`Yh?z0{jt zQU~3PMmVP4^@@IR8x-emI-i@Zi+=MK{`@wHTW?u@)x}NGZ;L>~D)3!hkCZ5G>moaN zfG6aDoRAB=AUEUzZ^#Szzz6b!FBE`+PzVZxANWHNus{G5g+M3<#i0b0gi=r%%0Lj5 zg>q0HDnKw)gh~(sp->sBKvnn#szG(A0X3l()P_1x7wSQM2!jUjEi{Bi&={IPQ)mXw zp#`*raA*asp$)W!cF-O=Ku72VouLbKg>KLtdO%O;1-+pU^o4%#9rT9*Fc1d8U>E{J zVHgaD5ik!Ho zF2F^&1ef6txB^$<8eE4Pa1;K7TW}lhz+Jcp_u&CNgh%igp1@Oh2G8LIyo6Wq8s5NL z_zV7qckmuQz(1zQj}=p$621T2LG6KwYQ@^&t!zz_-v48bM=d0!^VA zG=~<@62hSsw1zg&7TQ63=l~s|6Lf|y&=tBtcjy5 z=0GgWg?TU^7C;;ng==sfZop0W6K=t6xC3|L9^8iq@DLusV|W5j;Tb%K7w{5Z!E1N} zZ{aWa8{WZt_yGUd>-J~X7bdU=GdO@Fq=B^H1nD3>WPps22{MB-WPz-Z4P3w#+`t{O zg9ms*4#)|)zzcFi9`J^|kPmzyKlnlcC#P`IC2_?wf0!i$*izU3;PCKhu8!>51iGpgOKEap6n zR%!HK53+0{pQaXbu;C=@!ztTnwnl-5k@c~ZZS+o~ps$U(H~ZX4)~8XnlTtJ)V>s!P zQE+pMxwK(qeF$YcX{AQx4I}FlDBCDU3yazK9Pg9S1dWOtPO?5?vYqr$qhf}U^{J9= z)TpJ!9AFq(A0pXCn>8wH7+Iek*+vD!Kl{D=_`t|Eiq)v3;Uw!*CELhB?-}FESsw}6 zM*TmIKL63qHoC4+u;Kk|{rqPeHEzu}_$w#v(Ws(f^zpM?ob9C2Z7k+c!^ry6W*fz8 TRM{}H{){nli}P%2F}wZ`Tv@)_ delta 5644 zcmajjcT|mk0LSrew+InR3K7XD*&`!l@4fflJA3bt9U>!p?~t8MX7=7Ad++)Cyxrp- z$K&`p=lweU@p+zm=z4B_*X-HszD7A#t7x`!v2k#4uqmE$iet$XD}38_NND3}!yl84 zo6W6-_1mwFsJ`3P}j~_W$zl+*9i zs!}R9<*rhx)GCegP-#^<<*CxE49ZJoRNg9+%B-@etjb6Es%*+nWmh>=PL)gLR(Vuj zl~3hY1(d%ks0yjVs)!0uMO86XTm`BUs-!BVN~3s-!BbDypigrmCwN zs-~)?YO6Y`uBxZ%s|Ko}YNQ&gCaS4wrkbl3s-ZCfWE~=~Q zrn;*hDoFKIy;N`2NA*?xRDU%<4OD~FU^PSyRm0S9HA0P4qts{>tj4IZYMcsDVg{o<4x|*TF)J!!?g{#?Wj+(3HsR%V+El>;9BDGj8QA^b_wOp-GE7dBs zTCGuQ)jG9aZBQFkq}rr5t1T)@ZB^UUcC|z8RJ+t}6|MHDy=tG@uMVh#>X16Dj;I)Q zR2@^t)d_V{ol>#tv^t~Cs&neRx}YwqOX{+^qOPiI>bkn2ZmL`Awz{M4s(b3bdZ6Oe zL-j~KR!`JZ^-MiiFVsu*O1)NZ)LZpVy;mR9NA*d4R$tUt^-XKH*kkk zkQ&l}2c(5`;0fs=19(A3@PYmu6oq0?90H*Pl!Q`H8p=RfC6ZwSLg=ap$7y(Pv`}`p%3(he$XEV zz(5!TgJB2^g<&upM!-lI1*0Jt#=uw@2O%&XCcs3P1e0M3OodRG2Gd~%guzUh1>rCo z=D=K-2N5tI7QjMS1dCw_EQMvT99Fz>uo<>M6l{fUupM^5 zPS^#zAsY6;Uf2iw;Q$Ud3ewac|@3qwzCa?uF*nvI7gZSV82_PXP0!K&;Nx%t`LNZ7W&fo$mz!g%08@NL% zNDXPg1JXh|@Pzb`0lXk1cta-03|Sy6_<%2D13$x0DpZ5&Py=d0EvOB3pf1#d`p^Ix zLL+DlO`s_>gXYizT0$#m4Q-$;w1f800Xjk_=nP$;D|CbI&;x>?C-j2e&F!7v1d!Y~*PBVZ(qg3%BRV_+!eA!Mf^e7( zb6_sag9w-p3t%BEg2k`|mclYv4l7_Ktb*0B2G+tlSPvUuBSgX`*bG}B3bw*F*bX~j zC+vdV5Dj}^FYJT;Z~zX%Avg?2AO?=YF*pt<;3S-aSU3%5;4GYj^Kbz!!X>y2SKumK zgX?euZo)0N4R_!!+=Kh@0OH^wJc7sY1fIe(cn&Y%CA@;y@CM$(J9rNt;3Is3&+rAl z!Z-L1KWz2*GwTZz*n%1Cz#ig3d~kpSkPs4qBP50--~>q_86*d1aDf!y3Ms)2+#waD zhBV*-X(1hWLVCymUXT&IAroYVEaqrE{><*P_!0DJ10Qo9!;hdtZDQN~c6=1kxS@}E z5c6yLBJaQEll&X`n1!!7+P_gY^P^8(rBd zx_;&W!<{ULQ`XT8jf_85|1tWik-y Self: - """Creates a GNM instance from a model data dictionary and array module.""" + """Creates a GNM instance from a model data dictionary and array module.""" init_kwargs = cls._prepare_init_kwargs(model_data, xnp) # pylint: disable=no-value-for-parameter instance = super(GNM, cls).__new__(cls) @@ -257,6 +274,11 @@ def to_numpy_data_dict(self) -> dict[str, Any]: data_dict[field.name] = val return data_dict + @property + def bone_aligned_orientations(self) -> enpt.FloatArray: + """Alias for bone_aligned_template_joint_orientations.""" + return self.bone_aligned_template_joint_orientations + def _check_parameter_shapes( self, identity: enpt.FloatArray['...'] | None = None, @@ -390,6 +412,7 @@ def vertex_positions_world( joints: enpt.FloatArray['A1 ... An J 3'], rotations: enpt.FloatArray['A1 ... An J 3'], translation: enpt.FloatArray['A1 ... An 3'], + **_kwargs, ) -> enpt.FloatArray['A1 ... An V 3']: """Applies linear blend skinning to GNM vertices.""" return gnm_common.linear_blend_skinning( @@ -500,6 +523,7 @@ def vertex_positions_bind_pose( self, identity: enpt.FloatArray['A1 ... An I'], expression: enpt.FloatArray['A1 ... An E'], + **_kwargs, ) -> enpt.FloatArray['A1 ... An V 3']: return gnm_common.vertex_positions_bind_pose( identity, @@ -511,7 +535,7 @@ def vertex_positions_bind_pose( @enp.check_and_normalize_arrays(strict=False) def joint_positions_bind_pose( - self, identity: enpt.FloatArray['A1 ... An I'] + self, identity: enpt.FloatArray['A1 ... An I'], **_kwargs ) -> enpt.FloatArray['A1 ... An J 3']: return gnm_common.joint_positions_bind_pose( identity, @@ -521,7 +545,7 @@ def joint_positions_bind_pose( @enp.check_and_normalize_arrays(strict=False) def compute_pose_correctives( - self, rotations: enpt.FloatArray['A1 ... An J 3'] + self, rotations: enpt.FloatArray['A1 ... An J 3'], **_kwargs ) -> enpt.FloatArray['A1 ... An V 3']: return gnm_common.compute_pose_correctives( rotations, @@ -537,6 +561,7 @@ def joint_transforms_world( joints: enpt.FloatArray['A1 ... An J 3'], rotations: enpt.FloatArray['A1 ... An J 3'], translation: enpt.FloatArray['A1 ... An 3'], + **_kwargs, ) -> enpt.FloatArray['A1 ... An J 4 4']: return gnm_common.joint_transforms_world( joints, rotations, translation, self.joint_parent_indices @@ -579,7 +604,10 @@ def vertex_group_mask( operator, name = name[0], name[1:] if name[0] == '~': inverse, name = True, name[1:] - group_mask = self.vertex_group(name) > threshold + try: + group_mask = self.vertex_group(name) > threshold + except KeyError: + continue if inverse: group_mask = ~group_mask match operator: diff --git a/gnm/shape/visualization/render_gnm.py b/gnm/shape/visualization/render_gnm.py index d63805c2..78926e69 100644 --- a/gnm/shape/visualization/render_gnm.py +++ b/gnm/shape/visualization/render_gnm.py @@ -421,8 +421,8 @@ def get_look_at_world_to_camera( share_camera: np.ndarray | bool = True, y_up: np.ndarray | bool = False, look_at_vertex_groups: Sequence[str] = ('hockey_mask',), - left_vertex_groups: Sequence[str] = ('ears', '&left'), - right_vertex_groups: Sequence[str] = ('ears', '&right'), + left_vertex_groups: Sequence[str] = ('left_ear', 'ears', '&left'), + right_vertex_groups: Sequence[str] = ('right_ear', 'ears', '&right'), forward_vertex_groups: Sequence[str] = ('nose_region',), ) -> np.ndarray: """Compute world-to-camera matrices for a 'look-at' transform.