openGL利用贝塞尔曲线【Bézier curve】写汉字,seedfilling 填充算法
直接贴代码
#include <stack>
#include<GL\glut.h>
#include <iostream>
using namespace std;
#define drawed true
#define undraw false
#define width 498
#define height 444
GLubyte iPixel[3];
GLubyte borderColor[3]{0,0,0 };
GLubyte fillColor[3]{ 0,0,0 };
GLubyte bgColor[3]{255,255,255};
bool isDraw = 0;
struct Point
{
int x;
int y;
};
using namespace std;
int control_p[48][2] = {
{146,13}, {163,9}, {178,8}, {197,4},
{197,4}, {195,54}, {189,97}, {184,133},
{184,133},{250,119},{403,97}, {385,113},
{385,113},{331,162},{249,151},{182,164},
{182,164},{180,175},{177,184},{173,196},
{173,196},{330,332},{441,303},{494,440},
{494,440},{330,386},{223,276},{168,216},
{168,216},{117,332},{59,386}, {5,385},
{5,385}, {86,314},{124,228},{140,166},
{140,166}, {98,178},{15,201}, {14,183},
{14,183}, {16,167},{102,151},{145,142},
{145,142},{152,98}, {149,47}, {146,13} };
int xx, yy;//new point
int drag = 0;
int cps[2]{0};
int pos;
bool mouseDown = 0;
void glPoint(int x, int y, GLubyte fill[]) {
glColor3ub(fill[0], fill[1],fill[2]);
glPointSize(1);
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
glFlush();
}
bool Issamecolor(GLubyte a[], GLubyte b[]) { //if same return 1 or return 0
if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) {
return true;
}
else return false;
}
void seedFill(int startX, int startY, GLubyte fill_color[]) {
stack<Point> pixelStack;
Point ortherP{ };
Point tempPoint{};
Point point = { startX,startY };
pixelStack.push(point);
//如果栈不为空
while (!pixelStack.empty()) {
tempPoint = pixelStack.top();
pixelStack.pop();
glReadPixels(tempPoint.x, height - tempPoint.y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, iPixel);//pc=get (x,y) px;
if (!Issamecolor(iPixel, borderColor) && !Issamecolor(iPixel, fill_color)) {
glPoint(tempPoint.x, tempPoint.y, fill_color);
ortherP = { tempPoint .x-1,tempPoint .y};//left
pixelStack.push(ortherP);
ortherP = { tempPoint.x + 1,tempPoint.y };//right
pixelStack.push(ortherP);
ortherP = { tempPoint.x ,tempPoint.y-1};//up
pixelStack.push(ortherP);
ortherP = { tempPoint.x ,tempPoint.y+1 };//down
pixelStack.push(ortherP);
}
}
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
if (drag == 1) //update the position of first control point
{
control_p[pos][0] = xx; cout << "xx: " << xx << endl;
control_p[pos][1] = yy; cout << "yy: " << yy << endl;
}
glColor3f(0, 1, 0);//draw the line
glBegin(GL_LINES);
for (int i = 0; i < 47; i++) {
glVertex2i(control_p[i][0], control_p[i][1]);
glVertex2i(control_p[i + 1][0], control_p[i + 1][1]);
}
glEnd();
glPointSize(7); //draw big control points
glBegin(GL_POINTS);
for (int i = 0; i < 48;i+=4) {
glColor3f(0, 0.0, 0.0);
glVertex2iv(control_p[i]); glVertex2iv(control_p[i+3]);
glColor3f(0, 0.0, 1.0);
glVertex2iv(control_p[i +1]); glVertex2iv(control_p[i +2]);
}
glEnd();
for (int i = 0; i < 48; i=i+4) // draw 12 bezier curve
{
glBegin(GL_LINE_STRIP); //connect points to line
glColor3f(0, 0.0, 0.0);//绘图颜色黑色
for (float t = 0; t < 1.0000001; t = t + 0.01)
{
cps[0] =(float) control_p[i][0] * (1 - t) * (1 - t)* (1 - t) + 3 * (float)control_p[i+1][0] *
t * (1 - t) * (1 - t) + 3 * (float)control_p[i+2][0] * t * t * (1 - t) + (float)control_p[i + 3][0] * t * t * t;
cps[1] = (float)control_p[i][1] * (1 - t) * (1 - t) * (1 - t) + 3 * (float)control_p[i + 1][1] *
t * (1 - t) * (1 - t) + 3 * (float)control_p[i + 2][1] * t * t * (1 - t) + (float)control_p[i + 3][1] * t * t * t;
glVertex2iv(cps);
}
glEnd();
};
seedFill(159, 40, bgColor);//先填bgcolor色
seedFill(159, 40, fillColor);//再填fillcolor色
drag = 0;//reset drag
}
void mouse(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON) //left button
{
if (state == GLUT_DOWN) //pressed down
{
for (int i = 0; i < 48; i++) // check each of the 48 control points
{
if (x > control_p[i][0] - 7 && x < control_p[i][0] + 7 && y > control_p[i][1] - 7 && y < control_p[i][1] + 7) {
mouseDown = 1;// 空白位置乱按,鼠标不用变形 obtain the current position by(x, y)
pos = i;
//glutPostRedisplay(); //告诉display( ),there is updating,re draw it according to the new value
cout << "mouse DOWN" << endl;
break;
}
}
}
else if(state == GLUT_UP) {
if (mouseDown == 1) {
drag = 1;
xx = x;
yy = y;
cout << "mouse UP" << endl;
}
}
else {
drag = 0;
}//if not pressed,set drag=0, do not need a cross shape
}
}
void motion(int x, int y) { // deal with the event of mouse move
if (isDraw == undraw) {//first draw
isDraw = drawed;
glutDisplayFunc(display);
}
else {
if (drag == 1) // if it is in the drag mode
{
cout << "it will redisplay ,drag="<<drag<<endl;
glutPostRedisplay();
}
}
}
void main(int arge, char** argv)
{
glutInit(&arge, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(200, 100); // Init position window
glutInitWindowSize(width, height); //size of window
glutCreateWindow("da"); // name of window
//converse();
glClearColor(1.0, 1.0, 1.0, 0); //设定背景白色
glMatrixMode(GL_PROJECTION);//设定投影方式
gluOrtho2D(0.0, width, height,0.0);
glutMouseFunc(mouse); //interaction of mouse button
glutMotionFunc(motion); //mouse movement
glutMainLoop();
int a;
std::cin >> a;
}
注: 注解和代码存在多种问题,有待修改,先挂起来。
引用
使用seedfilling算法 要使用C++的stack,感谢这位博主,参考了ta很多的内容。
OpenGL绘图实例三之种子填充算法.