Maybe this fits in math.stackexchange.com, but since I am programing it in OpenGL, I shall ask it here.

I had the idea of an spaceship game where the world is confined in the surface of an 4-D hypersphere (also called a 3-sphere). Thus, in seeing it from inside, it would look like a 3-D world, but by navigating in every direction, I would never leave the limited volume of the 3-sphere.

To represent the 3-shpere as a "flat" 3-D space, I use an stereographic projection, which is very simple to implement as a GLSL shader, just need to divide the input vector by one minus its w coordinate.

To represent the vertices of the objects I am using normalized 4d vectors, such that x²+y²+z²+w²=1, thus keeping them inside the 3-sphere.

The first problem to solve was rotation. But I soon figured out that ordinary 3d rotation matrices would suffice to rotate the world around the viewer in the 3d projection, since it does not mess up with the w coordinate (pretty much like rotating a sphere around the z-axis would also rotate its stereographic projection).

Then I figured out that rotating along w-axis would be equivalent of translation inside the 3d projection (just not commutative, as ordinary 3d translations on "flat" spaces), then I could translate along the axis by using a simple around axis rotation matrix (x', y') = (x * cos a - y * sin a, x * sin a + y * cos a), but variating w along with another axis.

This is so far where I got, and I could not figure out how to navigate forward, based on the position the viewer is facing from the projection. I can apply the inverse transform to derive the normalized 4-D vector (called F) the viewer is facing in the hypersphere coordinates, but I don't know how to navigate in that direction by using a 4x4 matrix (what is optimal in OpenGL). I could think on a hackish solution: for every vertex V, do V' = normalize(d*F + V), where d is the distance moved forward (in some strange unit I can not exactly precise). This way only works for small values of d, there is no direct correlation between d and the angle variation.

Thus the question is: how to move forward (using a 4x4 matrix transform) being in the surface of a 4-D hypersphere?

3 Answers
3

It turns out that I wrote some papers in this area some time ago. This one (Interactive Visualization Methods For Four Dimensions) applies most closely to your particular problem but the other documents that cite this one may also help you. In that particular application, I was rotating the object being observed in 4D, not the viewer, but the math is equivalent.

Regarding this specific question:

Thus the question is: how to move
forward (using a 4x4 matrix transform)
being in the surface of an 4-D
hypersphere?

If you're moving around on the surface of a hypersphere, you aren't translating in w. You actually need to move in the spherical geometry around a great circle of unit radius. That means that, if you can construct the appropriate axes for your frame of reference, you can spherically interpolate between where you are and where you are going.

For example, one construction that could be used for such a slerp would be to use the unit vector that points straight ahead (your line of sight, aka p_1 in the Wikipedia equation), a vector point out of the top of your head (p_0) and a vector pointing out of your right ear (to make a right-handed coordinate system).

If you are then tracking your speed over the sphere in angular velocity rather than linear, you can just plug in a value for t (elapsed time) in the Wikipedia to find your new angular position.

Note that that equation places no limit on the number of components in the vertex p. Spherical interpolation works in any geometry.

EDIT (responding to questions in the comments):

Slerp seems not to be the case here,
because I do not want to interpolate a
rotation between 2 vectors over time.
Instead, at each time step, I want to
move every vertex into the opposite
direction the viewer is moving at that
moment. Thus, I am at position (0, 0,
0, 1) and I want to be at (sqrt(2)/2,
sqrt(2)/2, 0, 0) next frame.

Think of it this way: your position on a sphere (of any dimension) is a vector that displaces you from the center to the surface. If you're moving around at a particular angular velocity, that puts you at p0 and time t0, p1 at time t1, etc. Slerp is a handy way of calculating those positions at a particular time.

Likewise, your line of sight is a vector at right angles to the displacement vector. Line of sight is v0 at time t0, v1 at time t1 and so forth. Slerp again is useful for for calculating that vector.

How can I build the correspondent
transformation matrix, so every vertex
will be multiplied by the inverse of
it?

HOWEVER, before you can render your world onto a two dimensional screen, you first need to render it down from 4D to 3D. OpenGL (unsurprisingly) does not directly support this.

To see why, look at the perspective projection matrix. It assumes that you are rendering homogenous points in 3D space: x, y, z are in the first three components and w (a scaling factor) is in the fourth. w = 0 indicates a vector whereas w = anything else indicates a point. w = anything other than 1 is a non-normalized point.

So, there isn't a way to render a point at the 4D origin of (0, 0, 0, 0).

As you can see from the construction of the matrix, however, it isn't hard to make the 4D to 3D projection matrix. Apply that first to your geometry set independently from OpenGL's matrix pipeline. Then you can use OpenGL standard matrices for 3D to the screen.

I know I am not translating in w if I am moving around the surface, but variating the w coordinate in a rotation would displace the origin in the projection, what appears, to the viewer, that the world was translated.
–
lvellaMar 3 '11 at 1:18

About the slerp, I can not understand how can I make it into a transformation matrix. Slerp seems not to be the case here, because I do not want to interpolate a rotation between 2 vectors over time. Instead, at each time step, I want to move every vertex into the opposite direction the viewer is moving at that moment. Thus, I am at position (0, 0, 0, 1) and I want to be at (sqrt(2)/2, sqrt(2)/2, 0, 0) next frame. How can I build the correspondent transformation matrix, so every vertex will be multiplied by the inverse of it?
–
lvellaMar 3 '11 at 1:34

You'll probably need 5x5 matrices, as you're operating on a 4-space. The idea of homogenous coordinates is to introduce an additional dimension to represent additive operations by application of a linear operator.

I really like your idea, but just out of curiosity: Why not simply define a cyclic 3-space, i.e. wrap coordinates at a given value. Using a geometry shader you can duplicate those vertices of primitives that wrap around (you have to clip, and move the clipped vertex together with the introduced helper vertices toward the opposite end of the space). This would result in a kind of hall of mirrors effect, so you also have to introduce some kind of horizon.

The effect is not the same. Using a cyclic wrapping 3-D space seems that looking along one axis you would see your own back in the horizon, and depend on the angle you walk, you wold not get to the same position after one round-trip. The effect of a 3-sphere is, well, I'll need to code it to know...
–
lvellaMar 1 '11 at 3:57

@Ivella, actually, the cyclic coordinates would produce an effect similar to what you're looking for, if not exactly. One of the primary characteristics of navigating on any dimensional sphere is that, no matter which way you turn, you can always get back to your start point in the same distance. In cyclic coordinates, diagonal directions will be longer than straight up the axes directions.
–
Bob CrossMar 1 '11 at 13:04

I won't need 5x5 matrices for just rotations, 4x4 will suffice, the same way 3x3 matrix is enough for 3D rotation. I can not translate in the 4D euclidian space, because that would take me out of the hypersphere, so I don't need a 5x5 matrix.
–
lvellaMar 15 '11 at 16:37

I did ask the same question on math.stackexchange.com, because the question is too math related and I could possibly get a better answer there. Look here if you are interested in the original answer I've actually used.

Being in 4D, there is not a single vector perpendicular to any rotation, but actually a whole plane of perpendicular vectors, and that was confusing me.

Also, in OpenGL, I soon figured out that I could simplify the computation of the given solution, because I could always assume I am at the 4D projection origin (0,0,0,-1), always facing (0,0,-1,0), then translate a given angle along z and w, and multiply it to the already accumulated GL_MODELVIEW_MATRIX from the previous frame. So I did MODELVIEW <= M x MODELVIEW instead of MODELVIEW <= MODELVIEW x M I would get if I simply called glMultMatrix(M).