/* A 2D Bezier surface, built as part of a class exercise. Written by Scott D. Anderson scott.anderson@acm.org Fall 2007 */ #include #include // for atoi and exit #include #include "bezier-utils.h" bool Wirep = true; bool ShowControlPointsp = true; void heartHalfCurve( GLfloat height ) { const int Order = 4; GLfloat h=height; // shorthand GLfloat cp[Order*3] = { 0,0,0, // first point of heart curve 1,1,0, // second point of heart curve 1,-h+1,0, // third point of heart curve 0,-h,0 // fourth point of heart curve }; if(ShowControlPointsp) drawBezierCurveControlPoints(Order,3,cp); drawBezierCurve(Order,3,16,cp); } /* The width of the heart is 1 (at least, its control points) and the height, from dent to point, is determined by the argument. The origin is at the dent, and the point is on the negative Y axis. The heart comes out (along Z) by 0.5. */ void heartHalfSurface( GLfloat height ) { // U varies fastest through the array, V slowest. // Our heart curve is along V. const int U_Order = 3; const int V_Order = 4; const GLfloat f=1/-3.0; // move down by thirds GLfloat h=height; // shorthand GLfloat cp[U_Order*V_Order*3] = { // they all come together at the dent 0,0,0, 0,0,0, 0,0,0, // first point of heart curve 0,h*f,0.5, 0.5,h*f,0.5, 1,1,0, // second point of heart curve 0,2*h*f,0.5, 0.5,2*h*f,0.5, 1,-h+1,0, // third point of heart curve 0,-h,0, 0,-h,0, 0,-h,0 // fourth point of heart curve }; if(ShowControlPointsp) drawBezierSurfaceControlPoints(U_Order,3,V_Order,3*U_Order,cp); drawBezierSurface(Wirep?GL_LINE:GL_FILL, U_Order,16,V_Order,16,cp); } /* Same as heart half, except we do both sides with one surface. This gives us less control left-to-right, but is simpler. */ void heartWholeSurface( GLfloat height ) { // U varies fastest through the array, V slowest. // Our heart curve is along V. const int U_Order = 3; const int V_Order = 4; const GLfloat f=1/-3.0; // move down by thirds GLfloat h=height; // shorthand GLfloat cp[U_Order*V_Order*3] = { // they all come together at the dent 0,0,0, 0,0,0, 0,0,0, // first point of heart curve -1,1,0, 0,h*f,0.5, +1,1,0, // second point of heart curve -1,-h+1,0, 0,2*h*f,0.5, +1,-h+1,0, // third point of heart curve 0,-h,0, 0,-h,0, 0,-h,0 // fourth point of heart curve }; if(ShowControlPointsp) drawBezierSurfaceControlPoints(U_Order,3,V_Order,3*U_Order,cp); drawBezierSurface(Wirep?GL_LINE:GL_FILL, U_Order,16,V_Order,16,cp); } GLfloat HeartHeight = 2; void display(void) { twError(); twDisplayInit(); twCamera(); glPushAttrib(GL_ALL_ATTRIB_BITS); glColor3f(1,0,0); // red hearts heartHalfCurve(HeartHeight); glPushMatrix(); glTranslatef(2,0,0); heartHalfSurface(HeartHeight); glPopMatrix(); glPushMatrix(); glTranslatef(-2,0,0); heartWholeSurface(HeartHeight); glPopMatrix(); twError(); glPopAttrib(); glFlush(); glutSwapBuffers(); } void toggles(unsigned char key, int x, int y) { switch(key) { case 'w': Wirep = !Wirep; break; case 'c': ShowControlPointsp = !ShowControlPointsp; break; } glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); if( argc > 1 ) { HeartHeight = atof(argv[1]); } twInitWindowSize(500,500); glutCreateWindow(argv[0]); twError(); glutDisplayFunc(display); twError(); twBoundingBox(-4,+4, -2,+2, -1,1); twMainInit(); twKeyCallback('w',toggles,"toggle wireframe"); twKeyCallback('c',toggles,"toggle showing control points"); //printBezierSurfaceControlPoints(U_Order,3,V_Order,3*U_Order,control_points); glutMainLoop(); return 0; }