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