00001 using System;
00002 using Microsoft.Xna.Framework;
00003 using Microsoft.Xna.Framework.Graphics;
00004
00005 namespace Mindshifter
00006 {
00013 public sealed class OrbitCamera : ICamera
00014 {
00015 private Matrix mViewMatrix;
00016 private Projection mProjection;
00017
00018 private CameraSpring mLookAtSpring;
00019 private CameraSpring mEyeSpring;
00020
00021 private bool mLookAtSpringEnabled;
00022 private bool mEyeSpringEnabled;
00023
00024 private float mAzimuth;
00025 private float mDeclination;
00026 private float mRadius;
00027
00028 private float mMinAzimuth;
00029 private float mMaxAzimuth;
00030 private float mMinDeclination;
00031 private float mMaxDeclination;
00032 private float mMinRadius;
00033 private float mMaxRadius;
00034
00038 public Matrix ViewMatrix
00039 {
00040 get { return mViewMatrix; }
00041 }
00042
00046 public Matrix ProjectionMatrix
00047 {
00048 get { return mProjection.Matrix; }
00049 }
00050
00054 public Projection Projection
00055 {
00056 get { return mProjection; }
00057 }
00058
00062 public BoundingFrustum Frustum
00063 {
00064 get { return new BoundingFrustum(ViewMatrix * ProjectionMatrix); }
00065 }
00066
00070 public Vector3 Position
00071 {
00072 get
00073 {
00074 if(mEyeSpringEnabled)
00075 return mEyeSpring.Position;
00076
00077 return mEyeSpring.Origin;
00078 }
00079 }
00080
00084 public Vector3 LookAtPoint
00085 {
00086 get
00087 {
00088 if(mLookAtSpringEnabled)
00089 return mLookAtSpring.Position;
00090
00091 return mLookAtSpring.Origin;
00092 }
00093
00094 set { mLookAtSpring.Origin = value; }
00095 }
00096
00101 public bool EyeSpringEnabled
00102 {
00103 get { return mEyeSpringEnabled; }
00104 set { mEyeSpringEnabled = value; }
00105 }
00106
00110 public float EyeSpringStiffness
00111 {
00112 get { return mEyeSpring.Stiffness; }
00113 set { mEyeSpring.Stiffness = value; }
00114 }
00115
00119 public float EyeSpringDamping
00120 {
00121 get { return mEyeSpring.Damping; }
00122 set { mEyeSpring.Damping = value; }
00123 }
00124
00129 public bool LookAtSpringEnabled
00130 {
00131 get { return mLookAtSpringEnabled; }
00132 set { mLookAtSpringEnabled = value; }
00133 }
00134
00138 public float LookAtSpringStiffness
00139 {
00140 get { return mLookAtSpring.Stiffness; }
00141 set { mLookAtSpring.Stiffness = value; }
00142 }
00143
00147 public float LookAtSpringDamping
00148 {
00149 get { return mLookAtSpring.Damping; }
00150 set { mLookAtSpring.Damping = value; }
00151 }
00152
00156 public float Azimuth
00157 {
00158 get { return mAzimuth; }
00159 set { mAzimuth = MathHelper.Clamp(value, mMinAzimuth, mMaxAzimuth); }
00160 }
00161
00165 public float Declination
00166 {
00167 get { return mDeclination; }
00168 set { mDeclination = MathHelper.Clamp(value, mMinDeclination, mMaxDeclination); }
00169 }
00170
00174 public float Radius
00175 {
00176 get { return mRadius; }
00177 set { mRadius = MathHelper.Clamp(value, mMinRadius, mMaxRadius); }
00178 }
00179
00184 public float MinimumAzimuth
00185 {
00186 get { return mMinAzimuth; }
00187 set
00188 {
00189 mMinAzimuth = MathHelper.Clamp(value, float.MinValue, float.MaxValue);
00190
00191 if (mMaxAzimuth < mMinAzimuth)
00192 mMaxAzimuth = mMinAzimuth;
00193
00194 mAzimuth = MathHelper.Clamp(mAzimuth, mMinAzimuth, mMaxAzimuth);
00195 }
00196 }
00197
00202 public float MaximumAzimuth
00203 {
00204 get { return mMaxAzimuth; }
00205 set
00206 {
00207 mMaxAzimuth = MathHelper.Clamp(value, float.MinValue, float.MaxValue);
00208
00209 if (mMinAzimuth > mMaxAzimuth)
00210 mMinAzimuth = mMaxAzimuth;
00211
00212 mAzimuth = MathHelper.Clamp(mAzimuth, mMinAzimuth, mMaxAzimuth);
00213 }
00214 }
00215
00220 public float MinimumDeclination
00221 {
00222 get { return mMinDeclination; }
00223 set
00224 {
00225 mMinDeclination = MathHelper.Clamp(value, float.Epsilon, (float)Math.PI - float.Epsilon);
00226
00227 if (mMaxDeclination < mMinDeclination)
00228 mMaxDeclination = mMinDeclination;
00229
00230 mDeclination = MathHelper.Clamp(mDeclination, mMinDeclination, mMaxDeclination);
00231 }
00232 }
00233
00238 public float MaximumDeclination
00239 {
00240 get { return mMaxDeclination; }
00241 set
00242 {
00243 mMaxDeclination = MathHelper.Clamp(value, float.Epsilon, (float)Math.PI - float.Epsilon);
00244
00245 if (mMinDeclination > mMaxDeclination)
00246 mMinDeclination = mMaxDeclination;
00247
00248 mDeclination = MathHelper.Clamp(mDeclination, mMinDeclination, mMaxDeclination);
00249 }
00250 }
00251
00256 public float MinimumRadius
00257 {
00258 get { return mMinRadius; }
00259 set
00260 {
00261 mMinRadius = MathHelper.Clamp(value, float.Epsilon, float.MaxValue);
00262
00263 if (mMaxRadius < mMinRadius)
00264 mMaxRadius = mMinRadius;
00265
00266 mRadius = MathHelper.Clamp(mRadius, mMinRadius, mMaxRadius);
00267 }
00268 }
00269
00274 public float MaximumRadius
00275 {
00276 get { return mMaxRadius; }
00277 set
00278 {
00279 mMaxRadius = MathHelper.Clamp(value, float.Epsilon, float.MaxValue);
00280
00281 if (mMinRadius > mMaxRadius)
00282 mMinRadius = mMaxRadius;
00283
00284 mRadius = MathHelper.Clamp(mRadius, mMinRadius, mMaxRadius);
00285 }
00286 }
00287
00294 public OrbitCamera()
00295 : this(0f, (float)Math.PI /2f, 1f, (float)Math.PI / 4f, 4f / 3f, 1f, 1000f)
00296 {
00297
00298 }
00299
00308 public OrbitCamera(float azimuth, float declination, float radius)
00309 : this(azimuth, declination, radius, (float)Math.PI / 4f, 4f / 3f, 1f, 1000f)
00310 {
00311
00312 }
00313
00325 public OrbitCamera(float azimuth, float declination, float radius, float fov,
00326 float aspect, float near, float far)
00327 {
00328 mProjection = new Projection(fov, aspect, near, far);
00329
00330 mEyeSpring = new CameraSpring();
00331 mLookAtSpring = new CameraSpring();
00332
00333 mEyeSpringEnabled = false;
00334 mLookAtSpringEnabled = false;
00335
00336 mMinAzimuth = float.MinValue;
00337 mMaxAzimuth = float.MaxValue;
00338 mMinDeclination = float.Epsilon;
00339 mMaxDeclination = (float)Math.PI - float.Epsilon;
00340 mMinRadius = float.Epsilon;
00341 mMaxRadius = float.MaxValue;
00342
00343 mAzimuth = MathHelper.Clamp(azimuth, mMinAzimuth, mMaxAzimuth);
00344 mDeclination = MathHelper.Clamp(declination, mMinDeclination, mMaxDeclination);
00345 mRadius = MathHelper.Clamp(radius, mMinRadius, mMaxRadius);
00346 }
00347
00358 public OrbitCamera(float azimuth, float declination, float radius, Rectangle rect,
00359 float near, float far)
00360 {
00361 mProjection = new Projection(rect, near, far);
00362
00363 mEyeSpring = new CameraSpring();
00364 mLookAtSpring = new CameraSpring();
00365
00366 mEyeSpringEnabled = false;
00367 mLookAtSpringEnabled = false;
00368
00369 mMinAzimuth = float.MinValue;
00370 mMaxAzimuth = float.MaxValue;
00371 mMinDeclination = float.Epsilon;
00372 mMaxDeclination = (float)Math.PI - float.Epsilon;
00373 mMinRadius = float.Epsilon;
00374 mMaxRadius = float.MaxValue;
00375
00376 mAzimuth = MathHelper.Clamp(azimuth, mMinAzimuth, mMaxAzimuth);
00377 mDeclination = MathHelper.Clamp(declination, mMinDeclination, mMaxDeclination);
00378 mRadius = MathHelper.Clamp(radius, mMinRadius, mMaxRadius);
00379 }
00380
00385 public void Yaw(float value)
00386 {
00387 Azimuth += value;
00388 }
00389
00394 public void Pitch(float value)
00395 {
00396 Declination += value;
00397 }
00398
00403 public void Zoom(float value)
00404 {
00405 Radius += value;
00406 }
00407
00412 public void Update(float elapsedSeconds)
00413 {
00414 Vector3 eye = Vector3.Zero;
00415
00416 eye.X = mRadius * (float)Math.Sin(mDeclination) * (float)Math.Cos(mAzimuth);
00417 eye.Z = mRadius * (float)Math.Sin(mDeclination) * (float)Math.Sin(mAzimuth);
00418 eye.Y = mRadius * (float)Math.Cos(mDeclination);
00419
00420 mEyeSpring.Origin = LookAtPoint + eye;
00421
00422 mEyeSpring.Update(elapsedSeconds);
00423 mLookAtSpring.Update(elapsedSeconds);
00424
00425 mViewMatrix = Matrix.CreateLookAt(Position, LookAtPoint, Vector3.UnitY);
00426 }
00427
00433 public Ray GetPickRay(Vector2 position, Viewport viewport)
00434 {
00435 Vector3 near = viewport.Unproject(new Vector3(position, 0f), ProjectionMatrix,
00436 ViewMatrix, Matrix.Identity);
00437
00438 Vector3 far = viewport.Unproject(new Vector3(position, 1f), ProjectionMatrix,
00439 ViewMatrix, Matrix.Identity);
00440
00441 return new Ray(near, Vector3.Normalize(far - near));
00442 }
00443 }
00444 }