📄 constraint.cs
字号:
using System;
using Microsoft.DirectX;
namespace ParticleSystems
{
namespace Verlet
{
namespace Constraints
{
/// <summary>
/// An abstract help class for constraints dealing with two
/// particles
/// </summary>
public abstract class TwoParticleHolder
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="particle1">A particle</param>
/// <param name="particle2">A particle</param>
public TwoParticleHolder(Particle particle1, Particle particle2)
{
mParticle1 = particle1;
mParticle2 = particle2;
}
/// <summary>
/// Particle 1 of the constraint
/// </summary>
public Particle Particle1
{
get
{
return mParticle1;
}
}
/// <summary>
/// Particle 2 of the constraint
/// </summary>
public Particle Particle2
{
get
{
return mParticle2;
}
}
/// <summary>
/// Particle 1 holder
/// </summary>
protected Particle mParticle1;
/// <summary>
/// Particle 2 holder
/// </summary>
protected Particle mParticle2;
}
/// <summary>
/// Stick implements IConstraint. Stick is a two particle constraint
/// which emulate a stiff stick connecting two particles.
/// </summary>
public class Stick : TwoParticleHolder, IConstraint
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="particle1">A particle</param>
/// <param name="particle2">A particle</param>
public Stick(Particle particle1, Particle particle2)
: base(particle1, particle2)
{
mLength = (particle1.Position - particle2.Position).Length();
}
/// <summary>
/// Applies the constraint
/// </summary>
public void Apply()
{
float lParticle1InvertedMass = mParticle1.InvertedMass;
float lParticle2InvertedMass = mParticle2.InvertedMass;
Vector3 lDelta = mParticle2.mCurrentPosition - mParticle1.mCurrentPosition;
float lDeltaLength = lDelta.Length();
float lDiff = (lDeltaLength - mLength) / (lDeltaLength*(lParticle1InvertedMass + lParticle2InvertedMass));
mParticle1.mCurrentPosition.Add(lParticle1InvertedMass * lDiff *lDelta);
mParticle2.mCurrentPosition.Subtract(lParticle2InvertedMass * lDiff *lDelta);
}
/// <summary>
/// Length of stick
/// </summary>
public float Length
{
get
{
return mLength;
}
}
private float mLength;
}
/// <summary>
/// Rope implements IConstraint. Rope is a two particle constraint
/// which intends to emulate a rope connecting two particles. A
/// rope may be shorter than the specified length but not longer
/// </summary>
public class Rope : TwoParticleHolder, IConstraint
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="scale">The length of the rope constraint is multiplied by this parameter</param>
/// <param name="particle1">A particle</param>
/// <param name="particle2">A particle</param>
public Rope(float scale, Particle particle1, Particle particle2)
: base(particle1, particle2)
{
if( scale < 1.0f )
{
throw new Exception("scale parameter must be 1.0 or larger");
}
mLength = scale * (particle1.Position - particle2.Position).Length();
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="particle1">A particle</param>
/// <param name="particle2">A particle</param>
public Rope(Particle particle1, Particle particle2)
: base(particle1, particle2)
{
mLength = (particle1.Position - particle2.Position).Length();
}
/// <summary>
/// Applies the constraint
/// </summary>
public void Apply()
{
float lParticle1InvertedMass = mParticle1.InvertedMass;
float lParticle2InvertedMass = mParticle2.InvertedMass;
Vector3 lDelta =
mParticle2.mCurrentPosition - mParticle1.mCurrentPosition;
float lDeltaLength = lDelta.Length();
if( lDeltaLength > mLength )
{
float lDiff = (lDeltaLength - mLength) /
(lDeltaLength *
(lParticle1InvertedMass + lParticle2InvertedMass));
mParticle1.mCurrentPosition.Add(
lParticle1InvertedMass * lDiff *lDelta);
mParticle2.mCurrentPosition.Subtract(
lParticle2InvertedMass * lDiff *lDelta);
}
}
/// <summary>
/// Length of rope
/// </summary>
public float Length
{
get
{
return mLength;
}
}
private float mLength;
}
/// <summary>
/// Rope implements IConstraint and IEffect. SoftStick is sort of
/// a failed experiment.
/// The intention was a stick that when shortened,
/// instead of immedietly trying to return to its original length
/// grew back over ot its original length over time. It's still in
/// the code as it gives an example of how to implement a contraint
/// that is changed every update (as it's also an IEffect).
/// </summary>
public class SoftStick : TwoParticleHolder, IConstraint, IEffect
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="stiffness">The stiffness of the constraint</param>
/// <param name="particle1">A particle</param>
/// <param name="particle2">A particle</param>
public SoftStick(
float stiffness,
Particle particle1,
Particle particle2)
: base(particle1, particle2)
{
mStiffness = stiffness;
mLength = (particle1.Position - particle2.Position).Length();
mDesiredLength = mLength;
}
/// <summary>
/// Applies the effect
/// </summary>
/// <param name="timeDelta">The timedelta used by the particle system this iteration</param>
public void Apply(float timeDelta)
{
float lCurrentDistance = (mParticle2.mCurrentPosition -
mParticle1.mCurrentPosition).Length();
float lTimeDeltaCorrectedStiffness = mStiffness * timeDelta;
mDesiredLength =
mLength * lTimeDeltaCorrectedStiffness +
lCurrentDistance * ( 1 - lTimeDeltaCorrectedStiffness );
}
/// <summary>
/// Applies the constraint
/// </summary>
public void Apply()
{
float lParticle1InvertedMass = mParticle1.InvertedMass;
float lParticle2InvertedMass = mParticle2.InvertedMass;
Vector3 lDelta = mParticle2.mCurrentPosition - mParticle1.mCurrentPosition;
float lDeltaLength = lDelta.Length();
float lDiff = (lDeltaLength - mDesiredLength) / (lDeltaLength*(lParticle1InvertedMass + lParticle2InvertedMass));
mParticle1.mCurrentPosition.Add(lParticle1InvertedMass * lDiff *lDelta);
mParticle2.mCurrentPosition.Subtract(lParticle2InvertedMass * lDiff *lDelta);
}
/// <summary>
/// Length of soft stick
/// </summary>
public float Length
{
get
{
return mLength;
}
}
private float mStiffness;
private float mLength;
private float mDesiredLength;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -