cocos2dx CardinalSpline和CatmullRom算法
来源:互联网 发布:苹果电脑音乐制作软件 编辑:程序博客网 时间:2024/06/05 11:58
想想那些鱼儿游动的漂亮曲线,还记得水果忍者的手指划过那一道道划痕吗,众所周知这一切都是很多个点组成的线段,这些都离不开样条插值算法。
特别注意:CardinalSpline和CatmullRom这两种算法都是过点式,就是形成的曲线一定经过样品点,但是贝塞尔曲线就不一定经过所有的样品点
cocos2dx中主要有两处用到了:
一个是Action下面类:points代表样品点集合,tension代表张力因子,实际效果是如果等于1就是画直直的线,默认等于0.5,就是比较平滑的线,一般去0到1直之间调节
CardinalSplineBy::create(float duration, cocos2d::PointArray *points, float tension)
CardinalSplineTo::create(float duration, cocos2d::PointArray *points, float tension)
CatmullRomTo::create(float duration, cocos2d::PointArray *points)//等效于上面的tension=0.5
CatmullRomBy::create(float duration, cocos2d::PointArray *points)//等效于上面的tension=0.5
一个是DrawNode类下面成员函数,用来画图segments代表共用几个点来形成这条曲线
void drawCardinalSpline(PointArray *points, float tension, unsigned int segments, const Color4F &color);
void drawCatmullRom(PointArray *points, unsigned int segments, const Color4F &color);
cocos2dx中核心源码:
注解:
这里面lt特别不好理解,实际上这里是吧segments个点平均分成points总数个部分,每个segment的点占自己部分的百分比就是这个lt的意思,
这里面p又是什么意思呢,实际上他就表示区间的序号,在同一个区间内p是一样的。
所以此算法大概的原理就是把需要生成的segments点按样品点总数平均分一下,在固定区间内,找到固定的4个实际样品点,然后在这个区间内按点所在这个区间比例位置逐
个使用ccCardinalSplineAt算法生成新点,是一种典型分治法。不过这些仅仅是程序理解,关于样条插值算法推导过程估计还得找找大学专业的书本了。
void DrawNode::drawCardinalSpline(PointArray *config, float tension, unsigned int segments, const Color4F &color){ Vec2* vertices = new (std::nothrow) Vec2[segments + 1]; if( ! vertices ) return; ssize_t p; float lt; float deltaT = 1.0f / config->count(); for( unsigned int i=0; i < segments+1;i++) { float dt = (float)i / segments; // border if( dt == 1 ) { p = config->count() - 1; lt = 1; } else { p = dt / deltaT; lt = (dt - deltaT * (float)p) / deltaT; } // Interpolate Vec2 pp0 = config->getControlPointAtIndex(p-1); Vec2 pp1 = config->getControlPointAtIndex(p+0); Vec2 pp2 = config->getControlPointAtIndex(p+1); Vec2 pp3 = config->getControlPointAtIndex(p+2); Vec2 newPos = ccCardinalSplineAt( pp0, pp1, pp2, pp3, tension, lt); vertices[i].x = newPos.x; vertices[i].y = newPos.y; } drawPoly(vertices, segments+1, false, color); CC_SAFE_DELETE_ARRAY(vertices);}
Vec2 ccCardinalSplineAt(Vec2 &p0, Vec2 &p1, Vec2 &p2, Vec2 &p3, float tension, float t){ float t2 = t * t; float t3 = t2 * t; /* * Formula: s(-ttt + 2tt - t)P1 + s(-ttt + tt)P2 + (2ttt - 3tt + 1)P2 + s(ttt - 2tt + t)P3 + (-2ttt + 3tt)P3 + s(ttt - tt)P4 */ float s = (1 - tension) / 2; float b1 = s * ((-t3 + (2 * t2)) - t); // s(-t3 + 2 t2 - t)P1 float b2 = s * (-t3 + t2) + (2 * t3 - 3 * t2 + 1); // s(-t3 + t2)P2 + (2 t3 - 3 t2 + 1)P2 float b3 = s * (t3 - 2 * t2 + t) + (-2 * t3 + 3 * t2); // s(t3 - 2 t2 + t)P3 + (-2 t3 + 3 t2)P3 float b4 = s * (t3 - t2); // s(t3 - t2)P4 float x = (p0.x*b1 + p1.x*b2 + p2.x*b3 + p3.x*b4); float y = (p0.y*b1 + p1.y*b2 + p2.y*b3 + p3.y*b4); return Vec2(x,y);}
这里通过cocos2dx源码,小小总结一下CatmullRom算法公式:
static Vec2 CatmullRom(Vec2 &p0, Vec2 &p1, Vec2 &p2, Vec2 &p3, float t){float t2 = t * t;float t3 = t * t * t;float s =0.5;float b1 = s * ((-t3 + (2 * t2)) - t); float b2 = s * (-t3 + t2) + (2 * t3 - 3 * t2 + 1); float b3 = s * (t3 - 2 * t2 + t) + (-2 * t3 + 3 * t2); float b4 = s * (t3 - t2); return p0*b1 + p1*b2 + p2*b3 + p3*b4;}
static std::vector<Vec2> GetCatmullRom(PointArray *config,unsigned int segments){std::vector<Vec2> vector;ssize_t p;float lt;float deltaT = 1.0f / config->count();for( unsigned int i=0; i < segments+1;i++) {float dt = (float)i / segments;// borderif( dt == 1 ) {p = config->count() - 1;lt = 1;} else {p = dt / deltaT;lt = (dt - deltaT * (float)p) / deltaT;}// InterpolateVec2 pp0 = config->getControlPointAtIndex(p-1);Vec2 pp1 = config->getControlPointAtIndex(p+0);Vec2 pp2 = config->getControlPointAtIndex(p+1);Vec2 pp3 = config->getControlPointAtIndex(p+2);Vec2 newPos = CatmullRom( pp0, pp1, pp2, pp3, lt);vector.push_back(newPos);}return vector;}
- cocos2dx CardinalSpline和CatmullRom算法
- CatmullRom插值算法
- CCDrawingPrimitives(使用gl原始方法 绘制Points Line Rect Poly Circle Bezier CatmullRom CardinalSpline。。。。)
- cocos2dx A*算法
- cocos2dx A*算法
- Cocos2dx------八皇后算法
- cocos2dx(lua)ASTAR算法
- cocos2dx碰撞检测算法
- cocos2dx之A星算法
- cocos2dx A*寻路算法
- 【步兵 cocos2dx】四叉树碰撞算法
- A*算法 cocos2dx 8数码
- cocos2dx 2.0 和cocos2dx 2.2的区别
- cocos2dx CCLayerColor和CCLayerColor
- cocos2dx tag和zorder
- cocos2dx init 和onEnter
- cocos2dx convertToNodeSpace和convertToWorldSpace
- cocos2dx 暂停和恢复
- Android点击Button实现功能的几种方法总结
- php 生成笛卡尔集
- elem.attr()无法正确判断checkbox是否选中
- PHP的服务器Apache中httpd.conf 的中文详解
- java动态代理(JDK和cglib)
- cocos2dx CardinalSpline和CatmullRom算法
- 单线程/阻塞/同步/多线程/非阻塞/异步 的比喻
- python的moudles文件中__all__作用
- 关于P2P信息披露标准3.0的几点建议
- 在 docker 之间导出导入镜像
- LINUX GPIO Kernel/User API
- WPF 之Triggers
- Android---50---使用Socket进行通信
- Activiti介绍