自己根据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 object 108 if (mCameraType == CameraType.LANDOBJECT) 109 T.RotateY(angle); 110 // rotate around own up vector for aircraft 111 if (mCameraType == CameraType.AIRCRAFT) 112 T.RotateAxis(mUp, angle); 113 114 // rotate _right and _look around _up or y-axis 115 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 eachother 127 //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 Viewport 159 { 160 get 161 { 162 return mViewPort; 163 } 164 } 165 //观察变换矩阵 166 public Matrix ViewMatrix 167 { 168 get 169 { 170 return m_ViewMatrix; 171 } 172 } 173 //投影变换矩阵 174 public Matrix ProjectionMatrix 175 { 176 get 177 { 178 return m_ProjectionMatrix; 179 } 180 } 181 //世界变换矩阵 182 public Matrix WorldMatrix 183 { 184 get 185 { 186 return m_WorldMatrix; 187 } 188 } 189 /// <summary> 190 /// UnProject和Project之前需要调用该方法 191 /// </summary> 192 /// <param name="m_Device3d"></param> 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 /// <summary> 201 /// Projects a point from world to screen coordinates. 202 /// 计算指定世界坐标的屏幕坐标 203 /// </summary> 204 /// <param name="point">Point in world space</param> 205 /// <returns>Point in screen space</returns> 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 }