I've got a simple test program with a camera within a cubemap (skybox). You can look around, and it feels like you're in a 3D room, but really it's just a cubemap image.

Now I want to draw a point (well, ultimately, a large number of points) on the screen, such that it appears to be anchored at a point on the cubemap. For example, if the cubemap is of a room, then I want to put a point on the "wall", and have it appear to be stationary when you look around.

Given that there is no actual environment, it's just a cubemap, the points I want to project are represented as x/y rotational angles, rather than absolute 3D vertices. I tried calculating the position manually, using the camera x/y angles and interpolating across the screen. However because the cubemap is distorted at the edges due to the camera's projection matrix, my linear calculations don't match up, so the point appears to wobble as you look around.

I know I need to incorporate the camera's projection matrix to get it to appear in the correct position, but I'm not sure how. I'm using the CML math library, and I noticed it has a project_point() function, but it works with absolute 3D coordinates, so I don't know how that helps me when starting with angles instead of coordinates.

If someone could get me pointed in the right direction, I would appreciate it.

Edit: After reading other questions on polar coordinates, I came up with this for converting x/y angles (relative to the camera view angle) into a 3d coordinate that I could project onto the screen:

x = sin(horizontal_angle) * cos(vertical_angle)
y = sin(horizontal_angle) * sin(vertical_angle)
z = cos(horizontal_angle)

This almost works, I feel like I'm close. I can rotate the camera left and right, and the point appears to remain stationary. However, as soon as I rotate it up or down as well, the point moves rather significantly. However I I haven't been able to figure out why that is so far.

  • \$\begingroup\$ Do you want the point to stay stationary on the screen, or stationary with respect to the environment projected on the cubemap? \$\endgroup\$ Dec 22 '13 at 22:58
  • \$\begingroup\$ Stationary with respect to the environment, which involves moving the point around on the screen to compensate for camera rotation. \$\endgroup\$
    – Nairou
    Dec 23 '13 at 1:04

Well the camera must stay in the center of the cubemap, so its position is fixed. Say (0,0,0). It is easy to convert polar coordinates (x,y angles) to cartesian coordinates on a sphere of fixed radius (say r=1). That way those points are stationary within the scene and will appear anchored to the cubemap even though they are somewhere inside the cube.

I'm sure you'll find plenty of answers how to do that calculation on stackoverflow https://stackoverflow.com/search?q=polar+coordinates

But before you begin, why not check if something else is wrong? Put a point on some coordinates (0.5, 0.8, 0.3) and see if it behaves stationary, i.e. anchored to the cubemap. If it doesn't then your scene rendering and camera rotation steps are mixed up.

  • \$\begingroup\$ I don't quite follow your last paragraph. Scene rendering and camera rotation work fine. Both the cubemap and the camera are at origin. I know I could render a 3d point and have it appear in the correct place regardless of camera movement, the trick for me is creating the same illusion without it actually being a 3d point. \$\endgroup\$
    – Nairou
    Dec 23 '13 at 1:07
  • \$\begingroup\$ Updated my question after making a bit more progress from reading the questions you linked to. \$\endgroup\$
    – Nairou
    Dec 23 '13 at 1:14
  • \$\begingroup\$ Finally got it working. As you suggested, I tried projecting a point at specific coordinates rather than calculating the point from angles, and found a mis-calculation in my viewport matrix. After fixing that, angle calculations worked correctly. \$\endgroup\$
    – Nairou
    Dec 24 '13 at 20:42

I can't tell from what you wrote whether you want the point to stay stationary on the screen, or stationary with respect to the environment projected on the cubemap. However, in either case, the method I'd recommend would be the same: first map the angles to a point on a sphere, then project it onto the cube.

To get the location of the point on a sphere, start with a point at a fixed location in world space (i.e. wherever you want it to be if both angles are zero) and apply the rotations to it.

To project the point onto the cube, you first need to find out which side of the cube it is closest to, and then project it onto that side. For an axis-aligned unit cube centered on the origin, this is easy — just divide all coordinates of the point by the coordinate which has the largest absolute value. In pseudocode:

norm = max( abs( point.x ), abs( point.y ), abs( point.z ) );
point.x /= norm; point.y /= norm; point.z /= norm;

After this projection, one of the coordinates will be ±1.0, and the other two will range between -1.0 and +1.0.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .