curve klasse done

This commit is contained in:
SND\floAr_cp 2011-11-19 01:15:38 +00:00
parent 6899ffb4cc
commit 49b56d3862

View File

@ -51,41 +51,26 @@ namespace ANX.Framework
{
public class Curve
{
public Curve Clone()
{
throw new NotImplementedException();
}
private CurveKeyCollection keys;
private CurveLoopType preLoop;
private CurveLoopType postLoop;
public void ComputeTangent(Int32 value, CurveTangent tangent)
{
throw new NotImplementedException();
}
public void ComputeTangent(Int32 value, CurveTangent tangent1, CurveTangent tangent2)
{
throw new NotImplementedException();
}
public void ComputeTangents(CurveTangent tangent)
{
throw new NotImplementedException();
}
public void ComputeTangents(CurveTangent tangent1, CurveTangent tangent2)
{
throw new NotImplementedException();
}
public Single Evaluate(Single value)
{
throw new NotImplementedException();
}
public CurveLoopType PreLoop
{ get; set; }
{
get { return preLoop; }
set { preLoop = value; }
}
public CurveLoopType PostLoop
{ get; set; }
{
get { return postLoop; }
set { postLoop = value; }
}
public CurveKeyCollection Keys
{
get
{
throw new NotImplementedException();
return keys;
}
}
@ -93,8 +78,219 @@ namespace ANX.Framework
{
get
{
throw new NotImplementedException();
return this.keys.Count <= 1;
}
}
public Curve Clone()
{
Curve result = new Curve();
result.keys = this.keys.Clone();
result.preLoop = this.preLoop;
result.postLoop = this.postLoop;
return result;
}
public Curve()
{
this.keys = new CurveKeyCollection();
}
#region tangent calculation
//formulas from: http://msdn.microsoft.com/de-de/library/microsoft.xna.framework.curvetangent%28v=xnagamestudio.40%29.aspx
public void ComputeTangent(Int32 index, CurveTangent tangentInOutType)
{
if (index < 0 || index > keys.Count)
{
throw new ArgumentOutOfRangeException();
}
CurveKey prev = index > 0 ? this.keys[index - 1] : this.keys[index];
CurveKey current = this.keys[index];
current.TangentIn = 0;
CurveKey next = index < this.keys.Count - 1 ? this.keys[index + 1] : this.keys[index];
switch (tangentInOutType)
{
case CurveTangent.Flat:
current.TangentIn = 0;
current.TangentOut = 0;
break;
case CurveTangent.Linear:
current.TangentIn = current.Value - prev.Value;
current.TangentOut = next.Value - current.Value;
break;
case CurveTangent.Smooth:
current.TangentIn = ((next.Value - prev.Value) * ((current.Position - prev.Position) / (next.Position - prev.Position)));
current.TangentOut = ((next.Value - prev.Value) * ((next.Position - current.Position) / (next.Position - prev.Position)));
break;
}
}
public void ComputeTangent(Int32 index, CurveTangent tangentInType, CurveTangent tangentOutType)
{
if (index < 0 || index > keys.Count)
{
throw new ArgumentOutOfRangeException();
}
CurveKey prev = index > 0 ? this.keys[index - 1] : this.keys[index];
CurveKey current=this.keys[index];
current.TangentIn = 0;
CurveKey next=index <this.keys.Count-1? this.keys[index + 1] : this.keys[index];
switch (tangentInType)
{
case CurveTangent.Flat:
current.TangentIn = 0;
break;
case CurveTangent.Linear:
current.TangentIn = current.Value - prev.Value;
break;
case CurveTangent.Smooth:
current.TangentIn=((next.Value-prev.Value)*((current.Position-prev.Position)/(next.Position-prev.Position)));
break;
}
switch (tangentOutType)
{
case CurveTangent.Flat:
current.TangentOut = 0;
break;
case CurveTangent.Linear:
current.TangentOut = next.Value - current.Value;
break;
case CurveTangent.Smooth:
current.TangentOut=((next.Value-prev.Value)*((next.Position-current.Position)/(next.Position-prev.Position)));
break;
}
}
public void ComputeTangents(CurveTangent tangentInOutType)
{
for (int i = 0; i < this.keys.Count; ++i)
{
this.ComputeTangent(i, tangentInOutType);
}
}
public void ComputeTangents(CurveTangent tangentInType, CurveTangent tangentOutType)
{
for (int i = 0; i < this.keys.Count; ++i)
{
this.ComputeTangent(i, tangentInType,tangentOutType);
}
}
#endregion
public Single Evaluate(Single position)
{
//Get first and last Point
CurveKey first = keys[0];
CurveKey last = keys[keys.Count - 1];
float timeSpan=this.keys[this.keys.Count-1].Position-this.keys[0].Position;
//wanted point before first point
if (position < first.Position)
{
// Description from : http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.curvelooptype.aspx
switch (this.PreLoop)
{
case CurveLoopType.Constant:
//The Curve will evaluate to its first key for positions before the first point in the Curve and to the last key for positions after the last point.
return first.Value;
case CurveLoopType.Linear:
// Linear interpolation will be performed to determine the value.
return first.Value - first.TangentIn * (first.Position - position);
case CurveLoopType.Cycle:
// Positions specified past the ends of the curve will wrap around to the opposite side of the Curve.
return this.interpolate(position%timeSpan);
case CurveLoopType.CycleOffset:
//Positions specified past the ends of the curve will wrap around to the opposite side of the Curve.
//The value will be offset by the difference between the values of the first and last CurveKey
//multiplied by the number of times the position wraps around. If the position is before the first
//point in the Curve, the difference will be subtracted from its value; otherwise, the difference
//will be added.
float difference = (this.keys[this.keys.Count - 1].Value - this.keys[0].Value) * (position / timeSpan);
return this.interpolate(position % timeSpan)-difference;
case CurveLoopType.Oscillate:
//Positions specified past the ends of the Curve act as an offset from the same side of the Curve
//toward the opposite side.
return this.interpolate(timeSpan-(position % timeSpan));
}
}
//wanted point behind last point
else if (position > last.Position)
{
int cycle;
switch (this.PostLoop)
{
case CurveLoopType.Constant:
//The Curve will evaluate to its first key for positions before the first point in the Curve and to
//the last key for positions after the last point.
return last.Value;
case CurveLoopType.Linear:
//Linear interpolation will be performed to determine the value.
return last.Value + last.TangentOut * (position - last.Position);
case CurveLoopType.Cycle:
// Positions specified past the ends of the curve will wrap around to the opposite side of the Curve.
return this.interpolate(position%timeSpan);
case CurveLoopType.CycleOffset:
//Positions specified past the ends of the curve will wrap around to the opposite side of the Curve.
//The value will be offset by the difference between the values of the first and last CurveKey
//multiplied by the number of times the position wraps around. If the position is before the first
//point in the Curve, the difference will be subtracted from its value; otherwise, the difference
//will be added.
float difference = (this.keys[this.keys.Count - 1].Value - this.keys[0].Value) * (position / timeSpan);
return this.interpolate(position % timeSpan)+difference;
case CurveLoopType.Oscillate:
//Positions specified past the ends of the Curve act as an offset from the same side of the Curve
//toward the opposite side.
return this.interpolate(timeSpan - (position % timeSpan));
}
}
//in curve
return interpolate(position);
}
private float interpolate(float position)
{
//interpolate inside the curve with cubic hermite:
http://forums.create.msdn.com/forums/p/53392/323814.aspx
//assume position is inside curve
CurveKey a = this.keys[0];
CurveKey b;
for (int i = 1; i < this.keys.Count; i++)
{
b = this.Keys[i];
if (b.Position >= position)
{
//stepping
if (a.Continuity == CurveContinuity.Step)
{
return a.Value;
}
//smooth
//get the location between a and b in [0,1]
float moment = (position - a.Position) / (b.Position - a.Position);
return MathHelper.Hermite(a.Value, a.TangentOut, b.Value, b.TangentOut, moment);
}
//get next pair
a = b;
}
return 0f;
}
}
}