How do I rotate a vector 90 degrees in a random direction?

7.8k Views Asked by At

I'm building a tree generator and I'm at the point where I want to have sub branches branch off at right angles off the current branch, in random directions. I have a 3D vector defining the direction of the current branch but I can't for the life of me figure out how to transform that to a direction for the sub branch.

I have googled the problem and also searched here, but I can only find related problems and apparently I'm just not smart enough to figure out how to apply them to my problem.

So what needs to happen, given a certain 3D vector v, which can be pointing in any direction:

  1. Rotate v 90 degrees in some direction such that it ends up on the plane it defines; call that v'
  2. Rotate v' an arbitrary amount on that plane; in other words around the axis defined by v

Or put more simply:

  1. Rotate v 90 degrees in a random direction

I'm doing this in Java; the vector is stored in a javax.vecmath.Vector3f. I know about affine transforms, but as far as I understand they rotate around global axes, and I need to rotate my vector around the local axes defined by itself, if that makes sense.

Can someone hand hold me through this problem?

2

There are 2 best solutions below

12
On BEST ANSWER

If you know the branch vector $\vec b = (x_0, y_0, z_0)$, then any vector perpendicular to it , say $\vec p = (x_1, y_1, z_1)$ will have dot product $0$.

So,

$$ \vec b . \vec p = x_0x_1 + y_0y_1 + z_0z_1 = \vec0 \\\text{dot product is zero as they are perpendicular} $$pick any $x_1, y_1$ you prefer, and set $z_1$ as

$$z_1 = - \frac{\left (x_0 x_1 + y_0 y_1\right)}{ z_0}$$

That seems to be the simplest approach to get "random" branches.

If you want to control the length of the vector, then you can always normalize your obtained vector $\vec p$ and get the result vector $\vec r$ by using

$$ \vec r = len \times\frac{\vec p}{\left | \vec p\right| } $$

where $len$ is the desired length of the vector.

If $z_0$ is $0$, then you'll get a singularity when you try to divide by $z_0$.

However, since $z_0$ is $0$, it does not impact the dot product at all, and therefore we can pick any $z_1$ we want to.

Solve for $y_1$ by picking some $x_1$, and then allowing $z_1$ to be "free" (that is, you can pick any $z_1 \in \mathbb{R}$). However, in doing so, you'll face a problem if $y_0$ is $0$ as well.

If both $z_0 = y_0 = 0$, then, you're forced to set $x_1 = 0$ (to maintain the dot product as $0$ for perpendicularity) while having $y_1, z_1 \in \mathbb{R}$ (that is, they are free).

3
On

Let ${\bf u}$ be the unit vector in ${\mathbb R}^3$ giving the forward direction of the current branch, ending at the point ${\bf p}$. This branch emanated from a previous point ${\bf p}'$, and there was a unit vector ${\bf u}'$ defining the previous branch ending at ${\bf p}'.$ We shall need this vector for the next step!

Note that ${\bf u}'\perp{\bf u}$. The pair ${\bf u}'$, ${\bf u}$ is supplemented by ${\bf v}:={\bf u}'\times {\bf u}$ to an orthonormal basis of ${\mathbb R}^3$ containing ${\bf u}$ as a member. It follows that ${\bf u}'$ and ${\bf v}$ are orthogonal unit vectors in the plane orthogonal to ${\bf u}$.

In order to obtain a random unit vector ${\bf w}$ in this plane generate a uniformly distributed $\phi\in[0,2\pi]$ and put $${\bf w}:=\cos\phi\,{\bf u}'+\sin\phi\,{\bf v}\ .$$ Note that the vector ${\bf w}$ constructed in this way depends only on ${\bf u}$.