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 }