Wednesday, February 1, 2017

mathematics - How can I rotate about an arbitrary point in 3D (instead of the origin)?


I have some models that I want to rotate using quaternions in the normal manner, except instead of rotation about the origin, I want it to be offset slightly. I know that you don't say, in 3d space, that you rotate about a point; you say you rotate about an axis. So I'm visualizing it as rotating about a vector whose tail is positioned not at the local origin.



All affine transformations in my rendering / physics engine are stored using SQT (scale, quaternion, translation; an idea borrowed from the book Game Engine Architecture.) So I build a matrix each frame from these components and pass it to the vertex shader. In this system, translation is applied, then scale, then rotation.


In one specific case, I need to translate an object in world space, scale it, and rotate it about a vertex not centered at the object's local origin.


Question: Given the constraints of my current system described above, how can I achieve a local rotation centered about a point other than the origin? Automatic upvote to anyone who can describe how to do this using only matrices as well :)



Answer



In short


You only need to change T in your SQT form.


Replace the translation vector v with v' = v-invscale(p-invrotate(p)) where v is the initial translation vector, p is the point around which you want the rotation to occur, and invrotate and invscale are the inverses of your rotation and scale.


Quick demonstration


Let p be the point around which you apply rotation r. Let s be your scaling parameters and v your translation vector. The final matrix transformation is T(p)R(r)T(-p)S(s)T(v) instead of R(r)S(s)T(v).


What you want is new transformation parameters v', r' and s' such that the final matrix transformation is R(r')S(s')T(v') and we have:



T(p)R(r)T(-p)S(s)T(v) = R(r')S(s')T(v')

Behaviour at infinity indicates that rotation parameters and scaling parameters cannot change (this could be demonstrated). We thus have r = r' and s = s'. The only missing parameter is therefore v', your new translation vector:


T(p)R(r)T(-p)S(s)T(v) = R(r)S(s)T(v')

If these matrices are equal, their inverses are equal:


T(-v)S(-s)T(p)R(-r)T(-p) = T(-v')S(-s)R(-r)

This especially holds true for origin O:


T(-v)S(-s)T(p)R(-r)T(-p)O = T(-v')S(-s)R(-r)O


Scaling and rotating the origin yields the origin, whe thus get:


T(-v)S(-s)T(p)R(-r)(-p) = -v'

v' is the new translation vector you are looking for that lets you store your transformation in SQT form. It is probably possible to simplify the computation; but at least the required storage is not increased.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...