
参考贝塞尔曲线公式:
推导出八阶贝兹曲线的公式,结合CCDrawingPrimitives.cpp中的drawQuadBezier和drawSolidCircle ,
注意opengl的glDrawArrays(GL_TRIANGLE_FAN, 0, (GLsizei) segments+1),中GL_TRIANGLE_FAN决定了以三角扇的方式填充各个顶点,来弄成一个实心的闭合图形,GL_LINE_STRIP的话就是画线啦。
粗略地实现:
void drawOctupleSolidBezier(const Point& origin, const Point& control1, const Point& control2,const Point& control3,const Point& control4,const Point& control5,const Point& control6, const Point& destination, unsigned int segments,std::set *edge)
{
Point control7=Point(2*origin.x-control1.x,2*origin.y-control1.y);
lazy_init();
Vertex2F* vertices = new Vertex2F[segments + 1];
float t = 0;
for(unsigned int i = 0; i < segments; i++)
{
vertices[i].x =
powf(1 - t, 8) * origin.x
+ 8.0f *powf(1 - t, 7) * t * control1.x
+28.0f * powf(1 - t, 6) * t * t * control2.x
+56.0f * powf(1 - t, 5) * t * t *t * control3.x
+70.0f * powf(1 - t, 4) * t * t * t *t *control4.x
+56.0f * powf(1 - t, 3) * t * t * t *t *t *control5.x
+28.0f * powf(1 - t, 2) * t * t * t *t *t *t *control6.x
+8.0f * (1 - t) * t * t *t *t *t *t *t * control7.x
+t * t * t *t*t * t * t *t *destination.x;
vertices[i].y =
powf(1 - t, 8) * origin.y
+ 8.0f *powf(1 - t, 7) * t * control1.y
+28.0f * powf(1 - t, 6) * t * t * control2.y
+56.0f * powf(1 - t, 5) * t * t *t * control3.y
+70.0f * powf(1 - t, 4) * t * t * t *t *control4.y
+56.0f * powf(1 - t, 3) * t * t * t *t *t *control5.y
+28.0f * powf(1 - t, 2) * t * t * t *t *t *t *control6.y
+8.0f * (1 - t) * t * t *t *t *t *t *t * control7.y
+t * t * t *t*t * t * t *t *destination.y;
t += 1.0f / segments;
}
vertices[segments].x = destination.x;
vertices[segments].y = destination.y;
for(unsigned int i = 0; i < segments; i++)
{
calcEdges(i,edge,vertices);
}
s_shader->use();
//s_shader->setUniformForModelViewProjectionMatrix();
s_shader->setUniformsForBuiltins();
s_shader->setUniformLocationWith4fv(s_colorLocation, (GLfloat*) &s_color.r, 1);
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
#ifdef EMSCRIPTEN
setGLBufferData(vertices, (segments + 1) * sizeof(Vertex2F));
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, 0);
#else
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
#endif // EMSCRIPTEN
glDrawArrays(GL_TRIANGLE_FAN, 0, (GLsizei) segments + 1);
CC_SAFE_DELETE_ARRAY(vertices);
CC_INCREMENT_GL_DRAWS(1);
}
inline float distanceX(Vertex2F &v0,Vertex2F &v1){
return (sqrt(1+((v1.x-v0.x)*(v1.x-v0.x))/((v1.y-v0.y)*(v1.y-v0.y))));
}
inline float distanceY(Vertex2F &v0,Vertex2F &v1){
return (sqrt(1+((v1.y-v0.y)*(v1.y-v0.y))/((v1.x-v0.x)*(v1.x-v0.x))));
}
static void calcEdges(const int i,set *edge,const Vertex2F *vertices){
static float xx,yy;
static Vertex2F &v0=vertices[i];
static Vertex2F &v1=vertices[i+1];
xx=20/distanceX(v0,v1)+v0.x;
yy=20/distanceY(v0,v1)+v0.y;
edge->insert(int(xx/135)*1000+int(yy/135));
xx=-20/distanceX(v0,v1)+v0.x;
yy=-20/distanceY(v0,v1)+v0.y;
edge->insert(int(xx/135)*1000+int(yy/135));
xx=-20/distanceX(v0,v1)+v0.x;
yy=20/distanceY(v0,v1)+v0.y;
edge->insert(int(xx/135)*1000+int(yy/135));
xx=20/distanceX(v0,v1)+v0.x;
yy=-20/distanceY(v0,v1)+v0.y;
edge->insert(int(xx/135)*1000+int(yy/135));
}
抛出edges这个结构,来方便边界检测。




近期评论