Find if one player is visible to the other

Two players (p1 and p2) are standing in a 3D space, represented by points (x1, y1, z1) and (x2, y2, z2). Player 2 is holding a light source, pointing in the direction given by a normalised vector (xn, yn, zn). Given an angle cone (between 0 and 360) and a limiting distance max to which p2 can see with the light source, how can I determine if p1 is visible to p2.

• There are three sub-problems here. 1. calculate the sightline between the two actors, 2. determine if the sightline is within the light cone angle and 3. determine if that sightline is unobstructed. Do you need help with all three of these problems or can you solve one or two of them on your own? – Philipp Dec 23 '18 at 19:11
• Thanks for your comment Philipp. I need help with all the three steps. Please help me understand the physics. Also assume there are no other objects in the universe to obstruct vision. – rranjik Dec 23 '18 at 19:25
• Assuming that there are no other objects removes the need to explain step three :) – Philipp Dec 23 '18 at 19:45
• Yes, I don't have to do step 3. If you point me to sources from where I can learn this math, I would like to do this myself. This is what I feel intuitively: Project a line of length max, from p2, in the direction of vector n. I should have a circle of some radius (that I don't know) with the end point of this line as centre. p2 can see p1 if the angle between p1 and p2 is less that this conical angle and the perpendicular distance from p1 to this line less than the thickness of the cone at that point. I can imagine a picture, but I don't how to write this concrete math terms. – rranjik Dec 23 '18 at 20:33

The dot product of two unit vectors gives you the cosine of the angle between them, so if your angle is measured from the central axis to the outside of the cone you can check it like this:

(or if you measure the angle edge-to-edge, half it first)

bool IsIlluminated (Vector3 source, Vector3 target, Vector3 lookDirection, float angleDegrees, float maxDistance) {

// Compute vector from source to target.
Vector3 offset = target - source;

// Find its length, and fail if it's too long.
float squareMagnitude = Dot(offset, offset);
if(squareMagnitude > maxDistance * maxDistance)
return false;

// We're in range, so next check our direction.
Vector3 normalized = offset / Sqrt(squareMagnitude);

// This will give 1 if we're exactly in the look direction,
// or less and less the further we're off-center
float cosine = Dot(normalized, direction);

// Test our computed cosine against the threshold cosine.
return cosine >= Cos(angleDegrees * pi/180f);
}

After thinking about this for a while, I reduced the problem to 2d and came up with two conditions that have to be met for the object to be visible.

1> p1 should be within the circle drawn with p2 as centre and max as radius and

2> angle between the line joining p1 and p2, and n, should be less than half of the spread of light

In this picture, p1 is out of max and not within spread. p3 is within max but out of spread. p4 is within spread and within distance (thus visible). p5 is within spread but is out of max distance.

To satisfy 1: the distance between the vectors (straight line distance between p1 and p2 shown in dotted lines) should be less than max. For 2: angle between the line p1-p2 and n (shown as x in the picture) should be less than $\theta$/2. 