根据OpenGL提供的直线,多边形绘制算法(橡皮筋效果),实现基于鼠标交互的卡通人物设计与绘制。使用颜色填充与反走样技术对卡通人物外貌以及衣着进行绘制。实现对卡通人物轮廓的交互控制,点击鼠标左键可以对人物五官位置进行拖拽移动调整。按“↑”按键能够实现卡通人物绕坐标原点(或指定点)进行旋转。
附加要求:选中其中的一个多边形区域,点击鼠标右键,弹出一个菜单,可以对该区域进行不同颜色的选择。可以设计发型、衣服的模版,当作文件进行存储,可以在窗口最右边设计一个模板库,显示保存的发型与衣服,拖拽到卡通人物上可以为卡通人物进行发型或者衣服的替换。
#include<iostream>
#include <windows.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
using namespace std;
#define MAX_CHAR 128
int window_width = 600;
int window_height = 400;
#define LEFT_EYE 1
#define RIGHT_EYE 2
#define LEFT_ARM 3
#define RIGHT_ARM 4
#define JU_PAI 5
#define MOUTH 6
#define HAIR 7
#define TIE 8
#define BUFSIZE 512
GLuint selectBuf[BUFSIZE];
const double PI = 3.1415926;
static GLenum mode = GL_RENDER;
//判断被选中的是哪个物体
BOOL leftEye_Selected;
BOOL rightEye_selected;
BOOL leftArm_Selected;
BOOL rightArm_Selected;
BOOL juPai_Selected;
BOOL mouth_Selected;
BOOL hair_Selected;
BOOL tie_Selected;
/*
drawJuPai(100, 50);
drawMoxigan(220, 150);
glLoadName(RIGHT_ARM);
drawRightArm(-100, 0);
glLoadName(LEFT_ARM);
drawLeftArm(-100, 0);
glLoadName(MOUTH);
drawMouth(-100,60);
//画眼睛
glLoadName(LEFT_EYE);
drawLeftEye(-65,50);
glLoadName(RIGHT_EYE);
drawRightEye(-135,50);
*/
//物体初始坐标
GLuint leftEye[2] = { -65, 50 };
GLuint rightEye[2] = { -135, 50 };
GLuint leftArm[2] = { -50, 0 };
GLuint rightArm[2] = { -150, 0 };
GLuint juPai[2] = { 100, 50 };
GLuint mouth[2] = { -100, 60 };
GLuint hair[2] = { 220, 150 };
GLuint tie[2] = {
100,150};
int body[2] = { -100, 50 };
static int theta = 0;
//获取被选中改变颜色的物体
int selectedToChangeColor = -1;
//颜色数组
double lefteye_color[3] = { 1., 1., 1. };
double righteye_color[3] = { 1., 1., 1. };
double leftarm_color[3] = { 1., 1., 1. };
double rightarm_color[3] = { 1., 1., 1. };
double mouth_color[3] = { 1, 0.8, 0 };
double jupai_color[3] = { 1., 1., 1. };
double tie_color[3] = { 1.0, 0.5, 0 };
double hair_color[3] = { 0.8, 0.2, 0.8 };
//菜单颜色
double black[3] = { 0., 0., 0. };
double pink[3] = { 0.95, 0.62, 0.76 };
double yellowishbrown[3] = { 1, 0.8, 0 };
double oranger[3] = { 1.0, 0.5, 0 };
double brown[3] = {
0.5,0.25,0.};
double purple[3] = { 0.8, 0.2, 0.8 };
double white[3] = { 1.0, 1.0, 1.0 };
GLfloat fAspect;
void drawString(const char* str) {
static int isFirstCall = 1;
static GLuint lists;
if (isFirstCall) { // 如果是第一次调用,执行初始化
// 为每一个ASCII字符产生一个显示列表
isFirstCall = 0;
// 申请MAX_CHAR个连续的显示列表编号
lists = glGenLists(MAX_CHAR);
// 把每个字符的绘制命令都装到对应的显示列表中
wglUseFontBitmaps(wglGetCurrentDC(), 0, MAX_CHAR, lists);
}
// 调用每个字符对应的显示列表,绘制每个字符
for (; *str != '\0'; ++str)
glCallList(lists + *str);
}
//画圆(tianchong)
void drawCircle(int N, double radius, int angleStart = 0, int angleEnd = 360, double x = 0,double y=0,double s1=1.,double s2=1.){
glBegin(GL_POLYGON);
double start = (double)angleStart / 360.0*N;
double end = (double)angleEnd / 360 * N;
for (int i = start; i <end+1; i++){
glVertex3f(x+s1*cos(i * 2 * PI / N)*radius,y+ s2*sin(i * 2 * PI / N) *radius, 0.5);
}
glEnd();
}
//画圆(不填充)
void drawCircle2(int N, double radius, int angleStart = 0, int angleEnd = 360, int x = 0, int y = 0, double s1 = 1., double s2 = 1.){
glLineWidth(0.6);
glBegin(GL_LINE_STRIP);
double start = (double)angleStart / 360.0*N;
double end = (double)angleEnd / 360 * N;
for (int i = start; i <end+1; i++){
glVertex3f(x+s1*cos(i * 2 * PI / N)*radius,y + s2*sin(i * 2 * PI / N) *radius, 0.5);
}
glEnd();
}
//画左眼
void drawLeftEye(int x,int y){
glLoadIdentity();
glTranslatef(body[0], body[1], 0);
glRotatef(theta, 0, 0, 1);
glTranslatef(-body[0], -body[1], 0);
//睫毛
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_LINES);
glVertex3f(x+0,y+10,0.5);
glVertex3f(x+0, y+15, 0.5);
glVertex3f(x+5,y + 5*sqrt(3), 0.5);
glVertex3f(x+10, y+13, 0.5);
glVertex3f(x-5, y+5 * sqrt(3