zaccaro - 8 months ago 35

C++ Question

I have in a 3D space a fixed light ray

`Lr`

`M`

`Mrot`

`Mrot`

`d`

`P`

We can consider that the mirror plane has no borders (infinite plane) and it's rotation have no limits. Also, the mirror reflects only on the opposite side of its rotation point.

In the picture are two cases with different input point

`P1`

`P2`

`alpha1`

`alpha2`

At the moment I am calculating the intersection with the mirror plane in a random rotation, then calculate the ray reflection and see how far is from the point (P) I want to reach. Finally iterate with some condition changing the rotation until it match.

Obviously it's an overkill, but I can't figure it out how to code it in an analytic way.

Any thoughts?

Note: I have noticed that if the mirror rotates about a point (Mrot) contained in it's plane and the ray light is reaching that point (Mrot) I can easily calculate the the mirror angle, but unfortunately is not my case.

Answer

First note that there is only one parameter here, namely the distance `t`

along the ray at which it hits the mirror.

For any test value of `t`

, compute in order

- The point at which reflection occurs.
- The vectors of the incident and reflected rays.
- The normal vector of the mirror, which is found by taking the mean of the normalized incident and reflected vectors. Together with 1, you now know the plane of the mirror.
- The distance
`d`

of the mirror to the rotation point.

The problem is now to choose `t`

to make `d`

take the desired value. This boils down to an octic polynomial in `t`

, so there is no analytic formula^{[1]} and **the only solution is to iterate**.^{[2]}

Here's a code sample:

```
vec3 r; // Ray start position
vec3 v; // Ray direction
vec3 p; // Target point
vec3 m; // Mirror rotation point
double calc_d_from_t(double t)
{
vec3 reflection_point = r + t * v;
vec3 incident = normalize(-v);
vec3 reflected = normalize(p - reflection_point);
vec3 mirror_normal = normalize(incident + reflected);
return dot(reflection_point - m, mirror_normal);
}
```

Now pass `calc_d_from_t(t) = d`

to your favourite root finder, ensuring to find the root with `t > 0`

. Any half-decent root finder (e.g. Newton-Raphson) should be much faster than your current method.

[1] I.e. a formula involving arithmetic operations, nth roots and the coefficients.

[2] Unless the octic factorises identically, potentially reducing the problem to a quartic.