Reputation: 787
Trying to implement a sphere example code I found here on stackoverflow I have been running into problems. Note that I am not using the draw code, I am using the void SolidSphere
function from this example to create my vertex data.
This is my code with some minor changes to the example that I refered to:
std::vector<GLfloat> vertices;
std::vector<GLfloat> normals;
std::vector<GLfloat> texcoords;
std::vector<GLushort> indices;
Sphere(shared_ptr<GL::Shader> _shader, shared_ptr<Material> _material, float radius, unsigned int rings, unsigned int sectors)
{
this->attachShader(_shader);
this->attachMaterial(_material);
/** Implementation from:
https://stackoverflow.com/questions/5988686/how-do-i-create-a-3d-sphere-in-opengl-using-visual-c?lq=1
**/
float const R = 1./(float)(rings-1);
float const S = 1./(float)(sectors-1);
int r, s;
vertices.resize(rings * sectors * 3);
//normals.resize(rings * sectors * 3);
texcoords.resize(rings * sectors * 2);
std::vector<GLfloat>::iterator v = vertices.begin();
//std::vector<GLfloat>::iterator n = sphere_normals.begin();
std::vector<GLfloat>::iterator t = texcoords.begin();
for(r = 0; r < rings; r++) {
for(s = 0; s < sectors; s++) {
float const y = sin( -M_PI/2 + M_PI * r * R );
float const x = cos(2*M_PI * s * S) * sin( M_PI * r * R );
float const z = sin(2*M_PI * s * S) * sin( M_PI * r * R );
*t++ = s*S;
*t++ = r*R;
*v++ = x * radius;
*v++ = y * radius;
*v++ = z * radius;
//*n++ = x;
//*n++ = y;
//*n++ = z;
}
}
indices.resize(rings * sectors * 4);
std::vector<GLushort>::iterator i = indices.begin();
for(r = 0; r < rings; r++) {
for(s = 0; s < sectors; s++) {
*i++ = r * sectors + s;
*i++ = r * sectors + (s+1);
*i++ = (r+1) * sectors + (s+1);
*i++ = (r+1) * sectors + s;
}
}
/************* THIS IS THE ADDED PART ********/
for (unsigned int i = 0; i < vertices.size(); i += 3) {
vertexCoords.push_back(glm::vec4(vertices[i], vertices[i+1], vertices[i+2], 1));
}
for (unsigned int i = 0; i < texcoords.size(); i += 2) {
textureCoords.push_back(glm::vec2(texcoords[i], texcoords[i+1]));
}
indexElements = indices;
cout << "Vertex vector size: " << vertexCoords.size() << endl;
cout << "Texture vector size: " << textureCoords.size() << endl;
cout << "Element index vector size: " << indexElements.size() << endl;
}
The only big change here is using M_PI / 2
instead of M_PI_2
and two loops that pushes the value into the format my code uses which is:
vector <glm::vec4> vertexCoords;
vector <glm::vec2> textureCoords;
vector <GLushort> indexElements;
Here is a picture of what I am rendering:
so I am seeing this last line on the top of the sphere..
Is it anything obvious I am doing wrong in this code that could cause this?
Upvotes: 1
Views: 6813
Reputation: 137188
In this loop:
for(r = 0; r < rings; r++) {
for(s = 0; s < sectors; s++) {
*i++ = r * sectors + s;
*i++ = r * sectors + (s+1);
*i++ = (r+1) * sectors + (s+1);
*i++ = (r+1) * sectors + s;
}
}
you are accessing r+1
and s+1
which when r = rings - 1
and s = sectors - 1
(i.e. the last iteration of your loops) will be one higher than the data you have available.
This will be pointing to an uninitialised area of memory. This could contain anything, but in this case it appears to contain zeros which would explain the line going off to the origin.
As you are drawing the "next" quad you simply need to stop these loops one iteration earlier:
for(r = 0; r < rings-1; r++) {
for(s = 0; s < sectors-1; s++) {
Upvotes: 2
Reputation: 59
The problem is the output indices of bounds. Try to fix this part of the code so
indices.resize(rings * sectors * 4);
std::vector<GLushort>::iterator i = indices.begin();
for(r = 0; r < rings-1; r++) {
for(s = 0; s < sectors-1; s++) {
*i++ = r * sectors + s;
*i++ = r * sectors + (s+1);
*i++ = (r+1) * sectors + (s+1);
*i++ = (r+1) * sectors + s;
}
}
Upvotes: 1
Reputation: 2522
You have only rings*sectors
vertices but your indices go up to (rings-1+1)*sectors+(sectors-1+1)
=rings*sectors+sectors. Which is exactly sectors
number of vertices too much.
Upvotes: 1