By notlesh

2011-11-01 16:19:45 8 Comments

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 :)


@sam hocevar 2011-11-01 21:19:46

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.

@pachanga 2013-05-05 04:18:29

Thanks for the explanation. BTW, do you know of any resources where I could read more about SQT representation tricks?

@johnbakers 2013-06-07 01:04:24

Correct me if I'm wrong but it seems another solution would be to store your Quaternion as normal, and if you need to account for translation around an arbitrary point/axis, then build the Q matrix with this included, simply extract the translation vector from this matrix (last column, usually) and add it to the objects Translation vector, then toss out your temporary matrix.

@Josh 2011-11-01 16:40:53

All of the canonical rotational formulas used to derive your rotation matrices are for rotation about the origin. If you would like instead to apply that rotation around a specific point, you must first offset the origin -- or, equivalently, move the object so the point you want to rotate about is at the origin.

Consider the 2D case first, because it is simpler and the technique scales. If you had a cube of width 2 centered on the origin and you wanted to rotate it 45 degrees about its center, that would be a trivial application of the 2D rotation matrix.

But if instead you wanted to rotate it around it's upper right corner (located at 1,1) you'd first have to translate it so that corner was at the origin. This can be accomplished with a translation of -1,-1. Then you can rotate the object as before, but you must follow this up by translating it back (by 1,1). So in general, to achieve the rotation matrix R for a rotation of r about point P you do:

R = translate(-P) * rotate(r) * translate(P)

where translate and rotate are the canonical translation/rotation matrices, respectively. As it happens, this scales trivially to 3D, which the exception of having to supply an axis to the rotation as well -- you could just always choose the canonical X, Y or Z axis rotation matrices, but that would be dull. You'll want to use the arbitrary axis-angle rotation matrix. Your final R in 3D is thus:

R = translate(-P) * rotate(a,r) * translate(P)

where a is a unit vector representing the axis of rotation and P is now a 3D point in model space representing the rotation point.

As it happens, quaternions can be converted to and from matrix representations, so you could do your concatenation that way should you so choose. Or you could just leave everything as matrices (quaternions have some nice advantages such as being easier to interpolate in a sane fashion, but whether or not you need that is up to you).


So I'm visualizing it as rotating about a vector whose tail is positioned not at the local origin.

Strictly speaking, while vectors can be used to represent positions by considering them as displacements from an origin, vector's don't have positions themselves so it's a bit unusual to visualize one as such.

@notlesh 2011-11-01 18:42:50

Thanks, this is a good reply. It doesn't fit the constraints of my system though. I should have included in my question, "is it possible to do this given these constraints?," and I think the answer is that it is not, since this requires two translations and I only provide for one. Is this an inevitable shortcoming of the use of SQT as a representation of affine transformations?

@Josh 2011-11-01 19:27:26

It fits perfectly within your constraints. The matrix R (produced as translate-rotate-translate-back) is your rotation matrix. Replace Q with R in your "SQT" system so you have the more common scale-rotate-translate paradigm, and you're done. That last translate is independent of the two intermediate translations done to produce the desired rotation.

@notlesh 2011-11-01 20:00:43

You're proposing I replace the quaternion with a matrix? That's 12 more bytes per object (8 if I store it as a 4x3 matrix)! I'll silence the optimist in me, though, and give this a whirl. (That actually probably won't even amount to a 2kb increase in footprint...) Thanks for your responses.

@Josh 2011-11-01 21:25:39

You could -- you could also convert between them, constructing the rotation quaternion that way and plugging in back in to your existing system.

@sam hocevar 2011-11-02 08:05:26

Sorry, but the matrix R is not a rotation matrix so it does not fit in the SQT system at all. You cannot "construct the rotation quaternion" that way. In fact the rotation quaternion does not change, it's the translation (and only the translation) that needs to be adapted.

@sam hocevar 2011-11-02 15:32:37

Also, "If you would like instead to apply that rotation around a specific point, you must first offset the origin -- or, equivalently, move the object so the point you want to rotate about is at the origin" is wrong. Any combination of rotations and translations can be reduced to only one translation and one rotation.

@Martin Sojka 2011-11-02 16:38:46

@SamHocevar: Alternatively, any combination thereof can be expressed as a single screw.

Related Questions

Sponsored Content

2 Answered Questions

1 Answered Questions

[SOLVED] Using Quaternions to rotate a player towards a point

  • 2016-08-02 22:38:07
  • Ronan Collins
  • 187 View
  • 0 Score
  • 1 Answer
  • Tags:   rotation quaternion

1 Answered Questions

[SOLVED] Rotate camera with quaternion around axis going through the origin

  • 2015-12-03 23:41:31
  • Itsbananas
  • 553 View
  • 1 Score
  • 1 Answer
  • Tags:   directx quaternion

1 Answered Questions

[SOLVED] Rotating the view around the origin of the world coordinate system

  • 2015-07-30 12:52:04
  • Karnivaurus
  • 272 View
  • 0 Score
  • 1 Answer
  • Tags:   opengl rotation

1 Answered Questions

3 Answered Questions

1 Answered Questions

[SOLVED] How to make child transforms honor parent origin

2 Answered Questions

[SOLVED] Accumulating rotations for camera

1 Answered Questions

[SOLVED] Quaternions and rotation around world axis

  • 2011-08-20 08:08:51
  • Kaj
  • 5543 View
  • 11 Score
  • 1 Answer
  • Tags:   quaternion

2 Answered Questions

[SOLVED] How to think about 2D scaling/rotation transformations

  • 2010-09-18 02:33:39
  • Ilya
  • 2728 View
  • 6 Score
  • 2 Answer
  • Tags:   2d mathematics

Sponsored Content