In the iOS app The Fourth Dimension I implemented a 4D direct manipulation controller. It's like a virtual trackball that applies 4D rotations instead of 3D rotations.
How does this work?
A traditional 3D virtual trackball maps a dragging vector in screen space into a 3D rotation around an axis.
My goal was to convert a vector between a pair of 2D touch events into a 4D rotation.
With a traditional 3D virtual trackball, it's a lot more intuitive to let the user grab the target object directly and spin it, as opposed to presenting the user with three sliders for the X, Y, and Z rotations. I felt this should be possible in 4D as well.
In the third dimension, rotation is often described as an angle around a single axis. This isn't sufficient to describe a rotation in the fourth dimension, however.
A more general way to describe a rotation is as an angle of rotation around a point in a plane. This works in 2D, in which there is only one possible plane.
It works in 3D, where there is only one plane perpendicular to a given axis of rotation.
It also works in 4D. The plane of rotation floats in the 4D space, and all points rotate in planes parallel to this plane.
A plane can be defined in any dimension using two basis vectors, which means that the dot product of the two vectors will be zero. In other words, the two vectors are perpendicular to each other.
In 3D, two basis vectors can define a plane of rotation, and a third basis vector is necessary to span the rest of the 3D space. We call this third basis vector the axis of rotation.
In 4D, two basis vectors define a plane of rotation, but two additional basis vectors are required to span the rest of the 4D space. Consequently, it makes no sense to talk about "rotation around an axis" in 4D. There is no single unique axis left over to rotate around.
Rotation around an axis is only meaningful in the third dimension. Since our universe has three spatial dimensions, we tend to assume that this is simply how rotations are defined everywhere and that it should make sense in higher dimensions as well. This is not the case.
For 4D direct manipulation rotations, how should we choose the two basis vectors for a 4D rotation as the user drags their finger across the screen?
Remember, the dot product of the two basis vectors has to be zero.
For the first basis vector, we directly use the 3D dragging vector of the user's finger in the plane of the screen, with zero as the fourth component. This vector is (x, y, z, 0).
For the second basis vector, we choose the 4D unit vector (0, 0, 0, 1).
The dot product of (x, y, z, 0) and (0, 0, 0, 1) is zero, so this satisfies our constraint.
Assuming the Z axis points into the screen, this does limit the possible rotations to those that are combinations of the 4D planes XW and YW. I considered supporting a pinch gesture for ZW rotations, but I felt this would increase confusion. The 3D trackball I implemented supports rotations in XZ and YZ, and also in XY using two-fingered twisting rotations.
The upshot of all this is that the interface only requires buttons to switch between 3D and 4D rotation modes, and the user can rotate the tesseract by dragging naturally.
Given this scheme, for the 4D rotations, there's a direct relationship between the direction the user drags their finger on the screen and the 4D rotation that occurs. The projected tesseract essentially turns itself inside out in the direction that the user drags their finger.
With repeated exposure, the interaction feels intuitive, to the extent that effecting a 4D rotation on a tesseract projected into 3D space can be intuitive.
Once I determined the basis vectors for the plane in 4D space, I had to construct a rotation matrix to rotate the vertices of the tesseract. In 3D space, a 3x3 matrix is sufficient to define a rotation, but in 4D space, a 4x4 matrix is required.
I first wrote a function to rotate a 4D vector in a plane defined by two 4D basis vectors by an angle. This function projects the vector onto the plane, rotates it there using the standard 2D rotation equations, and then applies the inverse of the projection.
Given the 4D vector rotation function, I used this function to create the four column vectors of the 4D rotation matrix by rotating each of the four 4D unit vectors.