forked from bepu/bepuphysics1
-
Notifications
You must be signed in to change notification settings - Fork 0
/
IKConstraint.cs
102 lines (88 loc) · 4.06 KB
/
IKConstraint.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using System;
namespace BEPUik
{
public abstract class IKConstraint
{
protected float softness;
protected float errorCorrectionFactor;
/// <summary>
/// The rigidity of a constraint is used to derive the stiffness and damping coefficients using a fixed stiffness:damping ratio.
/// </summary>
/// <remarks>
/// This is used over independent coefficients because IK usages of the constraints don't really vary in behavior, just strength.
/// </remarks>
private const float StiffnessOverDamping = 0.25f;
private float rigidity = 16;
/// <summary>
/// Gets the rigidity of the constraint. Higher values correspond to more rigid constraints, lower values to less rigid constraints. Must be positive.
/// </summary>
/// <remarks>
/// Scaling up the rigidity is like preparing the constraint to handle a heavier load. If the load is proportionally heavier, the damping ratio stays the same.
/// If the load stays the same but the rigidity increases, the result is a more rigid joint, but with a slightly different damping ratio.
/// In other words, modifying rigidity without modifying the effective mass of the system results in a variable damping ratio.
/// This isn't a huge problem in practice- there is a massive ultra-damping hack in IK bone position integration that make a little physical deviation or underdamping irrelevant.
/// </remarks>
public float Rigidity
{
get
{
return rigidity;
}
set
{
if (value <= 0)
throw new ArgumentException("Rigidity must be positive.");
rigidity = value;
}
}
protected float maximumImpulse;
protected float maximumImpulseSquared;
protected float maximumForce = float.MaxValue;
/// <summary>
/// Gets or sets the maximum force that the constraint can apply.
/// </summary>
public float MaximumForce
{
get { return maximumForce; }
set
{
maximumForce = Math.Max(value, 0);
}
}
/// <summary>
/// Updates the softness, bias factor, and maximum impulse based on the current time step.
/// </summary>
/// <param name="dt">Time step duration.</param>
/// <param name="updateRate">Inverse time step duration.</param>
protected internal void Preupdate(float dt, float updateRate)
{
float stiffness = StiffnessOverDamping * rigidity;
float damping = rigidity;
float multiplier = 1 / (dt * stiffness + damping);
errorCorrectionFactor = stiffness * multiplier;
softness = updateRate * multiplier;
maximumImpulse = maximumForce * dt;
maximumImpulseSquared = Math.Min(float.MaxValue, maximumImpulse * maximumImpulse);
}
/// <summary>
/// Update the jacobians for the latest position and orientation bone states and store a velocity bias based on the error.
/// </summary>
protected internal abstract void UpdateJacobiansAndVelocityBias();
/// <summary>
/// Computes the effective mass matrix for the constraint for the current jacobians.
/// </summary>
protected internal abstract void ComputeEffectiveMass();
/// <summary>
/// Applies the accumulated impulse to warm up the constraint solving process.
/// </summary>
protected internal abstract void WarmStart();
/// <summary>
/// Applies impulses to satisfy the velocity constraint.
/// </summary>
protected internal abstract void SolveVelocityIteration();
/// <summary>
/// Clears out the accumulated impulse.
/// </summary>
protected internal abstract void ClearAccumulatedImpulses();
}
}