欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

openGL画线算法,橡皮筋算法

程序员文章站 2022-07-04 15:00:53
...

计算机图形学里面的橡皮筋算法,具体解释已经包含在代码中,看代码应该就可以理解了

#include<gl/glut.h>
#include"datastruct.h"                    //导入头文件

static const  int screenwidth = 1000;    //自定义窗口宽度
static const int screenheight = 1000;     //自定义窗口高度
vector<point> p; //多边形点集向量
vector<polygon> s; //多边形类向量,用来保存已经画完的多边形
int move_x,move_y; //鼠标当前坐标值,在鼠标移动动态画线时使用
bool select = false; //多边形封闭状态判断变量,当为true时即按下鼠标右键,将多边形封闭
bool judge = false;
float red=1.0, green=0.0, blue=0.0;
int lineWidth=1;   //使用此来改变线段的样式
GLuint Line;

void init()
{
	glClearColor(1.0,1.0,1.0,0.0);              // glClearColor 的作用是,指定刷新颜色缓冲区时所用的颜色
	glMatrixMode(GL_PROJECTION);               //https://blog.csdn.net/caoshangpa/article/details/80266028
	gluOrtho2D(0.0,screenwidth,0.0,screenheight);         //对应的模型坐标范围
}
void lineSegment()
{
	glClear(GL_COLOR_BUFFER_BIT);    //清除颜色缓冲区的作用是,防止缓冲区中原有的颜色信息影响本次绘图
	glColor3f(red,green,blue);   //通过改变red, green,blue设定颜色,既是线段颜色也是填充色
	int num=0;//两个循环控制变量,在下面的向量循环和数组循环中将被多次调用。
	if(judge){
		if(!p.empty()) 
		{
			//Line = glGenLists(1);
			//glNewList(Line, GL_COMPILE);
			//	int i = p.size() - 1; //将确定的最后一个点与当前鼠标所在位置连线,即动态画线
			glBegin(GL_LINES);
			glVertex2i(p[num].x, p[num].y);    //将鼠标点击的左边点与鼠标当前点画出
			glVertex2i(move_x, move_y);
			glEnd();		 
		}
	}
	glFlush();
}
void myMouse(int button, int state ,int x, int y) //鼠标点击事件响应函数
{
	if(state == GLUT_DOWN && button == GLUT_LEFT_BUTTON)//当鼠标左键被点击
	{
		int num = p.size();
		if(!p.empty()){               //将栈里面的vector元素全部弹出,目的使画第二条线的时候将第一条直线删除
			for(int i = 0;i<num;i++){
				p.pop_back();
			}
		}
		point v;   //申请一个点类变量,点类为自定义类,在zl.h中定义
		v.x = x;   //将点击处的点坐标,即x和y的值存入v中
		v.y = screenheight - y;    
		p.push_back(v);    //将点信息存入多边形点集向量p中
		glutPostRedisplay();   //重绘窗口
	}

	if(state == GLUT_UP && button == GLUT_LEFT_BUTTON) //判断鼠标是不是松开,如如果鼠标松开则下一次点击鼠标左键的时候不会将线段连接
	{
		judge = false;
	}
}
void myMotionFunc(int x, int y) //鼠标移动事件响应函数
{
	move_x = x;          //保存当前鼠标所在的坐标的值
	move_y = screenheight - y;
	judge = true;            //对按下的按键进行判断如果松开鼠标并且进行移动则将线画出来
	glutPostRedisplay();
}

void processSpqcialKeys(int key, int x, int y){       //按下按键改变线条的颜色
	if (key == 27) 
		exit(0);
	switch (key) 
	{
	case GLUT_KEY_F1:              //当点击鼠标上F1键的时候改变线段的颜色
		red = 0.5;
		green = 0.5;
		blue = 0.0;
		break;
	case GLUT_KEY_F2:
		red = 0.0;
		green = 1.0;
		blue = 0.0;
		break;
	case GLUT_KEY_F3:
		red = 0.0;
		green = 0.0;
		blue = 1.0;
		break;
	case GLUT_KEY_UP:             //按键盘上的向上的方向键则将线段调粗
		lineWidth = lineWidth+2;
		glLineWidth(lineWidth);
		break;
	case GLUT_KEY_DOWN:  //按键盘上的向上的方向键则将线段调细
		lineWidth = lineWidth-2;
		glLineWidth(lineWidth);
		break;
	default:
		break;
	}
}

//此时注意按键的时候按住CTRL+a,此时a的ascall改变成1,z变成26其他的按此规律改变 
void processNormalKey(unsigned char key, int x, int y){   //使用组合键改变线段的颜色
	printf("shift:%d ",key);
	int mod = glutGetModifiers();
	if(mod == GLUT_ACTIVE_CTRL )   //按住CTRL+a 改变线段的颜色
	{
		if(key == 1)       //对应a
		{
			red = 1.0;
			green = 0.0;
			blue = 0.0;
		}
		if(key == 26)    //对应CTRL+z
		{
			red = 0.0;
			green = 1.0;
			blue = 0.0;
		}
		else if(key == 24)   //对应CTRL+x
		{
			red = 0.0;
			green = 0.0;
			blue = 1.0;
		}
		else
		{
			red = 1.0;
		}

	}
	else if(mod == GLUT_ACTIVE_SHIFT){    //按住shift + a时,将实线换成虚线,并且对应不同的格式
		if(key == 65)
		{
			glEnable(GL_LINE_STIPPLE);
			glLineStipple(2, 0x4444);  
			//printf("画线ok");   //对应a
		}
		else if(key == 90)    //对应z
		{
			glEnable(GL_LINE_STIPPLE);
			glLineStipple(2, 0xffcc);
			//printf("画线ok2");
		}
		else if(key == 88)   //对应x  将虚线换成实线
		{
			//Line = glGenLists(1);
			//glNewList(Line, GL_COMPILE);
			glDisable(GL_LINE_STIPPLE);           //此时将虚线的格式取消则回到原来的实线模式
			//glEnable(GL_LINES);
			//glTranslatef(-50.0, 20.0, 0.0);
			//printf("画线ok3");
		}
	}
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(50,100);
	glutInitWindowSize(screenwidth,screenheight);
	glutCreateWindow("橡皮筋算法");
	init();
	glutMouseFunc(myMouse); //鼠标点击消息监控,即监控鼠标是否被点击,若被点击就调用myMouse函数
	glutDisplayFunc(lineSegment);//1.  窗口内容绘制2.   窗口大小改变3.   窗口重绘  会重绘窗口
	glutMotionFunc(myMotionFunc); //鼠标移动消息监控,即监控鼠标是否移动,若移动就调用myPassiveMotion函数
	glutSpecialFunc(processSpqcialKeys);         //改变按下按键改变按键的颜色,以及线条的粗细
	glutKeyboardFunc(processNormalKey);       //当有组合键按下时改变线段的颜色
	glutMainLoop();
	return 0;
}

头文件

#ifndef DATA_H_         //if not define-如果没有定义头文件,就编译一下,若头文件已经存在就不再重复编译  
#define DATA_H_
#include<vector>
using namespace std;
class point //点类,存储了一个点的两坐标值
{
public:
	int x;
	int y;
};
class polygon             //多边形类,存了一个多边形
{
public:
	vector<point> p;                  //多边形的顶点
};
#endif
相关标签: opengl graphql