山东大学 图形学 openGL实验一

本文介绍了一次使用OpenGL实现的图形学实验,通过鼠标交互设计和绘制卡通人物,支持颜色填充、反走样技术以及五官拖拽调整。此外,还实现了多边形区域的颜色选择、发型和衣服模板的存储与替换功能。
摘要由CSDN通过智能技术生成

根据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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值