/* This program displays a sphere with a picture texture-mapped onto it. Scott D. Anderson Scott.Anderson@acm.org Fall 2000 original Fall 2003 adapted for TW */ #include #include #include #include #include bool Wire = true; // wire-frame mode (vs filled) bool Texture = false; // texture mapping (on or off) int Stacks = 8; int Slices = 8; void setup(char* imagefile) { GLfloat mat_specular[]={1.0, 1.0, 1.0, 1.0}; GLfloat mat_diffuse[]={0.5, 1.0, 1.0, 1.0}; GLfloat mat_ambient[]={0.5, 1.0, 1.0, 1.0}; GLfloat mat_shininess={100.0}; GLfloat light_ambient[]={0.0, 0.0, 0.0, 1.0}; GLfloat light_diffuse[]={1.0, 1.0, 1.0, 1.0}; GLfloat light_specular[]={1.0, 1.0, 1.0, 1.0}; GLfloat light_position[]={10.0, 10.0, 10.0, 0.0}; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess); glEnable(GL_SMOOTH); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); /* automatic normalization of normals */ /* Define the 2D texture image. */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); twPPM_Tex2D(imagefile,true); } void SDA_wire_sphere(GLfloat radius, GLfloat stacks, GLfloat slices) { // i is the longitude counter, j is the latitude counter // i goes from 0-slices while longitude goes from 0 to 2PI // j goes from 0-stacks while latitude goes from -PI to +PI, // where 0,0 is on the positive x axis and negative latitude // is the southern hemisphere (negative y). int i, j; GLfloat lat_lo, lat_hi, cos_lat_lo, cos_lat_hi, nx, ny_lo, ny_hi, nz; GLfloat longitude, cos_longitude, sin_longitude; GLfloat x_lo,y_lo,z_lo,x_hi,y_hi,z_hi; GLfloat oldx_lo,oldy_lo,oldz_lo,oldx_hi,oldy_hi,oldz_hi; int prev=0; lat_lo = -M_PI/2; /* latitude of south pole */ cos_lat_lo = 0; /* radius at that latitude */ ny_lo = -1; /* same as sin_lat_lo */ for( j=1; j<=stacks; j++ ) { lat_hi = (M_PI * j)/stacks - M_PI/2.0; ny_hi = sin(lat_hi); cos_lat_hi = cos(lat_hi); prev = 0; glBegin(GL_LINES); for( i=0; i<=slices; i++ ) { longitude = (2*M_PI * i)/slices; cos_longitude = cos(longitude); sin_longitude = sin(longitude); nx = cos_lat_lo*cos_longitude; nz = cos_lat_lo*sin_longitude; x_lo=nx*radius; y_lo=ny_lo*radius; z_lo=nz*radius; glVertex3f(x_lo,y_lo,z_lo); nx = cos_lat_hi*cos_longitude; nz = cos_lat_hi*sin_longitude; x_hi=nx*radius; y_hi=ny_hi*radius; z_hi=nz*radius; glVertex3f(x_hi,y_hi,z_hi); if(prev) { glVertex3f(oldx_lo,oldy_lo,oldz_lo); glVertex3f(x_lo,y_lo,z_lo); glVertex3f(oldx_hi,oldy_hi,oldz_hi); glVertex3f(x_hi,y_hi,z_hi); } oldx_lo=x_lo; oldx_hi=x_hi; oldy_lo=y_lo; oldy_hi=y_hi; oldz_lo=z_lo; oldz_hi=z_hi; prev = 1; } glEnd(); lat_lo = lat_hi; ny_lo = ny_hi; cos_lat_lo = cos_lat_hi; } } void SDA_solid_sphere(GLfloat radius, GLfloat stacks, GLfloat slices) { // i is the longitude counter, j is the latitude counter // i goes from 0-slices while longitude goes from 0 to 2PI // j goes from 0-stacks while latitude goes from -PI to +PI, // where 0,0 is on the positive x axis and negative latitude // is the southern hemisphere (negative y). int i, j; GLfloat lat_lo, lat_hi, cos_lat_lo, cos_lat_hi, nx, ny_lo, ny_hi, nz; GLfloat longitude, cos_longitude, sin_longitude; lat_lo = -M_PI/2.0; /* latitude of south pole */ cos_lat_lo = 0; /* radius at that latitude */ ny_lo = -1; /* same as sin_lat_lo */ for( j=1; j<=stacks; j++ ) { lat_hi = (M_PI * j)/stacks - M_PI/2.0; ny_hi = sin(lat_hi); cos_lat_hi = cos(lat_hi); glBegin(GL_QUAD_STRIP); for( i=0; i<=slices; i++ ) { longitude = (2*M_PI * i)/slices; cos_longitude = cos(longitude); sin_longitude = sin(longitude); nx = cos_lat_lo*cos_longitude; nz = cos_lat_lo*sin_longitude; // The 1- on the s is because we go from east to west around // the globe, so we want the right hand edge of our texture to // map to the eastern silhouette, and so forth. The 1- on the // t is so that the top of the image is at the north pole. glTexCoord2f(1-longitude/(2*M_PI),1-lat_lo/M_PI+0.5); glNormal3f(nx,ny_lo,nz); glVertex3f(nx*radius,ny_lo*radius,nz*radius); nx = cos_lat_hi*cos_longitude; nz = cos_lat_hi*sin_longitude; glTexCoord2f(1-longitude/(2*M_PI),1-lat_hi/M_PI+0.5); glNormal3f(nx,ny_hi,nz); glVertex3f(nx*radius,ny_hi*radius,nz*radius); } glEnd(); lat_lo = lat_hi; ny_lo = ny_hi; cos_lat_lo = cos_lat_hi; } } void display(void) { twDisplayInit(); twCamera(); glPushAttrib(GL_ALL_ATTRIB_BITS); glEnable(GL_DEPTH_TEST); if(Wire) { glDisable(GL_LIGHTING); SDA_wire_sphere(5,Stacks,Slices); } else if(Texture) { glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); SDA_solid_sphere(5,Stacks,Slices); } else { glEnable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); SDA_solid_sphere(5,Stacks,Slices); } glFlush(); glutSwapBuffers(); glPopAttrib(); } void keys(unsigned char key, int x, int y) { switch(key) { case 'w': Wire = !Wire; break; case 't': Texture = !Texture; break; case '+': Stacks++; Slices++; break; case '-': Stacks--; Slices--; break; } glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500,500); glutCreateWindow(argv[0]); if(argc>1) setup(argv[1]); else setup("cokecan.ppm"); glutDisplayFunc(display); glLineWidth(1); twBoundingBox(-5,5,-5,5,-5,5); twMainInit(); twKeyCallback('w',keys,"toggle wire frame"); twKeyCallback('t',keys,"toggle texture mapping"); twKeyCallback('+',keys,"increase slices and stacks"); twKeyCallback('-',keys,"decrease slices and stacks"); glutMainLoop(); }