I'm learning OpenGL and I'm working on creating my own sphere model. I was able to draw a complete sphere, although with some puzzling results. I'm wondering if someone can explain (and possibly correct) my code.
The rationale: build triangles using carthesian coordinates calculated from polar coordinates. The number of subdivisions tells me the steps in phi or theta radians to generate the sphere point. From a particular point P(phi, theta), I build the other edges of the sector for [phi, delta_phi], [theta, delta_tetha], with phi varying from [0, pi] (180 degrees) and tetha from [0, 2*pi] (360 degrees).
This is the code I came up with (I'm using QT objects, but it should be pretty straitghforward):
QVector3D polarToCarthesian(float rho, float phi, float theta)
{
float r = qSin(phi) * rho;
float y = qCos(phi) * rho;
float x = r * qSin(theta);
float z = r * qCos(theta);
return QVector3D{x, y, z};
}
void make_sector(QVector<QVector3D>& mesh, float phi, float theta, float rho, float deltaPhi, float deltaTheta)
{
QVector3D p1 = polarToCarthesian(rho, phi, theta);
QVector3D p2 = polarToCarthesian(rho, phi, theta + deltaTheta);
QVector3D p3 = polarToCarthesian(rho, phi + deltaPhi, theta);
QVector3D p4 = polarToCarthesian(rho, phi + deltaPhi, theta + deltaTheta);
// First Triangle
mesh.push_back(p1);
mesh.push_back(p1); // Normal
mesh.push_back(p3);
mesh.push_back(p3); // Normal
mesh.push_back(p2);
mesh.push_back(p2); // Normal
// Second Triangle
mesh.push_back(p2);
mesh.push_back(p2); // Normal
mesh.push_back(p3);
mesh.push_back(p3); // Normal
mesh.push_back(p4);
mesh.push_back(p4); // Normal
}
void build_sphere(QVector<QVector3D>& mesh, int ndiv)
{
const float PHI_MAX = static_cast<float>(M_PI);
const float THETA_MAX = static_cast<float>(M_PI) * 2;
const float delta_phi = PHI_MAX / ndiv;
const float delta_theta = THETA_MAX / ndiv;
for (int i = 0; i < ndiv; ++i) {
float phi = i * delta_phi;
for (int j = 0; j < ndiv; ++j) {
float theta = j * delta_theta;
make_sector(mesh, phi, theta, 1.0f, delta_phi, delta_theta);
}
}
}
// Then I can generate the sphere with
build_sphere(sphere_mesh, 10);
However, I cannot get a complete sphere unless I change the iteration for phi
from ndiv
iterations to 3 * ndiv
iterations. I don't understand why! Phi should vary from 0 to PI to cover the whole Y axis while Theta from 0 to 2 * pi should cover the XZ plane.
Can somebody explain what's happening and why 3 * ndiv
works?