根据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 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;
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
printf("select_part:%d\n", select_part);
glGetIntegerv(GL_VIEWPORT, vie