How can I map this texture to a sphere?

Started by
6 comments, last by TheAdmiral 16 years, 11 months ago
Hello, I downloaded the moon texture from this page (at the bottom) and tried mapping it to a sphere, constructing the vertex and texture coordinates myself (well, in code, but not using any special API calls for spheres...). However, the texture converges badly towards the poles: I am using quads, equidistant in x, and stretched by sin in y (so y differences are smaller towards the poles). I get the same effect with equidistant y coordinates. I use this method as well for texture coordinates as for vertex coordinates, where the vertices converge by shrinking the radius of the resultic cylinder. I hope you understand this - the code is a bit convoluted, but you may want to have a look anyway:

  for (int x = 0; x <= max_x; ++x)
  {
    for (int y = 0; y <= max_y; ++y)
    {

      int dy = max_y - y;

      float d = r;
      d = sin((M_PI / 2) + y * (M_PI / 2)  / (float)max_y);

      // construct upper half

      coords[x][max_y - y].x = d * sin(x * (2 * M_PI / (float)max_x));
      coords[x][max_y - y].y = r * sin(y * M_PI / 2 / (float)max_y);
      coords[x][max_y - y].z = d * cos(x * (2 * M_PI / (float)max_x));

      double yf = y / ((float)max_y * 2.0);
      yf = sin(y * M_PI / 2 / (float)max_y) / 2;

      coords[x][max_y - y].u = x / ((float)max_x );
      coords[x][max_y - y].v = 0.5 - yf;

      // lower half

      coords[x][max_y + y].x =  coords[x][max_y - y].x;
      coords[x][max_y + y].y = -coords[x][max_y - y].y;
      coords[x][max_y + y].z =  coords[x][max_y - y].z;

      coords[x][max_y + y].u = coords[x][max_y - y].u;
      coords[x][max_y + y].v = 0.5 + yf;

    }
  }

Now the question is, can this texture be mapped better, what do you think by looking at it? What would be the correct formula? I'd appreciate any hint, as these are my first steps (using Open GL) :) Thanks! :)
Advertisement
I have found this piece of code that works quite well(it's not mine). IIRC "p" must be an even number in order for the sphere to render correctly.
The surface of a sphere is not topologically equivalent to a rectangle, so there is no way to 'cleanly' texture it. You can do a great job with a little multi-texturing, but if you're careful when creating the texture itself, you can do a reasonable job without all the effort.

The problem is that of Spherical Texture Mapping. Google can provide further help.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Thanks, I will try both of your suggestions.

Admiral, the problem is that I can't create this texture myself :) I hope the texture is appropriate to this spherical mapping that you mentioned...
The spherical mapping is basically the inverse of the task of projecting the sphere onto the rectangle in the first place (i.e., what the creators of the texture did). If you know what projection was used (e.g. Mercator is the one that makes those maps of the earth where Greenland is much larger than it should be, but everything is more or less the right *shape*), this will guide the decision of how to map back onto the sphere.
Try a geosphere. Since all the faces are uniform, it can be mapped in a way that has no stretching.

For local multiplayer retro themed games, visit Domarius Games.

Zahlman, thanks for explaining, that makes the idea of the mapping a lot clearer to me!

Domarius, this is an interesting idea, I implemented it by subdividing a cube and then normalizing the vertices. I guess it's the standard way to do it, but it was fun seeing it actually work :D
Quote:Original post by Domarius
Try a geosphere. Since all the faces are uniform, it can be mapped in a way that has no stretching.

While this is the best way to produce uniform results, it's not viable unless the texture is specifically designed. In particular, a geospherical net can't be represented in a rectangle without introducing a lot of dead space and taking a lot of care over the UV coordinates.

The texture on the page alceloco linked us to looks to be using a Gall-Peters projection, so using the 'uniform by angle' unprojection should work very well.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.

This topic is closed to new replies.

Advertisement