Trouble texture mapping an image on sphere.

Hey guys, I’m trying to texture map an image onto a sphere in OpenGL 3.3. But instead of showing the image it’s showing something like this:
[ATTACH=CONFIG]1602[/ATTACH]
I’m trying to map the face of buzz light year which is a 512x512 bmp image, and I don’t know why it isn’t texture mapping like it should on the sphere. It’s coming out fine on a cube or any flat surface, but I’m having trouble mapping it to a sphere. Here’s the code I’m using.


double Radius = 0.5;
int Lat = 10;
int Long = 10;

glm::vec2 t_coords[4] = {
  glm::vec2( 0.0, 0.0),
  glm::vec2( 0.0, 1.0),
  glm::vec2( 1.0, 0.0),
  glm::vec2( 1.0, 1.0)
};
void sphere(double radius, int Lats, int Longs)
{
  float lats,longs;

  float slices=(180/(float(Lats)*10))/2;
  float sectors=(180/(float(Longs)*10))/2;

  float l;int i=0;

  for (lats = 0.0; lats <= PI; lats+=sectors)  
  {
      for(longs = 0.0; longs <= 2.0*PI; longs+=slices)
	{
	  float x = radius * sin(lats) * cos(longs);
	  float y = radius * sin(lats) * sin(longs);
	  float z = radius * cos(lats);
	  glm::vec4 pt(x, y, z, 1.0);
    if(i>3) i=0;
	  v_colors[tri_idx] = white; v_positions[tri_idx] = pt; tex_coords[tri_idx] = t_coords[i];
	  v_normals[tri_idx] = pt; tri_idx++; i++;

	  w_colors[wire_idx] = black; w_positions[wire_idx] = pt; 
	  w_normals[wire_idx] = pt; wire_idx++;

	  
	  if(lats+sectors>PI)
	    l=PI;
	  else
	    l=lats+sectors;
	  x = radius * sin(l) * cos(longs);
	  y = radius * sin(l) * sin(longs);
	  z = radius * cos(l);
	  pt =glm::vec4(x, y, z, 1.0);
    if(i>3) i=0;
	  v_colors[tri_idx] = white; v_positions[tri_idx] = pt; tex_coords[tri_idx] = t_coords[i];
	  v_normals[tri_idx] = pt; tri_idx++; i++;

	  w_colors[wire_idx] = black; w_positions[wire_idx] = pt; 
	  w_normals[wire_idx] = pt; wire_idx++;
	  
	}
    }
  // To Complete the wireframe
  for (lats = 0.0; lats <= PI; lats+=sectors)  
    {
      for(longs = 0.0; longs <= 2.0*PI; longs+=slices)
	{
	  float x = radius * sin(lats) * cos(longs);
	  float y = radius * sin(lats) * sin(longs);
	  float z = radius * cos(lats);
	  glm::vec4 pt(x, y, z, 1.0);
	  
	  w_colors[wire_idx] = black; w_positions[wire_idx] = pt; 
	  w_normals[wire_idx] = pt; wire_idx++;
	  
	}
    }
}
void initBuffersGL(void)
{

  // Load shaders and use the resulting shader program
  std::string vertex_shader_file("vshader.glsl");
  std::string fragment_shader_file("fshader.glsl");

  std::vector<GLuint> shaderList;
  shaderList.push_back(csX75::LoadShaderGL(GL_VERTEX_SHADER, vertex_shader_file));
  shaderList.push_back(csX75::LoadShaderGL(GL_FRAGMENT_SHADER, fragment_shader_file));

  shaderProgram = csX75::CreateProgramGL(shaderList);
  glUseProgram( shaderProgram );

  // getting the attributes from the shader program
  GLuint vPosition = glGetAttribLocation( shaderProgram, "vPosition" );
  GLuint vColor = glGetAttribLocation( shaderProgram, "vColor" ); 
  GLuint vNormal = glGetAttribLocation( shaderProgram, "vNormal" ); 
  GLuint texCoord = glGetAttribLocation( shaderProgram, "texCoord" ); 
  uModelViewMatrix = glGetUniformLocation( shaderProgram, "uModelViewMatrix");
  normalMatrix =  glGetUniformLocation( shaderProgram, "normalMatrix");
  viewMatrix = glGetUniformLocation( shaderProgram, "viewMatrix");

  // Load Textures 
  GLuint tex=LoadTexture("images/buzz_face.bmp",512,512);
  glBindTexture(GL_TEXTURE_2D, tex);

  //Ask GL for two Vertex Attribute Objects (vao) , one for the colorcube and one for the plane.
  glGenVertexArrays (2, vao);
  //Ask GL for two Vertex Buffer Object (vbo)
  glGenBuffers (2, vbo);

  //Set 0 as the current array to be used by binding it
  glBindVertexArray (vao[0]);
  //Set 0 as the current buffer to be used by binding it
  glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);

  // Call the sphere function
  Lat = tesselation;
  Long = tesselation;
  sphere(Radius, Lat, Long);
  
  //Copy the points into the current buffer
  glBufferData (GL_ARRAY_BUFFER, sizeof (v_positions) + sizeof(v_colors) + sizeof(v_normals), NULL, GL_STATIC_DRAW);
  glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(v_positions), v_positions );
  glBufferSubData( GL_ARRAY_BUFFER, sizeof(v_positions), sizeof(v_colors), v_colors );
  glBufferSubData( GL_ARRAY_BUFFER, sizeof(v_colors)+sizeof(v_positions), sizeof(v_normals), v_normals );
  // set up vertex array

  glEnableVertexAttribArray( vPosition );
  glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
  
  //Textures
  glEnableVertexAttribArray( texCoord );
  glVertexAttribPointer( texCoord, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)) );

  // glEnableVertexAttribArray( vColor );
  // glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)) );

  // glEnableVertexAttribArray( vNormal );
  // glVertexAttribPointer( vNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions) + sizeof(v_colors)) );

  //Normal
  glEnableVertexAttribArray( vNormal );
  glVertexAttribPointer( vNormal, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)+sizeof(tex_coords)) );

  // For The Wireframe too ... --------

  //Set 1 as the current array to be used by binding it
  glBindVertexArray (vao[1]);
  //Set 1 as the current buffer to be used by binding it
  glBindBuffer (GL_ARRAY_BUFFER, vbo[1]);

    //Copy the points into the current buffer
  glBufferData (GL_ARRAY_BUFFER, sizeof (w_positions) + sizeof(w_colors) + sizeof(w_normals), NULL, GL_STATIC_DRAW);
  glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(w_positions), w_positions );
  glBufferSubData( GL_ARRAY_BUFFER, sizeof(w_positions), sizeof(w_colors), w_colors );
  glBufferSubData( GL_ARRAY_BUFFER, sizeof(w_colors)+sizeof(w_positions), sizeof(w_normals), w_normals );
  
  // set up vertex array

  glEnableVertexAttribArray( vPosition );
  glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
  
  glEnableVertexAttribArray( vColor );
  glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(w_positions)) );

  glEnableVertexAttribArray( vNormal );
  glVertexAttribPointer( vNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(w_positions) + sizeof(w_colors)) );


}

