-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCollidable.hh
84 lines (76 loc) · 3.34 KB
/
Collidable.hh
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
#ifndef COLLIDABLE_HH
#define COLLIDABLE_HH
#include "Object.hh"
#include <exception>
#include <algorithm>
template<class F>
class Collidable:
virtual public Object<F>
{
public:
Collidable(F springConstant, F dampeningConstant, F coefficientOfFriction, F rollingResistance)
: mSpringConstant(springConstant),
mDampeningConstant(dampeningConstant),
mCoefficientOfFriction(coefficientOfFriction),
mRollingResistance(rollingResistance)
{
}
protected:
void
InteractPhysically(Object<F>* other, F timeslice)
{
Collidable<F>* otherCollidable = dynamic_cast<Collidable<F>*>(other);
if (otherCollidable != NULL) {
ZenMatrix<F, 3, 1> location;
ZenMatrix<F, 3, 1> normal;
F overlap;
bool collides;
try {
collides = Collides(otherCollidable, location, normal, overlap);
} catch(...) {
collides = otherCollidable->Collides(this, location, normal, overlap);
normal = -normal;
}
if (collides) {
F springConstant = (mSpringConstant + otherCollidable->mSpringConstant) / 2;
F dampeningConstant = (mDampeningConstant + otherCollidable->mDampeningConstant) / 2;
F coefficientOfFriction = sqrt(mCoefficientOfFriction * otherCollidable->mCoefficientOfFriction);
// F rollingResistance = sqrt(mRollingResistance * otherCollidable->mRollingResistance);
ZenMatrix<F, 3, 1> normalVel = normal * Dot(normal, Object<F>::mVelocity);
ZenMatrix<F, 3, 1> otherNormalVel = normal * Dot(normal, other->mVelocity);
ZenMatrix<F, 3, 1> relNormalVel = otherNormalVel - normalVel;
ZenMatrix<F, 3, 1> rotationalVel = Cross(Object<F>::mAngularVelocity, normal * Object<F>::mRadius);
ZenMatrix<F, 3, 1> otherRotationalVel = Cross(other->mAngularVelocity, normal * -other->mRadius);
ZenMatrix<F, 3, 1> tangentVel = Object<F>::mVelocity - normalVel + rotationalVel;
ZenMatrix<F, 3, 1> otherTangentVel = other->mVelocity - otherNormalVel + otherRotationalVel;
ZenMatrix<F, 3, 1> relTangentVel = otherTangentVel - tangentVel;
F springStrength = overlap * springConstant;
F frictionStrength = coefficientOfFriction * springStrength;
F relStoppingStrength = Length(relTangentVel) / timeslice / 2;
ZenMatrix<F, 3, 1> tangentForce = Normalize(relTangentVel) * min(frictionStrength, relStoppingStrength);
ZenMatrix<F, 3, 1> force = normal * -springStrength + relNormalVel * dampeningConstant + tangentForce;
ApplyForce(force, timeslice);
other->ApplyForce(-force, timeslice);
// F rollingStrength = rollingResistance * springStrength / Object<F>::mRadius;
// F otherRollingStrength = rollingResistance * springStrength / other->mRadius;
// F stoppingStrength = Length(tangentVel) / timeslice;
// F otherStoppingStrength = Length(otherTangentVel) / timeslice;
// ZenMatrix<F, 3, 1> rollingForce = Normalize(tangentVel) * -min(rollingStrength, stoppingStrength);
// ZenMatrix<F, 3, 1> otherRollingForce = Normalize(otherTangentVel) * -min(otherRollingStrength, otherStoppingStrength);
ApplyTorque(Cross(location - Object<F>::mLocation, tangentForce), timeslice);
other->ApplyTorque(Cross(location - other->mLocation, -tangentForce), timeslice);
}
}
}
virtual bool
Collides(Collidable<F>* other, ZenMatrix<F, 3, 1>& location, ZenMatrix<F, 3, 1>& normal, F& overlap)
{
throw std::exception();
}
private:
F mSpringConstant;
F mDampeningConstant;
F mCoefficientOfFriction;
F mRollingResistance;
};
#endif // COLLIDABLE_HH