Desktop/Dev/Cameras/Cameras/QuaternionCamera.cs

Go to the documentation of this file.
00001 using System;
00002 using Microsoft.Xna.Framework;
00003 using Microsoft.Xna.Framework.Graphics;
00004 
00005 namespace Mindshifter
00006 {
00010     public enum TransformSpace
00011     {
00012         CameraSpace,
00013         WorldSpace,
00014     }
00015 
00020     public sealed class QuaternionCamera : ICamera
00021     {
00022         private Matrix          mViewMatrix;
00023         private Matrix          mInverseViewMatrix;
00024 
00025         private Projection      mProjection;
00026 
00027         private Vector3         mPosition;
00028         private Quaternion      mOrientation;
00029 
00030         private bool            mRequiresUpdate;
00031 
00035         public Matrix ViewMatrix
00036         {
00037             get
00038             {
00039                 if (mRequiresUpdate)
00040                     BuildMatrix();
00041 
00042                 return mViewMatrix;
00043             }
00044         }
00045 
00049         public Matrix InverseViewMatrix
00050         {
00051             get
00052             {
00053                 if (mRequiresUpdate)
00054                     BuildMatrix();
00055 
00056                 return mInverseViewMatrix;
00057             }
00058         }
00059 
00063         public Matrix ProjectionMatrix
00064         {
00065             get { return mProjection.Matrix; }
00066         }
00067 
00071         public Projection Projection
00072         {
00073             get { return mProjection; }
00074         }
00075 
00079         public Vector3 Position
00080         {
00081             get { return mPosition; }
00082             set
00083             {
00084                 mPosition = value;
00085                 mRequiresUpdate = true;
00086             }
00087         }
00088 
00092         public Quaternion Orientation
00093         {
00094             get { return mOrientation; }
00095             set
00096             {
00097                 Quaternion.Normalize(ref value, out mOrientation);
00098                 mRequiresUpdate = true;
00099             }
00100         }
00101 
00105         public float X
00106         {
00107             get { return mPosition.X; }
00108             set
00109             {
00110                 mPosition.X = value;
00111                 mRequiresUpdate = true;
00112             }
00113         }
00114 
00118         public float Y
00119         {
00120             get { return mPosition.Y; }
00121             set
00122             {
00123                 mPosition.Y = value;
00124                 mRequiresUpdate = true;
00125             }
00126         }
00127 
00131         public float Z
00132         {
00133             get { return mPosition.Z; }
00134             set
00135             {
00136                 mPosition.Z = value;
00137                 mRequiresUpdate = true;
00138             }
00139         }
00140 
00144         public Vector3 Up
00145         {
00146             get
00147             {
00148                 if (mRequiresUpdate)
00149                     BuildMatrix();
00150 
00151                 return mInverseViewMatrix.Up;
00152             }
00153         }
00154 
00158         public Vector3 Forward
00159         {
00160             get
00161             {
00162                 if (mRequiresUpdate)
00163                     BuildMatrix();
00164 
00165                 return mInverseViewMatrix.Forward;
00166             }
00167         }
00168 
00172         public Vector3 Right
00173         {
00174             get
00175             {
00176                 if (mRequiresUpdate)
00177                     BuildMatrix();
00178 
00179                 return mInverseViewMatrix.Right;
00180             }
00181         }
00182 
00186         public BoundingFrustum Frustum
00187         {
00188             get { return new BoundingFrustum(ViewMatrix * ProjectionMatrix); }
00189         }
00190 
00196         public QuaternionCamera() 
00197             : this(Vector3.Zero, Quaternion.Identity, (float)Math.PI / 4f, 4f /3f, 1f, 1000f)
00198         {
00199 
00200         }
00201 
00209         public QuaternionCamera(Vector3 position, Quaternion orientation)
00210             : this(position, orientation, (float)Math.PI / 4f, 4f / 3f, 1f, 1000f)
00211         {
00212 
00213         }
00214 
00225         public QuaternionCamera(Vector3 position, Quaternion orientation, float fov, 
00226                                     float aspect, float near, float far)
00227         {
00228             mPosition = position;
00229             mOrientation = orientation;
00230             mViewMatrix = Matrix.Identity;
00231             mInverseViewMatrix = Matrix.Identity;
00232 
00233             mProjection = new Projection(fov, aspect, near, far);
00234 
00235             mRequiresUpdate = true;
00236         }
00237 
00247         public QuaternionCamera(Vector3 position, Quaternion orientation, Rectangle rect, 
00248                                     float near, float far)
00249         {
00250             mPosition = position;
00251             mOrientation = orientation;
00252             mViewMatrix = Matrix.Identity;
00253             mInverseViewMatrix = Matrix.Identity;
00254 
00255             mProjection = new Projection(rect.X, rect.Y, rect.Width, rect.Height, near, far);
00256 
00257             mRequiresUpdate = true;
00258         }
00259 
00265         public void Pitch(float pitchAmount, TransformSpace space)
00266         {
00267             if (mRequiresUpdate)
00268                 BuildMatrix();
00269 
00270             switch (space)
00271             {
00272                 case TransformSpace.CameraSpace:
00273                     mOrientation *= Quaternion.CreateFromAxisAngle(Vector3.Normalize(mInverseViewMatrix.Right), pitchAmount);
00274                     break;
00275 
00276                 case TransformSpace.WorldSpace:
00277                     mOrientation *= Quaternion.CreateFromAxisAngle(Vector3.Right, pitchAmount);
00278                     break;
00279             }
00280 
00281             mRequiresUpdate = true;
00282         }
00283 
00288         public void Pitch(float pitchAmount)
00289         {
00290             Pitch(pitchAmount, TransformSpace.CameraSpace);
00291         }
00292 
00298         public void Yaw(float yawAmount, TransformSpace space)
00299         {
00300             if (mRequiresUpdate)
00301                 BuildMatrix();
00302 
00303             switch (space)
00304             {
00305                 case TransformSpace.CameraSpace:
00306                     mOrientation *= Quaternion.CreateFromAxisAngle(Vector3.Normalize(mInverseViewMatrix.Up), yawAmount);
00307                     break;
00308 
00309                 case TransformSpace.WorldSpace:
00310                     mOrientation *= Quaternion.CreateFromAxisAngle(Vector3.Up, yawAmount);
00311                     break;
00312             }
00313 
00314             mRequiresUpdate = true;
00315         }
00316 
00321         public void Yaw(float yawAmount)
00322         {
00323             Yaw(yawAmount, TransformSpace.CameraSpace);
00324         }
00325 
00331         public void Roll(float rollAmount, TransformSpace space)
00332         {
00333             if (mRequiresUpdate)
00334                 BuildMatrix();
00335 
00336             switch (space)
00337             {
00338                 case TransformSpace.CameraSpace:
00339                     mOrientation *= Quaternion.CreateFromAxisAngle(Vector3.Normalize(mInverseViewMatrix.Backward), rollAmount);
00340                     break;
00341 
00342                 case TransformSpace.WorldSpace:
00343                     mOrientation *= Quaternion.CreateFromAxisAngle(Vector3.Backward, rollAmount);
00344                     break;
00345             }
00346 
00347             mRequiresUpdate = true;
00348         }
00349 
00354         public void Roll(float rollAmount)
00355         {
00356             Roll(rollAmount, TransformSpace.CameraSpace);
00357         }
00358 
00364         public void Translate(Vector3 amount, TransformSpace space)
00365         {
00366             if (mRequiresUpdate)
00367                 BuildMatrix();
00368 
00369             switch (space)
00370             {
00371                 case TransformSpace.CameraSpace:
00372                     mPosition += mInverseViewMatrix.Right * amount.X +
00373                         mInverseViewMatrix.Up * amount.Y + mInverseViewMatrix.Backward * amount.Z;
00374                     break;
00375 
00376                 case TransformSpace.WorldSpace:
00377                     mPosition += amount;
00378                     break;
00379             }
00380 
00381             mRequiresUpdate = true;
00382         }
00383 
00388         public void Translate(Vector3 amount)
00389         {
00390             Translate(amount, TransformSpace.CameraSpace);
00391         }
00392 
00398         public void TranslateX(float amount, TransformSpace space)
00399         {
00400             if (mRequiresUpdate)
00401                 BuildMatrix();
00402 
00403             switch (space)
00404             {
00405                 case TransformSpace.CameraSpace:
00406                     mPosition += mInverseViewMatrix.Right * amount;
00407                     break;
00408 
00409                 case TransformSpace.WorldSpace:
00410                     mPosition.X += amount;
00411                     break;
00412             }
00413 
00414             mRequiresUpdate = true;
00415         }
00416 
00421         public void TranslateX(float amount)
00422         {
00423             TranslateX(amount, TransformSpace.CameraSpace);
00424         }
00425 
00431         public void TranslateY(float amount, TransformSpace space)
00432         {
00433             if (mRequiresUpdate)
00434                 BuildMatrix();
00435 
00436             switch (space)
00437             {
00438                 case TransformSpace.CameraSpace:
00439                     mPosition += mInverseViewMatrix.Up * amount;
00440                     break;
00441 
00442                 case TransformSpace.WorldSpace:
00443                     mPosition.Y += amount;
00444                     break;
00445             }
00446 
00447             mRequiresUpdate = true;
00448         }
00449 
00454         public void TranslateY(float amount)
00455         {
00456             TranslateY(amount, TransformSpace.CameraSpace);
00457         }
00458 
00464         public void TranslateZ(float amount, TransformSpace space)
00465         {
00466             if (mRequiresUpdate)
00467                 BuildMatrix();
00468 
00469             switch (space)
00470             {
00471                 case TransformSpace.CameraSpace:
00472                     mPosition += mInverseViewMatrix.Backward * amount;
00473                     break;
00474 
00475                 case TransformSpace.WorldSpace:
00476                     mPosition.Z += amount;
00477                     break;
00478             }
00479 
00480             mRequiresUpdate = true;
00481         }
00482 
00487         public void TranslateZ(float amount)
00488         {
00489             TranslateZ(amount, TransformSpace.CameraSpace);
00490         }
00491 
00495         private void BuildMatrix()
00496         {
00497             Vector3 P;
00498             Quaternion O;
00499             Matrix T;
00500             Matrix R;
00501 
00502             Vector3.Negate(ref mPosition, out P);
00503             Quaternion.Negate(ref mOrientation, out O);
00504 
00505             Matrix.CreateTranslation(ref P, out T);
00506             Matrix.CreateFromQuaternion(ref O, out R);
00507 
00508             Matrix.Multiply(ref T, ref R, out mViewMatrix);
00509             Matrix.Invert(ref mViewMatrix, out mInverseViewMatrix);
00510 
00511             mRequiresUpdate = false;
00512         }
00513 
00518         public void Update(float elapsedSeconds)
00519         {
00520             if (mRequiresUpdate)
00521                 BuildMatrix();
00522         }
00523 
00529         public Ray GetPickRay(Vector2 position, Viewport viewport)
00530         {
00531             Vector3 near = viewport.Unproject(new Vector3(position, 0f), ProjectionMatrix,
00532                                 ViewMatrix, Matrix.Identity);
00533 
00534             Vector3 far = viewport.Unproject(new Vector3(position, 1f), ProjectionMatrix,
00535                                 ViewMatrix, Matrix.Identity);
00536 
00537             return new Ray(near, Vector3.Normalize(far - near));
00538         }
00539     }
00540 }

Generated on Mon Mar 31 03:29:21 2008 for Cameras by  doxygen 1.5.1-p1