- -- pos - observer position
- -- vec - observer vector
- -- target - target position
- function angle (pos, vec, target)
- -- Imagine that the observer is wearing spherical helmet of raduis 1.
- -- He looks on the target, and his line of sight crosses the helmet.
- -- We'll calculate this crossing point by normalizing his looking
- -- vector.
- -- Normalization means making length of vector equal to 1, but
- -- still pointing to the same direction.
- local vec_look = vector.normalize(vec)
- -- We also calculate another vector, that is the difference
- -- between observer and target (= position relative to target).
- local vec_diff = vector.subtract(target, pos)
- -- Well, this requires normalization too.
- vec_diff = vector.normalize(vec_diff)
- -- Now both are starting from center and pointing to some point
- -- of surface of helmet. We will calculate the distance of
- -- Calculate the length between two vectors.
- local chord = vector.length(vector.subtract(vec_look, vec_diff))
- -- What we have calculated is a chord on some circle of sphere.
- -- Having this we can calculate the angle.
- -- https://en.wikipedia.org/wiki/Chord_%28geometry%29
- -- c = 2*r*sin(phi / 2)
- -- because r = 1, it degenerates to:
- -- c = 2 * sin(phi / 2)
- -- c/2 = sin(phi / 2)
- -- asin(c/2) = phi / 2
- -- 2 * asin(c/2) = phi
- local angle = 2 * math.asin(chord / 2)
- -- note the result is in radians. Convert it to degrees.
- return angle * 180 / math.pi