1. 程式人生 > >C#DirectX3D開發(1) 攝像機旋轉問題,旋轉上下90度時出問題

C#DirectX3D開發(1) 攝像機旋轉問題,旋轉上下90度時出問題

問題描述:

當繞X軸旋轉時,從90度旋轉到-90度正常,再繼續旋轉時無法旋轉過去,不能達到360度旋轉,求高手賜教。
自己搜尋了,有人碰到相同問題:

為了有人搜尋時能找到這裡,把他們的描述也貼出來:

求高手賜教,本人正在學習基於C#的directx開發,在攝像機旋轉遇到問題了,無法繞X軸旋轉360度。附部分程式碼 

(http://bbs.csdn.net/topics/390441832?page=1)

最近在做一個專案是使用C#模擬一些簡單的3D,在網路上早到了一些C#的程式碼,過程還好,但是唯一頭痛的問題就是攝像機旋轉到垂直方向後就不能繼續旋轉,結構翻轉到了原始位置,程式碼如下,希望大家幫我修改一下,我想是做個判斷就可以了,但是我對三維空間不是很清楚。希望大家幫個忙哦。

http://bbs.csdn.net/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度的時候,上下左右前後都會顛倒。

之所以為什麼會這樣,可能真的和發電機中的那個現象一樣吧。

不管了,程式能用了。