GLuint LoadTexture( const char * filename, int width, int height )
{
    GLuint texture;
    unsigned char header[54];// 54 Byte header of BMP
    int pos;
    unsigned int w,h;
    unsigned int size; //w*h*3
    unsigned char * data; // Data in RGB FORMAT
    FILE * file;
    
    file = fopen( filename, "rb" ); 
    if ( file == NULL ) return 0;  // if file is empty 
    if (fread(header,1,54,file)!=54)
      {
	printf("Incorrect BMP file
");
	return 0;
      }

    // Read  MetaData
    pos = *(int*)&(header[0x0A]);
    size = *(int*)&(header[0x22]);
    w = *(int*)&(header[0x12]);
    h = *(int*)&(header[0x16]);

    //Just in case metadata is missing
    if(size == 0) 
      size = w*h*3;
    if(pos == 0)
      pos = 54;

    data = new unsigned char [size];

    fread( data, size, 1, file ); // read the file
    fclose( file );
    //////////////////////////

    glGenTextures( 1, &texture );
    glBindTexture( GL_TEXTURE_2D, texture );
    
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
   

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
    
    free( data );
    return texture;// return the texture id
}


Your texture coordinates are bogus. I don’t know exactly how you intend to map the image to the sphere, but the texture coordinates should probably be based upon lat/lon.

Also: note that some amount of distortion is unavoidable with the fixed-function pipeline. You’ll end up with a grid of trapezoids, each of which will be split into two triangles. One of those triangles will be larger than the other, but both will map to the same area of the texture, resulting in a crease along the diagonal. You can avoid this issue by using a bilinear mapping, but that requires shaders; fixed-function texturing is limited to affine or projective mapping.