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