def on_changed(self, which): if not hasattr(self, '_lpl'): self.add_dterm('_lpl', maximum(multiply(a=multiply()), 0.0)) if not hasattr(self, 'ldn'): self.ldn = LightDotNormal(self.v.r.size/3) if not hasattr(self, 'vn'): logger.info('LambertianPointLight using auto-normals. This will be slow for derivative-free computations.') self.vn = VertNormals(f=self.f, v=self.v) self.vn.needs_autoupdate = True if 'v' in which and hasattr(self.vn, 'needs_autoupdate') and self.vn.needs_autoupdate: self.vn.v = self.v ldn_args = {k: getattr(self, k) for k in which if k in ('light_pos', 'v', 'vn')} if len(ldn_args) > 0: self.ldn.set(**ldn_args) self._lpl.a.a.a = self.ldn.reshape((-1,1)) if 'num_verts' in which or 'light_color' in which: # nc = self.num_channels # IS = np.arange(self.num_verts*nc) # JS = np.repeat(np.arange(self.num_verts), 3) # data = (row(self.light_color)*np.ones((self.num_verts, 3))).ravel() # mtx = sp.csc_matrix((data, (IS,JS)), shape=(self.num_verts*3, self.num_verts)) self._lpl.a.a.b = self.light_color.reshape((1,self.num_channels)) if 'vc' in which: self._lpl.a.b = self.vc.reshape((-1,self.num_channels))
def on_changed(self, which): if not hasattr(self, '_lpl'): self.add_dterm('_lpl', maximum(multiply(a=multiply()), 0.0)) if not hasattr(self, 'ldn'): self.ldn = LightDotNormal(self.v.r.size / 3) if not hasattr(self, 'vn'): logger.info( 'LambertianPointLight using auto-normals. This will be slow for derivative-free computations.' ) self.vn = VertNormals(f=self.f, v=self.v) self.vn.needs_autoupdate = True if 'v' in which and hasattr( self.vn, 'needs_autoupdate') and self.vn.needs_autoupdate: self.vn.v = self.v ldn_args = { k: getattr(self, k) for k in which if k in ('light_pos', 'v', 'vn') } if len(ldn_args) > 0: self.ldn.set(**ldn_args) self._lpl.a.a.a = self.ldn.reshape((-1, 1)) if 'num_verts' in which or 'light_color' in which: # nc = self.num_channels # IS = np.arange(self.num_verts*nc) # JS = np.repeat(np.arange(self.num_verts), 3) # data = (row(self.light_color)*np.ones((self.num_verts, 3))).ravel() # mtx = sp.csc_matrix((data, (IS,JS)), shape=(self.num_verts*3, self.num_verts)) self._lpl.a.a.b = self.light_color.reshape((1, self.num_channels)) if 'vc' in which: self._lpl.a.b = self.vc.reshape((-1, self.num_channels))
def mano_inverse_kinematics(mano_hand, desired_zimmerman_coords, plot_progress=False): joint_idxs_mano = np.asarray(range(16)) joint_idxs_zimmerman = MANO_TO_ZIMMERMAN_INDICES[joint_idxs_mano] assert (joint_idxs_zimmerman.shape == joint_idxs_mano.shape) joint_coords_mano = mano_hand.J_transformed[joint_idxs_mano] joint_coords_zimmerman = desired_zimmerman_coords[joint_idxs_zimmerman] mano_coords_centered = joint_coords_mano - joint_coords_mano[0] zimmerman_coords_centered = joint_coords_zimmerman - joint_coords_zimmerman[ 0] zimmerman_coords_centered *= 0.05 if plot_progress: plot_mano_skeleton(mano_coords_centered, zimmerman_coords_centered) tip_idxs_mano = np.asarray([1, 4, 10, 7]) # knuckles (align palms) scale = ch.var(1) mano_coords_scaled = mano_coords_centered * scale position_loss = (mano_coords_scaled[tip_idxs_mano] - zimmerman_coords_centered[tip_idxs_mano])**2 loss = position_loss inputs = [mano_hand.pose[:3], scale] objective = {'loss': loss} opt = {'maxiter': 10} print("Rotating and scaling palms together...") ch.minimize(objective, x0=inputs, method='dogleg', options=opt) bone_idxs = [] for zb0, zb1 in BONES: if zb0 in ZIMMERMAN_TO_MANO_DICT and zb1 in ZIMMERMAN_TO_MANO_DICT: b0 = ZIMMERMAN_TO_MANO_DICT[zb0] b1 = ZIMMERMAN_TO_MANO_DICT[zb1] bone_idxs.append([b0, b1]) bone_idxs = np.asarray(bone_idxs) zimmerman_displacements = zimmerman_coords_centered[ bone_idxs[:, 1]] - zimmerman_coords_centered[bone_idxs[:, 0]] mano_displacements = mano_coords_scaled[ bone_idxs[:, 1]] - mano_coords_scaled[bone_idxs[:, 0]] displacement_loss = ch.sum( ch.multiply(zimmerman_displacements, mano_displacements)) regularization_loss = 1e-5 * ch.sum(mano_hand.pose[3:]**2) # MAGIC HAPPENING RIGHT HERE: # This huge number is important. # Apparently, ch.minimize will attempt to push the loss to zero, # not towards minus infinity. # Here we're trying to maximize the dot product of all bones # in both hands (thereby making them all point in the same # direction). The dot product needs to be maximally positive, # and should not be zero, hence the huge number below. loss = (1000000 - displacement_loss) + regularization_loss inputs = [mano_hand.pose[3:]] opt = {'maxiter': 10} objective = {'loss': loss} print("Aligning all bones to be co-linear...") ch.minimize(objective, x0=inputs, method='dogleg', options=opt) if plot_progress: plot_mano_skeleton(mano_coords_scaled, zimmerman_coords_centered)