基于OpenGL实现的多段Bezier曲线拼接

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

截图:

基于OpenGL实现的多段Bezier曲线拼接

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

#ifndef _BEZIERCURVE_H
#define _BEZIERCURVE_H

#include "vec3.hpp"
#include <vector>
#include <iostream>
#include <gl/glut.h>

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<vertexVector.size(); i++)
  {
   Vec3d v = vertexVector[i];
   glBegin(GL_POINTS);
   glVertex3dv(v.getValue());
   glEnd();
  }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/270729584dbf2311efb6e609bfc79018.html