[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / third-party / chipmunk2d / src / cpDampedRotarySpring.c
1 /* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
2  * 
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:
9  * 
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  * 
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
19  * SOFTWARE.
20  */
21
22 #include "chipmunk/chipmunk_private.h"
23
24 static cpFloat
25 defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){
26         return (relativeAngle - spring->restAngle)*spring->stiffness;
27 }
28
29 static void
30 preStep(cpDampedRotarySpring *spring, cpFloat dt)
31 {
32         cpBody *a = spring->constraint.a;
33         cpBody *b = spring->constraint.b;
34         
35         cpFloat moment = a->i_inv + b->i_inv;
36         cpAssertSoft(moment != 0.0, "Unsolvable spring.");
37         spring->iSum = 1.0f/moment;
38
39         spring->w_coef = 1.0f - cpfexp(-spring->damping*dt*moment);
40         spring->target_wrn = 0.0f;
41
42         // apply spring torque
43         cpFloat j_spring = spring->springTorqueFunc((cpConstraint *)spring, a->a - b->a)*dt;
44         spring->jAcc = j_spring;
45         
46         a->w -= j_spring*a->i_inv;
47         b->w += j_spring*b->i_inv;
48 }
49
50 static void applyCachedImpulse(cpDampedRotarySpring *spring, cpFloat dt_coef){}
51
52 static void
53 applyImpulse(cpDampedRotarySpring *spring, cpFloat dt)
54 {
55         cpBody *a = spring->constraint.a;
56         cpBody *b = spring->constraint.b;
57         
58         // compute relative velocity
59         cpFloat wrn = a->w - b->w;//normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;
60         
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;
65         
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;
69         
70         a->w += j_damp*a->i_inv;
71         b->w -= j_damp*b->i_inv;
72 }
73
74 static cpFloat
75 getImpulse(cpDampedRotarySpring *spring)
76 {
77         return spring->jAcc;
78 }
79
80 static const cpConstraintClass klass = {
81         (cpConstraintPreStepImpl)preStep,
82         (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
83         (cpConstraintApplyImpulseImpl)applyImpulse,
84         (cpConstraintGetImpulseImpl)getImpulse,
85 };
86
87 cpDampedRotarySpring *
88 cpDampedRotarySpringAlloc(void)
89 {
90         return (cpDampedRotarySpring *)cpcalloc(1, sizeof(cpDampedRotarySpring));
91 }
92
93 cpDampedRotarySpring *
94 cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
95 {
96         cpConstraintInit((cpConstraint *)spring, &klass, a, b);
97         
98         spring->restAngle = restAngle;
99         spring->stiffness = stiffness;
100         spring->damping = damping;
101         spring->springTorqueFunc = (cpDampedRotarySpringTorqueFunc)defaultSpringTorque;
102         
103         spring->jAcc = 0.0f;
104         
105         return spring;
106 }
107
108 cpConstraint *
109 cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
110 {
111         return (cpConstraint *)cpDampedRotarySpringInit(cpDampedRotarySpringAlloc(), a, b, restAngle, stiffness, damping);
112 }
113
114 cpBool
115 cpConstraintIsDampedRotarySpring(const cpConstraint *constraint)
116 {
117         return (constraint->klass == &klass);
118 }
119
120 cpFloat
121 cpDampedRotarySpringGetRestAngle(const cpConstraint *constraint)
122 {
123         cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
124         return ((cpDampedRotarySpring *)constraint)->restAngle;
125 }
126
127 void
128 cpDampedRotarySpringSetRestAngle(cpConstraint *constraint, cpFloat restAngle)
129 {
130         cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
131         cpConstraintActivateBodies(constraint);
132         ((cpDampedRotarySpring *)constraint)->restAngle = restAngle;
133 }
134
135 cpFloat
136 cpDampedRotarySpringGetStiffness(const cpConstraint *constraint)
137 {
138         cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
139         return ((cpDampedRotarySpring *)constraint)->stiffness;
140 }
141
142 void
143 cpDampedRotarySpringSetStiffness(cpConstraint *constraint, cpFloat stiffness)
144 {
145         cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
146         cpConstraintActivateBodies(constraint);
147         ((cpDampedRotarySpring *)constraint)->stiffness = stiffness;
148 }
149
150 cpFloat
151 cpDampedRotarySpringGetDamping(const cpConstraint *constraint)
152 {
153         cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
154         return ((cpDampedRotarySpring *)constraint)->damping;
155 }
156
157 void
158 cpDampedRotarySpringSetDamping(cpConstraint *constraint, cpFloat damping)
159 {
160         cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
161         cpConstraintActivateBodies(constraint);
162         ((cpDampedRotarySpring *)constraint)->damping = damping;
163 }
164
165 cpDampedRotarySpringTorqueFunc
166 cpDampedRotarySpringGetSpringTorqueFunc(const cpConstraint *constraint)
167 {
168         cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
169         return ((cpDampedRotarySpring *)constraint)->springTorqueFunc;
170 }
171
172 void
173 cpDampedRotarySpringSetSpringTorqueFunc(cpConstraint *constraint, cpDampedRotarySpringTorqueFunc springTorqueFunc)
174 {
175         cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
176         cpConstraintActivateBodies(constraint);
177         ((cpDampedRotarySpring *)constraint)->springTorqueFunc = springTorqueFunc;
178 }