2 * Copyright (c) 2007 Walaber
3 * Modified by Ketmar // Invisible Vector
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 #include "SpringBody.h"
26 #include "VectorTools.h"
29 namespace JellyPhysics
{
31 SpringBody::SpringBody (
32 World
*w
, const ClosedShape
&shape
, float massPerPoint
,
33 float edgeSpringK
, float edgeSpringDamp
,
34 const Vector2
&pos
, float angleinRadians
,
35 const Vector2
&scale
, bool kinematic
36 ) : Body(w
, shape
, massPerPoint
, pos
, angleinRadians
, scale
, kinematic
) {
37 mShapeMatchingOn
= false;
38 setPositionAngle(pos
, angleinRadians
, scale
);
39 mEdgeSpringK
= edgeSpringK
;
40 mEdgeSpringDamp
= edgeSpringDamp
;
42 mShapeSpringDamp
= 0.0f
;
43 // build default springs
44 _buildDefaultSprings();
48 SpringBody::SpringBody (
49 World
*w
, const ClosedShape
&shape
, float massPerPoint
,
50 float shapeSpringK
, float shapeSpringDamp
,
51 float edgeSpringK
, float edgeSpringDamp
,
52 const Vector2
&pos
, float angleinRadians
,
53 const Vector2
&scale
, bool kinematic
54 ) : Body(w
, shape
, massPerPoint
, pos
, angleinRadians
, scale
, kinematic
) {
55 setPositionAngle(pos
, angleinRadians
, scale
);
56 mShapeMatchingOn
= true;
57 mShapeSpringK
= shapeSpringK
;
58 mShapeSpringDamp
= shapeSpringDamp
;
59 mEdgeSpringK
= edgeSpringK
;
60 mEdgeSpringDamp
= edgeSpringDamp
;
61 // build default springs
62 _buildDefaultSprings();
66 SpringBody::~SpringBody () {
70 void SpringBody::addInternalSpring (int pointA
, int pointB
, float springK
, float damping
) {
71 float dist
= (mPointMasses
[pointB
].Position
-mPointMasses
[pointA
].Position
).length();
72 InternalSpring
s(pointA
, pointB
, dist
, springK
, damping
);
73 mSprings
.push_back(s
);
77 void SpringBody::clearAllSprings () {
79 _buildDefaultSprings();
83 void SpringBody::_buildDefaultSprings () {
84 int c
= mPointCount
, n
;
85 for (int i
= 0; i
< c
; ++i
) {
86 if ((n
= i
+1) >= c
) n
= 0;
87 addInternalSpring(i
, n
, mEdgeSpringK
, mEdgeSpringDamp
);
92 void SpringBody::setEdgeSpringConstants (float edgeSpringK
, float edgeSpringDamp
) {
93 mEdgeSpringK
= edgeSpringK
;
94 mEdgeSpringDamp
= edgeSpringDamp
;
95 // we know that the first n springs in the list are the edge springs
97 for (int i
= 0; i
< c
; ++i
) {
98 mSprings
[i
].springK
= edgeSpringK
;
99 mSprings
[i
].damping
= edgeSpringDamp
;
104 void SpringBody::setSpringConstants (int springID
, float springK
, float springDamp
) {
105 // index is for all internal springs, AFTER the default internal springs
106 int index
= mPointCount
+springID
;
107 mSprings
[index
].springK
= springK
;
108 mSprings
[index
].damping
= springDamp
;
112 float SpringBody::getSpringK (int springID
) const {
113 int index
= mPointCount
+springID
;
114 return mSprings
[index
].springK
;
118 float SpringBody::getSpringDamping (int springID
) const {
119 int index
= mPointCount
+springID
;
120 return mSprings
[index
].damping
;
124 void SpringBody::accumulateInternalForces () {
125 // internal spring forces
128 for (SpringList::const_iterator it
= mSprings
.begin(); it
!= mSprings
.end(); ++it
, ++i
) {
129 const InternalSpring
&s
= *it
;
130 PointMass
& pmA
= mPointMasses
[s
.pointMassA
];
131 PointMass
& pmB
= mPointMasses
[s
.pointMassB
];
132 if (i
< mPointCount
) {
133 // spring forces for the edges of the shape can used the cached edge information to reduce calculations
134 force
= calculateSpringForce(-mEdgeInfo
[i
].dir
, mEdgeInfo
[i
].length
, pmA
.Velocity
, pmB
.Velocity
, s
.springD
, s
.springK
, s
.damping
);
136 // these are other internal springs, they must be fully calculated each frame
137 force
= calculateSpringForce(pmA
.Position
, pmA
.Velocity
, pmB
.Position
, pmB
.Velocity
, s
.springD
, s
.springK
, s
.damping
);
142 // shape matching forces
143 if (mShapeMatchingOn
) {
144 mBaseShape
.transformVertices(mDerivedPos
, mDerivedAngle
, mScale
, mGlobalShape
);
145 for (int i
= 0; i
< mPointCount
; ++i
) {
146 PointMass
& pmA
= mPointMasses
[i
];
147 if (mShapeSpringK
> 0) {
149 force
= calculateSpringForce(pmA
.Position
, pmA
.Velocity
, mGlobalShape
[i
], pmA
.Velocity
, 0.0f
, mShapeSpringK
, mShapeSpringDamp
);
151 force
= calculateSpringForce(pmA
.Position
, pmA
.Velocity
, mGlobalShape
[i
], Vector2::Zero
, 0.0f
, mShapeSpringK
, mShapeSpringDamp
);