1.通道省略
动画数据一般包括10个浮点数据:
- 平移translate(float x, float y, float z);
- 旋转rotate(float qx, float qy, float qz, float qw);
- 缩放scale(float x, float y, float z);
如果每秒30个样本,那么每个关节需要4字节 * 10通道 * 30 = 1200字节的数据,若游戏含1000s的动画数据,那么需要110M+数据,多数游戏显然是不会有如此大的空间存储这些数据的。因此最简单的方法压缩就是去省略一些无关通道,动画需要哪个通道就只保存哪些通道的信息,比方说UI的出现动画,从上方出现,显然,只需要平移就可以,这样就省掉了70%的空间,可见这样的提升是巨大的。
2.量化
把IEEE32位浮点数->n位整数表示的运算称叫量化
量化有编码,解码两种操作
下面介绍一下Jonathan Blow的RL缩放法,把[0,1]的的浮点值,压缩到nbits的整数中:
//编码输入对应浮点值与编码位数
U32 CompressUnitFloatRL(F32 unitFloat, U32 nBits)
{
//把1左移nbits位 如nbit=16: 00000000 00000000 10000000 00000000
U32 nIntervals = 1u << nBits;
//把输入值从[0,1]范围放缩至[0,nIntervals - 1]范围 00000000 00000000 01111111 11111111
//这里需要减一是由于希望最大的输出值能存储在nBits个位内
F32 scaled = unitFloat * (F32)(nIntervals - 1u);
//最后,我们需要加0.5f,在四舍五入至最近的区间中点
//然后,把该值截尾,取得区间索引(通过转型至U32)
U32 rounded = (U32)(scaled + 0.5f);
//为无效输入值做出保护
if (rounded > nIntervals - 1u)
rounded = nIntervals - 1u;
return rounded;
}
//解码
F32 DecompressUnitFloatRL(U32 quantized, U32 nBits)
{
//基于编码时的位数,判断区间数量
U32 nIntervals = 1u << nBits;
//解码时只需简单的把U32转为F32,并按区间大小缩放
F32 intervalSize = 1.0f / (F32)(nIntervals - 1u);
F32 approxUnitFloat = (F32)quantized * intervalSize;
return approxUnitFloat;
}
压缩有精度损失,不过一般肉眼无法察觉。如果上32位浮点值,可以压缩到16位中,又可以减少一半的内存。
3.降低采样频率及省略
- 比方说30帧的采样频率降低到15,同时考虑如果对效果影响不大的情况下,可以适当降低
- 省略样本,比方说匀速位移,呈某种确定函数运动的,可以直接用表达式或者首尾表示法,通过插值计算
4.基于曲线的压缩
可以分片段样条拟合,再通过采样线性插值的方法去压缩
5.选择性载入:
1.如我们游戏采用分场景加载配置,ui,以及动画等各种资源,