// glutSpin - modification of dinospin by Mark Kilgard /* New GLUT 3.0 glutGetModifiers() functionality used to make Shift-Left mouse scale the dinosaur's size. */ #include #include #include #include /* for cos(), sin(), and sqrt() */ #include #include "trackball.h" int spinning = 0, moving = 0; int beginx, beginy; int W = 300, H = 300; float curquat[4]; float lastquat[4]; GLdouble bodyWidth = 3.0; int newModel = 1; int scaling; float scalefactor = 1.0; /* *INDENT-OFF* */ GLfloat lightZeroPosition[] = {10.0, 4.0, 10.0, 1.0}; GLfloat lightZeroColor[] = {.5, .5, .5, 1.0}; GLfloat lightOnePosition[] = {-1.0, -2.0, 1.0, 0.0}; GLfloat lightOneColor[] = {1, 1, 1, 1.0}; GLboolean lightZeroSwitch = GL_TRUE, lightOneSwitch = GL_FALSE; /* *INDENT-ON* */ #define V 21 // Number of points of resolution #define RES V #define Z 5 float *vtx; float *clr1, *clr2; float *p, *p1; // // makeModel() calculate the vertex values // void makeModel(void) { int xi, yi; float vx, vy; // Allocate array vtx = malloc(sizeof (float) * RES * RES * 3); p = vtx; // Calculate the vertex data for(xi = 0; xi < V; xi++) { for(yi = 0; yi < V; yi++) { p[0] = (float) xi / (RES - 1.0) * V; p[1] = (float) yi / (RES - 1.0) * V; // Normalize x & y to +/- 3.0 range vx = ((float) xi / (RES - 1.0) - 0.5) * 6.0; vy = ((float) yi / (RES - 1.0) - 0.5) * 6.0; // Calculate function p[2] = cos(vx) * sin(vy) * 4.0; p+=3; } } // Allocate color array s clr1 = malloc(sizeof (float) * RES * RES * 3); clr2 = malloc(sizeof (float) * RES * RES * 3); p = clr1; p1 = clr2; for(xi = 0; xi < V; xi++) { for(yi = 0; yi < V; yi++) { // Red & White Stripes for the first color array if((xi % 2) == 0) { p[0] = 1.0; p[1] = 1.0; p[2] = 1.0; } else { p[0] = 1.0; p[1] = 0.0; p[2] = 0.0; } p += 3; // Green & Yellow diagonal stripes for the second color array if(((xi + yi)%2) == 0) { p1[0] = 0.0; p1[1] = 1.0; p1[2] = 0.0; } else { p1[0] = 1.0; p1[1] = 1.0; p1[2] = 0.0; // Yellow is the absense of blue! } p1 += 3; } } } void recalcModelView(void) { GLfloat m[4][4]; glPopMatrix(); glPushMatrix(); build_rotmatrix(m, curquat); glMultMatrixf(&m[0][0]); if (scalefactor == 1.0) { glDisable(GL_NORMALIZE); } else { glEnable(GL_NORMALIZE); } glScalef(scalefactor, scalefactor, scalefactor); glTranslatef(-8, -8, -bodyWidth / 2); newModel = 0; } void drawSurface() { int xi, yi; int x = V, y = V; float *v1, *v2; float *c1, *c2; v1 = vtx; if(lightZeroSwitch) c1 = clr1; else c1 = clr2; // Point to the next row of data v2 = v1 + (RES * 3); c2 = c1 + (RES * 3); for(yi = 0; yi < RES-1; yi++) { glBegin(GL_TRIANGLE_STRIP); for(xi = 0; xi < RES; xi++) { glColor3fv(c1); glVertex3fv(v1); glColor3fv(c2); glVertex3fv(v2); v1 += 3; v2 += 3; c1 += 3; c2 += 3; } glEnd(); } } // redraw() Draw the object and swap buffers void redraw(void) { if (newModel) recalcModelView(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawSurface(); glutSwapBuffers(); } void myReshape(int w, int h) { glViewport(0, 0, w, h); W = w; H = h; } void mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { spinning = 0; glutIdleFunc(NULL); moving = 1; beginx = x; beginy = y; if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) { scaling = 1; } else { scaling = 0; } } if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { moving = 0; } } void animate(void) { add_quats(lastquat, curquat, curquat); newModel = 1; glutPostRedisplay(); } void motion(int x, int y) { if (scaling) { scalefactor = scalefactor * (1.0 + (((float) (beginy - y)) / H)); beginx = x; beginy = y; newModel = 1; glutPostRedisplay(); return; } if (moving) { trackball(lastquat, (2.0 * beginx - W) / W, (H - 2.0 * beginy) / H, (2.0 * x - W) / W, (H - 2.0 * y) / H ); beginx = x; beginy = y; spinning = 1; glutIdleFunc(animate); } } void controlLights(int value) { switch (value) { case 1: lightZeroSwitch = !lightZeroSwitch; if (lightZeroSwitch) { glEnable(GL_LIGHT0); } else { glDisable(GL_LIGHT0); } break; case 2: lightOneSwitch = !lightOneSwitch; if (lightOneSwitch) { glEnable(GL_LIGHT1); } else { glDisable(GL_LIGHT1); } break; #ifdef GL_MULTISAMPLE_SGIS case 3: if (glIsEnabled(GL_MULTISAMPLE_SGIS)) { glDisable(GL_MULTISAMPLE_SGIS); } else { glEnable(GL_MULTISAMPLE_SGIS); } break; #endif case 4: glutFullScreen(); break; case 5: exit(0); break; } glutPostRedisplay(); } void vis(int visible) { if (visible == GLUT_VISIBLE) { if (spinning) glutIdleFunc(animate); } else { if (spinning) glutIdleFunc(NULL); } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); trackball(curquat, 0.0, 0.0, 0.0, 0.0); glutCreateWindow("glutSpin"); glutDisplayFunc(redraw); glutReshapeFunc(myReshape); glutVisibilityFunc(vis); glutMouseFunc(mouse); glutMotionFunc(motion); glutCreateMenu(controlLights); glutAddMenuEntry("Toggle color array", 1); //glutAddMenuEntry("Toggle left light", 2); if (glutGet(GLUT_WINDOW_NUM_SAMPLES) > 0) { glutAddMenuEntry("Toggle multisampling", 3); glutSetWindowTitle("dinospin (multisample capable)"); } glutAddMenuEntry("Full screen", 4); glutAddMenuEntry("Quit", 5); glutAttachMenu(GLUT_RIGHT_BUTTON); makeModel(); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); //glEnable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); gluPerspective( /* field of view in degree */ 40.0, /* aspect ratio */ 1.0, /* Z near */ 1.0, /* Z far */ 40.0); glMatrixMode(GL_MODELVIEW); gluLookAt(0.0, 0.0, 30.0, /* eye is at (0,0,30) */ 0.0, 0.0, 0.0, /* center is at (0,0,0) */ 0.0, 1.0, 0.); /* up is in positive Y direction */ glPushMatrix(); /* dummy push so we can pop on model recalc */ //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor); //glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1); //glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05); glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition); glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor); glEnable(GL_LIGHT0); glDisable(GL_LIGHT1); glLineWidth(2.0); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }