0
\$\begingroup\$

I need the Matrix4x4 to rotate around a given axis that does not go through (0,0,0). Is there some built in straightforward way to do this in the Unity libraries, or do I need to build and maintain my own?

Below is the formula I'd use to build my own in case somebody needs it:

We will define an arbitrary line by a point the line goes through and a direction vector. If the axis of rotation is given by two points P1 = (a,b,c) and P2 = (d,e,f), then a direction vector can be obtained by ⟨u,v,w⟩ = ⟨d-a,e-b,f -c⟩. [...] Assuming that ⟨u,v,w⟩ is a unit vector so that L = 1, we obtain [...]

enter image description here Source

I do need the rotation Matrix, not just the rotation. If I didn't need the Matrix I could use (not tested, may contain flaws, but you get the idea):

public Vector3 RotatePointAroundAxis(Vector3 point, Ray axis, float rotation) {
    return Quaternion.AngleAxis(rotation,axis.direction) * (point - axis.origin) + axis.origin;
}

So far the best I've got is the equivalent of the above (not tested, may contain flaws, but you get the idea), but it looks quite wasteful:

public Matrix4x4 RotationMatrixAroundAxis(Ray axis, float rotation) {
    return Matrix4x4.TRS(-Axis.origin, Quaternion.AngleAxis(rotation, Axis.direction), Vector3.one)
         * Matrix4x4.TRS(Axis.origin, Quaternion.identity, Vector3.one);
}
\$\endgroup\$
1
\$\begingroup\$

I don't believe that Unity has a built-in method for this. I believe that Transform.RotateAround is the closest, but if there's a utility function being used there then it isn't a documented one.

Your proposed method seems clear and straightforward, and not particularly wasteful. After the compiler gets done with it, it's likely to be quite good code for building that matrix.

The main optimization you could do yourself would be to construct only the rotation matrix, use it to help you build the combined translation (pre- and pos-rotate), then set the translation of the matrix to the result. This would make your intent a little more clear to the compiler.

In my opinion, unless you're calling this function in a very hot inner loop, it probably doesn't matter which way you do it.

\$\endgroup\$
1
  • \$\begingroup\$ I looked at the decompiled RotateAround, and it internally uses something similar to the RotatePointAroundAxis I made up in the question. So it looks like currently the function RotationMatrixAroundAxis I wrote is the simplest/safest option, and a function on the image in the question is the only high performance option. The compiler will probably not optimize RotationMatrixAroundAxis, because TRS is an external call which I guess is implemented in C++/CLR. \$\endgroup\$ – Peter Mar 14 '17 at 21:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.