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