using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Utility
{
public class CompactTexture
{
#region Variables
protected Texture2D tex;
protected Vector2 ori;
protected Vector2 sca;
protected Vector2 dim;
protected Vector2 factor;
protected Vector2 offset;
#endregion
#region Accessors
public Texture2D Texture
{
get{ return tex; }
set{ tex = value; Resolve(); }
}
public Vector2 Origin
{
get{ return ori; }
set{ ori = value;}
}
public Vector2 Scale
{
get { return sca; }
set { sca = value; }
}
///
/// The target pixel dimensions.
///
public Vector2 Factor
{
get { return ori; }
set { ori = value; Resolve(); }
}
///
/// Relative origin offset from center.
///
public Vector2 Offset
{
get { return sca; }
set { sca = value; Resolve(); }
}
public int Width
{
get{ return tex.Width; }
}
public int Height
{
get { return tex.Height; }
}
#endregion
#region System
public CompactTexture( Texture2D tex )
: this( tex, new Vector2( tex.Width, tex.Height), Vector2.Zero )
{
}
public CompactTexture( Texture2D tex, float factor )
: this( tex, new Vector2(factor, factor), Vector2.Zero )
{
}
public CompactTexture(Texture2D tex, float factor, Vector2 offset)
: this(tex, new Vector2(factor, factor), offset)
{
}
public CompactTexture(Texture2D tex, Vector2 factor)
: this(tex, factor, Vector2.Zero)
{
}
public CompactTexture( Texture2D tex, Vector2 factor, Vector2 offset)
{
this.tex = tex;
this.factor = factor;
this.offset = offset;
Resolve();
}
#endregion
#region Methods
protected void Resolve()
{
dim = new Vector2( tex.Width, tex.Height );
sca = factor / dim;
ori = dim * .5f * ( Vector2.One + offset * sca * 2f );
}
#endregion
}
public class Timer
{
#region Variables
float seed;
float val;
bool ready;
#endregion
#region Accessors
public bool Ready
{
get { return ready; }
}
public float Seed
{
get { return seed; }
set { seed = value; }
}
public float Value
{
get { return val; }
set { val = value; }
}
#endregion
#region System
public Timer( float seed )
{
this.seed = seed;
val = seed;
}
public bool Update( GameTime gameTime )
{
val = Math.Max(-1f, val - (float)gameTime.ElapsedGameTime.TotalSeconds);
ready = ( val < 0f );
return ready;
}
#endregion
#region Methods
public float Reset()
{
val = seed;
return val;
}
#endregion
}
class LinearSmoother
{
#region Variables
Vector2 actual;
Vector2 target;
Vector2 tester;
float spring;
float thresh;
#endregion
#region Accessors
public Vector2 Vector
{
get { return actual; }
}
public Vector2 Target
{
set { tester = value; }
}
#endregion
#region System
public LinearSmoother( Vector2 vec, float spring, float thresh )
{
this.actual = vec;
this.target = vec;
this.tester = vec;
this.spring = spring;
this.thresh = thresh;
}
void Update( GameTime gameTime )
{
}
#endregion
}
class QuaternalSmoother
{
#region Variables
Quaternion quat;
Vector2 actual;
Vector2 target;
Vector2 tester;
float length;
float angle;
float thresh;
float spring;
#endregion
#region Accessors
public Vector2 Vector
{
get { return actual; }
}
public Vector2 Target
{
set
{ tester = value; }
}
public float Angle
{
get { return angle; }
}
public float Length
{
get { return length; }
}
#endregion
#region System
public QuaternalSmoother(Vector2 vec, float spring, float threshold)
{
this.actual = vec;
this.target = vec;
this.tester = vec;
this.spring = spring;
this.thresh = threshold;
this.length = vec.Length();
actual.Normalize();
angle = (float)Math.Acos(Vector2.Dot(Vector2.UnitY, actual ) );
if (target.Y < 0.0f) angle = -angle;
Vector3 axis = Vector3.UnitZ;
Quaternion.CreateFromAxisAngle( ref axis, angle, out quat );
}
public void Update(GameTime gameTime)
{
length = tester.Length();
if (length > thresh)
{
target = tester;
}
target.Normalize();
float temp = (float)Math.Acos(Vector2.Dot(Vector2.UnitX, target ) );
if ( target.Y > 0f ) temp = -temp;
Quaternion test;
Vector3 axis = Vector3.UnitZ;
Quaternion.CreateFromAxisAngle( ref axis, temp, out test );
quat = Quaternion.Lerp( quat, test, spring );
Vector3 vec = QuaternionToEuler( quat );
angle = vec.Z;
actual.X = (float)Math.Cos( angle );
actual.Y = (float)Math.Sin( angle );
actual.Normalize();
}
#endregion
#region Methods
private Vector3 QuaternionToEuler(Quaternion rotation)
{
float q0 = rotation.W;
float q1 = rotation.Y;
float q2 = rotation.X;
float q3 = rotation.Z;
//In Radians
Vector3 angles = new Vector3();
angles.X = (float)Math.Atan2(2 * (q0 * q1 + q2 * q3), 1 - 2 * (Math.Pow(q1, 2) + Math.Pow(q2, 2)));
angles.Y = (float)Math.Asin(2 * (q0 * q2 - q3 * q1));
angles.Z = (float)Math.Atan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (Math.Pow(q2, 2) + Math.Pow(q3, 2)));
return angles;
}
#endregion
}
class RotationalSmoother
{
#region Variables
Vector2 actual;
Vector2 target;
Vector2 tester;
float length;
float angle;
float spring;
float thresh;
#endregion
#region Accessors
public Vector2 Vector
{
get{ return actual; }
}
public Vector2 Target
{
set
{ tester = value; }
}
public float Angle
{
get{ return angle; }
}
public float Length
{
get{ return length; }
}
#endregion
#region System
public RotationalSmoother( Vector2 vec, float spring, float threshold )
{
this.actual = vec;
this.target = vec;
this.tester = vec;
this.spring = spring;
this.thresh = threshold;
this.length = vec.Length();
}
public void Update( GameTime gameTime )
{
length = tester.Length();
if ( length > thresh )
{
target = tester;
}
actual += spring * (target - actual);
actual.Normalize();
angle = (float)Math.Acos(-actual.Y);
if (actual.X < 0.0f) angle = -angle;
}
#endregion
}
}