基于TexturePacker的骨骼动画压缩
基于TexturePacker的骨骼动画压缩
项目动画表现选型
1、骨骼动画,导出资源小,动作细腻度稍差
2、3渲2序列帧动画, 导出资源相对比较大,但是能提供丰富的动作。动画品质得到提高。
那么能否结合3渲2序列帧动画以及骨骼动画的优势,以及更高的序列帧压缩比来提供适合自己的工具了。
优化1:
如下图1是3D直接渲染的3渲2 的序列图。图2是渲染两次再在flash里面拼接出的导出图,很显然,图2的方式能减少一些公用的图片,这对我们游戏,分红蓝配色是很有帮组的,我们可以让用于红蓝区分的部位单独渲染出来,然后在flash里面进行拼接导出骨骼动画。在游戏中动态控制红来骨骼的显示隐藏来做出红蓝区分。
图1
图2
优化2:
导出图优化。在之前的版本中,我们是基于矩形块拼接的(如图3),这种拼接方式比较简单,速度快,但是缺点是透明空白区域比较多,后面发现TexturePacker有一种基于多边形的压缩(如图4),这无疑是拼接的福音。当即决定使用TexterPacker来压缩导出图。
图3
图4
最终决定对原有flash 骨骼动画进行一次升级。
接下来就是如何将texturePacker的多边形压缩集成到现有的骨骼动画工具之中了,在这个集成之中,要解决几个问题,
1、如何在工具中运行TexturePacker
2、如何保存骨骼动画中的骨骼锚点信息
3、如何在骨骼动画播放器中支持多边形渲染
由于现有骨骼动画导出工具是基于AIR开发的,所以集成TexturePacker的最好方式就是在AIR调用TexturePacker的命令行模式运行。
TexturePacker assets
createsout.plist (cocos2d) and out.png from all png files in the 'assets' directory
trimming allfiles and creating a texture with max. 2048x2048px
实验证明这个办法是可行的。
针对骨骼动画锚点信息这个是一个比较棘手的问题,由于flash坐标系和unity坐标系的Y轴方向是相反的。以及如何保存锚点信息到texturepacker中。后面发现Texturepacker 提供TPS工程文件,工程文件中可以对需要压缩的图设置锚点信息。(如图5),对应图6中锚点信息。但是细心会发现, 两处的锚点信息y轴数据不一样。其实这里是texturePacker自己做的一个处理,项目文件中保存的是left-top为0,0点,而在TexturePacker工具里面则是left-bottom为0,0 但是这个不影响最终的时候,只是在设置工程文件的时候需要从left-top的坐标系设置。
图5
图6
如此我们只需要在工具中对需要压缩的图片依次添加到TexturePacker的工程文件,以及设置好其锚点信息,在flash中即 -pivot.x/img.width,-pivot.y/img.height。最终生成一个用于命令行导出的工程文件,最后在程序中执行
TexturePacker --sheetC:\Users\ruisonzhou\u8001r\u8001r_t0.png --texture-format png --formatunity-texture2d --data C:\Users\ruisonzhou\u8001r\u8001r_sheet --algorithmPolygon --trim-mode Polygon C:\Users\ruisonzhou\u8001r\u8001r_t0.tps
即可导出最终压缩版的资源。
最后一步是在unity中渲染,在之前的基础上需要修改的即,将原来的骨骼矩形渲染,修改为现在多边形渲染。在这之前,需要将texturePacker的压缩文件读取出来。文件如图7
图7
其文件每行即是一张图片的压缩信息。依次是图片名,大图中位置区域,图片锚点位置,顶点个数,[顶点位置...],三角形个数,[三角形索引....]
有了这些信息之后,我们就可以在unity中还原出我们想要的骨骼动画了。
以下代码是还原骨骼图片顶点的代码
public static voidBuildSmartVerticesByMatrix(ref Vector3[] vertices,
ref Matrix m,
BlitFrameSmartDatasmartData,
int startIndex,
float scaleX = 1f,
float scaleY = 1f)
{
//scaleX = scaleY = 1f;
// 取得所有顶点 法线 uv
float xx;
float yy;
float xMin = -smartData.SpriteForRender.pivot.x * scaleX;
float yMin = -smartData.SpriteForRender.pivot.y * scaleY;
for (int ix = 0; ix < smartData.VerticesCount; ix++)
{
xx = smartData.Vertices[ix].x + xMin;
yy = smartData.Vertices[ix].y + yMin;
vertices[startIndex + ix].x = m.tx + (m.a * xx - m.c * yy);
vertices[startIndex + ix].y = -m.ty - m.b * xx + m.d * yy;
}
}
其中Matrix 为flash中骨骼在当前帧的矩阵信息。
骨骼UV设置如下:
public static void BuildSmartUVByMatrix(ref Vector2[] uvs, Sprite sprite,BlitFrameSmartData smartData, int startIndex)
{
Texture2D texture = sprite.texture;
for (int ix = 0; ix < smartData.VerticesCount; ix++)
{
uvs[startIndex + ix].x = (smartData.Rect.x + smartData.Vertices[ix].x) /texture.width;
uvs[startIndex + ix].y = (smartData.Rect.y + smartData.Vertices[ix].y) /texture.height;
}
}
最终效果如下:
根据项目测试,多边形压缩方式可提高20%-30%的压缩比,虽然这个数字看上去不是很明显,但是有时候往往就是这20%将影响到你的图 是1024*1024 还是1024*2048 如果压缩之后能在1024*1024内,那在显存和内存中将提供事半功倍的效果。
最后感谢在这次升级过程中帮组的同事.alencui, minichen。