游戏观察 游戏产业媒体
手机端下载
当前位置:游戏观察 > 新闻 > 研发资讯 > 正文

简化层次结构 关于游戏空间矩阵变化的深度探索

2017-07-22 10:28 来源:Gad

  游戏观察7月22日消息,在游戏空间的设计中需要运用到大量的计算问题,如果把游戏对象组织成层次化结构,并将其进行简化,这将极大地方便于在游戏引擎层面的结构设计,实现矩阵变化。下面我们就从理论和实践两方面入手,来说说这一问题。

  一、前言

  在游戏引擎中,习惯性的把游戏对象组织成层次化结构,比如下图(1)所示,有时候这个层次化结构非常深:

层次化结构

图(1)

  那么,一个很实际的问题,有没有办法简化这个层次的深度?或者说:是否存在一个有限深度d,其他任意层次深度可以简化成深度d,下面我们讲探索这个问题,并给出一个答案:d = 2。也就是说,在不考虑便捷性的情况下,任意深度的游戏对象可以简化成只有两层深度的游戏对象。

  二、理论

  我们知道游戏对象有世界位置和世界旋转,这两个变换实际上可以坍缩到一层,因此这两个变换并不能阻碍我们的简化过程,挡在我们道路上的是伸缩变换,这个变换没有直接的世界变换(Unity3D中有一个lossyScale),看起来束手无策?那么有没有办法呢?答案肯定是肯定的!

  我们可以从矩阵的分解算法中寻找灵感:Singular Value Decomposition。SVD算法可以把一个矩阵分解成一个旋转变换加一个伸缩变换加另一个旋转变换,我们只要把游戏对象的变换矩阵localToWorldMatrix的伸缩旋转核放到SVD中,出来的就是三个变换,我们用(U, S, VI)表示,再加上世界位置P,我们就可以用一个四元组(P, U, S, VI)表示这个对象的localToWorldMatrix变换,用语言描述一遍:一个任意深层次的游戏对象到世界坐标系的变换可以简化成如下四步:

  1. 用VI对该对象做旋转

  2. 用S对该对象做伸缩

  3. 用U对该对象做旋转

  4. 用P对该对象做位移。

  我们可以很容易的知道,四元组(P, U, S, VI)可以用一个两层结构完全表示,第二层的localRotation = VI,第一层的localPosition = P, localRotation = U, localScale = S。

  也就是说,任意深度的游戏对象可以简化成只有两层深度的游戏对象。

  三、实践

  有了理论,我们来实践一把。首先,我们得搞定SVD算法,这个难不倒我,matlab有现成的库,我们写一个my_svd,内容如下图(2)所示:

SVD算法

图(2)

  可以看到,my_svd实现了svd的功能,并且是对M的伸缩变换做的。

  写完之后,我们用matlab中的matlab coder工代码生成功能,生成一个my_svd.dll(使用matlabr2016a,vs2015)。然后把my_svd.dll拷贝到Assets/Plugins目录下,新建一个脚本TestScaleRotate.cs,在脚本里导入我们的my_svd.dll,如下图(3)所示:

my_svd.dll

图(3)

  开始时,要调用my_svd_initialize(),结束时,调用my_svd_terminate(),非常的方便。

  然后我们建立一个如下图(4)所示的场景

调用my_svd_initialize()

图(4)

  我们把TestScaleRotate.cs挂到CubeCopy对象上,让CubeCopy来复制Cube的TRS变换。

  TestScaleRotate.cs的主要内容如下图(5)所示(src指向Cube的Transform):

TestScaleRotate.cs的主要内容

图(5)

  代码意思就是拷贝我们之前的讨论,把src.localToWorldMatrix分解成(P, U, S, V),把P赋值给transform.parent.localPosition,U, S, V分别赋值给CubeCopy的三元组。产生的效果如下图(6)所示,可以看到,Mesh严丝合缝的一致,但BoxCollider不是(绿色的框),因为BoxCollider是按lossyScale伸缩的。

代码

图(6)

  四、讨论

  说了这么多,那么这个实际上有什么用呢?实际上是有用的,搞过PhysX的人都知道:PhysX里的Transform只有两层结构PxActor及PxShape,这样的设计大大简化了PhysX,同时又能保证其具有完备的能力。当然,基本物理组件里(Box, Sphere等)没有scale这个属性,只有在Mesh, HeightField里有PxMeshScale属性。因此对于基本物理组件,无法在物理中完备表示,因此只能用lossyScale来表示伸缩。

  另外,本文中的一个重要结论:任意TRS组合可以表示成(P, U, S, V)。可以用于简化Transform计算,比如某些动画。或者如果Transform的读写由于层数太多而导致性能问题,也有优化的基础。

最新游戏行业资讯,点击进入游戏观察!

本网站所收集的资料来源于互联网公开信息或网友自助投稿,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现网站上有侵犯您知识产权的资料,请与我们取得联系,本站会在3个工作日内删除。

游戏观察

聚焦极有价值的游戏产业资讯。打造有影响力的游戏产业媒体。

赋能游戏跨端开发,Unity于2021 ChinaJoy推出跨端移植服务