计算机图形学——二维卡通人物交互设计

根据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
  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值