OpenGL如何实现多段Bezier曲线拼接
小编这次要给大家分享的是OpenGL如何实现多段Bezier曲线拼接,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。
成都创新互联公司专注于象州网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供象州营销型网站建设,象州网站制作、象州网页设计、象州网站官网定制、成都微信小程序服务,打造象州网络公司原创品牌,更为您提供象州网站排名全网营销落地服务。
运行程序的交互方式有点类似corelDraw中的自由曲线绘制,或者photoShop中的钢笔自由路径绘制。
截图:
将BezierCurve封装成了一个类,代码如下:
#ifndef _BEZIERCURVE_H #define _BEZIERCURVE_H #include "vec3.hpp" #include#include #include using namespace std; //// 3次bezier曲线: 四个控制节点。曲线经过首末两个顶点。 class BezierCurve { public: //cell一共有四个控制顶点 // -cell经过V0和V3顶点, // -cell的始端相切于直线:(V0, V1) 和末端相切于(V2,V3) class BezierCell { public: BezierCell(int i0, int i1, int i2, int i3) { setValue(i0, i1, i2, i3); } void setValue(int i0, int i1, int i2, int i3) { ctrlVertxIndex[0] = i0; ctrlVertxIndex[1] = i1; ctrlVertxIndex[2] = i2; ctrlVertxIndex[3] = i3; } const int operator[](int index) const { if (index > 3 || index < 0) return -1; return ctrlVertxIndex[index]; } int ctrlVertxIndex[4]; }; enum eventType { LButtonDown = 0, MouseMove = 1, LButtonUp = 2 }; enum { Bezier3CtrlPnt = 4 }; BezierCurve() { clear(); } ~BezierCurve(){} void begin() { // 开启求值器 glEnable(GL_MAP1_VERTEX_3); clear(); } void mouseSynchro(eventType type, const Vec3d& v) //响应鼠标motion { ////////////////////////////////////////////////////////////////////////// //LButtonDown: 压入点 if (type == LButtonDown) { if (isFirstRender) //for the first cell { vertexVector.push_back(v); //push V0... vertexVector.push_back(v); //push V1... } else if ( cellRenderState() == cellRenderImple::Push ) //for any cell { vertexVector.push_back(v); //push V2... vertexVector.push_back(v); //push V3... cellRenderState.setChange(); //set the flag to change V3 cellNum++; //increase the cell counter } } ////////////////////////////////////////////////////////////////////////// //MouseMove: 动态更新相应的顶点数据 else if (type == MouseMove) { if (isFirstRender) //for the first cell { vertexVector.back() = v; //change the V1 immediately } else if ( cellRenderState() == cellRenderImple::Change )//for any cell { int vecSize = vertexVector.size(); vertexVector[vecSize-2] = v; //change the V2 immediately } } ////////////////////////////////////////////////////////////////////////// //LButtonUp: 为拼接做准备 else if (type == LButtonUp) { if (isFirstRender) { //只有第一个BezierCell可以编辑bezierCell的起始段:(V0,V1) isFirstRender = false; } else if ( cellRenderState() == cellRenderImple::Change) { //if finish the current cell's render //利用v1和中点v0计算出v2:(v1 + v2) / 2 = v0 //next cell begin: push the next cell's V1... int vecSize = vertexVector.size(); Vec3d v0 = vertexVector[vecSize-1]; Vec3d v1 = vertexVector[vecSize-2]; Vec3d v2 = 2 * v0 - v1; vertexVector.push_back(v2); //重置cellRenderFlag cellRenderState.setPush(); } } ////////////////////////////////////////////////////////////////////////// //更新数组的长度 _updateVertexNum(); } void end() { glDisable(GL_MAP1_VERTEX_3); } void renderCurve() { ////////////////////////////////////////////////////////////////////////// //rendering vertex... for (int i=0; i =2 ) { glEnable(GL_LINE_STIPPLE); { glLineStipple(1, 0x0101); glBegin(GL_LINES); { Vec3d v1 = vertexVector[vertexNum-1]; Vec3d v2 = vertexVector[vertexNum-2]; glVertex3dv(v1.getValue()); glVertex3dv(v2.getValue()); } glEnd(); }glDisable(GL_LINE_STIPPLE); } ////////////////////////////////////////////////////////////////////////// //if ( !_check() ) // return; //rendering bezier cells... system("CLS"); for (int i=0; i vertexVector; //顶点数组 class cellRenderImple { public: enum RenderStep { Push = 0, Change = 1 }; cellRenderImple(){ setPush(); } bool operator()(void) { return flag; } void setPush() { flag = Push; } void setChange() { flag = Change; } RenderStep flag; //cell的渲染状态 } cellRenderState; };
测试程序如下:
#include#include #include #include "BezierCurve.h" using namespace std; enum WindowSize{ WinWidth = 1024, WinHeight = 768 }; int g_Viewport[4]; double g_ModelMatrix[16]; double g_ProjMatrix[16]; BezierCurve myBezier; ////////////////////////////////////////////////////////////////////////// void init(); void display(); void reshape(int w, int h); void keyboard(unsigned char key, int x, int y); void mouse(int button, int state, int x, int y); void motion(int x, int y); int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize (WinWidth, WinHeight); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持创新互联。 init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc (keyboard); glutMouseFunc(mouse); glutMotionFunc(motion); glutMainLoop(); return 0; } void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); myBezier.begin(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 0.0); glPointSize(5.0); glPushMatrix(); { myBezier.renderCurve(); }glPopMatrix(); glutSwapBuffers(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w, 5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0); else glOrtho(-5.0*(GLfloat)w/(GLfloat)h, 5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; } } void mouse(int button, int state, int x, int y) { double vertex[3]; //获取矩阵信息 glGetIntegerv(GL_VIEWPORT, g_Viewport); glGetDoublev(GL_MODELVIEW_MATRIX, g_ModelMatrix); glGetDoublev(GL_PROJECTION_MATRIX, g_ProjMatrix); y = g_Viewport[3] - y; gluUnProject( x, y, 0, g_ModelMatrix, g_ProjMatrix, g_Viewport, &vertex[0], &vertex[1], &vertex[2] ); if (button==GLUT_LEFT && state==GLUT_DOWN) { myBezier.mouseSynchro( BezierCurve::LButtonDown, vertex ); glutSetCursor( GLUT_CURSOR_RIGHT_ARROW ); } else if (button == GLUT_LEFT && state == GLUT_UP) { myBezier.mouseSynchro( BezierCurve::LButtonUp, vertex ); } glutPostredisplay(); } ////////////////////////////////////////////////////////////////////////// // 计算控制节点 void motion(int x, int y) { double vertex[3]; glutSetCursor( GLUT_CURSOR_CROSSHAIR ); y = g_Viewport[3] - y; gluUnProject( x, y, 0, g_ModelMatrix, g_ProjMatrix, g_Viewport, &vertex[0], &vertex[1], &vertex[2] ); myBezier.mouseSynchro( BezierCurve::MouseMove, vertex ); glutPostRedisplay(); }
看完这篇关于OpenGL如何实现多段Bezier曲线拼接的文章,如果觉得文章内容写得不错的话,可以把它分享出去给更多人看到。
名称栏目:OpenGL如何实现多段Bezier曲线拼接
文章位置:http://ybzwz.com/article/ieeshg.html