#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288
#endif

struct coord3D {
  float x;
  float y;
  float z; } ;

struct coord2D {
  float x;
  float y; } ;

void solidSphere(double r,int lat,int lon) {
  int npt = 2 + (lat-1)*lon;
  int ntx = (lat+1)*(lon+1);
  coord3D *pts =(coord3D *) calloc(npt,sizeof(coord3D));
  coord2D *tex =(coord2D *) calloc(ntx,sizeof(coord2D));
  pts[0].x = 0.0f;
  pts[0].y = 0.0f;
  pts[0].z = 1.0f;
  pts[1].x = 0.0f;
  pts[1].y = 0.0f;
  pts[1].z = -1.0f;
  int n = 0 ;
  int i,j ;
  for ( j = 0 ; j < lat+1 ; j++ ) {
    for ( i = 0 ; i < lon+1 ; i++ ) {
      tex[n].x =(float) i/lon;
      tex[n].y =(float) j/lat;
      n++; } }
  n = 2 ;
  for ( j = 0 ; j < (lat-1) ; j++ ) {
    double aa = M_PI/2.0-(j+1)*M_PI/lat;
    double c = r*cos(aa);
    double s = r*sin(aa);
    for ( i = 0 ; i < lon ; i++ ) {
      double a = i*M_PI*2.0/lon;
      pts[n].x = c*cos(a);
      pts[n].y = c*sin(a);
      pts[n].z = s;
      n++; } }
  glBegin(GL_QUADS);
  for ( i = 0 ; i < lon ; i++ ) {
    glTexCoord2fv((float *) &tex[i]);
    glNormal3fv((float *) &pts[0]);
    glVertex3fv((float *) &pts[0]);
    glTexCoord2fv((float *) &tex[i+lon+1]);
    glNormal3fv((float *) &pts[2+i]);
    glVertex3fv((float *) &pts[2+i]);
    glTexCoord2fv((float *) &tex[i+lon+2]);
    glNormal3fv((float *) &pts[2+(i+1)%lon]);
    glVertex3fv((float *) &pts[2+(i+1)%lon]);
    glTexCoord2fv((float *) &tex[i+1]);
    glNormal3fv((float *) &pts[0]);
    glVertex3fv((float *) &pts[0]); }
  for ( j = 0 ; j < lat-2 ; j++ ) {
    for ( i = 0 ; i < lon ; i++ ) {
      glTexCoord2fv((float *) &tex[i+(j+1)*(lon+1)]);
      glNormal3fv((float *) &pts[2+i+j*lon]);
      glVertex3fv((float *) &pts[2+i+j*lon]);
      glTexCoord2fv((float *) &tex[i+1+(j+1)*(lon+1)]);
      glNormal3fv((float *) &pts[2+(i+1)%lon+j*lon]);
      glVertex3fv((float *) &pts[2+(i+1)%lon+j*lon]);
      glTexCoord2fv((float *) &tex[i+1+(j+2)*(lon+1)]);
      glNormal3fv((float *) &pts[2+(i+1)%lon+(j+1)*lon]);
      glVertex3fv((float *) &pts[2+(i+1)%lon+(j+1)*lon]);
      glTexCoord2fv((float *) &tex[i+(j+2)*(lon+1)]);
      glNormal3fv((float *) &pts[2+i+(j+1)*lon]);
      glVertex3fv((float *) &pts[2+i+(j+1)*lon]); } }
  for ( i = 0 ; i < lon ; i++ ) {
    glTexCoord2fv((float *) &tex[i+lat*(lon+1)]);
    glNormal3fv((float *) &pts[1]);
    glVertex3fv((float *) &pts[1]);
    glTexCoord2fv((float *) &tex[i+(lat-1)*(lon+1)]);
    glNormal3fv((float *) &pts[2+(lat-2)*lon+i]);
    glVertex3fv((float *) &pts[2+(lat-2)*lon+i]);
    glTexCoord2fv((float *) &tex[i+1+(lat-1)*(lon+1)]);
    glNormal3fv((float *) &pts[2+(lat-2)*lon+(i+1)%lon]);
    glVertex3fv((float *) &pts[2+(lat-2)*lon+(i+1)%lon]);
    glTexCoord2fv((float *) &tex[i+1+lat*(lon+1)]);
    glNormal3fv((float *) &pts[1]);
    glVertex3fv((float *) &pts[1]); }
  glEnd();
  free(tex);
  free(pts);
}
  
