[Math] Rotate vector relative to XZ plane to be relative to a new plane defined by given normal

linear algebra

The up reference is Y.

I have a bunch of vectors that are oriented relative to the XZ plane. I'm not sure if that makes sense, so just consider that these vectors all have positive Y values, and that these vectors are normalized.

My goal is to rotate these vectors so that they are oriented relative to a new plane, given that plane's normal.

This image may help:
Applying orange vectors to a surface defined by a blue normal.

I want to take each of the orange vectors, and apply a rotation to them so that they lie on the plane segment whose edges have green lines attached to it, this plane is defined by a blue normal.

Let $v$ be an orange vector to rotate, whose length is 1, and whose y value is positive. Let $n$ be a blue surface normal, whose length is 1, and whose y value is positive.

Currently I do this by finding an axis and angle to rotate by, where the axis is $ u = n \times \{0,1,0\} $, and the angle is $ \theta = acos(\{0,1,0\} \cdot n) $.

Then I form an axis-angle rotation matrix, and multiply this matrix by $v$ to get the desired rotated vector.

The problem with this is that it is slow, so I need a faster way.

I thought that I might be able to form a rotation matrix by finding the tangent, binormal and having the given blue normal vector $n$.

So I tried this:

Tangent $t = n \times \{1,0,0\}$.

Binormal $b = t \times n$.

Then I normalize $t$ and $b$ and put them in a matrix like so:

$R = \begin{array}{ccc}
t_x & b_x & n_x \\
t_y & b_y & n_y \\
t_z & b_z & n_z \end{array} $

Then I multiply the rotation matrix $R$ by $v$, but this doesn't rotate $v$ onto the plane as desired.

Is there a fast way to find the rotation matrix to rotate $v$ onto the plane defined by $n$? Does my tangent/normal/binormal matrix idea work, but I'm just making a small mistake, like calculating the binormal wrong?

Best Answer

The problem with your "binormal" idea is that it uses a different rotation axis than the angle/axis approach. You want a rotation matrix that maps $z = (0, 0, 1)^T$ to $n$ and leaves $t$ alone. To build this matrix, you need a third correspondence, say from $a = t \times z$ to $b = t \times n$. Set up two matrices (defined by their columns) $A := (z, t, a)$ and $B := (n, t, b)$. The rotation matrix you are looking for is given by $R = B A^{-1} = B A^T$. You can multiply this out explicitly, but this is probably as efficient as it gets.