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