一个柔体的cocos2d-x实现

参考贝塞尔曲线公式:
贝兹曲线
推导出八阶贝兹曲线的公式,结合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这个结构,来方便边界检测。