现在的位置: 首页 > 综合 > 正文

[OpenGL]图形学课程设计:二维卡通人脸交互设计与控制

2013年11月02日 ⁄ 综合 ⁄ 共 6132字 ⁄ 字号 评论关闭

实验名称:二维卡通人脸交互设计与控制

实验要求:

  1. 根据OpenGL提供的直线,多边形绘制算法,实现基于鼠标交互的卡通人物设计与绘制。
  2. 使用颜色填充与反走样技术对人脸进行绘制。
  3. 实现对卡通人脸的交互控制,点击鼠标左键可以对人脸进行拖拽移动。
  4. 按“↑”按键能够实现卡通人脸绕坐标原点进行旋转。
  5. 附加要求:选中其中的一个多边形区域,点击鼠标右键,弹出一个菜单,可以对该区域进行不同颜色的选择。

实验步骤:左击选择对象,右击染色。按住向上箭头逆时针旋转,按住向下箭头顺时针旋转。

实验截图:

实验源码:

#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 6

static 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.2

static 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;

		
		//将鼠标偏移量旋转-theta
		t_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;
		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);   
		glPopMatrix();  
		glMatrixMode(GL_MODELVIEW); 
		hits = glRenderMode(GL_RENDER);  
		processHits(hits, selectBuf); 
		glutPostRedisplay();
	}  
}

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();

}

抱歉!评论已关闭.