def _get_recommended_pivot_bank(self, geometries, tm_ref, tm_ref_dir, pos_toes, direction=1): """ Determine recommended position using ray-cast from the toes. TODO: If the ray-case fail, use a specified default value. return: The recommended position as a world pymel.datatypes.Vector """ # Sanity check, ensure that at least one point is in the bounds of geometries. # This can prevent rays from being fired from outside a geometry. # TODO: Make it more robust. filtered_geometries = [] for geometry in geometries: xmin, ymin, zmin, xmax, ymax, zmax = cmds.exactWorldBoundingBox(geometry.__melobject__()) bound = pymel.datatypes.BoundingBox((xmin, ymin, zmin), (xmax, ymax, zmax)) if bound.contains(pos_toes): filtered_geometries.append(geometry) dir = pymel.datatypes.Point(direction, 0, 0) * tm_ref_dir pos = libRigging.ray_cast_nearest(pos_toes, dir, filtered_geometries) if not pos: cmds.warning("Can't automatically solve FootRoll bank inn pivot.") pos = pos_toes pos.y = 0 return pos
def _get_bounds_using_raycast(positions, dirs, geometries, parent_tm=None, filter=None): min_x = max_x = min_y = max_y = min_z = max_z = None parent_tm_inv = parent_tm.inverse() # Ray-cast for pos in positions: #x = pos.x #y = pos.y #z = pos.z pos_local = pymel.datatypes.Point(pos) * parent_tm_inv if parent_tm is not None else pos x_local = pos_local.x y_local = pos_local.y z_local = pos_local.z if min_x is None or x_local < min_x: min_x = x_local if max_x is None or x_local > max_x: max_x = x_local if min_y is None or y_local < min_y: min_y = y_local if max_y is None or y_local > max_y: max_y = y_local if min_z is None or z_local < min_z: min_z = z_local if max_z is None or z_local > max_z: max_z = z_local for dir in dirs: ray_cast_pos = libRigging.ray_cast_nearest(pos, dir, geometries, debug=False) if ray_cast_pos is None: continue if parent_tm is not None: ray_cast_pos = ray_cast_pos * parent_tm_inv x = ray_cast_pos.x y = ray_cast_pos.y z = ray_cast_pos.z if min_x is None or x < min_x: min_x = x if max_x is None or x > max_x: max_x = x if min_y is None or y < min_y: min_y = y if max_y is None or y > max_y: max_y = y if min_z is None or z < min_z: min_z = z if max_z is None or z > max_z: max_z = z return min_x, max_x, min_y, max_y, min_z, max_z
def raycast_nearest(self, pos, dir, geos=None): """ Return the nearest point on any of the rig registered geometries using provided position and direction. """ if not geos: geos = self.get_shapes() if not geos: return None result = libRigging.ray_cast_nearest(pos, dir, geos) if not result: return None return result
def _get_bounds_using_raycast(positions, dirs, geometries, parent_tm=None, filter=None): min_x = max_x = min_y = max_y = min_z = max_z = None parent_tm_inv = parent_tm.inverse() # Ray-cast for pos in positions: #x = pos.x #y = pos.y #z = pos.z # Expand bounds using starting positions. pos_local = pymel.datatypes.Point( pos) * parent_tm_inv if parent_tm is not None else pos x_local = pos_local.x y_local = pos_local.y z_local = pos_local.z if min_x is None or x_local < min_x: min_x = x_local if max_x is None or x_local > max_x: max_x = x_local if min_y is None or y_local < min_y: min_y = y_local if max_y is None or y_local > max_y: max_y = y_local if min_z is None or z_local < min_z: min_z = z_local if max_z is None or z_local > max_z: max_z = z_local for dir in dirs: ray_cast_pos = libRigging.ray_cast_nearest(pos, dir, geometries, debug=False) if ray_cast_pos is None: continue if parent_tm is not None: ray_cast_pos = ray_cast_pos * parent_tm_inv x = ray_cast_pos.x y = ray_cast_pos.y z = ray_cast_pos.z if min_x is None or x < min_x: min_x = x if max_x is None or x > max_x: max_x = x if min_y is None or y < min_y: min_y = y if max_y is None or y > max_y: max_y = y if min_z is None or z < min_z: min_z = z if max_z is None or z > max_z: max_z = z return min_x, max_x, min_y, max_y, min_z, max_z