Blender V5.0
cloth.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_cloth_types.h"
14#include "DNA_mesh_types.h"
15#include "DNA_meshdata_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_matrix.h"
22#include "BLI_math_rotation.h"
23#include "BLI_math_vector.h"
24#include "BLI_rand.h"
25
26#include "DEG_depsgraph.hh"
28
29#include "BKE_bvhutils.hh"
30#include "BKE_cloth.hh"
31#include "BKE_customdata.hh"
32#include "BKE_effect.h"
33#include "BKE_global.hh"
34#include "BKE_lib_id.hh"
35#include "BKE_mesh.hh"
36#include "BKE_modifier.hh"
37#include "BKE_pointcache.h"
38
39#include "SIM_mass_spring.h"
40
41// #include "BLI_time.h" /* timing for debug prints */
42
43/* ********** cloth engine ******* */
44/* Prototypes for internal functions.
45 */
46static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]);
47static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, const Mesh *mesh);
48static bool cloth_from_object(
49 Object *ob, ClothModifierData *clmd, const Mesh *mesh, float framenr, int first);
51static void cloth_update_verts(Object *ob, ClothModifierData *clmd, const Mesh *mesh);
52static void cloth_update_spring_lengths(ClothModifierData *clmd, const Mesh *mesh);
53static bool cloth_build_springs(ClothModifierData *clmd, const Mesh *mesh);
54static void cloth_apply_vgroup(ClothModifierData *clmd, const Mesh *mesh);
55
61
62/******************************************************************************
63 *
64 * External interface called by modifier.cc clothModifier functions.
65 *
66 ******************************************************************************/
67
69{
70 if (!clmd) {
71 return nullptr;
72 }
73
74 Cloth *cloth = clmd->clothObject;
75
76 if (!cloth) {
77 return nullptr;
78 }
79
80 ClothVertex *verts = cloth->verts;
81 const blender::int3 *vert_tris = cloth->vert_tris;
82
83 /* in the moment, return zero if no faces there */
84 if (!cloth->primitive_num) {
85 return nullptr;
86 }
87
88 /* Create quad-tree with k=26. */
89 BVHTree *bvhtree = BLI_bvhtree_new(cloth->primitive_num, epsilon, 4, 26);
90
91 /* fill tree */
92 if (clmd->hairdata == nullptr) {
93 for (int i = 0; i < cloth->primitive_num; i++) {
94 float co[3][3];
95
96 copy_v3_v3(co[0], verts[vert_tris[i][0]].xold);
97 copy_v3_v3(co[1], verts[vert_tris[i][1]].xold);
98 copy_v3_v3(co[2], verts[vert_tris[i][2]].xold);
99
100 BLI_bvhtree_insert(bvhtree, i, co[0], 3);
101 }
102 }
103 else {
104 const blender::int2 *edges = cloth->edges;
105
106 for (int i = 0; i < cloth->primitive_num; i++) {
107 float co[2][3];
108
109 copy_v3_v3(co[0], verts[edges[i][0]].xold);
110 copy_v3_v3(co[1], verts[edges[i][1]].xold);
111
112 BLI_bvhtree_insert(bvhtree, i, co[0], 2);
113 }
114 }
115
116 /* balance tree */
117 BLI_bvhtree_balance(bvhtree);
118
119 return bvhtree;
120}
121
123{
124 uint i = 0;
125 Cloth *cloth = clmd->clothObject;
126 BVHTree *bvhtree;
127 ClothVertex *verts = cloth->verts;
128
129 BLI_assert(!(clmd->hairdata != nullptr && self));
130
131 if (self) {
132 bvhtree = cloth->bvhselftree;
133 }
134 else {
135 bvhtree = cloth->bvhtree;
136 }
137
138 if (!bvhtree) {
139 return;
140 }
141
142 const blender::int3 *vert_tris = cloth->vert_tris;
143
144 /* update vertex position in bvh tree */
145 if (clmd->hairdata == nullptr) {
146 if (verts && vert_tris) {
147 for (i = 0; i < cloth->primitive_num; i++) {
148 float co[3][3], co_moving[3][3];
149 bool ret;
150
151 /* copy new locations into array */
152 if (moving) {
153 copy_v3_v3(co[0], verts[vert_tris[i][0]].txold);
154 copy_v3_v3(co[1], verts[vert_tris[i][1]].txold);
155 copy_v3_v3(co[2], verts[vert_tris[i][2]].txold);
156
157 /* update moving positions */
158 copy_v3_v3(co_moving[0], verts[vert_tris[i][0]].tx);
159 copy_v3_v3(co_moving[1], verts[vert_tris[i][1]].tx);
160 copy_v3_v3(co_moving[2], verts[vert_tris[i][2]].tx);
161
162 ret = BLI_bvhtree_update_node(bvhtree, i, co[0], co_moving[0], 3);
163 }
164 else {
165 copy_v3_v3(co[0], verts[vert_tris[i][0]].tx);
166 copy_v3_v3(co[1], verts[vert_tris[i][1]].tx);
167 copy_v3_v3(co[2], verts[vert_tris[i][2]].tx);
168
169 ret = BLI_bvhtree_update_node(bvhtree, i, co[0], nullptr, 3);
170 }
171
172 /* check if tree is already full */
173 if (ret == false) {
174 break;
175 }
176 }
177
179 }
180 }
181 else {
182 if (verts) {
183 const blender::int2 *edges = reinterpret_cast<const blender::int2 *>(cloth->edges);
184
185 for (i = 0; i < cloth->primitive_num; i++) {
186 float co[2][3];
187
188 copy_v3_v3(co[0], verts[edges[i][0]].tx);
189 copy_v3_v3(co[1], verts[edges[i][1]].tx);
190
191 if (!BLI_bvhtree_update_node(bvhtree, i, co[0], nullptr, 2)) {
192 break;
193 }
194 }
195
197 }
198 }
199}
200
201void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
202{
203 PTCacheID pid;
204
205 BKE_ptcache_id_from_cloth(&pid, ob, clmd);
206
207 /* don't do anything as long as we're in editmode! */
208 if (pid.cache->edit && ob->mode & OB_MODE_PARTICLE_EDIT) {
209 return;
210 }
211
213}
214
215static bool do_init_cloth(Object *ob, ClothModifierData *clmd, const Mesh *result, int framenr)
216{
217 PointCache *cache;
218
219 cache = clmd->point_cache;
220
221 /* initialize simulation data if it didn't exist already */
222 if (clmd->clothObject == nullptr) {
223 if (!cloth_from_object(ob, clmd, result, framenr, 1)) {
225 BKE_modifier_set_error(ob, &(clmd->modifier), "Cannot initialize cloth");
226 return false;
227 }
228
229 if (clmd->clothObject == nullptr) {
231 BKE_modifier_set_error(ob, &(clmd->modifier), "Null cloth object");
232 return false;
233 }
234
236
237 ClothSimSettings *parms = clmd->sim_parms;
240 {
242 }
243
244 clmd->clothObject->last_frame = MINFRAME - 1;
245 clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame;
246 }
247
248 return true;
249}
250
251static int do_step_cloth(
252 Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, const Mesh *result, int framenr)
253{
254 using namespace blender;
255 /* simulate 1 frame forward */
256 ClothVertex *verts = nullptr;
257 Cloth *cloth;
258 ListBase *effectors = nullptr;
259 uint i = 0;
260 int ret = 0;
261 bool vert_mass_changed = false;
262
263 cloth = clmd->clothObject;
264 verts = cloth->verts;
265 const Span<float3> positions = result->vert_positions();
266 vert_mass_changed = verts->mass != clmd->sim_parms->mass;
267
268 /* force any pinned verts to their constrained location. */
269 for (i = 0; i < clmd->clothObject->mvert_num; i++, verts++) {
270 /* save the previous position. */
271 copy_v3_v3(verts->xold, verts->xconst);
272 copy_v3_v3(verts->txold, verts->x);
273
274 /* Get the current position. */
275 copy_v3_v3(verts->xconst, positions[i]);
276 mul_m4_v3(ob->object_to_world().ptr(), verts->xconst);
277
278 if (vert_mass_changed) {
279 verts->mass = clmd->sim_parms->mass;
281 }
282 }
283
284 effectors = BKE_effectors_create(
285 depsgraph, ob, nullptr, clmd->sim_parms->effector_weights, false);
286
288 cloth_update_verts(ob, clmd, result);
289 }
290
291 /* Support for dynamic vertex groups, changing from frame to frame */
293
295 (clmd->sim_parms->vgroup_shrink > 0) || (clmd->sim_parms->shrink_min != 0.0f))
296 {
298 }
299
301
302 // TIMEIT_START(cloth_step)
303
304 /* call the solver. */
305 ret = SIM_cloth_solve(depsgraph, ob, framenr, clmd, effectors);
306
307 // TIMEIT_END(cloth_step)
308
309 BKE_effectors_free(effectors);
310
311 // printf ( "%f\n", ( float ) tval() );
312
313 return ret;
314}
315
316/************************************************
317 * clothModifier_do - main simulation function
318 ************************************************/
319
321 Depsgraph *depsgraph,
322 Scene *scene,
323 Object *ob,
324 const Mesh *mesh,
325 float (*vertexCos)[3])
326{
327 PointCache *cache;
328 PTCacheID pid;
329 float timescale;
330 int framenr, startframe, endframe;
331 int cache_result;
332
333 framenr = DEG_get_ctime(depsgraph);
334 cache = clmd->point_cache;
335
336 BKE_ptcache_id_from_cloth(&pid, ob, clmd);
337 BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
338 clmd->sim_parms->timescale = timescale * clmd->sim_parms->time_scale;
339
340 if (clmd->sim_parms->reset ||
341 (clmd->clothObject && mesh->verts_num != clmd->clothObject->mvert_num))
342 {
343 clmd->sim_parms->reset = 0;
344 cache->flag |= PTCACHE_OUTDATED;
346 BKE_ptcache_validate(cache, 0);
347 cache->last_exact = 0;
348 cache->flag &= ~PTCACHE_REDO_NEEDED;
349 }
350
351 /* simulation is only active during a specific period */
352 if (framenr < startframe) {
354 return;
355 }
356 framenr = std::min(framenr, endframe);
357
358 /* initialize simulation data if it didn't exist already */
359 if (!do_init_cloth(ob, clmd, mesh, framenr)) {
360 return;
361 }
362
363 if (framenr == startframe) {
365 do_init_cloth(ob, clmd, mesh, framenr);
366 BKE_ptcache_validate(cache, framenr);
367 cache->flag &= ~PTCACHE_REDO_NEEDED;
368 clmd->clothObject->last_frame = framenr;
369 return;
370 }
371
372 /* Since implicit sharing is introduced, mesh data can be moved to other places.
373 * Therefore some fields in simulation data need to be updated accordingly */
374 clmd->clothObject->edges = mesh->edges().data();
375
376 /* try to read from cache */
377 bool can_simulate = (framenr == clmd->clothObject->last_frame + 1) &&
378 !(cache->flag & PTCACHE_BAKED);
379
380 cache_result = BKE_ptcache_read(&pid, float(framenr) + scene->r.subframe, can_simulate);
381
382 if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED ||
383 (!can_simulate && cache_result == PTCACHE_READ_OLD))
384 {
386 cloth_to_object(ob, clmd, vertexCos);
387
388 BKE_ptcache_validate(cache, framenr);
389
390 if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) {
391 BKE_ptcache_write(&pid, framenr);
392 }
393
394 clmd->clothObject->last_frame = framenr;
395
396 return;
397 }
398 if (cache_result == PTCACHE_READ_OLD) {
400 }
401 else if (
402 /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */
403 /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED))
404 {
405 /* if baked and nothing in cache, do nothing */
407 return;
408 }
409
410 /* if on second frame, write cache for first frame */
411 if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0))
412 {
413 BKE_ptcache_write(&pid, startframe);
414 }
415
416 clmd->sim_parms->timescale *= framenr - cache->simframe;
417
418 /* do simulation */
419 BKE_ptcache_validate(cache, framenr);
420
421 if (!do_step_cloth(depsgraph, ob, clmd, mesh, framenr)) {
423 }
424 else {
425 BKE_ptcache_write(&pid, framenr);
426 }
427
428 cloth_to_object(ob, clmd, vertexCos);
429 clmd->clothObject->last_frame = framenr;
430}
431
433{
434 Cloth *cloth = nullptr;
435
436 if (!clmd) {
437 return;
438 }
439
440 cloth = clmd->clothObject;
441
442 if (cloth) {
444
445 /* Free the verts. */
446 MEM_SAFE_FREE(cloth->verts);
447 cloth->mvert_num = 0;
448
449 /* Free the springs. */
450 if (cloth->springs != nullptr) {
451 LinkNode *search = cloth->springs;
452 while (search) {
453 ClothSpring *spring = static_cast<ClothSpring *>(search->link);
454
455 MEM_SAFE_FREE(spring->pa);
456 MEM_SAFE_FREE(spring->pb);
457
458 MEM_freeN(spring);
459 search = search->next;
460 }
461 BLI_linklist_free(cloth->springs, nullptr);
462
463 cloth->springs = nullptr;
464 }
465
466 cloth->springs = nullptr;
467 cloth->numsprings = 0;
468
469 /* free BVH collision tree */
470 if (cloth->bvhtree) {
472 }
473
474 if (cloth->bvhselftree && cloth->bvhselftree != cloth->bvhtree) {
476 }
477
478 /* we save our faces for collision objects */
479 if (cloth->vert_tris) {
480 MEM_freeN(cloth->vert_tris);
481 }
482
483#if 0
484 if (clmd->clothObject->facemarks) {
485 MEM_freeN(clmd->clothObject->facemarks);
486 }
487#endif
488 MEM_delete(cloth);
489 clmd->clothObject = nullptr;
490 }
491}
492
494{
495 Cloth *cloth = nullptr;
496 if (G.debug & G_DEBUG_SIMDATA) {
497 printf("cloth_free_modifier_extern\n");
498 }
499
500 if (!clmd) {
501 return;
502 }
503
504 cloth = clmd->clothObject;
505
506 if (cloth) {
507 if (G.debug & G_DEBUG_SIMDATA) {
508 printf("cloth_free_modifier_extern in\n");
509 }
510
512
513 /* Free the verts. */
514 MEM_SAFE_FREE(cloth->verts);
515 cloth->mvert_num = 0;
516
517 /* Free the springs. */
518 if (cloth->springs != nullptr) {
519 LinkNode *search = cloth->springs;
520 while (search) {
521 ClothSpring *spring = static_cast<ClothSpring *>(search->link);
522
523 MEM_SAFE_FREE(spring->pa);
524 MEM_SAFE_FREE(spring->pb);
525
526 MEM_freeN(spring);
527 search = search->next;
528 }
529 BLI_linklist_free(cloth->springs, nullptr);
530
531 cloth->springs = nullptr;
532 }
533
534 cloth->springs = nullptr;
535 cloth->numsprings = 0;
536
537 /* free BVH collision tree */
538 if (cloth->bvhtree) {
540 }
541
542 if (cloth->bvhselftree && cloth->bvhselftree != cloth->bvhtree) {
544 }
545
546 /* we save our faces for collision objects */
547 if (cloth->vert_tris) {
548 MEM_freeN(cloth->vert_tris);
549 }
550
551#if 0
552 if (clmd->clothObject->facemarks) {
553 MEM_freeN(clmd->clothObject->facemarks);
554 }
555#endif
556 MEM_delete(cloth);
557 clmd->clothObject = nullptr;
558 }
559}
560
561/******************************************************************************
562 *
563 * Internal functions.
564 *
565 ******************************************************************************/
566
570static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexCos)[3])
571{
572 uint i = 0;
573 Cloth *cloth = clmd->clothObject;
574
575 if (clmd->clothObject) {
576 /* Inverse matrix is not up to date. */
577 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
578
579 for (i = 0; i < cloth->mvert_num; i++) {
580 copy_v3_v3(vertexCos[i], cloth->verts[i].x);
581 mul_m4_v3(ob->world_to_object().ptr(), vertexCos[i]); /* cloth is in global coords */
582 }
583 }
584}
585
587{
588 return (((clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) &&
589 (clmd->coll_parms->vgroup_selfcol > 0)) ||
591 (clmd->coll_parms->vgroup_objcol > 0)) ||
592 (clmd->sim_parms->vgroup_pressure > 0) || (clmd->sim_parms->vgroup_struct > 0) ||
593 (clmd->sim_parms->vgroup_bend > 0) || (clmd->sim_parms->vgroup_shrink > 0) ||
594 (clmd->sim_parms->vgroup_intern > 0) || (clmd->sim_parms->vgroup_mass > 0) ||
595 (clmd->sim_parms->vgroup_shear > 0));
596}
597
601static void cloth_apply_vgroup(ClothModifierData *clmd, const Mesh *mesh)
602{
603 if (!clmd || !mesh) {
604 return;
605 }
606
607 int mvert_num = mesh->verts_num;
608
610
611 const blender::Span<MDeformVert> dverts = mesh->deform_verts();
612
613 if (cloth_uses_vgroup(clmd)) {
614 for (int i = 0; i < mvert_num; i++, verts++) {
615
616 /* Reset Goal values to standard */
617 if (clmd->sim_parms->vgroup_mass > 0) {
618 verts->goal = clmd->sim_parms->defgoal;
619 }
620 else {
621 verts->goal = 0.0f;
622 }
623
624 /* Compute base cloth shrink weight */
625 verts->shrink_factor = 0.0f;
626
627 /* Reset vertex flags */
630
631 if (!dverts.is_empty()) {
632 const MDeformVert *dvert = &dverts[i];
633 for (int j = 0; j < dvert->totweight; j++) {
634 if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass - 1)) {
635 verts->goal = dvert->dw[j].weight;
636
637 // goalfac = 1.0f; /* UNUSED */
638
639 /* Kicking goal factor to simplify things...who uses that anyway? */
640 // ABS (clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal);
641
642 verts->goal = pow4f(verts->goal);
643 if (verts->goal >= SOFTGOALSNAP) {
645 }
646 }
647
648 if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_struct - 1)) {
649 verts->struct_stiff = dvert->dw[j].weight;
650 }
651
652 if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shear - 1)) {
653 verts->shear_stiff = dvert->dw[j].weight;
654 }
655
656 if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_bend - 1)) {
657 verts->bend_stiff = dvert->dw[j].weight;
658 }
659
660 if (dvert->dw[j].def_nr == (clmd->coll_parms->vgroup_selfcol - 1)) {
661 if (dvert->dw[j].weight > 0.0f) {
663 }
664 }
665
666 if (dvert->dw[j].def_nr == (clmd->coll_parms->vgroup_objcol - 1)) {
667 if (dvert->dw[j].weight > 0.0f) {
669 }
670 }
671
672 if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shrink - 1)) {
673 /* Used for linear interpolation between min and max
674 * shrink factor based on weight. */
675 verts->shrink_factor = dvert->dw[j].weight;
676 }
677
678 if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_intern - 1)) {
679 /* Used to define the stiffness weight on the internal spring connected to this vertex.
680 */
681 verts->internal_stiff = dvert->dw[j].weight;
682 }
683
684 if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_pressure - 1)) {
685 /* Used to define how much the pressure settings should affect the given vertex. */
686 verts->pressure_factor = dvert->dw[j].weight;
687 }
688 }
689 }
690 }
691 }
692}
693
694static float cloth_shrink_factor(ClothModifierData *clmd, ClothVertex *verts, int i1, int i2)
695{
696 /* Linear interpolation between min and max shrink factor based on weight. */
697 float base = 1.0f - clmd->sim_parms->shrink_min;
698 float shrink_factor_delta = clmd->sim_parms->shrink_min - clmd->sim_parms->shrink_max;
699
700 float k1 = base + shrink_factor_delta * verts[i1].shrink_factor;
701 float k2 = base + shrink_factor_delta * verts[i2].shrink_factor;
702
703 /* Use geometrical mean to average two factors since it behaves better
704 * for diagonals when a rectangle transforms into a trapezoid. */
705 return sqrtf(k1 * k2);
706}
707
709 Object *ob, ClothModifierData *clmd, const Mesh *mesh, float /*framenr*/, int first)
710{
711 using namespace blender;
712 int i = 0;
713 ClothVertex *verts = nullptr;
714 const float (*shapekey_rest)[3] = nullptr;
715 const float tnull[3] = {0, 0, 0};
716
717 /* If we have a clothObject, free it. */
718 if (clmd->clothObject != nullptr) {
720 if (G.debug & G_DEBUG_SIMDATA) {
721 printf("cloth_free_modifier cloth_from_object\n");
722 }
723 }
724
725 /* Allocate a new cloth object. */
726 clmd->clothObject = MEM_new<Cloth>(__func__);
727 if (clmd->clothObject) {
728 clmd->clothObject->old_solver_type = 255;
729 }
730 else {
731 BKE_modifier_set_error(ob, &(clmd->modifier), "Out of memory on allocating cloth object");
732 return false;
733 }
734
735 /* mesh input objects need Mesh */
736 if (!mesh) {
737 return false;
738 }
739
740 cloth_from_mesh(clmd, ob, mesh);
741
742 /* create springs */
743 clmd->clothObject->springs = nullptr;
744 clmd->clothObject->numsprings = -1;
745
746 if (clmd->sim_parms->shapekey_rest &&
748 {
749 shapekey_rest = static_cast<const float (*)[3]>(
751 }
752
753 const Span<float3> positions = mesh->vert_positions();
754
755 verts = clmd->clothObject->verts;
756
757 /* set initial values */
758 for (i = 0; i < mesh->verts_num; i++, verts++) {
759 if (first) {
760 copy_v3_v3(verts->x, positions[i]);
761
762 mul_m4_v3(ob->object_to_world().ptr(), verts->x);
763
764 if (shapekey_rest) {
765 copy_v3_v3(verts->xrest, shapekey_rest[i]);
766 mul_m4_v3(ob->object_to_world().ptr(), verts->xrest);
767 }
768 else {
769 copy_v3_v3(verts->xrest, verts->x);
770 }
771 }
772
773 /* no GUI interface yet */
774 verts->mass = clmd->sim_parms->mass;
775 verts->impulse_count = 0;
776
777 if (clmd->sim_parms->vgroup_mass > 0) {
778 verts->goal = clmd->sim_parms->defgoal;
779 }
780 else {
781 verts->goal = 0.0f;
782 }
783
784 verts->shrink_factor = 0.0f;
785
786 verts->flags = 0;
787 copy_v3_v3(verts->xold, verts->x);
788 copy_v3_v3(verts->xconst, verts->x);
789 copy_v3_v3(verts->txold, verts->x);
790 copy_v3_v3(verts->tx, verts->x);
791 mul_v3_fl(verts->v, 0.0f);
792
793 verts->impulse_count = 0;
794 copy_v3_v3(verts->impulse, tnull);
795 }
796
797 /* apply / set vertex groups */
798 /* has to be happen before springs are build! */
799 cloth_apply_vgroup(clmd, mesh);
800
801 if (!cloth_build_springs(clmd, mesh)) {
803 BKE_modifier_set_error(ob, &(clmd->modifier), "Cannot build springs");
804 return false;
805 }
806
807 /* init our solver */
808 SIM_cloth_solver_init(ob, clmd);
809
810 if (!first) {
812 }
813
815
816 if (compare_ff(clmd->coll_parms->selfepsilon, clmd->coll_parms->epsilon, 1e-6f)) {
817 /* Share the BVH tree if the epsilon is the same. */
819 }
820 else {
822 }
823
824 return true;
825}
826
827static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, const Mesh *mesh)
828{
829 const blender::Span<int> corner_verts = mesh->corner_verts();
830 const blender::Span<blender::int3> corner_tris = mesh->corner_tris();
831 const uint mvert_num = mesh->verts_num;
832
833 /* Allocate our vertices. */
834 clmd->clothObject->mvert_num = mvert_num;
836 __func__);
837 if (clmd->clothObject->verts == nullptr) {
839 BKE_modifier_set_error(ob, &(clmd->modifier), "Out of memory on allocating vertices");
840 return;
841 }
842
843 /* save face information */
844 if (clmd->hairdata == nullptr) {
845 clmd->clothObject->primitive_num = corner_tris.size();
846 }
847 else {
848 clmd->clothObject->primitive_num = mesh->edges_num;
849 }
850
851 clmd->clothObject->vert_tris = MEM_malloc_arrayN<blender::int3>(size_t(corner_tris.size()),
852 __func__);
853 if (clmd->clothObject->vert_tris == nullptr) {
855 BKE_modifier_set_error(ob, &(clmd->modifier), "Out of memory on allocating triangles");
856 return;
857 }
859 corner_verts, corner_tris, {clmd->clothObject->vert_tris, corner_tris.size()});
860
861 clmd->clothObject->edges = mesh->edges().data();
862
863 /* Free the springs since they can't be correct if the vertices
864 * changed.
865 */
866 if (clmd->clothObject->springs != nullptr) {
868 }
869}
870
871/* -------------------------------------------------------------------- */
874
876{
877 if (v0 < v1) {
878 spring->ij = v0;
879 spring->kl = v1;
880 }
881 else {
882 spring->ij = v1;
883 spring->kl = v0;
884 }
885}
886
887static void cloth_free_edgelist(LinkNodePair *edgelist, uint mvert_num)
888{
889 if (edgelist) {
890 for (uint i = 0; i < mvert_num; i++) {
891 BLI_linklist_free(edgelist[i].list, nullptr);
892 }
893
894 MEM_freeN(edgelist);
895 }
896}
897
899 LinkNodePair *edgelist,
900 BendSpringRef *spring_ref)
901{
902 if (cloth->springs != nullptr) {
903 LinkNode *search = cloth->springs;
904 while (search) {
905 ClothSpring *spring = static_cast<ClothSpring *>(search->link);
906
907 MEM_SAFE_FREE(spring->pa);
908 MEM_SAFE_FREE(spring->pb);
909
910 MEM_freeN(spring);
911 search = search->next;
912 }
913 BLI_linklist_free(cloth->springs, nullptr);
914
915 cloth->springs = nullptr;
916 }
917
918 cloth_free_edgelist(edgelist, cloth->mvert_num);
919
920 MEM_SAFE_FREE(spring_ref);
921
922 cloth->edgeset.clear();
923}
924
926 ClothVertex *verts, int i, int j, const int *inds, int len, float r_dir[3])
927{
928 float cent[3] = {0};
929 float fact = 1.0f / len;
930
931 for (int x = 0; x < len; x++) {
932 madd_v3_v3fl(cent, verts[inds[x]].xrest, fact);
933 }
934
935 normal_tri_v3(r_dir, verts[i].xrest, verts[j].xrest, cent);
936}
937
939 ClothVertex *verts, int i, int j, int *i_a, int *i_b, int len_a, int len_b)
940{
941 float dir_a[3], dir_b[3];
942 float tmp[3], vec_e[3];
943 float sin, cos;
944
945 /* Poly vectors. */
946 cloth_bend_poly_dir(verts, j, i, i_a, len_a, dir_a);
947 cloth_bend_poly_dir(verts, i, j, i_b, len_b, dir_b);
948
949 /* Edge vector. */
950 sub_v3_v3v3(vec_e, verts[i].xrest, verts[j].xrest);
951 normalize_v3(vec_e);
952
953 /* Compute angle. */
954 cos = dot_v3v3(dir_a, dir_b);
955
956 cross_v3_v3v3(tmp, dir_a, dir_b);
957 sin = dot_v3v3(tmp, vec_e);
958
959 return atan2f(sin, cos);
960}
961
963{
964 Cloth *cloth = clmd->clothObject;
965 LinkNode *search = nullptr;
966 float hair_frame[3][3], dir_old[3], dir_new[3];
967 int prev_mn; /* to find hair chains */
968
969 if (!clmd->hairdata) {
970 return;
971 }
972
973 /* XXX NOTE: we need to propagate frames from the root up,
974 * but structural hair springs are stored in reverse order.
975 * The bending springs however are then inserted in the same
976 * order as vertices again ...
977 * This messy situation can be resolved when solver data is
978 * generated directly from a dedicated hair system.
979 */
980
981 prev_mn = -1;
982 for (search = cloth->springs; search; search = search->next) {
983 ClothSpring *spring = static_cast<ClothSpring *>(search->link);
984 ClothHairData *hair_ij, *hair_kl;
985 bool is_root = spring->kl != prev_mn;
986
987 if (spring->type != CLOTH_SPRING_TYPE_BENDING_HAIR) {
988 continue;
989 }
990
991 hair_ij = &clmd->hairdata[spring->ij];
992 hair_kl = &clmd->hairdata[spring->kl];
993 if (is_root) {
994 /* initial hair frame from root orientation */
995 copy_m3_m3(hair_frame, hair_ij->rot);
996 /* surface normal is the initial direction,
997 * parallel transport then keeps it aligned to the hair direction
998 */
999 copy_v3_v3(dir_new, hair_frame[2]);
1000 }
1001
1002 copy_v3_v3(dir_old, dir_new);
1003 sub_v3_v3v3(dir_new, cloth->verts[spring->mn].x, cloth->verts[spring->kl].x);
1004 normalize_v3(dir_new);
1005
1006 /* get local targets for kl/mn vertices by putting rest targets into the current frame,
1007 * then multiply with the rest length to get the actual goals
1008 */
1009
1010 mul_v3_m3v3(spring->target, hair_frame, hair_kl->rest_target);
1011 mul_v3_fl(spring->target, spring->restlen);
1012
1013 /* move frame to next hair segment */
1014 cloth_parallel_transport_hair_frame(hair_frame, dir_old, dir_new);
1015
1016 prev_mn = spring->mn;
1017 }
1018}
1019
1021{
1022 Cloth *cloth = clmd->clothObject;
1023 LinkNode *search = nullptr;
1024 float hair_frame[3][3], dir_old[3], dir_new[3];
1025 int prev_mn; /* to find hair roots */
1026
1027 if (!clmd->hairdata) {
1028 return;
1029 }
1030
1031 /* XXX NOTE: we need to propagate frames from the root up,
1032 * but structural hair springs are stored in reverse order.
1033 * The bending springs however are then inserted in the same
1034 * order as vertices again ...
1035 * This messy situation can be resolved when solver data is
1036 * generated directly from a dedicated hair system.
1037 */
1038
1039 prev_mn = -1;
1040 for (search = cloth->springs; search; search = search->next) {
1041 ClothSpring *spring = static_cast<ClothSpring *>(search->link);
1042 ClothHairData *hair_ij, *hair_kl;
1043 bool is_root = spring->kl != prev_mn;
1044
1045 if (spring->type != CLOTH_SPRING_TYPE_BENDING_HAIR) {
1046 continue;
1047 }
1048
1049 hair_ij = &clmd->hairdata[spring->ij];
1050 hair_kl = &clmd->hairdata[spring->kl];
1051 if (is_root) {
1052 /* initial hair frame from root orientation */
1053 copy_m3_m3(hair_frame, hair_ij->rot);
1054 /* surface normal is the initial direction,
1055 * parallel transport then keeps it aligned to the hair direction
1056 */
1057 copy_v3_v3(dir_new, hair_frame[2]);
1058 }
1059
1060 copy_v3_v3(dir_old, dir_new);
1061 sub_v3_v3v3(dir_new, cloth->verts[spring->mn].xrest, cloth->verts[spring->kl].xrest);
1062 normalize_v3(dir_new);
1063
1064 /* dir expressed in the hair frame defines the rest target direction */
1065 copy_v3_v3(hair_kl->rest_target, dir_new);
1066 mul_transposed_m3_v3(hair_frame, hair_kl->rest_target);
1067
1068 /* move frame to next hair segment */
1069 cloth_parallel_transport_hair_frame(hair_frame, dir_old, dir_new);
1070
1071 prev_mn = spring->mn;
1072 }
1073}
1074
1075/* update stiffness if vertex group values are changing from frame to frame */
1077{
1078 Cloth *cloth = clmd->clothObject;
1079 LinkNode *search = nullptr;
1080
1081 search = cloth->springs;
1082 while (search) {
1083 ClothSpring *spring = static_cast<ClothSpring *>(search->link);
1084
1085 spring->lin_stiffness = 0.0f;
1086
1088 if (spring->type & CLOTH_SPRING_TYPE_BENDING) {
1089 spring->ang_stiffness = (cloth->verts[spring->kl].bend_stiff +
1090 cloth->verts[spring->ij].bend_stiff) /
1091 2.0f;
1092 }
1093 }
1094
1095 if (spring->type & CLOTH_SPRING_TYPE_STRUCTURAL) {
1096 spring->lin_stiffness = (cloth->verts[spring->kl].struct_stiff +
1097 cloth->verts[spring->ij].struct_stiff) /
1098 2.0f;
1099 }
1100 else if (spring->type & CLOTH_SPRING_TYPE_SHEAR) {
1101 spring->lin_stiffness = (cloth->verts[spring->kl].shear_stiff +
1102 cloth->verts[spring->ij].shear_stiff) /
1103 2.0f;
1104 }
1105 else if (spring->type == CLOTH_SPRING_TYPE_BENDING) {
1106 spring->lin_stiffness = (cloth->verts[spring->kl].bend_stiff +
1107 cloth->verts[spring->ij].bend_stiff) /
1108 2.0f;
1109 }
1110 else if (spring->type & CLOTH_SPRING_TYPE_INTERNAL) {
1111 spring->lin_stiffness = (cloth->verts[spring->kl].internal_stiff +
1112 cloth->verts[spring->ij].internal_stiff) /
1113 2.0f;
1114 }
1115 else if (spring->type == CLOTH_SPRING_TYPE_BENDING_HAIR) {
1116 ClothVertex *v1 = &cloth->verts[spring->ij];
1117 ClothVertex *v2 = &cloth->verts[spring->kl];
1118 if (clmd->hairdata) {
1119 /* copy extra hair data to generic cloth vertices */
1120 v1->bend_stiff = clmd->hairdata[spring->ij].bending_stiffness;
1121 v2->bend_stiff = clmd->hairdata[spring->kl].bending_stiffness;
1122 }
1123 spring->lin_stiffness = (v1->bend_stiff + v2->bend_stiff) / 2.0f;
1124 }
1125 else if (spring->type == CLOTH_SPRING_TYPE_GOAL) {
1126 /* WARNING: Appending NEW goal springs does not work
1127 * because implicit solver would need reset! */
1128
1129 /* Activate / Deactivate existing springs */
1130 if (!(cloth->verts[spring->ij].flags & CLOTH_VERT_FLAG_PINNED) &&
1131 (cloth->verts[spring->ij].goal > ALMOST_ZERO))
1132 {
1134 }
1135 else {
1137 }
1138 }
1139
1140 search = search->next;
1141 }
1142
1144}
1145
1146/* Update rest verts, for dynamically deformable cloth */
1147static void cloth_update_verts(Object *ob, ClothModifierData *clmd, const Mesh *mesh)
1148{
1149 using namespace blender;
1150 uint i = 0;
1151 const Span<float3> positions = mesh->vert_positions();
1153
1154 /* vertex count is already ensured to match */
1155 for (i = 0; i < mesh->verts_num; i++, verts++) {
1156 copy_v3_v3(verts->xrest, positions[i]);
1157 mul_m4_v3(ob->object_to_world().ptr(), verts->xrest);
1158 }
1159}
1160
1161/* Write rest vert locations to a copy of the mesh. */
1163{
1164 using namespace blender;
1165 Mesh *new_mesh = BKE_mesh_copy_for_eval(*mesh);
1167 MutableSpan<float3> positions = new_mesh->vert_positions_for_write();
1168
1169 /* vertex count is already ensured to match */
1170 for (const int i : positions.index_range()) {
1171 positions[i] = verts[i].xrest;
1172 }
1173 new_mesh->tag_positions_changed();
1174
1175 return new_mesh;
1176}
1177
1178/* Update spring rest length, for dynamically deformable cloth */
1180{
1181 Cloth *cloth = clmd->clothObject;
1182 LinkNode *search = cloth->springs;
1183 uint struct_springs = 0;
1184 uint i = 0;
1185 uint mvert_num = uint(mesh->verts_num);
1186 float shrink_factor;
1187
1188 clmd->sim_parms->avg_spring_len = 0.0f;
1189
1190 for (i = 0; i < mvert_num; i++) {
1191 cloth->verts[i].avg_spring_len = 0.0f;
1192 }
1193
1194 while (search) {
1195 ClothSpring *spring = static_cast<ClothSpring *>(search->link);
1196
1197 if (spring->type != CLOTH_SPRING_TYPE_SEWING) {
1200 {
1201 shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
1202 }
1203 else {
1204 shrink_factor = 1.0f;
1205 }
1206
1207 spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) *
1208 shrink_factor;
1209
1210 if (spring->type & CLOTH_SPRING_TYPE_BENDING) {
1211 spring->restang = cloth_spring_angle(
1212 cloth->verts, spring->ij, spring->kl, spring->pa, spring->pb, spring->la, spring->lb);
1213 }
1214 }
1215
1216 if (spring->type & CLOTH_SPRING_TYPE_STRUCTURAL) {
1217 clmd->sim_parms->avg_spring_len += spring->restlen;
1218 cloth->verts[spring->ij].avg_spring_len += spring->restlen;
1219 cloth->verts[spring->kl].avg_spring_len += spring->restlen;
1220 struct_springs++;
1221 }
1222
1223 search = search->next;
1224 }
1225
1226 if (struct_springs > 0) {
1227 clmd->sim_parms->avg_spring_len /= struct_springs;
1228 }
1229
1230 for (i = 0; i < mvert_num; i++) {
1231 if (cloth->verts[i].spring_count > 0) {
1232 cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49f /
1233 float(cloth->verts[i].spring_count);
1234 }
1235 }
1236}
1237
1238BLI_INLINE void cross_identity_v3(float r[3][3], const float v[3])
1239{
1240 zero_m3(r);
1241 r[0][1] = v[2];
1242 r[0][2] = -v[1];
1243 r[1][0] = -v[2];
1244 r[1][2] = v[0];
1245 r[2][0] = v[1];
1246 r[2][1] = -v[0];
1247}
1248
1249BLI_INLINE void madd_m3_m3fl(float r[3][3], const float m[3][3], float f)
1250{
1251 r[0][0] += m[0][0] * f;
1252 r[0][1] += m[0][1] * f;
1253 r[0][2] += m[0][2] * f;
1254 r[1][0] += m[1][0] * f;
1255 r[1][1] += m[1][1] * f;
1256 r[1][2] += m[1][2] * f;
1257 r[2][0] += m[2][0] * f;
1258 r[2][1] += m[2][1] * f;
1259 r[2][2] += m[2][2] * f;
1260}
1261
1263 const float dir_old[3],
1264 const float dir_new[3])
1265{
1266 float rot[3][3];
1267
1268 /* rotation between segments */
1269 rotation_between_vecs_to_mat3(rot, dir_old, dir_new);
1270
1271 /* rotate the frame */
1272 mul_m3_m3m3(mat, rot, mat);
1273}
1274
1275/* Add a shear and a bend spring between two verts within a face. */
1277 LinkNodePair *edgelist,
1278 const blender::Span<int> corner_verts,
1280 int i,
1281 int j,
1282 int k)
1283{
1284 Cloth *cloth = clmd->clothObject;
1285 ClothSpring *spring;
1286 const int *tmp_corner;
1287 float shrink_factor;
1288 int x, y;
1289
1290 /* Combined shear/bend properties. */
1291 spring = MEM_callocN<ClothSpring>("cloth spring");
1292
1293 if (!spring) {
1294 return false;
1295 }
1296
1297 spring_verts_ordered_set(spring, corner_verts[faces[i][j]], corner_verts[faces[i][k]]);
1298
1299 shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
1300 spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) *
1301 shrink_factor;
1302 spring->type |= CLOTH_SPRING_TYPE_SHEAR;
1303 spring->lin_stiffness = (cloth->verts[spring->kl].shear_stiff +
1304 cloth->verts[spring->ij].shear_stiff) /
1305 2.0f;
1306
1307 if (edgelist) {
1308 BLI_linklist_append(&edgelist[spring->ij], spring);
1309 BLI_linklist_append(&edgelist[spring->kl], spring);
1310 }
1311
1312 /* Bending specific properties. */
1315
1316 spring->la = k - j + 1;
1317 spring->lb = faces[i].size() - k + j + 1;
1318
1319 spring->pa = MEM_malloc_arrayN<int>(size_t(spring->la), "spring poly");
1320 if (!spring->pa) {
1321 return false;
1322 }
1323
1324 spring->pb = MEM_malloc_arrayN<int>(size_t(spring->lb), "spring poly");
1325 if (!spring->pb) {
1326 return false;
1327 }
1328
1329 tmp_corner = &corner_verts[faces[i].start()];
1330
1331 for (x = 0; x < spring->la; x++) {
1332 spring->pa[x] = tmp_corner[j + x];
1333 }
1334
1335 for (x = 0; x <= j; x++) {
1336 spring->pb[x] = tmp_corner[x];
1337 }
1338
1339 for (y = k; y < faces[i].size(); x++, y++) {
1340 spring->pb[x] = tmp_corner[y];
1341 }
1342
1343 spring->mn = -1;
1344
1345 spring->restang = cloth_spring_angle(
1346 cloth->verts, spring->ij, spring->kl, spring->pa, spring->pb, spring->la, spring->lb);
1347
1348 spring->ang_stiffness = (cloth->verts[spring->ij].bend_stiff +
1349 cloth->verts[spring->kl].bend_stiff) /
1350 2.0f;
1351 }
1352
1353 BLI_linklist_prepend(&cloth->springs, spring);
1354
1355 return true;
1356}
1357
1358BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const int *corner_verts)
1359{
1360 int *p = MEM_malloc_arrayN<int>(size_t(len), "spring poly");
1361
1362 if (!p) {
1363 return false;
1364 }
1365
1366 for (int i = 0; i < len; i++) {
1367 p[i] = corner_verts[i];
1368 }
1369
1370 *poly = p;
1371
1372 return true;
1373}
1374
1376 const blender::Span<blender::float3> vert_normals,
1377 uint v_idx,
1378 RNG *rng,
1379 float max_length,
1380 float max_diversion,
1381 bool check_normal,
1382 int *r_tar_v_idx)
1383{
1384 float co[3], no[3], new_co[3];
1385 float radius;
1386
1387 copy_v3_v3(co, treedata->vert_positions[v_idx]);
1388 negate_v3_v3(no, vert_normals[v_idx]);
1389
1390 float vec_len = sin(max_diversion);
1391 float offset[3];
1392
1393 offset[0] = 0.5f - BLI_rng_get_float(rng);
1394 offset[1] = 0.5f - BLI_rng_get_float(rng);
1395 offset[2] = 0.5f - BLI_rng_get_float(rng);
1396
1397 normalize_v3(offset);
1398 mul_v3_fl(offset, vec_len);
1399 add_v3_v3(no, offset);
1400 normalize_v3(no);
1401
1402 /* Nudge the start point so we do not hit it with the ray. */
1403 copy_v3_v3(new_co, no);
1404 mul_v3_fl(new_co, FLT_EPSILON);
1405 add_v3_v3(new_co, co);
1406
1407 radius = 0.0f;
1408 if (max_length == 0.0f) {
1409 max_length = FLT_MAX;
1410 }
1411
1412 BVHTreeRayHit rayhit = {0};
1413 rayhit.index = -1;
1414 rayhit.dist = max_length;
1415
1417 treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata);
1418
1419 int vert_idx = -1;
1420 const int *corner_verts = treedata->corner_verts.data();
1421
1422 if (rayhit.index != -1 && rayhit.dist <= max_length) {
1423 if (check_normal && dot_v3v3(rayhit.no, no) < 0.0f) {
1424 /* We hit a point that points in the same direction as our starting point. */
1425 return false;
1426 }
1427
1428 float min_len = FLT_MAX;
1429 const blender::int3 &tri = treedata->corner_tris[rayhit.index];
1430
1431 for (int i = 0; i < 3; i++) {
1432 int tmp_vert_idx = corner_verts[tri[i]];
1433 if (tmp_vert_idx == v_idx) {
1434 /* We managed to hit ourselves. */
1435 return false;
1436 }
1437
1438 float len = len_v3v3(co, rayhit.co);
1439 if (len < min_len) {
1440 min_len = len;
1441 vert_idx = tmp_vert_idx;
1442 }
1443 }
1444
1445 *r_tar_v_idx = vert_idx;
1446 return true;
1447 }
1448
1449 return false;
1450}
1451
1452static bool cloth_build_springs(ClothModifierData *clmd, const Mesh *mesh)
1453{
1454 using namespace blender;
1455 using namespace blender::bke;
1456 Cloth *cloth = clmd->clothObject;
1457 ClothSpring *spring = nullptr, *tspring = nullptr, *tspring2 = nullptr;
1458 uint struct_springs = 0, shear_springs = 0, bend_springs = 0, struct_springs_real = 0;
1459 uint mvert_num = uint(mesh->verts_num);
1460 uint numedges = uint(mesh->edges_num);
1461 uint numface = uint(mesh->faces_num);
1462 float shrink_factor;
1463 const blender::Span<int2> edges = mesh->edges();
1464 const OffsetIndices faces = mesh->faces();
1465 const Span<int> corner_verts = mesh->corner_verts();
1466 const Span<int> corner_edges = mesh->corner_edges();
1467 int index2 = 0; /* our second vertex index */
1468 LinkNodePair *edgelist = nullptr;
1469 LinkNode *search = nullptr, *search2 = nullptr;
1470 BendSpringRef *spring_ref = nullptr;
1471
1472 /* error handling */
1473 if (numedges == 0) {
1474 return false;
1475 }
1476
1477 /* NOTE: handling ownership of springs and edgeset is quite sloppy
1478 * currently they are never initialized but assert just to be sure */
1479 BLI_assert(cloth->springs == nullptr);
1480 BLI_assert(cloth->edgeset.is_empty());
1481
1482 cloth->springs = nullptr;
1483
1485 spring_ref = MEM_calloc_arrayN<BendSpringRef>(numedges, __func__);
1486
1487 if (!spring_ref) {
1488 return false;
1489 }
1490 }
1491 else {
1492 edgelist = MEM_calloc_arrayN<LinkNodePair>(mvert_num, __func__);
1493
1494 if (!edgelist) {
1495 return false;
1496 }
1497 }
1498
1499 bool use_internal_springs = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS);
1500
1501 if (use_internal_springs && numface > 0) {
1502 int tar_v_idx;
1503 Mesh *tmp_mesh = nullptr;
1504 RNG *rng;
1505
1506 /* If using the rest shape key, it's necessary to make a copy of the mesh. */
1507 if (clmd->sim_parms->shapekey_rest &&
1509 {
1510 tmp_mesh = cloth_make_rest_mesh(clmd, mesh);
1511 }
1512
1513 Set<OrderedEdge> existing_vert_pairs;
1514 blender::bke::BVHTreeFromMesh treedata = tmp_mesh ? tmp_mesh->bvh_corner_tris() :
1515 mesh->bvh_corner_tris();
1516 rng = BLI_rng_new_srandom(0);
1517
1518 const blender::Span<blender::float3> vert_normals = tmp_mesh ? tmp_mesh->vert_normals() :
1519 mesh->vert_normals();
1520
1521 for (int i = 0; i < mvert_num; i++) {
1523 &treedata,
1524 vert_normals,
1525 i,
1526 rng,
1530 &tar_v_idx))
1531 {
1532 if (existing_vert_pairs.contains({i, tar_v_idx})) {
1533 /* We have already created a spring between these verts! */
1534 continue;
1535 }
1536
1537 existing_vert_pairs.add({i, tar_v_idx});
1538
1539 spring = MEM_callocN<ClothSpring>("cloth spring");
1540
1541 if (spring) {
1542 spring_verts_ordered_set(spring, i, tar_v_idx);
1543
1544 shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
1545 spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest,
1546 cloth->verts[spring->ij].xrest) *
1547 shrink_factor;
1548 spring->lin_stiffness = (cloth->verts[spring->kl].internal_stiff +
1549 cloth->verts[spring->ij].internal_stiff) /
1550 2.0f;
1552
1553 spring->flags = 0;
1554
1555 BLI_linklist_prepend(&cloth->springs, spring);
1556
1557 if (spring_ref) {
1558 spring_ref[i].spring = spring;
1559 }
1560 }
1561 else {
1562 cloth_free_errorsprings(cloth, edgelist, spring_ref);
1563 if (tmp_mesh) {
1564 BKE_id_free(nullptr, &tmp_mesh->id);
1565 }
1566 BLI_rng_free(rng);
1567 return false;
1568 }
1569 }
1570 }
1571 existing_vert_pairs.clear();
1572 if (tmp_mesh) {
1573 BKE_id_free(nullptr, &tmp_mesh->id);
1574 }
1575 BLI_rng_free(rng);
1576 }
1577
1578 clmd->sim_parms->avg_spring_len = 0.0f;
1579 for (int i = 0; i < mvert_num; i++) {
1580 cloth->verts[i].avg_spring_len = 0.0f;
1581 }
1582
1584 /* cloth->sew_edge_graph should not exist before this */
1586 }
1587
1588 /* Structural springs. */
1589 const LooseEdgeCache &loose_edges = mesh->loose_edges();
1590 for (int i = 0; i < numedges; i++) {
1591 spring = MEM_callocN<ClothSpring>("cloth spring");
1592
1593 if (spring) {
1594 spring_verts_ordered_set(spring, edges[i][0], edges[i][1]);
1595 if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW && loose_edges.count > 0 &&
1596 loose_edges.is_loose_bits[i])
1597 {
1598 /* handle sewing (loose edges will be pulled together) */
1599 spring->restlen = 0.0f;
1600 spring->lin_stiffness = 1.0f;
1602
1603 cloth->sew_edge_graph.add({edges[i][0], edges[i][1]});
1604 }
1605 else {
1606 shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
1607 spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest,
1608 cloth->verts[spring->ij].xrest) *
1609 shrink_factor;
1610 spring->lin_stiffness = (cloth->verts[spring->kl].struct_stiff +
1611 cloth->verts[spring->ij].struct_stiff) /
1612 2.0f;
1614
1615 clmd->sim_parms->avg_spring_len += spring->restlen;
1616 cloth->verts[spring->ij].avg_spring_len += spring->restlen;
1617 cloth->verts[spring->kl].avg_spring_len += spring->restlen;
1618 cloth->verts[spring->ij].spring_count++;
1619 cloth->verts[spring->kl].spring_count++;
1620 struct_springs_real++;
1621 }
1622
1623 spring->flags = 0;
1624 struct_springs++;
1625
1626 BLI_linklist_prepend(&cloth->springs, spring);
1627
1628 if (spring_ref) {
1629 spring_ref[i].spring = spring;
1630 }
1631 }
1632 else {
1633 cloth_free_errorsprings(cloth, edgelist, spring_ref);
1634 return false;
1635 }
1636 }
1637
1638 if (struct_springs_real > 0) {
1639 clmd->sim_parms->avg_spring_len /= struct_springs_real;
1640 }
1641
1642 for (int i = 0; i < mvert_num; i++) {
1643 if (cloth->verts[i].spring_count > 0) {
1644 cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49f /
1645 float(cloth->verts[i].spring_count);
1646 }
1647 }
1648
1649 cloth->edgeset.reserve(numedges);
1650
1651 if (numface) {
1652 for (int i = 0; i < numface; i++) {
1653 /* Shear springs. */
1654 /* Triangle faces already have shear springs due to structural geometry. */
1655 if (faces[i].size() > 3) {
1656 for (int j = 1; j < faces[i].size() - 1; j++) {
1657 if (j > 1) {
1658 if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, faces, i, 0, j)) {
1659 shear_springs++;
1660
1662 bend_springs++;
1663 }
1664 }
1665 else {
1666 cloth_free_errorsprings(cloth, edgelist, spring_ref);
1667 return false;
1668 }
1669 }
1670
1671 for (int k = j + 2; k < faces[i].size(); k++) {
1672 if (cloth_add_shear_bend_spring(clmd, edgelist, corner_verts, faces, i, j, k)) {
1673 shear_springs++;
1674
1676 bend_springs++;
1677 }
1678 }
1679 else {
1680 cloth_free_errorsprings(cloth, edgelist, spring_ref);
1681 return false;
1682 }
1683 }
1684 }
1685 }
1686
1687 /* Angular bending springs along struct springs. */
1689 for (int j = 0; j < faces[i].size(); j++) {
1690 const int edge_i = corner_edges[faces[i][j]];
1691 BendSpringRef *curr_ref = &spring_ref[edge_i];
1692 curr_ref->face++;
1693
1694 /* First poly found for this edge, store poly index. */
1695 if (curr_ref->face == 1) {
1696 curr_ref->index = i;
1697 }
1698 /* Second poly found for this edge, add bending data. */
1699 else if (curr_ref->face == 2) {
1700 spring = curr_ref->spring;
1701
1703
1704 spring->la = faces[curr_ref->index].size();
1705 spring->lb = faces[i].size();
1706
1708 &spring->pa, spring->la, &corner_verts[faces[curr_ref->index].start()]) ||
1710 &spring->pb, spring->lb, &corner_verts[faces[i].start()]))
1711 {
1712 cloth_free_errorsprings(cloth, edgelist, spring_ref);
1713 return false;
1714 }
1715
1716 spring->mn = edge_i;
1717
1718 spring->restang = cloth_spring_angle(cloth->verts,
1719 spring->ij,
1720 spring->kl,
1721 spring->pa,
1722 spring->pb,
1723 spring->la,
1724 spring->lb);
1725
1726 spring->ang_stiffness = (cloth->verts[spring->ij].bend_stiff +
1727 cloth->verts[spring->kl].bend_stiff) /
1728 2.0f;
1729
1730 bend_springs++;
1731 }
1732 /* Third poly found for this edge, remove bending data. */
1733 else if (curr_ref->face == 3) {
1734 spring = curr_ref->spring;
1735
1737 MEM_freeN(spring->pa);
1738 MEM_freeN(spring->pb);
1739 spring->pa = nullptr;
1740 spring->pb = nullptr;
1741
1742 bend_springs--;
1743 }
1744 }
1745 }
1746 }
1747
1748 /* Linear bending springs. */
1750 search2 = cloth->springs;
1751
1752 for (int i = struct_springs; i < struct_springs + shear_springs; i++) {
1753 if (!search2) {
1754 break;
1755 }
1756
1757 tspring2 = static_cast<ClothSpring *>(search2->link);
1758 search = edgelist[tspring2->kl].list;
1759
1760 while (search) {
1761 tspring = static_cast<ClothSpring *>(search->link);
1762 index2 = ((tspring->ij == tspring2->kl) ? (tspring->kl) : (tspring->ij));
1763
1764 /* Check for existing spring. */
1765 /* Check also if start-point is equal to endpoint. */
1766 if ((index2 != tspring2->ij) && !cloth->edgeset.contains({tspring2->ij, index2})) {
1767 spring = MEM_callocN<ClothSpring>("cloth spring");
1768
1769 if (!spring) {
1770 cloth_free_errorsprings(cloth, edgelist, spring_ref);
1771 return false;
1772 }
1773
1774 spring_verts_ordered_set(spring, tspring2->ij, index2);
1775 shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl);
1776 spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest,
1777 cloth->verts[spring->ij].xrest) *
1778 shrink_factor;
1780 spring->lin_stiffness = (cloth->verts[spring->kl].bend_stiff +
1781 cloth->verts[spring->ij].bend_stiff) /
1782 2.0f;
1783 cloth->edgeset.add({spring->ij, spring->kl});
1784 bend_springs++;
1785
1786 BLI_linklist_prepend(&cloth->springs, spring);
1787 }
1788
1789 search = search->next;
1790 }
1791
1792 search2 = search2->next;
1793 }
1794 }
1795 }
1796 else if (struct_springs > 2) {
1797 if (G.debug_value != 1112) {
1798 search = cloth->springs;
1799 search2 = search->next;
1800 while (search && search2) {
1801 tspring = static_cast<ClothSpring *>(search->link);
1802 tspring2 = static_cast<ClothSpring *>(search2->link);
1803
1804 if (tspring->ij == tspring2->kl) {
1805 spring = MEM_callocN<ClothSpring>("cloth spring");
1806
1807 if (!spring) {
1808 cloth_free_errorsprings(cloth, edgelist, spring_ref);
1809 return false;
1810 }
1811
1812 spring->ij = tspring2->ij;
1813 spring->kl = tspring->ij;
1814 spring->mn = tspring->kl;
1815 spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest,
1816 cloth->verts[spring->ij].xrest);
1818 spring->lin_stiffness = (cloth->verts[spring->kl].bend_stiff +
1819 cloth->verts[spring->ij].bend_stiff) /
1820 2.0f;
1821 bend_springs++;
1822
1823 BLI_linklist_prepend(&cloth->springs, spring);
1824 }
1825
1826 search = search->next;
1827 search2 = search2->next;
1828 }
1829 }
1830 else {
1831 /* bending springs for hair strands
1832 * The current algorithm only goes through the edges in order of the mesh edges list
1833 * and makes springs between the outer vert of edges sharing a vertex. This works just
1834 * fine for hair, but not for user generated string meshes. This could/should be later
1835 * extended to work with non-ordered edges so that it can be used for general "rope
1836 * dynamics" without the need for the vertices or edges to be ordered through the length
1837 * of the strands. -jahka */
1838 search = cloth->springs;
1839 search2 = search->next;
1840 while (search && search2) {
1841 tspring = static_cast<ClothSpring *>(search->link);
1842 tspring2 = static_cast<ClothSpring *>(search2->link);
1843
1844 if (tspring->ij == tspring2->kl) {
1845 spring = MEM_callocN<ClothSpring>("cloth spring");
1846
1847 if (!spring) {
1848 cloth_free_errorsprings(cloth, edgelist, spring_ref);
1849 return false;
1850 }
1851
1852 spring->ij = tspring2->ij;
1853 spring->kl = tspring->kl;
1854 spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest,
1855 cloth->verts[spring->ij].xrest);
1857 spring->lin_stiffness = (cloth->verts[spring->kl].bend_stiff +
1858 cloth->verts[spring->ij].bend_stiff) /
1859 2.0f;
1860 bend_springs++;
1861
1862 BLI_linklist_prepend(&cloth->springs, spring);
1863 }
1864
1865 search = search->next;
1866 search2 = search2->next;
1867 }
1868 }
1869
1871 }
1872
1873 /* NOTE: the edges may already exist so run reinsert. */
1874
1875 /* Insert other near springs in `edgeset` AFTER bending springs are calculated
1876 * (for self-collision). */
1877 for (int i = 0; i < numedges; i++) { /* struct springs */
1878 cloth->edgeset.add({edges[i][0], edges[i][1]});
1879 }
1880
1881 for (int i = 0; i < numface; i++) { /* edge springs */
1882 if (faces[i].size() == 4) {
1883 cloth->edgeset.add({corner_verts[faces[i].start() + 0], corner_verts[faces[i].start() + 2]});
1884 cloth->edgeset.add({corner_verts[faces[i].start() + 1], corner_verts[faces[i].start() + 3]});
1885 }
1886 }
1887
1888 MEM_SAFE_FREE(spring_ref);
1889
1890 cloth->numsprings = struct_springs + shear_springs + bend_springs;
1891
1892 cloth_free_edgelist(edgelist, mvert_num);
1893
1894#if 0
1895 if (G.debug_value > 0) {
1896 printf("avg_len: %f\n", clmd->sim_parms->avg_spring_len);
1897 }
1898#endif
1899
1900 return true;
1901}
1902
@ 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_GOAL
Definition BKE_cloth.hh:189
@ CLOTH_SPRING_TYPE_INTERNAL
Definition BKE_cloth.hh:192
@ CLOTH_VERT_FLAG_PINNED
Definition BKE_cloth.hh:38
@ CLOTH_VERT_FLAG_NOSELFCOLL
Definition BKE_cloth.hh:39
@ CLOTH_VERT_FLAG_NOOBJCOLL
Definition BKE_cloth.hh:40
@ CLOTH_SPRING_FLAG_DEACTIVATE
Definition BKE_cloth.hh:197
#define SOFTGOALSNAP
Definition BKE_cloth.hh:30
#define ALMOST_ZERO
Definition BKE_cloth.hh:34
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
void BKE_effectors_free(struct ListBase *lb)
Definition effect.cc:361
struct ListBase * BKE_effectors_create(struct Depsgraph *depsgraph, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool use_rotation)
Definition effect.cc:306
@ G_DEBUG_SIMDATA
void BKE_id_free(Main *bmain, void *idv)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
#define PTCACHE_CLEAR_AFTER
void BKE_ptcache_validate(struct PointCache *cache, int framenr)
#define PTCACHE_READ_INTERPOLATED
#define PTCACHE_READ_OLD
int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd)
int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
#define PTCACHE_RESET_OUTDATED
int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *pid, int mode)
void BKE_ptcache_invalidate(struct PointCache *cache)
#define PTCACHE_READ_EXACT
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_INLINE
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
void BLI_bvhtree_balance(BVHTree *tree)
void BLI_bvhtree_update_tree(BVHTree *tree)
void BLI_bvhtree_free(BVHTree *tree)
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints)
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
MINLINE int compare_ff(float a, float b, float max_diff)
MINLINE float pow4f(float x)
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:41
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void zero_m3(float m[3][3])
void mul_m4_v3(const float M[4][4], float r[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
void mul_transposed_m3_v3(const float M[3][3], float r[3])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3])
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_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
Random number functions.
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:53
struct RNG * BLI_rng_new_srandom(unsigned int seed)
Definition rand.cc:46
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:88
unsigned int uint
float DEG_get_ctime(const Depsgraph *graph)
@ CLOTH_BENDING_LINEAR
@ CLOTH_BENDING_ANGULAR
@ CLOTH_COLLSETTINGS_FLAG_ENABLED
@ CLOTH_COLLSETTINGS_FLAG_SELF
@ CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH
@ CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS_NORMAL
@ CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL
@ CLOTH_SIMSETTINGS_FLAG_SEW
@ CLOTH_SIMSETTINGS_FLAG_PRESSURE
@ CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS
@ CD_CLOTH_ORCO
@ OB_MODE_PARTICLE_EDIT
Object is a sort of wrapper for general info.
@ PTCACHE_BAKED
@ PTCACHE_OUTDATED
@ PTCACHE_REDO_NEEDED
#define MINFRAME
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void SIM_cloth_solver_free(ClothModifierData *clmd)
int SIM_cloth_solver_init(Object *, ClothModifierData *clmd)
void SIM_cloth_solver_set_volume(ClothModifierData *clmd)
void SIM_mass_spring_set_implicit_vertex_mass(Implicit_Data *data, int index, float mass)
void SIM_cloth_solver_set_positions(ClothModifierData *clmd)
int SIM_cloth_solve(Depsgraph *depsgraph, Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
PyObject * self
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
void reserve(const int64_t n)
Definition BLI_set.hh:637
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
bool is_empty() const
Definition BLI_set.hh:595
void clear()
Definition BLI_set.hh:551
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr bool is_empty() const
Definition BLI_span.hh:260
nullptr float
static int do_step_cloth(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, const Mesh *result, int framenr)
Definition cloth.cc:251
static bool cloth_build_springs(ClothModifierData *clmd, const Mesh *mesh)
Definition cloth.cc:1452
static float cloth_spring_angle(ClothVertex *verts, int i, int j, int *i_a, int *i_b, int len_a, int len_b)
Definition cloth.cc:938
BLI_INLINE void cross_identity_v3(float r[3][3], const float v[3])
Definition cloth.cc:1238
static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, const Mesh *mesh)
Definition cloth.cc:827
void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
Definition cloth.cc:201
BLI_INLINE void cloth_bend_poly_dir(ClothVertex *verts, int i, int j, const int *inds, int len, float r_dir[3])
Definition cloth.cc:925
static void cloth_to_object(Object *ob, ClothModifierData *clmd, float(*vertexCos)[3])
Definition cloth.cc:570
static void cloth_free_edgelist(LinkNodePair *edgelist, uint mvert_num)
Definition cloth.cc:887
static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, LinkNodePair *edgelist, const blender::Span< int > corner_verts, const blender::OffsetIndices< int > faces, int i, int j, int k)
Definition cloth.cc:1276
static float cloth_shrink_factor(ClothModifierData *clmd, ClothVertex *verts, int i1, int i2)
Definition cloth.cc:694
BLI_INLINE void madd_m3_m3fl(float r[3][3], const float m[3][3], float f)
Definition cloth.cc:1249
static void cloth_update_spring_lengths(ClothModifierData *clmd, const Mesh *mesh)
Definition cloth.cc:1179
static void cloth_hair_update_bending_rest_targets(ClothModifierData *clmd)
Definition cloth.cc:1020
static void cloth_hair_update_bending_targets(ClothModifierData *clmd)
Definition cloth.cc:962
void cloth_free_modifier_extern(ClothModifierData *clmd)
Definition cloth.cc:493
void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving, bool self)
Definition cloth.cc:122
void clothModifier_do(ClothModifierData *clmd, Depsgraph *depsgraph, Scene *scene, Object *ob, const Mesh *mesh, float(*vertexCos)[3])
Definition cloth.cc:320
static void cloth_update_verts(Object *ob, ClothModifierData *clmd, const Mesh *mesh)
Definition cloth.cc:1147
int cloth_uses_vgroup(ClothModifierData *clmd)
Definition cloth.cc:586
static void cloth_update_springs(ClothModifierData *clmd)
Definition cloth.cc:1076
void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3])
Definition cloth.cc:1262
BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const int *corner_verts)
Definition cloth.cc:1358
static Mesh * cloth_make_rest_mesh(ClothModifierData *clmd, const Mesh *mesh)
Definition cloth.cc:1162
BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1)
Definition cloth.cc:875
static void cloth_apply_vgroup(ClothModifierData *clmd, const Mesh *mesh)
Definition cloth.cc:601
static bool find_internal_spring_target_vertex(blender::bke::BVHTreeFromMesh *treedata, const blender::Span< blender::float3 > vert_normals, uint v_idx, RNG *rng, float max_length, float max_diversion, bool check_normal, int *r_tar_v_idx)
Definition cloth.cc:1375
static bool cloth_from_object(Object *ob, ClothModifierData *clmd, const Mesh *mesh, float framenr, int first)
Definition cloth.cc:708
static void cloth_free_errorsprings(Cloth *cloth, LinkNodePair *edgelist, BendSpringRef *spring_ref)
Definition cloth.cc:898
void cloth_free_modifier(ClothModifierData *clmd)
Definition cloth.cc:432
static BVHTree * bvhtree_build_from_cloth(ClothModifierData *clmd, float epsilon)
Definition cloth.cc:68
static bool do_init_cloth(Object *ob, ClothModifierData *clmd, const Mesh *result, int framenr)
Definition cloth.cc:215
#define rot(x, k)
static float verts[][3]
#define printf(...)
#define sin
#define cos
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
static char faces[256]
#define G(x, y, z)
void vert_tris_from_corner_tris(Span< int > corner_verts, Span< int3 > corner_tris, MutableSpan< int3 > vert_tris)
VecBase< int32_t, 2 > int2
VecBase< int32_t, 3 > int3
return ret
#define sqrtf
#define atan2f
#define FLT_MAX
Definition stdcycles.h:14
ClothSpring * spring
Definition cloth.cc:59
float bending_stiffness
Definition BKE_cloth.hh:48
float rest_target[3]
Definition BKE_cloth.hh:46
float rot[3][3]
Definition BKE_cloth.hh:45
struct ClothHairData * hairdata
struct Cloth * clothObject
struct PointCache * point_cache
struct ClothSimSettings * sim_parms
struct ClothCollSettings * coll_parms
struct EffectorWeights * effector_weights
float internal_spring_max_diversion
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 bend_stiff
Definition BKE_cloth.hh:109
float avg_spring_len
Definition BKE_cloth.hh:107
float x[3]
Definition BKE_cloth.hh:96
float internal_stiff
Definition BKE_cloth.hh:113
float shear_stiff
Definition BKE_cloth.hh:110
float xrest[3]
Definition BKE_cloth.hh:104
float struct_stiff
Definition BKE_cloth.hh:108
blender::Set< blender::OrderedEdge > edgeset
Definition BKE_cloth.hh:81
BVHTree * bvhtree
Definition BKE_cloth.hh:77
ClothVertex * verts
Definition BKE_cloth.hh:69
BVHTree * bvhselftree
Definition BKE_cloth.hh:78
unsigned int numsprings
Definition BKE_cloth.hh:71
Implicit_Data * implicit
Definition BKE_cloth.hh:80
LinkNode * springs
Definition BKE_cloth.hh:70
unsigned int mvert_num
Definition BKE_cloth.hh:72
unsigned char old_solver_type
Definition BKE_cloth.hh:74
int last_frame
Definition BKE_cloth.hh:82
const blender::int2 * edges
Definition BKE_cloth.hh:85
blender::int3 * vert_tris
Definition BKE_cloth.hh:79
blender::Set< blender::OrderedEdge > sew_edge_graph
Definition BKE_cloth.hh:86
unsigned int primitive_num
Definition BKE_cloth.hh:73
LinkNode * list
void * link
struct LinkNode * next
struct MDeformWeight * dw
unsigned int def_nr
int edges_num
CustomData vert_data
int verts_num
ObjectRuntimeHandle * runtime
struct PointCache * cache
struct PTCacheEdit * edit
Definition rand.cc:33
struct RenderData r
BVHTree_RayCastCallback raycast_callback
blender::BitVector is_loose_bits
i
Definition text_draw.cc:230
uint len