Blender  V2.93
implicit_eigen.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) Blender Foundation
17  * All rights reserved.
18  */
19 
24 #include "implicit.h"
25 
26 #ifdef IMPLICIT_SOLVER_EIGEN
27 
28 //#define USE_EIGEN_CORE
29 # define USE_EIGEN_CONSTRAINED_CG
30 
31 # ifdef __GNUC__
32 # pragma GCC diagnostic push
33 /* XXX suppress verbose warnings in eigen */
34 //# pragma GCC diagnostic ignored "-Wlogical-op"
35 # endif
36 
37 # ifndef IMPLICIT_ENABLE_EIGEN_DEBUG
38 # ifdef NDEBUG
39 # define IMPLICIT_NDEBUG
40 # endif
41 # define NDEBUG
42 # endif
43 
44 # include <Eigen/Sparse>
45 # include <Eigen/src/Core/util/DisableStupidWarnings.h>
46 
47 # ifdef USE_EIGEN_CONSTRAINED_CG
49 # endif
50 
51 # ifndef IMPLICIT_ENABLE_EIGEN_DEBUG
52 # ifndef IMPLICIT_NDEBUG
53 # undef NDEBUG
54 # else
55 # undef IMPLICIT_NDEBUG
56 # endif
57 # endif
58 
59 # ifdef __GNUC__
60 # pragma GCC diagnostic pop
61 # endif
62 
63 # include "MEM_guardedalloc.h"
64 
65 extern "C" {
66 # include "DNA_meshdata_types.h"
67 # include "DNA_object_force_types.h"
68 # include "DNA_object_types.h"
69 # include "DNA_scene_types.h"
70 # include "DNA_texture_types.h"
71 
72 # include "BLI_linklist.h"
73 # include "BLI_math.h"
74 # include "BLI_utildefines.h"
75 
76 # include "BKE_cloth.h"
77 # include "BKE_collision.h"
78 # include "BKE_effect.h"
79 # include "BKE_global.h"
80 
81 # include "SIM_mass_spring.h"
82 }
83 
84 typedef float Scalar;
85 
86 static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
87 
88 /* slightly extended Eigen vector class
89  * with conversion to/from plain C float array
90  */
91 class fVector : public Eigen::Vector3f {
92  public:
93  typedef float *ctype;
94 
95  fVector()
96  {
97  }
98 
99  fVector(const ctype &v)
100  {
101  for (int k = 0; k < 3; k++) {
102  coeffRef(k) = v[k];
103  }
104  }
105 
106  fVector &operator=(const ctype &v)
107  {
108  for (int k = 0; k < 3; k++) {
109  coeffRef(k) = v[k];
110  }
111  return *this;
112  }
113 
114  operator ctype()
115  {
116  return data();
117  }
118 };
119 
120 /* slightly extended Eigen matrix class
121  * with conversion to/from plain C float array
122  */
123 class fMatrix : public Eigen::Matrix3f {
124  public:
125  typedef float (*ctype)[3];
126 
127  fMatrix()
128  {
129  }
130 
131  fMatrix(const ctype &v)
132  {
133  for (int k = 0; k < 3; k++) {
134  for (int l = 0; l < 3; l++) {
135  coeffRef(l, k) = v[k][l];
136  }
137  }
138  }
139 
140  fMatrix &operator=(const ctype &v)
141  {
142  for (int k = 0; k < 3; k++) {
143  for (int l = 0; l < 3; l++) {
144  coeffRef(l, k) = v[k][l];
145  }
146  }
147  return *this;
148  }
149 
150  operator ctype()
151  {
152  return (ctype)data();
153  }
154 };
155 
156 /* Extension of dense Eigen vectors,
157  * providing 3-float block access for blenlib math functions
158  */
159 class lVector : public Eigen::VectorXf {
160  public:
161  typedef Eigen::VectorXf base_t;
162 
163  lVector()
164  {
165  }
166 
167  template<typename T> lVector &operator=(T rhs)
168  {
169  base_t::operator=(rhs);
170  return *this;
171  }
172 
173  float *v3(int vertex)
174  {
175  return &coeffRef(3 * vertex);
176  }
177 
178  const float *v3(int vertex) const
179  {
180  return &coeffRef(3 * vertex);
181  }
182 };
183 
184 typedef Eigen::Triplet<Scalar> Triplet;
185 typedef std::vector<Triplet> TripletList;
186 
187 typedef Eigen::SparseMatrix<Scalar> lMatrix;
188 
189 /* Constructor type that provides more convenient handling of Eigen triplets
190  * for efficient construction of sparse 3x3 block matrices.
191  * This should be used for building lMatrix instead of writing to such lMatrix directly (which is
192  * very inefficient). After all elements have been defined using the set() method, the actual
193  * matrix can be filled using construct().
194  */
195 struct lMatrixCtor {
196  lMatrixCtor()
197  {
198  }
199 
200  void reset()
201  {
202  m_trips.clear();
203  }
204 
205  void reserve(int numverts)
206  {
207  /* reserve for diagonal entries */
208  m_trips.reserve(numverts * 9);
209  }
210 
211  void add(int i, int j, const fMatrix &m)
212  {
213  i *= 3;
214  j *= 3;
215  for (int k = 0; k < 3; k++) {
216  for (int l = 0; l < 3; l++) {
217  m_trips.push_back(Triplet(i + k, j + l, m.coeff(l, k)));
218  }
219  }
220  }
221 
222  void sub(int i, int j, const fMatrix &m)
223  {
224  i *= 3;
225  j *= 3;
226  for (int k = 0; k < 3; k++) {
227  for (int l = 0; l < 3; l++) {
228  m_trips.push_back(Triplet(i + k, j + l, -m.coeff(l, k)));
229  }
230  }
231  }
232 
233  inline void construct(lMatrix &m)
234  {
235  m.setFromTriplets(m_trips.begin(), m_trips.end());
236  m_trips.clear();
237  }
238 
239  private:
240  TripletList m_trips;
241 };
242 
243 # ifdef USE_EIGEN_CORE
244 typedef Eigen::ConjugateGradient<lMatrix, Eigen::Lower, Eigen::DiagonalPreconditioner<Scalar>>
246 # endif
247 # ifdef USE_EIGEN_CONSTRAINED_CG
249  Eigen::Lower,
250  lMatrix,
251  Eigen::DiagonalPreconditioner<Scalar>>
252  ConstraintConjGrad;
253 # endif
254 using Eigen::ComputationInfo;
255 
256 static void print_lvector(const lVector &v)
257 {
258  for (int i = 0; i < v.rows(); i++) {
259  if (i > 0 && i % 3 == 0) {
260  printf("\n");
261  }
262 
263  printf("%f,\n", v[i]);
264  }
265 }
266 
267 static void print_lmatrix(const lMatrix &m)
268 {
269  for (int j = 0; j < m.rows(); j++) {
270  if (j > 0 && j % 3 == 0) {
271  printf("\n");
272  }
273 
274  for (int i = 0; i < m.cols(); i++) {
275  if (i > 0 && i % 3 == 0) {
276  printf(" ");
277  }
278 
279  implicit_print_matrix_elem(m.coeff(j, i));
280  }
281  printf("\n");
282  }
283 }
284 
285 BLI_INLINE void lMatrix_reserve_elems(lMatrix &m, int num)
286 {
287  m.reserve(Eigen::VectorXi::Constant(m.cols(), num));
288 }
289 
290 BLI_INLINE float *lVector_v3(lVector &v, int vertex)
291 {
292  return v.data() + 3 * vertex;
293 }
294 
295 BLI_INLINE const float *lVector_v3(const lVector &v, int vertex)
296 {
297  return v.data() + 3 * vertex;
298 }
299 
300 # if 0
301 BLI_INLINE void triplets_m3(TripletList &tlist, float m[3][3], int i, int j)
302 {
303  i *= 3;
304  j *= 3;
305  for (int l = 0; l < 3; l++) {
306  for (int k = 0; k < 3; k++) {
307  tlist.push_back(Triplet(i + k, j + l, m[k][l]));
308  }
309  }
310 }
311 
312 BLI_INLINE void triplets_m3fl(TripletList &tlist, float m[3][3], int i, int j, float factor)
313 {
314  i *= 3;
315  j *= 3;
316  for (int l = 0; l < 3; l++) {
317  for (int k = 0; k < 3; k++) {
318  tlist.push_back(Triplet(i + k, j + l, m[k][l] * factor));
319  }
320  }
321 }
322 
323 BLI_INLINE void lMatrix_add_triplets(lMatrix &r, const TripletList &tlist)
324 {
325  lMatrix t(r.rows(), r.cols());
326  t.setFromTriplets(tlist.begin(), tlist.end());
327  r += t;
328 }
329 
330 BLI_INLINE void lMatrix_madd_triplets(lMatrix &r, const TripletList &tlist, float f)
331 {
332  lMatrix t(r.rows(), r.cols());
333  t.setFromTriplets(tlist.begin(), tlist.end());
334  r += f * t;
335 }
336 
337 BLI_INLINE void lMatrix_sub_triplets(lMatrix &r, const TripletList &tlist)
338 {
339  lMatrix t(r.rows(), r.cols());
340  t.setFromTriplets(tlist.begin(), tlist.end());
341  r -= t;
342 }
343 # endif
344 
345 BLI_INLINE void outerproduct(float r[3][3], const float a[3], const float b[3])
346 {
347  mul_v3_v3fl(r[0], a, b[0]);
348  mul_v3_v3fl(r[1], a, b[1]);
349  mul_v3_v3fl(r[2], a, b[2]);
350 }
351 
352 BLI_INLINE void cross_m3_v3m3(float r[3][3], const float v[3], float m[3][3])
353 {
354  cross_v3_v3v3(r[0], v, m[0]);
355  cross_v3_v3v3(r[1], v, m[1]);
356  cross_v3_v3v3(r[2], v, m[2]);
357 }
358 
359 BLI_INLINE void cross_v3_identity(float r[3][3], const float v[3])
360 {
361  r[0][0] = 0.0f;
362  r[1][0] = v[2];
363  r[2][0] = -v[1];
364  r[0][1] = -v[2];
365  r[1][1] = 0.0f;
366  r[2][1] = v[0];
367  r[0][2] = v[1];
368  r[1][2] = -v[0];
369  r[2][2] = 0.0f;
370 }
371 
372 BLI_INLINE void madd_m3_m3fl(float r[3][3], float m[3][3], float f)
373 {
374  r[0][0] += m[0][0] * f;
375  r[0][1] += m[0][1] * f;
376  r[0][2] += m[0][2] * f;
377  r[1][0] += m[1][0] * f;
378  r[1][1] += m[1][1] * f;
379  r[1][2] += m[1][2] * f;
380  r[2][0] += m[2][0] * f;
381  r[2][1] += m[2][1] * f;
382  r[2][2] += m[2][2] * f;
383 }
384 
385 BLI_INLINE void madd_m3_m3m3fl(float r[3][3], float a[3][3], float b[3][3], float f)
386 {
387  r[0][0] = a[0][0] + b[0][0] * f;
388  r[0][1] = a[0][1] + b[0][1] * f;
389  r[0][2] = a[0][2] + b[0][2] * f;
390  r[1][0] = a[1][0] + b[1][0] * f;
391  r[1][1] = a[1][1] + b[1][1] * f;
392  r[1][2] = a[1][2] + b[1][2] * f;
393  r[2][0] = a[2][0] + b[2][0] * f;
394  r[2][1] = a[2][1] + b[2][1] * f;
395  r[2][2] = a[2][2] + b[2][2] * f;
396 }
397 
398 struct Implicit_Data {
399  typedef std::vector<fMatrix> fMatrixVector;
400 
401  Implicit_Data(int numverts)
402  {
403  resize(numverts);
404  }
405 
406  void resize(int numverts)
407  {
408  this->numverts = numverts;
409  int tot = 3 * numverts;
410 
411  M.resize(tot, tot);
412  F.resize(tot);
413  dFdX.resize(tot, tot);
414  dFdV.resize(tot, tot);
415 
416  tfm.resize(numverts, I);
417 
418  X.resize(tot);
419  Xnew.resize(tot);
420  V.resize(tot);
421  Vnew.resize(tot);
422 
423  A.resize(tot, tot);
424  B.resize(tot);
425 
426  dV.resize(tot);
427  z.resize(tot);
428  S.resize(tot, tot);
429 
430  iM.reserve(numverts);
431  idFdX.reserve(numverts);
432  idFdV.reserve(numverts);
433  iS.reserve(numverts);
434  }
435 
436  int numverts;
437 
438  /* inputs */
439  lMatrix M; /* masses */
440  lVector F; /* forces */
441  lMatrix dFdX, dFdV; /* force jacobians */
442 
443  fMatrixVector tfm; /* local coordinate transform */
444 
445  /* motion state data */
446  lVector X, Xnew; /* positions */
447  lVector V, Vnew; /* velocities */
448 
449  /* internal solver data */
450  lVector B; /* B for A*dV = B */
451  lMatrix A; /* A for A*dV = B */
452 
453  lVector dV; /* velocity change (solution of A*dV = B) */
454  lVector z; /* target velocity in constrained directions */
455  lMatrix S; /* filtering matrix for constraints */
456 
457  /* temporary constructors */
458  lMatrixCtor iM; /* masses */
459  lMatrixCtor idFdX, idFdV; /* force jacobians */
460  lMatrixCtor iS; /* filtering matrix for constraints */
461 };
462 
463 Implicit_Data *SIM_mass_spring_solver_create(int numverts, int numsprings)
464 {
465  Implicit_Data *id = new Implicit_Data(numverts);
466  return id;
467 }
468 
470 {
471  if (id) {
472  delete id;
473  }
474 }
475 
477 {
478  if (id) {
479  return id->numverts;
480  }
481  else {
482  return 0;
483  }
484 }
485 
486 /* ==== Transformation from/to root reference frames ==== */
487 
488 BLI_INLINE void world_to_root_v3(Implicit_Data *data, int index, float r[3], const float v[3])
489 {
490  copy_v3_v3(r, v);
491  mul_transposed_m3_v3(data->tfm[index], r);
492 }
493 
494 BLI_INLINE void root_to_world_v3(Implicit_Data *data, int index, float r[3], const float v[3])
495 {
496  mul_v3_m3v3(r, data->tfm[index], v);
497 }
498 
499 BLI_INLINE void world_to_root_m3(Implicit_Data *data, int index, float r[3][3], float m[3][3])
500 {
501  float trot[3][3];
502  copy_m3_m3(trot, data->tfm[index]);
503  transpose_m3(trot);
504  mul_m3_m3m3(r, trot, m);
505 }
506 
507 BLI_INLINE void root_to_world_m3(Implicit_Data *data, int index, float r[3][3], float m[3][3])
508 {
509  mul_m3_m3m3(r, data->tfm[index], m);
510 }
511 
512 /* ================================ */
513 
515 {
516 # ifdef USE_EIGEN_CORE
517  typedef ConjugateGradient solver_t;
518 # endif
519 # ifdef USE_EIGEN_CONSTRAINED_CG
520  typedef ConstraintConjGrad solver_t;
521 # endif
522 
523  data->iM.construct(data->M);
524  data->idFdX.construct(data->dFdX);
525  data->idFdV.construct(data->dFdV);
526  data->iS.construct(data->S);
527 
528  solver_t cg;
529  cg.setMaxIterations(100);
530  cg.setTolerance(0.01f);
531 
532 # ifdef USE_EIGEN_CONSTRAINED_CG
533  cg.filter() = data->S;
534 # endif
535 
536  data->A = data->M - dt * data->dFdV - dt * dt * data->dFdX;
537  cg.compute(data->A);
538 
539  data->B = dt * data->F + dt * dt * data->dFdX * data->V;
540 
541 # ifdef IMPLICIT_PRINT_SOLVER_INPUT_OUTPUT
542  printf("==== A ====\n");
543  print_lmatrix(id->A);
544  printf("==== z ====\n");
545  print_lvector(id->z);
546  printf("==== B ====\n");
547  print_lvector(id->B);
548  printf("==== S ====\n");
549  print_lmatrix(id->S);
550 # endif
551 
552 # ifdef USE_EIGEN_CORE
553  data->dV = cg.solve(data->B);
554 # endif
555 # ifdef USE_EIGEN_CONSTRAINED_CG
556  data->dV = cg.solveWithGuess(data->B, data->z);
557 # endif
558 
559 # ifdef IMPLICIT_PRINT_SOLVER_INPUT_OUTPUT
560  printf("==== dV ====\n");
561  print_lvector(id->dV);
562  printf("========\n");
563 # endif
564 
565  data->Vnew = data->V + data->dV;
566 
567  switch (cg.info()) {
568  case Eigen::Success:
569  result->status = SIM_SOLVER_SUCCESS;
570  break;
571  case Eigen::NoConvergence:
573  break;
574  case Eigen::InvalidInput:
576  break;
577  case Eigen::NumericalIssue:
579  break;
580  }
581 
582  result->iterations = cg.iterations();
583  result->error = cg.error();
584 
585  return cg.info() == Eigen::Success;
586 }
587 
589 {
590  data->Xnew = data->X + data->Vnew * dt;
591  return true;
592 }
593 
594 /* ================================ */
595 
597 {
598  data->X = data->Xnew;
599  data->V = data->Vnew;
600 }
601 
602 void SIM_mass_spring_set_vertex_mass(Implicit_Data *data, int index, float mass)
603 {
604  float m[3][3];
605  copy_m3_m3(m, I);
606  mul_m3_fl(m, mass);
607  data->iM.add(index, index, m);
608 }
609 
610 void SIM_mass_spring_set_rest_transform(Implicit_Data *data, int index, float tfm[3][3])
611 {
612 # ifdef CLOTH_ROOT_FRAME
613  copy_m3_m3(data->tfm[index], tfm);
614 # else
615  unit_m3(data->tfm[index]);
616  (void)tfm;
617 # endif
618 }
619 
621  int index,
622  const float x[3],
623  const float v[3])
624 {
625  world_to_root_v3(data, index, data->X.v3(index), x);
626  world_to_root_v3(data, index, data->V.v3(index), v);
627 }
628 
629 void SIM_mass_spring_set_position(Implicit_Data *data, int index, const float x[3])
630 {
631  world_to_root_v3(data, index, data->X.v3(index), x);
632 }
633 
634 void SIM_mass_spring_set_velocity(Implicit_Data *data, int index, const float v[3])
635 {
636  world_to_root_v3(data, index, data->V.v3(index), v);
637 }
638 
640  int index,
641  float x[3],
642  float v[3])
643 {
644  if (x) {
645  root_to_world_v3(data, index, x, data->X.v3(index));
646  }
647  if (v) {
648  root_to_world_v3(data, index, v, data->V.v3(index));
649  }
650 }
651 
652 void SIM_mass_spring_get_position(struct Implicit_Data *data, int index, float x[3])
653 {
654  root_to_world_v3(data, index, x, data->X.v3(index));
655 }
656 
657 void SIM_mass_spring_get_new_velocity(Implicit_Data *data, int index, float v[3])
658 {
659  root_to_world_v3(data, index, v, data->V.v3(index));
660 }
661 
662 void SIM_mass_spring_set_new_velocity(Implicit_Data *data, int index, const float v[3])
663 {
664  world_to_root_v3(data, index, data->V.v3(index), v);
665 }
666 
668 {
669  int numverts = data->numverts;
670  for (int i = 0; i < numverts; i++) {
671  data->iS.add(i, i, I);
672  zero_v3(data->z.v3(i));
673  }
674 }
675 
676 void SIM_mass_spring_add_constraint_ndof0(Implicit_Data *data, int index, const float dV[3])
677 {
678  data->iS.sub(index, index, I);
679 
680  world_to_root_v3(data, index, data->z.v3(index), dV);
681 }
682 
684  Implicit_Data *data, int index, const float c1[3], const float c2[3], const float dV[3])
685 {
686  float m[3][3], p[3], q[3], u[3], cmat[3][3];
687 
688  world_to_root_v3(data, index, p, c1);
689  outerproduct(cmat, p, p);
690  copy_m3_m3(m, cmat);
691 
692  world_to_root_v3(data, index, q, c2);
693  outerproduct(cmat, q, q);
694  add_m3_m3m3(m, m, cmat);
695 
696  /* XXX not sure but multiplication should work here */
697  data->iS.sub(index, index, m);
698  // mul_m3_m3m3(data->S[index].m, data->S[index].m, m);
699 
700  world_to_root_v3(data, index, u, dV);
701  add_v3_v3(data->z.v3(index), u);
702 }
703 
705  int index,
706  const float c1[3],
707  const float dV[3])
708 {
709  float m[3][3], p[3], u[3], cmat[3][3];
710 
711  world_to_root_v3(data, index, p, c1);
712  outerproduct(cmat, p, p);
713  copy_m3_m3(m, cmat);
714 
715  data->iS.sub(index, index, m);
716  // mul_m3_m3m3(data->S[index].m, data->S[index].m, m);
717 
718  world_to_root_v3(data, index, u, dV);
719  add_v3_v3(data->z.v3(index), u);
720 }
721 
723 {
724  data->F.setZero();
725  data->dFdX.setZero();
726  data->dFdV.setZero();
727 }
728 
730  int index,
731  const float acceleration[3],
732  const float omega[3],
733  const float domega_dt[3],
734  float mass)
735 {
736 # ifdef CLOTH_ROOT_FRAME
737  float acc[3], w[3], dwdt[3];
738  float f[3], dfdx[3][3], dfdv[3][3];
739  float euler[3], coriolis[3], centrifugal[3], rotvel[3];
740  float deuler[3][3], dcoriolis[3][3], dcentrifugal[3][3], drotvel[3][3];
741 
742  world_to_root_v3(data, index, acc, acceleration);
743  world_to_root_v3(data, index, w, omega);
744  world_to_root_v3(data, index, dwdt, domega_dt);
745 
746  cross_v3_v3v3(euler, dwdt, data->X.v3(index));
747  cross_v3_v3v3(coriolis, w, data->V.v3(index));
748  mul_v3_fl(coriolis, 2.0f);
749  cross_v3_v3v3(rotvel, w, data->X.v3(index));
750  cross_v3_v3v3(centrifugal, w, rotvel);
751 
752  sub_v3_v3v3(f, acc, euler);
753  sub_v3_v3(f, coriolis);
754  sub_v3_v3(f, centrifugal);
755 
756  mul_v3_fl(f, mass); /* F = m * a */
757 
758  cross_v3_identity(deuler, dwdt);
759  cross_v3_identity(dcoriolis, w);
760  mul_m3_fl(dcoriolis, 2.0f);
761  cross_v3_identity(drotvel, w);
762  cross_m3_v3m3(dcentrifugal, w, drotvel);
763 
764  add_m3_m3m3(dfdx, deuler, dcentrifugal);
765  negate_m3(dfdx);
766  mul_m3_fl(dfdx, mass);
767 
768  copy_m3_m3(dfdv, dcoriolis);
769  negate_m3(dfdv);
770  mul_m3_fl(dfdv, mass);
771 
772  add_v3_v3(data->F.v3(index), f);
773  data->idFdX.add(index, index, dfdx);
774  data->idFdV.add(index, index, dfdv);
775 # else
776  (void)data;
777  (void)index;
778  (void)acceleration;
779  (void)omega;
780  (void)domega_dt;
781 # endif
782 }
783 
784 void SIM_mass_spring_force_gravity(Implicit_Data *data, int index, float mass, const float g[3])
785 {
786  /* force = mass * acceleration (in this case: gravity) */
787  float f[3];
788  world_to_root_v3(data, index, f, g);
789  mul_v3_fl(f, mass);
790 
791  add_v3_v3(data->F.v3(index), f);
792 }
793 
795 {
796  int numverts = data->numverts;
797  for (int i = 0; i < numverts; i++) {
798  float tmp[3][3];
799 
800  /* NB: uses root space velocity, no need to transform */
801  madd_v3_v3fl(data->F.v3(i), data->V.v3(i), -drag);
802 
803  copy_m3_m3(tmp, I);
804  mul_m3_fl(tmp, -drag);
805  data->idFdV.add(i, i, tmp);
806  }
807 }
808 
810  struct Implicit_Data *data, int i, const float f[3], float dfdx[3][3], float dfdv[3][3])
811 {
812  float tf[3], tdfdx[3][3], tdfdv[3][3];
813  world_to_root_v3(data, i, tf, f);
814  world_to_root_m3(data, i, tdfdx, dfdx);
815  world_to_root_m3(data, i, tdfdv, dfdv);
816 
817  add_v3_v3(data->F.v3(i), tf);
818  data->idFdX.add(i, i, tdfdx);
819  data->idFdV.add(i, i, tdfdv);
820 }
821 
822 static float calc_nor_area_tri(float nor[3],
823  const float v1[3],
824  const float v2[3],
825  const float v3[3])
826 {
827  float n1[3], n2[3];
828 
829  sub_v3_v3v3(n1, v1, v2);
830  sub_v3_v3v3(n2, v2, v3);
831 
832  cross_v3_v3v3(nor, n1, n2);
833  return normalize_v3(nor) / 2.0f;
834 }
835 
836 /* XXX does not support force jacobians yet,
837  * since the effector system does not provide them either. */
839  Implicit_Data *data, int v1, int v2, int v3, const float (*winvec)[3])
840 {
841  const float effector_scale = 0.02f;
842  float win[3], nor[3], area;
843  float factor;
844 
845  /* calculate face normal and area */
846  area = calc_nor_area_tri(nor, data->X.v3(v1), data->X.v3(v2), data->X.v3(v3));
847  factor = effector_scale * area / 3.0f;
848 
849  world_to_root_v3(data, v1, win, winvec[v1]);
850  madd_v3_v3fl(data->F.v3(v1), nor, factor * dot_v3v3(win, nor));
851 
852  world_to_root_v3(data, v2, win, winvec[v2]);
853  madd_v3_v3fl(data->F.v3(v2), nor, factor * dot_v3v3(win, nor));
854 
855  world_to_root_v3(data, v3, win, winvec[v3]);
856  madd_v3_v3fl(data->F.v3(v3), nor, factor * dot_v3v3(win, nor));
857 }
858 
859 void SIM_mass_spring_force_edge_wind(Implicit_Data *data, int v1, int v2, const float (*winvec)[3])
860 {
861  const float effector_scale = 0.01;
862  float win[3], dir[3], nor[3], length;
863 
864  sub_v3_v3v3(dir, data->X.v3(v1), data->X.v3(v2));
865  length = normalize_v3(dir);
866 
867  world_to_root_v3(data, v1, win, winvec[v1]);
868  madd_v3_v3v3fl(nor, win, dir, -dot_v3v3(win, dir));
869  madd_v3_v3fl(data->F.v3(v1), nor, effector_scale * length);
870 
871  world_to_root_v3(data, v2, win, winvec[v2]);
872  madd_v3_v3v3fl(nor, win, dir, -dot_v3v3(win, dir));
873  madd_v3_v3fl(data->F.v3(v2), nor, effector_scale * length);
874 }
875 
876 BLI_INLINE void dfdx_spring(float to[3][3], const float dir[3], float length, float L, float k)
877 {
878  /* dir is unit length direction, rest is spring's restlength, k is spring constant. */
879  // return ((I - outerprod(dir, dir)) * Min(1.0f, rest / length) - I) * -k;
880  outerproduct(to, dir, dir);
881  sub_m3_m3m3(to, I, to);
882 
883  mul_m3_fl(to, (L / length));
884  sub_m3_m3m3(to, to, I);
885  mul_m3_fl(to, k);
886 }
887 
888 /* unused */
889 # if 0
890 BLI_INLINE void dfdx_damp(float to[3][3],
891  const float dir[3],
892  float length,
893  const float vel[3],
894  float rest,
895  float damping)
896 {
897  /* inner spring damping vel is the relative velocity of the endpoints. */
898  // return (I-outerprod(dir, dir)) * (-damping * -(dot(dir, vel)/Max(length, rest)));
899  mul_fvectorT_fvector(to, dir, dir);
900  sub_fmatrix_fmatrix(to, I, to);
901  mul_fmatrix_S(to, (-damping * -(dot_v3v3(dir, vel) / MAX2(length, rest))));
902 }
903 # endif
904 
905 BLI_INLINE void dfdv_damp(float to[3][3], const float dir[3], float damping)
906 {
907  /* Derivative of force with regards to velocity. */
908  outerproduct(to, dir, dir);
909  mul_m3_fl(to, -damping);
910 }
911 
912 BLI_INLINE float fb(float length, float L)
913 {
914  float x = length / L;
915  return (-11.541f * powf(x, 4) + 34.193f * powf(x, 3) - 39.083f * powf(x, 2) + 23.116f * x -
916  9.713f);
917 }
918 
919 BLI_INLINE float fbderiv(float length, float L)
920 {
921  float x = length / L;
922 
923  return (-46.164f * powf(x, 3) + 102.579f * powf(x, 2) - 78.166f * x + 23.116f);
924 }
925 
926 BLI_INLINE float fbstar(float length, float L, float kb, float cb)
927 {
928  float tempfb_fl = kb * fb(length, L);
929  float fbstar_fl = cb * (length - L);
930 
931  if (tempfb_fl < fbstar_fl) {
932  return fbstar_fl;
933  }
934  else {
935  return tempfb_fl;
936  }
937 }
938 
939 /* Function to calculate bending spring force (taken from Choi & Co). */
940 BLI_INLINE float fbstar_jacobi(float length, float L, float kb, float cb)
941 {
942  float tempfb_fl = kb * fb(length, L);
943  float fbstar_fl = cb * (length - L);
944 
945  if (tempfb_fl < fbstar_fl) {
946  return -cb;
947  }
948  else {
949  return -kb * fbderiv(length, L);
950  }
951 }
952 
953 /* calculate elongation */
955  int i,
956  int j,
957  float r_extent[3],
958  float r_dir[3],
959  float *r_length,
960  float r_vel[3])
961 {
962  sub_v3_v3v3(r_extent, data->X.v3(j), data->X.v3(i));
963  sub_v3_v3v3(r_vel, data->V.v3(j), data->V.v3(i));
964  *r_length = len_v3(r_extent);
965 
966  if (*r_length > ALMOST_ZERO) {
967 # if 0
968  if (length > L) {
969  if ((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) &&
970  (((length - L) * 100.0f / L) > clmd->sim_parms->maxspringlen)) {
971  /* cut spring! */
972  s->flags |= CSPRING_FLAG_DEACTIVATE;
973  return false;
974  }
975  }
976 # endif
977  mul_v3_v3fl(r_dir, r_extent, 1.0f / (*r_length));
978  }
979  else {
980  zero_v3(r_dir);
981  }
982 
983  return true;
984 }
985 
987  Implicit_Data *data, int i, int j, const float f[3], float dfdx[3][3], float dfdv[3][3])
988 {
989  add_v3_v3(data->F.v3(i), f);
990  sub_v3_v3(data->F.v3(j), f);
991 
992  data->idFdX.add(i, i, dfdx);
993  data->idFdX.add(j, j, dfdx);
994  data->idFdX.sub(i, j, dfdx);
995  data->idFdX.sub(j, i, dfdx);
996 
997  data->idFdV.add(i, i, dfdv);
998  data->idFdV.add(j, j, dfdv);
999  data->idFdV.sub(i, j, dfdv);
1000  data->idFdV.sub(j, i, dfdv);
1001 }
1002 
1004  int i,
1005  int j,
1006  float restlen,
1007  float stiffness,
1008  float damping,
1009  bool no_compress,
1010  float clamp_force,
1011  float r_f[3],
1012  float r_dfdx[3][3],
1013  float r_dfdv[3][3])
1014 {
1015  float extent[3], length, dir[3], vel[3];
1016 
1017  /* calculate elongation */
1018  spring_length(data, i, j, extent, dir, &length, vel);
1019 
1020  if (length > restlen || no_compress) {
1021  float stretch_force, f[3], dfdx[3][3], dfdv[3][3];
1022 
1023  stretch_force = stiffness * (length - restlen);
1024  if (clamp_force > 0.0f && stretch_force > clamp_force) {
1025  stretch_force = clamp_force;
1026  }
1027  mul_v3_v3fl(f, dir, stretch_force);
1028 
1029  /* Ascher & Boxman, p.21: Damping only during elongation
1030  * something wrong with it... */
1031  madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
1032 
1033  dfdx_spring(dfdx, dir, length, restlen, stiffness);
1034  dfdv_damp(dfdv, dir, damping);
1035 
1036  apply_spring(data, i, j, f, dfdx, dfdv);
1037 
1038  if (r_f) {
1039  copy_v3_v3(r_f, f);
1040  }
1041  if (r_dfdx) {
1042  copy_m3_m3(r_dfdx, dfdx);
1043  }
1044  if (r_dfdv) {
1045  copy_m3_m3(r_dfdv, dfdv);
1046  }
1047 
1048  return true;
1049  }
1050  else {
1051  if (r_f) {
1052  zero_v3(r_f);
1053  }
1054  if (r_dfdx) {
1055  zero_m3(r_dfdx);
1056  }
1057  if (r_dfdv) {
1058  zero_m3(r_dfdv);
1059  }
1060 
1061  return false;
1062  }
1063 }
1064 
1065 /* See "Stable but Responsive Cloth" (Choi, Ko 2005) */
1067  int i,
1068  int j,
1069  float restlen,
1070  float kb,
1071  float cb,
1072  float r_f[3],
1073  float r_dfdx[3][3],
1074  float r_dfdv[3][3])
1075 {
1076  float extent[3], length, dir[3], vel[3];
1077 
1078  /* calculate elongation */
1079  spring_length(data, i, j, extent, dir, &length, vel);
1080 
1081  if (length < restlen) {
1082  float f[3], dfdx[3][3], dfdv[3][3];
1083 
1084  mul_v3_v3fl(f, dir, fbstar(length, restlen, kb, cb));
1085 
1086  outerproduct(dfdx, dir, dir);
1087  mul_m3_fl(dfdx, fbstar_jacobi(length, restlen, kb, cb));
1088 
1089  /* XXX damping not supported */
1090  zero_m3(dfdv);
1091 
1092  apply_spring(data, i, j, f, dfdx, dfdv);
1093 
1094  if (r_f) {
1095  copy_v3_v3(r_f, f);
1096  }
1097  if (r_dfdx) {
1098  copy_m3_m3(r_dfdx, dfdx);
1099  }
1100  if (r_dfdv) {
1101  copy_m3_m3(r_dfdv, dfdv);
1102  }
1103 
1104  return true;
1105  }
1106  else {
1107  if (r_f) {
1108  zero_v3(r_f);
1109  }
1110  if (r_dfdx) {
1111  zero_m3(r_dfdx);
1112  }
1113  if (r_dfdv) {
1114  zero_m3(r_dfdv);
1115  }
1116 
1117  return false;
1118  }
1119 }
1120 
1121 /* Jacobian of a direction vector.
1122  * Basically the part of the differential orthogonal to the direction,
1123  * inversely proportional to the length of the edge.
1124  *
1125  * dD_ij/dx_i = -dD_ij/dx_j = (D_ij * D_ij^T - I) / len_ij
1126  */
1128  Implicit_Data *data, int i, int j, float edge[3], float dir[3], float grad_dir[3][3])
1129 {
1130  float length;
1131 
1132  sub_v3_v3v3(edge, data->X.v3(j), data->X.v3(i));
1133  length = normalize_v3_v3(dir, edge);
1134 
1135  if (length > ALMOST_ZERO) {
1136  outerproduct(grad_dir, dir, dir);
1137  sub_m3_m3m3(grad_dir, I, grad_dir);
1138  mul_m3_fl(grad_dir, 1.0f / length);
1139  }
1140  else {
1141  zero_m3(grad_dir);
1142  }
1143 }
1144 
1145 BLI_INLINE void spring_angbend_forces(Implicit_Data *data,
1146  int i,
1147  int j,
1148  int k,
1149  const float goal[3],
1150  float stiffness,
1151  float damping,
1152  int q,
1153  const float dx[3],
1154  const float dv[3],
1155  float r_f[3])
1156 {
1157  float edge_ij[3], dir_ij[3];
1158  float edge_jk[3], dir_jk[3];
1159  float vel_ij[3], vel_jk[3], vel_ortho[3];
1160  float f_bend[3], f_damp[3];
1161  float fk[3];
1162  float dist[3];
1163 
1164  zero_v3(fk);
1165 
1166  sub_v3_v3v3(edge_ij, data->X.v3(j), data->X.v3(i));
1167  if (q == i) {
1168  sub_v3_v3(edge_ij, dx);
1169  }
1170  if (q == j) {
1171  add_v3_v3(edge_ij, dx);
1172  }
1173  normalize_v3_v3(dir_ij, edge_ij);
1174 
1175  sub_v3_v3v3(edge_jk, data->X.v3(k), data->X.v3(j));
1176  if (q == j) {
1177  sub_v3_v3(edge_jk, dx);
1178  }
1179  if (q == k) {
1180  add_v3_v3(edge_jk, dx);
1181  }
1182  normalize_v3_v3(dir_jk, edge_jk);
1183 
1184  sub_v3_v3v3(vel_ij, data->V.v3(j), data->V.v3(i));
1185  if (q == i) {
1186  sub_v3_v3(vel_ij, dv);
1187  }
1188  if (q == j) {
1189  add_v3_v3(vel_ij, dv);
1190  }
1191 
1192  sub_v3_v3v3(vel_jk, data->V.v3(k), data->V.v3(j));
1193  if (q == j) {
1194  sub_v3_v3(vel_jk, dv);
1195  }
1196  if (q == k) {
1197  add_v3_v3(vel_jk, dv);
1198  }
1199 
1200  /* bending force */
1201  sub_v3_v3v3(dist, goal, edge_jk);
1202  mul_v3_v3fl(f_bend, dist, stiffness);
1203 
1204  add_v3_v3(fk, f_bend);
1205 
1206  /* damping force */
1207  madd_v3_v3v3fl(vel_ortho, vel_jk, dir_jk, -dot_v3v3(vel_jk, dir_jk));
1208  mul_v3_v3fl(f_damp, vel_ortho, damping);
1209 
1210  sub_v3_v3(fk, f_damp);
1211 
1212  copy_v3_v3(r_f, fk);
1213 }
1214 
1215 /* Finite Differences method for estimating the jacobian of the force */
1216 BLI_INLINE void spring_angbend_estimate_dfdx(Implicit_Data *data,
1217  int i,
1218  int j,
1219  int k,
1220  const float goal[3],
1221  float stiffness,
1222  float damping,
1223  int q,
1224  float dfdx[3][3])
1225 {
1226  const float delta = 0.00001f; /* TODO find a good heuristic for this */
1227  float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
1228  float f[3];
1229  int a, b;
1230 
1231  zero_m3(dvec_null);
1232  unit_m3(dvec_pos);
1233  mul_m3_fl(dvec_pos, delta * 0.5f);
1234  copy_m3_m3(dvec_neg, dvec_pos);
1235  negate_m3(dvec_neg);
1236 
1237  /* XXX TODO offset targets to account for position dependency */
1238 
1239  for (a = 0; a < 3; a++) {
1240  spring_angbend_forces(
1241  data, i, j, k, goal, stiffness, damping, q, dvec_pos[a], dvec_null[a], f);
1242  copy_v3_v3(dfdx[a], f);
1243 
1244  spring_angbend_forces(
1245  data, i, j, k, goal, stiffness, damping, q, dvec_neg[a], dvec_null[a], f);
1246  sub_v3_v3(dfdx[a], f);
1247 
1248  for (b = 0; b < 3; b++) {
1249  dfdx[a][b] /= delta;
1250  }
1251  }
1252 }
1253 
1254 /* Finite Differences method for estimating the jacobian of the force */
1255 BLI_INLINE void spring_angbend_estimate_dfdv(Implicit_Data *data,
1256  int i,
1257  int j,
1258  int k,
1259  const float goal[3],
1260  float stiffness,
1261  float damping,
1262  int q,
1263  float dfdv[3][3])
1264 {
1265  const float delta = 0.00001f; /* TODO find a good heuristic for this */
1266  float dvec_null[3][3], dvec_pos[3][3], dvec_neg[3][3];
1267  float f[3];
1268  int a, b;
1269 
1270  zero_m3(dvec_null);
1271  unit_m3(dvec_pos);
1272  mul_m3_fl(dvec_pos, delta * 0.5f);
1273  copy_m3_m3(dvec_neg, dvec_pos);
1274  negate_m3(dvec_neg);
1275 
1276  /* XXX TODO offset targets to account for position dependency */
1277 
1278  for (a = 0; a < 3; a++) {
1279  spring_angbend_forces(
1280  data, i, j, k, goal, stiffness, damping, q, dvec_null[a], dvec_pos[a], f);
1281  copy_v3_v3(dfdv[a], f);
1282 
1283  spring_angbend_forces(
1284  data, i, j, k, goal, stiffness, damping, q, dvec_null[a], dvec_neg[a], f);
1285  sub_v3_v3(dfdv[a], f);
1286 
1287  for (b = 0; b < 3; b++) {
1288  dfdv[a][b] /= delta;
1289  }
1290  }
1291 }
1292 
1293 /* Angular spring that pulls the vertex toward the local target
1294  * See "Artistic Simulation of Curly Hair" (Pixar technical memo #12-03a)
1295  */
1296 bool SIM_mass_spring_force_spring_bending_angular(Implicit_Data *data,
1297  int i,
1298  int j,
1299  int k,
1300  const float target[3],
1301  float stiffness,
1302  float damping)
1303 {
1304  float goal[3];
1305  float fj[3], fk[3];
1306  float dfj_dxi[3][3], dfj_dxj[3][3], dfk_dxi[3][3], dfk_dxj[3][3], dfk_dxk[3][3];
1307  float dfj_dvi[3][3], dfj_dvj[3][3], dfk_dvi[3][3], dfk_dvj[3][3], dfk_dvk[3][3];
1308 
1309  const float vecnull[3] = {0.0f, 0.0f, 0.0f};
1310 
1311  world_to_root_v3(data, j, goal, target);
1312 
1313  spring_angbend_forces(data, i, j, k, goal, stiffness, damping, k, vecnull, vecnull, fk);
1314  negate_v3_v3(fj, fk); /* counterforce */
1315 
1316  spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, i, dfk_dxi);
1317  spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, j, dfk_dxj);
1318  spring_angbend_estimate_dfdx(data, i, j, k, goal, stiffness, damping, k, dfk_dxk);
1319  copy_m3_m3(dfj_dxi, dfk_dxi);
1320  negate_m3(dfj_dxi);
1321  copy_m3_m3(dfj_dxj, dfk_dxj);
1322  negate_m3(dfj_dxj);
1323 
1324  spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, i, dfk_dvi);
1325  spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, j, dfk_dvj);
1326  spring_angbend_estimate_dfdv(data, i, j, k, goal, stiffness, damping, k, dfk_dvk);
1327  copy_m3_m3(dfj_dvi, dfk_dvi);
1328  negate_m3(dfj_dvi);
1329  copy_m3_m3(dfj_dvj, dfk_dvj);
1330  negate_m3(dfj_dvj);
1331 
1332  /* add forces and jacobians to the solver data */
1333 
1334  add_v3_v3(data->F.v3(j), fj);
1335  add_v3_v3(data->F.v3(k), fk);
1336 
1337  data->idFdX.add(j, j, dfj_dxj);
1338  data->idFdX.add(k, k, dfk_dxk);
1339 
1340  data->idFdX.add(i, j, dfj_dxi);
1341  data->idFdX.add(j, i, dfj_dxi);
1342  data->idFdX.add(j, k, dfk_dxj);
1343  data->idFdX.add(k, j, dfk_dxj);
1344  data->idFdX.add(i, k, dfk_dxi);
1345  data->idFdX.add(k, i, dfk_dxi);
1346 
1347  data->idFdV.add(j, j, dfj_dvj);
1348  data->idFdV.add(k, k, dfk_dvk);
1349 
1350  data->idFdV.add(i, j, dfj_dvi);
1351  data->idFdV.add(j, i, dfj_dvi);
1352  data->idFdV.add(j, k, dfk_dvj);
1353  data->idFdV.add(k, j, dfk_dvj);
1354  data->idFdV.add(i, k, dfk_dvi);
1355  data->idFdV.add(k, i, dfk_dvi);
1356 
1357  /* XXX analytical calculation of derivatives below is incorrect.
1358  * This proved to be difficult, but for now just using the finite difference method for
1359  * estimating the jacobians should be sufficient.
1360  */
1361 # if 0
1362  float edge_ij[3], dir_ij[3], grad_dir_ij[3][3];
1363  float edge_jk[3], dir_jk[3], grad_dir_jk[3][3];
1364  float dist[3], vel_jk[3], vel_jk_ortho[3], projvel[3];
1365  float target[3];
1366  float tmp[3][3];
1367  float fi[3], fj[3], fk[3];
1368  float dfi_dxi[3][3], dfj_dxi[3][3], dfj_dxj[3][3], dfk_dxi[3][3], dfk_dxj[3][3], dfk_dxk[3][3];
1369  float dfdvi[3][3];
1370 
1371  /* TESTING */
1372  damping = 0.0f;
1373 
1374  zero_v3(fi);
1375  zero_v3(fj);
1376  zero_v3(fk);
1377  zero_m3(dfi_dxi);
1378  zero_m3(dfj_dxi);
1379  zero_m3(dfk_dxi);
1380  zero_m3(dfk_dxj);
1381  zero_m3(dfk_dxk);
1382 
1383  /* jacobian of direction vectors */
1384  spring_grad_dir(data, i, j, edge_ij, dir_ij, grad_dir_ij);
1385  spring_grad_dir(data, j, k, edge_jk, dir_jk, grad_dir_jk);
1386 
1387  sub_v3_v3v3(vel_jk, data->V[k], data->V[j]);
1388 
1389  /* bending force */
1390  mul_v3_v3fl(target, dir_ij, restlen);
1391  sub_v3_v3v3(dist, target, edge_jk);
1392  mul_v3_v3fl(fk, dist, stiffness);
1393 
1394  /* damping force */
1395  madd_v3_v3v3fl(vel_jk_ortho, vel_jk, dir_jk, -dot_v3v3(vel_jk, dir_jk));
1396  madd_v3_v3fl(fk, vel_jk_ortho, damping);
1397 
1398  /* XXX this only holds true as long as we assume straight rest shape!
1399  * eventually will become a bit more involved since the opposite segment
1400  * gets its own target, under condition of having equal torque on both sides.
1401  */
1402  copy_v3_v3(fi, fk);
1403 
1404  /* counterforce on the middle point */
1405  sub_v3_v3(fj, fi);
1406  sub_v3_v3(fj, fk);
1407 
1408  /* === derivatives === */
1409 
1410  madd_m3_m3fl(dfk_dxi, grad_dir_ij, stiffness * restlen);
1411 
1412  madd_m3_m3fl(dfk_dxj, grad_dir_ij, -stiffness * restlen);
1413  madd_m3_m3fl(dfk_dxj, I, stiffness);
1414 
1415  madd_m3_m3fl(dfk_dxk, I, -stiffness);
1416 
1417  copy_m3_m3(dfi_dxi, dfk_dxk);
1418  negate_m3(dfi_dxi);
1419 
1420  /* dfj_dfi == dfi_dfj due to symmetry,
1421  * dfi_dfj == dfk_dfj due to fi == fk
1422  * XXX see comment above on future bent rest shapes
1423  */
1424  copy_m3_m3(dfj_dxi, dfk_dxj);
1425 
1426  /* dfj_dxj == -(dfi_dxj + dfk_dxj) due to fj == -(fi + fk) */
1427  sub_m3_m3m3(dfj_dxj, dfj_dxj, dfj_dxi);
1428  sub_m3_m3m3(dfj_dxj, dfj_dxj, dfk_dxj);
1429 
1430  /* add forces and jacobians to the solver data */
1431  add_v3_v3(data->F[i], fi);
1432  add_v3_v3(data->F[j], fj);
1433  add_v3_v3(data->F[k], fk);
1434 
1435  add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, dfi_dxi);
1436  add_m3_m3m3(data->dFdX[j].m, data->dFdX[j].m, dfj_dxj);
1437  add_m3_m3m3(data->dFdX[k].m, data->dFdX[k].m, dfk_dxk);
1438 
1439  add_m3_m3m3(data->dFdX[block_ij].m, data->dFdX[block_ij].m, dfj_dxi);
1440  add_m3_m3m3(data->dFdX[block_jk].m, data->dFdX[block_jk].m, dfk_dxj);
1441  add_m3_m3m3(data->dFdX[block_ik].m, data->dFdX[block_ik].m, dfk_dxi);
1442 # endif
1443 
1444  return true;
1445 }
1446 
1448  int i,
1449  const float goal_x[3],
1450  const float goal_v[3],
1451  float stiffness,
1452  float damping,
1453  float r_f[3],
1454  float r_dfdx[3][3],
1455  float r_dfdv[3][3])
1456 {
1457  float root_goal_x[3], root_goal_v[3], extent[3], length, dir[3], vel[3];
1458  float f[3], dfdx[3][3], dfdv[3][3];
1459 
1460  /* goal is in world space */
1461  world_to_root_v3(data, i, root_goal_x, goal_x);
1462  world_to_root_v3(data, i, root_goal_v, goal_v);
1463 
1464  sub_v3_v3v3(extent, root_goal_x, data->X.v3(i));
1465  sub_v3_v3v3(vel, root_goal_v, data->V.v3(i));
1466  length = normalize_v3_v3(dir, extent);
1467 
1468  if (length > ALMOST_ZERO) {
1469  mul_v3_v3fl(f, dir, stiffness * length);
1470 
1471  /* Ascher & Boxman, p.21: Damping only during elongation
1472  * something wrong with it... */
1473  madd_v3_v3fl(f, dir, damping * dot_v3v3(vel, dir));
1474 
1475  dfdx_spring(dfdx, dir, length, 0.0f, stiffness);
1476  dfdv_damp(dfdv, dir, damping);
1477 
1478  add_v3_v3(data->F.v3(i), f);
1479  data->idFdX.add(i, i, dfdx);
1480  data->idFdV.add(i, i, dfdv);
1481 
1482  if (r_f) {
1483  copy_v3_v3(r_f, f);
1484  }
1485  if (r_dfdx) {
1486  copy_m3_m3(r_dfdx, dfdx);
1487  }
1488  if (r_dfdv) {
1489  copy_m3_m3(r_dfdv, dfdv);
1490  }
1491 
1492  return true;
1493  }
1494  else {
1495  if (r_f) {
1496  zero_v3(r_f);
1497  }
1498  if (r_dfdx) {
1499  zero_m3(r_dfdx);
1500  }
1501  if (r_dfdv) {
1502  zero_m3(r_dfdv);
1503  }
1504 
1505  return false;
1506  }
1507 }
1508 
1509 #endif /* IMPLICIT_SOLVER_EIGEN */
typedef float(TangentPoint)[2]
#define ALMOST_ZERO
Definition: BKE_cloth.h:47
#define BLI_INLINE
void sub_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:1080
void negate_m3(float R[3][3])
Definition: math_matrix.c:993
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:89
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
void mul_m3_fl(float R[3][3], float f)
Definition: math_matrix.c:960
void add_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:1036
void zero_m3(float m[3][3])
Definition: math_matrix.c:41
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:901
void transpose_m3(float R[3][3])
Definition: math_matrix.c:1312
void mul_transposed_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:940
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:391
void madd_m3_m3m3fl(float R[3][3], const float A[3][3], const float B[3][3], const float f)
Definition: math_matrix.c:1058
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define MAX2(a, b)
Object is a sort of wrapper for general info.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
int SIM_mass_spring_solver_numvert(struct Implicit_Data *id)
@ SIM_SOLVER_SUCCESS
@ SIM_SOLVER_INVALID_INPUT
@ SIM_SOLVER_NUMERICAL_ISSUE
@ SIM_SOLVER_NO_CONVERGENCE
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
btGeneric6DofConstraint & operator=(btGeneric6DofConstraint &other)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
void reset()
clear internal cached data and reset random seed
A conjugate gradient solver for sparse self-adjoint problems with additional constraints.
BLI_INLINE void madd_m3_m3fl(float r[3][3], const float m[3][3], float f)
Definition: cloth.c:1266
Eigen::ConjugateGradient< lMatrix, Eigen::Lower, Eigen::DiagonalPreconditioner< Scalar > > ConjugateGradient
Definition: eigen_utils.h:202
std::vector< Triplet > TripletList
Definition: eigen_utils.h:143
Eigen::VectorXf lVector
Definition: eigen_utils.h:112
BLI_INLINE void print_lmatrix(const lMatrix &m)
Definition: eigen_utils.h:217
Eigen::SparseMatrix< Scalar > lMatrix
Definition: eigen_utils.h:145
BLI_INLINE void print_lvector(const lVector3f &v)
Definition: eigen_utils.h:206
float Scalar
Definition: eigen_utils.h:42
Eigen::Triplet< Scalar > Triplet
Definition: eigen_utils.h:142
uint nor
void SIM_mass_spring_add_constraint_ndof1(struct Implicit_Data *data, int index, const float c1[3], const float c2[3], const float dV[3])
void SIM_mass_spring_get_motion_state(struct Implicit_Data *data, int index, float x[3], float v[3])
void SIM_mass_spring_add_constraint_ndof0(struct Implicit_Data *data, int index, const float dV[3])
void SIM_mass_spring_force_reference_frame(struct Implicit_Data *data, int index, const float acceleration[3], const float omega[3], const float domega_dt[3], float mass)
void SIM_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2, float radius1, float radius2, const float(*winvec)[3])
void SIM_mass_spring_set_new_velocity(struct Implicit_Data *data, int index, const float v[3])
bool SIM_mass_spring_force_spring_goal(struct Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3], float stiffness, float damping)
void SIM_mass_spring_set_vertex_mass(struct Implicit_Data *data, int index, float mass)
void SIM_mass_spring_set_motion_state(struct Implicit_Data *data, int index, const float x[3], const float v[3])
bool SIM_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen, float stiffness_tension, float damping_tension, float stiffness_compression, float damping_compression, bool resist_compress, bool new_compress, float clamp_force)
bool SIM_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen, float kb, float cb)
void SIM_mass_spring_apply_result(struct Implicit_Data *data)
void SIM_mass_spring_set_position(struct Implicit_Data *data, int index, const float x[3])
void SIM_mass_spring_add_constraint_ndof2(struct Implicit_Data *data, int index, const float c1[3], const float dV[3])
BLI_INLINE void implicit_print_matrix_elem(float v)
Definition: implicit.h:62
void SIM_mass_spring_force_face_wind(struct Implicit_Data *data, int v1, int v2, int v3, const float(*winvec)[3])
void SIM_mass_spring_get_position(struct Implicit_Data *data, int index, float x[3])
bool SIM_mass_spring_solve_velocities(struct Implicit_Data *data, float dt, struct ImplicitSolverResult *result)
void SIM_mass_spring_force_drag(struct Implicit_Data *data, float drag)
void SIM_mass_spring_clear_constraints(struct Implicit_Data *data)
bool SIM_mass_spring_solve_positions(struct Implicit_Data *data, float dt)
void SIM_mass_spring_get_new_velocity(struct Implicit_Data *data, int index, float v[3])
void SIM_mass_spring_set_velocity(struct Implicit_Data *data, int index, const float v[3])
void SIM_mass_spring_force_extern(struct Implicit_Data *data, int i, const float f[3], float dfdx[3][3], float dfdv[3][3])
void SIM_mass_spring_force_gravity(struct Implicit_Data *data, int index, float mass, const float g[3])
void SIM_mass_spring_set_rest_transform(struct Implicit_Data *data, int index, float tfm[3][3])
void SIM_mass_spring_clear_forces(struct Implicit_Data *data)
BLI_INLINE void apply_spring(Implicit_Data *data, int i, int j, const float f[3], const float dfdx[3][3], const float dfdv[3][3])
BLI_INLINE float fbstar_jacobi(float length, float L, float kb, float cb)
DO_INLINE void mul_fvectorT_fvector(float to[3][3], const float vectorA[3], const float vectorB[3])
BLI_INLINE void cross_m3_v3m3(float r[3][3], const float v[3], const float m[3][3])
BLI_INLINE float fb(float length, float L)
DO_INLINE void mul_fmatrix_S(float matrix[3][3], float scalar)
Implicit_Data * SIM_mass_spring_solver_create(int numverts, int numsprings)
BLI_INLINE float fbderiv(float length, float L)
BLI_INLINE bool spring_length(Implicit_Data *data, int i, int j, float r_extent[3], float r_dir[3], float *r_length, float r_vel[3])
BLI_INLINE void root_to_world_m3(Implicit_Data *data, int index, float r[3][3], const float m[3][3])
void SIM_mass_spring_solver_free(Implicit_Data *id)
BLI_INLINE void cross_v3_identity(float r[3][3], const float v[3])
BLI_INLINE void outerproduct(float r[3][3], const float a[3], const float b[3])
DO_INLINE void sub_fmatrix_fmatrix(float to[3][3], const float matrixA[3][3], const float matrixB[3][3])
struct Implicit_Data Implicit_Data
BLI_INLINE void dfdx_spring(float to[3][3], const float dir[3], float length, float L, float k)
BLI_INLINE void spring_grad_dir(Implicit_Data *data, int i, int j, float edge[3], float dir[3], float grad_dir[3][3])
static float calc_nor_area_tri(float nor[3], const float v1[3], const float v2[3], const float v3[3])
BLI_INLINE void root_to_world_v3(Implicit_Data *data, int index, float r[3], const float v[3])
BLI_INLINE void world_to_root_m3(Implicit_Data *data, int index, float r[3][3], const float m[3][3])
BLI_INLINE float fbstar(float length, float L, float kb, float cb)
BLI_INLINE void world_to_root_v3(Implicit_Data *data, int index, float r[3], const float v[3])
BLI_INLINE void dfdv_damp(float to[3][3], const float dir[3], float damping)
#define powf(x, y)
#define T
#define L
static void add(GHash *messages, MemArena *memarena, const Message *msg)
Definition: msgfmt.c:268
static unsigned a[3]
Definition: RandGen.cpp:92
static void area(int d1, int d2, int e1, int e2, float weights[2])
#define I
fmatrix3x3 * M
fmatrix3x3 * A
fmatrix3x3 * S
fmatrix3x3 * dFdX
fmatrix3x3 * dFdV
fmatrix3x3 * tfm