C#DirectX3D开发(1) 摄像机旋转问题,旋转上下90度时出问题

本文探讨并解决了使用C#进行DirectX开发时,摄像机绕X轴旋转过程中无法达到完整360度旋转的问题。通过分析代码逻辑和三维空间特性,提出在特定条件下的修正方法,确保摄像机能够顺利绕X轴旋转至任意角度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

当绕X轴旋转时,从90度旋转到-90度正常,再继续旋转时无法旋转过去,不能达到360度旋转,求高手赐教。
自己搜索了,有人碰到相同问题:

为了有人搜索时能找到这里,把他们的描述也贴出来:

求高手赐教,本人正在学习基于C#的directx开发,在摄像机旋转遇到问题了,无法绕X轴旋转360度。附部分代码 

(http://bbs.youkuaiyun.com/topics/390441832?page=1)

最近在做一个项目是使用C#模拟一些简单的3D,在网络上早到了一些C#的代码,过程还好,但是唯一头痛的问题就是摄像机旋转到垂直方向后就不能继续旋转,结构翻转到了原始位置,代码如下,希望大家帮我修改一下,我想是做个判断就可以了,但是我对三维空间不是很清楚。希望大家帮个忙哦。

http://bbs.youkuaiyun.com/topics/390441832?page=1

但没找到解决方案,只能自己研究下看看。

花了半天多总算解决了:在每次转过上下90度时把upVector取反就行了。

现在想想前面的第二位既然是项目,应该最终也解决了。


相关代码:

private void RotateXAxis(float angleSpeed)
        {
            Rotate(XAxis, angleSpeed);//旋转
            Vector3 lastXAixs = XAxis;//保存上次的x轴
            SetDeviceView();//这里面XAxis的值发生了变化
            Vector3 newXAixs = XAxis;//现在的x轴值
            double flag = Vector3.Dot(lastXAixs, newXAixs);
            if (flag < 0)//旋转变化后x轴是否反方向了
            {
                //修改向上方向
                UpVector.X *= -1;
                UpVector.Y *= -1;
                UpVector.Z *= -1;
            }
        }
        private void RotateYAxis(float angleSpeed)
        {
            Rotate(ZAxis, angleSpeed);
            SetDeviceView();
        }
        private void Rotate(Vector3 xAxis, float angle)
        {
            //Console.Write("xAxis:({0},{1},{2})\n", xAxis.X, xAxis.Y, xAxis.Z);
            //WriteInfo();
            Vector4 tempV4 = Rotate(R, xAxis, angle);
            //Console.Write("tempV4:({0},{1},{2},{3}) {4}\n", tempV4.X, tempV4.Y, tempV4.Z, tempV4.W, tempV4.Length());
            Postion.X = Target.X + tempV4.X;
            Postion.Y = Target.Y + tempV4.Y;
            Postion.Z = Target.Z + tempV4.Z;
            //Console.Write("Postion:({0},{1},{2})\n", Postion.X, Postion.Y, Postion.Z);
        }


以下是研究过程的记录,比较乱,仅做记录。


计算视图矩阵时,z轴是从position指向target的向量zAxis(R),给一个upVector,将upVector和zAxis相乘,得到一个xAxis。根据叉积方向和两向量垂直,实际上,最后的yAxis应该是和upVector方向平行的。

问题是,特殊情况,如果upVector和zAxis平行呢?

A B 的叉积的大小等于a*b*sin<a,b>,当平行时,方向不定,大小为零了。

这绝对是一种异常情况,或许就是这个导致了90度无法转过去……

那样的话,是不是让upVector不和zAxis平行就行呢?

问题在于让R绕自身的x轴旋转的话,必定会转到y轴,也就是upVector,此时,就会出现异常。

那只要让R不绕x轴旋转就行了吧,比如旋转的时候给转动的向量(x轴)加一个(1,1,1)的偏移,不会出现转不过的问题,但是旋转轨迹怪怪的,而且无论上下,最终都会在某个角度徘徊。不会形成一个圈。难道是那种无限缩小的圈吗?

 

那还是在接近平行时判断一下,想办法绕开那个特殊情况?

计算两向量的夹角,A*B/|A|*|B|=sin<A,B>

可以判断出来,怎么绕开呢?多转一些,直接绕过去?

如果绕着固定的轴 Vector3 XVector = new Vector3(1, 0, 0); 旋转,则不会转不过,而是转过90度后就又重新反向转回来了。

找到无法绕过去的原因了。

绕着xAxis轴旋转时,xAxis一般是固定不变的,但绕过某个角度后,xAxis的方向会突然反一下。

然后,相当于又沿反方向绕回来了。不断地反复,就停在那了。绕过去之后,要绕的角度就应该变个方向。

感觉和发电机中的电流流向原理有点像,当经过一个角度时,线圈(或其他某个结构)要反一下。

加个标志能判断是否反向一次,然后让标识反一下,就好了。

但是这样虽然不会停在那里,还是绕不过90度,就和前面围绕固定的(1, 0, 0)效果一样,会重新反向转回来。

不对,看起来是反转了,但从数字上看,Position确实是有绕一圈

 

 

另外,如果  Postion = new Vector3(10, 10, -50); Target = newVector3(10, 10, 0);。则在绕过去的时候会左右反一下。

而,如果  Postion = new Vector3(10, 10, -50); Target = newVector3(0, 0, 0);。则不会左右颠倒。

说明Target在原点时就不会了。

用茶壶看时发现,实际上Target在原点时也会左右颠倒的,只是原来是中心对称,看不出来。

可能在那个特殊时刻,要对z轴旋转一下。

看来是上下左右都颠倒一下,之前只看到左右颠倒也是因为对称的关系。

对z轴旋转180度吧。

但摄像机实际是只是一个向量而已,所谓的沿z轴旋转式没有任何效果的。

也就是说,问题可能处在摄像机之外,投影变换吗?

好像也不是,投影变换没有相应的参数。

发现摄像机有个参数一直被遗忘,向上方向。上下颠倒的话不就是上下左右都变了吗?

可以!

不过还有一瞬间的上下左右颠倒,应该是修改upVector的时机不对吧,再改改。

 

总数解决了,前面的处理都是只看到问题的一小部分所作的修正,并没有解决问题核心,虽然也起到一步一步慢慢接近问题核心的作用。

总之就是要修改向上方向(upVector),在每次转过上下90度时把upVector取反就行了。

实际上从一开始,转到上下90度的时候,上下左右前后都会颠倒。

之所以为什么会这样,可能真的和发电机中的那个现象一样吧。

不管了,程序能用了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值