/* Example 4.7.texobjects.c: texture objects and coordinates */ // by Jim X. Chen; June, 2001 #include #include #include #include #include #define ESC 27 #define SPACE 32 int Height=600, Width=600; int cnt=1, moonView=0; float O, A, B, C; float alpha=-30, beta=-30, gama=60, aalpha=1, abeta=1, agama=-2; int depth=2, enabletex=0; static float vdata[6][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0} }; float white[] = { 1., 1., 1., 1.}; float whitish[] = { .6, .6, .6, 1.}; float black[] = { 0., 0., 0., 1.}; float blackish[] = { .2, .2, .2, 1.}; float red[] = { 1., 0., 0., 1.}; float redish[] = { .3, .0, .0, 1.}; float green[] = { 0., 1., 0., 1.}; float greenish[] = { .0, .3, .0, 1.}; float blue[] = { 0., 0., 1., 1.}; float blueish[] = { 0., 0., .3, 1.}; float cyan[] = { 0.0, 1.0, 1.0, 1.}; float magenta[] = { 1.0, 0.0, 1.0, 1.}; float yellow[] = { 1.0, 1.0, 0.0, 1.}; #define stars_pixels 512 #define iris_pixels 512 #define earth_pixelx 512 #define earth_pixely 256 static GLuint iris1_tex, iris2_tex, stars_tex, earth_tex; static GLubyte iris1_image[iris_pixels][iris_pixels][3]; static GLubyte iris2_image[iris_pixels][iris_pixels][3]; static GLubyte stars_image[stars_pixels][stars_pixels]; static GLubyte earth_image[earth_pixelx][earth_pixely][3]; void read_iris_image(int k) { int i,j; FILE *iris_file; if (k==1) iris_file=fopen("images/Iris1.bmp","rb"); else iris_file=fopen("images/Iris2.bmp","rb"); if(iris_file==NULL) { printf("File earth.bmp could not be opened, errno=%d\n",errno); for(i=0;i0) { if (z>0) *s = atan(z/x)/PI2; else *s = 1 + atan(z/x)/PI2; } else if (x<0) *s = 0.5 + atan(z/x)/PI2; else { if (z>0) *s = 0.25; if (z<0) *s = 0.75; if (z==0) *s = -1.0; } *t = acos(y)/PI; } void drawSphereTriangle(float *v1, float *v2, float *v3) { float s1, t1, s2, t2, s3, t3; textureCoord(v1, &s1, &t1); textureCoord(v2, &s2, &t2); textureCoord(v3, &s3, &t3); // for coord at z=0 if (s1 == -1.0) s1 = (s2+s3)/2; else if (s2 == -1.0) s2 = (s1+s3)/2; else if (s3 == -1.0) s3 = (s2+s1)/2; glBindTexture(GL_TEXTURE_2D, earth_tex); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (enabletex) glEnable(GL_TEXTURE_2D); else glDisable(GL_TEXTURE_2D); glBegin(GL_POLYGON); glTexCoord2f(s1, t1); glNormal3fv(v1); glVertex3fv(v1); glTexCoord2f(s2, t2); glNormal3fv(v2); glVertex3fv(v2); glTexCoord2f(s3, t3); glNormal3fv(v3); glVertex3fv(v3); glEnd(); glDisable(GL_TEXTURE_2D); } void drawConeSide(float *v1, float *v2, float *v3) { float v11[3], v22[3], v33[3]; int i; for (i=0; i<3; i++) { v11[i] = v1[i] + v3[i]; // normal for cone vertex 1 v22[i] = v2[i] + v3[i]; // normal for cone vertex 2 v33[i] = v11[i] + v22[i]; // normal for cone vertex 3 } glBegin(GL_TRIANGLES); glNormal3fv(v11); glVertex3fv(v1); glNormal3fv(v22); glVertex3fv(v2); glNormal3fv(v33); glVertex3fv(v3); glEnd(); } void ncrossprod(float v1[3], float v2[3], float v3[3]) { v3[0] = v1[1]*v2[2] - v1[2]*v2[1]; v3[1] = v1[2]*v2[0] - v1[0]*v2[2]; v3[2] = v1[0]*v2[1] - v1[1]*v2[0]; normalize(v3); } void drawBottom(float *v1, float *v2, float *v3) { float v12[3], v23[3], vb[3];// normal to the cone or cylinder bottom int i; for (i=0; i<3; i++) { // two edge vectors v12[i] = v2[i] - v1[i]; v23[i] = v3[i] - v2[i]; } ncrossprod(v12, v23, vb); // vb = normalized cross prod. of v12 X v23 glBegin(GL_TRIANGLES); glNormal3fv(vb); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); glEnd(); } void subdivideSphere(float *v1, float *v2, float *v3, long depth) { float v12[3], v23[3], v31[3]; int i; if (depth == 0) { glColor3f(v1[0]*v1[0], v2[1]*v2[1], v3[2]*v3[2]); drawSphereTriangle(v1, v2, v3); return; } for (i = 0; i < 3; i++) { v12[i] = v1[i]+v2[i]; v23[i] = v2[i]+v3[i]; v31[i] = v3[i]+v1[i]; } normalize(v12); normalize(v23); normalize(v31); subdivideSphere(v1, v12, v31, depth - 1); subdivideSphere(v2, v23, v12, depth - 1); subdivideSphere(v3, v31, v23, depth - 1); subdivideSphere(v12, v23, v31, depth - 1); } void drawSphere(void) // draw a cone with z=height and bottom in xy plane { subdivideSphere(vdata[0], vdata[1], vdata[4], depth); subdivideSphere(vdata[0], vdata[4], vdata[3], depth); subdivideSphere(vdata[0], vdata[3], vdata[5], depth); subdivideSphere(vdata[0], vdata[5], vdata[1], depth); subdivideSphere(vdata[2], vdata[1], vdata[5], depth); subdivideSphere(vdata[2], vdata[5], vdata[3], depth); subdivideSphere(vdata[2], vdata[3], vdata[4], depth); subdivideSphere(vdata[2], vdata[4], vdata[1], depth); } void subdivideCone(float *v1, float *v2, int depth) { float v11[3], v22[3], v00[3] = {0, 0, 0}, v12[3]; int i; if (depth == 0) { glColor3f(v1[0]*v1[0], v1[1]*v1[1], v1[2]*v1[2]); for (i=0; i<3; i++) { v11[i] = v1[i]; v22[i] = v2[i]; } drawBottom(v22, v11, v00); // bottom cover of the cone v00[2] = 1; // height of the cone, the tip on z axis drawConeSide(v11, v22, v00); // side cover of the cone return; } for (i=0; i<3; i++) v12[i] = v1[i]+v2[i]; normalize(v12); subdivideCone(v1, v12, depth - 1); subdivideCone(v12, v2, depth - 1); } void drawCone(void) // draw a unit cone with center at the origin and bottom in xy plane { subdivideCone(vdata[0], vdata[1], depth); subdivideCone(vdata[1], vdata[2], depth); subdivideCone(vdata[2], vdata[3], depth); subdivideCone(vdata[3], vdata[0], depth); } void subdivideCylinder(float *v1, float *v2, int depth, float t1, float t2) { float v11[3], v22[3], v00[3] = {0, 0, 0}, v12[3]; int i; if (depth == 0) { glColor3f(v1[0]*v1[0], v1[1]*v1[1], v1[2]*v1[2]); drawBottom(v2, v1, v00); // draw the cylinder bottom for (i=0; i<3; i++) { v11[i] = v1[i]; v22[i] = v2[i]; } // the height of the cone along z axis v11[2] = v22[2] = 1; if ((cnt % 100) - 50 > 0) glBindTexture(GL_TEXTURE_2D, iris1_tex); else glBindTexture(GL_TEXTURE_2D, iris2_tex); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); if (enabletex) glEnable(GL_TEXTURE_2D); else glDisable(GL_TEXTURE_2D); glBegin(GL_POLYGON); // draw the side rectangles of the cylinder glNormal3fv(v2); glTexCoord2f(t1, 0.0); glVertex3fv(v1); glTexCoord2f(t2, 0.0); glVertex3fv(v2); glNormal3fv(v1); glTexCoord2f(t2, 1.0); glVertex3fv(v22); glTexCoord2f(t1, 1.0); glVertex3fv(v11); glEnd(); glDisable(GL_TEXTURE_2D); v00[2] = 1; drawBottom(v00, v11, v22); // draw the other bottom return; } v12[0] = v1[0]+v2[0]; v12[1] = v1[1]+v2[1]; v12[2] = v1[2]+v2[2]; normalize(v12); subdivideCylinder(v1, v12, depth - 1, t1, (t2+t1)/2); subdivideCylinder(v12, v2, depth - 1, (t2+t1)/2, t2); } void drawCylinder(void) // draw a unit cylinder with bottom in xy plane { subdivideCylinder(vdata[0], vdata[1], depth, 0, 0.25); subdivideCylinder(vdata[1], vdata[2], depth, 0.25, 0.5); subdivideCylinder(vdata[2], vdata[3], depth, 0.5, 0.75); subdivideCylinder(vdata[3], vdata[0], depth, 0.75, 1.0); } drawColorCoord(float xlen, float ylen, float zlen) { // coordinate lines glBegin(GL_LINES); glMaterialfv(GL_FRONT, GL_EMISSION, red); glColor3f(1,0,0); glVertex3f(0,0,0); glVertex3f(0,0,zlen); glMaterialfv(GL_FRONT, GL_EMISSION, green); glColor3f(0,1,0); glVertex3f(0,0,0); glVertex3f(0,ylen, 0); glMaterialfv(GL_FRONT, GL_EMISSION, blue); glColor3f(0,0,1); glVertex3f(0,0,0); glVertex3f(xlen,0,0); glEnd(); // coordinate labels: X, Y, Z glPushMatrix(); glTranslatef(xlen,0.,0.); glScalef(xlen/Width,xlen/Width,1); glutStrokeCharacter(GLUT_STROKE_ROMAN, 'X'); glPopMatrix(); glPushMatrix(); glMaterialfv(GL_FRONT, GL_EMISSION, green); glColor3f(0,1,0); glTranslatef(0., ylen,0.); glScalef(ylen/Width,ylen/Width,1); glutStrokeCharacter(GLUT_STROKE_ROMAN, 'Y'); glPopMatrix(); glPushMatrix(); glMaterialfv(GL_FRONT, GL_EMISSION, red); glColor3f(1,0,0); glTranslatef(0., 0.,zlen); glScalef(zlen/Width,zlen/Width,1); glutStrokeCharacter(GLUT_STROKE_ROMAN, 'Z'); glPopMatrix(); glMaterialfv(GL_FRONT, GL_EMISSION, black); // turn emission off } myMaterialColor(float *myAmbient, float *myDiffuse, float *mySpecular, float *myEmission) { glMaterialfv(GL_FRONT, GL_AMBIENT, myAmbient); glMaterialfv(GL_FRONT, GL_DIFFUSE, myDiffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mySpecular); glMaterialfv(GL_FRONT, GL_EMISSION, myEmission); } void drawSolar(float E, float e, float M, float m) { float position[] = { 0., 0., 0., 1.}; float spot_direction[] = { -1., 0., 0., 1.}; float red[] = { 1., 0., 0., .3}; float green[] = { 0., 1., 0., .5}; float blue[] = { 0., 0., 1., .4}; float tilt=30; // Global coordinates glLineWidth(2); drawColorCoord(Width/6, Width/6, Width/6); glPushMatrix(); glRotatef(e, 0.0, 1.0, 0.0); // rotating around the "sun"; proceed angle glRotatef(tilt, 0.0, 0.0, 1.0); // tilt angle glTranslatef(0., 2.0*E, .0); glPushMatrix(); glTranslatef(0., E, .0); glScalef(E, E, E); enabletex = 1; // enable texture drawSphere(); enabletex = 0; // disable texture glPopMatrix(); glPushMatrix(); glScalef(E/2,2.0*E,E/2); glRotatef(90, 1.0, 0.0, 0.0); // orient the cone drawCone(); glPopMatrix(); glTranslatef(0., E/2, .0); glRotatef(m, 0.0, 1.0, 0.); // 1st moon rotating around the "earth" glPushMatrix(); glTranslatef(1.5*M, 0., 0.); glLineWidth(1); drawColorCoord(Width/4, Width/4, Width/4); glScalef(E/2,E/2,E/2); myMaterialColor(red, red, red, red); glLightfv(GL_LIGHT1, GL_POSITION, position); glEnable (GL_BLEND); glDepthMask (GL_FALSE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); drawSphere(); glPopMatrix(); glRotatef(120, 0.0, 1.0, 0.); // 2nd moon rotating around the "earth" glPushMatrix(); glTranslatef(1.5*M, 0., 0.); drawColorCoord(Width/4, Width/4, Width/4); glLightfv(GL_LIGHT2, GL_POSITION, position); glScalef(E/2,E/2,E/2); myMaterialColor(green, green, green, green); drawSphere(); glPopMatrix(); glRotatef(120, 0.0, 1.0, 0.); // 3rd moon rotating around the "earth" glTranslatef(1.5*M, 0., 0.); glLightfv(GL_LIGHT3, GL_POSITION, position); drawColorCoord(Width/4, Width/4, Width/4); glScalef(E/2,E/2,E/2); myMaterialColor(blue, blue, blue, blue); drawSphere(); glMaterialfv(GL_FRONT, GL_EMISSION, black); // turn off emission glDepthMask (GL_TRUE); glDisable (GL_BLEND); glPopMatrix(); } drawArm(float End1, float End2) { float scale; scale = End2-End1; glPushMatrix(); glRotatef(90.0, 0.0, 1.0, 0.0); glScalef(scale/5.0, scale/5.0, scale); glRotatef(cnt*10, 0.0, 0.0, 1.0); // roate the texture image IRIS drawCylinder(); // if (moonView) drawCylinder(); // else { // glTranslatef(0.0, 0.0, 0.5); // drawSphere(); // } glPopMatrix(); } static void drawRobot(float A, float B, float C, float alpha, float beta, float gama) { // Global coordinates glLineWidth(3); drawColorCoord(Width/4, Width/4, Width/4); myMaterialColor(blackish, white, white, black); glPushMatrix(); glRotatef (cnt, 0.0, 1.0, 0.0); glRotatef (alpha, 0.0, 0.0, 1.0); // R_z(alpha) is on top of the matrix stack enabletex = 1; // enable texture drawArm (O, A); glTranslatef (A, 0.0, 0.0); glRotatef (beta, 0.0, 0.0, 1.0); // R_z(alpha)T_x(A)R_z(beta) is on top of the matrix stack drawArm (A, B); glTranslatef (B-A, 0.0, 0.0); glRotatef (gama, 0.0, 0.0, 1.0); // R_z(alpha)T_x(A)R_z(beta)T_x(B)R_z(gama) is on top of the matrix stack drawArm (B, C); enabletex = 0; // disable texture // put the solar system at the end of the robot arm glTranslatef (C-B, 0.0, 0.0); drawSolar(Width/4, 2.5*cnt, Width/3, 3.5*cnt); glPopMatrix(); } void myLookat(float A, float B, float C, float alpha, float beta, float gama) { float alpha1=30; float E = Width/4, e = 2.5*cnt, M = Width/6, m = 1.5*cnt; glRotatef (-90., 0., 1., 0.); // camera facing the negative x axis glTranslatef(-M, 0., 0.); glRotatef(-m, 0.0, 1.0, 0.); // rotating around the "earth" glTranslatef(0., -E, 0.0); glRotatef(-alpha1, 0.0, 0.0, 1.0); // tilt angle glRotatef(-e, 0.0, 1.0, 0.0); // rotating around the "sun"; proceed angle glTranslatef (-C+B, 0.0, 0.0); glRotatef (-gama, 0.0, 0.0, 1.0); glTranslatef (-B+A, 0.0, 0.0); glRotatef (-beta, 0.0, 0.0, 1.0); glTranslatef (-A, 0., 0.); // at the end of A glRotatef (-alpha, 0.0, 0.0, 1.0); glRotatef (-cnt, 0.0, 1.0, 0.0); } void display(void) { cnt++; depth = (cnt/100) % 4; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (cnt % 500 > 350) drawTexture(-2.4*Width, -2.4*Height, -1.9*Width); if (cnt % 60 == 0) aalpha = -aalpha; if (cnt % 60 == 0) abeta = -abeta; if (cnt % 60 == 0) agama = -agama; alpha+= aalpha; beta+= abeta; gama+= agama; if (cnt % 100 < 50) moonView = 0; else moonView = 1; glPushMatrix(); if (moonView==1) myLookat(A, B, C, alpha, beta, gama); // look at the solar system from the moon point of view drawRobot(A, B, C, alpha, beta, gama); glPopMatrix(); glutSwapBuffers(); } init() { float position[] = { 0., 0., 1., 0.}; float fogColor[4] = {0., 0., 0., 1.0}; initTexture(); glEnable(GL_LIGHTING); glEnable(GL_NORMALIZE); glEnable(GL_CULL_FACE); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glEnable(GL_LIGHT2); glEnable(GL_LIGHT3); glLightfv(GL_LIGHT0, GL_POSITION, position); glLightfv(GL_LIGHT0, GL_AMBIENT, blackish); glLightfv(GL_LIGHT0, GL_DIFFUSE, whitish); glLightfv(GL_LIGHT0, GL_SPECULAR, whitish); glLightfv(GL_LIGHT1, GL_AMBIENT, redish); glLightfv(GL_LIGHT1, GL_DIFFUSE, red); glLightfv(GL_LIGHT1, GL_SPECULAR, red); glLightfv(GL_LIGHT2, GL_AMBIENT, greenish); glLightfv(GL_LIGHT2, GL_DIFFUSE, green); glLightfv(GL_LIGHT2, GL_SPECULAR, green); glLightfv(GL_LIGHT3, GL_AMBIENT, blueish); glLightfv(GL_LIGHT3, GL_DIFFUSE, blue); glLightfv(GL_LIGHT3, GL_SPECULAR, blue); glMaterialfv(GL_FRONT, GL_AMBIENT, blackish); glMaterialfv(GL_FRONT, GL_DIFFUSE, whitish); glMaterialfv(GL_FRONT, GL_SPECULAR, white); glMaterialf(GL_FRONT, GL_SHININESS, 100.0); glClearColor (0.0, 0.0, 0.0, 1.0); // glEnable(GL_FOG); // glFogi (GL_FOG_MODE, GL_EXP); // glFogi (GL_FOG_MODE, GL_EXP2); glFogi (GL_FOG_MODE, GL_LINEAR); glFogfv (GL_FOG_COLOR, fogColor); // glFogf (GL_FOG_DENSITY, 0.5/Width); glHint (GL_FOG_HINT, GL_DONT_CARE); glFogf (GL_FOG_START, 1.5*Width); glFogf (GL_FOG_END, 5.5*Width); } static void Reshape(int w, int h) { float zNear=w, zFar=5*w; Width = w; Height = h; // glClearColor (0.0, 0.0, 0.0, 1.0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); //initialize robot arm end pointions O = 0.0; A = (float) 4*w/8; B = (float) 7*w/8; C = (float) 9*w/8; glViewport (0, 0, w, h); // hardware set to use projection transformation matrix stack glMatrixMode (GL_PROJECTION); glLoadIdentity (); // glOrtho(-w, w, -h, h, -zNear, zFar); glFrustum(-w/2, w/2, -h/2, h/2, zNear, zFar); // hardware set to use model transformation matrix stack glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glTranslatef (0., 0., -3*w); // the origin is at the center between znear and zfar } static void Key(unsigned char key, int x, int y) { switch (key) { case ESC: exit(0); case SPACE: glRotatef(1., 1., 1., 1.); glutIdleFunc(display); break; default: glutIdleFunc(NULL); } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE); glutInitWindowSize(Width, Height); glutCreateWindow("Example: press SPACE & another key"); init(); glutKeyboardFunc(Key); glutReshapeFunc(Reshape); glutDisplayFunc(display); glutIdleFunc(display); glutMainLoop(); }