[OpenGL]图形学课程设计:二维卡通人脸交互设计与控制
实验名称:二维卡通人脸交互设计与控制
实验要求:
- 根据OpenGL提供的直线,多边形绘制算法,实现基于鼠标交互的卡通人物设计与绘制。使用颜色填充与反走样技术对人脸进行绘制。实现对卡通人脸的交互控制,点击鼠标左键可以对人脸进行拖拽移动。按“↑”按键能够实现卡通人脸绕坐标原点进行旋转。附加要求:选中其中的一个多边形区域,点击鼠标右键,弹出一个菜单,可以对该区域进行不同颜色的选择。
实验步骤:左击选择对象,右击染色。按住向上箭头逆时针旋转,按住向下箭头顺时针旋转。
#include <Windows.h>#include <gl\glut.h>#include <stdio.h> #include<math.h>#define PI 3.14#define SIZE 512 #define FACE 1#define NOSE 2#define MOUTH 3#define HAIR 4#define BROW 5#define EYES 6static int FACE_COLOR = 7;static int NOSE_COLOR = 6;static int MOUTH_COLOR = 1;static int HAIR_COLOR = 4;static int BROW_COLOR = 5;static int EYES_COLOR = 0;static GLfloat theta = 0; static GLfloat t_x = 0;static GLfloat t_y = 0;int select_part = 0;static int o_x = 0;static int o_y = 0;#define WIN_WIDTH 500#define WIN_HEIGHT 500#define VIEW_WIDTH 2.2#define VIEW_HEIGHT 2.2static GLfloat colors[8][3] = { { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 1.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 1.0, 1.0, 0.0 }, { 1.0, 1.0, 1.0 } }; //画眼睛void drawEyes(){glBegin(GL_POLYGON); glVertex2f( -0.27, 0.12);glVertex2f( -0.27, 0.18);glVertex2f( -0.33, 0.18);glVertex2f( -0.33, 0.12);glEnd();glBegin(GL_POLYGON); glVertex2f( 0.27, 0.12);glVertex2f( 0.27, 0.18);glVertex2f( 0.33, 0.18);glVertex2f( 0.33, 0.12);glEnd();}//画眉毛void drawBrow(){glLineWidth(5); glBegin(GL_LINES); glVertex2f( -0.4, 0.3);glVertex2f( -0.2, 0.2);glVertex2f( 0.2, 0.2);glVertex2f( 0.4, 0.3);glEnd();}//画头发void drawHair(){glBegin( GL_TRIANGLE_FAN); glVertex2f( 0.4, 0.9);glVertex2f( -0.5, 0.8);glVertex2f( -0.8, 0.3);glVertex2f( 0.1, 0.5);glVertex2f( 0.2, 0.3);glVertex2f( 0.5, 0.5);glVertex2f( 0.8, 0.4);glEnd();}//画脸void drawFace(){glBegin(GL_POLYGON);glVertex2f( -0.5 , 0.5);glVertex2f( -0.4 , -0.5);glVertex2f( 0.0 , -0.8);glVertex2f( 0.4 , -0.5);glVertex2f( 0.5 , 0.5);glEnd();}//画嘴巴void drawMouth(){glBegin( GL_POLYGON);glVertex2f( -0.2, -0.4);glVertex2f( -0.1, -0.6);glVertex2f( 0.1, -0.6);glVertex2f( 0.2, -0.4);glEnd();}//画鼻子void drawNose(){glBegin( GL_TRIANGLES);glVertex2f( 0, 0.1);glVertex2f( -0.1, -0.3);glVertex2f( 0.1, -0.3);glEnd();}//绘制函数void drawObjects(GLenum mode) { if(mode == GL_SELECT) glLoadName(FACE);//画脸glColor3f(colors[FACE_COLOR][0],colors[FACE_COLOR][1],colors[FACE_COLOR][2]);drawFace();if(mode == GL_SELECT) glLoadName(NOSE);//画鼻子glColor3f(colors[NOSE_COLOR][0],colors[NOSE_COLOR][1],colors[NOSE_COLOR][2]);drawNose();if(mode == GL_SELECT) glLoadName(MOUTH);//画嘴巴glColor3f(colors[MOUTH_COLOR][0],colors[MOUTH_COLOR][1],colors[MOUTH_COLOR][2]);drawMouth();if(mode == GL_SELECT) glLoadName(HAIR);//画头发glColor3f(colors[HAIR_COLOR][0],colors[HAIR_COLOR][1],colors[HAIR_COLOR][2]);drawHair();if(mode == GL_SELECT) glLoadName(BROW);//画眉毛glColor3f(colors[BROW_COLOR][0],colors[BROW_COLOR][1],colors[BROW_COLOR][2]);drawBrow();if(mode == GL_SELECT) glLoadName(EYES);//画眼睛glColor3f(colors[EYES_COLOR][0],colors[EYES_COLOR][1],colors[EYES_COLOR][2]);drawEyes();} void myDisplay(){//清除缓存glClear(GL_COLOR_BUFFER_BIT);//旋转glLoadIdentity(); //如果是绕人脸原点//glTranslatef(t_x, t_y, 0.0); //glRotatef(theta, 0.0, 0.0, 1.0);//如果是绕系统原点glRotatef(theta, 0.0, 0.0, 1.0);glTranslatef(t_x, t_y, 0.0); //RANDER模式绘制物体drawObjects(GL_RENDER);//绘制glFlush(); }void myInit(){glClearColor(0.0, 0.0, 0.0, 1.0);}void myRreshape(int w, int h){glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-VIEW_WIDTH/2,VIEW_WIDTH/2,-VIEW_HEIGHT/2,VIEW_HEIGHT/2);glMatrixMode(GL_MODELVIEW); glLoadIdentity();//开启反走样glEnable( GL_BLEND);glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST);glEnable( GL_POLYGON_SMOOTH);glEnable( GL_POINT_SMOOTH);glEnable( GL_LINE_SMOOTH);}//处理点击事件void processHits (GLint hits, GLuint buffer[]) { unsigned int i, j; GLuint names, *ptr; printf("一共打中%d个!\n", hits); ptr=(GLuint *) buffer; for (i = 0; i < hits; i++) {/* for each hit */ names = *ptr;ptr+=3;for (j = 0; j < names; j++) { /* for each name */ if(*ptr==1){printf ("打脸\n");}else if(*ptr==2){printf ("鼻子\n"); select_part = NOSE;}else if(*ptr==3){printf ("嘴巴\n"); select_part = MOUTH;}else if(*ptr==4){printf ("头发\n"); select_part = HAIR;}else if(*ptr==5){printf ("眉毛\n"); select_part = BROW;}else if(*ptr==6){printf ("眼睛\n"); select_part = EYES;}ptr++; } } printf ("select_part:%d\n",select_part); } static bool left_down = false;//脸移动void myMouseMove(int x,int y){if(left_down){GLfloat d_x = (x - o_x) * VIEW_WIDTH / WIN_WIDTH;GLfloat d_y = (o_y - y) * VIEW_HEIGHT / WIN_HEIGHT;//如果绕着脸中心转//t_x += d_x;//t_y += d_y;//将鼠标偏移量旋转-thetat_x += d_x*cos(-2*PI*theta/360)-d_y*sin(-2*PI*theta/360);t_y += d_x*sin(-2*PI*theta/360)+d_y*cos(-2*PI*theta/360);//记录下鼠标的坐标o_x = x;o_y = y;glutPostRedisplay();}}//鼠标响应void myMouse(int button, int state, int x, int y){GLuint selectBuf[SIZE]; GLint hits; GLint viewport[4];if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {left_down = true;o_x = x;o_y = y;}if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {left_down = false;}if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { printf ("select_part:%d\n",select_part); glGetIntegerv(GL_VIEWPORT, viewport); glSelectBuffer (SIZE, selectBuf); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix((GLdouble) x, (GLdouble) (viewport[3] - y),3.0, 3.0, viewport); gluOrtho2D(-VIEW_WIDTH/2,VIEW_WIDTH/2,-VIEW_HEIGHT/2,VIEW_HEIGHT/2);drawObjects(GL_SELECT); glMatrixMode(GL_PROJECTION); glPopMatrix(); hits = glRenderMode(GL_RENDER); processHits(hits, selectBuf); } }void mySpecial(int key, int x, int y){switch (key) { case GLUT_KEY_UP: theta = (theta+10);glutPostRedisplay();break;case GLUT_KEY_DOWN: theta = (theta-10);glutPostRedisplay();break;} }void myKeyboard(unsigned char key, int x, int y){switch (key) { }}void main_menu(int index) { if(index == -1)return;switch (select_part) { case FACE:FACE_COLOR = index;break; case NOSE:NOSE_COLOR = index;break; case MOUTH:MOUTH_COLOR = index;break; case HAIR:HAIR_COLOR = index;break;case BROW:BROW_COLOR = index;break; case EYES:EYES_COLOR = index;break; }glutPostRedisplay();}void main(int argc,char** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowSize(500,500);glutInitWindowPosition(0,0);glutCreateWindow("OpenGL_01");myInit();glutReshapeFunc(myRreshape); glutDisplayFunc(myDisplay); glutMouseFunc(myMouse); glutKeyboardFunc(myKeyboard);glutSpecialFunc(mySpecial);glutMotionFunc(myMouseMove);//右击事件glutCreateMenu(main_menu); glutAddMenuEntry("左击选择染色对象", -1); glutAddMenuEntry("黑色", 0); glutAddMenuEntry("红色", 1); glutAddMenuEntry("绿色", 2); glutAddMenuEntry("蓝色", 3); glutAddMenuEntry("青色", 4); glutAddMenuEntry("紫色", 5); glutAddMenuEntry("黄色", 6); glutAddMenuEntry("白色", 7); glutAttachMenu(GLUT_RIGHT_BUTTON); glutMainLoop();}