Blender V5.0
SIM_mass_spring.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2004-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11#include "DNA_cloth_types.h"
12#include "DNA_modifier_types.h"
14#include "DNA_object_types.h"
15#include "DNA_scene_types.h"
16
17#include "BLI_linklist.h"
18#include "BLI_math_geom.h"
19#include "BLI_math_vector.h"
20#include "BLI_math_vector.hh"
21#include "BLI_utildefines.h"
22
23#include "BKE_cloth.hh"
24#include "BKE_collision.h"
25#include "BKE_effect.h"
26
27#include "SIM_mass_spring.h"
28#include "implicit.h"
29
30#include "DEG_depsgraph.hh"
32
33static float I3[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
34
35/* Number of off-diagonal non-zero matrix blocks.
36 * Basically there is one of these for each vertex-vertex interaction.
37 */
39{
40 LinkNode *link;
41 int nondiag = 0;
42
43 for (link = cloth->springs; link; link = link->next) {
44 ClothSpring *spring = (ClothSpring *)link->link;
45 switch (spring->type) {
47 /* angular bending combines 3 vertices */
48 nondiag += 3;
49 break;
50
51 default:
52 /* all other springs depend on 2 vertices only */
53 nondiag += 1;
54 break;
55 }
56 }
57
58 return nondiag;
59}
60
62 const blender::int3 &vert_tri,
63 float *r_weights)
64{
65 /* We have custom vertex weights for pressure. */
66 if (clmd->sim_parms->vgroup_pressure > 0) {
67 Cloth *cloth = clmd->clothObject;
68 ClothVertex *verts = cloth->verts;
69
70 for (uint j = 0; j < 3; j++) {
71 r_weights[j] = verts[vert_tri[j]].pressure_factor;
72
73 /* Skip the entire triangle if it has a zero weight. */
74 if (r_weights[j] == 0.0f) {
75 return false;
76 }
77 }
78 }
79
80 return true;
81}
82
84 const float gradient_vector[3],
85 float *r_vertex_pressure)
86{
87 Cloth *cloth = clmd->clothObject;
88 Implicit_Data *data = cloth->implicit;
89 uint mvert_num = cloth->mvert_num;
90 float pt[3];
91
92 for (uint i = 0; i < mvert_num; i++) {
94 r_vertex_pressure[i] = dot_v3v3(pt, gradient_vector);
95 }
96}
97
99{
100 /* Calculate the (closed) cloth volume. */
101 Cloth *cloth = clmd->clothObject;
102 const blender::int3 *vert_tris = cloth->vert_tris;
103 Implicit_Data *data = cloth->implicit;
104 float weights[3] = {1.0f, 1.0f, 1.0f};
105 float vol = 0;
106
107 /* Early exit for hair, as it never has volume. */
108 if (clmd->hairdata) {
109 return 0.0f;
110 }
111
112 for (uint i = 0; i < cloth->primitive_num; i++) {
113 const blender::int3 tri = vert_tris[i];
114
115 if (cloth_get_pressure_weights(clmd, tri, weights)) {
116 vol += SIM_tri_tetra_volume_signed_6x(data, tri[0], tri[1], tri[2]);
117 }
118 }
119
120 /* We need to divide by 6 to get the actual volume. */
121 vol = vol / 6.0f;
122
123 return vol;
124}
125
127{
128 /* Calculate the (closed) cloth volume. */
129 Cloth *cloth = clmd->clothObject;
130 const blender::int3 *vert_tris = cloth->vert_tris;
131 const ClothVertex *v = cloth->verts;
132 float weights[3] = {1.0f, 1.0f, 1.0f};
133 float vol = 0;
134
135 /* Early exit for hair, as it never has volume. */
136 if (clmd->hairdata) {
137 return 0.0f;
138 }
139
140 for (uint i = 0; i < cloth->primitive_num; i++) {
141 const blender::int3 tri = vert_tris[i];
142
143 if (cloth_get_pressure_weights(clmd, tri, weights)) {
145 v[tri[0]].xrest, v[tri[1]].xrest, v[tri[2]].xrest);
146 }
147 }
148
149 /* We need to divide by 6 to get the actual volume. */
150 vol = vol / 6.0f;
151
152 return vol;
153}
154
155static float cloth_calc_average_pressure(ClothModifierData *clmd, const float *vertex_pressure)
156{
157 Cloth *cloth = clmd->clothObject;
158 const blender::int3 *vert_tris = cloth->vert_tris;
159 Implicit_Data *data = cloth->implicit;
160 float weights[3] = {1.0f, 1.0f, 1.0f};
161 float total_force = 0;
162 float total_area = 0;
163
164 for (uint i = 0; i < cloth->primitive_num; i++) {
165 const blender::int3 tri = vert_tris[i];
166
167 if (cloth_get_pressure_weights(clmd, tri, weights)) {
168 float area = SIM_tri_area(data, tri[0], tri[1], tri[2]);
169
170 total_force += (vertex_pressure[tri[0]] + vertex_pressure[tri[1]] +
171 vertex_pressure[tri[2]]) *
172 area / 3.0f;
173 total_area += area;
174 }
175 }
176
177 return total_force / total_area;
178}
179
181{
182 Cloth *cloth = clmd->clothObject;
183 ClothVertex *verts = cloth->verts;
184 const float ZERO[3] = {0.0f, 0.0f, 0.0f};
185 Implicit_Data *id;
186 uint i, nondiag;
187
188 nondiag = cloth_count_nondiag_blocks(cloth);
189 cloth->implicit = id = SIM_mass_spring_solver_create(cloth->mvert_num, nondiag);
190
191 for (i = 0; i < cloth->mvert_num; i++) {
193 }
194
195 for (i = 0; i < cloth->mvert_num; i++) {
197 }
198
199 return 1;
200}
201
203{
205}
206
208{
209 Cloth *cloth = clmd->clothObject;
210
211 if (cloth->implicit) {
213 cloth->implicit = nullptr;
214 }
215}
216
218{
219 Cloth *cloth = clmd->clothObject;
220 ClothVertex *verts = cloth->verts;
221 uint mvert_num = cloth->mvert_num, i;
222 ClothHairData *cloth_hairdata = clmd->hairdata;
223 Implicit_Data *id = cloth->implicit;
224
225 for (i = 0; i < mvert_num; i++) {
226 if (cloth_hairdata) {
227 ClothHairData *root = &cloth_hairdata[i];
229 }
230 else {
232 }
233
235 }
236}
237
239{
240 Cloth *cloth = clmd->clothObject;
241
243}
244
245/* Init constraint matrix
246 * This is part of the modified CG method suggested by Baraff/Witkin in
247 * "Large Steps in Cloth Simulation" (SIGGRAPH 1998)
248 */
250{
251 Cloth *cloth = clmd->clothObject;
252 Implicit_Data *data = cloth->implicit;
253 ClothVertex *verts = cloth->verts;
254 int mvert_num = cloth->mvert_num;
255 int v;
256
257 const float ZERO[3] = {0.0f, 0.0f, 0.0f};
258
260
261 for (v = 0; v < mvert_num; v++) {
262 if (verts[v].flags & CLOTH_VERT_FLAG_PINNED) {
263 /* pinned vertex constraints */
264 SIM_mass_spring_add_constraint_ndof0(data, v, ZERO); /* velocity is defined externally */
265 }
266
267 verts[v].impulse_count = 0;
268 }
269}
270
277 Object * /*ob*/, ClothModifierData *clmd, float (*initial_cos)[3], float /*step*/, float dt)
278{
279 Cloth *cloth = clmd->clothObject;
280 float (*cos)[3] = MEM_calloc_arrayN<float[3]>(cloth->mvert_num, "cos cloth_calc_helper_forces");
281 float *masses = MEM_calloc_arrayN<float>(cloth->mvert_num, "cos cloth_calc_helper_forces");
282 LinkNode *node;
283 ClothSpring *spring;
284 ClothVertex *cv;
285 int i, steps;
286
287 cv = cloth->verts;
288 for (i = 0; i < cloth->mvert_num; i++, cv++) {
289 copy_v3_v3(cos[i], cv->tx);
290
291 if (cv->goal == 1.0f || len_squared_v3v3(initial_cos[i], cv->tx) != 0.0f) {
292 masses[i] = 1e+10;
293 }
294 else {
295 masses[i] = cv->mass;
296 }
297 }
298
299 steps = 55;
300 for (i = 0; i < steps; i++) {
301 for (node = cloth->springs; node; node = node->next) {
302 // ClothVertex *cv1, *cv2; /* UNUSED */
303 int v1, v2;
304 float len, c, l, vec[3];
305
306 spring = (ClothSpring *)node->link;
308 continue;
309 }
310
311 v1 = spring->ij;
312 v2 = spring->kl;
313 // cv1 = cloth->verts + v1; /* UNUSED. */
314 // cv2 = cloth->verts + v2; /* UNUSED. */
315 len = len_v3v3(cos[v1], cos[v2]);
316
317 sub_v3_v3v3(vec, cos[v1], cos[v2]);
318 normalize_v3(vec);
319
320 c = (len - spring->restlen);
321 if (c == 0.0f) {
322 continue;
323 }
324
325 l = c / ((1.0f / masses[v1]) + (1.0f / masses[v2]));
326
327 mul_v3_fl(vec, -(1.0f / masses[v1]) * l);
328 add_v3_v3(cos[v1], vec);
329
330 sub_v3_v3v3(vec, cos[v2], cos[v1]);
331 normalize_v3(vec);
332
333 mul_v3_fl(vec, -(1.0f / masses[v2]) * l);
334 add_v3_v3(cos[v2], vec);
335 }
336 }
337
338 cv = cloth->verts;
339 for (i = 0; i < cloth->mvert_num; i++, cv++) {
340 float vec[3];
341
342 /* Compute forces. */
343 sub_v3_v3v3(vec, cos[i], cv->tx);
344 mul_v3_fl(vec, cv->mass * dt * 20.0f);
345 add_v3_v3(cv->tv, vec);
346 // copy_v3_v3(cv->tx, cos[i]);
347 }
348
349 MEM_freeN(cos);
350 MEM_freeN(masses);
351
352 return 1;
353}
354
356{
357 Cloth *cloth = clmd->clothObject;
358 ClothSimSettings *parms = clmd->sim_parms;
359 Implicit_Data *data = cloth->implicit;
360 bool using_angular = parms->bending_model == CLOTH_BENDING_ANGULAR;
361 bool resist_compress = (parms->flags & CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS) &&
362 !using_angular;
363
365
366 /* Calculate force of bending springs. */
367 if ((s->type & CLOTH_SPRING_TYPE_BENDING) && using_angular) {
368#ifdef CLOTH_FORCE_SPRING_BEND
369 float k, scaling;
370
372
373 scaling = parms->bending + s->ang_stiffness * fabsf(parms->max_bend - parms->bending);
374 /* Multiplying by 0.1, just to scale the forces to more reasonable values. */
375 k = scaling * s->restlen * 0.1f;
376
378 data, s->ij, s->kl, s->pa, s->pb, s->la, s->lb, s->restang, k, parms->bending_damping);
379#endif
380 }
381
382 /* Calculate force of structural + shear springs. */
383 if (s->type &
385 {
386#ifdef CLOTH_FORCE_SPRING_STRUCTURAL
387 float k_tension, scaling_tension;
388
390
391 scaling_tension = parms->tension +
392 s->lin_stiffness * fabsf(parms->max_tension - parms->tension);
393 k_tension = scaling_tension / (parms->avg_spring_len + FLT_EPSILON);
394
396 /* TODO: verify, half verified (couldn't see error)
397 * sewing springs usually have a large distance at first so clamp the force so we don't get
398 * tunneling through collision objects. */
400 s->ij,
401 s->kl,
402 s->restlen,
403 k_tension,
404 parms->tension_damp,
405 0.0f,
406 0.0f,
407 false,
408 false,
409 parms->max_sewing);
410 }
411 else if (s->type & CLOTH_SPRING_TYPE_STRUCTURAL) {
412 float k_compression, scaling_compression;
413 scaling_compression = parms->compression +
414 s->lin_stiffness * fabsf(parms->max_compression - parms->compression);
415 k_compression = scaling_compression / (parms->avg_spring_len + FLT_EPSILON);
416
418 s->ij,
419 s->kl,
420 s->restlen,
421 k_tension,
422 parms->tension_damp,
423 k_compression,
424 parms->compression_damp,
425 resist_compress,
426 using_angular,
427 0.0f);
428 }
429 else {
430 /* CLOTH_SPRING_TYPE_INTERNAL */
432
433 scaling_tension = parms->internal_tension +
434 s->lin_stiffness *
436 k_tension = scaling_tension / (parms->avg_spring_len + FLT_EPSILON);
437 float scaling_compression = parms->internal_compression +
439 parms->internal_compression);
440 float k_compression = scaling_compression / (parms->avg_spring_len + FLT_EPSILON);
441
442 float k_tension_damp = parms->tension_damp;
443 float k_compression_damp = parms->compression_damp;
444
445 if (k_tension == 0.0f) {
446 /* No damping so it behaves as if no tension spring was there at all. */
447 k_tension_damp = 0.0f;
448 }
449
450 if (k_compression == 0.0f) {
451 /* No damping so it behaves as if no compression spring was there at all. */
452 k_compression_damp = 0.0f;
453 }
454
456 s->ij,
457 s->kl,
458 s->restlen,
459 k_tension,
460 k_tension_damp,
461 k_compression,
462 k_compression_damp,
463 resist_compress,
464 using_angular,
465 0.0f);
466 }
467#endif
468 }
469 else if (s->type & CLOTH_SPRING_TYPE_SHEAR) {
470#ifdef CLOTH_FORCE_SPRING_SHEAR
471 float k, scaling;
472
474
475 scaling = parms->shear + s->lin_stiffness * fabsf(parms->max_shear - parms->shear);
476 k = scaling / (parms->avg_spring_len + FLT_EPSILON);
477
479 s->ij,
480 s->kl,
481 s->restlen,
482 k,
483 parms->shear_damp,
484 0.0f,
485 0.0f,
486 resist_compress,
487 false,
488 0.0f);
489#endif
490 }
491 else if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */
492#ifdef CLOTH_FORCE_SPRING_BEND
493 float kb, cb, scaling;
494
496
497 scaling = parms->bending + s->lin_stiffness * fabsf(parms->max_bend - parms->bending);
498 kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON));
499
500 /* Fix for #45084 for cloth stiffness must have cb proportional to kb */
501 cb = kb * parms->bending_damping;
502
504#endif
505 }
506 else if (s->type & CLOTH_SPRING_TYPE_BENDING_HAIR) {
507#ifdef CLOTH_FORCE_SPRING_BEND
508 float kb, cb, scaling;
509
511
512 /* XXX WARNING: angular bending springs for hair apply stiffness factor as an overall factor,
513 * unlike cloth springs! this is crap, but needed due to cloth/hair mixing ... max_bend factor
514 * is not even used for hair, so ...
515 */
516 scaling = s->lin_stiffness * parms->bending;
517 kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON));
518
519 /* Fix for #45084 for cloth stiffness must have cb proportional to kb */
520 cb = kb * parms->bending_damping;
521
522 /* XXX assuming same restlen for ij and jk segments here,
523 * this can be done correctly for hair later. */
525
526# if 0
527 {
528 float x_kl[3], x_mn[3], v[3], d[3];
529
532
533 BKE_sim_debug_data_add_dot(clmd->debug_data, x_kl, 0.9, 0.9, 0.9, "target", 7980, s->kl);
535 clmd->debug_data, x_kl, x_mn, 0.8, 0.8, 0.8, "target", 7981, s->kl);
536
537 copy_v3_v3(d, s->target);
539 clmd->debug_data, x_kl, d, 0.8, 0.8, 0.2, "target", 7982, s->kl);
540
541 // copy_v3_v3(d, s->target_ij);
542 // BKE_sim_debug_data_add_vector(clmd->debug_data, x, d, 1, 0.4, 0.4, "target", 7983, s->kl);
543 }
544# endif
545#endif
546 }
547}
548
550 blender::float3 &gmin,
551 blender::float3 &gmax)
552{
553 Cloth *cloth = clmd->clothObject;
554 Implicit_Data *data = cloth->implicit;
555 uint mvert_num = cloth->mvert_num;
556 int i;
557
558 INIT_MINMAX(gmin, gmax);
559 for (i = 0; i < mvert_num; i++) {
562 blender::math::min_max(x, gmin, gmax);
563 }
564}
565
567 Scene *scene, ClothModifierData *clmd, float /*frame*/, ListBase *effectors, float time)
568{
569 /* Collect forces and derivatives: F, dFdX, dFdV. */
570 Cloth *cloth = clmd->clothObject;
571 ClothSimSettings *parms = clmd->sim_parms;
572 Implicit_Data *data = cloth->implicit;
573 uint i = 0;
574 float drag = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */
575 float gravity[3] = {0.0f, 0.0f, 0.0f};
576 const blender::int3 *vert_tris = cloth->vert_tris;
577 uint mvert_num = cloth->mvert_num;
578 ClothVertex *vert;
579
580#ifdef CLOTH_FORCE_GRAVITY
581 /* global acceleration (gravitation) */
583 /* scale gravity force */
584 mul_v3_v3fl(gravity,
586 0.001f * clmd->sim_parms->effector_weights->global_gravity);
587 }
588
589 vert = cloth->verts;
590 for (i = 0; i < cloth->mvert_num; i++, vert++) {
591 SIM_mass_spring_force_gravity(data, i, vert->mass, gravity);
592
593 /* Vertex goal springs */
594 if (!(vert->flags & CLOTH_VERT_FLAG_PINNED) && (vert->goal > FLT_EPSILON)) {
595 float goal_x[3], goal_v[3];
596 float k;
597
598 /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */
599 interp_v3_v3v3(goal_x, vert->xold, vert->xconst, time / clmd->sim_parms->time_scale);
600 sub_v3_v3v3(goal_v, vert->xconst, vert->xold); /* distance covered over dt==1 */
601
602 k = vert->goal * clmd->sim_parms->goalspring /
603 (clmd->sim_parms->avg_spring_len + FLT_EPSILON);
604
606 data, i, goal_x, goal_v, k, clmd->sim_parms->goalfrict * 0.01f);
607 }
608 }
609#endif
610
611 // cloth_calc_volume_force(clmd);
612
613#ifdef CLOTH_FORCE_DRAG
615#endif
616 /* handle pressure forces (making sure that this never gets computed for hair). */
617 if ((parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE) && (clmd->hairdata == nullptr)) {
618 /* The difference in pressure between the inside and outside of the mesh. */
619 float pressure_difference = 0.0f;
620 float volume_factor = 1.0f;
621
622 float init_vol;
624 init_vol = clmd->sim_parms->target_volume;
625 }
626 else {
627 init_vol = cloth->initial_mesh_volume;
628 }
629
630 /* Check if we need to calculate the volume of the mesh. */
631 if (init_vol > 1E-6f) {
632 float f;
633 float vol = cloth_calc_volume(clmd);
634
635 /* If the volume is the same don't apply any pressure. */
636 volume_factor = init_vol / vol;
637 pressure_difference = volume_factor - 1;
638
639 /* Calculate an artificial maximum value for cloth pressure. */
640 f = fabs(clmd->sim_parms->uniform_pressure_force) + 200.0f;
641
642 /* Clamp the cloth pressure to the calculated maximum value. */
643 CLAMP_MAX(pressure_difference, f);
644 }
645
646 pressure_difference += clmd->sim_parms->uniform_pressure_force;
647 pressure_difference *= clmd->sim_parms->pressure_factor;
648
649 /* Compute the hydrostatic pressure gradient if enabled. */
650 float fluid_density = clmd->sim_parms->fluid_density * 1000; /* kg/l -> kg/m3 */
651 float *hydrostatic_pressure = nullptr;
652
653 if (fabs(fluid_density) > 1e-6f) {
654 float hydrostatic_vector[3];
655 copy_v3_v3(hydrostatic_vector, gravity);
656
657 /* When the fluid is inside the object, factor in the acceleration of
658 * the object into the pressure field, as gravity is indistinguishable
659 * from acceleration from the inside. */
660 if (fluid_density > 0) {
661 sub_v3_v3(hydrostatic_vector, cloth->average_acceleration);
662
663 /* Preserve the total mass by scaling density to match the change in volume. */
664 fluid_density *= volume_factor;
665 }
666
667 mul_v3_fl(hydrostatic_vector, fluid_density);
668
669 /* Compute an array of per-vertex hydrostatic pressure, and subtract the average. */
670 hydrostatic_pressure = MEM_malloc_arrayN<float>(mvert_num, "hydrostatic pressure gradient");
671
672 cloth_calc_pressure_gradient(clmd, hydrostatic_vector, hydrostatic_pressure);
673
674 pressure_difference -= cloth_calc_average_pressure(clmd, hydrostatic_pressure);
675 }
676
677 /* Apply pressure. */
678 if (hydrostatic_pressure || fabs(pressure_difference) > 1E-6f) {
679 float weights[3] = {1.0f, 1.0f, 1.0f};
680
681 for (i = 0; i < cloth->primitive_num; i++) {
682 const blender::int3 tri = vert_tris[i];
683
684 if (cloth_get_pressure_weights(clmd, tri, weights)) {
686 data, tri[0], tri[1], tri[2], pressure_difference, hydrostatic_pressure, weights);
687 }
688 }
689 }
690
691 if (hydrostatic_pressure) {
692 MEM_freeN(hydrostatic_pressure);
693 }
694 }
695
696 /* handle external forces like wind */
697 if (effectors) {
698 bool is_not_hair = (clmd->hairdata == nullptr) && (cloth->primitive_num > 0);
699 bool has_wind = false, has_force = false;
700
701 /* cache per-vertex forces to avoid redundant calculation */
702 float (*winvec)[3] = MEM_calloc_arrayN<float[3]>(mvert_num * 2, "effector forces");
703 float (*forcevec)[3] = is_not_hair ? winvec + mvert_num : winvec;
704
705 for (i = 0; i < cloth->mvert_num; i++) {
706 float x[3], v[3];
707 EffectedPoint epoint;
708
710 pd_point_from_loc(scene, x, v, i, &epoint);
711 BKE_effectors_apply(effectors,
712 nullptr,
714 &epoint,
715 forcevec[i],
716 winvec[i],
717 nullptr);
718
719 has_wind = has_wind || !is_zero_v3(winvec[i]);
720 has_force = has_force || !is_zero_v3(forcevec[i]);
721 }
722
723 /* Hair has only edges. */
724 if (is_not_hair) {
725 for (i = 0; i < cloth->primitive_num; i++) {
726 const blender::int3 tri = vert_tris[i];
727 if (has_wind) {
728 SIM_mass_spring_force_face_wind(data, tri[0], tri[1], tri[2], winvec);
729 }
730 if (has_force) {
731 SIM_mass_spring_force_face_extern(data, tri[0], tri[1], tri[2], forcevec);
732 }
733 }
734 }
735 else {
736#if 0
737 ClothHairData *hairdata = clmd->hairdata;
738 ClothHairData *hair_ij, *hair_kl;
739
740 for (LinkNode *link = cloth->springs; link; link = link->next) {
741 ClothSpring *spring = (ClothSpring *)link->link;
742 if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) {
743 if (hairdata) {
744 hair_ij = &hairdata[spring->ij];
745 hair_kl = &hairdata[spring->kl];
747 data, spring->ij, spring->kl, hair_ij->radius, hair_kl->radius, winvec);
748 }
749 else {
750 SIM_mass_spring_force_edge_wind(data, spring->ij, spring->kl, 1.0f, 1.0f, winvec);
751 }
752 }
753 }
754#else
755 ClothHairData *hairdata = clmd->hairdata;
756
757 vert = cloth->verts;
758 for (i = 0; i < cloth->mvert_num; i++, vert++) {
759 if (hairdata) {
760 ClothHairData *hair = &hairdata[i];
762 }
763 else {
765 }
766 }
767#endif
768 }
769
770 MEM_freeN(winvec);
771 }
772
773 /* calculate spring forces */
774 for (LinkNode *link = cloth->springs; link; link = link->next) {
775 ClothSpring *spring = (ClothSpring *)link->link;
776 /* only handle active springs */
777 if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) {
778 cloth_calc_spring_force(clmd, spring);
779 }
780 }
781}
782
783/* returns vertices' motion state */
785 float cell_scale,
786 const float cell_offset[3],
787 int index,
788 float x[3],
789 float v[3])
790{
793
794 mul_v3_fl(x, cell_scale);
795 add_v3_v3(x, cell_offset);
796}
797
798/* returns next spring forming a continuous hair sequence */
800{
801 ClothSpring *spring = (ClothSpring *)spring_link->link;
802 LinkNode *next = spring_link->next;
803 if (next) {
804 ClothSpring *next_spring = (ClothSpring *)next->link;
805 if (next_spring->type == CLOTH_SPRING_TYPE_STRUCTURAL && next_spring->kl == spring->ij) {
806 return next;
807 }
808 }
809 return nullptr;
810}
811
812/* XXX this is nasty: cloth meshes do not explicitly store
813 * the order of hair segments!
814 * We have to rely on the spring build function for now,
815 * which adds structural springs in reverse order:
816 * (3,4), (2,3), (1,2)
817 * This is currently the only way to figure out hair geometry inside this code ...
818 */
820 const float cell_scale,
821 const float cell_offset[3],
822 Cloth *cloth,
823 LinkNode *spring_link)
824{
825 Implicit_Data *data = cloth->implicit;
826 LinkNode *next_spring_link = nullptr; /* return value */
827 ClothSpring *spring1, *spring2, *spring3;
828 // ClothVertex *verts = cloth->verts;
829 // ClothVertex *vert3, *vert4;
830 float x1[3], v1[3], x2[3], v2[3], x3[3], v3[3], x4[3], v4[3];
831 float dir1[3], dir2[3], dir3[3];
832
833 spring1 = nullptr;
834 spring2 = nullptr;
835 spring3 = (ClothSpring *)spring_link->link;
836
837 zero_v3(x1);
838 zero_v3(v1);
839 zero_v3(dir1);
840 zero_v3(x2);
841 zero_v3(v2);
842 zero_v3(dir2);
843
844 // vert3 = &verts[spring3->kl];
845 cloth_get_grid_location(data, cell_scale, cell_offset, spring3->kl, x3, v3);
846 // vert4 = &verts[spring3->ij];
847 cloth_get_grid_location(data, cell_scale, cell_offset, spring3->ij, x4, v4);
848 sub_v3_v3v3(dir3, x4, x3);
849 normalize_v3(dir3);
850
851 while (spring_link) {
852 /* move on */
853 spring1 = spring2;
854 spring2 = spring3;
855
856 // vert3 = vert4;
857
858 copy_v3_v3(x1, x2);
859 copy_v3_v3(v1, v2);
860 copy_v3_v3(x2, x3);
861 copy_v3_v3(v2, v3);
862 copy_v3_v3(x3, x4);
863 copy_v3_v3(v3, v4);
864
865 copy_v3_v3(dir1, dir2);
866 copy_v3_v3(dir2, dir3);
867
868 /* read next segment */
869 next_spring_link = spring_link->next;
870 spring_link = hair_spring_next(spring_link);
871
872 if (spring_link) {
873 spring3 = (ClothSpring *)spring_link->link;
874 // vert4 = &verts[spring3->ij];
875 cloth_get_grid_location(data, cell_scale, cell_offset, spring3->ij, x4, v4);
876 sub_v3_v3v3(dir3, x4, x3);
877 normalize_v3(dir3);
878 }
879 else {
880 spring3 = nullptr;
881 // vert4 = nullptr;
882 zero_v3(x4);
883 zero_v3(v4);
884 zero_v3(dir3);
885 }
886
888 x1,
889 v1,
890 x2,
891 v2,
892 x3,
893 v3,
894 x4,
895 v4,
896 spring1 ? dir1 : nullptr,
897 dir2,
898 spring3 ? dir3 : nullptr);
899 }
900
901 return next_spring_link;
902}
903
904static void cloth_continuum_fill_grid(HairGrid *grid, Cloth *cloth)
905{
906#if 0
907 Implicit_Data *data = cloth->implicit;
908 int mvert_num = cloth->mvert_num;
909 ClothVertex *vert;
910 int i;
911
912 for (i = 0, vert = cloth->verts; i < mvert_num; i++, vert++) {
913 float x[3], v[3];
914
915 cloth_get_vertex_motion_state(data, vert, x, v);
917 }
918#else
919 LinkNode *link;
920 float cellsize, gmin[3], cell_scale, cell_offset[3];
921
922 /* scale and offset for transforming vertex locations into grid space
923 * (cell size is 0..1, gmin becomes origin)
924 */
925 SIM_hair_volume_grid_geometry(grid, &cellsize, nullptr, gmin, nullptr);
926 cell_scale = cellsize > 0.0f ? 1.0f / cellsize : 0.0f;
927 mul_v3_v3fl(cell_offset, gmin, cell_scale);
928 negate_v3(cell_offset);
929
930 link = cloth->springs;
931 while (link) {
932 ClothSpring *spring = (ClothSpring *)link->link;
933 if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) {
934 link = cloth_continuum_add_hair_segments(grid, cell_scale, cell_offset, cloth, link);
935 }
936 else {
937 link = link->next;
938 }
939 }
940#endif
942}
943
944static void cloth_continuum_step(ClothModifierData *clmd, float dt)
945{
946 ClothSimSettings *parms = clmd->sim_parms;
947 Cloth *cloth = clmd->clothObject;
948 Implicit_Data *data = cloth->implicit;
949 int mvert_num = cloth->mvert_num;
950 ClothVertex *vert;
951
952 const float fluid_factor = 0.95f; /* blend between PIC and FLIP methods */
953 float smoothfac = parms->velocity_smooth;
954 /* XXX FIXME arbitrary factor!!! this should be based on some intuitive value instead,
955 * like number of hairs per cell and time decay instead of "strength"
956 */
957 float density_target = parms->density_target;
958 float density_strength = parms->density_strength;
959 blender::float3 gmin, gmax;
960 int i;
961
962 /* clear grid info */
964 zero_v3(clmd->hair_grid_min);
965 zero_v3(clmd->hair_grid_max);
966 clmd->hair_grid_cellsize = 0.0f;
967
968 hair_get_boundbox(clmd, gmin, gmax);
969
970 /* gather velocities & density */
971 if (smoothfac > 0.0f || density_strength > 0.0f) {
973 clmd->sim_parms->voxel_cell_size, gmin, gmax);
974
975 cloth_continuum_fill_grid(grid, cloth);
976
977 /* main hair continuum solver */
978 SIM_hair_volume_solve_divergence(grid, dt, density_target, density_strength);
979
980 for (i = 0, vert = cloth->verts; i < mvert_num; i++, vert++) {
981 float x[3], v[3], nv[3];
982
983 /* calculate volumetric velocity influence */
986
987 SIM_hair_volume_grid_velocity(grid, x, v, fluid_factor, nv);
988
989 interp_v3_v3v3(nv, v, nv, smoothfac);
990
991 /* apply on hair data */
993 }
994
995 /* store basic grid info in the modifier data */
997 &clmd->hair_grid_cellsize,
998 clmd->hair_grid_res,
999 clmd->hair_grid_min,
1000 clmd->hair_grid_max);
1001
1002#if 0 /* DEBUG hair velocity vector field */
1003 {
1004 const int size = 64;
1005 int i, j;
1006 float offset[3], a[3], b[3];
1007 const int axis = 0;
1008 const float shift = 0.0f;
1009
1010 copy_v3_v3(offset, clmd->hair_grid_min);
1011 zero_v3(a);
1012 zero_v3(b);
1013
1014 offset[axis] = shift * clmd->hair_grid_cellsize;
1015 a[(axis + 1) % 3] = clmd->hair_grid_max[(axis + 1) % 3] -
1016 clmd->hair_grid_min[(axis + 1) % 3];
1017 b[(axis + 2) % 3] = clmd->hair_grid_max[(axis + 2) % 3] -
1018 clmd->hair_grid_min[(axis + 2) % 3];
1019
1020 BKE_sim_debug_data_clear_category(clmd->debug_data, "grid velocity");
1021 for (j = 0; j < size; j++) {
1022 for (i = 0; i < size; i++) {
1023 float x[3], v[3], gvel[3], gvel_smooth[3], gdensity;
1024
1025 madd_v3_v3v3fl(x, offset, a, float(i) / float(size - 1));
1026 madd_v3_v3fl(x, b, float(j) / float(size - 1));
1027 zero_v3(v);
1028
1030 grid, x, &gdensity, gvel, gvel_smooth, nullptr, nullptr);
1031
1032# if 0
1034 clmd->debug_data, x, gdensity, 0.7, 0.3, 1, "grid density", i, j, 3111);
1035# endif
1036 if (!is_zero_v3(gvel) || !is_zero_v3(gvel_smooth)) {
1037 float dvel[3];
1038 sub_v3_v3v3(dvel, gvel_smooth, gvel);
1039# if 0
1041 clmd->debug_data, x, gvel, 0.4, 0, 1, "grid velocity", i, j, 3112);
1043 clmd->debug_data, x, gvel_smooth, 0.6, 1, 1, "grid velocity", i, j, 3113);
1044# endif
1046 clmd->debug_data, x, dvel, 0.4, 1, 0.7, "grid velocity", i, j, 3114);
1047# if 0
1048 if (gdensity > 0.0f) {
1049 float col0[3] = {0.0, 0.0, 0.0};
1050 float col1[3] = {0.0, 1.0, 0.0};
1051 float col[3];
1052
1054 col0,
1055 col1,
1056 std::clamp(gdensity * clmd->sim_parms->density_strength, 0.0, 1.0));
1057# if 0
1058 BKE_sim_debug_data_add_circle(clmd->debug_data,
1059 x,
1060 gdensity * clmd->sim_parms->density_strength,
1061 0,
1062 1,
1063 0.4,
1064 "grid velocity",
1065 i,
1066 j,
1067 3115);
1069 clmd->debug_data, x, col[0], col[1], col[2], "grid velocity", i, j, 3115);
1070# endif
1072 clmd->debug_data, x, 0.01f, col[0], col[1], col[2], "grid velocity", i, j, 3115);
1073 }
1074# endif
1075 }
1076 }
1077 }
1078 }
1079#endif
1080
1082 }
1083}
1084
1085#if 0
1086static void cloth_calc_volume_force(ClothModifierData *clmd)
1087{
1088 ClothSimSettings *parms = clmd->sim_parms;
1089 Cloth *cloth = clmd->clothObject;
1090 Implicit_Data *data = cloth->implicit;
1091 int mvert_num = cloth->mvert_num;
1092 ClothVertex *vert;
1093
1094 /* 2.0f is an experimental value that seems to give good results */
1095 float smoothfac = 2.0f * parms->velocity_smooth;
1096 float collfac = 2.0f * parms->collider_friction;
1097 float pressfac = parms->pressure;
1098 float minpress = parms->pressure_threshold;
1099 float gmin[3], gmax[3];
1100 int i;
1101
1102 hair_get_boundbox(clmd, gmin, gmax);
1103
1104 /* gather velocities & density */
1105 if (smoothfac > 0.0f || pressfac > 0.0f) {
1106 HairVertexGrid *vertex_grid = SIM_hair_volume_create_vertex_grid(
1107 clmd->sim_parms->voxel_res, gmin, gmax);
1108
1109 vert = cloth->verts;
1110 for (i = 0; i < mvert_num; i++, vert++) {
1111 float x[3], v[3];
1112
1113 if (vert->solver_index < 0) {
1114 copy_v3_v3(x, vert->x);
1115 copy_v3_v3(v, vert->v);
1116 }
1117 else {
1118 SIM_mass_spring_get_motion_state(data, vert->solver_index, x, v);
1119 }
1120 SIM_hair_volume_add_vertex(vertex_grid, x, v);
1121 }
1123
1124 vert = cloth->verts;
1125 for (i = 0; i < mvert_num; i++, vert++) {
1126 float x[3], v[3], f[3], dfdx[3][3], dfdv[3][3];
1127
1128 if (vert->solver_index < 0) {
1129 continue;
1130 }
1131
1132 /* calculate volumetric forces */
1133 SIM_mass_spring_get_motion_state(data, vert->solver_index, x, v);
1135 vertex_grid, x, v, smoothfac, pressfac, minpress, f, dfdx, dfdv);
1136 /* apply on hair data */
1137 SIM_mass_spring_force_extern(data, vert->solver_index, f, dfdx, dfdv);
1138 }
1139
1141 }
1142}
1143#endif
1144
1146{
1147 Cloth *cloth = clmd->clothObject;
1148 Implicit_Data *data = cloth->implicit;
1149 int i, mvert_num = cloth->mvert_num;
1150 float total[3] = {0.0f, 0.0f, 0.0f};
1151
1152 for (i = 0; i < mvert_num; i++) {
1153 float v[3], nv[3];
1154
1157
1158 sub_v3_v3(nv, v);
1159 add_v3_v3(total, nv);
1160 }
1161
1162 mul_v3_fl(total, 1.0f / dt / mvert_num);
1163
1164 /* Smooth the data using a running average to prevent instability.
1165 * This is effectively an abstraction of the wave propagation speed in fluid. */
1166 interp_v3_v3v3(cloth->average_acceleration, total, cloth->average_acceleration, powf(0.25f, dt));
1167}
1168
1170 Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt)
1171{
1172 Cloth *cloth = clmd->clothObject;
1173 Implicit_Data *id = cloth->implicit;
1174 ClothVertex *verts = cloth->verts;
1175 int mvert_num = cloth->mvert_num;
1176 const float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
1177 int i;
1178
1179 if (!(clmd->coll_parms->flags &
1181 {
1182 return;
1183 }
1184
1185 if (!clmd->clothObject->bvhtree) {
1186 return;
1187 }
1188
1190
1191 /* Update verts to current positions. */
1192 for (i = 0; i < mvert_num; i++) {
1194
1195 sub_v3_v3v3(verts[i].tv, verts[i].tx, verts[i].txold);
1196 zero_v3(verts[i].dcvel);
1197 }
1198
1200 depsgraph, ob, clmd, step / clmd->sim_parms->timescale, dt / clmd->sim_parms->timescale))
1201 {
1202 for (i = 0; i < mvert_num; i++) {
1203 if ((clmd->sim_parms->vgroup_mass > 0) && (verts[i].flags & CLOTH_VERT_FLAG_PINNED)) {
1204 continue;
1205 }
1206
1208 madd_v3_v3fl(verts[i].tv, verts[i].dcvel, time_multiplier);
1210 }
1211 }
1212}
1213
1215{
1216 ClothSolverResult *sres = clmd->solver_result;
1217
1218 sres->status = 0;
1219 sres->max_error = sres->min_error = sres->avg_error = 0.0f;
1220 sres->max_iterations = sres->min_iterations = 0;
1221 sres->avg_iterations = 0.0f;
1222}
1223
1225{
1226 ClothSolverResult *sres = clmd->solver_result;
1227
1228 if (sres->status) { /* already initialized ? */
1229 /* error only makes sense for successful iterations */
1230 if (result->status == SIM_SOLVER_SUCCESS) {
1231 sres->min_error = min_ff(sres->min_error, result->error);
1232 sres->max_error = max_ff(sres->max_error, result->error);
1233 sres->avg_error += result->error * dt;
1234 }
1235
1236 sres->min_iterations = min_ii(sres->min_iterations, result->iterations);
1237 sres->max_iterations = max_ii(sres->max_iterations, result->iterations);
1238 sres->avg_iterations += float(result->iterations) * dt;
1239 }
1240 else {
1241 /* error only makes sense for successful iterations */
1242 if (result->status == SIM_SOLVER_SUCCESS) {
1243 sres->min_error = sres->max_error = result->error;
1244 sres->avg_error += result->error * dt;
1245 }
1246
1247 sres->min_iterations = sres->max_iterations = result->iterations;
1248 sres->avg_iterations += float(result->iterations) * dt;
1249 }
1250
1251 sres->status |= result->status;
1252}
1253
1255 Depsgraph *depsgraph, Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
1256{
1257 /* Hair currently is a cloth sim in disguise ...
1258 * Collision detection and volumetrics work differently then.
1259 * Bad design, TODO
1260 */
1262 const bool is_hair = (clmd->hairdata != nullptr);
1263
1264 uint i = 0;
1265 float step = 0.0f, tf = clmd->sim_parms->timescale;
1266 Cloth *cloth = clmd->clothObject;
1267 ClothVertex *verts = cloth->verts /*, *cv*/;
1268 uint mvert_num = cloth->mvert_num;
1269 float dt = clmd->sim_parms->dt * clmd->sim_parms->timescale;
1270 Implicit_Data *id = cloth->implicit;
1271
1272 /* Hydrostatic pressure gradient of the fluid inside the object is affected by acceleration. */
1273 bool use_acceleration = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE) &&
1274 (clmd->sim_parms->fluid_density > 0);
1275
1277
1278 if (!clmd->solver_result) {
1279 clmd->solver_result = MEM_callocN<ClothSolverResult>("cloth solver result");
1280 }
1281 cloth_clear_result(clmd);
1282
1283 if (clmd->sim_parms->vgroup_mass > 0) { /* Do goal stuff. */
1284 for (i = 0; i < mvert_num; i++) {
1285 /* update velocities with constrained velocities from pinned verts */
1286 if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
1287 float v[3];
1288 sub_v3_v3v3(v, verts[i].xconst, verts[i].xold);
1289 // mul_v3_fl(v, clmd->sim_parms->stepsPerFrame);
1290 /* divide by time_scale to prevent constrained velocities from being multiplied */
1291 mul_v3_fl(v, 1.0f / clmd->sim_parms->time_scale);
1293 }
1294 }
1295 }
1296
1297 if (!use_acceleration) {
1299 }
1300
1301 while (step < tf) {
1303
1304 /* setup vertex constraints for pinned vertices */
1306
1307 /* initialize forces to zero */
1309
1310 /* calculate forces */
1311 cloth_calc_force(scene, clmd, frame, effectors, step);
1312
1313 /* calculate new velocity and position */
1315 cloth_record_result(clmd, &result, dt);
1316
1317 /* Calculate collision impulses. */
1318 cloth_solve_collisions(depsgraph, ob, clmd, step, dt);
1319
1320 if (is_hair) {
1321 cloth_continuum_step(clmd, dt);
1322 }
1323
1324 if (use_acceleration) {
1326 }
1327
1330
1331 /* move pinned verts to correct position */
1332 for (i = 0; i < mvert_num; i++) {
1333 if (clmd->sim_parms->vgroup_mass > 0) {
1334 if (verts[i].flags & CLOTH_VERT_FLAG_PINNED) {
1335 float x[3];
1336 /* divide by time_scale to prevent pinned vertices'
1337 * delta locations from being multiplied */
1339 x, verts[i].xold, verts[i].xconst, (step + dt) / clmd->sim_parms->time_scale);
1341 }
1342 }
1343
1344 SIM_mass_spring_get_motion_state(id, i, verts[i].txold, nullptr);
1345 }
1346
1347 step += dt;
1348 }
1349
1350 /* copy results back to cloth data */
1351 for (i = 0; i < mvert_num; i++) {
1353 copy_v3_v3(verts[i].txold, verts[i].x);
1354 }
1355
1356 return 1;
1357}
@ CLOTH_SPRING_TYPE_SEWING
Definition BKE_cloth.hh:190
@ CLOTH_SPRING_TYPE_SHEAR
Definition BKE_cloth.hh:187
@ CLOTH_SPRING_TYPE_BENDING_HAIR
Definition BKE_cloth.hh:191
@ CLOTH_SPRING_TYPE_STRUCTURAL
Definition BKE_cloth.hh:186
@ CLOTH_SPRING_TYPE_BENDING
Definition BKE_cloth.hh:188
@ CLOTH_SPRING_TYPE_INTERNAL
Definition BKE_cloth.hh:192
@ CLOTH_VERT_FLAG_PINNED
Definition BKE_cloth.hh:38
@ CLOTH_SPRING_FLAG_DEACTIVATE
Definition BKE_cloth.hh:197
@ CLOTH_SPRING_FLAG_NEEDED
Definition BKE_cloth.hh:198
int cloth_bvh_collision(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt)
#define BKE_sim_debug_data_add_dot(p, r, g, b, category,...)
Definition BKE_effect.h:238
void BKE_sim_debug_data_clear_category(const char *category)
Definition effect.cc:1370
#define BKE_sim_debug_data_add_vector(p, d, r, g, b, category,...)
Definition BKE_effect.h:258
#define BKE_sim_debug_data_add_line(p1, p2, r, g, b, category,...)
Definition BKE_effect.h:252
void BKE_effectors_apply(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *wind_force, float *impulse)
Definition effect.cc:1106
#define BKE_sim_debug_data_add_circle(p, radius, r, g, b, category,...)
Definition BKE_effect.h:245
void pd_point_from_loc(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point)
Definition effect.cc:414
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_INLINE
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
float volume_tri_tetrahedron_signed_v3_6x(const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:263
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
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 float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
MINLINE void zero_v3_int(int r[3])
MINLINE void negate_v3(float r[3])
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
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 normalize_v3(float n[3])
unsigned int uint
#define UNUSED_FUNCTION(x)
#define CLAMP_MAX(a, c)
#define INIT_MINMAX(min, max)
#define ELEM(...)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
@ CLOTH_BENDING_ANGULAR
@ CLOTH_COLLSETTINGS_FLAG_ENABLED
@ CLOTH_COLLSETTINGS_FLAG_SELF
@ CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL
@ CLOTH_SIMSETTINGS_FLAG_PRESSURE
@ CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS
Object is a sort of wrapper for general info.
@ PHYS_GLOBAL_GRAVITY
Read Guarded memory(de)allocation.
void SIM_cloth_solver_free(ClothModifierData *clmd)
BLI_INLINE void cloth_get_grid_location(Implicit_Data *data, float cell_scale, const float cell_offset[3], int index, float x[3], float v[3])
static void cloth_continuum_step(ClothModifierData *clmd, float dt)
static int UNUSED_FUNCTION cloth_calc_helper_forces(Object *, ClothModifierData *clmd, float(*initial_cos)[3], float, float dt)
static void cloth_continuum_fill_grid(HairGrid *grid, Cloth *cloth)
static void cloth_clear_result(ClothModifierData *clmd)
static float cloth_calc_average_pressure(ClothModifierData *clmd, const float *vertex_pressure)
static float cloth_calc_rest_volume(ClothModifierData *clmd)
static void cloth_calc_pressure_gradient(ClothModifierData *clmd, const float gradient_vector[3], float *r_vertex_pressure)
static int cloth_count_nondiag_blocks(Cloth *cloth)
int SIM_cloth_solver_init(Object *, ClothModifierData *clmd)
static void hair_get_boundbox(ClothModifierData *clmd, blender::float3 &gmin, blender::float3 &gmax)
static void cloth_calc_average_acceleration(ClothModifierData *clmd, float dt)
static bool cloth_get_pressure_weights(ClothModifierData *clmd, const blender::int3 &vert_tri, float *r_weights)
static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *result, float dt)
BLI_INLINE LinkNode * hair_spring_next(LinkNode *spring_link)
static void cloth_calc_force(Scene *scene, ClothModifierData *clmd, float, ListBase *effectors, float time)
BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
void SIM_cloth_solver_set_volume(ClothModifierData *clmd)
static void cloth_setup_constraints(ClothModifierData *clmd)
static float cloth_calc_volume(ClothModifierData *clmd)
void SIM_mass_spring_set_implicit_vertex_mass(Implicit_Data *data, int index, float mass)
static void cloth_solve_collisions(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt)
void SIM_cloth_solver_set_positions(ClothModifierData *clmd)
static float I3[3][3]
int SIM_cloth_solve(Depsgraph *depsgraph, Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
static LinkNode * cloth_continuum_add_hair_segments(HairGrid *grid, const float cell_scale, const float cell_offset[3], Cloth *cloth, LinkNode *spring_link)
@ SIM_SOLVER_SUCCESS
#define ZERO
Definition StrokeRep.cpp:88
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
nullptr float
#define powf(x, y)
static float verts[][3]
uint col
#define cos
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
void SIM_hair_volume_add_segment(HairGrid *grid, const float[3], const float[3], const float x2[3], const float v2[3], const float x3[3], const float v3[3], const float[3], const float[3], const float[3], const float[3], const float[3])
void SIM_hair_volume_grid_velocity(HairGrid *grid, const float x[3], const float v[3], float fluid_factor, float r_v[3])
void SIM_hair_volume_grid_interpolate(HairGrid *grid, const float x[3], float *density, float velocity[3], float velocity_smooth[3], float density_gradient[3], float velocity_gradient[3][3])
void SIM_hair_volume_grid_geometry(HairGrid *grid, float *cellsize, int res[3], float gmin[3], float gmax[3])
void SIM_hair_volume_free_vertex_grid(HairGrid *grid)
bool SIM_hair_volume_solve_divergence(HairGrid *grid, float, float target_density, float target_strength)
void SIM_hair_volume_add_vertex(HairGrid *grid, const float x[3], const float v[3])
HairGrid * SIM_hair_volume_create_vertex_grid(float cellsize, const float gmin[3], const float gmax[3])
void SIM_hair_volume_normalize_vertex_grid(HairGrid *grid)
void SIM_hair_volume_vertex_grid_forces(HairGrid *grid, const float x[3], const float v[3], float smoothfac, float pressurefac, float minpressure, float f[3], float dfdx[3][3], float dfdv[3][3])
void SIM_mass_spring_force_vertex_wind(struct Implicit_Data *data, int v, float radius, const float(*winvec)[3])
float SIM_tri_tetra_volume_signed_6x(struct Implicit_Data *data, int v1, int v2, int v3)
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_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)
float SIM_tri_area(struct Implicit_Data *data, int v1, int v2, int v3)
void SIM_mass_spring_set_vertex_mass(struct Implicit_Data *data, int index, float mass)
void SIM_mass_spring_force_face_extern(struct Implicit_Data *data, int v1, int v2, int v3, const float(*forcevec)[3])
void SIM_mass_spring_get_velocity(struct Implicit_Data *data, int index, float v[3])
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)
void SIM_mass_spring_get_new_position(struct Implicit_Data *data, int index, float x[3])
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])
bool SIM_mass_spring_force_spring_bending_hair(struct Implicit_Data *data, int i, int j, int k, const float target[3], float stiffness, float damping)
void SIM_mass_spring_force_pressure(struct Implicit_Data *data, int v1, int v2, int v3, float common_pressure, const float *vertex_pressure, const float weights[3])
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])
bool SIM_mass_spring_force_spring_angular(struct Implicit_Data *data, int i, int j, int *i_a, int *i_b, int len_a, int len_b, float restang, float stiffness, float damping)
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)
Implicit_Data * SIM_mass_spring_solver_create(int numverts, int numsprings)
void SIM_mass_spring_solver_free(Implicit_Data *id)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 fabs(const float2 a)
static ulong * next
void min_max(const T &value, T &min, T &max)
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
#define fabsf
float rot[3][3]
Definition BKE_cloth.hh:45
struct ClothSolverResult * solver_result
struct ClothHairData * hairdata
struct Cloth * clothObject
struct ClothSimSettings * sim_parms
struct ClothCollSettings * coll_parms
struct EffectorWeights * effector_weights
float ang_stiffness
Definition BKE_cloth.hh:133
float lin_stiffness
Definition BKE_cloth.hh:132
float target[3]
Definition BKE_cloth.hh:137
float restang
Definition BKE_cloth.hh:129
float restlen
Definition BKE_cloth.hh:128
float tv[3]
Definition BKE_cloth.hh:100
float x[3]
Definition BKE_cloth.hh:96
float v[3]
Definition BKE_cloth.hh:94
float tx[3]
Definition BKE_cloth.hh:98
float xconst[3]
Definition BKE_cloth.hh:95
float xold[3]
Definition BKE_cloth.hh:97
BVHTree * bvhtree
Definition BKE_cloth.hh:77
float initial_mesh_volume
Definition BKE_cloth.hh:83
ClothVertex * verts
Definition BKE_cloth.hh:69
float average_acceleration[3]
Definition BKE_cloth.hh:84
Implicit_Data * implicit
Definition BKE_cloth.hh:80
LinkNode * springs
Definition BKE_cloth.hh:70
unsigned int mvert_num
Definition BKE_cloth.hh:72
blender::int3 * vert_tris
Definition BKE_cloth.hh:79
unsigned int primitive_num
Definition BKE_cloth.hh:73
void * link
struct LinkNode * next
struct PhysicsSettings physics_settings
i
Definition text_draw.cc:230
uint len