近期在研究寻路功能的测试工作,需要对玩家寻路过程中的行进轨迹进行采样,判断采样点是否在特定的寻路区域内。UE4自带了NavModifierVolume
的actor,可以放置到场景里标识某个区域的寻路成本(不了解寻路相关背景的话可以参考先前的文章),因此我们做采样的时候,也需要判断某个点是否在特定的NavModifierVolume
里。由于自己所负责的游戏是网游,NavModifierVolume
最后导出给服务器用了,实际游戏里获取不到这些actor的数据,因此实际测试时,一方面需要下载服务器上的NavModifierVolume
数据,另一方面还要手写相关的计算方法,来达到我们的工作目的。
NavModifierVolume
是一个空的长方体,可以旋转成任意形式。因此判断玩家寻路采样点是否在特定寻路区域内,也就必须解决这个数学问题——3D空间下判断一个点是否在特定长方体内。
通常而言,这个问题有以下的解法:
- 判断是否在3组平行平面同一侧
- 判断坐标是否在XYZ范围内,如果是AABB(对齐坐标轴)
针对UE4环境,一个长方体会包含transform以及单位大小的信息:
- 位置Location:中心点
- 旋转Rotation:Pitch、Yaw、Roll
- 大小比例Scale
因此这个问题可以用这样的步骤解决(应该是对的吧,数学不好= =):
- 获取中心点到目标点A的向量,其中目标点A是我们需要判断是否在长方体内的点
- 对这个向量进行基于Rotation的逆运算,这样目标点的位置会变化,得到新的目标点B
- 判断目标点B,是否在一个以Location为中心点,Scale*单位长度大小的AABB中
这里面最需要解决的,是如何求旋转。我们可以通过UE内部的源码来寻找思路。
1 | // UnrealMath.cpp |
由一个旋转FRotator
(带Pitch、Yaw、Roll属性),以及一个向量,可以直接求得旋转后/逆旋转后的向量。旋转一个向量需要构建特定的旋转矩阵,通过矩阵乘法得到新向量分量的值。逆旋转的矩阵则是旋转矩阵的转置,而转换原向量的计算方式也是相同的。
针对不同的坐标系规则,旋转矩阵的计算方法有很多种,而实测UE4用的旋转矩阵也是独特的一种(试过网上的一些旋转矩阵老是有分量正负号不对= =)。在FRotationMatrix
、FRotationTranslationMatrix
的定义中,我们可以看到旋转矩阵的构造方法:
1 | // RotationTranslationMatrix.h |
可以看到旋转矩阵是一个4x4的结构(因为可能有设定原点坐标)。而之后,TransformVector
是这样计算的:
1 | // Matrix.inl |
最终其实就是原向量[[x, y, z, 0]](1x4)
乘以转置矩阵(4x4)
,得到新的1x4
的向量,也就是我们需要的旋转后的向量。UE4内部对计算过程做了优化,此处暂不多做分析。
得到了计算向量旋转的方法,我们也可以通过其转置矩阵,进行向量的某个旋转的逆运算,这样目标点相对于中心点的位置有所改变,但对应的长方体就是对齐坐标轴的了。这时就可以直接通过判断点的三个分量是不是在长方体X、Y、Z范围内,就能得出答案。