curve klasse done
This commit is contained in:
parent
6899ffb4cc
commit
49b56d3862
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user