Files
libremetaverse/applications/sceneviewer/Camera.cs
bushing 4fa67d3b35 svn:eol-style native is your friend
git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@360 52acb1d6-8a22-11de-b505-999d5b087335
2006-10-21 02:52:28 +00:00

188 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
namespace sceneviewer
{
/// <summary>
/// Simple third-person camera class
/// </summary>
public class Camera
{
#region Constants
private static readonly float MAX_RADIANS = (float)(Math.PI * 2.0);
private static readonly float MAX_PHI = (float)((Math.PI) * 2.0);
private static readonly float MIN_PHI = 0;
#endregion Constants
#region Private Fields
private Vector3 _cameraPosition;
private Vector3 _lookatPosition;
private Matrix _projection;
private float _theta;
private float _phi;
private float _zoom;
#endregion Private Fields
#region Constructors
/// <summary>
/// Default constructor. Assumes the camera should be oriented up.
/// </summary>
/// <param name="pos"></param>
/// <param name="lookAt"></param>
public Camera(GameWindow window, Vector3 pos, Vector3 lookAt)
{
_cameraPosition = pos;
_lookatPosition = lookAt;
UpdateProjection(window);
}
#endregion Constructors
#region Properties
/// <summary>
/// Generate the current view matrix for the camera
/// </summary>
public Matrix ViewMatrix
{
get
{
Vector3 newCameraPosition = _cameraPosition;
Matrix rotationMatrix;
// Apply zoom
newCameraPosition += GetZoomVector();
// Apply Z rotation
rotationMatrix = Matrix.CreateRotationX(_phi);
newCameraPosition = Vector3.Transform(newCameraPosition,
rotationMatrix);
// Apply Y rotation
rotationMatrix = Matrix.CreateRotationY( _theta);
newCameraPosition = Vector3.Transform(newCameraPosition,
rotationMatrix);
return Matrix.CreateLookAt(newCameraPosition, _lookatPosition,
new Vector3(0.0f, 0.0f, 1.0f));
}
}
public Matrix ProjectionMatrix
{
get
{
return _projection;
}
}
/// <summary>
/// Gets the view and projection matrices multiplied together
/// </summary>
public Matrix ViewProjectionMatrix
{
get
{
return ViewMatrix * _projection;
}
}
/// <summary>
/// Gets the camera position
/// </summary>
public Vector3 Position
{
get
{
return _cameraPosition;
}
}
/// <summary>
/// Get or set the current angle of rotation in radians about the
/// Y-axis for the camera.
/// </summary>
public float Theta
{
get { return _theta; }
set
{
_theta = value % MAX_RADIANS;
}
}
/// <summary>
/// Get or set the current angle of rotation in radians about the
/// Z-axis for the camera.
///
/// Applies a hard cap on the minimum or maximum values of phi.
/// </summary>
public float Phi
{
get { return _phi; }
set
{
if (value > MAX_PHI)
{
_phi = MAX_PHI;
}
else if (value < MIN_PHI)
{
_phi = MIN_PHI;
}
else
{
_phi = value;
}
}
}
/// <summary>
/// Get or set the current zoom of the camera.
///
/// TODO: I should set a hard value on how close
/// the camera can zoom in; it should never be able to go
/// through the look at point.
/// </summary>
public float Zoom
{
get { return _zoom; }
// TODO: Add a hard limit on zoom amount.
set { _zoom = value; }
}
#endregion Properties
/// <summary>
/// Call this method any time the client window changes.
/// </summary>
public void UpdateProjection(GameWindow window)
{
_projection = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 4.0f,
(float)window.ClientWidth / (float)window.ClientHeight,
1.0f, 512.0f);
}
/// <summary>
/// Determine how far the camera should move forward
/// or backward based on the current zoom value.
///
/// This is calculated by finding the normal vector
/// between the camera's position and the LookAt
/// point and multiplying this vector by the zoom
/// amount.
/// </summary>
/// <returns></returns>
private Vector3 GetZoomVector()
{
Vector3 diff = _cameraPosition - _lookatPosition;
diff.Normalize();
diff *= _zoom;
return diff;
}
}
}