-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpin_joint.go
91 lines (70 loc) · 1.93 KB
/
pin_joint.go
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
package cm
import (
"math"
"github.com/setanarut/vec"
)
type PinJoint struct {
*Constraint
AnchorA, AnchorB vec.Vec2
Dist float64
r1, r2, n vec.Vec2
nMass, jnAcc, bias float64
}
func NewPinJoint(a, b *Body, anchorA, anchorB vec.Vec2) *Constraint {
joint := &PinJoint{
AnchorA: anchorA,
AnchorB: anchorB,
}
// static body check
var p1, p2 vec.Vec2
if a != nil {
p1 = a.transform.Apply(anchorA)
} else {
p1 = anchorA
}
if b != nil {
p2 = b.transform.Apply(anchorB)
} else {
p2 = anchorB
}
joint.Dist = p2.Sub(p1).Mag()
// TODO: warn about joint.dist > 0 being unstable, use pivot joint
joint.jnAcc = 0
joint.Constraint = NewConstraint(joint, a, b)
return joint.Constraint
}
func (joint *PinJoint) PreStep(dt float64) {
a := joint.bodyA
b := joint.bodyB
joint.r1 = a.transform.ApplyVector(joint.AnchorA.Sub(a.centerOfGravity))
joint.r2 = b.transform.ApplyVector(joint.AnchorB.Sub(b.centerOfGravity))
delta := b.position.Add(joint.r2.Sub(a.position.Add(joint.r1)))
dist := delta.Mag()
if dist != 0 {
joint.n = delta.Scale(1 / dist)
} else {
joint.n = delta.Scale(1 / infinity)
}
joint.nMass = 1 / kScalar(a, b, joint.r1, joint.r2, joint.n)
maxBias := joint.maxBias
joint.bias = clamp(-biasCoef(joint.errorBias, dt)*(dist-joint.Dist)/dt, -maxBias, maxBias)
}
func (joint *PinJoint) ApplyCachedImpulse(dtCoef float64) {
j := joint.n.Scale(joint.jnAcc * dtCoef)
applyImpulses(joint.bodyA, joint.bodyB, joint.r1, joint.r2, j)
}
func (joint *PinJoint) ApplyImpulse(dt float64) {
a := joint.bodyA
b := joint.bodyB
n := joint.n
vrn := normalRelativeVelocity(a, b, joint.r1, joint.r2, n)
jnMax := joint.maxForce * dt
jn := (joint.bias - vrn) * joint.nMass
jnOld := joint.jnAcc
joint.jnAcc = clamp(jnOld+jn, -jnMax, jnMax)
jn = joint.jnAcc - jnOld
applyImpulses(a, b, joint.r1, joint.r2, n.Scale(jn))
}
func (joint *PinJoint) GetImpulse() float64 {
return math.Abs(joint.jnAcc)
}