1 /* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 #include "chipmunk/chipmunk_private.h"
25 defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){
26 return (relativeAngle - spring->restAngle)*spring->stiffness;
30 preStep(cpDampedRotarySpring *spring, cpFloat dt)
32 cpBody *a = spring->constraint.a;
33 cpBody *b = spring->constraint.b;
35 cpFloat moment = a->i_inv + b->i_inv;
36 cpAssertSoft(moment != 0.0, "Unsolvable spring.");
37 spring->iSum = 1.0f/moment;
39 spring->w_coef = 1.0f - cpfexp(-spring->damping*dt*moment);
40 spring->target_wrn = 0.0f;
42 // apply spring torque
43 cpFloat j_spring = spring->springTorqueFunc((cpConstraint *)spring, a->a - b->a)*dt;
44 spring->jAcc = j_spring;
46 a->w -= j_spring*a->i_inv;
47 b->w += j_spring*b->i_inv;
50 static void applyCachedImpulse(cpDampedRotarySpring *spring, cpFloat dt_coef){}
53 applyImpulse(cpDampedRotarySpring *spring, cpFloat dt)
55 cpBody *a = spring->constraint.a;
56 cpBody *b = spring->constraint.b;
58 // compute relative velocity
59 cpFloat wrn = a->w - b->w;//normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;
61 // compute velocity loss from drag
62 // not 100% certain this is derived correctly, though it makes sense
63 cpFloat w_damp = (spring->target_wrn - wrn)*spring->w_coef;
64 spring->target_wrn = wrn + w_damp;
66 //apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass));
67 cpFloat j_damp = w_damp*spring->iSum;
68 spring->jAcc += j_damp;
70 a->w += j_damp*a->i_inv;
71 b->w -= j_damp*b->i_inv;
75 getImpulse(cpDampedRotarySpring *spring)
80 static const cpConstraintClass klass = {
81 (cpConstraintPreStepImpl)preStep,
82 (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
83 (cpConstraintApplyImpulseImpl)applyImpulse,
84 (cpConstraintGetImpulseImpl)getImpulse,
87 cpDampedRotarySpring *
88 cpDampedRotarySpringAlloc(void)
90 return (cpDampedRotarySpring *)cpcalloc(1, sizeof(cpDampedRotarySpring));
93 cpDampedRotarySpring *
94 cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
96 cpConstraintInit((cpConstraint *)spring, &klass, a, b);
98 spring->restAngle = restAngle;
99 spring->stiffness = stiffness;
100 spring->damping = damping;
101 spring->springTorqueFunc = (cpDampedRotarySpringTorqueFunc)defaultSpringTorque;
109 cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
111 return (cpConstraint *)cpDampedRotarySpringInit(cpDampedRotarySpringAlloc(), a, b, restAngle, stiffness, damping);
115 cpConstraintIsDampedRotarySpring(const cpConstraint *constraint)
117 return (constraint->klass == &klass);
121 cpDampedRotarySpringGetRestAngle(const cpConstraint *constraint)
123 cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
124 return ((cpDampedRotarySpring *)constraint)->restAngle;
128 cpDampedRotarySpringSetRestAngle(cpConstraint *constraint, cpFloat restAngle)
130 cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
131 cpConstraintActivateBodies(constraint);
132 ((cpDampedRotarySpring *)constraint)->restAngle = restAngle;
136 cpDampedRotarySpringGetStiffness(const cpConstraint *constraint)
138 cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
139 return ((cpDampedRotarySpring *)constraint)->stiffness;
143 cpDampedRotarySpringSetStiffness(cpConstraint *constraint, cpFloat stiffness)
145 cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
146 cpConstraintActivateBodies(constraint);
147 ((cpDampedRotarySpring *)constraint)->stiffness = stiffness;
151 cpDampedRotarySpringGetDamping(const cpConstraint *constraint)
153 cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
154 return ((cpDampedRotarySpring *)constraint)->damping;
158 cpDampedRotarySpringSetDamping(cpConstraint *constraint, cpFloat damping)
160 cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
161 cpConstraintActivateBodies(constraint);
162 ((cpDampedRotarySpring *)constraint)->damping = damping;
165 cpDampedRotarySpringTorqueFunc
166 cpDampedRotarySpringGetSpringTorqueFunc(const cpConstraint *constraint)
168 cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
169 return ((cpDampedRotarySpring *)constraint)->springTorqueFunc;
173 cpDampedRotarySpringSetSpringTorqueFunc(cpConstraint *constraint, cpDampedRotarySpringTorqueFunc springTorqueFunc)
175 cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
176 cpConstraintActivateBodies(constraint);
177 ((cpDampedRotarySpring *)constraint)->springTorqueFunc = springTorqueFunc;