自己根据C++ D3D的源码改写一个相机类(第一人称)。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using Microsoft.DirectX; 6 using Microsoft.DirectX.PrivateImplementationDetails; 7 using Microsoft.DirectX.Direct3D; 8 9 namespace AppScene 10 { 11 public enum CameraType { LANDOBJECT, AIRCRAFT }; 12 public class Camera 13 { 14 CameraType mCameraType; 15 Vector3 mPosition; //相机位置 16 Vector3 mLook;//LookVector 17 Vector3 mUp;// UpVector 18 Vector3 mRight;// RightVector 19 Vector3 ViewFrustum;// 平面截投体 20 21 protected Viewport mViewPort;//视口大小 22 protected Matrix m_ProjectionMatrix; //上一次渲染采用的投影变换矩阵 Projection matrix used in last render. 23 protected Matrix m_ViewMatrix; //上一次渲染采用的观察矩阵 View matrix used in last render. 24 protected Matrix m_WorldMatrix = Matrix.Identity;//世界变换矩阵 25 public Camera() 26 { 27 mCameraType = CameraType.AIRCRAFT; 28 mPosition = new Vector3(0.0f, 0.0f, -50.0f);//注意默认位置,现在对了。 29 mRight = new Vector3(0.0f, 1.0f, 0.0f); 30 mUp = new Vector3(0.0f, 1.0f, 0.0f); 31 mLook = new Vector3(0.0f, 0.0f, 10.0f); 32 } 33 public Camera(Vector3 cameraPosition, Vector3 cameraTarget, Vector3 upVector) 34 { 35 mCameraType = CameraType.AIRCRAFT; 36 mPosition = new Vector3(0.0f, 0.0f, -100.0f); 37 mRight = new Vector3(1.0f, 0.0f, 0.0f); 38 mUp = new Vector3(0.0f, 1.0f, 0.0f); 39 mLook = new Vector3(0.0f, 0.0f, 0.0f); 40 } 41 public void setCameraType(CameraType cameraType) 42 { 43 mCameraType = cameraType; 44 } 45 //前后移动 46 public void walk(float units) 47 { 48 // move only on xz plane for land object 49 if (mCameraType == CameraType.LANDOBJECT) 50 mPosition += new Vector3(mLook.X, 0.0f, mLook.Z) * units; 51 52 if (mCameraType == CameraType.AIRCRAFT) 53 mPosition += mLook * units; 54 } 55 //左右移动,扫射 56 public void strafe(float units) 57 { 58 // move only on xz plane for land object 59 if (mCameraType == CameraType.LANDOBJECT) 60 mPosition += new Vector3(mRight.X, 0.0f, mRight.Z) * units; 61 62 if (mCameraType == CameraType.AIRCRAFT) 63 mPosition += mRight * units; 64 } 65 //上下移动 66 public void fly(float units) 67 { 68 // move only on y-axis for land object 69 if (mCameraType == CameraType.LANDOBJECT) 70 mPosition.Y += units; 71 72 if (mCameraType == CameraType.AIRCRAFT) 73 mPosition += mUp * units; 74 } 75 76 // 倾斜角 77 public void Pitch(float angle) 78 { 79 Matrix T = Matrix.Identity; 80 //D3DXMatrixRotationAxis(&T, &_right, angle); 81 T.RotateAxis(mRight, angle); 82 // rotate _up and _look around _right vector 83 mUp.TransformCoordinate(T); 84 mLook.TransformCoordinate(T); 85 //D3DXVec3TransformCoord(&_up, &_up, &T); 86 //D3DXVec3TransformCoord(&_look, &_look, &T); 87 } 88 //俯仰角 89 public void Roll(float angle) 90 { 91 // only roll for aircraft type 92 if (mCameraType == CameraType.AIRCRAFT) 93 { 94 Matrix T = Matrix.Identity; 95 T.RotateAxis(mLook, angle); 96 97 // rotate _up and _right around _look vector 98 mRight.TransformCoordinate(T); 99 mUp.TransformCoordinate(T);100 }101 }102 // 航偏角103 public void Yaw(float angle)104 {105 Matrix T = Matrix.Identity;106 107 // rotate around world y (0, 1, 0) always for land object108 if (mCameraType == CameraType.LANDOBJECT)109 T.RotateY(angle);110 // rotate around own up vector for aircraft111 if (mCameraType == CameraType.AIRCRAFT)112 T.RotateAxis(mUp, angle);113 114 // rotate _right and _look around _up or y-axis115 mRight.TransformCoordinate(T);116 mLook.TransformCoordinate(T);117 }118 public void SetPosition(Vector3 position)// 设置相机世界坐标 119 {120 mPosition = position;121 }122 //更新相机状态123 public Matrix UpdateCamera()124 {125 Matrix mViewMatrix = Matrix.Identity;126 // Keep camera's axes orthogonal to eachother127 //D3DXVec3Normalize(&_look, &_look);128 mLook.Normalize();129 //D3DXVec3Cross(&, &_look, &_right);130 // _up = Vector3.Cross(_look, _right);131 //D3DXVec3Normalize(&_up, &_up);132 mUp.Normalize();133 //D3DXVec3Cross(&_right, &_up, &_look);134 mRight = Vector3.Cross(mUp, mLook);135 //D3DXVec3Normalize(&_right, &_right);136 mRight.Normalize();137 // Build the view matrix:138 //float x = -D3DXVec3Dot(&_right, &_pos);139 //float y = -D3DXVec3Dot(&_up, &_pos);140 //float z = -D3DXVec3Dot(&_look, &_pos);141 float x = -Vector3.Dot(mRight, mPosition);142 float y = -Vector3.Dot(mUp, mPosition);143 float z = -Vector3.Dot(mLook, mPosition);144 145 mViewMatrix.M11 = mRight.X; mViewMatrix.M12 = mUp.X; mViewMatrix.M13 = mLook.X; mViewMatrix.M14 = 0.0f;146 mViewMatrix.M21 = mRight.Y; mViewMatrix.M22 = mUp.Y; mViewMatrix.M23 = mLook.Y; mViewMatrix.M24 = 0.0f;147 mViewMatrix.M31 = mRight.Z; mViewMatrix.M32 = mUp.Z; mViewMatrix.M33 = mLook.Z; mViewMatrix.M34 = 0.0f;148 mViewMatrix.M41 = x; mViewMatrix.M42 = y; mViewMatrix.M43 = z; mViewMatrix.M44 = 1.0f;149 return mViewMatrix;150 }151 152 public void Update(Microsoft.DirectX.Direct3D.Device m_Device3d)153 {154 Matrix V = UpdateCamera();155 m_Device3d.SetTransform(TransformType.View, V);156 }157 //视口大小158 public Viewport Viewport159 {160 get161 {162 return mViewPort;163 }164 }165 //观察变换矩阵166 public Matrix ViewMatrix167 {168 get169 {170 return m_ViewMatrix;171 }172 }173 //投影变换矩阵174 public Matrix ProjectionMatrix175 {176 get177 {178 return m_ProjectionMatrix;179 }180 }181 //世界变换矩阵182 public Matrix WorldMatrix183 {184 get185 {186 return m_WorldMatrix;187 }188 }189 ///190 /// UnProject和Project之前需要调用该方法191 /// 192 /// 193 public void ComputeMatrix(Device m_Device3d)194 {195 m_WorldMatrix = m_Device3d.GetTransform(TransformType.World);196 m_ProjectionMatrix = m_Device3d.GetTransform(TransformType.Projection);197 m_ViewMatrix = m_Device3d.GetTransform(TransformType.View);198 mViewPort = m_Device3d.Viewport;199 }200 ///201 /// Projects a point from world to screen coordinates.202 /// 计算指定世界坐标的屏幕坐标203 /// 204 /// Point in world space205 ///Point in screen space 206 public Vector3 Project(Vector3 point)207 {208 point.Project(mViewPort, m_ProjectionMatrix, m_ViewMatrix, m_WorldMatrix);209 return point;210 }211 212 internal Vector3 UnProject(Vector3 v1)213 {214 v1.Unproject(mViewPort, m_ProjectionMatrix, m_ViewMatrix, m_WorldMatrix);215 return v1;216 }217 }218 }
增加一个围绕某条射线旋转的方法:
1 // 2 public void RotateRay(float angle, Vector3 vOrigin, Vector3 vAxis) 3 { 4 // 计算新的焦点 5 Vector3 vView = mLook - vOrigin; 6 Matrix temp = Matrix.RotationAxis(vAxis, angle); 7 vView.TransformCoordinate(temp); 8 //vView.RotateAxis(angle, vAxis); 9 mLook = vOrigin + vView;10 11 // 计算新的视点12 vView = mPosition - vOrigin;13 // Matrix temp2 = Matrix.RotationAxis(vAxis, angle);14 vView.TransformCoordinate(temp);15 //vView.RotateAxis(angle, vAxis);16 mPosition = vOrigin + vView;17 18 mUp.TransformCoordinate(temp);19 // m_strafe.RotateAxis(angle, vAxis);20 }