当前位置:首页 > 通信资讯 > 正文

本文实例为大家分享了OpenGL实现多段Bezier曲线拼接的具体代码,供大家参考,具体内容如下

运行程序的交互方式有点类似corelDraw中的自由曲线绘制,或者photoShop中的钢笔自由路径绘制。

截图:

基于opengl实现多段bezier曲线拼接(基于opengl实现多段bezier曲线拼接)

将BezierCurve封装成了一个类,代码如下:

  1. #ifndef _BEZIERCURVE_H
  2. #define _BEZIERCURVE_H
  3. #include "vec3.hpp"
  4. #include <vector>
  5. #include <iostream>
  6. #include <gl/glut.h>
  7. using namespace std;
  8. //// 3次bezier曲线: 四个控制节点。曲线经过首末两个顶点。
  9. class BezierCurve
  10. {
  11. public:
  12. //cell一共有四个控制顶点
  13. // -cell经过V0和V3顶点,
  14. // -cell的始端相切于直线:(V0, V1) 和末端相切于(V2,V3)
  15. class BezierCell
  16. {
  17. public:
  18. BezierCell(int i0, int i1, int i2, int i3)
  19. {
  20. setValue(i0, i1, i2, i3);
  21. }
  22. void setValue(int i0, int i1, int i2, int i3)
  23. {
  24. ctrlVertxIndex[0] = i0;
  25. ctrlVertxIndex[1] = i1;
  26. ctrlVertxIndex[2] = i2;
  27. ctrlVertxIndex[3] = i3;
  28. }
  29. const int operator[](int index) const
  30. {
  31. if (index > 3 || index < 0)
  32. return -1;
  33. return ctrlVertxIndex[index];
  34. }
  35. int ctrlVertxIndex[4];
  36. };
  37. enum eventType
  38. {
  39. LButtonDown = 0,
  40. MouseMove = 1,
  41. LButtonUp = 2
  42. };
  43. enum { Bezier3CtrlPnt = 4 };
  44. BezierCurve() { clear(); }
  45. ~BezierCurve(){}
  46. void begin()
  47. {
  48. // 开启求值器
  49. glEnable(GL_MAP1_VERTEX_3);
  50. clear();
  51. }
  52. void mouseSynchro(eventType type, const Vec3d& v) //响应鼠标motion
  53. {
  54. //////////////////////////////////////////////////////////////////////////
  55. //LButtonDown: 压入点
  56. if (type == LButtonDown)
  57. {
  58. if (isFirstRender) //for the first cell
  59. {
  60. vertexVector.push_back(v); //push V0...
  61. vertexVector.push_back(v); //push V1...
  62. }
  63. else if ( cellRenderState() == cellRenderImple::Push ) //for any cell
  64. {
  65. vertexVector.push_back(v); //push V2...
  66. vertexVector.push_back(v); //push V3...
  67. cellRenderState.setChange(); //set the flag to change V3
  68. cellNum++; //increase the cell counter
  69. }
  70. }
  71. //////////////////////////////////////////////////////////////////////////
  72. //MouseMove: 动态更新相应的顶点数据
  73. else if (type == MouseMove)
  74. {
  75. if (isFirstRender) //for the first cell
  76. {
  77. vertexVector.back() = v; //change the V1 immediately
  78. }
  79. else if ( cellRenderState() == cellRenderImple::Change )//for any cell
  80. {
  81. int vecSize = vertexVector.size();
  82. vertexVector[vecSize-2] = v; //change the V2 immediately
  83. }
  84. }
  85. //////////////////////////////////////////////////////////////////////////
  86. //LButtonUp: 为拼接做准备
  87. else if (type == LButtonUp)
  88. {
  89. if (isFirstRender)
  90. {
  91. //只有第一个BezierCell可以编辑bezierCell的起始段:(V0,V1)
  92. isFirstRender = false;
  93. }
  94. else if ( cellRenderState() == cellRenderImple::Change)
  95. {
  96. //if finish the current cell's render
  97. //利用v1和中点v0计算出v2:(v1 + v2) / 2 = v0
  98. //next cell begin: push the next cell's V1...
  99. int vecSize = vertexVector.size();
  100. Vec3d v0 = vertexVector[vecSize-1];
  101. Vec3d v1 = vertexVector[vecSize-2];
  102. Vec3d v2 = 2 * v0 - v1;
  103. vertexVector.push_back(v2);
  104. //重置cellRenderFlag
  105. cellRenderState.setPush();
  106. }
  107. }
  108. //////////////////////////////////////////////////////////////////////////
  109. //更新数组的长度
  110. _updateVertexNum();
  111. }
  112. void end()
  113. {
  114. glDisable(GL_MAP1_VERTEX_3);
  115. }
  116. void renderCurve()
  117. {
  118. //////////////////////////////////////////////////////////////////////////
  119. //rendering vertex...
  120. for (int i=0; i<vertexVector.size(); i++)
  121. {
  122. Vec3d v = vertexVector[i];
  123. glBegin(GL_POINTS);
  124. glVertex3dv(v.getValue());
  125. glEnd();
  126. }
  127. //////////////////////////////////////////////////////////////////////////
  128. //rendering moving tangent(切线)
  129. //(vertexNum-1, vertexNum-2)
  130. if ( vertexNum>=2 )
  131. {
  132. glEnable(GL_LINE_STIPPLE);
  133. {
  134. glLineStipple(1, 0x0101);
  135. glBegin(GL_LINES);
  136. {
  137. Vec3d v1 = vertexVector[vertexNum-1];
  138. Vec3d v2 = vertexVector[vertexNum-2];
  139. glVertex3dv(v1.getValue());
  140. glVertex3dv(v2.getValue());
  141. } glEnd();
  142. }glDisable(GL_LINE_STIPPLE);
  143. }
  144. //////////////////////////////////////////////////////////////////////////
  145. //if ( !_check() )
  146. // return;
  147. //rendering bezier cells...
  148. system("CLS");
  149. for (int i=0; i<cellNum; i++)
  150. {
  151. int pos = i * 3;
  152. if ( (pos+3) < vertexNum )
  153. renderBezierCell( BezierCell(pos, pos+1, pos+2, pos+3) );
  154. }
  155. //////////////////////////////////////////////////////////////////////////
  156. }
  157. // 3次bezier曲线经过vetex0和vextex3
  158. void renderBezierCell(const BezierCell& cell)
  159. {
  160. double *pBuffer = new double[Bezier3CtrlPnt * 3];
  161. cout << "----------------------------------------------------" << endl;
  162. cout << "Vertex number : " << vertexNum << endl;
  163. cout << "Cell number : " << cellNum << endl;
  164. cout << "The render cell: " << cell[0] << " " << cell[1] << " " << cell[2] << " " << cell[3] << endl;
  165. for (int i = 0, bg = 0; i<4; i++)
  166. {
  167. Vec3d v = vertexVector[ cell[i] ];
  168. pBuffer[bg++] = v.x();
  169. pBuffer[bg++] = v.y();
  170. pBuffer[bg++] = v.z();
  171. cout << v.x() << " " << v.y() << " " << v.z() << endl;
  172. }cout << "----------------------------------------------------" << endl;
  173. glMap1d(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, Bezier3CtrlPnt, pBuffer);
  174. glBegin(GL_LINE_STRIP);
  175. {
  176. for (int i = 0; i <= 30; i++)
  177. glEvalCoord1f((GLfloat) i/30.0f);
  178. } glEnd();
  179. delete pBuffer; pBuffer = 0;
  180. }
  181. void clear()
  182. {
  183. cellNum = 0;
  184. vertexNum = 0;
  185. isFirstRender = true;
  186. vertexVector.clear();
  187. }
  188. protected:
  189. bool _check() { vertexNum =vertexVector.size();
  190. return vertexNum == (cellNum - 1) * 3 + 4; }
  191. void _updateVertexNum() { vertexNum=vertexVector.size();}
  192. int cellNum; //单元个数
  193. int vertexNum; //顶点个数
  194. bool isFirstRender; //首次标志
  195. std::vector<Vec3d> vertexVector; //顶点数组
  196. class cellRenderImple
  197. {
  198. public:
  199. enum RenderStep
  200. {
  201. Push = 0,
  202. Change = 1
  203. };
  204. cellRenderImple(){ setPush(); }
  205. bool operator()(void) { return flag; }
  206. void setPush() { flag = Push; }
  207. void setChange() { flag = Change; }
  208. RenderStep flag; //cell的渲染状态
  209. } cellRenderState;
  210. };

