万向节锁的一种解决办法(非欧拉限角)

看到网上有个flash游戏,控制一个方盒子在地板上移动,我便想写一个3D版的,但是发现让方盒子向任意方向翻滚存在万向节锁问题。

有关万向节锁,网上有一段视频:优酷地址

 

简单来说,万向节锁就是:一个3D物体存在3个坐标轴,物体发生旋转的时候,是围绕三个坐标轴发生的。在XNA中,一个3D模型的旋转是通过旋转变换矩阵完成的,请看下面的代码:

 

                    effect.Alpha = alpha;
                    effect.EnableDefaultLighting();
                    effect.World = Matrix.CreateRotationX(rotation.X) *
                        Matrix.CreateRotationY(rotation.Y) *
                        Matrix.CreateRotationZ(rotation.Z)
*
                        Matrix.CreateScale(scale) *
                        Matrix.CreateTranslation(position);
                    effect.View = camera.View;
                    effect.Projection = camera.Projection;

上面这段代码中划线部分既是使3D模型发生旋转的代码。但是大家知道,矩阵乘法是不遵守交换律的,也就是说A*B!=B*A,这使得XYZ三个坐标轴上的旋转有了层级关系。按照上面这段代码给出的顺序,X轴是父层级,Y轴是X轴的子层级,Z轴是Y轴的子层级。

 

所谓层级,也就是说,如果3D模型围绕X轴发生旋转,那么同时也将改变Y轴和Z轴的朝向,但是当模型围绕Z轴转动的时候,X轴的方向却是不变的。这样便形成了万向节锁。万向节锁发生的时候,会有两个坐标轴重合。

 

举个例子,比如在初始状态下,XYZ三个轴相互垂直,然后我们让物体围绕Y轴发生转动,这样一来,X轴没有发生变化,但是Z轴随着物体转向了X轴,并在合适时候会与X轴重合。重合之后会发生什么呢?那便是我们失去了一个坐标轴。原因很简单,因为此时X轴和Z轴重合了嘛,无论你是围绕X轴转动,还是为绕Z轴转动,最终效果都是一样的。

 

 

建议大家看一看本文开头连接的优酷上那段视频。在那段视频中,解说采用了一种叫欧拉限角的方法解决万向节锁问题。这个方法简单说就是给旋转加上一个限制,不让3D物体发生任意角度的完全自由的旋转,从而避免万向节锁的发生。

 

但是对于我们的游戏,需要物体发生可能产生万向节锁的旋转,怎么办呢?

 

我尝试让物体在发生旋转并产生万向节锁之后,再自己转回来。

简单说,对于一个在坐标轴方向上均匀对称的物体(比如球和立方体)来说,当我们站在一个固定角度上看他的时候,它的坐标轴朝向无关紧要,因为我们说了,它是个在坐标轴方向上对称的物体,那么我们为什么不可以在代码里把旋转的晕头转向的这个3D物体在摆正了呢?反正玩家看不出来嘛!

那么对于非对称的物体呢?

我们只需要多做几个模型,适应这种非对称状况就好了。

但是这个办法和欧拉限角方法一样,不是万能的,对于各向异性的物体,比如一个人物,比如一朵花,特别是会动的东西(带动画的模型),几乎不起作用了。

 

下面给出我做完的两个小游戏,一个是仿照网上的立方体在地板上滚动,滚过去地板就消失那个做的,另一个是仿照网上的长方体在地板上滚动,最后到达目的地做的。两个游戏都是用上下左右键控制就ok了,空格键可以重置。希望大家指教~~~

 

 

立方体

长方体

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值