c# 中Direct3D摄像机旋转问题,求答案,感激上苍解决!

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

if (isRotateByMouse)
            {
// CamPostion 摄像机位置
//CamTarget 摄像机目标位置
//mouseLastX,mouseLastY记录鼠标按下时的坐标位置
                Matrix currentView = device.Transform.View;//当前摄像机的视图矩阵

                float tempAngleY = 2 * (float)(e.X - mouseLastX) / this.Width;
                CamPostion.Subtract(CamTarget);

                Vector4 tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
                    Quaternion.RotationAxis(new Vector3(currentView.M12, currentView.M22, currentView.M32), tempAngleY)));
                CamPostion.X = tempV4.X;
                CamPostion.Y = tempV4.Y;
                CamPostion.Z = tempV4.Z;

                float tempAngleX = 4 * (float)(e.Y - mouseLastY) / this.Height;
                tempV4 = Vector3.Transform(CamPostion, Matrix.RotationQuaternion(
                    Quaternion.RotationAxis(new Vector3(currentView.M11, currentView.M21, currentView.M31), tempAngleX)));
                CamPostion.X = tempV4.X + CamTarget.X;
                CamPostion.Y = tempV4.Y + CamTarget.Y;
                CamPostion.Z = tempV4.Z + CamTarget.Z;
                Matrix viewMatrix = Matrix.LookAtLH(CamPostion, CamTarget, new Vector3(0, 1, 0));
                device.Transform.View = viewMatrix;

                mouseLastX = e.X;
                mouseLastY = e.Y;
            }

4 个解决方案

#1


调试跟踪,就能找到问题了。

#2


对于摄像头啊,其实呢,我推荐只是用两个参数表示摄像头的观察方向。
X和Y
X定义摄像头左右旋转角度
Y定义摄像头上下旋转角度
只需要用矩阵绕Z轴旋转X度,绕X轴旋转Y度即可。
和鼠标关联也简单,鼠标左右动就加减X,上下动就加减Y。

#3


引用 2 楼 ZIP_xG 的回复:
对于摄像头啊,其实呢,我推荐只是用两个参数表示摄像头的观察方向。
X和Y
X定义摄像头左右旋转角度
Y定义摄像头上下旋转角度
只需要用矩阵绕Z轴旋转X度,绕X轴旋转Y度即可。
和鼠标关联也简单,鼠标左右动就加减X,上下动就加减Y。

补充一下,如果你想做到像某些太空游戏,模型什么的都可以颠倒无重力之类的。
你可以再定义一个Z,这个Z呢,是摄像机绕Y轴旋转Z度。
可以用Q和E来加减Z。这样按Q和Z时,就能变相的在空间里转向颠倒了。

#4


花了半天多总算解决了:在每次转过上下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);
        }

完整的C# Camera类: http://blog.csdn.net/llhswwha/article/details/25957053

#1


调试跟踪,就能找到问题了。

#2


对于摄像头啊,其实呢,我推荐只是用两个参数表示摄像头的观察方向。
X和Y
X定义摄像头左右旋转角度
Y定义摄像头上下旋转角度
只需要用矩阵绕Z轴旋转X度,绕X轴旋转Y度即可。
和鼠标关联也简单,鼠标左右动就加减X,上下动就加减Y。

#3


引用 2 楼 ZIP_xG 的回复:
对于摄像头啊,其实呢,我推荐只是用两个参数表示摄像头的观察方向。
X和Y
X定义摄像头左右旋转角度
Y定义摄像头上下旋转角度
只需要用矩阵绕Z轴旋转X度,绕X轴旋转Y度即可。
和鼠标关联也简单,鼠标左右动就加减X,上下动就加减Y。

补充一下,如果你想做到像某些太空游戏,模型什么的都可以颠倒无重力之类的。
你可以再定义一个Z,这个Z呢,是摄像机绕Y轴旋转Z度。
可以用Q和E来加减Z。这样按Q和Z时,就能变相的在空间里转向颠倒了。

#4


花了半天多总算解决了:在每次转过上下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);
        }

完整的C# Camera类: http://blog.csdn.net/llhswwha/article/details/25957053