运行程序的交互方式有点类似corelDraw中的自由曲线绘制,或者photoShop中的钢笔自由路径绘制。
截图:
将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();
}