1
\$\begingroup\$

I'm trying to learn some lwjgl and opengl, and I was trying to make a 3d sphere etc, I found a code to do that, but I don't 100% understand the code and the math behind it and would like to get some deeper explanation about it.

This is my draw sphere method:

public void drawSphere(float radius) {
    final float PI = 3.141592f;
    float x, y, z, alpha, beta;
    int gradation = 100;
    for (alpha = 0.0f; alpha < Math.PI; alpha += PI / gradation) {
        glBegin(GL_TRIANGLE_STRIP);
        for (beta = 0.0f; beta < 2.01f * Math.PI; beta += PI / gradation) {
            x = (float) (radius * Math.cos(beta) * Math.sin(alpha));
            y = (float) (radius * Math.sin(beta) * Math.sin(alpha));
            z = (float) (radius * Math.cos(alpha));
            glTexCoord2f(beta / (2.0f * PI), alpha / PI);
            glVertex3f(x, y, z);
            x = (float) (radius * Math.cos(beta) * Math.sin(alpha + PI / gradation));
            y = (float) (radius * Math.sin(beta) * Math.sin(alpha + PI / gradation));
            z = (float) (radius * Math.cos(alpha + PI / gradation));
            glTexCoord2f(beta / (2.0f * PI), alpha / PI + 1.0f / gradation);
            glVertex3f(x, y, z);
        }
        glEnd();
    }
}

I understand the general idea of this, and I understand how the x, y, z are calculated, but what I don't understand is the 2 nested loops aka:

for (alpha = 0.0f; alpha < Math.PI; alpha += PI / gradation)

and

for (beta = 0.0f; beta < 2.01f * Math.PI; beta += PI / gradation)

One more thing, is the glTexCoord2f that I don't quite understand the math behind it, so an explanation about this would be really nice as well for:

glTexCoord2f(beta / (2.0f * PI), alpha / PI);

and

glTexCoord2f(beta / (2.0f * PI), alpha / PI + 1.0f / gradation);
\$\endgroup\$
2
\$\begingroup\$

Think of a globe with latitude and longitude lines drawn on it. What the loops are doing is marching around the longitude lines of the sphere at different latitudes. The outer loop goes from 0 to π radians, or 0 to 180°. This is from the south pole to the north. It's sometimes expressed as -π/2 to π/2 (-90° to +90°) with 0 radians/degrees being the equator.

At each latitude, the inner loop walks around the longitudinal lines from 0° to 360°.

To understand the texture coordinates, you need to understand an equirectangular projection. An image in this format has its x coordinates representing the longitudes, and the y coordinates representing the latitudes. I'm assuming that the texture is in a GL_TEXTURE_2D texture target. That means that the texture coordinates need to be normalized. So the 2 lines you quoted are converting the longitude and latitude from their normal ranges (longitude = 0 to π, latitude = 0 to 2 * π), into the range 0 to 1. This makes a texture in an equirectangular projection map properly onto the sphere. The vertex at lat/long of (alpha, beta) will be assigned a texture coordinate (u, v) in such a way that the bottom of the image is at the south pole, the equator is in the middle, the top is at the north pole, and the left and right edge meet at the international date line.

\$\endgroup\$
  • \$\begingroup\$ Thank you! That was a great answer. Its still a bit hard for me to understand it, because there's a lot of math behind it I don't know and understand, but your answer is a good explanation of what I wanted to know. One more thing if you don't mind, the glTexCoord lines are working well with a few texture, except for 1 texture, for example earth texture, I need to change the (2.0f * PI) to (2.07f * PI) for it to work, otherwise the result will be like here: i.imgur.com/s0pn0Oy.png Again, thats the case only with the earth texture, and that might be because of the texture dimensions. \$\endgroup\$ – msacco Jun 20 '18 at 5:41
  • \$\begingroup\$ *continue - the earth texture dimensions are 1000x500, the other textures I've tested are 1024x512 and 2048x1024, so that might be the cause for that and as far as I remember the textures needs to be by the power of 2^ (aka 512 instead of 500), but again, Im not sure about that. \$\endgroup\$ – msacco Jun 20 '18 at 5:42
  • \$\begingroup\$ Debugging that should probably be another question. It could be a power of 2 issue, though I'd be a little surprised by that on modern hardware. Why don't you post your texture uploading code in a new question and we can discuss it there? \$\endgroup\$ – user1118321 Jun 20 '18 at 5:44
  • \$\begingroup\$ I don't think I have enough time for that now, as I need to go to a job interview very soon, but there's barely code for the texture: sunTexture = TextureLoader.getTexture("jpg", new FileInputStream("res/sun.jpg")); mercuryTexture = TextureLoader.getTexture("jpg", new FileInputStream("res/mercury.jpg")); thats the uploading texture method, then I simply enable texture_2d and bind the texture. \$\endgroup\$ – msacco Jun 20 '18 at 5:47
  • \$\begingroup\$ Don't know if you'll see this, but just a small update, the texture problem was indeed because of the earth texture being 1000x500 and not by power of 2, after changing it to 1024x512 it works as it should. Anyway, thanks for the help :) \$\endgroup\$ – msacco Jun 20 '18 at 15:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.