Blender V5.0
softbody.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
25
26#include <algorithm>
27#include <cmath>
28#include <cstdlib>
29#include <cstring>
30
31#include "CLG_log.h"
32
33#include "MEM_guardedalloc.h"
34
35/* types */
37#include "DNA_curve_types.h"
38#include "DNA_lattice_types.h"
39#include "DNA_mesh_types.h"
40#include "DNA_meshdata_types.h"
42#include "DNA_object_types.h"
43#include "DNA_scene_types.h"
44
45#include "BLI_ghash.h"
46#include "BLI_listbase.h"
47#include "BLI_math_geom.h"
48#include "BLI_math_matrix.h"
49#include "BLI_math_vector.h"
50#include "BLI_threads.h"
51#include "BLI_time.h"
52#include "BLI_utildefines.h"
53
54#include "BKE_collision.h"
55#include "BKE_curve.hh"
56#include "BKE_customdata.hh"
57#include "BKE_deform.hh"
58#include "BKE_effect.h"
59#include "BKE_global.hh"
60#include "BKE_layer.hh"
61#include "BKE_mesh.hh"
62#include "BKE_modifier.hh"
63#include "BKE_pointcache.h"
64#include "BKE_scene.hh"
65#include "BKE_softbody.h"
66
67#include "DEG_depsgraph.hh"
69
70static CLG_LogRef LOG = {"physics.softbody"};
71
72/* callbacks for errors and interrupts and some goo */
73static int (*SB_localInterruptCallBack)() = nullptr;
74
75/* ********** soft body engine ******* */
76
77enum type_spring { SB_EDGE = 1, SB_BEND = 2, SB_STIFFQUAD = 3, SB_HANDLE = 4 };
78
79struct BodySpring {
80 int v1, v2;
81 float len, cf, load;
82 float ext_force[3]; /* edges colliding and sailing */
84 short flag;
85};
86
87struct BodyFace {
88 int v1, v2, v3;
89 float ext_force[3]; /* faces colliding */
90 short flag;
91};
92
94 float pos[3]; /* position relative to com */
95 float mass; /* node mass */
96};
97
99 float com[3]; /* Center of mass. */
100 ReferenceVert *ivert; /* List of initial values. */
101};
102
103/* Private scratch pad for caching and other data only needed when alive. */
113
128
129#define MID_PRESERVE 1
130
131#define SOFTGOALSNAP 0.999f
132/* if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp
133 * removes *unnecessary* stiffness from ODE system
134 */
135#define HEUNWARNLIMIT 1 /* 500 would be fine i think for detecting severe *stiff* stuff */
136
137#define BSF_INTERSECT 1 /* edge intersects collider face */
138
139/* private definitions for body-point states */
140#define SBF_DOFUZZY 1 /* Body-point do fuzzy. */
141#define SBF_OUTOFCOLLISION 2 /* Body-point does not collide. */
142
143#define BFF_INTERSECT 1 /* collider edge intrudes face. */
144#define BFF_CLOSEVERT 2 /* collider vertex repulses face. */
145
146/* Hum .. this should be calculated from sb parameters and sizes. */
147static float SoftHeunTol = 1.0f;
148
149/* local prototypes */
150static void free_softbody_intern(SoftBody *sb);
151
152/*+++ frame based timing +++ */
153
154/* Physical unit of force is `kg * m / sec^2`. */
155
160static float sb_grav_force_scale(Object * /*ob*/)
161{
162 return (0.001f);
163}
164
169static float sb_fric_force_scale(Object * /*ob*/)
170{
171 return (0.01f);
172}
173
177static float sb_time_scale(Object *ob)
178{
179 SoftBody *sb = ob->soft; /* is supposed to be there */
180 if (sb) {
181 return (sb->physics_speed);
182 /* Hum .. this could be IPO as well :)
183 * estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
184 * 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames
185 * theory would give a 50 frames period .. so there must be something inaccurate ..
186 * looking for that (BM). */
187 }
188 return (1.0f);
189 /*
190 * this would be frames/sec independent timing assuming 25 fps is default
191 * but does not work very well with NLA
192 * return (25.0f/scene->r.frs_sec)
193 */
194}
195/*--- frame based timing ---*/
196
197/* helper functions for everything is animatable jow_go_for2_5 +++++++ */
198/* introducing them here, because i know: steps in properties ( at frame timing )
199 * will cause unwanted responses of the softbody system (which does inter frame calculations )
200 * so first 'cure' would be: interpolate linear in time ..
201 * Q: why do i write this?
202 * A: because it happened once, that some eager coder 'streamlined' code to fail.
203 * We DO linear interpolation for goals .. and i think we should do on animated properties as well
204 */
205
206/* animate sb->maxgoal, sb->mingoal */
207static float _final_goal(Object *ob, BodyPoint *bp) /* jow_go_for2_5 */
208{
209 float f = -1999.99f;
210 if (ob) {
211 SoftBody *sb = ob->soft; /* is supposed to be there */
212 if (!(ob->softflag & OB_SB_GOAL)) {
213 return (0.0f);
214 }
215 if (sb && bp) {
216 if (bp->goal < 0.0f) {
217 return (0.0f);
218 }
219 f = sb->mingoal + bp->goal * fabsf(sb->maxgoal - sb->mingoal);
220 f = pow(f, 4.0f);
221 return f;
222 }
223 }
224 CLOG_ERROR(&LOG, "sb or bp == NULL");
225 return f; /* Using crude but spot able values some times helps debugging. */
226}
227
228static float _final_mass(Object *ob, BodyPoint *bp)
229{
230 if (ob) {
231 SoftBody *sb = ob->soft; /* is supposed to be there */
232 if (sb && bp) {
233 return (bp->mass * sb->nodemass);
234 }
235 }
236 CLOG_ERROR(&LOG, "sb or bp == NULL");
237 return 1.0f;
238}
239/* Helper functions for everything is animatable jow_go_for2_5. */
240
241/* +++ collider caching and dicing +++ */
242
243/*
244 * for each target object/face the axis aligned bounding box (AABB) is stored
245 * faces parallel to global axes
246 * so only simple "value" in [min, max] checks are used
247 * float operations still
248 */
249
250/* Just an ID here to reduce the prob for killing objects
251 * `ob->sumohandle` points to we should not kill :)
252 */
253static const int CCD_SAFETY = 190561;
254
257};
258
259struct ccd_Mesh {
266 /* Axis Aligned Bounding Box AABB */
267 float bbmin[3];
268 float bbmax[3];
269};
270
272{
274 ccd_Mesh *pccd_M = nullptr;
275 CCDF_MinMax *mima;
276 float hull;
277 int i;
278
280
281 /* first some paranoia checks */
282 if (!cmd) {
283 return nullptr;
284 }
285 if (!cmd->mvert_num || !cmd->tri_num) {
286 return nullptr;
287 }
288
289 pccd_M = MEM_mallocN<ccd_Mesh>("ccd_Mesh");
290 pccd_M->mvert_num = cmd->mvert_num;
291 pccd_M->tri_num = cmd->tri_num;
292 pccd_M->safety = CCD_SAFETY;
293 pccd_M->bbmin[0] = pccd_M->bbmin[1] = pccd_M->bbmin[2] = 1e30f;
294 pccd_M->bbmax[0] = pccd_M->bbmax[1] = pccd_M->bbmax[2] = -1e30f;
295 pccd_M->vert_positions_prev = nullptr;
296
297 /* Blow it up with force-field ranges. */
298 hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
299
300 /* Allocate and copy verts. */
301 pccd_M->vert_positions = static_cast<const float (*)[3]>(MEM_dupallocN(cmd->xnew));
302 /* note that xnew coords are already in global space, */
303 /* determine the ortho BB */
304 for (i = 0; i < pccd_M->mvert_num; i++) {
305 const float *v;
306
307 /* evaluate limits */
308 v = pccd_M->vert_positions[i];
309 pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
310 pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
311 pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
312
313 pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
314 pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
315 pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
316 }
317 /* Allocate and copy faces. */
318 pccd_M->vert_tris = static_cast<const blender::int3 *>(MEM_dupallocN(cmd->vert_tris));
319
320 /* OBBs for idea1 */
321 pccd_M->mima = MEM_malloc_arrayN<CCDF_MinMax>(size_t(pccd_M->tri_num), "ccd_Mesh_Faces_mima");
322
323 /* Anyhow we need to walk the list of faces and find OBB they live in. */
324 for (i = 0, mima = pccd_M->mima; i < pccd_M->tri_num; i++, mima++) {
325 const float *v;
326
327 mima->minx = mima->miny = mima->minz = 1e30f;
328 mima->maxx = mima->maxy = mima->maxz = -1e30f;
329
330 v = pccd_M->vert_positions[pccd_M->vert_tris[i][0]];
331 mima->minx = min_ff(mima->minx, v[0] - hull);
332 mima->miny = min_ff(mima->miny, v[1] - hull);
333 mima->minz = min_ff(mima->minz, v[2] - hull);
334 mima->maxx = max_ff(mima->maxx, v[0] + hull);
335 mima->maxy = max_ff(mima->maxy, v[1] + hull);
336 mima->maxz = max_ff(mima->maxz, v[2] + hull);
337
338 v = pccd_M->vert_positions[pccd_M->vert_tris[i][1]];
339 mima->minx = min_ff(mima->minx, v[0] - hull);
340 mima->miny = min_ff(mima->miny, v[1] - hull);
341 mima->minz = min_ff(mima->minz, v[2] - hull);
342 mima->maxx = max_ff(mima->maxx, v[0] + hull);
343 mima->maxy = max_ff(mima->maxy, v[1] + hull);
344 mima->maxz = max_ff(mima->maxz, v[2] + hull);
345
346 v = pccd_M->vert_positions[pccd_M->vert_tris[i][2]];
347 mima->minx = min_ff(mima->minx, v[0] - hull);
348 mima->miny = min_ff(mima->miny, v[1] - hull);
349 mima->minz = min_ff(mima->minz, v[2] - hull);
350 mima->maxx = max_ff(mima->maxx, v[0] + hull);
351 mima->maxy = max_ff(mima->maxy, v[1] + hull);
352 mima->maxz = max_ff(mima->maxz, v[2] + hull);
353 }
354
355 return pccd_M;
356}
357static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
358{
360 CCDF_MinMax *mima;
361 float hull;
362 int i;
363
365
366 /* first some paranoia checks */
367 if (!cmd) {
368 return;
369 }
370 if (!cmd->mvert_num || !cmd->tri_num) {
371 return;
372 }
373
374 if ((pccd_M->mvert_num != cmd->mvert_num) || (pccd_M->tri_num != cmd->tri_num)) {
375 return;
376 }
377
378 pccd_M->bbmin[0] = pccd_M->bbmin[1] = pccd_M->bbmin[2] = 1e30f;
379 pccd_M->bbmax[0] = pccd_M->bbmax[1] = pccd_M->bbmax[2] = -1e30f;
380
381 /* Blow it up with force-field ranges. */
382 hull = max_ff(ob->pd->pdef_sbift, ob->pd->pdef_sboft);
383
384 /* rotate current to previous */
385 if (pccd_M->vert_positions_prev) {
387 }
388 pccd_M->vert_positions_prev = pccd_M->vert_positions;
389 /* Allocate and copy verts. */
390 pccd_M->vert_positions = static_cast<const float (*)[3]>(MEM_dupallocN(cmd->xnew));
391 /* note that xnew coords are already in global space, */
392 /* determine the ortho BB */
393 for (i = 0; i < pccd_M->mvert_num; i++) {
394 const float *v;
395
396 /* evaluate limits */
397 v = pccd_M->vert_positions[i];
398 pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
399 pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
400 pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
401
402 pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
403 pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
404 pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
405
406 /* evaluate limits */
407 v = pccd_M->vert_positions_prev[i];
408 pccd_M->bbmin[0] = min_ff(pccd_M->bbmin[0], v[0] - hull);
409 pccd_M->bbmin[1] = min_ff(pccd_M->bbmin[1], v[1] - hull);
410 pccd_M->bbmin[2] = min_ff(pccd_M->bbmin[2], v[2] - hull);
411
412 pccd_M->bbmax[0] = max_ff(pccd_M->bbmax[0], v[0] + hull);
413 pccd_M->bbmax[1] = max_ff(pccd_M->bbmax[1], v[1] + hull);
414 pccd_M->bbmax[2] = max_ff(pccd_M->bbmax[2], v[2] + hull);
415 }
416
417 /* Anyhow we need to walk the list of faces and find OBB they live in. */
418 for (i = 0, mima = pccd_M->mima; i < pccd_M->tri_num; i++, mima++) {
419 const float *v;
420
421 mima->minx = mima->miny = mima->minz = 1e30f;
422 mima->maxx = mima->maxy = mima->maxz = -1e30f;
423
424 /* vert_positions */
425 v = pccd_M->vert_positions[pccd_M->vert_tris[i][0]];
426 mima->minx = min_ff(mima->minx, v[0] - hull);
427 mima->miny = min_ff(mima->miny, v[1] - hull);
428 mima->minz = min_ff(mima->minz, v[2] - hull);
429 mima->maxx = max_ff(mima->maxx, v[0] + hull);
430 mima->maxy = max_ff(mima->maxy, v[1] + hull);
431 mima->maxz = max_ff(mima->maxz, v[2] + hull);
432
433 v = pccd_M->vert_positions[pccd_M->vert_tris[i][1]];
434 mima->minx = min_ff(mima->minx, v[0] - hull);
435 mima->miny = min_ff(mima->miny, v[1] - hull);
436 mima->minz = min_ff(mima->minz, v[2] - hull);
437 mima->maxx = max_ff(mima->maxx, v[0] + hull);
438 mima->maxy = max_ff(mima->maxy, v[1] + hull);
439 mima->maxz = max_ff(mima->maxz, v[2] + hull);
440
441 v = pccd_M->vert_positions[pccd_M->vert_tris[i][2]];
442 mima->minx = min_ff(mima->minx, v[0] - hull);
443 mima->miny = min_ff(mima->miny, v[1] - hull);
444 mima->minz = min_ff(mima->minz, v[2] - hull);
445 mima->maxx = max_ff(mima->maxx, v[0] + hull);
446 mima->maxy = max_ff(mima->maxy, v[1] + hull);
447 mima->maxz = max_ff(mima->maxz, v[2] + hull);
448
449 /* vert_positions_prev */
450 v = pccd_M->vert_positions_prev[pccd_M->vert_tris[i][0]];
451 mima->minx = min_ff(mima->minx, v[0] - hull);
452 mima->miny = min_ff(mima->miny, v[1] - hull);
453 mima->minz = min_ff(mima->minz, v[2] - hull);
454 mima->maxx = max_ff(mima->maxx, v[0] + hull);
455 mima->maxy = max_ff(mima->maxy, v[1] + hull);
456 mima->maxz = max_ff(mima->maxz, v[2] + hull);
457
458 v = pccd_M->vert_positions_prev[pccd_M->vert_tris[i][1]];
459 mima->minx = min_ff(mima->minx, v[0] - hull);
460 mima->miny = min_ff(mima->miny, v[1] - hull);
461 mima->minz = min_ff(mima->minz, v[2] - hull);
462 mima->maxx = max_ff(mima->maxx, v[0] + hull);
463 mima->maxy = max_ff(mima->maxy, v[1] + hull);
464 mima->maxz = max_ff(mima->maxz, v[2] + hull);
465
466 v = pccd_M->vert_positions_prev[pccd_M->vert_tris[i][2]];
467 mima->minx = min_ff(mima->minx, v[0] - hull);
468 mima->miny = min_ff(mima->miny, v[1] - hull);
469 mima->minz = min_ff(mima->minz, v[2] - hull);
470 mima->maxx = max_ff(mima->maxx, v[0] + hull);
471 mima->maxy = max_ff(mima->maxy, v[1] + hull);
472 mima->maxz = max_ff(mima->maxz, v[2] + hull);
473 }
474}
475
476static void ccd_mesh_free(ccd_Mesh *ccdm)
477{
478 /* Make sure we're not nuking objects we don't know. */
479 if (ccdm && (ccdm->safety == CCD_SAFETY)) {
481 MEM_freeN(ccdm->vert_tris);
482 if (ccdm->vert_positions_prev) {
484 }
485 MEM_freeN(ccdm->mima);
486 MEM_freeN(ccdm);
487 }
488}
489
491{
492 /* only with deflecting set */
493 if (ob->pd && ob->pd->deflect) {
494 void **val_p;
495 if (!BLI_ghash_ensure_p(hash, ob, &val_p)) {
496 ccd_Mesh *ccdmesh = ccd_mesh_make(ob);
497 *val_p = ccdmesh;
498 }
499 }
500}
501
505static void ccd_build_deflector_hash(Depsgraph *depsgraph,
506 Collection *collection,
507 Object *vertexowner,
508 GHash *hash)
509{
510 if (!hash) {
511 return;
512 }
513
514 uint numobjects;
516 depsgraph, vertexowner, collection, &numobjects, eModifierType_Collision);
517
518 for (int i = 0; i < numobjects; i++) {
519 Object *ob = objects[i];
520
521 if (ob->type == OB_MESH) {
523 }
524 }
525
527}
528
530{
531 if (ob->pd && ob->pd->deflect) {
532 ccd_Mesh *ccdmesh = static_cast<ccd_Mesh *>(BLI_ghash_lookup(hash, ob));
533 if (ccdmesh) {
534 ccd_mesh_update(ob, ccdmesh);
535 }
536 }
537}
538
543 Collection *collection,
544 Object *vertexowner,
545 GHash *hash)
546{
547 if ((!hash) || (!vertexowner)) {
548 return;
549 }
550
551 uint numobjects;
553 depsgraph, vertexowner, collection, &numobjects, eModifierType_Collision);
554
555 for (int i = 0; i < numobjects; i++) {
556 Object *ob = objects[i];
557
558 if (ob->type == OB_MESH) {
560 }
561 }
562
564}
565
566/*--- collider caching and dicing ---*/
567
568static int count_mesh_quads(Mesh *mesh)
569{
570 int result = 0;
571 const blender::OffsetIndices faces = mesh->faces();
572 for (const int i : faces.index_range()) {
573 if (faces[i].size() == 4) {
574 result++;
575 }
576 }
577 return result;
578}
579
581{
582 Mesh *mesh = static_cast<Mesh *>(ob->data);
583 // BodyPoint *bp; /* UNUSED */
584 if (ob->soft) {
585 int nofquads;
586 // float s_shear = ob->soft->shearstiff*ob->soft->shearstiff;
587
588 nofquads = count_mesh_quads(mesh);
589 if (nofquads) {
590 const blender::OffsetIndices faces = mesh->faces();
591 const blender::Span<int> corner_verts = mesh->corner_verts();
592 BodySpring *bs;
593
594 /* resize spring-array to hold additional quad springs */
595 ob->soft->bspring = static_cast<BodySpring *>(MEM_recallocN(
596 ob->soft->bspring, sizeof(BodySpring) * (ob->soft->totspring + nofquads * 2)));
597
598 /* fill the tail */
599 bs = &ob->soft->bspring[ob->soft->totspring];
600 // bp = ob->soft->bpoint; /* UNUSED */
601 for (int a = 0; a < mesh->faces_num; a++) {
602 const int poly_size = faces[a].size();
603 if (poly_size == 4) {
604 bs->v1 = corner_verts[faces[a].start() + 0];
605 bs->v2 = corner_verts[faces[a].start() + 2];
607 bs++;
608 bs->v1 = corner_verts[faces[a].start() + 1];
609 bs->v2 = corner_verts[faces[a].start() + 3];
611 bs++;
612 }
613 }
614
615 /* now we can announce new springs */
616 ob->soft->totspring += nofquads * 2;
617 }
618 }
619}
620
621static void add_2nd_order_roller(Object *ob, float /*stiffness*/, int *counter, int addsprings)
622{
623 /* Assume we have a softbody. */
624 SoftBody *sb = ob->soft; /* is supposed to be there */
625 BodyPoint *bp, *bpo;
626 BodySpring *bs, *bs2, *bs3 = nullptr;
627 int a, b, c, notthis = 0, v0;
628 if (!sb->bspring) {
629 return;
630 } /* we are 2nd order here so 1rst should have been build :) */
631 /* First run counting second run adding. */
632 *counter = 0;
633 if (addsprings) {
634 bs3 = ob->soft->bspring + ob->soft->totspring;
635 }
636 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
637 /* Scan for neighborhood. */
638 bpo = nullptr;
639 v0 = (sb->totpoint - a);
640 for (b = bp->nofsprings; b > 0; b--) {
641 bs = sb->bspring + bp->springs[b - 1];
642 /* Nasty thing here that springs have two ends
643 * so here we have to make sure we examine the other */
644 if (v0 == bs->v1) {
645 bpo = sb->bpoint + bs->v2;
646 notthis = bs->v2;
647 }
648 else {
649 if (v0 == bs->v2) {
650 bpo = sb->bpoint + bs->v1;
651 notthis = bs->v1;
652 }
653 else {
654 CLOG_ERROR(&LOG, "oops we should not get here");
655 }
656 }
657 if (bpo) { /* so now we have a 2nd order humpdidump */
658 for (c = bpo->nofsprings; c > 0; c--) {
659 bs2 = sb->bspring + bpo->springs[c - 1];
660 if ((bs2->v1 != notthis) && (bs2->v1 > v0)) {
661 (*counter)++; /* hit */
662 if (addsprings) {
663 bs3->v1 = v0;
664 bs3->v2 = bs2->v1;
665 bs3->springtype = SB_BEND;
666 bs3++;
667 }
668 }
669 if ((bs2->v2 != notthis) && (bs2->v2 > v0)) {
670 (*counter)++; /* hit */
671 if (addsprings) {
672 bs3->v1 = v0;
673 bs3->v2 = bs2->v2;
674 bs3->springtype = SB_BEND;
675 bs3++;
676 }
677 }
678 }
679 }
680 }
681 /* Scan for neighborhood done. */
682 }
683}
684
685static void add_2nd_order_springs(Object *ob, float stiffness)
686{
687 int counter = 0;
688 BodySpring *bs_new;
689 stiffness *= stiffness;
690
691 add_2nd_order_roller(ob, stiffness, &counter, 0); /* counting */
692 if (counter) {
693 /* resize spring-array to hold additional springs */
694 bs_new = MEM_calloc_arrayN<BodySpring>(size_t(ob->soft->totspring) + size_t(counter),
695 "bodyspring");
696 memcpy(bs_new, ob->soft->bspring, (ob->soft->totspring) * sizeof(BodySpring));
697
698 if (ob->soft->bspring) {
699 MEM_freeN(ob->soft->bspring);
700 }
701 ob->soft->bspring = bs_new;
702
703 add_2nd_order_roller(ob, stiffness, &counter, 1); /* adding */
704 ob->soft->totspring += counter;
705 }
706}
707
708static void add_bp_springlist(BodyPoint *bp, int springID)
709{
710 int *newlist;
711
712 if (bp->springs == nullptr) {
713 bp->springs = MEM_calloc_arrayN<int>(1, "bpsprings");
714 bp->springs[0] = springID;
715 bp->nofsprings = 1;
716 }
717 else {
718 bp->nofsprings++;
719 newlist = MEM_calloc_arrayN<int>(bp->nofsprings, "bpsprings");
720 memcpy(newlist, bp->springs, (bp->nofsprings - 1) * sizeof(int));
721 MEM_freeN(bp->springs);
722 bp->springs = newlist;
723 bp->springs[bp->nofsprings - 1] = springID;
724 }
725}
726
732{
733 SoftBody *sb = ob->soft; /* is supposed to be there */
734 BodyPoint *bp;
735 BodySpring *bs;
736 int a, b;
737
738 if (sb == nullptr) {
739 return; /* paranoia check */
740 }
741
742 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
743 /* throw away old list */
744 if (bp->springs) {
745 MEM_freeN(bp->springs);
746 bp->springs = nullptr;
747 }
748 /* scan for attached inner springs */
749 for (b = sb->totspring, bs = sb->bspring; b > 0; b--, bs++) {
750 if ((sb->totpoint - a) == bs->v1) {
751 add_bp_springlist(bp, sb->totspring - b);
752 }
753 if ((sb->totpoint - a) == bs->v2) {
754 add_bp_springlist(bp, sb->totspring - b);
755 }
756 } /* For springs. */
757 } /* For bp. */
758}
759
761{
762 SoftBody *sb = ob->soft; /* is supposed to be there */
763 BodyPoint *bp;
764 BodySpring *bs;
765 int a, b, akku_count;
766 float min, max, akku;
767
768 if (sb == nullptr) {
769 return; /* paranoia check */
770 }
771
772 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
773 bp->colball = 0;
774 akku = 0.0f;
775 akku_count = 0;
776 min = 1e22f;
777 max = -1e22f;
778 /* first estimation based on attached */
779 for (b = bp->nofsprings; b > 0; b--) {
780 bs = sb->bspring + bp->springs[b - 1];
781 if (bs->springtype == SB_EDGE) {
782 akku += bs->len;
783 akku_count++;
784 min = min_ff(bs->len, min);
785 max = max_ff(bs->len, max);
786 }
787 }
788
789 if (akku_count > 0) {
790 if (sb->sbc_mode == SBC_MODE_MANUAL) {
791 bp->colball = sb->colball;
792 }
793 if (sb->sbc_mode == SBC_MODE_AVG) {
794 bp->colball = akku / float(akku_count) * sb->colball;
795 }
796 if (sb->sbc_mode == SBC_MODE_MIN) {
797 bp->colball = min * sb->colball;
798 }
799 if (sb->sbc_mode == SBC_MODE_MAX) {
800 bp->colball = max * sb->colball;
801 }
802 if (sb->sbc_mode == SBC_MODE_AVGMINMAX) {
803 bp->colball = (min + max) / 2.0f * sb->colball;
804 }
805 }
806 else {
807 bp->colball = 0;
808 }
809 } /* For bp. */
810}
811
812/* creates new softbody if didn't exist yet, makes new points and springs arrays */
813static void renew_softbody(Object *ob, int totpoint, int totspring)
814{
815 SoftBody *sb;
816 int i;
817 short softflag;
818 if (ob->soft == nullptr) {
819 ob->soft = sbNew();
820 }
821 else {
823 }
824 sb = ob->soft;
825 softflag = ob->softflag;
826
827 if (totpoint) {
828 sb->totpoint = totpoint;
829 sb->totspring = totspring;
830
831 sb->bpoint = MEM_malloc_arrayN<BodyPoint>(size_t(totpoint), "bodypoint");
832 if (totspring) {
833 sb->bspring = MEM_malloc_arrayN<BodySpring>(size_t(totspring), "bodyspring");
834 }
835
836 /* initialize BodyPoint array */
837 for (i = 0; i < totpoint; i++) {
838 BodyPoint *bp = &sb->bpoint[i];
839
840 /* hum as far as i see this is overridden by _final_goal() now jow_go_for2_5 */
841 /* sadly breaks compatibility with older versions */
842 /* but makes goals behave the same for meshes, lattices and curves */
843 if (softflag & OB_SB_GOAL) {
844 bp->goal = sb->defgoal;
845 }
846 else {
847 bp->goal = 0.0f;
848 /* So this will definitely be below #SOFTGOALSNAP. */
849 }
850
851 bp->nofsprings = 0;
852 bp->springs = nullptr;
853 bp->choke = 0.0f;
854 bp->choke2 = 0.0f;
855 bp->frozen = 1.0f;
856 bp->colball = 0.0f;
857 bp->loc_flag = 0;
858 bp->springweight = 1.0f;
859 bp->mass = 1.0f;
860 }
861 }
862}
863
865{
866 SBVertex *key;
867 int k;
868
869 for (k = 0; k < sb->totkey; k++) {
870 key = *(sb->keys + k);
871 if (key) {
872 MEM_freeN(key);
873 }
874 }
875 MEM_SAFE_FREE(sb->keys);
876 sb->totkey = 0;
877}
878static void free_scratch(SoftBody *sb)
879{
880 if (sb->scratch) {
881 /* TODO: make sure everything is cleaned up nicely. */
882 if (sb->scratch->colliderhash) {
884 nullptr,
885 (GHashValFreeFP)ccd_mesh_free); /* This hopefully will free all caches. */
886 sb->scratch->colliderhash = nullptr;
887 }
888 if (sb->scratch->bodyface) {
890 }
891 if (sb->scratch->Ref.ivert) {
893 }
894 MEM_freeN(sb->scratch);
895 sb->scratch = nullptr;
896 }
897}
898
899/* only frees internal data */
901{
902 if (sb) {
903 int a;
904 BodyPoint *bp;
905
906 if (sb->bpoint) {
907 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
908 /* free spring list */
909 if (bp->springs != nullptr) {
910 MEM_freeN(bp->springs);
911 }
912 }
913 MEM_freeN(sb->bpoint);
914 }
915
916 if (sb->bspring) {
917 MEM_freeN(sb->bspring);
918 }
919
920 sb->totpoint = sb->totspring = 0;
921 sb->bpoint = nullptr;
922 sb->bspring = nullptr;
923
924 free_scratch(sb);
926 }
927}
928
929/* ************ dynamics ********** */
930
931/* the most general (micro physics correct) way to do collision
932 * (only needs the current particle position)
933 *
934 * it actually checks if the particle intrudes a short range force field generated
935 * by the faces of the target object and returns a force to drive the particle out
936 * the strength of the field grows exponentially if the particle is on the 'wrong' side of the face
937 * 'wrong' side : projection to the face normal is negative (all referred to a vertex in the face)
938 *
939 * flaw of this: 'fast' particles as well as 'fast' colliding faces
940 * give a 'tunnel' effect such that the particle passes through the force field
941 * without ever 'seeing' it
942 * this is fully compliant to heisenberg: h >= fuzzy(location) * fuzzy(time)
943 * besides our h is way larger than in QM because forces propagate way slower here
944 * we have to deal with fuzzy(time) in the range of 1/25 seconds (typical frame rate)
945 * yup collision targets are not known here any better
946 * and 1/25 second is very long compared to real collision events
947 * Q: why not use 'simple' collision here like bouncing back a particle
948 * --> reverting is velocity on the face normal
949 * A: because our particles are not alone here
950 * and need to tell their neighbors exactly what happens via spring forces
951 * unless sbObjectStep( .. ) is called on sub frame timing level
952 * BTW that also questions the use of a 'implicit' solvers on soft-bodies
953 * since that would only valid for 'slow' moving collision targets and ditto particles.
954 */
955
956/* +++ dependency information functions. */
957
961static int query_external_colliders(Depsgraph *depsgraph, Collection *collection)
962{
963 uint numobjects;
965 depsgraph, nullptr, collection, &numobjects, eModifierType_Collision);
967
968 return (numobjects != 0);
969}
970/* --- dependency information functions. */
971
972/* +++ the aabb "force" section. */
973static int sb_detect_aabb_collisionCached(float /*force*/[3], Object *vertexowner, float /*time*/)
974{
975 Object *ob;
976 SoftBody *sb = vertexowner->soft;
977 GHash *hash;
978 GHashIterator *ihash;
979 float aabbmin[3], aabbmax[3];
980 int deflected = 0;
981#if 0
982 int a;
983#endif
984
985 if ((sb == nullptr) || (sb->scratch == nullptr)) {
986 return 0;
987 }
988 copy_v3_v3(aabbmin, sb->scratch->aabbmin);
989 copy_v3_v3(aabbmax, sb->scratch->aabbmax);
990
991 hash = vertexowner->soft->scratch->colliderhash;
993 while (!BLI_ghashIterator_done(ihash)) {
994
995 ccd_Mesh *ccdm = static_cast<ccd_Mesh *>(BLI_ghashIterator_getValue(ihash));
996 ob = static_cast<Object *>(BLI_ghashIterator_getKey(ihash));
997 {
998 /* only with deflecting set */
999 if (ob->pd && ob->pd->deflect) {
1000 if (ccdm) {
1001 if ((aabbmax[0] < ccdm->bbmin[0]) || (aabbmax[1] < ccdm->bbmin[1]) ||
1002 (aabbmax[2] < ccdm->bbmin[2]) || (aabbmin[0] > ccdm->bbmax[0]) ||
1003 (aabbmin[1] > ccdm->bbmax[1]) || (aabbmin[2] > ccdm->bbmax[2]))
1004 {
1005 /* boxes don't intersect */
1007 continue;
1008 }
1009
1010 /* so now we have the 2 boxes overlapping */
1011 /* forces actually not used */
1012 deflected = 2;
1013 }
1014 else {
1015 /* Aye that should be cached. */
1016 CLOG_ERROR(&LOG, "missing cache error");
1018 continue;
1019 }
1020 } /* if (ob->pd && ob->pd->deflect) */
1022 }
1023 } /* while () */
1025 return deflected;
1026}
1027/* --- the aabb section. */
1028
1029/* +++ the face external section. */
1030static int sb_detect_face_pointCached(const float face_v1[3],
1031 const float face_v2[3],
1032 const float face_v3[3],
1033 float *damp,
1034 float force[3],
1035 Object *vertexowner,
1036 float time)
1037{
1038 Object *ob;
1039 GHash *hash;
1040 GHashIterator *ihash;
1041 float nv1[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
1042 float facedist, outerfacethickness, tune = 10.0f;
1043 int a, deflected = 0;
1044
1045 aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
1046 aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
1047 aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
1048 aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
1049 aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
1050 aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
1051
1052 /* calculate face normal once again SIGH */
1053 sub_v3_v3v3(edge1, face_v1, face_v2);
1054 sub_v3_v3v3(edge2, face_v3, face_v2);
1055 cross_v3_v3v3(d_nvect, edge2, edge1);
1056 normalize_v3(d_nvect);
1057
1058 hash = vertexowner->soft->scratch->colliderhash;
1059 ihash = BLI_ghashIterator_new(hash);
1060 while (!BLI_ghashIterator_done(ihash)) {
1061
1062 ccd_Mesh *ccdm = static_cast<ccd_Mesh *>(BLI_ghashIterator_getValue(ihash));
1063 ob = static_cast<Object *>(BLI_ghashIterator_getKey(ihash));
1064 {
1065 /* only with deflecting set */
1066 if (ob->pd && ob->pd->deflect) {
1067 const float (*vert_positions)[3] = nullptr;
1068 const float (*vert_positions_prev)[3] = nullptr;
1069 if (ccdm) {
1070 vert_positions = ccdm->vert_positions;
1071 a = ccdm->mvert_num;
1072 vert_positions_prev = ccdm->vert_positions_prev;
1073 outerfacethickness = ob->pd->pdef_sboft;
1074 if ((aabbmax[0] < ccdm->bbmin[0]) || (aabbmax[1] < ccdm->bbmin[1]) ||
1075 (aabbmax[2] < ccdm->bbmin[2]) || (aabbmin[0] > ccdm->bbmax[0]) ||
1076 (aabbmin[1] > ccdm->bbmax[1]) || (aabbmin[2] > ccdm->bbmax[2]))
1077 {
1078 /* boxes don't intersect */
1080 continue;
1081 }
1082 }
1083 else {
1084 /* Aye that should be cached. */
1085 CLOG_ERROR(&LOG, "missing cache error");
1087 continue;
1088 }
1089
1090 /* Use mesh. */
1091 if (vert_positions) {
1092 while (a) {
1093 copy_v3_v3(nv1, vert_positions[a - 1]);
1094 if (vert_positions_prev) {
1095 mul_v3_fl(nv1, time);
1096 madd_v3_v3fl(nv1, vert_positions_prev[a - 1], 1.0f - time);
1097 }
1098 /* Origin to face_v2. */
1099 sub_v3_v3(nv1, face_v2);
1100 facedist = dot_v3v3(nv1, d_nvect);
1101 if (fabsf(facedist) < outerfacethickness) {
1102 if (isect_point_tri_prism_v3(nv1, face_v1, face_v2, face_v3)) {
1103 float df;
1104 if (facedist > 0) {
1105 df = (outerfacethickness - facedist) / outerfacethickness;
1106 }
1107 else {
1108 df = (outerfacethickness + facedist) / outerfacethickness;
1109 }
1110
1111 *damp = df * tune * ob->pd->pdef_sbdamp;
1112
1113 df = 0.01f * expf(-100.0f * df);
1114 madd_v3_v3fl(force, d_nvect, -df);
1115 deflected = 3;
1116 }
1117 }
1118 a--;
1119 } /* while (a) */
1120 } /* if (vert_positions) */
1121 } /* if (ob->pd && ob->pd->deflect) */
1123 }
1124 } /* while () */
1126 return deflected;
1127}
1128
1129static int sb_detect_face_collisionCached(const float face_v1[3],
1130 const float face_v2[3],
1131 const float face_v3[3],
1132 float *damp,
1133 float force[3],
1134 Object *vertexowner,
1135 float time)
1136{
1137 Object *ob;
1138 GHash *hash;
1139 GHashIterator *ihash;
1140 float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
1141 float t, tune = 10.0f;
1142 int a, deflected = 0;
1143
1144 aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
1145 aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
1146 aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
1147 aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
1148 aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
1149 aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
1150
1151 hash = vertexowner->soft->scratch->colliderhash;
1152 ihash = BLI_ghashIterator_new(hash);
1153 while (!BLI_ghashIterator_done(ihash)) {
1154
1155 ccd_Mesh *ccdm = static_cast<ccd_Mesh *>(BLI_ghashIterator_getValue(ihash));
1156 ob = static_cast<Object *>(BLI_ghashIterator_getKey(ihash));
1157 {
1158 /* only with deflecting set */
1159 if (ob->pd && ob->pd->deflect) {
1160 const float (*vert_positions)[3] = nullptr;
1161 const float (*vert_positions_prev)[3] = nullptr;
1162 const blender::int3 *vt = nullptr;
1163 const CCDF_MinMax *mima = nullptr;
1164
1165 if (ccdm) {
1166 vert_positions = ccdm->vert_positions;
1167 vt = ccdm->vert_tris;
1168 vert_positions_prev = ccdm->vert_positions_prev;
1169 mima = ccdm->mima;
1170 a = ccdm->tri_num;
1171
1172 if ((aabbmax[0] < ccdm->bbmin[0]) || (aabbmax[1] < ccdm->bbmin[1]) ||
1173 (aabbmax[2] < ccdm->bbmin[2]) || (aabbmin[0] > ccdm->bbmax[0]) ||
1174 (aabbmin[1] > ccdm->bbmax[1]) || (aabbmin[2] > ccdm->bbmax[2]))
1175 {
1176 /* boxes don't intersect */
1178 continue;
1179 }
1180 }
1181 else {
1182 /* Aye that should be cached. */
1183 CLOG_ERROR(&LOG, "missing cache error");
1185 continue;
1186 }
1187
1188 /* Use mesh. */
1189 while (a--) {
1190 if ((aabbmax[0] < mima->minx) || (aabbmin[0] > mima->maxx) ||
1191 (aabbmax[1] < mima->miny) || (aabbmin[1] > mima->maxy) ||
1192 (aabbmax[2] < mima->minz) || (aabbmin[2] > mima->maxz))
1193 {
1194 mima++;
1195 vt++;
1196 continue;
1197 }
1198
1199 if (vert_positions) {
1200
1201 copy_v3_v3(nv1, vert_positions[(*vt)[0]]);
1202 copy_v3_v3(nv2, vert_positions[(*vt)[1]]);
1203 copy_v3_v3(nv3, vert_positions[(*vt)[2]]);
1204
1205 if (vert_positions_prev) {
1206 mul_v3_fl(nv1, time);
1207 madd_v3_v3fl(nv1, vert_positions_prev[(*vt)[0]], 1.0f - time);
1208
1209 mul_v3_fl(nv2, time);
1210 madd_v3_v3fl(nv2, vert_positions_prev[(*vt)[1]], 1.0f - time);
1211
1212 mul_v3_fl(nv3, time);
1213 madd_v3_v3fl(nv3, vert_positions_prev[(*vt)[2]], 1.0f - time);
1214 }
1215 }
1216
1217 /* Switch origin to be nv2. */
1218 sub_v3_v3v3(edge1, nv1, nv2);
1219 sub_v3_v3v3(edge2, nv3, nv2);
1220 cross_v3_v3v3(d_nvect, edge2, edge1);
1221 normalize_v3(d_nvect);
1222 if (isect_line_segment_tri_v3(nv1, nv2, face_v1, face_v2, face_v3, &t, nullptr) ||
1223 isect_line_segment_tri_v3(nv2, nv3, face_v1, face_v2, face_v3, &t, nullptr) ||
1224 isect_line_segment_tri_v3(nv3, nv1, face_v1, face_v2, face_v3, &t, nullptr))
1225 {
1226 madd_v3_v3fl(force, d_nvect, -0.5f);
1227 *damp = tune * ob->pd->pdef_sbdamp;
1228 deflected = 2;
1229 }
1230 mima++;
1231 vt++;
1232 } /* while a */
1233 } /* if (ob->pd && ob->pd->deflect) */
1235 }
1236 } /* while () */
1238 return deflected;
1239}
1240
1241static void scan_for_ext_face_forces(Object *ob, float timenow)
1242{
1243 SoftBody *sb = ob->soft;
1244 BodyFace *bf;
1245 int a;
1246 float damp = 0.0f, choke = 1.0f;
1247 float tune = -10.0f;
1248 float feedback[3];
1249
1250 if (sb && sb->scratch->bodyface_num) {
1251
1252 bf = sb->scratch->bodyface;
1253 for (a = 0; a < sb->scratch->bodyface_num; a++, bf++) {
1254 bf->ext_force[0] = bf->ext_force[1] = bf->ext_force[2] = 0.0f;
1255 /*+++edges intruding. */
1256 bf->flag &= ~BFF_INTERSECT;
1257 zero_v3(feedback);
1259 sb->bpoint[bf->v2].pos,
1260 sb->bpoint[bf->v3].pos,
1261 &damp,
1262 feedback,
1263 ob,
1264 timenow))
1265 {
1266 madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
1267 madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
1268 madd_v3_v3fl(sb->bpoint[bf->v3].force, feedback, tune);
1269 // madd_v3_v3fl(bf->ext_force, feedback, tune);
1270 bf->flag |= BFF_INTERSECT;
1271 choke = min_ff(max_ff(damp, choke), 1.0f);
1272 }
1273 /*---edges intruding. */
1274
1275 /*+++ close vertices. */
1276 if ((bf->flag & BFF_INTERSECT) == 0) {
1277 bf->flag &= ~BFF_CLOSEVERT;
1278 tune = -1.0f;
1279 zero_v3(feedback);
1281 sb->bpoint[bf->v2].pos,
1282 sb->bpoint[bf->v3].pos,
1283 &damp,
1284 feedback,
1285 ob,
1286 timenow))
1287 {
1288 madd_v3_v3fl(sb->bpoint[bf->v1].force, feedback, tune);
1289 madd_v3_v3fl(sb->bpoint[bf->v2].force, feedback, tune);
1290 madd_v3_v3fl(sb->bpoint[bf->v3].force, feedback, tune);
1291 // madd_v3_v3fl(bf->ext_force, feedback, tune);
1292 bf->flag |= BFF_CLOSEVERT;
1293 choke = min_ff(max_ff(damp, choke), 1.0f);
1294 }
1295 }
1296 /*--- close vertices. */
1297 }
1298 bf = sb->scratch->bodyface;
1299 for (a = 0; a < sb->scratch->bodyface_num; a++, bf++) {
1300 if ((bf->flag & BFF_INTERSECT) || (bf->flag & BFF_CLOSEVERT)) {
1301 sb->bpoint[bf->v1].choke2 = max_ff(sb->bpoint[bf->v1].choke2, choke);
1302 sb->bpoint[bf->v2].choke2 = max_ff(sb->bpoint[bf->v2].choke2, choke);
1303 sb->bpoint[bf->v3].choke2 = max_ff(sb->bpoint[bf->v3].choke2, choke);
1304 }
1305 }
1306 }
1307}
1308
1309/* --- the face external section. */
1310
1311/* +++ the spring external section. */
1312
1313static int sb_detect_edge_collisionCached(const float edge_v1[3],
1314 const float edge_v2[3],
1315 float *damp,
1316 float force[3],
1317 Object *vertexowner,
1318 float time)
1319{
1320 Object *ob;
1321 GHash *hash;
1322 GHashIterator *ihash;
1323 float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3];
1324 float t, el;
1325 int a, deflected = 0;
1326
1327 minmax_v3v3_v3(aabbmin, aabbmax, edge_v1);
1328 minmax_v3v3_v3(aabbmin, aabbmax, edge_v2);
1329
1330 el = len_v3v3(edge_v1, edge_v2);
1331
1332 hash = vertexowner->soft->scratch->colliderhash;
1333 ihash = BLI_ghashIterator_new(hash);
1334 while (!BLI_ghashIterator_done(ihash)) {
1335
1336 ccd_Mesh *ccdm = static_cast<ccd_Mesh *>(BLI_ghashIterator_getValue(ihash));
1337 ob = static_cast<Object *>(BLI_ghashIterator_getKey(ihash));
1338 {
1339 /* only with deflecting set */
1340 if (ob->pd && ob->pd->deflect) {
1341 const float (*vert_positions)[3] = nullptr;
1342 const float (*vert_positions_prev)[3] = nullptr;
1343 const blender::int3 *vt = nullptr;
1344 const CCDF_MinMax *mima = nullptr;
1345
1346 if (ccdm) {
1347 vert_positions = ccdm->vert_positions;
1348 vert_positions_prev = ccdm->vert_positions_prev;
1349 vt = ccdm->vert_tris;
1350 mima = ccdm->mima;
1351 a = ccdm->tri_num;
1352
1353 if ((aabbmax[0] < ccdm->bbmin[0]) || (aabbmax[1] < ccdm->bbmin[1]) ||
1354 (aabbmax[2] < ccdm->bbmin[2]) || (aabbmin[0] > ccdm->bbmax[0]) ||
1355 (aabbmin[1] > ccdm->bbmax[1]) || (aabbmin[2] > ccdm->bbmax[2]))
1356 {
1357 /* boxes don't intersect */
1359 continue;
1360 }
1361 }
1362 else {
1363 /* Aye that should be cached. */
1364 CLOG_ERROR(&LOG, "missing cache error");
1366 continue;
1367 }
1368
1369 /* Use mesh. */
1370 while (a--) {
1371 if ((aabbmax[0] < mima->minx) || (aabbmin[0] > mima->maxx) ||
1372 (aabbmax[1] < mima->miny) || (aabbmin[1] > mima->maxy) ||
1373 (aabbmax[2] < mima->minz) || (aabbmin[2] > mima->maxz))
1374 {
1375 mima++;
1376 vt++;
1377 continue;
1378 }
1379
1380 if (vert_positions) {
1381
1382 copy_v3_v3(nv1, vert_positions[(*vt)[0]]);
1383 copy_v3_v3(nv2, vert_positions[(*vt)[1]]);
1384 copy_v3_v3(nv3, vert_positions[(*vt)[2]]);
1385
1386 if (vert_positions_prev) {
1387 mul_v3_fl(nv1, time);
1388 madd_v3_v3fl(nv1, vert_positions_prev[(*vt)[0]], 1.0f - time);
1389
1390 mul_v3_fl(nv2, time);
1391 madd_v3_v3fl(nv2, vert_positions_prev[(*vt)[1]], 1.0f - time);
1392
1393 mul_v3_fl(nv3, time);
1394 madd_v3_v3fl(nv3, vert_positions_prev[(*vt)[2]], 1.0f - time);
1395 }
1396 }
1397
1398 /* Switch origin to be nv2. */
1399 sub_v3_v3v3(edge1, nv1, nv2);
1400 sub_v3_v3v3(edge2, nv3, nv2);
1401
1402 cross_v3_v3v3(d_nvect, edge2, edge1);
1403 normalize_v3(d_nvect);
1404 if (isect_line_segment_tri_v3(edge_v1, edge_v2, nv1, nv2, nv3, &t, nullptr)) {
1405 float v1[3], v2[3];
1406 float intrusiondepth, i1, i2;
1407 sub_v3_v3v3(v1, edge_v1, nv2);
1408 sub_v3_v3v3(v2, edge_v2, nv2);
1409 i1 = dot_v3v3(v1, d_nvect);
1410 i2 = dot_v3v3(v2, d_nvect);
1411 intrusiondepth = -min_ff(i1, i2) / el;
1412 madd_v3_v3fl(force, d_nvect, intrusiondepth);
1413 *damp = ob->pd->pdef_sbdamp;
1414 deflected = 2;
1415 }
1416
1417 mima++;
1418 vt++;
1419 } /* while a */
1420 } /* if (ob->pd && ob->pd->deflect) */
1422 }
1423 } /* while () */
1425 return deflected;
1426}
1427
1429 Scene *scene, Object *ob, float timenow, int ifirst, int ilast, ListBase *effectors)
1430{
1431 SoftBody *sb = ob->soft;
1432 int a;
1433 float damp;
1434 float feedback[3];
1435
1436 if (sb && sb->totspring) {
1437 for (a = ifirst; a < ilast; a++) {
1438 BodySpring *bs = &sb->bspring[a];
1439 bs->ext_force[0] = bs->ext_force[1] = bs->ext_force[2] = 0.0f;
1440 feedback[0] = feedback[1] = feedback[2] = 0.0f;
1441 bs->flag &= ~BSF_INTERSECT;
1442
1443 if (bs->springtype == SB_EDGE) {
1444 /* +++ springs colliding */
1445 if (ob->softflag & OB_SB_EDGECOLL) {
1447 sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos, &damp, feedback, ob, timenow))
1448 {
1449 add_v3_v3(bs->ext_force, feedback);
1450 bs->flag |= BSF_INTERSECT;
1451 // bs->cf=damp;
1452 bs->cf = sb->choke * 0.01f;
1453 }
1454 }
1455 /* ---- springs colliding */
1456
1457 /* +++ springs seeing wind ... n stuff depending on their orientation. */
1458 /* NOTE: we don't use `sb->mediafrict` but use `sb->aeroedge` for magnitude of effect. */
1459 if (sb->aeroedge) {
1460 float vel[3], sp[3], pr[3], force[3];
1461 float f, windfactor = 0.25f;
1462 /* See if we have wind. */
1463 if (effectors) {
1464 EffectedPoint epoint;
1465 float speed[3] = {0.0f, 0.0f, 0.0f};
1466 float pos[3];
1467 mid_v3_v3v3(pos, sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos);
1468 mid_v3_v3v3(vel, sb->bpoint[bs->v1].vec, sb->bpoint[bs->v2].vec);
1469 pd_point_from_soft(scene, pos, vel, -1, &epoint);
1471 effectors, nullptr, sb->effector_weights, &epoint, force, nullptr, speed);
1472
1473 mul_v3_fl(speed, windfactor);
1474 add_v3_v3(vel, speed);
1475 }
1476 /* media in rest */
1477 else {
1478 add_v3_v3v3(vel, sb->bpoint[bs->v1].vec, sb->bpoint[bs->v2].vec);
1479 }
1480 f = normalize_v3(vel);
1481 f = -0.0001f * f * f * sb->aeroedge;
1482 /* (todo) add a nice angle dependent function done for now BUT */
1483 /* still there could be some nice drag/lift function, but who needs it */
1484
1485 sub_v3_v3v3(sp, sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos);
1486 project_v3_v3v3(pr, vel, sp);
1487 sub_v3_v3(vel, pr);
1488 normalize_v3(vel);
1489 if (ob->softflag & OB_SB_AERO_ANGLE) {
1490 normalize_v3(sp);
1491 madd_v3_v3fl(bs->ext_force, vel, f * (1.0f - fabsf(dot_v3v3(vel, sp))));
1492 }
1493 else {
1494 madd_v3_v3fl(bs->ext_force, vel, f); /* to keep compatible with 2.45 release files */
1495 }
1496 }
1497 /* --- springs seeing wind */
1498 }
1499 }
1500 }
1501}
1502
1504{
1507 pctx->scene, pctx->ob, pctx->timenow, pctx->ifirst, pctx->ilast, pctx->effectors);
1508 return nullptr;
1509}
1510
1511static void sb_sfesf_threads_run(Depsgraph *depsgraph,
1512 Scene *scene,
1513 Object *ob,
1514 float timenow,
1515 int totsprings,
1516 int *ptr_to_break_func(void))
1517{
1518 UNUSED_VARS(ptr_to_break_func);
1519 ListBase threads;
1520 SB_thread_context *sb_threads;
1521 int i, totthread, left, dec;
1522
1523 /* wild guess .. may increase with better thread management 'above'
1524 * or even be UI option sb->spawn_cf_threads_nopts */
1525 int lowsprings = 100;
1526
1527 ListBase *effectors = BKE_effectors_create(
1528 depsgraph, ob, nullptr, ob->soft->effector_weights, false);
1529
1530 /* figure the number of threads while preventing pretty pointless threading overhead */
1531 totthread = BKE_scene_num_threads(scene);
1532 /* What if we got zillions of CPUs running but less to spread. */
1533 while ((totsprings / totthread < lowsprings) && (totthread > 1)) {
1534 totthread--;
1535 }
1536
1537 sb_threads = MEM_calloc_arrayN<SB_thread_context>(totthread, "SBSpringsThread");
1538 left = totsprings;
1539 dec = totsprings / totthread + 1;
1540 for (i = 0; i < totthread; i++) {
1541 sb_threads[i].scene = scene;
1542 sb_threads[i].ob = ob;
1543 sb_threads[i].forcetime = 0.0; /* not used here */
1544 sb_threads[i].timenow = timenow;
1545 sb_threads[i].ilast = left;
1546 left = left - dec;
1547 if (left > 0) {
1548 sb_threads[i].ifirst = left;
1549 }
1550 else {
1551 sb_threads[i].ifirst = 0;
1552 }
1553 sb_threads[i].effectors = effectors;
1554 sb_threads[i].do_deflector = false; /* not used here */
1555 sb_threads[i].fieldfactor = 0.0f; /* not used here */
1556 sb_threads[i].windfactor = 0.0f; /* not used here */
1557 sb_threads[i].nr = i;
1558 sb_threads[i].tot = totthread;
1559 }
1560 if (totthread > 1) {
1562
1563 for (i = 0; i < totthread; i++) {
1564 BLI_threadpool_insert(&threads, &sb_threads[i]);
1565 }
1566
1567 BLI_threadpool_end(&threads);
1568 }
1569 else {
1570 exec_scan_for_ext_spring_forces(&sb_threads[0]);
1571 }
1572 /* clean up */
1573 MEM_freeN(sb_threads);
1574
1575 BKE_effectors_free(effectors);
1576}
1577
1578/* --- the spring external section. */
1579
1580static int choose_winner(
1581 float *w, float *pos, float *a, float *b, float *c, float *ca, float *cb, float *cc)
1582{
1583 float mindist, cp;
1584 int winner = 1;
1585 mindist = fabsf(dot_v3v3(pos, a));
1586
1587 cp = fabsf(dot_v3v3(pos, b));
1588 if (mindist < cp) {
1589 mindist = cp;
1590 winner = 2;
1591 }
1592
1593 cp = fabsf(dot_v3v3(pos, c));
1594 if (mindist < cp) {
1595 mindist = cp;
1596 winner = 3;
1597 }
1598 switch (winner) {
1599 case 1:
1600 copy_v3_v3(w, ca);
1601 break;
1602 case 2:
1603 copy_v3_v3(w, cb);
1604 break;
1605 case 3:
1606 copy_v3_v3(w, cc);
1607 }
1608 return winner;
1609}
1610
1611static int sb_detect_vertex_collisionCached(float opco[3],
1612 float facenormal[3],
1613 float *damp,
1614 float force[3],
1615 Object *vertexowner,
1616 float time,
1617 float vel[3],
1618 float *intrusion)
1619{
1620 Object *ob = nullptr;
1621 GHash *hash;
1622 GHashIterator *ihash;
1623 float nv1[3], nv2[3], nv3[3], edge1[3], edge2[3], d_nvect[3], dv1[3], ve[3],
1624 avel[3] = {0.0, 0.0, 0.0}, vv1[3], vv2[3], vv3[3], coledge[3] = {0.0f, 0.0f, 0.0f},
1625 mindistedge = 1000.0f, outerforceaccu[3], innerforceaccu[3], facedist,
1626 /* n_mag, */ /* UNUSED */ force_mag_norm, minx, miny, minz, maxx, maxy, maxz,
1627 innerfacethickness = -0.5f, outerfacethickness = 0.2f, ee = 5.0f, ff = 0.1f, fa = 1;
1628 int a, deflected = 0, cavel = 0, ci = 0;
1629 /* init */
1630 *intrusion = 0.0f;
1631 hash = vertexowner->soft->scratch->colliderhash;
1632 ihash = BLI_ghashIterator_new(hash);
1633 outerforceaccu[0] = outerforceaccu[1] = outerforceaccu[2] = 0.0f;
1634 innerforceaccu[0] = innerforceaccu[1] = innerforceaccu[2] = 0.0f;
1635 /* go */
1636 while (!BLI_ghashIterator_done(ihash)) {
1637
1638 ccd_Mesh *ccdm = static_cast<ccd_Mesh *>(BLI_ghashIterator_getValue(ihash));
1639 ob = static_cast<Object *>(BLI_ghashIterator_getKey(ihash));
1640 {
1641 /* only with deflecting set */
1642 if (ob->pd && ob->pd->deflect) {
1643 const float (*vert_positions)[3] = nullptr;
1644 const float (*vert_positions_prev)[3] = nullptr;
1645 const blender::int3 *vt = nullptr;
1646 const CCDF_MinMax *mima = nullptr;
1647
1648 if (ccdm) {
1649 vert_positions = ccdm->vert_positions;
1650 vert_positions_prev = ccdm->vert_positions_prev;
1651 vt = ccdm->vert_tris;
1652 mima = ccdm->mima;
1653 a = ccdm->tri_num;
1654
1655 minx = ccdm->bbmin[0];
1656 miny = ccdm->bbmin[1];
1657 minz = ccdm->bbmin[2];
1658
1659 maxx = ccdm->bbmax[0];
1660 maxy = ccdm->bbmax[1];
1661 maxz = ccdm->bbmax[2];
1662
1663 if ((opco[0] < minx) || (opco[1] < miny) || (opco[2] < minz) || (opco[0] > maxx) ||
1664 (opco[1] > maxy) || (opco[2] > maxz))
1665 {
1666 /* Outside the padded bound-box -> collision object is too far away. */
1668 continue;
1669 }
1670 }
1671 else {
1672 /* Aye that should be cached. */
1673 CLOG_ERROR(&LOG, "missing cache error");
1675 continue;
1676 }
1677
1678 /* do object level stuff */
1679 /* need to have user control for that since it depends on model scale */
1680 innerfacethickness = -ob->pd->pdef_sbift;
1681 outerfacethickness = ob->pd->pdef_sboft;
1682 fa = (ff * outerfacethickness - outerfacethickness);
1683 fa *= fa;
1684 fa = 1.0f / fa;
1685 avel[0] = avel[1] = avel[2] = 0.0f;
1686 /* Use mesh. */
1687 while (a--) {
1688 if ((opco[0] < mima->minx) || (opco[0] > mima->maxx) || (opco[1] < mima->miny) ||
1689 (opco[1] > mima->maxy) || (opco[2] < mima->minz) || (opco[2] > mima->maxz))
1690 {
1691 mima++;
1692 vt++;
1693 continue;
1694 }
1695
1696 if (vert_positions) {
1697
1698 copy_v3_v3(nv1, vert_positions[(*vt)[0]]);
1699 copy_v3_v3(nv2, vert_positions[(*vt)[1]]);
1700 copy_v3_v3(nv3, vert_positions[(*vt)[2]]);
1701
1702 if (vert_positions_prev) {
1703 /* Grab the average speed of the collider vertices before we spoil nvX
1704 * hum could be done once a SB steps but then we' need to store that too
1705 * since the AABB reduced probability to get here drastically
1706 * it might be a nice tradeoff CPU <--> memory.
1707 */
1708 sub_v3_v3v3(vv1, nv1, vert_positions_prev[(*vt)[0]]);
1709 sub_v3_v3v3(vv2, nv2, vert_positions_prev[(*vt)[1]]);
1710 sub_v3_v3v3(vv3, nv3, vert_positions_prev[(*vt)[2]]);
1711
1712 mul_v3_fl(nv1, time);
1713 madd_v3_v3fl(nv1, vert_positions_prev[(*vt)[0]], 1.0f - time);
1714
1715 mul_v3_fl(nv2, time);
1716 madd_v3_v3fl(nv2, vert_positions_prev[(*vt)[1]], 1.0f - time);
1717
1718 mul_v3_fl(nv3, time);
1719 madd_v3_v3fl(nv3, vert_positions_prev[(*vt)[2]], 1.0f - time);
1720 }
1721 }
1722
1723 /* Switch origin to be nv2. */
1724 sub_v3_v3v3(edge1, nv1, nv2);
1725 sub_v3_v3v3(edge2, nv3, nv2);
1726 /* Abuse dv1 to have vertex in question at *origin* of triangle. */
1727 sub_v3_v3v3(dv1, opco, nv2);
1728
1729 cross_v3_v3v3(d_nvect, edge2, edge1);
1730 /* n_mag = */ /* UNUSED */ normalize_v3(d_nvect);
1731 facedist = dot_v3v3(dv1, d_nvect);
1732 /* so rules are */
1733
1734 if ((facedist > innerfacethickness) && (facedist < outerfacethickness)) {
1735 if (isect_point_tri_prism_v3(opco, nv1, nv2, nv3)) {
1736 force_mag_norm = float(exp(double(-ee * facedist)));
1737 if (facedist > outerfacethickness * ff) {
1738 force_mag_norm = force_mag_norm * fa * (facedist - outerfacethickness) *
1739 (facedist - outerfacethickness);
1740 }
1741 *damp = ob->pd->pdef_sbdamp;
1742 if (facedist > 0.0f) {
1743 *damp *= (1.0f - facedist / outerfacethickness);
1744 madd_v3_v3fl(outerforceaccu, d_nvect, force_mag_norm);
1745 deflected = 3;
1746 }
1747 else {
1748 madd_v3_v3fl(innerforceaccu, d_nvect, force_mag_norm);
1749 deflected = std::max(deflected, 2);
1750 }
1751 if ((vert_positions_prev) && (*damp > 0.0f)) {
1752 choose_winner(ve, opco, nv1, nv2, nv3, vv1, vv2, vv3);
1753 add_v3_v3(avel, ve);
1754 cavel++;
1755 }
1756 *intrusion += facedist;
1757 ci++;
1758 }
1759 }
1760
1761 mima++;
1762 vt++;
1763 } /* while a */
1764 } /* if (ob->pd && ob->pd->deflect) */
1766 }
1767 } /* while () */
1768
1769 if (deflected == 1) { /* no face but 'outer' edge cylinder sees vert */
1770 force_mag_norm = float(exp(double() - ee * mindistedge));
1771 if (mindistedge > outerfacethickness * ff) {
1772 force_mag_norm = force_mag_norm * fa * (mindistedge - outerfacethickness) *
1773 (mindistedge - outerfacethickness);
1774 }
1775 madd_v3_v3fl(force, coledge, force_mag_norm);
1776 *damp = ob->pd->pdef_sbdamp;
1777 if (mindistedge > 0.0f) {
1778 *damp *= (1.0f - mindistedge / outerfacethickness);
1779 }
1780 }
1781 if (deflected == 2) { /* face inner detected */
1782 add_v3_v3(force, innerforceaccu);
1783 }
1784 if (deflected == 3) { /* face outer detected */
1785 add_v3_v3(force, outerforceaccu);
1786 }
1787
1789 if (cavel) {
1790 mul_v3_fl(avel, 1.0f / float(cavel));
1791 }
1792 copy_v3_v3(vel, avel);
1793 if (ci) {
1794 *intrusion /= ci;
1795 }
1796 if (deflected) {
1797 normalize_v3_v3(facenormal, force);
1798 }
1799 return deflected;
1800}
1801
1802/* Sandbox to plug in various deflection algorithms. */
1804 float *actpos,
1805 float *facenormal,
1806 float *force,
1807 float *cf,
1808 float time,
1809 float *vel,
1810 float *intrusion)
1811{
1812 float s_actpos[3];
1813 int deflected;
1814 copy_v3_v3(s_actpos, actpos);
1816 s_actpos, facenormal, cf, force, ob, time, vel, intrusion);
1817#if 0
1818 deflected = sb_detect_vertex_collisionCachedEx(
1819 s_actpos, facenormal, cf, force, ob, time, vel, intrusion);
1820#endif
1821 return deflected;
1822}
1823
1824/* Hiding this for now, but the jacobian may pop up on other tasks - so I'd like to keep it. */
1825#if 0
1826static void dfdx_spring(int ia, int ic, int op, float dir[3], float L, float len, float factor)
1827{
1828 float m, delta_ij;
1829 int i, j;
1830 if (L < len) {
1831 for (i = 0; i < 3; i++) {
1832 for (j = 0; j < 3; j++) {
1833 delta_ij = (i == j ? (1.0f) : (0.0f));
1834 m = factor * (dir[i] * dir[j] + (1 - L / len) * (delta_ij - dir[i] * dir[j]));
1835 EIG_linear_solver_matrix_add(ia + i, op + ic + j, m);
1836 }
1837 }
1838 }
1839 else {
1840 for (i = 0; i < 3; i++) {
1841 for (j = 0; j < 3; j++) {
1842 m = factor * dir[i] * dir[j];
1843 EIG_linear_solver_matrix_add(ia + i, op + ic + j, m);
1844 }
1845 }
1846 }
1847}
1848
1849static void dfdx_goal(int ia, int ic, int op, float factor)
1850{
1851 int i;
1852 for (i = 0; i < 3; i++) {
1853 EIG_linear_solver_matrix_add(ia + i, op + ic + i, factor);
1854 }
1855}
1856
1857static void dfdv_goal(int ia, int ic, float factor)
1858{
1859 int i;
1860 for (i = 0; i < 3; i++) {
1861 EIG_linear_solver_matrix_add(ia + i, ic + i, factor);
1862 }
1863}
1864#endif /* if 0 */
1865
1866static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, float /*forcetime*/)
1867{
1868 SoftBody *sb = ob->soft; /* is supposed to be there */
1869 BodyPoint *bp1, *bp2;
1870
1871 float dir[3], dvel[3];
1872 float distance, forcefactor, kd, absvel, projvel, kw;
1873#if 0 /* UNUSED */
1874 int ia, ic;
1875#endif
1876 /* prepare depending on which side of the spring we are on */
1877 if (bpi == bs->v1) {
1878 bp1 = &sb->bpoint[bs->v1];
1879 bp2 = &sb->bpoint[bs->v2];
1880#if 0 /* UNUSED */
1881 ia = 3 * bs->v1;
1882 ic = 3 * bs->v2;
1883#endif
1884 }
1885 else if (bpi == bs->v2) {
1886 bp1 = &sb->bpoint[bs->v2];
1887 bp2 = &sb->bpoint[bs->v1];
1888#if 0 /* UNUSED */
1889 ia = 3 * bs->v2;
1890 ic = 3 * bs->v1;
1891#endif
1892 }
1893 else {
1894 /* TODO: make this debug option. */
1895 CLOG_WARN(&LOG, "bodypoint <bpi> is not attached to spring <*bs>");
1896 return;
1897 }
1898
1899 /* do bp1 <--> bp2 elastic */
1900 sub_v3_v3v3(dir, bp1->pos, bp2->pos);
1901 distance = normalize_v3(dir);
1902 if (bs->len < distance) {
1903 iks = 1.0f / (1.0f - sb->inspring) - 1.0f; /* inner spring constants function */
1904 }
1905 else {
1906 iks = 1.0f / (1.0f - sb->inpush) - 1.0f; /* inner spring constants function */
1907 }
1908
1909 if (bs->len > 0.0f) { /* check for degenerated springs */
1910 forcefactor = iks / bs->len;
1911 }
1912 else {
1913 forcefactor = iks;
1914 }
1915 kw = (bp1->springweight + bp2->springweight) / 2.0f;
1916 kw = kw * kw;
1917 kw = kw * kw;
1918 switch (bs->springtype) {
1919 case SB_EDGE:
1920 case SB_HANDLE:
1921 forcefactor *= kw;
1922 break;
1923 case SB_BEND:
1924 forcefactor *= sb->secondspring * kw;
1925 break;
1926 case SB_STIFFQUAD:
1927 forcefactor *= sb->shearstiff * sb->shearstiff * kw;
1928 break;
1929 default:
1930 break;
1931 }
1932
1933 madd_v3_v3fl(bp1->force, dir, (bs->len - distance) * forcefactor);
1934
1935 /* do bp1 <--> bp2 viscous */
1936 sub_v3_v3v3(dvel, bp1->vec, bp2->vec);
1937 kd = sb->infrict * sb_fric_force_scale(ob);
1938 absvel = normalize_v3(dvel);
1939 projvel = dot_v3v3(dir, dvel);
1940 kd *= absvel * projvel;
1941 madd_v3_v3fl(bp1->force, dir, -kd);
1942}
1943
1944/* since this is definitely the most CPU consuming task here .. try to spread it */
1945/* core function _softbody_calc_forces_slice_in_a_thread */
1946/* result is int to be able to flag user break */
1948 Object *ob,
1949 float forcetime,
1950 float timenow,
1951 int ifirst,
1952 int ilast,
1953 int *ptr_to_break_func(void),
1954 ListBase *effectors,
1955 int do_deflector,
1956 float fieldfactor,
1957 float windfactor)
1958{
1959 UNUSED_VARS(ptr_to_break_func);
1960 float iks;
1961 int bb, do_selfcollision, do_springcollision, do_aero;
1962 int number_of_points_here = ilast - ifirst;
1963 SoftBody *sb = ob->soft; /* is supposed to be there */
1964 BodyPoint *bp;
1965
1966 /* initialize */
1967 if (sb) {
1968 /* check conditions for various options */
1969 /* +++ could be done on object level to squeeze out the last bits of it */
1970 do_selfcollision = ((ob->softflag & OB_SB_EDGES) && (sb->bspring) &&
1971 (ob->softflag & OB_SB_SELF));
1972 do_springcollision = do_deflector && (ob->softflag & OB_SB_EDGES) &&
1973 (ob->softflag & OB_SB_EDGECOLL);
1974 do_aero = ((sb->aeroedge) && (ob->softflag & OB_SB_EDGES));
1975 /* --- could be done on object level to squeeze out the last bits of it */
1976 }
1977 else {
1978 CLOG_ERROR(&LOG, "expected a SB here");
1979 return 999;
1980 }
1981
1982 /* Debugging. */
1983 if (sb->totpoint < ifirst) {
1984 printf("Aye 998");
1985 return 998;
1986 }
1987 /* Debugging. */
1988
1989 bp = &sb->bpoint[ifirst];
1990 for (bb = number_of_points_here; bb > 0; bb--, bp++) {
1991 /* Clear forces accumulator. */
1992 bp->force[0] = bp->force[1] = bp->force[2] = 0.0;
1993 /* naive ball self collision */
1994 /* needs to be done if goal snaps or not */
1995 if (do_selfcollision) {
1996 int attached;
1997 BodyPoint *obp;
1998 BodySpring *bs;
1999 int c, b;
2000 float velcenter[3], dvel[3], def[3];
2001 float distance;
2002 float compare;
2003 float bstune = sb->ballstiff;
2004
2005 /* Running in a slice we must not assume anything done with obp
2006 * neither alter the data of obp. */
2007 for (c = sb->totpoint, obp = sb->bpoint; c > 0; c--, obp++) {
2008 compare = (obp->colball + bp->colball);
2009 sub_v3_v3v3(def, bp->pos, obp->pos);
2010 /* rather check the AABBoxes before ever calculating the real distance */
2011 /* mathematically it is completely nuts, but performance is pretty much (3) times faster */
2012 if ((fabsf(def[0]) > compare) || (fabsf(def[1]) > compare) || (fabsf(def[2]) > compare)) {
2013 continue;
2014 }
2015 distance = normalize_v3(def);
2016 if (distance < compare) {
2017 /* exclude body points attached with a spring */
2018 attached = 0;
2019 for (b = obp->nofsprings; b > 0; b--) {
2020 bs = sb->bspring + obp->springs[b - 1];
2021 if (ELEM(ilast - bb, bs->v2, bs->v1)) {
2022 attached = 1;
2023 continue;
2024 }
2025 }
2026 if (!attached) {
2027 float f = bstune / (distance) + bstune / (compare * compare) * distance -
2028 2.0f * bstune / compare;
2029
2030 mid_v3_v3v3(velcenter, bp->vec, obp->vec);
2031 sub_v3_v3v3(dvel, velcenter, bp->vec);
2032 mul_v3_fl(dvel, _final_mass(ob, bp));
2033
2034 madd_v3_v3fl(bp->force, def, f * (1.0f - sb->balldamp));
2035 madd_v3_v3fl(bp->force, dvel, sb->balldamp);
2036 }
2037 }
2038 }
2039 }
2040 /* naive ball self collision done */
2041
2042 if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* omit this bp when it snaps */
2043 float auxvect[3];
2044 float velgoal[3];
2045
2046 /* do goal stuff */
2047 if (ob->softflag & OB_SB_GOAL) {
2048 /* true elastic goal */
2049 float ks, kd;
2050 sub_v3_v3v3(auxvect, bp->pos, bp->origT);
2051 ks = 1.0f / (1.0f - _final_goal(ob, bp) * sb->goalspring) - 1.0f;
2052 bp->force[0] += -ks * (auxvect[0]);
2053 bp->force[1] += -ks * (auxvect[1]);
2054 bp->force[2] += -ks * (auxvect[2]);
2055
2056 /* Calculate damping forces generated by goals. */
2057 sub_v3_v3v3(velgoal, bp->origS, bp->origE);
2058 kd = sb->goalfrict * sb_fric_force_scale(ob);
2059 add_v3_v3v3(auxvect, velgoal, bp->vec);
2060
2061 /* Make sure friction does not become rocket motor on time reversal. */
2062 if (forcetime > 0.0f) {
2063 bp->force[0] -= kd * (auxvect[0]);
2064 bp->force[1] -= kd * (auxvect[1]);
2065 bp->force[2] -= kd * (auxvect[2]);
2066 }
2067 else {
2068 bp->force[0] -= kd * (velgoal[0] - bp->vec[0]);
2069 bp->force[1] -= kd * (velgoal[1] - bp->vec[1]);
2070 bp->force[2] -= kd * (velgoal[2] - bp->vec[2]);
2071 }
2072 }
2073 /* done goal stuff */
2074
2075 /* gravitation */
2077 float gravity[3];
2078 copy_v3_v3(gravity, scene->physics_settings.gravity);
2079
2080 /* Individual mass of node here. */
2081 mul_v3_fl(gravity,
2082 sb_grav_force_scale(ob) * _final_mass(ob, bp) *
2084
2085 add_v3_v3(bp->force, gravity);
2086 }
2087
2088 /* particle field & vortex */
2089 if (effectors) {
2090 EffectedPoint epoint;
2091 float kd;
2092 float force[3] = {0.0f, 0.0f, 0.0f};
2093 float speed[3] = {0.0f, 0.0f, 0.0f};
2094
2095 /* just for calling function once */
2096 float eval_sb_fric_force_scale = sb_fric_force_scale(ob);
2097
2098 pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint - bp, &epoint);
2100 effectors, nullptr, sb->effector_weights, &epoint, force, nullptr, speed);
2101
2102 /* Apply force-field. */
2103 mul_v3_fl(force, fieldfactor * eval_sb_fric_force_scale);
2104 add_v3_v3(bp->force, force);
2105
2106 /* BP friction in moving media */
2107 kd = sb->mediafrict * eval_sb_fric_force_scale;
2108 bp->force[0] -= kd * (bp->vec[0] + windfactor * speed[0] / eval_sb_fric_force_scale);
2109 bp->force[1] -= kd * (bp->vec[1] + windfactor * speed[1] / eval_sb_fric_force_scale);
2110 bp->force[2] -= kd * (bp->vec[2] + windfactor * speed[2] / eval_sb_fric_force_scale);
2111 /* now we'll have nice centrifugal effect for vortex */
2112 }
2113 else {
2114 /* BP friction in media (not) moving. */
2115 float kd = sb->mediafrict * sb_fric_force_scale(ob);
2116 /* assume it to be proportional to actual velocity */
2117 bp->force[0] -= bp->vec[0] * kd;
2118 bp->force[1] -= bp->vec[1] * kd;
2119 bp->force[2] -= bp->vec[2] * kd;
2120 /* friction in media done */
2121 }
2122 /* +++cached collision targets */
2123 bp->choke = 0.0f;
2124 bp->choke2 = 0.0f;
2125 bp->loc_flag &= ~SBF_DOFUZZY;
2126 if (do_deflector && !(bp->loc_flag & SBF_OUTOFCOLLISION)) {
2127 float cfforce[3], defforce[3] = {0.0f, 0.0f, 0.0f}, vel[3] = {0.0f, 0.0f, 0.0f},
2128 facenormal[3], cf = 1.0f, intrusion;
2129 float kd = 1.0f;
2130
2131 if (sb_deflect_face(ob, bp->pos, facenormal, defforce, &cf, timenow, vel, &intrusion)) {
2132 if (intrusion < 0.0f) {
2133 sb->scratch->flag |= SBF_DOFUZZY;
2134 bp->loc_flag |= SBF_DOFUZZY;
2135 bp->choke = sb->choke * 0.01f;
2136 }
2137
2138 sub_v3_v3v3(cfforce, bp->vec, vel);
2139 madd_v3_v3fl(bp->force, cfforce, -cf * 50.0f);
2140
2141 madd_v3_v3fl(bp->force, defforce, kd);
2142 }
2143 }
2144 /* ---cached collision targets */
2145
2146 /* +++springs */
2147 iks = 1.0f / (1.0f - sb->inspring) - 1.0f; /* inner spring constants function */
2148 if (ob->softflag & OB_SB_EDGES) {
2149 if (sb->bspring) { /* Spring list exists at all? */
2150 int b;
2151 BodySpring *bs;
2152 for (b = bp->nofsprings; b > 0; b--) {
2153 bs = sb->bspring + bp->springs[b - 1];
2154 if (do_springcollision || do_aero) {
2155 add_v3_v3(bp->force, bs->ext_force);
2156 if (bs->flag & BSF_INTERSECT) {
2157 bp->choke = bs->cf;
2158 }
2159 }
2160 // sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, float forcetime)
2161 sb_spring_force(ob, ilast - bb, bs, iks, forcetime);
2162 } /* loop springs. */
2163 } /* existing spring list. */
2164 } /* Any edges. */
2165 /* ---springs */
2166 } /* Omit on snap. */
2167 } /* Loop all bp's. */
2168 return 0; /* Done fine. */
2169}
2170
2172{
2175 pctx->ob,
2176 pctx->forcetime,
2177 pctx->timenow,
2178 pctx->ifirst,
2179 pctx->ilast,
2180 nullptr,
2181 pctx->effectors,
2182 pctx->do_deflector,
2183 pctx->fieldfactor,
2184 pctx->windfactor);
2185 return nullptr;
2186}
2187
2188static void sb_cf_threads_run(Scene *scene,
2189 Object *ob,
2190 float forcetime,
2191 float timenow,
2192 int totpoint,
2193 int *ptr_to_break_func(void),
2194 ListBase *effectors,
2195 int do_deflector,
2196 float fieldfactor,
2197 float windfactor)
2198{
2199 UNUSED_VARS(ptr_to_break_func);
2200 ListBase threads;
2201 SB_thread_context *sb_threads;
2202 int i, totthread, left, dec;
2203
2204 /* wild guess .. may increase with better thread management 'above'
2205 * or even be UI option sb->spawn_cf_threads_nopts. */
2206 int lowpoints = 100;
2207
2208 /* figure the number of threads while preventing pretty pointless threading overhead */
2209 totthread = BKE_scene_num_threads(scene);
2210 /* What if we got zillions of CPUs running but less to spread. */
2211 while ((totpoint / totthread < lowpoints) && (totthread > 1)) {
2212 totthread--;
2213 }
2214
2215 // printf("sb_cf_threads_run spawning %d threads\n", totthread);
2216
2217 sb_threads = MEM_calloc_arrayN<SB_thread_context>(totthread, "SBThread");
2218 left = totpoint;
2219 dec = totpoint / totthread + 1;
2220 for (i = 0; i < totthread; i++) {
2221 sb_threads[i].scene = scene;
2222 sb_threads[i].ob = ob;
2223 sb_threads[i].forcetime = forcetime;
2224 sb_threads[i].timenow = timenow;
2225 sb_threads[i].ilast = left;
2226 left = left - dec;
2227 if (left > 0) {
2228 sb_threads[i].ifirst = left;
2229 }
2230 else {
2231 sb_threads[i].ifirst = 0;
2232 }
2233 sb_threads[i].effectors = effectors;
2234 sb_threads[i].do_deflector = do_deflector;
2235 sb_threads[i].fieldfactor = fieldfactor;
2236 sb_threads[i].windfactor = windfactor;
2237 sb_threads[i].nr = i;
2238 sb_threads[i].tot = totthread;
2239 }
2240
2241 if (totthread > 1) {
2242 BLI_threadpool_init(&threads, exec_softbody_calc_forces, totthread);
2243
2244 for (i = 0; i < totthread; i++) {
2245 BLI_threadpool_insert(&threads, &sb_threads[i]);
2246 }
2247
2248 BLI_threadpool_end(&threads);
2249 }
2250 else {
2251 exec_softbody_calc_forces(&sb_threads[0]);
2252 }
2253 /* clean up */
2254 MEM_freeN(sb_threads);
2255}
2256
2258 Depsgraph *depsgraph, Scene *scene, Object *ob, float forcetime, float timenow)
2259{
2260 /* rule we never alter free variables :bp->vec bp->pos in here !
2261 * this will ruin adaptive stepsize AKA heun! (BM)
2262 */
2263 SoftBody *sb = ob->soft; /* is supposed to be there */
2264 // BodyPoint *bproot; /* UNUSED */
2265 // float gravity; /* UNUSED */
2266 // float iks;
2267 float fieldfactor = -1.0f, windfactor = 0.25;
2268 int do_deflector /*, do_selfcollision */, do_springcollision, do_aero;
2269
2270 // gravity = sb->grav * sb_grav_force_scale(ob); /* UNUSED */
2271
2272 /* check conditions for various options */
2274#if 0
2275 do_selfcollision = ((ob->softflag & OB_SB_EDGES) && (sb->bspring) &&
2276 (ob->softflag & OB_SB_SELF));
2277#endif
2278 do_springcollision = do_deflector && (ob->softflag & OB_SB_EDGES) &&
2279 (ob->softflag & OB_SB_EDGECOLL);
2280 do_aero = ((sb->aeroedge) && (ob->softflag & OB_SB_EDGES));
2281
2282 // iks = 1.0f / (1.0f - sb->inspring) - 1.0f; /* Inner spring constants function. */ /* UNUSED */
2283 // bproot = sb->bpoint; /* Need this for proper spring addressing. */ /* UNUSED */
2284
2285 if (do_springcollision || do_aero) {
2286 sb_sfesf_threads_run(depsgraph, scene, ob, timenow, sb->totspring, nullptr);
2287 }
2288
2289 /* After spring scan because it uses effectors too. */
2290 ListBase *effectors = BKE_effectors_create(depsgraph, ob, nullptr, sb->effector_weights, false);
2291
2292 if (do_deflector) {
2293 float defforce[3];
2294 do_deflector = sb_detect_aabb_collisionCached(defforce, ob, timenow);
2295 }
2296
2297 sb_cf_threads_run(scene,
2298 ob,
2299 forcetime,
2300 timenow,
2301 sb->totpoint,
2302 nullptr,
2303 effectors,
2304 do_deflector,
2305 fieldfactor,
2306 windfactor);
2307
2308 /* finally add forces caused by face collision */
2309 if (ob->softflag & OB_SB_FACECOLL) {
2310 scan_for_ext_face_forces(ob, timenow);
2311 }
2312
2313 /* finish matrix and solve */
2314 BKE_effectors_free(effectors);
2315}
2316
2317static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err, int mid_flags)
2318{
2319 /* time evolution */
2320 /* actually does an explicit euler step mode == 0 */
2321 /* or heun ~ 2nd order runge-kutta steps, mode 1, 2 */
2322 SoftBody *sb = ob->soft; /* is supposed to be there */
2323 BodyPoint *bp;
2324 float dx[3] = {0}, dv[3], aabbmin[3], aabbmax[3], cm[3] = {0.0f, 0.0f, 0.0f};
2325 float timeovermass /*, freezeloc=0.00001f, freezeforce=0.00000000001f*/;
2326 float maxerrpos = 0.0f, maxerrvel = 0.0f;
2327 int a, fuzzy = 0;
2328
2329 forcetime *= sb_time_scale(ob);
2330
2331 aabbmin[0] = aabbmin[1] = aabbmin[2] = 1e20f;
2332 aabbmax[0] = aabbmax[1] = aabbmax[2] = -1e20f;
2333
2334 /* old one with homogeneous masses */
2335 /* claim a minimum mass for vertex */
2336#if 0
2337 if (sb->nodemass > 0.009999f) {
2338 timeovermass = forcetime / sb->nodemass;
2339 }
2340 else {
2341 timeovermass = forcetime / 0.009999f;
2342 }
2343#endif
2344
2345 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
2346 /* Now we have individual masses. */
2347 /* claim a minimum mass for vertex */
2348 if (_final_mass(ob, bp) > 0.009999f) {
2349 timeovermass = forcetime / _final_mass(ob, bp);
2350 }
2351 else {
2352 timeovermass = forcetime / 0.009999f;
2353 }
2354
2355 if (_final_goal(ob, bp) < SOFTGOALSNAP) {
2356 /* this makes t~ = t */
2357 if (mid_flags & MID_PRESERVE) {
2358 copy_v3_v3(dx, bp->vec);
2359 }
2360
2375 mul_v3_fl(bp->force, timeovermass); /* individual mass of node here */
2376 /* some nasty if's to have heun in here too */
2377 copy_v3_v3(dv, bp->force);
2378
2379 if (mode == 1) {
2380 copy_v3_v3(bp->prevvec, bp->vec);
2381 copy_v3_v3(bp->prevdv, dv);
2382 }
2383
2384 if (mode == 2) {
2385 /* be optimistic and execute step */
2386 bp->vec[0] = bp->prevvec[0] + 0.5f * (dv[0] + bp->prevdv[0]);
2387 bp->vec[1] = bp->prevvec[1] + 0.5f * (dv[1] + bp->prevdv[1]);
2388 bp->vec[2] = bp->prevvec[2] + 0.5f * (dv[2] + bp->prevdv[2]);
2389 /* compare euler to heun to estimate error for step sizing */
2390 maxerrvel = max_ff(maxerrvel, fabsf(dv[0] - bp->prevdv[0]));
2391 maxerrvel = max_ff(maxerrvel, fabsf(dv[1] - bp->prevdv[1]));
2392 maxerrvel = max_ff(maxerrvel, fabsf(dv[2] - bp->prevdv[2]));
2393 }
2394 else {
2395 add_v3_v3(bp->vec, bp->force);
2396 }
2397
2398 /* This makes `t~ = t+dt`. */
2399 if (!(mid_flags & MID_PRESERVE)) {
2400 copy_v3_v3(dx, bp->vec);
2401 }
2402
2403 /* So here is: `(x)'= v(elocity)`.
2404 * The euler step for location then becomes:
2405 * `x(t + dt) = x(t) + v(t~) * dt` */
2406 mul_v3_fl(dx, forcetime);
2407
2408 /* the freezer coming sooner or later */
2409#if 0
2410 if ((dot_v3v3(dx, dx) < freezeloc) && (dot_v3v3(bp->force, bp->force) < freezeforce)) {
2411 bp->frozen /= 2;
2412 }
2413 else {
2414 bp->frozen = min_ff(bp->frozen * 1.05f, 1.0f);
2415 }
2416 mul_v3_fl(dx, bp->frozen);
2417#endif
2418 /* again some nasty if's to have heun in here too */
2419 if (mode == 1) {
2420 copy_v3_v3(bp->prevpos, bp->pos);
2421 copy_v3_v3(bp->prevdx, dx);
2422 }
2423
2424 if (mode == 2) {
2425 bp->pos[0] = bp->prevpos[0] + 0.5f * (dx[0] + bp->prevdx[0]);
2426 bp->pos[1] = bp->prevpos[1] + 0.5f * (dx[1] + bp->prevdx[1]);
2427 bp->pos[2] = bp->prevpos[2] + 0.5f * (dx[2] + bp->prevdx[2]);
2428 maxerrpos = max_ff(maxerrpos, fabsf(dx[0] - bp->prevdx[0]));
2429 maxerrpos = max_ff(maxerrpos, fabsf(dx[1] - bp->prevdx[1]));
2430 maxerrpos = max_ff(maxerrpos, fabsf(dx[2] - bp->prevdx[2]));
2431
2432 /* bp->choke is set when we need to pull a vertex or edge out of the collider.
2433 * the collider object signals to get out by pushing hard. on the other hand
2434 * we don't want to end up in deep space so we add some <viscosity>
2435 * to balance that out */
2436 if (bp->choke2 > 0.0f) {
2437 mul_v3_fl(bp->vec, (1.0f - bp->choke2));
2438 }
2439 if (bp->choke > 0.0f) {
2440 mul_v3_fl(bp->vec, (1.0f - bp->choke));
2441 }
2442 }
2443 else {
2444 add_v3_v3(bp->pos, dx);
2445 }
2446 } /*snap*/
2447 /* so while we are looping BPs anyway do statistics on the fly */
2448 minmax_v3v3_v3(aabbmin, aabbmax, bp->pos);
2449 if (bp->loc_flag & SBF_DOFUZZY) {
2450 fuzzy = 1;
2451 }
2452 } /*for*/
2453
2454 if (sb->totpoint) {
2455 mul_v3_fl(cm, 1.0f / sb->totpoint);
2456 }
2457 if (sb->scratch) {
2458 copy_v3_v3(sb->scratch->aabbmin, aabbmin);
2459 copy_v3_v3(sb->scratch->aabbmax, aabbmax);
2460 }
2461
2462 if (err) { /* so step size will be controlled by biggest difference in slope */
2463 if (sb->solverflags & SBSO_OLDERR) {
2464 *err = max_ff(maxerrpos, maxerrvel);
2465 }
2466 else {
2467 *err = maxerrpos;
2468 }
2469 // printf("EP %f EV %f\n", maxerrpos, maxerrvel);
2470 if (fuzzy) {
2471 *err /= sb->fuzzyness;
2472 }
2473 }
2474}
2475
2476/* used by heun when it overshoots */
2478{
2479 SoftBody *sb = ob->soft; /* is supposed to be there. */
2480 BodyPoint *bp;
2481 int a;
2482
2483 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
2484 copy_v3_v3(bp->vec, bp->prevvec);
2485 copy_v3_v3(bp->pos, bp->prevpos);
2486 }
2487}
2488
2489#if 0
2490static void softbody_store_step(Object *ob)
2491{
2492 SoftBody *sb = ob->soft; /* is supposed to be there. */
2493 BodyPoint *bp;
2494 int a;
2495
2496 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
2497 copy_v3_v3(bp->prevvec, bp->vec);
2498 copy_v3_v3(bp->prevpos, bp->pos);
2499 }
2500}
2501
2502/* used by predictors and correctors */
2503static void softbody_store_state(Object *ob, float *ppos, float *pvel)
2504{
2505 SoftBody *sb = ob->soft; /* is supposed to be there. */
2506 BodyPoint *bp;
2507 int a;
2508 float *pp = ppos, *pv = pvel;
2509
2510 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
2511
2512 copy_v3_v3(pv, bp->vec);
2513 pv += 3;
2514
2515 copy_v3_v3(pp, bp->pos);
2516 pp += 3;
2517 }
2518}
2519
2520/* used by predictors and correctors */
2521static void softbody_retrieve_state(Object *ob, float *ppos, float *pvel)
2522{
2523 SoftBody *sb = ob->soft; /* is supposed to be there. */
2524 BodyPoint *bp;
2525 int a;
2526 float *pp = ppos, *pv = pvel;
2527
2528 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
2529
2530 copy_v3_v3(bp->vec, pv);
2531 pv += 3;
2532
2533 copy_v3_v3(bp->pos, pp);
2534 pp += 3;
2535 }
2536}
2537
2538/* used by predictors and correctors */
2539static void softbody_swap_state(Object *ob, float *ppos, float *pvel)
2540{
2541 SoftBody *sb = ob->soft; /* is supposed to be there. */
2542 BodyPoint *bp;
2543 int a;
2544 float *pp = ppos, *pv = pvel;
2545 float temp[3];
2546
2547 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
2548
2549 copy_v3_v3(temp, bp->vec);
2550 copy_v3_v3(bp->vec, pv);
2551 copy_v3_v3(pv, temp);
2552 pv += 3;
2553
2554 copy_v3_v3(temp, bp->pos);
2555 copy_v3_v3(bp->pos, pp);
2556 copy_v3_v3(pp, temp);
2557 pp += 3;
2558 }
2559}
2560#endif
2561
2570{
2571 SoftBody *sb = ob->soft; /* is supposed to be there */
2572 BodyPoint *bp;
2573 int a;
2574
2575 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
2576 if (_final_goal(ob, bp) >= SOFTGOALSNAP) {
2577 copy_v3_v3(bp->prevpos, bp->pos);
2578 copy_v3_v3(bp->pos, bp->origT);
2579 }
2580 }
2581}
2582
2584{
2585 SoftBody *sb = ob->soft;
2586 BodySpring *bs;
2587 BodyPoint *bp1, *bp2;
2588 int a;
2589 float b, l, r;
2590
2591 if (sb && sb->totspring) {
2592 b = sb->plastic;
2593 for (a = 0; a < sb->totspring; a++) {
2594 bs = &sb->bspring[a];
2595 bp1 = &sb->bpoint[bs->v1];
2596 bp2 = &sb->bpoint[bs->v2];
2597 l = len_v3v3(bp1->pos, bp2->pos);
2598 r = bs->len / l;
2599 if ((r > 1.05f) || (r < 0.95f)) {
2600 bs->len = ((100.0f - b) * bs->len + b * l) / 100.0f;
2601 }
2602 }
2603 }
2604}
2605
2606/* expects full initialized softbody */
2607static void interpolate_exciter(Object *ob, int timescale, int time)
2608{
2609 SoftBody *sb = ob->soft;
2610 BodyPoint *bp;
2611 float f;
2612 int a;
2613
2614 f = float(time) / float(timescale);
2615
2616 for (a = sb->totpoint, bp = sb->bpoint; a > 0; a--, bp++) {
2617 bp->origT[0] = bp->origS[0] + f * (bp->origE[0] - bp->origS[0]);
2618 bp->origT[1] = bp->origS[1] + f * (bp->origE[1] - bp->origS[1]);
2619 bp->origT[2] = bp->origS[2] + f * (bp->origE[2] - bp->origS[2]);
2620 if (_final_goal(ob, bp) >= SOFTGOALSNAP) {
2621 bp->vec[0] = bp->origE[0] - bp->origS[0];
2622 bp->vec[1] = bp->origE[1] - bp->origS[1];
2623 bp->vec[2] = bp->origE[2] - bp->origS[2];
2624 }
2625 }
2626}
2627
2628/* ************ converters ********** */
2629
2630/* for each object type we need;
2631 * - xxxx_to_softbody(Object *ob) : a full (new) copy, creates SB geometry
2632 */
2633
2634/* Resetting a Mesh SB object's springs */
2635/* Spring length are calculated from 'raw' mesh vertices that are NOT altered by modifier stack. */
2637{
2638 SoftBody *sb;
2639 Mesh *mesh = static_cast<Mesh *>(ob->data);
2640 BodyPoint *bp;
2641 int a;
2642 float scale = 1.0f;
2643 const blender::Span<blender::float3> positions = mesh->vert_positions();
2644
2645 sb = ob->soft;
2646 if (mesh && sb) {
2647 /* using bp->origS as a container for spring calculations here
2648 * will be overwritten sbObjectStep() to receive
2649 * actual modifier stack vert_positions
2650 */
2651 if (mesh->verts_num) {
2652 bp = ob->soft->bpoint;
2653 for (a = 0; a < mesh->verts_num; a++, bp++) {
2654 copy_v3_v3(bp->origS, positions[a]);
2655 mul_m4_v3(ob->object_to_world().ptr(), bp->origS);
2656 }
2657 }
2658 /* recalculate spring length for meshes here */
2659 /* public version shrink to fit */
2660 if (sb->springpreload != 0) {
2661 scale = sb->springpreload / 100.0f;
2662 }
2663 for (a = 0; a < sb->totspring; a++) {
2664 BodySpring *bs = &sb->bspring[a];
2665 bs->len = scale * len_v3v3(sb->bpoint[bs->v1].origS, sb->bpoint[bs->v2].origS);
2666 }
2667 }
2668}
2669
2670/* makes totally fresh start situation */
2671static void mesh_to_softbody(Object *ob)
2672{
2673 SoftBody *sb;
2674 Mesh *mesh = static_cast<Mesh *>(ob->data);
2675 const blender::Span<blender::int2> edges = mesh->edges();
2676 BodyPoint *bp;
2677 int a, totedge;
2678 int defgroup_index, defgroup_index_mass, defgroup_index_spring;
2679
2680 if (ob->softflag & OB_SB_EDGES) {
2681 totedge = mesh->edges_num;
2682 }
2683 else {
2684 totedge = 0;
2685 }
2686
2687 /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
2688 renew_softbody(ob, mesh->verts_num, totedge);
2689
2690 /* we always make body points */
2691 sb = ob->soft;
2692 bp = sb->bpoint;
2693
2694 const MDeformVert *dvert = mesh->deform_verts().data();
2695
2696 defgroup_index = dvert ? (sb->vertgroup - 1) : -1;
2697 defgroup_index_mass = dvert ? BKE_id_defgroup_name_index(&mesh->id, sb->namedVG_Mass) : -1;
2698 defgroup_index_spring = dvert ? BKE_id_defgroup_name_index(&mesh->id, sb->namedVG_Spring_K) : -1;
2699
2700 for (a = 0; a < mesh->verts_num; a++, bp++) {
2701 /* get scalar values needed *per vertex* from vertex group functions,
2702 * so we can *paint* them nicely ..
2703 * they are normalized [0.0..1.0] so may be we need amplitude for scale
2704 * which can be done by caller but still .. i'd like it to go this way
2705 */
2706
2707 if (ob->softflag & OB_SB_GOAL) {
2708 BLI_assert(bp->goal == sb->defgoal);
2709 }
2710 if ((ob->softflag & OB_SB_GOAL) && (defgroup_index != -1)) {
2711 bp->goal *= BKE_defvert_find_weight(&dvert[a], defgroup_index);
2712 }
2713
2714 /* to proof the concept
2715 * this enables per vertex *mass painting*
2716 */
2717
2718 if (defgroup_index_mass != -1) {
2719 bp->mass *= BKE_defvert_find_weight(&dvert[a], defgroup_index_mass);
2720 }
2721
2722 if (defgroup_index_spring != -1) {
2723 bp->springweight *= BKE_defvert_find_weight(&dvert[a], defgroup_index_spring);
2724 }
2725 }
2726
2727 /* but we only optionally add body edge springs */
2728 if (ob->softflag & OB_SB_EDGES) {
2729 if (!edges.is_empty()) {
2730 for (const int i : edges.index_range()) {
2731 sb->bspring[i].v1 = edges[i][0];
2732 sb->bspring[i].v2 = edges[i][1];
2733 sb->bspring[i].springtype = SB_EDGE;
2734 }
2735
2736 /* insert *diagonal* springs in quads if desired */
2737 if (ob->softflag & OB_SB_QUADS) {
2739 }
2740
2741 build_bps_springlist(ob); /* Scan for springs attached to body-points *once*. */
2742 /* insert *other second order* springs if desired */
2743 if (sb->secondspring > 0.0000001f) {
2744 /* Exploits the first run of `build_bps_springlist(ob)`. */
2746 /* yes we need to do it again. */
2748 }
2749 springs_from_mesh(ob); /* write the *rest*-length of the springs */
2750 if (ob->softflag & OB_SB_SELF) {
2752 }
2753 }
2754 }
2755}
2756
2758{
2759 SoftBody *sb = ob->soft;
2760 const Mesh *mesh = static_cast<const Mesh *>(ob->data);
2761 BodyFace *bodyface;
2762 int a;
2763 const blender::Span<int> corner_verts = mesh->corner_verts();
2764
2765 /* Allocate and copy faces. */
2766
2770 mesh->vert_positions(), mesh->faces(), mesh->corner_verts(), corner_tris);
2771
2772 bodyface = sb->scratch->bodyface = MEM_malloc_arrayN<BodyFace>(size_t(sb->scratch->bodyface_num),
2773 "SB_body_Faces");
2774
2775 for (a = 0; a < sb->scratch->bodyface_num; a++, bodyface++) {
2776 bodyface->v1 = corner_verts[corner_tris[a][0]];
2777 bodyface->v2 = corner_verts[corner_tris[a][1]];
2778 bodyface->v3 = corner_verts[corner_tris[a][2]];
2779 zero_v3(bodyface->ext_force);
2780 bodyface->ext_force[0] = bodyface->ext_force[1] = bodyface->ext_force[2] = 0.0f;
2781 bodyface->flag = 0;
2782 }
2783}
2785{
2786 SoftBody *sb = ob->soft;
2787 ReferenceVert *rp;
2788 BodyPoint *bp;
2789 float accu_pos[3] = {0.0f, 0.0f, 0.0f};
2790 float accu_mass = 0.0f;
2791 int a;
2792
2793 sb->scratch->Ref.ivert = MEM_malloc_arrayN<ReferenceVert>(size_t(sb->totpoint), "SB_Reference");
2794 bp = ob->soft->bpoint;
2795 rp = sb->scratch->Ref.ivert;
2796 for (a = 0; a < sb->totpoint; a++, rp++, bp++) {
2797 copy_v3_v3(rp->pos, bp->pos);
2798 add_v3_v3(accu_pos, bp->pos);
2799 accu_mass += _final_mass(ob, bp);
2800 }
2801 mul_v3_fl(accu_pos, 1.0f / accu_mass);
2802 copy_v3_v3(sb->scratch->Ref.com, accu_pos);
2803 // printf("reference_to_scratch\n");
2804}
2805
2810static float globallen(float *v1, float *v2, Object *ob)
2811{
2812 float p1[3], p2[3];
2813 copy_v3_v3(p1, v1);
2814 mul_m4_v3(ob->object_to_world().ptr(), p1);
2815 copy_v3_v3(p2, v2);
2816 mul_m4_v3(ob->object_to_world().ptr(), p2);
2817 return len_v3v3(p1, p2);
2818}
2819
2820static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff, Object *ob)
2821{
2822 BPoint *bp = lt->def, *bpu;
2823 int u, v, w, dv, dw, bpc = 0, bpuc;
2824
2825 dv = lt->pntsu;
2826 dw = dv * lt->pntsv;
2827
2828 for (w = 0; w < lt->pntsw; w++) {
2829
2830 for (v = 0; v < lt->pntsv; v++) {
2831
2832 for (u = 0, bpuc = 0, bpu = nullptr; u < lt->pntsu; u++, bp++, bpc++) {
2833
2834 if (w) {
2835 bs->v1 = bpc;
2836 bs->v2 = bpc - dw;
2837 bs->springtype = SB_EDGE;
2838 bs->len = globallen((bp - dw)->vec, bp->vec, ob);
2839 bs++;
2840 }
2841 if (v) {
2842 bs->v1 = bpc;
2843 bs->v2 = bpc - dv;
2844 bs->springtype = SB_EDGE;
2845 bs->len = globallen((bp - dv)->vec, bp->vec, ob);
2846 bs++;
2847 }
2848 if (u) {
2849 bs->v1 = bpuc;
2850 bs->v2 = bpc;
2851 bs->springtype = SB_EDGE;
2852 bs->len = globallen((bpu)->vec, bp->vec, ob);
2853 bs++;
2854 }
2855
2856 if (dostiff) {
2857
2858 if (w) {
2859 if (v && u) {
2860 bs->v1 = bpc;
2861 bs->v2 = bpc - dw - dv - 1;
2862 bs->springtype = SB_BEND;
2863 bs->len = globallen((bp - dw - dv - 1)->vec, bp->vec, ob);
2864 bs++;
2865 }
2866 if ((v < lt->pntsv - 1) && (u != 0)) {
2867 bs->v1 = bpc;
2868 bs->v2 = bpc - dw + dv - 1;
2869 bs->springtype = SB_BEND;
2870 bs->len = globallen((bp - dw + dv - 1)->vec, bp->vec, ob);
2871 bs++;
2872 }
2873 }
2874
2875 if (w < lt->pntsw - 1) {
2876 if (v && u) {
2877 bs->v1 = bpc;
2878 bs->v2 = bpc + dw - dv - 1;
2879 bs->springtype = SB_BEND;
2880 bs->len = globallen((bp + dw - dv - 1)->vec, bp->vec, ob);
2881 bs++;
2882 }
2883 if ((v < lt->pntsv - 1) && (u != 0)) {
2884 bs->v1 = bpc;
2885 bs->v2 = bpc + dw + dv - 1;
2886 bs->springtype = SB_BEND;
2887 bs->len = globallen((bp + dw + dv - 1)->vec, bp->vec, ob);
2888 bs++;
2889 }
2890 }
2891 }
2892 bpu = bp;
2893 bpuc = bpc;
2894 }
2895 }
2896 }
2897}
2898
2899/* makes totally fresh start situation */
2901{
2902 Lattice *lt = static_cast<Lattice *>(ob->data);
2903 SoftBody *sb;
2904 int totvert, totspring = 0, a;
2905 BodyPoint *bp;
2906 BPoint *bpnt = lt->def;
2907 int defgroup_index, defgroup_index_mass, defgroup_index_spring;
2908
2909 totvert = lt->pntsu * lt->pntsv * lt->pntsw;
2910
2911 if (ob->softflag & OB_SB_EDGES) {
2912 totspring = ((lt->pntsu - 1) * lt->pntsv + (lt->pntsv - 1) * lt->pntsu) * lt->pntsw +
2913 lt->pntsu * lt->pntsv * (lt->pntsw - 1);
2914 if (ob->softflag & OB_SB_QUADS) {
2915 totspring += 4 * (lt->pntsu - 1) * (lt->pntsv - 1) * (lt->pntsw - 1);
2916 }
2917 }
2918
2919 /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
2920 renew_softbody(ob, totvert, totspring);
2921 sb = ob->soft; /* can be created in renew_softbody() */
2922 bp = sb->bpoint;
2923
2924 defgroup_index = lt->dvert ? (sb->vertgroup - 1) : -1;
2925 defgroup_index_mass = lt->dvert ? BKE_id_defgroup_name_index(&lt->id, sb->namedVG_Mass) : -1;
2926 defgroup_index_spring = lt->dvert ? BKE_id_defgroup_name_index(&lt->id, sb->namedVG_Spring_K) :
2927 -1;
2928
2929 /* same code used as for mesh vertices */
2930 for (a = 0; a < totvert; a++, bp++, bpnt++) {
2931
2932 if (ob->softflag & OB_SB_GOAL) {
2933 BLI_assert(bp->goal == sb->defgoal);
2934 }
2935
2936 if ((ob->softflag & OB_SB_GOAL) && (defgroup_index != -1)) {
2937 bp->goal *= BKE_defvert_find_weight(&lt->dvert[a], defgroup_index);
2938 }
2939 else {
2940 bp->goal *= bpnt->weight;
2941 }
2942
2943 if (defgroup_index_mass != -1) {
2944 bp->mass *= BKE_defvert_find_weight(&lt->dvert[a], defgroup_index_mass);
2945 }
2946
2947 if (defgroup_index_spring != -1) {
2948 bp->springweight *= BKE_defvert_find_weight(&lt->dvert[a], defgroup_index_spring);
2949 }
2950 }
2951
2952 /* create some helper edges to enable SB lattice to be useful at all */
2953 if (ob->softflag & OB_SB_EDGES) {
2954 makelatticesprings(lt, ob->soft->bspring, ob->softflag & OB_SB_QUADS, ob);
2955 build_bps_springlist(ob); /* link bps to springs */
2956 if (ob->softflag & OB_SB_SELF) {
2958 }
2959 }
2960}
2961
2962/* makes totally fresh start situation */
2964{
2965 Curve *cu = static_cast<Curve *>(ob->data);
2966 SoftBody *sb;
2967 BodyPoint *bp;
2968 BodySpring *bs;
2969 BezTriple *bezt;
2970 BPoint *bpnt;
2971 int a, curindex = 0;
2972 int totvert, totspring = 0, setgoal = 0;
2973
2974 totvert = BKE_nurbList_verts_count(&cu->nurb);
2975
2976 if (ob->softflag & OB_SB_EDGES) {
2977 if (ob->type == OB_CURVES_LEGACY) {
2978 totspring = totvert - BLI_listbase_count(&cu->nurb);
2979 }
2980 }
2981
2982 /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
2983 renew_softbody(ob, totvert, totspring);
2984 sb = ob->soft; /* can be created in renew_softbody() */
2985
2986 /* set vars now */
2987 bp = sb->bpoint;
2988 bs = sb->bspring;
2989
2990 /* Weights from bpoints, same code used as for mesh vertices. */
2991 /* if ((ob->softflag & OB_SB_GOAL) && sb->vertgroup) 2.4x hack. */
2992 /* new! take the weights from curve vertex anyhow */
2993 if (ob->softflag & OB_SB_GOAL) {
2994 setgoal = 1;
2995 }
2996
2997 LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
2998 if (nu->bezt) {
2999 /* Bezier case; this is nicely said naive; who ever wrote this part,
3000 * it was not me (JOW) :).
3001 *
3002 * a: never ever make tangent handles (sub) and or (ob)ject to collision.
3003 * b: rather calculate them using some C2
3004 * (C2= continuous in second derivative -> no jump in bending ) condition.
3005 *
3006 * Not too hard to do, but needs some more code to care for;
3007 * some one may want look at it (JOW 2010/06/12). */
3008 for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++, bp += 3, curindex += 3) {
3009 if (setgoal) {
3010 bp->goal *= bezt->weight;
3011
3012 /* All three triples. */
3013 (bp + 1)->goal = bp->goal;
3014 (bp + 2)->goal = bp->goal;
3015 /* Do not collide handles. */
3016 (bp + 1)->loc_flag |= SBF_OUTOFCOLLISION;
3017 (bp + 2)->loc_flag |= SBF_OUTOFCOLLISION;
3018 }
3019
3020 if (totspring) {
3021 if (a > 0) {
3022 bs->v1 = curindex - 3;
3023 bs->v2 = curindex;
3024 bs->springtype = SB_HANDLE;
3025 bs->len = globallen((bezt - 1)->vec[0], bezt->vec[0], ob);
3026 bs++;
3027 }
3028 bs->v1 = curindex;
3029 bs->v2 = curindex + 1;
3030 bs->springtype = SB_HANDLE;
3031 bs->len = globallen(bezt->vec[0], bezt->vec[1], ob);
3032 bs++;
3033
3034 bs->v1 = curindex + 1;
3035 bs->v2 = curindex + 2;
3036 bs->springtype = SB_HANDLE;
3037 bs->len = globallen(bezt->vec[1], bezt->vec[2], ob);
3038 bs++;
3039 }
3040 }
3041 }
3042 else {
3043 for (bpnt = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bpnt++, bp++, curindex++) {
3044 if (setgoal) {
3045 bp->goal *= bpnt->weight;
3046 }
3047 if (totspring && a > 0) {
3048 bs->v1 = curindex - 1;
3049 bs->v2 = curindex;
3050 bs->springtype = SB_EDGE;
3051 bs->len = globallen((bpnt - 1)->vec, bpnt->vec, ob);
3052 bs++;
3053 }
3054 }
3055 }
3056 }
3057
3058 if (totspring) {
3059 build_bps_springlist(ob); /* link bps to springs */
3060 if (ob->softflag & OB_SB_SELF) {
3062 }
3063 }
3064}
3065
3066/* copies softbody result back in object */
3067static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, int local)
3068{
3069 SoftBody *sb = ob->soft;
3070 if (sb) {
3071 BodyPoint *bp = sb->bpoint;
3072 int a;
3073 if (sb->solverflags & SBSO_ESTIMATEIPO) {
3074 SB_estimate_transform(ob, sb->lcom, sb->lrot, sb->lscale);
3075 }
3076 /* Inverse matrix is not up to date. */
3077 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
3078
3079 for (a = 0; a < numVerts; a++, bp++) {
3080 copy_v3_v3(vertexCos[a], bp->pos);
3081 if (local == 0) {
3082 /* softbody is in global coords, baked optionally not */
3083 mul_m4_v3(ob->world_to_object().ptr(), vertexCos[a]);
3084 }
3085 }
3086 }
3087}
3088
3089/* +++ ************ maintaining scratch *************** */
3090static void sb_new_scratch(SoftBody *sb)
3091{
3092 if (!sb) {
3093 return;
3094 }
3095 sb->scratch = MEM_callocN<SBScratch>("SBScratch");
3096 sb->scratch->colliderhash = BLI_ghash_ptr_new("sb_new_scratch gh");
3097 sb->scratch->bodyface = nullptr;
3098 sb->scratch->bodyface_num = 0;
3099 sb->scratch->aabbmax[0] = sb->scratch->aabbmax[1] = sb->scratch->aabbmax[2] = 1.0e30f;
3100 sb->scratch->aabbmin[0] = sb->scratch->aabbmin[1] = sb->scratch->aabbmin[2] = -1.0e30f;
3101 sb->scratch->Ref.ivert = nullptr;
3102}
3103/* --- ************ maintaining scratch *************** */
3104
3105/* ************ Object level, exported functions *************** */
3106
3108{
3109 SoftBody *sb;
3110
3111 sb = MEM_callocN<SoftBody>("softbody");
3112
3113 sb->mediafrict = 0.5f;
3114 sb->nodemass = 1.0f;
3115 sb->grav = 9.8f;
3116 sb->physics_speed = 1.0f;
3117 sb->rklimit = 0.1f;
3118
3119 sb->goalspring = 0.5f;
3120 sb->goalfrict = 0.0f;
3121 sb->mingoal = 0.0f;
3122 sb->maxgoal = 1.0f;
3123 sb->defgoal = 0.7f;
3124
3125 sb->inspring = 0.5f;
3126 sb->infrict = 0.5f;
3127 /* TODO: backward file compatibility should copy `inspring` to `inpush` while reading old files.
3128 */
3129 sb->inpush = 0.5f;
3130
3131 sb->colball = 0.49f;
3132 sb->balldamp = 0.50f;
3133 sb->ballstiff = 1.0f;
3134 sb->sbc_mode = 1;
3135
3136 sb->minloops = 10;
3137 sb->maxloops = 300;
3138
3139 sb->choke = 3;
3140 sb->fuzzyness = 1;
3141 sb_new_scratch(sb);
3142 /* TODO: backward file compatibility should set `sb->shearstiff = 1.0f` while reading old files.
3143 */
3144 sb->shearstiff = 1.0f;
3145 sb->solverflags |= SBSO_OLDERR;
3146
3147 sb->shared = MEM_callocN<SoftBody_Shared>("SoftBody_Shared");
3149
3150 if (!sb->effector_weights) {
3152 }
3153
3154 sb->last_frame = MINFRAME - 1;
3155
3156 return sb;
3157}
3158
3160{
3161 SoftBody *sb = ob->soft;
3162 if (sb == nullptr) {
3163 return;
3164 }
3165
3166 const bool is_orig = (ob->id.tag & ID_TAG_COPIED_ON_EVAL) == 0;
3167
3169
3170 if (is_orig) {
3171 /* Only free shared data on non-evaluated copies */
3173 sb->shared->pointcache = nullptr;
3174 MEM_freeN(sb->shared);
3175 }
3176 if (sb->effector_weights) {
3178 }
3179 MEM_freeN(sb);
3180
3181 ob->soft = nullptr;
3182}
3183
3185{
3187}
3188
3190{
3191 // ob->softflag |= OB_SB_REDO;
3192
3194}
3195
3196static bool object_has_edges(const Object *ob)
3197{
3198 if (ob->type == OB_MESH) {
3199 return ((Mesh *)ob->data)->edges_num;
3200 }
3201 if (ob->type == OB_LATTICE) {
3202 return true;
3203 }
3204
3205 return false;
3206}
3207
3209{
3211}
3212
3214 SoftBody *sb,
3215 float (*vertexCos)[3],
3216 int numVerts)
3217{
3218 BodyPoint *bp;
3219 int a;
3220
3221 if (!sb || !sb->bpoint) {
3222 return;
3223 }
3224
3225 for (a = 0, bp = sb->bpoint; a < numVerts; a++, bp++) {
3226 /* store where goals are now */
3227 copy_v3_v3(bp->origS, bp->origE);
3228 /* copy the position of the goals at desired end time */
3229 copy_v3_v3(bp->origE, vertexCos[a]);
3230 /* vertexCos came from local world, go global */
3231 mul_m4_v3(ob->object_to_world().ptr(), bp->origE);
3232 /* just to be save give bp->origT a defined value
3233 * will be calculated in interpolate_exciter() */
3234 copy_v3_v3(bp->origT, bp->origE);
3235 }
3236}
3237
3238void SB_estimate_transform(Object *ob, float lloc[3], float lrot[3][3], float lscale[3][3])
3239{
3240 BodyPoint *bp;
3241 ReferenceVert *rp;
3242 SoftBody *sb = nullptr;
3243 float (*opos)[3];
3244 float (*rpos)[3];
3245 float com[3], rcom[3];
3246 int a;
3247
3248 if (!ob || !ob->soft) {
3249 return; /* why did we get here ? */
3250 }
3251 sb = ob->soft;
3252 if (!sb || !sb->bpoint) {
3253 return;
3254 }
3255 opos = MEM_calloc_arrayN<float[3]>(sb->totpoint, "SB_OPOS");
3256 rpos = MEM_calloc_arrayN<float[3]>(sb->totpoint, "SB_RPOS");
3257 /* might filter vertex selection with a vertex group */
3258 for (a = 0, bp = sb->bpoint, rp = sb->scratch->Ref.ivert; a < sb->totpoint; a++, bp++, rp++) {
3259 copy_v3_v3(rpos[a], rp->pos);
3260 copy_v3_v3(opos[a], bp->pos);
3261 }
3262
3264 sb->totpoint, opos, nullptr, rpos, nullptr, com, rcom, lrot, lscale);
3265 // sub_v3_v3(com, rcom);
3266 if (lloc) {
3267 copy_v3_v3(lloc, com);
3268 }
3269 copy_v3_v3(sb->lcom, com);
3270 if (lscale) {
3271 copy_m3_m3(sb->lscale, lscale);
3272 }
3273 if (lrot) {
3274 copy_m3_m3(sb->lrot, lrot);
3275 }
3276
3277 MEM_freeN(opos);
3278 MEM_freeN(rpos);
3279}
3280
3281static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts)
3282{
3283 BodyPoint *bp;
3284 int a;
3285
3286 for (a = 0, bp = sb->bpoint; a < numVerts; a++, bp++) {
3287 copy_v3_v3(bp->pos, vertexCos[a]);
3288 mul_m4_v3(ob->object_to_world().ptr(), bp->pos); /* Yep, soft-body is global coords. */
3289 copy_v3_v3(bp->origS, bp->pos);
3290 copy_v3_v3(bp->origE, bp->pos);
3291 copy_v3_v3(bp->origT, bp->pos);
3292 bp->vec[0] = bp->vec[1] = bp->vec[2] = 0.0f;
3293
3294 /* The `bp->prev*` 's are for rolling back from a canceled try to propagate in time
3295 * adaptive step size algorithm in a nutshell:
3296 * 1) set scheduled time step to new dtime
3297 * 2) try to advance the scheduled time step, being optimistic execute it
3298 * 3) check for success
3299 * 3a) we 're fine continue, may be we can increase scheduled time again ?? if so, do so!
3300 * 3b) we did exceed error limit --> roll back, shorten the scheduled time and try again at 2.
3301 * 4) check if we did reach dtime
3302 * 4a) nope we need to do some more at 2.
3303 * 4b) yup we're done
3304 */
3305
3306 copy_v3_v3(bp->prevpos, bp->pos);
3307 copy_v3_v3(bp->prevvec, bp->vec);
3308 copy_v3_v3(bp->prevdx, bp->vec);
3309 copy_v3_v3(bp->prevdv, bp->vec);
3310 }
3311
3312 /* make a nice clean scratch struct */
3313 free_scratch(sb); /* clear if any */
3314 sb_new_scratch(sb); /* make a new */
3316 zero_v3(sb->lcom);
3317 unit_m3(sb->lrot);
3318 unit_m3(sb->lscale);
3319
3320 /* copy some info to scratch */
3321 /* we only need that if we want to reconstruct IPO */
3322 if (true) {
3324 SB_estimate_transform(ob, nullptr, nullptr, nullptr);
3325 SB_estimate_transform(ob, nullptr, nullptr, nullptr);
3326 }
3327 switch (ob->type) {
3328 case OB_MESH:
3329 if (ob->softflag & OB_SB_FACECOLL) {
3331 }
3332 break;
3333 case OB_LATTICE:
3334 break;
3335 case OB_CURVES_LEGACY:
3336 case OB_SURF:
3337 break;
3338 default:
3339 break;
3340 }
3341}
3342
3343static void softbody_step(
3344 Depsgraph *depsgraph, Scene *scene, Object *ob, SoftBody *sb, float dtime)
3345{
3346 /* the simulator */
3347 float forcetime;
3348 double sct, sst;
3349
3350 sst = BLI_time_now_seconds();
3351 /* Integration back in time is possible in theory, but pretty useless here.
3352 * So we refuse to do so. Since we do not know anything about 'outside' changes
3353 * especially colliders we refuse to go more than 10 frames.
3354 */
3355 if (dtime < 0 || dtime > 10.5f) {
3356 return;
3357 }
3358
3360
3361 if (sb->scratch->needstobuildcollider) {
3364 }
3365
3366 if (sb->solver_ID < 2) {
3367 /* special case of 2nd order Runge-Kutta type AKA Heun */
3368 int mid_flags = 0;
3369 float err = 0;
3370 /* Set defaults guess we shall do one frame */
3371 float forcetimemax = 1.0f;
3372 /* Set defaults guess 1/100 is tight enough */
3373 float forcetimemin = 0.01f;
3374 /* How far did we get without violating error condition. */
3375 float timedone = 0.0;
3376 /* Loops = counter for emergency brake we don't want to lock up the system if physics fail. */
3377 int loops = 0;
3378
3379 SoftHeunTol = sb->rklimit; /* Hum .. this should be calculated from sb parameters and sizes */
3380 /* adjust loop limits */
3381 if (sb->minloops > 0) {
3382 forcetimemax = dtime / sb->minloops;
3383 }
3384 if (sb->maxloops > 0) {
3385 forcetimemin = dtime / sb->maxloops;
3386 }
3387
3388 if (sb->solver_ID > 0) {
3389 mid_flags |= MID_PRESERVE;
3390 }
3391
3392 forcetime = forcetimemax; /* hope for integrating in one step */
3393 while ((fabsf(timedone) < fabsf(dtime)) && (loops < 2000)) {
3394 /* set goals in time */
3395 interpolate_exciter(ob, 200, int(200.0f * (timedone / dtime)));
3396
3397 sb->scratch->flag &= ~SBF_DOFUZZY;
3398 /* do predictive euler step */
3399 softbody_calc_forces(depsgraph, scene, ob, forcetime, timedone / dtime);
3400
3401 softbody_apply_forces(ob, forcetime, 1, nullptr, mid_flags);
3402
3403 /* crop new slope values to do averaged slope step */
3404 softbody_calc_forces(depsgraph, scene, ob, forcetime, timedone / dtime);
3405
3406 softbody_apply_forces(ob, forcetime, 2, &err, mid_flags);
3408
3409 if (err > SoftHeunTol) { /* error needs to be scaled to some quantity */
3410
3411 if (forcetime > forcetimemin) {
3412 forcetime = max_ff(forcetime / 2.0f, forcetimemin);
3414 // printf("down, ");
3415 }
3416 else {
3417 timedone += forcetime;
3418 }
3419 }
3420 else {
3421 float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */
3422
3423 if (sb->scratch->flag & SBF_DOFUZZY) {
3424 // /* stay with this stepsize unless err really small */
3425 // if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) {
3426 newtime = forcetime;
3427 // }
3428 }
3429 else {
3430 if (err > SoftHeunTol / 2.0f) { /* stay with this stepsize unless err really small */
3431 newtime = forcetime;
3432 }
3433 }
3434 timedone += forcetime;
3435 newtime = min_ff(forcetimemax, max_ff(newtime, forcetimemin));
3436 // if (newtime > forcetime) printf("up, ");
3437 if (forcetime > 0.0f) {
3438 forcetime = min_ff(dtime - timedone, newtime);
3439 }
3440 else {
3441 forcetime = max_ff(dtime - timedone, newtime);
3442 }
3443 }
3444 loops++;
3445 if (sb->solverflags & SBSO_MONITOR) {
3446 sct = BLI_time_now_seconds();
3447 if (sct - sst > 0.5) {
3448 printf("%3.0f%% \r", 100.0f * timedone / dtime);
3449 }
3450 }
3451 /* ask for user break */
3453 break;
3454 }
3455 }
3456 /* move snapped to final position */
3457 interpolate_exciter(ob, 2, 2);
3459
3460 // if (G.debug & G_DEBUG) {
3461 if (sb->solverflags & SBSO_MONITOR) {
3462 if (loops > HEUNWARNLIMIT) { /* monitor high loop counts */
3463 printf("\r needed %d steps/frame", loops);
3464 }
3465 }
3466 }
3467 else if (sb->solver_ID == 2) {
3468 /* do semi "fake" implicit euler */
3469 /* removed */
3470 } /* SOLVER SELECT */
3471 else if (sb->solver_ID == 4) {
3472 /* do semi "fake" implicit euler */
3473 } /* SOLVER SELECT */
3474 else if (sb->solver_ID == 3) {
3475 /* do "stupid" semi "fake" implicit euler */
3476 /* removed */
3477
3478 } /* SOLVER SELECT */
3479 else {
3480 CLOG_ERROR(&LOG, "softbody no valid solver ID!");
3481 } /* SOLVER SELECT */
3482 if (sb->plastic) {
3484 }
3485
3486 if (sb->solverflags & SBSO_MONITOR) {
3487 sct = BLI_time_now_seconds();
3488 if ((sct - sst > 0.5) || (G.debug & G_DEBUG)) {
3489 printf(" solver time %f sec %s\n", sct - sst, ob->id.name);
3490 }
3491 }
3492}
3493
3494static void sbStoreLastFrame(Depsgraph *depsgraph, Object *object, float framenr)
3495{
3496 if (!DEG_is_active(depsgraph)) {
3497 return;
3498 }
3499 Object *object_orig = DEG_get_original(object);
3500 object->soft->last_frame = framenr;
3501 object_orig->soft->last_frame = framenr;
3502}
3503
3504void sbObjectStep(Depsgraph *depsgraph,
3505 Scene *scene,
3506 Object *ob,
3507 float cfra,
3508 float (*vertexCos)[3],
3509 int numVerts)
3510{
3511 SoftBody *sb = ob->soft;
3512 PointCache *cache;
3513 PTCacheID pid;
3514 float dtime, timescale;
3515 int framedelta, framenr, startframe, endframe;
3516 int cache_result;
3517 cache = sb->shared->pointcache;
3518
3519 framenr = int(cfra);
3520 framedelta = framenr - cache->simframe;
3521
3522 BKE_ptcache_id_from_softbody(&pid, ob, sb);
3523 BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
3524
3525 /* check for changes in mesh, should only happen in case the mesh
3526 * structure changes during an animation */
3527 if (sb->bpoint && numVerts != sb->totpoint) {
3529 return;
3530 }
3531
3532 /* clamp frame ranges */
3533 if (framenr < startframe) {
3535 return;
3536 }
3537 framenr = std::min(framenr, endframe);
3538
3539 /* verify if we need to create the softbody data */
3540 if (sb->bpoint == nullptr ||
3541 ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob)))
3542 {
3543
3544 switch (ob->type) {
3545 case OB_MESH:
3546 mesh_to_softbody(ob);
3547 break;
3548 case OB_LATTICE:
3550 break;
3551 case OB_CURVES_LEGACY:
3552 case OB_SURF:
3554 break;
3555 default:
3556 renew_softbody(ob, numVerts, 0);
3557 break;
3558 }
3559
3560 softbody_update_positions(ob, sb, vertexCos, numVerts);
3561 softbody_reset(ob, sb, vertexCos, numVerts);
3562 }
3563
3564 /* still no points? go away */
3565 if (sb->totpoint == 0) {
3566 return;
3567 }
3568 if (framenr == startframe) {
3570
3571 /* first frame, no simulation to do, just set the vert_positions */
3572 softbody_update_positions(ob, sb, vertexCos, numVerts);
3573
3574 BKE_ptcache_validate(cache, framenr);
3575 cache->flag &= ~PTCACHE_REDO_NEEDED;
3576
3577 sbStoreLastFrame(depsgraph, ob, framenr);
3578
3579 return;
3580 }
3581
3582 /* try to read from cache */
3583 bool can_write_cache = DEG_is_active(depsgraph);
3584 bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED) &&
3585 can_write_cache;
3586
3587 cache_result = BKE_ptcache_read(&pid, float(framenr) + scene->r.subframe, can_simulate);
3588
3589 if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED ||
3590 (!can_simulate && cache_result == PTCACHE_READ_OLD))
3591 {
3592 /* Keep goal positions in track. */
3593 softbody_update_positions(ob, sb, vertexCos, numVerts);
3594 softbody_to_object(ob, vertexCos, numVerts, sb->local);
3595
3596 BKE_ptcache_validate(cache, framenr);
3597
3598 if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED &&
3599 can_write_cache)
3600 {
3601 BKE_ptcache_write(&pid, framenr);
3602 }
3603
3604 sbStoreLastFrame(depsgraph, ob, framenr);
3605
3606 return;
3607 }
3608 if (cache_result == PTCACHE_READ_OLD) {
3609 /* pass */
3610 }
3611 else if (/*ob->id.lib || */
3612 /* "library linking & point-caches" has to be solved properly at some point. */
3613 (cache->flag & PTCACHE_BAKED))
3614 {
3615 /* If baked and nothing in cache, do nothing. */
3616 if (can_write_cache) {
3618 }
3619 return;
3620 }
3621
3622 if (!can_simulate) {
3623 return;
3624 }
3625
3626 /* if on second frame, write cache for first frame */
3627 if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0))
3628 {
3629 BKE_ptcache_write(&pid, startframe);
3630 }
3631
3632 softbody_update_positions(ob, sb, vertexCos, numVerts);
3633
3634 /* checking time: */
3635 dtime = framedelta * timescale;
3636
3637 /* do simulation */
3638 softbody_step(depsgraph, scene, ob, sb, dtime);
3639
3640 softbody_to_object(ob, vertexCos, numVerts, 0);
3641
3642 BKE_ptcache_validate(cache, framenr);
3643 BKE_ptcache_write(&pid, framenr);
3644
3645 sbStoreLastFrame(depsgraph, ob, framenr);
3646}
#define SOFTGOALSNAP
Definition BKE_cloth.hh:30
void BKE_collision_objects_free(struct Object **objects)
struct Object ** BKE_collision_objects_create(struct Depsgraph *depsgraph, struct Object *self, struct Collection *collection, unsigned int *numcollobj, unsigned int modifier_type)
int BKE_nurbList_verts_count(const ListBase *nurb)
Definition curve.cc:537
CustomData interface, see also DNA_customdata_types.h.
support for deformation groups and hooks.
int BKE_id_defgroup_name_index(const ID *id, blender::StringRef name)
Definition deform.cc:549
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:774
struct EffectorWeights * BKE_effector_add_weights(struct Collection *collection)
Definition effect.cc:58
void BKE_effectors_free(struct ListBase *lb)
Definition effect.cc:361
void BKE_effectors_apply(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *wind_force, float *impulse)
Definition effect.cc:1106
void pd_point_from_soft(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point)
Definition effect.cc:429
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
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
void BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
void BKE_ptcache_validate(struct PointCache *cache, int framenr)
void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb)
struct PointCache * BKE_ptcache_add(struct ListBase *ptcaches)
#define PTCACHE_READ_INTERPOLATED
#define PTCACHE_READ_OLD
int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
void BKE_ptcache_free_list(struct ListBase *ptcaches)
#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
int BKE_scene_num_threads(const Scene *scene)
Definition scene.cc:2910
#define BLI_assert(a)
Definition BLI_assert.h:46
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:295
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition BLI_ghash.cc:911
void BLI_ghashIterator_free(GHashIterator *ghi)
Definition BLI_ghash.cc:925
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:299
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
GHashIterator * BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:888
void(* GHashValFreeFP)(void *val)
Definition BLI_ghash.h:35
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:752
BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:307
#define LISTBASE_FOREACH(type, var, list)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
MINLINE float max_fff(float a, float b, float c)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE float min_fff(float a, float b, float c)
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
void vcloud_estimate_transform_v3(int list_size, const float(*pos)[3], const float *weight, const float(*rpos)[3], const float *rweight, float lloc[3], float rloc[3], float lrot[3][3], float lscale[3][3])
bool isect_line_segment_tri_v3(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3])
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void unit_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])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
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 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])
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
unsigned int uint
void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot)
Definition threads.cc:121
void BLI_threadpool_end(struct ListBase *threadbase)
Definition threads.cc:234
void BLI_threadpool_insert(struct ListBase *threadbase, void *callerdata)
Definition threads.cc:184
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:113
#define UNUSED_VARS(...)
#define ELEM(...)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:188
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:323
T * DEG_get_original(T *id)
@ ID_TAG_COPIED_ON_EVAL
Definition DNA_ID.h:997
Object groups, one object can be in many groups at once.
@ eModifierType_Collision
@ SBC_MODE_AVGMINMAX
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_SURF
@ OB_MESH
@ OB_CURVES_LEGACY
@ PTCACHE_BAKED
@ PTCACHE_OUTDATED
@ PTCACHE_REDO_NEEDED
#define MINFRAME
@ PHYS_GLOBAL_GRAVITY
Read Guarded memory(de)allocation.
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
constexpr bool is_empty() const
Definition BLI_span.hh:260
nullptr float
#define expf(x)
uint pos
#define printf(...)
#define pow
#define exp
float distance(VecOp< float, D >, VecOp< float, D >) RET
BLI_INLINE void dfdx_spring(float to[3][3], const float dir[3], float length, float L, float k)
void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double value)
#define LOG(level)
Definition log.h:97
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
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_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static int left
#define L
static char faces[256]
#define G(x, y, z)
void corner_tris_calc(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, MutableSpan< int3 > corner_tris)
VecBase< int32_t, 3 > int3
#define hash
Definition noise_c.cc:154
#define fabsf
#define BFF_INTERSECT
Definition softbody.cc:143
static void add_mesh_quad_diag_springs(Object *ob)
Definition softbody.cc:580
static int query_external_colliders(Depsgraph *depsgraph, Collection *collection)
Definition softbody.cc:961
static ccd_Mesh * ccd_mesh_make(Object *ob)
Definition softbody.cc:271
#define SBF_OUTOFCOLLISION
Definition softbody.cc:141
static int sb_deflect_face(Object *ob, float *actpos, float *facenormal, float *force, float *cf, float time, float *vel, float *intrusion)
Definition softbody.cc:1803
static void sbStoreLastFrame(Depsgraph *depsgraph, Object *object, float framenr)
Definition softbody.cc:3494
static void ccd_mesh_free(ccd_Mesh *ccdm)
Definition softbody.cc:476
static int sb_detect_face_pointCached(const float face_v1[3], const float face_v2[3], const float face_v3[3], float *damp, float force[3], Object *vertexowner, float time)
Definition softbody.cc:1030
static void * exec_softbody_calc_forces(void *data)
Definition softbody.cc:2171
static float _final_mass(Object *ob, BodyPoint *bp)
Definition softbody.cc:228
static void mesh_faces_to_scratch(Object *ob)
Definition softbody.cc:2757
static void springs_from_mesh(Object *ob)
Definition softbody.cc:2636
static float _final_goal(Object *ob, BodyPoint *bp)
Definition softbody.cc:207
void sbObjectToSoftbody(Object *ob)
Definition softbody.cc:3189
static void ccd_build_deflector_hash_single(GHash *hash, Object *ob)
Definition softbody.cc:490
static void softbody_restore_prev_step(Object *ob)
Definition softbody.cc:2477
static void sb_sfesf_threads_run(Depsgraph *depsgraph, Scene *scene, Object *ob, float timenow, int totsprings, int *ptr_to_break_func(void))
Definition softbody.cc:1511
static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow, int totpoint, int *ptr_to_break_func(void), ListBase *effectors, int do_deflector, float fieldfactor, float windfactor)
Definition softbody.cc:2188
void sbSetInterruptCallBack(int(*f)())
Definition softbody.cc:3208
static int sb_detect_edge_collisionCached(const float edge_v1[3], const float edge_v2[3], float *damp, float force[3], Object *vertexowner, float time)
Definition softbody.cc:1313
static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, int ifirst, int ilast, ListBase *effectors)
Definition softbody.cc:1428
static int(* SB_localInterruptCallBack)()
Definition softbody.cc:73
static void mesh_to_softbody(Object *ob)
Definition softbody.cc:2671
static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, float)
Definition softbody.cc:1866
static void curve_surf_to_softbody(Object *ob)
Definition softbody.cc:2963
static void softbody_apply_goalsnap(Object *ob)
Definition softbody.cc:2569
static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *damp, float force[3], Object *vertexowner, float time, float vel[3], float *intrusion)
Definition softbody.cc:1611
static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err, int mid_flags)
Definition softbody.cc:2317
type_spring
Definition softbody.cc:77
@ SB_STIFFQUAD
Definition softbody.cc:77
@ SB_BEND
Definition softbody.cc:77
@ SB_HANDLE
Definition softbody.cc:77
@ SB_EDGE
Definition softbody.cc:77
static void ccd_build_deflector_hash(Depsgraph *depsgraph, Collection *collection, Object *vertexowner, GHash *hash)
Definition softbody.cc:505
void sbFree(Object *ob)
Definition softbody.cc:3159
SoftBody * sbNew()
Definition softbody.cc:3107
static void calculate_collision_balls(Object *ob)
Definition softbody.cc:760
static void build_bps_springlist(Object *ob)
Definition softbody.cc:731
static void add_bp_springlist(BodyPoint *bp, int springID)
Definition softbody.cc:708
static const int CCD_SAFETY
Definition softbody.cc:253
static void softbody_reset(Object *ob, SoftBody *sb, float(*vertexCos)[3], int numVerts)
Definition softbody.cc:3281
static void renew_softbody(Object *ob, int totpoint, int totspring)
Definition softbody.cc:813
static void softbody_step(Depsgraph *depsgraph, Scene *scene, Object *ob, SoftBody *sb, float dtime)
Definition softbody.cc:3343
static float globallen(float *v1, float *v2, Object *ob)
Definition softbody.cc:2810
static void softbody_to_object(Object *ob, float(*vertexCos)[3], int numVerts, int local)
Definition softbody.cc:3067
static void add_2nd_order_springs(Object *ob, float stiffness)
Definition softbody.cc:685
#define SBF_DOFUZZY
Definition softbody.cc:140
static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
Definition softbody.cc:529
static void free_softbody_intern(SoftBody *sb)
Definition softbody.cc:900
static void softbody_calc_forces(Depsgraph *depsgraph, Scene *scene, Object *ob, float forcetime, float timenow)
Definition softbody.cc:2257
static int sb_detect_face_collisionCached(const float face_v1[3], const float face_v2[3], const float face_v3[3], float *damp, float force[3], Object *vertexowner, float time)
Definition softbody.cc:1129
static void add_2nd_order_roller(Object *ob, float, int *counter, int addsprings)
Definition softbody.cc:621
#define HEUNWARNLIMIT
Definition softbody.cc:135
void sbFreeSimulation(SoftBody *sb)
Definition softbody.cc:3184
static int sb_detect_aabb_collisionCached(float[3], Object *vertexowner, float)
Definition softbody.cc:973
#define MID_PRESERVE
Definition softbody.cc:129
static void sb_new_scratch(SoftBody *sb)
Definition softbody.cc:3090
static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow, int ifirst, int ilast, int *ptr_to_break_func(void), ListBase *effectors, int do_deflector, float fieldfactor, float windfactor)
Definition softbody.cc:1947
static float sb_time_scale(Object *ob)
Definition softbody.cc:177
static void free_scratch(SoftBody *sb)
Definition softbody.cc:878
#define BFF_CLOSEVERT
Definition softbody.cc:144
static void interpolate_exciter(Object *ob, int timescale, int time)
Definition softbody.cc:2607
void SB_estimate_transform(Object *ob, float lloc[3], float lrot[3][3], float lscale[3][3])
Definition softbody.cc:3238
void sbObjectStep(Depsgraph *depsgraph, Scene *scene, Object *ob, float cfra, float(*vertexCos)[3], int numVerts)
Definition softbody.cc:3504
#define BSF_INTERSECT
Definition softbody.cc:137
static int choose_winner(float *w, float *pos, float *a, float *b, float *c, float *ca, float *cb, float *cc)
Definition softbody.cc:1580
static float sb_fric_force_scale(Object *)
Definition softbody.cc:169
static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff, Object *ob)
Definition softbody.cc:2820
static float SoftHeunTol
Definition softbody.cc:147
static void reference_to_scratch(Object *ob)
Definition softbody.cc:2784
static bool object_has_edges(const Object *ob)
Definition softbody.cc:3196
static void free_softbody_baked(SoftBody *sb)
Definition softbody.cc:864
static void lattice_to_softbody(Object *ob)
Definition softbody.cc:2900
static void * exec_scan_for_ext_spring_forces(void *data)
Definition softbody.cc:1503
static void ccd_update_deflector_hash(Depsgraph *depsgraph, Collection *collection, Object *vertexowner, GHash *hash)
Definition softbody.cc:542
static void scan_for_ext_face_forces(Object *ob, float timenow)
Definition softbody.cc:1241
static float sb_grav_force_scale(Object *)
Definition softbody.cc:160
static void apply_spring_memory(Object *ob)
Definition softbody.cc:2583
static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M)
Definition softbody.cc:357
static void softbody_update_positions(Object *ob, SoftBody *sb, float(*vertexCos)[3], int numVerts)
Definition softbody.cc:3213
static int count_mesh_quads(Mesh *mesh)
Definition softbody.cc:568
#define min(a, b)
Definition sort.cc:36
float vec[4]
float vec[3][3]
short flag
Definition softbody.cc:90
float ext_force[3]
Definition softbody.cc:89
float pos[3]
float force[3]
float origE[3]
float vec[3]
float prevdv[3]
float choke2
float prevdx[3]
float prevvec[3]
float choke
float colball
short loc_flag
float prevpos[3]
int * springs
float origT[3]
float origS[3]
float frozen
float springweight
type_spring springtype
Definition softbody.cc:83
float ext_force[3]
Definition softbody.cc:82
float len
Definition softbody.cc:81
float load
Definition softbody.cc:81
short flag
Definition softbody.cc:84
float cf
Definition softbody.cc:81
ListBase nurb
int tag
Definition DNA_ID.h:442
char name[258]
Definition DNA_ID.h:432
struct MDeformVert * dvert
struct BPoint * def
int corners_num
int edges_num
int faces_num
int verts_num
ObjectRuntimeHandle * runtime
struct PartDeflect * pd
struct SoftBody * soft
float com[3]
Definition softbody.cc:99
ReferenceVert * ivert
Definition softbody.cc:100
float pos[3]
Definition softbody.cc:94
float aabbmin[3]
Definition softbody.cc:110
short flag
Definition softbody.cc:107
int bodyface_num
Definition softbody.cc:109
short needstobuildcollider
Definition softbody.cc:106
ReferenceState Ref
Definition softbody.cc:111
GHash * colliderhash
Definition softbody.cc:105
float aabbmax[3]
Definition softbody.cc:110
BodyFace * bodyface
Definition softbody.cc:108
ListBase * effectors
Definition softbody.cc:121
struct PhysicsSettings physics_settings
struct RenderData r
struct PointCache * pointcache
struct SoftBody_Shared * shared
struct Collection * collision_group
struct EffectorWeights * effector_weights
char namedVG_Spring_K[64]
struct BodySpring * bspring
struct SBScratch * scratch
struct BodyPoint * bpoint
int safety
Definition softbody.cc:264
int tri_num
Definition softbody.cc:260
const float(* vert_positions_prev)[3]
Definition softbody.cc:262
float bbmin[3]
Definition softbody.cc:267
int mvert_num
Definition softbody.cc:260
CCDF_MinMax * mima
Definition softbody.cc:265
const blender::int3 * vert_tris
Definition softbody.cc:263
float bbmax[3]
Definition softbody.cc:268
const float(* vert_positions)[3]
Definition softbody.cc:261
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint len