ZvRadialBlendShape用了一种非常精简效果却令人惊叹的方式完成了眼睛的变形器。
他把眼睛的变形归结为圆柱体坐标系上的变形,并且加上了线性的offset,非常有创造性的用简单的数学表达式来表现眼睛的神态!
在wiki上,有笛卡尔坐标系和圆柱坐标系的转换公式,不过这公式的轴向是如下:

maya里面的轴向有些不一样,而且需要按照我们的圆柱方向而定:
对于在圆柱上面的一点,如图上面的彩色locator。它的p是图上的蓝色曲线的下面一段,angle就是这个蓝色曲线所摆出的角度。最后的z,也就是我们的x轴。所以笛卡尔坐标系转化为圆柱坐标系:
// radius
outPoint.x = sqrt(point.z*point.z + point.y*point.y);
// angle
outPoint.y = atan2(point.y, point.z);
// h
outPoint.z = point.x;
这样,我们在变形之前,可以起始point和结束point都转化到圆柱坐标系中,然后中间的过渡就在圆柱坐标系中进行blend
——————————————————————————————————————————————————
细节:C++的atan2的范围在(−π, π]之间,参看http://zh.wikipedia.org/wiki/Atan2
π之后,即π到2π之间,没有连续性(-2π到-π之间曲线也没有连续性),y的线性blend也需要在这之间,所以需要对数据进行范围处理)
arcTan的是1阶曲线,它得到的y的结果曲线比较难看。相当于z= arcTan(y/1),这样的效果就像是一个半圆的曲线反向,然后被拉长了。。


atan2就有2个参数,它的结果就符合一个圆的规律。
————————————————————————————————————————
在此基础之上,Paolo Dominici还加入了额外的线性blend。这个blend与locator的tx相关。
根据point的tx与locator的tx之差,给blend加入了一个1阶和2阶的参数:
localBlend = (blend + (curvature*origPointLS.x + twist)*origPointLS.x)*weight;
在这里origPointLS.x 是以locator为参照系的point的position
——————————————————————
以闭眼为例,大概的outPoint.y都会在180度以上。也就是,终点会大概在-100+,起点是大概100+
所以,1阶的变形,也就是twist,它为正时,outpoint.y是从(100~0~-100)*origPointLS.x
利用atan2的园性变形过渡,结果就像在x大于0时,有个半圆向下运动(Y不断减小,并接近横向轴),在x小于0的地方,有个半圆不断向上运动(逆向增加),形成了一个非常帅的S形。
对于curvature而言,也是如此,默认情况下是,两个小一点的半圆(因为是x的2次方,Paolo在这里都让他们处于0~1之间)向下运动,Paolo并没有这样,他乘以了一个-1.这样两个小半圆就默认向上了,这对动画师来说更舒服。