/* This code is Copyright 2001 by Ben Woodhouse (ben@elf-stone.com). You have my permission to use it or parts of it in your own work, but please give credit where due. */ #include #include #include #include #include void crossProduct(float *c,float a[3], float b[3]); void normalize(float *vect); void getFaceNormal(float *norm,float pointa[3],float pointb[3],float pointc[3]); void initCube(void); static void redraw(void); int main(int argc, char **argv); struct { struct { float pos[3]; float col[3]; }ver[8]; struct { unsigned int ver[6]; float norm[3]; }quad[6]; }cube; typedef struct { float pos[4]; float diffuse[4]; float specular[4]; float ambient[4]; }light_t; light_t light={ {0,0,1,1}, //position (the final 1 means the light is positional) {1,1,1,1}, //diffuse {1,1,0,1}, //specular {1.1,0.1,0.1,1} //ambient }; int main(int argc, char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("Spinning cube"); glutDisplayFunc(redraw); glMatrixMode(GL_PROJECTION); gluPerspective(45, //view angle 1.0, //aspect ratio 10.0, //near clip 200.0);//far clip glMatrixMode(GL_MODELVIEW); initCube(); glEnable(GL_LIGHTING); //enables lighting glEnable(GL_LIGHT0); //enables a light glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1); //sets lighting to one-sided glEnable(GL_COLOR_MATERIAL); //causes lighting model to take glColor() calls //into account glColorMaterial(GL_FRONT,GL_DIFFUSE); float black[4]={0,0,0,0}; glMaterialfv(GL_FRONT,GL_AMBIENT,black); glMaterialfv(GL_FRONT,GL_SPECULAR,black); glEnable(GL_CULL_FACE); //glCullFace(GL_FRONT); glutMainLoop(); return 0; } void initCube(void) { //defines the position of each vertex float vertexPosDat[8][3]= { {-10, 10, 10}, //left,top,front {10, 10, 10}, //right,top,front {10, 10,-10}, //right,top,back {-10, 10,-10}, //left, top,back {-10,-10, 10}, //left,bottom,front {10, -10, 10}, //right,bottom,front {10, -10,-10}, //right,bottom,back {-10,-10,-10} //left,bottom,back }; //defines the colour of each vertex float vertexColDat[8][3]= { {0.5,0 ,0 }, //dark red {1 ,1 ,0.3}, //yellow {1 ,0 ,0 }, //red {0.5,1 ,0.2}, //dull yellow?? {1 ,1 ,0 }, //yellow {0.9,0.5,0 }, //orange {1 ,0.9,0.1}, //yellow {1 ,0 ,0 }, //red }; //defines the vertexes of each quad in anti-clockwise order unsigned int quadVerDat[6][4]= { {0,1,2,3}, //top {0,3,7,4}, //left {3,2,6,7}, //back {2,1,5,6}, //right {0,4,5,1}, //front {4,7,6,5}, //bottom }; int a,b; //put the vertex data into the cube struct for (a=0;a<8;++a) { for (b=0;b<3;++b) { cube.ver[a].pos[b]=vertexPosDat[a][b]; cube.ver[a].col[b]=vertexColDat[a][b]; } } //put the quad data into the cube struct for (a=0;a<6;++a) { for (b=0;b<4;++b) { cube.quad[a].ver[b]=quadVerDat[a][b]; } } //new //get the normals for the quads for (a=0;a<6;++a) { getFaceNormal(cube.quad[a].norm, cube.ver[ cube.quad[a].ver[2] ].pos, cube.ver[ cube.quad[a].ver[1] ].pos, cube.ver[ cube.quad[a].ver[0] ].pos); } } static void redraw(void) { static float rotateBy=0; int a,b; unsigned int currentVer; rotateBy+=0.1; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLightfv(GL_LIGHT0,GL_POSITION,light.pos); //updates the light's position glLightfv(GL_LIGHT0,GL_DIFFUSE,light.diffuse); //updates the light's diffuse colour glLightfv(GL_LIGHT0,GL_SPECULAR,light.specular); //updates the light's specular colour glLightfv(GL_LIGHT0,GL_AMBIENT,light.ambient); //updates the light's ambient colour glPushMatrix(); glTranslatef(0,0,-50); glRotatef(rotateBy,1,1,0); glBegin(GL_QUADS); for (a=0;a<6;++a) { glNormal3fv(cube.quad[ a ].norm); //sets the current normal to this quad's normal for (b=0;b<4;++b) { currentVer=cube.quad[a].ver[b]; glColor3fv(cube.ver[ currentVer ].col); glVertex3fv(cube.ver[ currentVer ].pos); } } glEnd(); glPopMatrix(); glutSwapBuffers(); glutPostRedisplay(); } void getFaceNormal(float *norm,float pointa[3],float pointb[3],float pointc[3]) { float vect[2][3]; int a,b; float point[3][3]; for (a=0;a<3;++a) { point[0][a]=pointa[a]; //copies points into point[][] point[1][a]=pointb[a]; point[2][a]=pointc[a]; } for (a=0;a<2;++a) //calculates vectors from point[0] to point[1] { //and point[0] to point[2] for (b=0;b<3;++b) { vect[a][b]=point[2-a][b]-point[0][b]; } } crossProduct(norm,vect[0],vect[1]); //calculates vector at 90° to to 2 vectors normalize(norm); //makes the vector length 1 } void normalize(float * vect) //scales a vector a length of 1 { float length; int a; length=sqrt( //A^2 + B^2 + C^2 = length^2 pow(vect[0],2)+ pow(vect[1],2)+ pow(vect[2],2) ); for (a=0;a<3;++a) //divides vector by its length to normalise { vect[a]/=length; } } void crossProduct(float *c,float a[3], float b[3]) //finds the cross product of two vectors { c[0]=a[1]*b[2] - b[1]*a[2]; c[1]=a[2]*b[0] - b[2]*a[0]; c[2]=a[0]*b[1] - b[0]*a[1]; }