facebook开源卡通片引擎 pop 源码阅读笔记
facebook开源动画引擎 pop 源码阅读笔记:
代码包括四个目录:
Animations: 定义pop支持的动画类型,并抽像各种动画的低层数据结构
Engine:组织动化运行的数据结构,核心是动化管理者,还包括了动画引擎所需要的可动画属性定义、动画追踪等内容
Utility: 封装Engine中用到的各种功能,包括数值运算,数据转换,运算等
WebCore: 这部分是苹果公司的代码,矩阵运算和贝赛尔曲线的,用于底层运算,非常值得学习。
各层关键类的功能注释:
a.Animations
POPAnimation :定义了动画基类POPAnimation
私有变量:结构体_POPAnimationState 纪录动画状态,是实现动画最关键的属性
公有变量:name beginTime delegate tracer(动画追踪,纪录各种动画事件) ^completionBlock removedOnCompletion paused
NSObject (POP)让所有对象增加pop动画支持(增删改查)通过POPAnimator进行管理
b.Engine
POPAnimateableProperty 可动画的属性,用于定义动画类型和动画时修改值
POPConcreteAnimatableProperty
POPMutableAnimatableProperty
POPPlaceholderAnimatableProperty
POPStaticAnimatableProperty
POPAnimationEvent POPAnimationTracer的基本元素
POPAnimationExtras 扩展CAAnimation 和POPSpringAnimation 的方法(分类)
POPAnimationRuntime 这里有几个函数比较特殊
POPBox 包装一个函数vector,把vector转化为point,size,rect,color等
POPUnbox 解包一个向量,把point,size,rect,color对象转换为vector
POPAnimationTracer 动画跟踪 通过POPAnimationEvent来描述
POPAnimator 动画管理者,纪录所有的动画事件(POPAnimatorItem,纪录了动画作用到的对象、动画key、动画对象等信息),初始化是把CADisplayLink注册到runloop里定时触发render过程,进行一帧动画渲染。她提供了add、remove等操作Animation集合的方法,并提供了Observer和delegate等事件函数
POPAnimator通过两层(key,view)存储动画,(动画目标对象,(动画key,动画对象))
具体每帧的渲染过程有两步:1.renderTime,更新state的状态。 2.updateAnimatable,把state的变化更新到obj的具体属性上
c.Utility 各种工具类编写
POPAction: ActionDisabler和ActionEnabler 利用RAII暂停核心动画以ActionEnabler为例,创建ActionEnabler时停止动画,销毁时重新运行动画
POPCGUtils:颜色转换函数,数组和点,point,size,rect,color等转换函数
POPGeometry:扩展NSValue到POP自定义类型的转换
POPLayerExtras:图层矩阵变换封装,底层由TransformationMatrix实现
POPMath:数学计算接口,封装了UnitBezier,POPVector和其他数字计算
SpringSolver:spring插值计算
POPVector:向量运算
d.WebCore
FloatConversion:浮点数转换方法,提供double->float和double->CGFloat,
用途:服务于矩阵运算
TransformationMatrix:矩阵运算,包括初始化,scale,rotate,translate,flipX,flipY,skew,applyPerspective???,multVecMatrix向量和矩阵相乘等矩阵操作,
备注:以后详细看:
CATransform3D 矩阵变换之立方体旋转实现细节 http://blog.****.net/ch_soft/article/details/7351896
矩阵的三维变换(转)http://www.cnblogs.com/Clingingboy/archive/2010/10/17/1853566.html
关键方法说明:
计算行列式的值:不列举了,很枯燥,行列式计算的基本概念,从二阶计算到三阶再计算到四阶。主要作用是引擎层对layer进行坐标变换
UnitBezier: 结构体,初始化参数为两个控制点p1(p1x,p1y),p2(p2x,p2y),用于表示起始点为s(0,0),终止点为e(1,1),p1为第一控制点,p2为第二控制点的二次Bezier。
用途:重新实现系统的自带动画
备注:UnitBezier曲线相关知识:http://blog.****.net/jimi36/article/details/7792103
方法说明:
UnitBezier(double p1x, double p1y, double p2x, double p2y)//用两个控制点的坐标初始化曲线,
double sampleCurveX(double t)//通过参数t计算对应的x值
double sampleCurveY(double t)//通过参数t计算对应的y值
double sampleCurveDerivativeX(double t)
//epsilon表示一个小间距,相当于数学计算里的dX,一般为全距离的1/1000,
//求解x对应的t值,用到了函数sampleCurveDerivativeX
double solveCurveX(double x, double epsilon)
double solve(double x, double epsilon)//求解x对应的y值,分为两步算,1.由x计算t;2.由t计算y
2.动画执行流程:
1)POPAnimator是单例对象,初始化对象实例时注册把CADisplayLink到runloop,定时调用render,通过renderTime函数遍历所有正在执行的动画,使动画进行到下一帧,并刷新画面,直到所有动画推进完成。
2)动画状态的推进最终都是通过_POPAnimationState类和其子类的advance方法推进的,advance更新时间戳,updateAnimatable方法把state的状态变更到动画要作用的obj对象。
3)Spring、Decay、Basic 都有各自实现的advance函数计算,而Custom方式不同,他是通过一个POPCustomAnimationBlock类型的回调来就算这一帧的值的。
3.动画算法
不同动画的advance都是如何推进的呢?
Basic:动画通过起点为(0,0),终点为(1,1)的Bezier曲线计算,x轴为时间,y轴为比例。advance方法中需要根据t值计算出对应的y值p,然后根据p的值进行插值计算(v=s+(e-s)*p),并进行了按照最小精度的四舍五入(源码设置的精度是 1/(1000*总时间) ,动画时间越长,精度越高)。
Spring:这里的Vector4d不是真的向量,它可以表示point,size等结构,它起始就是个属性的数组而已,不要去想它的几何意义。
这个模型其实是一个简谐运动,
计算过程类似于弹簧,计算主要使用到这样几个量:
|---------|------|------ 轨迹
起点 当前点 间隔 平衡位置
p,表示当前点到弹簧平衡位置的距离 v,表示振子的速度 当前时间t 间隔时间dt
k弹簧的 劲度系数 f= kl b阻力系数 m质量
_tp 瞬时值(偏移量)
_tv 瞬时速度
_ta 瞬时加速的
Derivative 导数~~
利用这些参数做插值算法,算出下一时刻的p和v
计算原理大致就是 p2 = p + dt * v(因为v=p');v2 = v + dt * v'。
计算过程中运用了插值算法减小误差。说实话,没太看懂。希望这方面专家补充下。
问题:程序中计算dv用的是state.p*(-_k/_m) - state.v*(_b/_m);
正常dv=加速度a=f/m=f牵引/m-f阻力/m = state.p*(-_k/_m) - 阻力/m 这里库的作者可能认为阻力和速度成正比~~~,高中物理学的阻力是恒定的,但是模型运行的效果确实不错。
ps:看到这里让我很后悔上学时没好好学习计算方法,如果多会一点计算方法,这里应该能看的稍微明白点,懂得大牛指点下
Decay:衰减函数,没有说明 不知道为什么,应该和衰减公式有点关系,没弄清楚怎么变形的,下边是源码中的注释,v表示速度,dt时间间隔x位移
// v0 = v / 1000
// v = v0 * powf(deceleration, dt);
// v = v * 1000;
// x0 = x;
// x = x0 + v0 * deceleration * (1 - powf(deceleration, dt)) / (1 - deceleration)
Custom:通过自定义block刷新动画帧,更灵活的方式
后续问题:
1.没弄明白衰减公式的原理,希望数学物理大牛不吝赐教,期待学到这方面的知识。
2.Custom具体没试过,自由度应该很大,下次做做demo试试。
3.很多细节调用没有看懂,还有很多值得学习的地方
facebook开源动画引擎 pop源码阅读笔记:
初识POP:http://geek.****.net/news/detail/7534POP官网:https://github.com/facebook/pop
demo:https://github.com/jxd001/POPdemo/blob/master/README.md
转载请注明出处:facebook开源动画引擎 pop源码阅读笔记:
代码包括四个目录:
Animations: 定义pop支持的动画类型,并抽像各种动画的低层数据结构
Engine:组织动化运行的数据结构,核心是动化管理者,还包括了动画引擎所需要的可动画属性定义、动画追踪等内容
Utility: 封装Engine中用到的各种功能,包括数值运算,数据转换,运算等
WebCore: 这部分是苹果公司的代码,矩阵运算和贝赛尔曲线的,用于底层运算,非常值得学习。
各层关键类的功能注释:
a.Animations
POPAnimation :定义了动画基类POPAnimation
私有变量:结构体_POPAnimationState 纪录动画状态,是实现动画最关键的属性
公有变量:name beginTime delegate tracer(动画追踪,纪录各种动画事件) ^completionBlock removedOnCompletion paused
继承关系:
NSObject
POPAnimation
POPPropertyAnimation
POPBasicAnimation
POPDecayAnimation
POPSpringAnimation
POPCustomAnimation
_POPAnimationState
_POPPropertyAnimationState
_POPBasicAnimationState
_POPDecayAnimationState
_POPSpringAnimationState
NSObject (POP)让所有对象增加pop动画支持(增删改查)通过POPAnimator进行管理
b.Engine
POPAnimateableProperty 可动画的属性,用于定义动画类型和动画时修改值
POPStaticAnimatablePropertyState 结构体纪录了属性名,readBlock,writeBlock,和域值
79行 POPStaticAnimatablePropertyState _staticStates[] 纪录了所有可动画的属性对应的名称,其中的writeblock功能是把二进制数据写到对应的属性里
类族:
POPConcreteAnimatableProperty
POPMutableAnimatableProperty
POPPlaceholderAnimatableProperty
POPStaticAnimatableProperty
POPAnimationEvent POPAnimationTracer的基本元素
POPAnimationExtras 扩展CAAnimation 和POPSpringAnimation 的方法(分类)
POPAnimationRuntime 这里有几个函数比较特殊
POPBox 包装一个函数vector,把vector转化为point,size,rect,color等
POPUnbox 解包一个向量,把point,size,rect,color对象转换为vector
POPAnimationTracer 动画跟踪 通过POPAnimationEvent来描述
POPAnimator 动画管理者,纪录所有的动画事件(POPAnimatorItem,纪录了动画作用到的对象、动画key、动画对象等信息),初始化是把CADisplayLink注册到runloop里定时触发render过程,进行一帧动画渲染。她提供了add、remove等操作Animation集合的方法,并提供了Observer和delegate等事件函数
POPAnimator通过两层(key,view)存储动画,(动画目标对象,(动画key,动画对象))
具体每帧的渲染过程有两步:1.renderTime,更新state的状态。 2.updateAnimatable,把state的变化更新到obj的具体属性上
c.Utility 各种工具类编写
POPAction: ActionDisabler和ActionEnabler 利用RAII暂停核心动画以ActionEnabler为例,创建ActionEnabler时停止动画,销毁时重新运行动画
POPCGUtils:颜色转换函数,数组和点,point,size,rect,color等转换函数
POPGeometry:扩展NSValue到POP自定义类型的转换
POPLayerExtras:图层矩阵变换封装,底层由TransformationMatrix实现
POPMath:数学计算接口,封装了UnitBezier,POPVector和其他数字计算
SpringSolver:spring插值计算
POPVector:向量运算
d.WebCore
FloatConversion:浮点数转换方法,提供double->float和double->CGFloat,
用途:服务于矩阵运算
TransformationMatrix:矩阵运算,包括初始化,scale,rotate,translate,flipX,flipY,skew,applyPerspective???,multVecMatrix向量和矩阵相乘等矩阵操作,
备注:以后详细看:
CATransform3D 矩阵变换之立方体旋转实现细节 http://blog.****.net/ch_soft/article/details/7351896
矩阵的三维变换(转)http://www.cnblogs.com/Clingingboy/archive/2010/10/17/1853566.html
关键方法说明:
计算行列式的值:不列举了,很枯燥,行列式计算的基本概念,从二阶计算到三阶再计算到四阶。主要作用是引擎层对layer进行坐标变换
UnitBezier: 结构体,初始化参数为两个控制点p1(p1x,p1y),p2(p2x,p2y),用于表示起始点为s(0,0),终止点为e(1,1),p1为第一控制点,p2为第二控制点的二次Bezier。
用途:重新实现系统的自带动画
备注:UnitBezier曲线相关知识:http://blog.****.net/jimi36/article/details/7792103
方法说明:
UnitBezier(double p1x, double p1y, double p2x, double p2y)//用两个控制点的坐标初始化曲线,
double sampleCurveX(double t)//通过参数t计算对应的x值
double sampleCurveY(double t)//通过参数t计算对应的y值
double sampleCurveDerivativeX(double t)
//epsilon表示一个小间距,相当于数学计算里的dX,一般为全距离的1/1000,
//求解x对应的t值,用到了函数sampleCurveDerivativeX
double solveCurveX(double x, double epsilon)
double solve(double x, double epsilon)//求解x对应的y值,分为两步算,1.由x计算t;2.由t计算y
2.动画执行流程:
1)POPAnimator是单例对象,初始化对象实例时注册把CADisplayLink到runloop,定时调用render,通过renderTime函数遍历所有正在执行的动画,使动画进行到下一帧,并刷新画面,直到所有动画推进完成。
2)动画状态的推进最终都是通过_POPAnimationState类和其子类的advance方法推进的,advance更新时间戳,updateAnimatable方法把state的状态变更到动画要作用的obj对象。
3)Spring、Decay、Basic 都有各自实现的advance函数计算,而Custom方式不同,他是通过一个POPCustomAnimationBlock类型的回调来就算这一帧的值的。
3.动画算法
不同动画的advance都是如何推进的呢?
Basic:动画通过起点为(0,0),终点为(1,1)的Bezier曲线计算,x轴为时间,y轴为比例。advance方法中需要根据t值计算出对应的y值p,然后根据p的值进行插值计算(v=s+(e-s)*p),并进行了按照最小精度的四舍五入(源码设置的精度是 1/(1000*总时间) ,动画时间越长,精度越高)。
Spring:这里的Vector4d不是真的向量,它可以表示point,size等结构,它起始就是个属性的数组而已,不要去想它的几何意义。
这个模型其实是一个简谐运动,
计算过程类似于弹簧,计算主要使用到这样几个量:
|---------|------|------ 轨迹
起点 当前点 间隔 平衡位置
p,表示当前点到弹簧平衡位置的距离 v,表示振子的速度 当前时间t 间隔时间dt
k弹簧的 劲度系数 f= kl b阻力系数 m质量
_tp 瞬时值(偏移量)
_tv 瞬时速度
_ta 瞬时加速的
Derivative 导数~~
利用这些参数做插值算法,算出下一时刻的p和v
计算原理大致就是 p2 = p + dt * v(因为v=p');v2 = v + dt * v'。
计算过程中运用了插值算法减小误差。说实话,没太看懂。希望这方面专家补充下。
问题:程序中计算dv用的是state.p*(-_k/_m) - state.v*(_b/_m);
正常dv=加速度a=f/m=f牵引/m-f阻力/m = state.p*(-_k/_m) - 阻力/m 这里库的作者可能认为阻力和速度成正比~~~,高中物理学的阻力是恒定的,但是模型运行的效果确实不错。
ps:看到这里让我很后悔上学时没好好学习计算方法,如果多会一点计算方法,这里应该能看的稍微明白点,懂得大牛指点下
Decay:衰减函数,没有说明 不知道为什么,应该和衰减公式有点关系,没弄清楚怎么变形的,下边是源码中的注释,v表示速度,dt时间间隔x位移
// v0 = v / 1000
// v = v0 * powf(deceleration, dt);
// v = v * 1000;
// x0 = x;
// x = x0 + v0 * deceleration * (1 - powf(deceleration, dt)) / (1 - deceleration)
Custom:通过自定义block刷新动画帧,更灵活的方式
后续问题:
1.没弄明白衰减公式的原理,希望数学物理大牛不吝赐教,期待学到这方面的知识。
2.Custom具体没试过,自由度应该很大,下次做做demo试试。
3.很多细节调用没有看懂,还有很多值得学习的地方