[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / third-party / bullet3 / src / BulletSoftBody / btDeformableBackwardEulerObjective.cpp
1 /*
2  Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
3  
4  Bullet Continuous Collision Detection and Physics Library
5  Copyright (c) 2019 Google Inc. http://bulletphysics.org
6  This software is provided 'as-is', without any express or implied warranty.
7  In no event will the authors be held liable for any damages arising from the use of this software.
8  Permission is granted to anyone to use this software for any purpose,
9  including commercial applications, and to alter it and redistribute it freely,
10  subject to the following restrictions:
11  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13  3. This notice may not be removed or altered from any source distribution.
14  */
15
16 #include "btDeformableBackwardEulerObjective.h"
17 #include "btPreconditioner.h"
18 #include "LinearMath/btQuickprof.h"
19
20 btDeformableBackwardEulerObjective::btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody*>& softBodies, const TVStack& backup_v)
21         : m_softBodies(softBodies), m_projection(softBodies), m_backupVelocity(backup_v), m_implicit(false)
22 {
23         m_massPreconditioner = new MassPreconditioner(m_softBodies);
24         m_KKTPreconditioner = new KKTPreconditioner(m_softBodies, m_projection, m_lf, m_dt, m_implicit);
25         m_preconditioner = m_KKTPreconditioner;
26 }
27
28 btDeformableBackwardEulerObjective::~btDeformableBackwardEulerObjective()
29 {
30         delete m_KKTPreconditioner;
31         delete m_massPreconditioner;
32 }
33
34 void btDeformableBackwardEulerObjective::reinitialize(bool nodeUpdated, btScalar dt)
35 {
36         BT_PROFILE("reinitialize");
37         if (dt > 0)
38         {
39                 setDt(dt);
40         }
41         if (nodeUpdated)
42         {
43                 updateId();
44         }
45         for (int i = 0; i < m_lf.size(); ++i)
46         {
47                 m_lf[i]->reinitialize(nodeUpdated);
48         }
49         btMatrix3x3 I;
50         I.setIdentity();
51         for (int i = 0; i < m_softBodies.size(); ++i)
52         {
53                 btSoftBody* psb = m_softBodies[i];
54                 for (int j = 0; j < psb->m_nodes.size(); ++j)
55                 {
56                         if (psb->m_nodes[j].m_im > 0)
57                                 psb->m_nodes[j].m_effectiveMass = I * (1.0 / psb->m_nodes[j].m_im);
58                 }
59         }
60         m_projection.reinitialize(nodeUpdated);
61         //    m_preconditioner->reinitialize(nodeUpdated);
62 }
63
64 void btDeformableBackwardEulerObjective::setDt(btScalar dt)
65 {
66         m_dt = dt;
67 }
68
69 void btDeformableBackwardEulerObjective::multiply(const TVStack& x, TVStack& b) const
70 {
71         BT_PROFILE("multiply");
72         // add in the mass term
73         size_t counter = 0;
74         for (int i = 0; i < m_softBodies.size(); ++i)
75         {
76                 btSoftBody* psb = m_softBodies[i];
77                 for (int j = 0; j < psb->m_nodes.size(); ++j)
78                 {
79                         const btSoftBody::Node& node = psb->m_nodes[j];
80                         b[counter] = (node.m_im == 0) ? btVector3(0, 0, 0) : x[counter] / node.m_im;
81                         ++counter;
82                 }
83         }
84
85         for (int i = 0; i < m_lf.size(); ++i)
86         {
87                 // add damping matrix
88                 m_lf[i]->addScaledDampingForceDifferential(-m_dt, x, b);
89         // Always integrate picking force implicitly for stability.
90         if (m_implicit || m_lf[i]->getForceType() == BT_MOUSE_PICKING_FORCE)
91                 {
92                         m_lf[i]->addScaledElasticForceDifferential(-m_dt * m_dt, x, b);
93                 }
94         }
95         int offset = m_nodes.size();
96         for (int i = offset; i < b.size(); ++i)
97         {
98                 b[i].setZero();
99         }
100         // add in the lagrange multiplier terms
101
102         for (int c = 0; c < m_projection.m_lagrangeMultipliers.size(); ++c)
103         {
104                 // C^T * lambda
105                 const LagrangeMultiplier& lm = m_projection.m_lagrangeMultipliers[c];
106                 for (int i = 0; i < lm.m_num_nodes; ++i)
107                 {
108                         for (int j = 0; j < lm.m_num_constraints; ++j)
109                         {
110                                 b[lm.m_indices[i]] += x[offset + c][j] * lm.m_weights[i] * lm.m_dirs[j];
111                         }
112                 }
113                 // C * x
114                 for (int d = 0; d < lm.m_num_constraints; ++d)
115                 {
116                         for (int i = 0; i < lm.m_num_nodes; ++i)
117                         {
118                                 b[offset + c][d] += lm.m_weights[i] * x[lm.m_indices[i]].dot(lm.m_dirs[d]);
119                         }
120                 }
121         }
122 }
123
124 void btDeformableBackwardEulerObjective::updateVelocity(const TVStack& dv)
125 {
126         for (int i = 0; i < m_softBodies.size(); ++i)
127         {
128                 btSoftBody* psb = m_softBodies[i];
129                 for (int j = 0; j < psb->m_nodes.size(); ++j)
130                 {
131                         btSoftBody::Node& node = psb->m_nodes[j];
132                         node.m_v = m_backupVelocity[node.index] + dv[node.index];
133                 }
134         }
135 }
136
137 void btDeformableBackwardEulerObjective::applyForce(TVStack& force, bool setZero)
138 {
139         size_t counter = 0;
140         for (int i = 0; i < m_softBodies.size(); ++i)
141         {
142                 btSoftBody* psb = m_softBodies[i];
143                 if (!psb->isActive())
144                 {
145                         counter += psb->m_nodes.size();
146                         continue;
147                 }
148                 if (m_implicit)
149                 {
150                         for (int j = 0; j < psb->m_nodes.size(); ++j)
151                         {
152                                 if (psb->m_nodes[j].m_im != 0)
153                                 {
154                                         psb->m_nodes[j].m_v += psb->m_nodes[j].m_effectiveMass_inv * force[counter++];
155                                 }
156                         }
157                 }
158                 else
159                 {
160                         for (int j = 0; j < psb->m_nodes.size(); ++j)
161                         {
162                                 btScalar one_over_mass = (psb->m_nodes[j].m_im == 0) ? 0 : psb->m_nodes[j].m_im;
163                                 psb->m_nodes[j].m_v += one_over_mass * force[counter++];
164                         }
165                 }
166         }
167         if (setZero)
168         {
169                 for (int i = 0; i < force.size(); ++i)
170                         force[i].setZero();
171         }
172 }
173
174 void btDeformableBackwardEulerObjective::computeResidual(btScalar dt, TVStack& residual)
175 {
176         BT_PROFILE("computeResidual");
177         // add implicit force
178         for (int i = 0; i < m_lf.size(); ++i)
179         {
180         // Always integrate picking force implicitly for stability.
181                 if (m_implicit || m_lf[i]->getForceType() == BT_MOUSE_PICKING_FORCE)
182                 {
183                         m_lf[i]->addScaledForces(dt, residual);
184                 }
185                 else
186                 {
187                         m_lf[i]->addScaledDampingForce(dt, residual);
188                 }
189         }
190         //    m_projection.project(residual);
191 }
192
193 btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual) const
194 {
195         btScalar mag = 0;
196         for (int i = 0; i < residual.size(); ++i)
197         {
198                 mag += residual[i].length2();
199         }
200         return std::sqrt(mag);
201 }
202
203 btScalar btDeformableBackwardEulerObjective::totalEnergy(btScalar dt)
204 {
205         btScalar e = 0;
206         for (int i = 0; i < m_lf.size(); ++i)
207         {
208                 e += m_lf[i]->totalEnergy(dt);
209         }
210         return e;
211 }
212
213 void btDeformableBackwardEulerObjective::applyExplicitForce(TVStack& force)
214 {
215         for (int i = 0; i < m_softBodies.size(); ++i)
216         {
217                 m_softBodies[i]->advanceDeformation();
218         }
219         if (m_implicit)
220         {
221                 // apply forces except gravity force
222                 btVector3 gravity;
223                 for (int i = 0; i < m_lf.size(); ++i)
224                 {
225                         if (m_lf[i]->getForceType() == BT_GRAVITY_FORCE)
226                         {
227                                 gravity = static_cast<btDeformableGravityForce*>(m_lf[i])->m_gravity;
228                         }
229                         else
230                         {
231                                 m_lf[i]->addScaledForces(m_dt, force);
232                         }
233                 }
234                 for (int i = 0; i < m_lf.size(); ++i)
235                 {
236                         m_lf[i]->addScaledHessian(m_dt);
237                 }
238                 for (int i = 0; i < m_softBodies.size(); ++i)
239                 {
240                         btSoftBody* psb = m_softBodies[i];
241                         if (psb->isActive())
242                         {
243                                 for (int j = 0; j < psb->m_nodes.size(); ++j)
244                                 {
245                                         // add gravity explicitly
246                                         psb->m_nodes[j].m_v += m_dt * psb->m_gravityFactor * gravity;
247                                 }
248                         }
249                 }
250         }
251         else
252         {
253                 for (int i = 0; i < m_lf.size(); ++i)
254                 {
255                         m_lf[i]->addScaledExplicitForce(m_dt, force);
256                 }
257         }
258         // calculate inverse mass matrix for all nodes
259         for (int i = 0; i < m_softBodies.size(); ++i)
260         {
261                 btSoftBody* psb = m_softBodies[i];
262                 if (psb->isActive())
263                 {
264                         for (int j = 0; j < psb->m_nodes.size(); ++j)
265                         {
266                                 if (psb->m_nodes[j].m_im > 0)
267                                 {
268                                         psb->m_nodes[j].m_effectiveMass_inv = psb->m_nodes[j].m_effectiveMass.inverse();
269                                 }
270                         }
271                 }
272         }
273         applyForce(force, true);
274 }
275
276 void btDeformableBackwardEulerObjective::initialGuess(TVStack& dv, const TVStack& residual)
277 {
278         size_t counter = 0;
279         for (int i = 0; i < m_softBodies.size(); ++i)
280         {
281                 btSoftBody* psb = m_softBodies[i];
282                 for (int j = 0; j < psb->m_nodes.size(); ++j)
283                 {
284                         dv[counter] = psb->m_nodes[j].m_im * residual[counter];
285                         ++counter;
286                 }
287         }
288 }
289
290 //set constraints as projections
291 void btDeformableBackwardEulerObjective::setConstraints(const btContactSolverInfo& infoGlobal)
292 {
293         m_projection.setConstraints(infoGlobal);
294 }
295
296 void btDeformableBackwardEulerObjective::applyDynamicFriction(TVStack& r)
297 {
298         m_projection.applyDynamicFriction(r);
299 }