UE4 数据压缩方法(二)

导语
在之前的压缩方法一里面我们把表示状态的数据编码到uint32的每个bit上,进行网络传输后再解码出来,以达到压缩数据,节省带宽的效果。这次我们尝试把UE4中的Rotator数据也进行压缩。

实现思路

UE中的Rotator本质上就是一个结构体,其中有三个float,那么传输一个Rotator要占用12个字节。
但是可以发现Rotator就是表示三个轴的旋转角度,而角度的范围是0 - 360.0,远小于float可以表示的范围,那么我们的目标就变成了如何用更小的数据量来传递0 - 360.0 了。
根据压缩精度不同,本文提供2种压缩方法,均为有损压缩。

上代码

其实UE 的 Actor 移动同步中已经有一些对数据进行量化(Quantization)的设置了。

量化的意思就是把某个数值范围映射(Map)到另一个数值范围。

image-20210818221744775

我把源码翻出来了,需要的话自己封装一下,就可以用啦!

Runtime\Core\Public\Math\Rotator.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 压缩一个float的角度值为一个byte.
*
* @param Angle 要压缩的角度.
* @return 压缩后的角度byte值.
*/
static uint8 CompressAxisToByte( float Angle );

/**
* 把一个byte的角度值到解压为一个float.
*
* @param Angle 角度byte值.
* @return 解压后的角度.
*/
static float DecompressAxisFromByte( uint8 Angle );

/**
* 压缩一个float的角度值为一个uint16.
*
* @param Angle 要压缩的角度.
* @return 压缩后的角度uint16值.
*/
static uint16 CompressAxisToShort( float Angle );

/**
* 把一个uint16的角度值到解压为一个float.
*
* @param Angle 角度uint16值.
* @return 解压后的角度.
*/
static float DecompressAxisFromShort( uint16 Angle );

Rotator.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
FORCEINLINE uint8 FRotator::CompressAxisToByte( float Angle )
{
// 映射 [0->360) 到 [0->256) and mask off any winding
return FMath::RoundToInt(Angle * 256.f / 360.f) & 0xFF;
}


FORCEINLINE float FRotator::DecompressAxisFromByte( uint8 Angle )
{
// map [0->256) to [0->360)
return (Angle * 360.f / 256.f);
}


FORCEINLINE uint16 FRotator::CompressAxisToShort( float Angle )
{
// map [0->360) to [0->65536) and mask off any winding
return FMath::RoundToInt(Angle * 65536.f / 360.f) & 0xFFFF;
}


FORCEINLINE float FRotator::DecompressAxisFromShort( uint16 Angle )
{
// map [0->65536) to [0->360)
return (Angle * 360.f / 65536.f);
}

总结

UE 中有很多优秀的源码的,多读源码可以少造轮子。

------------- 感谢您的阅读-------------
作者dreamingpoet
有问题请发邮箱 Dreamingoet@126.com
您的鼓励将成为创作者的动力