<Introduction to 3D Game Programming with Direct3D 11.0>第15章Camera类的C#(SharpDX)实现。
using System; using SharpDX; namespace SharpDX_Study_001 { class Camera { public Camera() { mPosition = Vector3.Zero; mRight = Vector3.UnitX; mUp = Vector3.UnitY; mLook = Vector3.UnitZ; SetLens(0.2f * SharpDX.MathUtil.Pi, 1.0f, 1.0f, 1000.0f); } public Vector4 PositionXM { get { return new Vector4(mPosition, 0); } } public Vector3 Position { get { return mPosition; } set { mPosition = value; } } public Vector4 RightXM { get { return new Vector4(mRight, 0); } } public Vector4 UpXM { get { return new Vector4(mUp, 0); } } public Vector4 LookXM { get { return new Vector4(mLook, 0); } } public Vector3 Right { get { return mRight; } } public Vector3 Look { get { return mLook; } } public Vector3 Up { get { return mUp; } } public float NearZ { get { return mNearZ; } } public float FarZ { get { return mFarZ; } } public float Aspect { get { return mAspect; } } public float FovY { get { return mFovY; } } public float FovX { get { float halfWidth = 0.5f * NearWindowWidth; return 2.0f * Convert.ToSingle(Math.Atan(halfWidth / mNearZ)); } } public float NearWindowWidth { get { return mAspect * mNearWindowHeight; } } public float NearWindowHeight { get { return mNearWindowHeight; } } public float FarWindowWidth { get { return mAspect * mFarWindowHeight; } } public float FarWindowHeight { get { return mFarWindowHeight; } } /// <summary> /// Set frustum. /// </summary> /// <param name="fovY"></param> /// <param name="aspect"></param> /// <param name="zn"></param> /// <param name="zf"></param> public void SetLens(float fovY, float aspect, float zn, float zf) { // cache properties mFovY = fovY; mAspect = aspect; mNearZ = zn; mFarZ = zf; mNearWindowHeight = 2.0f * mNearZ * Convert.ToSingle(Math.Tan(0.5f * mFovY)); mFarWindowHeight = 2.0f * mFarZ * Convert.ToSingle(Math.Tan(0.5f * mFovY)); mProj = Matrix.PerspectiveFovLH(mFovY, mAspect, mNearZ, mFarZ); } // // Define camera space via LookAt parameters. public void LookAt(Vector4 pos, Vector4 target, Vector4 worldUp) { Vector3 L = new Vector3(pos.X, pos.Y, pos.Z); Vector3 T = new Vector3(target.X, target.Y, target.Z); Vector3 U = new Vector3(worldUp.X, worldUp.Y, worldUp.Z); LookAt(L, T, U); } public void LookAt(Vector3 pos, Vector3 target, Vector3 up) { mPosition = pos; mLook = Vector3.Normalize(target - pos); mRight = Vector3.Normalize(Vector3.Cross(up, mLook)); mUp = Vector3.Cross(mLook, mRight); } public Matrix View { get { return mView; } } public Matrix Proj { get { return mProj; } } public Matrix ViewProj { get { return View * Proj; } } // Strafe/Walk the camera a distance d. public void Strafe(float d) { // mPosition += d*mRight Vector4 s = new Vector4(d); var nPos = (s * RightXM + PositionXM); mPosition = new Vector3(nPos.X, nPos.Y, nPos.Z); } public void Walk(float d) { // mPosition += d*mLook Vector4 s = new Vector4(d); var nPos = (s * LookXM + PositionXM); mPosition = new Vector3(nPos.X, nPos.Y, nPos.Z); } // Rotate the camera. public void Pitch(float angle) { // Rotate up and look vector about the right vector. Matrix R = Matrix.RotationAxis(mRight, angle); mUp = Vector3.TransformNormal(mUp, R); mLook = Vector3.TransformNormal(mLook, R); } public void RotateY(float angle) { // Rotate the basis vectors about the world y-axis. Matrix R = Matrix.RotationY(angle); mRight = Vector3.TransformNormal(mRight, R); mUp = Vector3.TransformNormal(mUp, R); mLook = Vector3.TransformNormal(mLook, R); } // After modifying camera position/orientation, call to rebuild the view matrix. public void UpdateViewMatrix() { var R = mRight; var U = mUp; var L = mLook; var P = mPosition; // Keep camera's axes orthogonal to each other and of unit length. L = Vector3.Normalize(L); U = Vector3.Normalize(Vector3.Cross(mLook, mRight)); // U, L already ortho-normal, so no need to normalize cross product. R = Vector3.Cross(U, L); // Fill in the view matrix entries. float x = -Vector3.Dot(P, R); float y = -Vector3.Dot(P, U); float z = -Vector3.Dot(P, L); mRight = R; mUp = U; mLook = L; mView.Column1 = new Vector4(mRight, x); mView.Column2 = new Vector4(mUp, y); mView.Column3 = new Vector4(mLook, z); mView.Column4 = Vector4.UnitW; } private Vector3 mPosition; private Vector3 mRight; private Vector3 mUp; private Vector3 mLook; // Cache frustum properties. float mNearZ; float mFarZ; float mAspect; float mFovY; float mNearWindowHeight; float mFarWindowHeight; Matrix mView; Matrix mProj; } }