测试程序如下:

  1. #include <iostream>
  2. #include <vector>
  3. #include <GL/glut.h>
  4. #include "BezierCurve.h"
  5. using namespace std;
  6. enum WindowSize{
  7. WinWidth = 1024,
  8. WinHeight = 768
  9. };
  10. int g_Viewport[4];
  11. double g_ModelMatrix[16];
  12. double g_ProjMatrix[16];
  13. BezierCurve myBezier;
  14. //////////////////////////////////////////////////////////////////////////
  15. void init();
  16. void display();
  17. void reshape(int w, int h);
  18. void keyboard(unsigned char key, int x, int y);
  19. void mouse(int button, int state, int x, int y);
  20. void motion(int x, int y);
  21. int main(int argc, char** argv)
  22. {
  23. glutInit(&argc, argv);
  24. glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
  25. glutInitWindowSize (WinWidth, WinHeight);
  26. glutInitWindowPosition (100, 100);
  27. glutCreateWindow (argv[0]);
  28. 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
  29. init ();
  30. glutDisplayFunc(display);
  31. glutReshapeFunc(reshape);
  32. glutKeyboardFunc (keyboard);
  33. glutMouseFunc(mouse);
  34. glutMotionFunc(motion);
  35. glutMainLoop();
  36. return 0;
  37. }
  38. void init(void)
  39. {
  40. glClearColor(0.0, 0.0, 0.0, 0.0);
  41. glShadeModel(GL_SMOOTH);
  42. myBezier.begin();
  43. }
  44. void display(void)
  45. {
  46. glClear(GL_COLOR_BUFFER_BIT);
  47. glColor3f(1.0, 1.0, 0.0);
  48. glPointSize(5.0);
  49. glPushMatrix();
  50. {
  51. myBezier.renderCurve();
  52. }glPopMatrix();
  53. glutSwapBuffers();
  54. }
  55. void reshape(int w, int h)
  56. {
  57. glViewport(0, 0, (GLsizei) w, (GLsizei) h);
  58. glMatrixMode(GL_PROJECTION);
  59. glLoadIdentity();
  60. if (w <= h)
  61. glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
  62. 5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
  63. else
  64. glOrtho(-5.0*(GLfloat)w/(GLfloat)h,
  65. 5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
  66. glMatrixMode(GL_MODELVIEW);
  67. glLoadIdentity();
  68. }
  69. void keyboard(unsigned char key, int x, int y)
  70. {
  71. switch (key) {
  72. case 27:
  73. exit(0);
  74. break;
  75. }
  76. }
  77. void mouse(int button, int state, int x, int y)
  78. {
  79. double vertex[3];
  80. //获取矩阵信息
  81. glGetIntegerv(GL_VIEWPORT, g_Viewport);
  82. glGetDoublev(GL_MODELVIEW_MATRIX, g_ModelMatrix);
  83. glGetDoublev(GL_PROJECTION_MATRIX, g_ProjMatrix);
  84. y = g_Viewport[3] - y;
  85. gluUnProject( x, y, 0,
  86. g_ModelMatrix, g_ProjMatrix, g_Viewport,
  87. &vertex[0], &vertex[1], &vertex[2] );
  88. if (button==GLUT_LEFT && state==GLUT_DOWN)
  89. {
  90. myBezier.mouseSynchro( BezierCurve::LButtonDown, vertex );
  91. glutSetCursor( GLUT_CURSOR_RIGHT_ARROW );
  92. }
  93. else if (button == GLUT_LEFT && state == GLUT_UP)
  94. {
  95. myBezier.mouseSynchro( BezierCurve::LButtonUp, vertex );
  96. }
  97. glutPostRedisplay();
  98. }
  99. //////////////////////////////////////////////////////////////////////////
  100. // 计算控制节点
  101. void motion(int x, int y)
  102. {
  103. double vertex[3];
  104. glutSetCursor( GLUT_CURSOR_CROSSHAIR );
  105. y = g_Viewport[3] - y;
  106. gluUnProject( x, y, 0,
  107. g_ModelMatrix, g_ProjMatrix, g_Viewport,
  108. &vertex[0], &vertex[1], &vertex[2] );
  109. myBezier.mouseSynchro( BezierCurve::MouseMove, vertex );
  110. glutPostRedisplay();
  111. }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

原文链接:https://blog.csdn.net/ryfdizuo/article/details/4728785

如果您对该产品感兴趣,请填写办理(客服微信:xiaoxiongyidong)

为您推荐:

发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。