cosmetix
[k8-jellyphysics.git] / src / jelly / SpringBody.cpp
blob36901cde0502afdc1a09edc2f1cb048ce374910b
1 #include "SpringBody.h"
3 #include "World.h"
4 #include "VectorTools.h"
7 namespace JellyPhysics {
9 SpringBody::SpringBody (
10 World *w, const ClosedShape &shape, float massPerPoint,
11 float edgeSpringK, float edgeSpringDamp,
12 const Vector2 &pos, float angleinRadians,
13 const Vector2 &scale, bool kinematic
14 ) : Body(w, shape, massPerPoint, pos, angleinRadians, scale, kinematic) {
15 mShapeMatchingOn = false;
16 setPositionAngle(pos, angleinRadians, scale);
17 mEdgeSpringK = edgeSpringK;
18 mEdgeSpringDamp = edgeSpringDamp;
19 mShapeSpringK = 0.0f;
20 mShapeSpringDamp = 0.0f;
21 // build default springs
22 _buildDefaultSprings();
26 SpringBody::SpringBody (
27 World *w, const ClosedShape &shape, float massPerPoint,
28 float shapeSpringK, float shapeSpringDamp,
29 float edgeSpringK, float edgeSpringDamp,
30 const Vector2 &pos, float angleinRadians,
31 const Vector2 &scale, bool kinematic
32 ) : Body(w, shape, massPerPoint, pos, angleinRadians, scale, kinematic) {
33 setPositionAngle(pos, angleinRadians, scale);
34 mShapeMatchingOn = true;
35 mShapeSpringK = shapeSpringK;
36 mShapeSpringDamp = shapeSpringDamp;
37 mEdgeSpringK = edgeSpringK;
38 mEdgeSpringDamp = edgeSpringDamp;
39 // build default springs
40 _buildDefaultSprings();
44 void SpringBody::addInternalSpring (int pointA, int pointB, float springK, float damping) {
45 float dist = (mPointMasses[pointB].Position-mPointMasses[pointA].Position).length();
46 InternalSpring s(pointA, pointB, dist, springK, damping);
47 mSprings.push_back(s);
51 void SpringBody::clearAllSprings () {
52 mSprings.clear();
53 _buildDefaultSprings();
57 void SpringBody::_buildDefaultSprings () {
58 int c = mPointCount, n;
59 for (int i = 0; i < c; ++i) {
60 if ((n = i+1) >= c) n = 0;
61 addInternalSpring(i, n, mEdgeSpringK, mEdgeSpringDamp);
66 void SpringBody::setEdgeSpringConstants (float edgeSpringK, float edgeSpringDamp) {
67 mEdgeSpringK = edgeSpringK;
68 mEdgeSpringDamp = edgeSpringDamp;
69 // we know that the first n springs in the list are the edge springs
70 int c = mPointCount;
71 for (int i = 0; i < c; ++i) {
72 mSprings[i].springK = edgeSpringK;
73 mSprings[i].damping = edgeSpringDamp;
78 void SpringBody::setSpringConstants (int springID, float springK, float springDamp) {
79 // index is for all internal springs, AFTER the default internal springs
80 int index = mPointCount+springID;
81 mSprings[index].springK = springK;
82 mSprings[index].damping = springDamp;
86 float SpringBody::getSpringK (int springID) const {
87 int index = mPointCount+springID;
88 return mSprings[index].springK;
92 float SpringBody::getSpringDamping (int springID) const {
93 int index = mPointCount+springID;
94 return mSprings[index].damping;
98 void SpringBody::accumulateInternalForces () {
99 // internal spring forces
100 Vector2 force;
101 int i = 0;
102 for (SpringList::const_iterator it = mSprings.begin(); it != mSprings.end(); ++it, ++i) {
103 const InternalSpring &s = *it;
104 PointMass& pmA = mPointMasses[s.pointMassA];
105 PointMass& pmB = mPointMasses[s.pointMassB];
106 if (i < mPointCount) {
107 // spring forces for the edges of the shape can used the cached edge information to reduce calculations
108 force = VectorTools::calculateSpringForce(-mEdgeInfo[i].dir, mEdgeInfo[i].length, pmA.Velocity, pmB.Velocity, s.springD, s.springK, s.damping);
109 } else {
110 // these are other internal springs, they must be fully calculated each frame
111 force = VectorTools::calculateSpringForce(pmA.Position, pmA.Velocity, pmB.Position, pmB.Velocity, s.springD, s.springK, s.damping);
113 pmA.Force += force;
114 pmB.Force -= force;
116 // shape matching forces
117 if (mShapeMatchingOn) {
118 mBaseShape.transformVertices(mDerivedPos, mDerivedAngle, mScale, mGlobalShape);
119 for (int i = 0; i < mPointCount; ++i) {
120 PointMass& pmA = mPointMasses[i];
121 if (mShapeSpringK > 0) {
122 if (!mKinematic) {
123 force = VectorTools::calculateSpringForce(pmA.Position, pmA.Velocity, mGlobalShape[i], pmA.Velocity, 0.0f, mShapeSpringK, mShapeSpringDamp);
124 } else {
125 force = VectorTools::calculateSpringForce(pmA.Position, pmA.Velocity, mGlobalShape[i], Vector2::Zero, 0.0f, mShapeSpringK, mShapeSpringDamp);
127 pmA.Force += force;