Something like this, but not that the pitch assumption is WRONG. Positive pitch values mean looking down.
def is_looking_at(pos_a, pitch_a, yaw_a, pos_b, threshold_deg=45):
"""
Check if Player A is looking at Player B within a certain angle threshold.
Args:
pos_a: (x, y, z) of player A
pitch_a: pitch of player A in degrees
yaw_a: yaw of player A in degrees
pos_b: (x, y, z) of player B
threshold_deg: angle threshold in degrees to consider "looking at"
Returns:
True if A is looking at B, False otherwise
"""
# Convert angles to radians
pitch = np.radians(pitch_a)
yaw = np.radians(yaw_a)
# Forward vector from pitch and yaw (Z-up system)
# Assumes:
# - yaw 0 = facing +X
# - yaw 90 = +Y
# - pitch 0 = level, positive = up
direction = np.array([
np.cos(pitch) * np.cos(yaw), # X
np.cos(pitch) * np.sin(yaw), # Y
np.sin(pitch) # Z
])
# Normalize direction vector
direction /= np.linalg.norm(direction)
# Vector from A to B
to_b = np.array(pos_b) - np.array(pos_a)
to_b /= np.linalg.norm(to_b)
# Compute angle between view direction and vector to B
dot_product = np.clip(np.dot(direction, to_b), -1.0, 1.0)
angle_deg = np.degrees(np.arccos(dot_product))
# print(angle_deg)
return angle_deg <= threshold_deg
Something like this, but not that the pitch assumption is WRONG. Positive pitch values mean looking down.