/* A Bezier surface, coded in plain C++. Written by Scott D. Anderson scott.anderson@acm.org Fall 2007 */ #include #include // for atoi and exit #include int Order = 0; // must be 2, 3, or 4. Checked in the function bool Wirep = true; bool Texturep = true; /* ================================================================================ Some control-point arrays for Bezier patches. All of them are flat (all Z components are zero), and symmetrical across both X and Y. The corners form an 8x4 rectangle. The order 4 and order 3 versions are roughly oval, with derivatives at the corner of 45 degrees; the order 2 is obviously a rectangle. */ GLfloat spatial_cp_order2[2*2*3] = { // top row, left to right -4, +2, 0, +4, +2, 0, -4, -2, 0, +4, -2, 0 }; GLfloat spatial_cp_order3[3*3*3] = { // top row, left to right -4, +2, 0, 0, +6, 0, +4, +2, 0, -6, 0, 0, 0, 0, 0, +6, 0, 0, -4, -2, 0, 0, -6, 0, +4, -2, 0 }; GLfloat spatial_cp_order4[4*4*3] = { // top row, left to right -4, +2, 0, -2, +4, 0, +2, +4, 0, +4, +2, 0 , -5, +1, 0, -2, +1, 0, +2, +1, 0, +5, +1, 0 , -5, -1, 0, -2, -1, 0, +2, -1, 0, +5, -1, 0 , -4, -2, 0, -2, -4, 0, +2, -4, 0, +4, -2, 0 }; GLfloat texture_cp[4*4*2] = { // top row, left to right 0, 0, 1, 0, 0, 1, 1, 1 }; void bezier_patch(int order) { GLfloat* cp; switch(order) { case 2: glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 2, 0, 1, 6, 2, spatial_cp_order2); glEnable(GL_MAP2_VERTEX_3); cp = spatial_cp_order2; break; case 3: glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 3, 0, 1, 9, 3, spatial_cp_order3); glEnable(GL_MAP2_VERTEX_3); cp = spatial_cp_order3; break; case 4: glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, spatial_cp_order4); glEnable(GL_MAP2_VERTEX_3); cp = spatial_cp_order4; break; default: fprintf(stderr,"Invalid order: %d\n", order); } // Show the control points, for debugging glPushAttrib(GL_ALL_ATTRIB_BITS); glColor3f(0,0,0); glPointSize(6); glBegin(GL_POINTS); for( int i=0; i<3*order*order; i+=3 ) { glVertex3fv(&cp[i]); // printf("%d: %f %f %f\n", i, cp[i], cp[i+1], cp[i+2]); } glEnd(); glPopAttrib(); twError(); } void display(void) { twError(); twDisplayInit(); twCamera(); glPushAttrib(GL_ALL_ATTRIB_BITS); glColor3f(0,1,0); // green patch bezier_patch(Order); if( Texturep ) { glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, texture_cp); glEnable(GL_MAP2_TEXTURE_COORD_2); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); } else { glDisable(GL_TEXTURE_2D); } twError(); const int steps = 16; glMapGrid2f(steps,0,1,steps,0,1); glEvalMesh2( Wirep ? GL_LINE : GL_FILL, 0, steps, 0, steps ); twError(); glPopAttrib(); glFlush(); glutSwapBuffers(); } int main(int argc, char** argv) { if( argc != 4 ) { printf("Usage: %s Order Wirep Texturep\n",argv[0]); exit(0); } Order = atoi(argv[1]); Wirep = (atoi(argv[2]) == 1); Texturep = (atoi(argv[3]) == 1); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); twInitWindowSize(500,500); glutCreateWindow(argv[0]); twError(); glutDisplayFunc(display); twError(); twUSflag(); twBoundingBox(-4,+4, -2,+2, -1,1); twMainInit(); glutMainLoop(); return 0; }