/*
Copyright (C) 2010 Bepu Entertainment LLC.
This software source code is provided 'as-is', without
any express or implied warranty. In no event will the authors be held
liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Contact us at:
contact@bepu-games.com
*/
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using BEPUphysics;
using BEPUphysics.Entities;
using Microsoft.Xna.Framework.Input.Touch;
using BEPUphysicsPhoneDemo.UIManagement;
using System;
namespace BEPUphysicsPhoneDemo
{
///
/// Simple camera class for moving around the demos area.
///
public class Camera
{
///
/// Gets or sets the position of the camera.
///
public Vector3 position { get; set; }
float myYaw;
float myPitch;
///
/// Gets or sets the yaw rotation of the camera.
///
public float yaw
{
get
{
return myYaw;
}
set
{
myYaw = MathHelper.WrapAngle(value);
}
}
///
/// Gets or sets the pitch rotation of the camera.
///
public float pitch
{
get
{
return myPitch;
}
set
{
myPitch = value;
if (myPitch > MathHelper.PiOver2)
myPitch = MathHelper.PiOver2;
else if (myPitch < -MathHelper.PiOver2)
myPitch = -MathHelper.PiOver2;
}
}
///
/// Gets or sets the speed at which the camera moves.
///
public float speed { get; set; }
Matrix myViewMatrix;
///
/// Gets the view matrix of the camera.
///
public Matrix viewMatrix
{
get
{
return myViewMatrix;
}
}
///
/// Gets or sets the projection matrix of the camera.
///
public Matrix projectionMatrix { get; set; }
Matrix myWorldMatrix;
///
/// Gets the world transformation of the camera.
///
public Matrix worldMatrix
{
get
{
return myWorldMatrix;
}
}
///
/// Gets the game used by the camera.
///
public PhoneGame game { get; private set; }
///
/// Creates a camera.
///
/// Game used by the camera.
/// Touch manager to control the input of the camera.
/// Initial position of the camera.
/// Speed of the camera per second.
/// Initial pitch angle of the camera.
/// Initial yaw value of the camera.
/// Projection matrix used.
public Camera(PhoneGame game, TouchManager manager, Vector3 pos, float s, float p, float y, Matrix projMatrix)
{
this.game = game;
position = pos;
speed = s;
yaw = y;
pitch = p;
projectionMatrix = projMatrix;
touchedMethod = new Func(touched);
touchUpdatedMethod = new Func(touchUpdated);
touchReleasedMethod = new Func(released);
}
///
/// Moves the camera forward.
///
/// Distance to move.
public void moveForward(float distance)
{
position += myWorldMatrix.Forward * distance;
}
///
/// Moves the camera to the right.
///
/// Distance to move.
public void moveRight(float distance)
{
position += myWorldMatrix.Right * distance;
}
///
/// Moves the camera up.
///
/// Distanec to move.
public void moveUp(float distance)
{
position += new Vector3(0, distance, 0);
}
TouchLocation originalTouchLocation;
TouchLocation currentTouchLocation;
bool touched(TouchLocation location)
{
if (originalTouchLocation.State == TouchLocationState.Invalid)
{
originalTouchLocation = location;
currentTouchLocation = originalTouchLocation;
return true;
}
return false;
}
bool released(TouchLocation location)
{
if (originalTouchLocation.Id == location.Id)
{
originalTouchLocation = default(TouchLocation);
return true;
}
return false;
}
bool touchUpdated(TouchLocation location)
{
if (location.Id == originalTouchLocation.Id)
{
currentTouchLocation = location;
return true;
}
return false;
}
///
/// Updates the state of the camera.
///
/// Time since the last frame in seconds.
public void update(float dt)
{
myWorldMatrix = Matrix.CreateFromAxisAngle(Vector3.Right, pitch) * Matrix.CreateFromAxisAngle(Vector3.Up, yaw);
float distance = speed * dt;
if (originalTouchLocation.State != TouchLocationState.Invalid)
{
bool moving = false;
if (originalTouchLocation.Position.X < game.graphics.PreferredBackBufferWidth * .1f)
{
moveRight(-distance);
moving = true;
}
if (originalTouchLocation.Position.X > game.graphics.PreferredBackBufferWidth * .9f)
{
moveRight(distance);
moving = true;
}
if (originalTouchLocation.Position.Y < game.graphics.PreferredBackBufferHeight * .1f)
{
moveForward(distance);
moving = true;
}
if (originalTouchLocation.Position.Y > game.graphics.PreferredBackBufferHeight * .9f)
{
moveForward(-distance);
moving = true;
}
if (!moving)
{
Vector2 offset;
TouchLocation oldLocation;
if (currentTouchLocation.TryGetPreviousLocation(out oldLocation))
{
offset = currentTouchLocation.Position - oldLocation.Position;
yaw += offset.X * .05f * dt;
pitch += offset.Y * .05f * dt;
}
}
}
myWorldMatrix = myWorldMatrix * Matrix.CreateTranslation(position);
myViewMatrix = Matrix.Invert(myWorldMatrix);
}
Func touchedMethod, touchUpdatedMethod, touchReleasedMethod;
///
/// Clears out any input handling events that the camera is using.
///
public void removeInputEvents()
{
originalTouchLocation = default(TouchLocation);
game.touchManager.touched -= touchedMethod;
game.touchManager.touchUpdated -= touchUpdatedMethod;
game.touchManager.released -= touchReleasedMethod;
}
///
/// Adds input handling events to the camera.
///
public void addInputEvents()
{
game.touchManager.touched += touchedMethod;
game.touchManager.touchUpdated += touchUpdatedMethod;
game.touchManager.released += touchReleasedMethod;
}
}
}