5 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version. The Blender
11 * Foundation also sells licenses for use in proprietary software under
12 * the Blender License. See http://www.blender.org/BL/ for information
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * The Original Code is Copyright (C) Blender Foundation
25 * All rights reserved.
27 * The Original Code is: all of this file.
29 * Contributor(s): none yet.
31 * ***** END GPL/BL DUAL LICENSE BLOCK *****
36 variables on the UI for now
38 float mediafrict; friction to env
39 float nodemass; softbody mass of *vertex*
40 float grav; softbody amount of gravitaion to apply
42 float goalspring; softbody goal springs
43 float goalfrict; softbody goal springs friction
44 float mingoal; quick limits for goal
47 float inspring; softbody inner springs
48 float infrict; softbody inner springs friction
58 #include "MEM_guardedalloc.h"
61 #include "DNA_curve_types.h"
62 #include "DNA_object_types.h"
63 #include "DNA_object_force.h" /* here is the softbody struct */
64 #include "DNA_particle_types.h"
65 #include "DNA_key_types.h"
66 #include "DNA_mesh_types.h"
67 #include "DNA_meshdata_types.h"
68 #include "DNA_modifier_types.h"
69 #include "DNA_lattice_types.h"
70 #include "DNA_scene_types.h"
72 #include "BLI_blenlib.h"
73 #include "BLI_arithb.h"
74 #include "BLI_ghash.h"
75 #include "BKE_curve.h"
76 #include "BKE_effect.h"
77 #include "BKE_global.h"
79 #include "BKE_object.h"
80 #include "BKE_particle.h"
81 #include "BKE_softbody.h"
82 #include "BKE_utildefines.h"
83 #include "BKE_DerivedMesh.h"
84 #include "BKE_pointcache.h"
85 #include "BKE_modifier.h"
87 #include "BIF_editdeform.h"
88 #include "BIF_graphics.h"
91 /* callbacks for errors and interrupts and some goo */
92 static int (*SB_localInterruptCallBack)(void) = NULL;
95 /* ********** soft body engine ******* */
98 typedef struct BodySpring {
100 float len, strength, cf;
101 float ext_force[3]; /* edges colliding and sailing */
106 typedef struct BodyFace {
108 float ext_force[3]; /* edges colliding and sailing */
113 /*private scratch pad for caching and other data only needed when alive*/
114 typedef struct SBScratch {
116 short needstobuildcollider;
120 float aabbmin[3],aabbmax[3];
123 #define SOFTGOALSNAP 0.999f
124 /* if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp
125 removes *unnecessary* stiffnes from ODE system
127 #define HEUNWARNLIMIT 1 /* 500 would be fine i think for detecting severe *stiff* stuff */
130 #define BSF_INTERSECT 1 /* edge intersects collider face */
131 #define SBF_DOFUZZY 1 /* edge intersects collider face */
132 #define BFF_INTERSECT 1 /* edge intersects collider face */
135 float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
137 /* local prototypes */
138 static void free_softbody_intern(SoftBody *sb);
139 /* aye this belongs to arith.c */
140 static void Vec3PlusStVec(float *v, float s, float *v1);
142 /*+++ frame based timing +++*/
144 /*physical unit of force is [kg * m / sec^2]*/
146 static float sb_grav_force_scale(Object *ob)
147 /* since unit of g is [m/sec^2] and F = mass * g we rescale unit mass of node to 1 gramm
148 put it to a function here, so we can add user options later without touching simulation code
154 static float sb_fric_force_scale(Object *ob)
155 /* rescaling unit of drag [1 / sec] to somehow reasonable
156 put it to a function here, so we can add user options later without touching simulation code
162 static float sb_time_scale(Object *ob)
163 /* defining the frames to *real* time relation */
165 SoftBody *sb= ob->soft; /* is supposed to be there */
167 return(sb->physics_speed);
168 /*hrms .. this could be IPO as well :)
169 estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
170 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames
171 theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM)
176 this would be frames/sec independant timing assuming 25 fps is default
177 but does not work very well with NLA
178 return (25.0f/G.scene->r.frs_sec)
181 /*--- frame based timing ---*/
183 /*+++ collider caching and dicing +++*/
185 /********************
186 for each target object/face the axis aligned bounding box (AABB) is stored
187 faces paralell to global axes
188 so only simple "value" in [min,max] ckecks are used
189 float operations still
192 /* just an ID here to reduce the prob for killing objects
193 ** ob->sumohandle points to we should not kill :)
195 const int CCD_SAVETY = 190561;
197 typedef struct ccdf_minmax{
198 float minx,miny,minz,maxx,maxy,maxz;
203 typedef struct ccd_Mesh {
204 int totvert, totface;
210 /* Axis Aligned Bounding Box AABB */
218 ccd_Mesh *ccd_mesh_make(Object *ob, DerivedMesh *dm)
220 ccd_Mesh *pccd_M = NULL;
221 ccdf_minmax *mima =NULL;
226 /* first some paranoia checks */
227 if (!dm) return NULL;
228 if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return NULL;
230 pccd_M = MEM_mallocN(sizeof(ccd_Mesh),"ccd_Mesh");
231 pccd_M->totvert = dm->getNumVerts(dm);
232 pccd_M->totface = dm->getNumFaces(dm);
233 pccd_M->savety = CCD_SAVETY;
234 pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
235 pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
236 pccd_M->mprevvert=NULL;
239 /* blow it up with forcefield ranges */
240 hull = MAX2(ob->pd->pdef_sbift,ob->pd->pdef_sboft);
242 /* alloc and copy verts*/
243 pccd_M->mvert = dm->dupVertArray(dm);
244 /* ah yeah, put the verices to global coords once */
245 /* and determine the ortho BB on the fly */
246 for(i=0; i < pccd_M->totvert; i++){
247 Mat4MulVecfl(ob->obmat, pccd_M->mvert[i].co);
249 /* evaluate limits */
250 VECCOPY(v,pccd_M->mvert[i].co);
251 pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0],v[0]-hull);
252 pccd_M->bbmin[1] = MIN2(pccd_M->bbmin[1],v[1]-hull);
253 pccd_M->bbmin[2] = MIN2(pccd_M->bbmin[2],v[2]-hull);
255 pccd_M->bbmax[0] = MAX2(pccd_M->bbmax[0],v[0]+hull);
256 pccd_M->bbmax[1] = MAX2(pccd_M->bbmax[1],v[1]+hull);
257 pccd_M->bbmax[2] = MAX2(pccd_M->bbmax[2],v[2]+hull);
260 /* alloc and copy faces*/
261 pccd_M->mface = dm->dupFaceArray(dm);
264 pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax)*pccd_M->totface,"ccd_Mesh_Faces_mima");
266 mface = pccd_M->mface;
269 /* anyhoo we need to walk the list of faces and find OBB they live in */
270 for(i=0; i < pccd_M->totface; i++){
271 mima->minx=mima->miny=mima->minz=1e30f;
272 mima->maxx=mima->maxy=mima->maxz=-1e30f;
274 VECCOPY(v,pccd_M->mvert[mface->v1].co);
275 mima->minx = MIN2(mima->minx,v[0]-hull);
276 mima->miny = MIN2(mima->miny,v[1]-hull);
277 mima->minz = MIN2(mima->minz,v[2]-hull);
278 mima->maxx = MAX2(mima->maxx,v[0]+hull);
279 mima->maxy = MAX2(mima->maxy,v[1]+hull);
280 mima->maxz = MAX2(mima->maxz,v[2]+hull);
282 VECCOPY(v,pccd_M->mvert[mface->v2].co);
283 mima->minx = MIN2(mima->minx,v[0]-hull);
284 mima->miny = MIN2(mima->miny,v[1]-hull);
285 mima->minz = MIN2(mima->minz,v[2]-hull);
286 mima->maxx = MAX2(mima->maxx,v[0]+hull);
287 mima->maxy = MAX2(mima->maxy,v[1]+hull);
288 mima->maxz = MAX2(mima->maxz,v[2]+hull);
290 VECCOPY(v,pccd_M->mvert[mface->v3].co);
291 mima->minx = MIN2(mima->minx,v[0]-hull);
292 mima->miny = MIN2(mima->miny,v[1]-hull);
293 mima->minz = MIN2(mima->minz,v[2]-hull);
294 mima->maxx = MAX2(mima->maxx,v[0]+hull);
295 mima->maxy = MAX2(mima->maxy,v[1]+hull);
296 mima->maxz = MAX2(mima->maxz,v[2]+hull);
299 VECCOPY(v,pccd_M->mvert[mface->v4].co);
300 mima->minx = MIN2(mima->minx,v[0]-hull);
301 mima->miny = MIN2(mima->miny,v[1]-hull);
302 mima->minz = MIN2(mima->minz,v[2]-hull);
303 mima->maxx = MAX2(mima->maxx,v[0]+hull);
304 mima->maxy = MAX2(mima->maxy,v[1]+hull);
305 mima->maxz = MAX2(mima->maxz,v[2]+hull);
315 void ccd_mesh_update(Object *ob,ccd_Mesh *pccd_M, DerivedMesh *dm)
317 ccdf_minmax *mima =NULL;
322 /* first some paranoia checks */
324 if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return ;
326 if ((pccd_M->totvert != dm->getNumVerts(dm)) ||
327 (pccd_M->totface != dm->getNumFaces(dm))) return;
329 pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
330 pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
333 /* blow it up with forcefield ranges */
334 hull = MAX2(ob->pd->pdef_sbift,ob->pd->pdef_sboft);
336 /* rotate current to previous */
337 if(pccd_M->mprevvert) MEM_freeN(pccd_M->mprevvert);
338 pccd_M->mprevvert = pccd_M->mvert;
339 /* alloc and copy verts*/
340 pccd_M->mvert = dm->dupVertArray(dm);
341 /* ah yeah, put the verices to global coords once */
342 /* and determine the ortho BB on the fly */
343 for(i=0; i < pccd_M->totvert; i++){
344 Mat4MulVecfl(ob->obmat, pccd_M->mvert[i].co);
346 /* evaluate limits */
347 VECCOPY(v,pccd_M->mvert[i].co);
348 pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0],v[0]-hull);
349 pccd_M->bbmin[1] = MIN2(pccd_M->bbmin[1],v[1]-hull);
350 pccd_M->bbmin[2] = MIN2(pccd_M->bbmin[2],v[2]-hull);
352 pccd_M->bbmax[0] = MAX2(pccd_M->bbmax[0],v[0]+hull);
353 pccd_M->bbmax[1] = MAX2(pccd_M->bbmax[1],v[1]+hull);
354 pccd_M->bbmax[2] = MAX2(pccd_M->bbmax[2],v[2]+hull);
356 /* evaluate limits */
357 VECCOPY(v,pccd_M->mprevvert[i].co);
358 pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0],v[0]-hull);
359 pccd_M->bbmin[1] = MIN2(pccd_M->bbmin[1],v[1]-hull);
360 pccd_M->bbmin[2] = MIN2(pccd_M->bbmin[2],v[2]-hull);
362 pccd_M->bbmax[0] = MAX2(pccd_M->bbmax[0],v[0]+hull);
363 pccd_M->bbmax[1] = MAX2(pccd_M->bbmax[1],v[1]+hull);
364 pccd_M->bbmax[2] = MAX2(pccd_M->bbmax[2],v[2]+hull);
369 mface = pccd_M->mface;
372 /* anyhoo we need to walk the list of faces and find OBB they live in */
373 for(i=0; i < pccd_M->totface; i++){
374 mima->minx=mima->miny=mima->minz=1e30f;
375 mima->maxx=mima->maxy=mima->maxz=-1e30f;
377 VECCOPY(v,pccd_M->mvert[mface->v1].co);
378 mima->minx = MIN2(mima->minx,v[0]-hull);
379 mima->miny = MIN2(mima->miny,v[1]-hull);
380 mima->minz = MIN2(mima->minz,v[2]-hull);
381 mima->maxx = MAX2(mima->maxx,v[0]+hull);
382 mima->maxy = MAX2(mima->maxy,v[1]+hull);
383 mima->maxz = MAX2(mima->maxz,v[2]+hull);
385 VECCOPY(v,pccd_M->mvert[mface->v2].co);
386 mima->minx = MIN2(mima->minx,v[0]-hull);
387 mima->miny = MIN2(mima->miny,v[1]-hull);
388 mima->minz = MIN2(mima->minz,v[2]-hull);
389 mima->maxx = MAX2(mima->maxx,v[0]+hull);
390 mima->maxy = MAX2(mima->maxy,v[1]+hull);
391 mima->maxz = MAX2(mima->maxz,v[2]+hull);
393 VECCOPY(v,pccd_M->mvert[mface->v3].co);
394 mima->minx = MIN2(mima->minx,v[0]-hull);
395 mima->miny = MIN2(mima->miny,v[1]-hull);
396 mima->minz = MIN2(mima->minz,v[2]-hull);
397 mima->maxx = MAX2(mima->maxx,v[0]+hull);
398 mima->maxy = MAX2(mima->maxy,v[1]+hull);
399 mima->maxz = MAX2(mima->maxz,v[2]+hull);
402 VECCOPY(v,pccd_M->mvert[mface->v4].co);
403 mima->minx = MIN2(mima->minx,v[0]-hull);
404 mima->miny = MIN2(mima->miny,v[1]-hull);
405 mima->minz = MIN2(mima->minz,v[2]-hull);
406 mima->maxx = MAX2(mima->maxx,v[0]+hull);
407 mima->maxy = MAX2(mima->maxy,v[1]+hull);
408 mima->maxz = MAX2(mima->maxz,v[2]+hull);
412 VECCOPY(v,pccd_M->mprevvert[mface->v1].co);
413 mima->minx = MIN2(mima->minx,v[0]-hull);
414 mima->miny = MIN2(mima->miny,v[1]-hull);
415 mima->minz = MIN2(mima->minz,v[2]-hull);
416 mima->maxx = MAX2(mima->maxx,v[0]+hull);
417 mima->maxy = MAX2(mima->maxy,v[1]+hull);
418 mima->maxz = MAX2(mima->maxz,v[2]+hull);
420 VECCOPY(v,pccd_M->mprevvert[mface->v2].co);
421 mima->minx = MIN2(mima->minx,v[0]-hull);
422 mima->miny = MIN2(mima->miny,v[1]-hull);
423 mima->minz = MIN2(mima->minz,v[2]-hull);
424 mima->maxx = MAX2(mima->maxx,v[0]+hull);
425 mima->maxy = MAX2(mima->maxy,v[1]+hull);
426 mima->maxz = MAX2(mima->maxz,v[2]+hull);
428 VECCOPY(v,pccd_M->mprevvert[mface->v3].co);
429 mima->minx = MIN2(mima->minx,v[0]-hull);
430 mima->miny = MIN2(mima->miny,v[1]-hull);
431 mima->minz = MIN2(mima->minz,v[2]-hull);
432 mima->maxx = MAX2(mima->maxx,v[0]+hull);
433 mima->maxy = MAX2(mima->maxy,v[1]+hull);
434 mima->maxz = MAX2(mima->maxz,v[2]+hull);
437 VECCOPY(v,pccd_M->mprevvert[mface->v4].co);
438 mima->minx = MIN2(mima->minx,v[0]-hull);
439 mima->miny = MIN2(mima->miny,v[1]-hull);
440 mima->minz = MIN2(mima->minz,v[2]-hull);
441 mima->maxx = MAX2(mima->maxx,v[0]+hull);
442 mima->maxy = MAX2(mima->maxy,v[1]+hull);
443 mima->maxz = MAX2(mima->maxz,v[2]+hull);
454 void ccd_mesh_free(ccd_Mesh *ccdm)
456 if(ccdm && (ccdm->savety == CCD_SAVETY )){ /*make sure we're not nuking objects we don't know*/
457 MEM_freeN(ccdm->mface);
458 MEM_freeN(ccdm->mvert);
459 if (ccdm->mprevvert) MEM_freeN(ccdm->mprevvert);
460 MEM_freeN(ccdm->mima);
466 void ccd_build_deflector_hache(Object *vertexowner,GHash *hash)
470 base= G.scene->base.first;
471 base= G.scene->base.first;
474 /*Only proceed for mesh object in same layer */
475 if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
478 if((vertexowner) && (ob == vertexowner)) {
479 if(vertexowner->soft->particles){
483 /* if vertexowner is given we don't want to check collision with owner object */
489 /*+++ only with deflecting set */
490 if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == 0) {
491 DerivedMesh *dm= NULL;
494 dm = psys_get_modifier(ob,psys_get_current(ob))->dm;
497 if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */
498 dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
500 dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH);
504 ccd_Mesh *ccdmesh = ccd_mesh_make(ob, dm);
505 BLI_ghash_insert(hash, ob, ccdmesh);
507 /* we did copy & modify all we need so give 'em away again */
511 }/*--- only with deflecting set */
518 void ccd_update_deflector_hache(Object *vertexowner,GHash *hash)
522 base= G.scene->base.first;
523 base= G.scene->base.first;
524 if ((!hash) || (!vertexowner)) return;
526 /*Only proceed for mesh object in same layer */
527 if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
529 if(ob == vertexowner){
530 /* if vertexowner is given we don't want to check collision with owner object */
535 /*+++ only with deflecting set */
536 if(ob->pd && ob->pd->deflect) {
537 DerivedMesh *dm= NULL;
539 if(ob->softflag & OB_SB_COLLFINAL) { /* so maybe someone wants overkill to collide with subsurfed */
540 dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
542 dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH);
545 ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash,ob);
547 ccd_mesh_update(ob,ccdmesh,dm);
549 /* we did copy & modify all we need so give 'em away again */
552 }/*--- only with deflecting set */
562 /*--- collider caching and dicing ---*/
565 static int count_mesh_quads(Mesh *me)
568 MFace *mface= me->mface;
571 for(a=me->totface; a>0; a--, mface++) {
572 if(mface->v4) result++;
578 static void add_mesh_quad_diag_springs(Object *ob)
581 MFace *mface= me->mface;
583 BodySpring *bs, *bs_new;
589 nofquads = count_mesh_quads(me);
591 /* resize spring-array to hold additional quad springs */
592 bs_new= MEM_callocN( (ob->soft->totspring + nofquads *2 )*sizeof(BodySpring), "bodyspring");
593 memcpy(bs_new,ob->soft->bspring,(ob->soft->totspring )*sizeof(BodySpring));
595 if(ob->soft->bspring)
596 MEM_freeN(ob->soft->bspring); /* do this before reassigning the pointer or have a 1st class memory leak */
597 ob->soft->bspring = bs_new;
601 bs = bs_new+ob->soft->totspring;
602 bp= ob->soft->bpoint;
604 for(a=me->totface; a>0; a--, mface++) {
621 /* now we can announce new springs */
622 ob->soft->totspring += nofquads *2;
627 static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int addsprings)
629 /*assume we have a softbody*/
630 SoftBody *sb= ob->soft; /* is supposed to be there */
632 BodySpring *bs,*bs2,*bs3= NULL;
633 int a,b,c,notthis= 0,v0;
634 if (!sb->bspring){return;} /* we are 2nd order here so 1rst should have been build :) */
635 /* first run counting second run adding */
637 if (addsprings) bs3 = ob->soft->bspring+ob->soft->totspring;
638 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
639 /*scan for neighborhood*/
641 v0 = (sb->totpoint-a);
642 for(b=bp->nofsprings;b>0;b--){
643 bs = sb->bspring + bp->springs[b-1];
644 /*nasty thing here that springs have two ends
645 so here we have to make sure we examine the other */
646 if (( v0 == bs->v1) ){
647 bpo =sb->bpoint+bs->v2;
651 if (( v0 == bs->v2) ){
652 bpo =sb->bpoint+bs->v1;
655 else {printf("oops we should not get here - add_2nd_order_springs");}
657 if (bpo){/* so now we have a 2nd order humpdidump */
658 for(c=bpo->nofsprings;c>0;c--){
659 bs2 = sb->bspring + bpo->springs[c-1];
660 if ((bs2->v1 != notthis) && (bs2->v1 > v0)){
661 (*counter)++;/*hit */
665 bs3->strength= stiffness;
670 if ((bs2->v2 !=notthis)&&(bs2->v2 > v0)){
671 (*counter)++;/*hit */
675 bs3->strength= stiffness;
686 /*scan for neighborhood done*/
691 static void add_2nd_order_springs(Object *ob,float stiffness)
696 add_2nd_order_roller(ob,stiffness,&counter,0); /* counting */
698 /* resize spring-array to hold additional springs */
699 bs_new= MEM_callocN( (ob->soft->totspring + counter )*sizeof(BodySpring), "bodyspring");
700 memcpy(bs_new,ob->soft->bspring,(ob->soft->totspring )*sizeof(BodySpring));
702 if(ob->soft->bspring)
703 MEM_freeN(ob->soft->bspring);
704 ob->soft->bspring = bs_new;
706 add_2nd_order_roller(ob,stiffness,&counter,1); /* adding */
707 ob->soft->totspring +=counter ;
711 static void add_bp_springlist(BodyPoint *bp,int springID)
715 if (bp->springs == NULL) {
716 bp->springs = MEM_callocN( sizeof(int), "bpsprings");
717 bp->springs[0] = springID;
722 newlist = MEM_callocN(bp->nofsprings * sizeof(int), "bpsprings");
723 memcpy(newlist,bp->springs,(bp->nofsprings-1)* sizeof(int));
724 MEM_freeN(bp->springs);
725 bp->springs = newlist;
726 bp->springs[bp->nofsprings-1] = springID;
730 /* do this once when sb is build
731 it is O(N^2) so scanning for springs every iteration is too expensive
733 static void build_bps_springlist(Object *ob)
735 SoftBody *sb= ob->soft; /* is supposed to be there */
740 if (sb==NULL) return; /* paranoya check */
742 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
743 /* throw away old list */
745 MEM_freeN(bp->springs);
748 /* scan for attached inner springs */
749 for(b=sb->totspring, bs= sb->bspring; b>0; b--, bs++) {
750 if (( (sb->totpoint-a) == bs->v1) ){
751 add_bp_springlist(bp,sb->totspring -b);
753 if (( (sb->totpoint-a) == bs->v2) ){
754 add_bp_springlist(bp,sb->totspring -b);
760 static void calculate_collision_balls(Object *ob)
762 SoftBody *sb= ob->soft; /* is supposed to be there */
768 if (sb==NULL) return; /* paranoya check */
770 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
776 /* first estimation based on attached */
777 for(b=bp->nofsprings;b>0;b--){
778 bs = sb->bspring + bp->springs[b-1];
782 min = MIN2(bs->len,min);
783 max = MAX2(bs->len,max);
787 if (akku_count > 0) {
788 if (sb->sbc_mode == SBC_MODE_MANUAL){
789 bp->colball=sb->colball;
791 if (sb->sbc_mode == SBC_MODE_AVG){
792 bp->colball = akku/(float)akku_count*sb->colball;
794 if (sb->sbc_mode == SBC_MODE_MIN){
795 bp->colball=min*sb->colball;
797 if (sb->sbc_mode == SBC_MODE_MAX){
798 bp->colball=max*sb->colball;
800 if (sb->sbc_mode == SBC_MODE_AVGMINMAX){
801 bp->colball = (min + max)/2.0f*sb->colball;
809 char set_octant_flags(float *ce, float *pos, float ball)
817 case 0: x=pos[0]; y=pos[1]; z=pos[2]; break;
818 case 1: x=pos[0]+ball; y=pos[1]; z=pos[2]; break;
819 case 2: x=pos[0]-ball; y=pos[1]; z=pos[2]; break;
820 case 3: x=pos[0]; y=pos[1]+ball; z=pos[2]; break;
821 case 4: x=pos[0]; y=pos[1]-ball; z=pos[2]; break;
822 case 5: x=pos[0]; y=pos[1]; z=pos[2]+ball; break;
823 case 6: x=pos[0]; y=pos[1]; z=pos[2]-ball; break;
826 x=pos[0]; y=pos[1]; z=pos[2];
830 if (z > ce[2]) res|= 1;
834 if (z > ce[2]) res|= 4;
841 if (z > ce[2]) res|= 16;
845 if (z > ce[2]) res|= 64;
853 /* creates new softbody if didn't exist yet, makes new points and springs arrays */
854 static void renew_softbody(Object *ob, int totpoint, int totspring)
859 if(ob->soft==NULL) ob->soft= sbNew();
860 else free_softbody_intern(ob->soft);
862 softflag=ob->softflag;
865 sb->totpoint= totpoint;
866 sb->totspring= totspring;
868 sb->bpoint= MEM_mallocN( totpoint*sizeof(BodyPoint), "bodypoint");
870 sb->bspring= MEM_mallocN( totspring*sizeof(BodySpring), "bodyspring");
872 /* initialise BodyPoint array */
873 for (i=0; i<totpoint; i++) {
874 BodyPoint *bp = &sb->bpoint[i];
876 if(softflag & OB_SB_GOAL) {
877 bp->goal= sb->defgoal;
881 /* so this will definily be below SOFTGOALSNAP */
894 static void free_softbody_baked(SoftBody *sb)
899 for(k=0; k<sb->totkey; k++) {
900 key= *(sb->keys + k);
901 if(key) MEM_freeN(key);
903 if(sb->keys) MEM_freeN(sb->keys);
908 static void free_scratch(SoftBody *sb)
911 /* todo make sure everything is cleaned up nicly */
912 if (sb->scratch->colliderhash){
913 BLI_ghash_free(sb->scratch->colliderhash, NULL,
914 (GHashValFreeFP) ccd_mesh_free); /*this hoepfully will free all caches*/
915 sb->scratch->colliderhash = NULL;
917 if (sb->scratch->bodyface){
918 MEM_freeN(sb->scratch->bodyface);
920 MEM_freeN(sb->scratch);
926 /* only frees internal data */
927 static void free_softbody_intern(SoftBody *sb)
934 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
935 /* free spring list */
936 if (bp->springs != NULL) {
937 MEM_freeN(bp->springs);
940 MEM_freeN(sb->bpoint);
943 if(sb->bspring) MEM_freeN(sb->bspring);
945 sb->totpoint= sb->totspring= 0;
950 free_softbody_baked(sb);
955 /* ************ dynamics ********** */
957 /* the most general (micro physics correct) way to do collision
958 ** (only needs the current particle position)
960 ** it actually checks if the particle intrudes a short range force field generated
961 ** by the faces of the target object and returns a force to drive the particel out
962 ** the strenght of the field grows exponetially if the particle is on the 'wrong' side of the face
963 ** 'wrong' side : projection to the face normal is negative (all referred to a vertex in the face)
965 ** flaw of this: 'fast' particles as well as 'fast' colliding faces
966 ** give a 'tunnel' effect such that the particle passes through the force field
967 ** without ever 'seeing' it
968 ** this is fully compliant to heisenberg: h >= fuzzy(location) * fuzzy(time)
969 ** besides our h is way larger than in QM because forces propagate way slower here
970 ** we have to deal with fuzzy(time) in the range of 1/25 seconds (typical frame rate)
971 ** yup collision targets are not known here any better
972 ** and 1/25 second is looong compared to real collision events
973 ** Q: why not use 'simple' collision here like bouncing back a particle
974 ** --> reverting is velocity on the face normal
975 ** A: because our particles are not alone here
976 ** and need to tell their neighbours exactly what happens via spring forces
977 ** unless sbObjectStep( .. ) is called on sub frame timing level
978 ** BTW that also questions the use of a 'implicit' solvers on softbodies
979 ** since that would only valid for 'slow' moving collision targets and dito particles
982 /* aye this belongs to arith.c */
983 static void Vec3PlusStVec(float *v, float s, float *v1)
990 /* +++ dependancy information functions*/
991 static int are_there_deflectors(unsigned int layer)
995 for(base = G.scene->base.first; base; base= base->next) {
996 if( (base->lay & layer) && base->object->pd) {
997 if(base->object->pd->deflect)
1004 static int query_external_colliders(Object *me)
1006 return(are_there_deflectors(me->lay));
1010 static int query_external_forces(Object *me)
1012 /* silly but true: we need to create effector cache to see if anything is in it */
1013 ListBase *ec = pdInitEffectors(me,NULL);
1017 pdEndEffectors(ec); /* sorry ec, yes i'm an idiot, but i needed to know if you were there */
1023 any of that external objects may have an IPO or something alike ..
1024 so unless we can ask them if they are moving we have to assume they do
1026 static int query_external_time(Object *me)
1028 if (query_external_colliders(me)) return 1;
1029 if (query_external_forces(me)) return 1;
1032 static int query_internal_time(Object *me)
1034 if (me->softflag & OB_SB_GOAL) return 1;
1038 /* --- dependancy information functions*/
1040 /* +++ the aabb "force" section*/
1041 int sb_detect_aabb_collisionCached( float force[3], unsigned int par_layer,struct Object *vertexowner,float time)
1044 SoftBody *sb=vertexowner->soft;
1046 GHashIterator *ihash;
1047 float aabbmin[3],aabbmax[3];
1050 if ((sb == NULL) || (sb->scratch ==NULL)) return 0;
1051 VECCOPY(aabbmin,sb->scratch->aabbmin);
1052 VECCOPY(aabbmax,sb->scratch->aabbmax);
1054 hash = vertexowner->soft->scratch->colliderhash;
1055 ihash = BLI_ghashIterator_new(hash);
1056 while (!BLI_ghashIterator_isDone(ihash) ) {
1058 ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
1059 ob = BLI_ghashIterator_getKey (ihash);
1060 /* only with deflecting set */
1061 if(ob->pd && ob->pd->deflect) {
1064 MVert *mprevvert= NULL;
1065 ccdf_minmax *mima= NULL;
1069 mprevvert= ccdm->mprevvert;
1073 if ((aabbmax[0] < ccdm->bbmin[0]) ||
1074 (aabbmax[1] < ccdm->bbmin[1]) ||
1075 (aabbmax[2] < ccdm->bbmin[2]) ||
1076 (aabbmin[0] > ccdm->bbmax[0]) ||
1077 (aabbmin[1] > ccdm->bbmax[1]) ||
1078 (aabbmin[2] > ccdm->bbmax[2]) ) {
1079 /* boxes dont intersect */
1080 BLI_ghashIterator_step(ihash);
1084 /* so now we have the 2 boxes overlapping */
1085 /* forces actually not used */
1090 /*aye that should be cached*/
1091 printf("missing cache error \n");
1092 BLI_ghashIterator_step(ihash);
1095 } /* if(ob->pd && ob->pd->deflect) */
1096 BLI_ghashIterator_step(ihash);
1098 BLI_ghashIterator_free(ihash);
1101 /* --- the aabb section*/
1104 /* +++ the face external section*/
1106 int sb_detect_face_collisionCached(float face_v1[3],float face_v2[3],float face_v3[3],float *damp,
1107 float force[3], unsigned int par_layer,struct Object *vertexowner,float time)
1111 GHashIterator *ihash;
1112 float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3],aabbmax[3];
1116 aabbmin[0] = MIN3(face_v1[0],face_v2[0],face_v3[0]);
1117 aabbmin[1] = MIN3(face_v1[1],face_v2[1],face_v3[1]);
1118 aabbmin[2] = MIN3(face_v1[2],face_v2[2],face_v3[2]);
1119 aabbmax[0] = MAX3(face_v1[0],face_v2[0],face_v3[0]);
1120 aabbmax[1] = MAX3(face_v1[1],face_v2[1],face_v3[1]);
1121 aabbmax[2] = MAX3(face_v1[2],face_v2[2],face_v3[2]);
1123 hash = vertexowner->soft->scratch->colliderhash;
1124 ihash = BLI_ghashIterator_new(hash);
1125 while (!BLI_ghashIterator_isDone(ihash) ) {
1127 ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
1128 ob = BLI_ghashIterator_getKey (ihash);
1129 /* only with deflecting set */
1130 if(ob->pd && ob->pd->deflect) {
1133 MVert *mprevvert= NULL;
1134 ccdf_minmax *mima= NULL;
1138 mprevvert= ccdm->mprevvert;
1142 if ((aabbmax[0] < ccdm->bbmin[0]) ||
1143 (aabbmax[1] < ccdm->bbmin[1]) ||
1144 (aabbmax[2] < ccdm->bbmin[2]) ||
1145 (aabbmin[0] > ccdm->bbmax[0]) ||
1146 (aabbmin[1] > ccdm->bbmax[1]) ||
1147 (aabbmin[2] > ccdm->bbmax[2]) ) {
1148 /* boxes dont intersect */
1149 BLI_ghashIterator_step(ihash);
1155 /*aye that should be cached*/
1156 printf("missing cache error \n");
1157 BLI_ghashIterator_step(ihash);
1165 (aabbmax[0] < mima->minx) ||
1166 (aabbmin[0] > mima->maxx) ||
1167 (aabbmax[1] < mima->miny) ||
1168 (aabbmin[1] > mima->maxy) ||
1169 (aabbmax[2] < mima->minz) ||
1170 (aabbmin[2] > mima->maxz)
1180 VECCOPY(nv1,mvert[mface->v1].co);
1181 VECCOPY(nv2,mvert[mface->v2].co);
1182 VECCOPY(nv3,mvert[mface->v3].co);
1184 VECCOPY(nv4,mvert[mface->v4].co);
1188 Vec3PlusStVec(nv1,(1.0f-time),mprevvert[mface->v1].co);
1191 Vec3PlusStVec(nv2,(1.0f-time),mprevvert[mface->v2].co);
1194 Vec3PlusStVec(nv3,(1.0f-time),mprevvert[mface->v3].co);
1198 Vec3PlusStVec(nv4,(1.0f-time),mprevvert[mface->v4].co);
1203 /* switch origin to be nv2*/
1204 VECSUB(edge1, nv1, nv2);
1205 VECSUB(edge2, nv3, nv2);
1206 Crossf(d_nvect, edge2, edge1);
1209 LineIntersectsTriangle(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
1210 LineIntersectsTriangle(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
1211 LineIntersectsTriangle(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL) ){
1212 Vec3PlusStVec(force,-1.0f,d_nvect);
1213 *damp=ob->pd->pdef_sbdamp;
1216 if (mface->v4){ /* quad */
1217 /* switch origin to be nv4 */
1218 VECSUB(edge1, nv3, nv4);
1219 VECSUB(edge2, nv1, nv4);
1220 Crossf(d_nvect, edge2, edge1);
1223 LineIntersectsTriangle(nv1, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
1224 LineIntersectsTriangle(nv3, nv4, face_v1, face_v2, face_v3, &t, NULL) ||
1225 LineIntersectsTriangle(nv4, nv1, face_v1, face_v2, face_v3, &t, NULL) ){
1226 Vec3PlusStVec(force,-1.0f,d_nvect);
1227 *damp=ob->pd->pdef_sbdamp;
1234 } /* if(ob->pd && ob->pd->deflect) */
1235 BLI_ghashIterator_step(ihash);
1237 BLI_ghashIterator_free(ihash);
1243 void scan_for_ext_face_forces(Object *ob,float timenow)
1245 SoftBody *sb = ob->soft;
1249 float tune = -10.0f;
1252 if (sb && sb->scratch->totface){
1255 bf = sb->scratch->bodyface;
1256 for(a=0; a<sb->scratch->totface; a++, bf++) {
1257 bf->ext_force[0]=bf->ext_force[1]=bf->ext_force[2]=0.0f;
1258 feedback[0]=feedback[1]=feedback[2]=0.0f;
1259 bf->flag &= ~BFF_INTERSECT;
1261 if (sb_detect_face_collisionCached(sb->bpoint[bf->v1].pos,sb->bpoint[bf->v2].pos, sb->bpoint[bf->v3].pos,
1262 &damp, feedback, ob->lay ,ob , timenow)){
1263 Vec3PlusStVec(bf->ext_force,tune,feedback);
1264 bf->flag |= BFF_INTERSECT;
1267 feedback[0]=feedback[1]=feedback[2]=0.0f;
1268 if ((bf->v4) && (sb_detect_face_collisionCached(sb->bpoint[bf->v1].pos,sb->bpoint[bf->v3].pos, sb->bpoint[bf->v4].pos,
1269 &damp, feedback, ob->lay ,ob , timenow))){
1270 Vec3PlusStVec(bf->ext_force,tune,feedback);
1271 bf->flag |= BFF_INTERSECT;
1277 bf = sb->scratch->bodyface;
1278 for(a=0; a<sb->scratch->totface; a++, bf++) {
1279 if ( bf->flag & BFF_INTERSECT)
1281 VECADD(sb->bpoint[bf->v1].force,sb->bpoint[bf->v1].force,bf->ext_force);
1282 VECADD(sb->bpoint[bf->v2].force,sb->bpoint[bf->v2].force,bf->ext_force);
1283 VECADD(sb->bpoint[bf->v3].force,sb->bpoint[bf->v3].force,bf->ext_force);
1285 VECADD(sb->bpoint[bf->v4].force,sb->bpoint[bf->v4].force,bf->ext_force);
1298 /* --- the face external section*/
1301 /* +++ the spring external section*/
1303 int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp,
1304 float force[3], unsigned int par_layer,struct Object *vertexowner,float time)
1308 GHashIterator *ihash;
1309 float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3],aabbmax[3];
1313 aabbmin[0] = MIN2(edge_v1[0],edge_v2[0]);
1314 aabbmin[1] = MIN2(edge_v1[1],edge_v2[1]);
1315 aabbmin[2] = MIN2(edge_v1[2],edge_v2[2]);
1316 aabbmax[0] = MAX2(edge_v1[0],edge_v2[0]);
1317 aabbmax[1] = MAX2(edge_v1[1],edge_v2[1]);
1318 aabbmax[2] = MAX2(edge_v1[2],edge_v2[2]);
1320 el = VecLenf(edge_v1,edge_v2);
1322 hash = vertexowner->soft->scratch->colliderhash;
1323 ihash = BLI_ghashIterator_new(hash);
1324 while (!BLI_ghashIterator_isDone(ihash) ) {
1326 ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
1327 ob = BLI_ghashIterator_getKey (ihash);
1328 /* only with deflecting set */
1329 if(ob->pd && ob->pd->deflect) {
1332 MVert *mprevvert= NULL;
1333 ccdf_minmax *mima= NULL;
1337 mprevvert= ccdm->mprevvert;
1341 if ((aabbmax[0] < ccdm->bbmin[0]) ||
1342 (aabbmax[1] < ccdm->bbmin[1]) ||
1343 (aabbmax[2] < ccdm->bbmin[2]) ||
1344 (aabbmin[0] > ccdm->bbmax[0]) ||
1345 (aabbmin[1] > ccdm->bbmax[1]) ||
1346 (aabbmin[2] > ccdm->bbmax[2]) ) {
1347 /* boxes dont intersect */
1348 BLI_ghashIterator_step(ihash);
1354 /*aye that should be cached*/
1355 printf("missing cache error \n");
1356 BLI_ghashIterator_step(ihash);
1364 (aabbmax[0] < mima->minx) ||
1365 (aabbmin[0] > mima->maxx) ||
1366 (aabbmax[1] < mima->miny) ||
1367 (aabbmin[1] > mima->maxy) ||
1368 (aabbmax[2] < mima->minz) ||
1369 (aabbmin[2] > mima->maxz)
1379 VECCOPY(nv1,mvert[mface->v1].co);
1380 VECCOPY(nv2,mvert[mface->v2].co);
1381 VECCOPY(nv3,mvert[mface->v3].co);
1383 VECCOPY(nv4,mvert[mface->v4].co);
1387 Vec3PlusStVec(nv1,(1.0f-time),mprevvert[mface->v1].co);
1390 Vec3PlusStVec(nv2,(1.0f-time),mprevvert[mface->v2].co);
1393 Vec3PlusStVec(nv3,(1.0f-time),mprevvert[mface->v3].co);
1397 Vec3PlusStVec(nv4,(1.0f-time),mprevvert[mface->v4].co);
1402 /* switch origin to be nv2*/
1403 VECSUB(edge1, nv1, nv2);
1404 VECSUB(edge2, nv3, nv2);
1406 Crossf(d_nvect, edge2, edge1);
1408 if ( LineIntersectsTriangle(edge_v1, edge_v2, nv1, nv2, nv3, &t, NULL)){
1410 float intrusiondepth,i1,i2;
1411 VECSUB(v1, edge_v1, nv2);
1412 VECSUB(v2, edge_v2, nv2);
1413 i1 = Inpf(v1,d_nvect);
1414 i2 = Inpf(v2,d_nvect);
1415 intrusiondepth = -MIN2(i1,i2)/el;
1416 Vec3PlusStVec(force,intrusiondepth,d_nvect);
1417 *damp=ob->pd->pdef_sbdamp;
1420 if (mface->v4){ /* quad */
1421 /* switch origin to be nv4 */
1422 VECSUB(edge1, nv3, nv4);
1423 VECSUB(edge2, nv1, nv4);
1425 Crossf(d_nvect, edge2, edge1);
1427 if (LineIntersectsTriangle( edge_v1, edge_v2,nv1, nv3, nv4, &t, NULL)){
1429 float intrusiondepth,i1,i2;
1430 VECSUB(v1, edge_v1, nv4);
1431 VECSUB(v2, edge_v2, nv4);
1432 i1 = Inpf(v1,d_nvect);
1433 i2 = Inpf(v2,d_nvect);
1434 intrusiondepth = -MIN2(i1,i2)/el;
1437 Vec3PlusStVec(force,intrusiondepth,d_nvect);
1438 *damp=ob->pd->pdef_sbdamp;
1445 } /* if(ob->pd && ob->pd->deflect) */
1446 BLI_ghashIterator_step(ihash);
1448 BLI_ghashIterator_free(ihash);
1453 void scan_for_ext_spring_forces(Object *ob,float timenow)
1455 SoftBody *sb = ob->soft;
1456 ListBase *do_effector;
1460 do_effector= pdInitEffectors(ob,NULL);
1462 if (sb && sb->totspring){
1463 for(a=0; a<sb->totspring; a++) {
1464 BodySpring *bs = &sb->bspring[a];
1465 bs->ext_force[0]=bs->ext_force[1]=bs->ext_force[2]=0.0f;
1466 feedback[0]=feedback[1]=feedback[2]=0.0f;
1467 bs->flag &= ~BSF_INTERSECT;
1470 /* +++ springs colliding */
1471 if (ob->softflag & OB_SB_EDGECOLL){
1472 if ( sb_detect_edge_collisionCached (sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos,
1473 &damp,feedback,ob->lay,ob,timenow)){
1474 VecAddf(bs->ext_force,bs->ext_force,feedback);
1475 bs->flag |= BSF_INTERSECT;
1477 bs->cf=sb->choke*0.01f;
1481 /* ---- springs colliding */
1483 /* +++ springs seeing wind ... n stuff depending on their orientation*/
1484 /* note we don't use sb->mediafrict but use sb->aeroedge for magnitude of effect*/
1486 float vel[3],sp[3],pr[3],force[3];
1487 float f,windfactor = 250.0f;
1488 /*see if we have wind*/
1490 float speed[3]={0.0f,0.0f,0.0f};
1492 VecMidf(pos, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos);
1493 VecMidf(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec);
1494 pdDoEffectors(do_effector, pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);
1495 VecMulf(speed,windfactor);
1496 VecAddf(vel,vel,speed);
1500 VECADD(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec);
1503 f = -0.0001f*f*f*sb->aeroedge;
1504 /* todo add a nice angle dependant function */
1505 /* look up one at bergman scheafer */
1507 VECSUB(sp, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos);
1511 Vec3PlusStVec(bs->ext_force,f,vel);
1513 /* --- springs seeing wind */
1518 pdEndEffectors(do_effector);
1520 /* --- the spring external section*/
1522 int choose_winner(float*w, float* pos,float*a,float*b,float*c,float*ca,float*cb,float*cc)
1526 mindist = ABS(Inpf(pos,a));
1528 cp = ABS(Inpf(pos,b));
1529 if ( mindist < cp ){
1534 cp = ABS(Inpf(pos,c));
1540 case 1: VECCOPY(w,ca); break;
1541 case 2: VECCOPY(w,cb); break;
1542 case 3: VECCOPY(w,cc);
1549 int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *damp,
1550 float force[3], unsigned int par_layer,struct Object *vertexowner,
1551 float time,float vel[3], float *intrusion)
1555 GHashIterator *ihash;
1556 float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3],ve[3],avel[3]={0.0,0.0,0.0},
1557 vv1[3], vv2[3], vv3[3], vv4[3], coledge[3], mindistedge = 1000.0f,
1558 outerforceaccu[3],innerforceaccu[3],
1559 facedist,n_mag,force_mag_norm,minx,miny,minz,maxx,maxy,maxz,
1560 innerfacethickness = -0.5f, outerfacethickness = 0.2f,
1561 ee = 5.0f, ff = 0.1f, fa=1;
1562 int a, deflected=0, cavel=0,ci=0;
1565 hash = vertexowner->soft->scratch->colliderhash;
1566 ihash = BLI_ghashIterator_new(hash);
1567 outerforceaccu[0]=outerforceaccu[1]=outerforceaccu[2]=0.0f;
1568 innerforceaccu[0]=innerforceaccu[1]=innerforceaccu[2]=0.0f;
1570 while (!BLI_ghashIterator_isDone(ihash) ) {
1572 ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
1573 ob = BLI_ghashIterator_getKey (ihash);
1574 /* only with deflecting set */
1575 if(ob->pd && ob->pd->deflect) {
1578 MVert *mprevvert= NULL;
1579 ccdf_minmax *mima= NULL;
1584 mprevvert= ccdm->mprevvert;
1588 minx =ccdm->bbmin[0];
1589 miny =ccdm->bbmin[1];
1590 minz =ccdm->bbmin[2];
1592 maxx =ccdm->bbmax[0];
1593 maxy =ccdm->bbmax[1];
1594 maxz =ccdm->bbmax[2];
1596 if ((opco[0] < minx) ||
1601 (opco[2] > maxz) ) {
1602 /* outside the padded boundbox --> collision object is too far away */
1603 BLI_ghashIterator_step(ihash);
1608 /*aye that should be cached*/
1609 printf("missing cache error \n");
1610 BLI_ghashIterator_step(ihash);
1614 /* do object level stuff */
1615 /* need to have user control for that since it depends on model scale */
1616 innerfacethickness =-ob->pd->pdef_sbift;
1617 outerfacethickness =ob->pd->pdef_sboft;
1618 fa = (ff*outerfacethickness-outerfacethickness);
1621 avel[0]=avel[1]=avel[2]=0.0f;
1625 (opco[0] < mima->minx) ||
1626 (opco[0] > mima->maxx) ||
1627 (opco[1] < mima->miny) ||
1628 (opco[1] > mima->maxy) ||
1629 (opco[2] < mima->minz) ||
1630 (opco[2] > mima->maxz)
1639 VECCOPY(nv1,mvert[mface->v1].co);
1640 VECCOPY(nv2,mvert[mface->v2].co);
1641 VECCOPY(nv3,mvert[mface->v3].co);
1643 VECCOPY(nv4,mvert[mface->v4].co);
1647 /* grab the average speed of the collider vertices
1649 humm could be done once a SB steps but then we' need to store that too
1650 since the AABB reduced propabitlty to get here drasticallly
1651 it might be a nice tradeof CPU <--> memory
1653 VECSUB(vv1,nv1,mprevvert[mface->v1].co);
1654 VECSUB(vv2,nv2,mprevvert[mface->v2].co);
1655 VECSUB(vv3,nv3,mprevvert[mface->v3].co);
1657 VECSUB(vv4,nv4,mprevvert[mface->v4].co);
1661 Vec3PlusStVec(nv1,(1.0f-time),mprevvert[mface->v1].co);
1664 Vec3PlusStVec(nv2,(1.0f-time),mprevvert[mface->v2].co);
1667 Vec3PlusStVec(nv3,(1.0f-time),mprevvert[mface->v3].co);
1671 Vec3PlusStVec(nv4,(1.0f-time),mprevvert[mface->v4].co);
1676 /* switch origin to be nv2*/
1677 VECSUB(edge1, nv1, nv2);
1678 VECSUB(edge2, nv3, nv2);
1679 VECSUB(dv1,opco,nv2); /* abuse dv1 to have vertex in question at *origin* of triangle */
1681 Crossf(d_nvect, edge2, edge1);
1682 n_mag = Normalize(d_nvect);
1683 facedist = Inpf(dv1,d_nvect);
1687 if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
1688 if (point_in_tri_prism(opco, nv1, nv2, nv3) ){
1689 force_mag_norm =(float)exp(-ee*facedist);
1690 if (facedist > outerfacethickness*ff)
1691 force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
1692 *damp=ob->pd->pdef_sbdamp;
1693 if (facedist > 0.0f){
1694 *damp *= (1.0f - facedist/outerfacethickness);
1695 Vec3PlusStVec(outerforceaccu,force_mag_norm,d_nvect);
1700 Vec3PlusStVec(innerforceaccu,force_mag_norm,d_nvect);
1701 if (deflected < 2) deflected = 2;
1703 if ((mprevvert) && (*damp > 0.0f)){
1704 choose_winner(ve,opco,nv1,nv2,nv3,vv1,vv2,vv3);
1705 VECADD(avel,avel,ve);
1708 *intrusion += facedist;
1712 if (mface->v4){ /* quad */
1713 /* switch origin to be nv4 */
1714 VECSUB(edge1, nv3, nv4);
1715 VECSUB(edge2, nv1, nv4);
1716 VECSUB(dv1,opco,nv4); /* abuse dv1 to have vertex in question at *origin* of triangle */
1718 Crossf(d_nvect, edge2, edge1);
1719 n_mag = Normalize(d_nvect);
1720 facedist = Inpf(dv1,d_nvect);
1722 if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
1723 if (point_in_tri_prism(opco, nv1, nv3, nv4) ){
1724 force_mag_norm =(float)exp(-ee*facedist);
1725 if (facedist > outerfacethickness*ff)
1726 force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
1727 *damp=ob->pd->pdef_sbdamp;
1728 if (facedist > 0.0f){
1729 *damp *= (1.0f - facedist/outerfacethickness);
1730 Vec3PlusStVec(outerforceaccu,force_mag_norm,d_nvect);
1735 Vec3PlusStVec(innerforceaccu,force_mag_norm,d_nvect);
1736 if (deflected < 2) deflected = 2;
1739 if ((mprevvert) && (*damp > 0.0f)){
1740 choose_winner(ve,opco,nv1,nv3,nv4,vv1,vv3,vv4);
1741 VECADD(avel,avel,ve);
1744 *intrusion += facedist;
1749 if ((deflected < 2)&& (G.rt != 444)) // we did not hit a face until now
1750 { // see if 'outer' hits an edge
1753 PclosestVL3Dfl(ve, opco, nv1, nv2);
1755 dist = Normalize(ve);
1756 if ((dist < outerfacethickness)&&(dist < mindistedge )){
1757 VECCOPY(coledge,ve);
1762 PclosestVL3Dfl(ve, opco, nv2, nv3);
1764 dist = Normalize(ve);
1765 if ((dist < outerfacethickness)&&(dist < mindistedge )){
1766 VECCOPY(coledge,ve);
1771 PclosestVL3Dfl(ve, opco, nv3, nv1);
1773 dist = Normalize(ve);
1774 if ((dist < outerfacethickness)&&(dist < mindistedge )){
1775 VECCOPY(coledge,ve);
1779 if (mface->v4){ /* quad */
1780 PclosestVL3Dfl(ve, opco, nv3, nv4);
1782 dist = Normalize(ve);
1783 if ((dist < outerfacethickness)&&(dist < mindistedge )){
1784 VECCOPY(coledge,ve);
1789 PclosestVL3Dfl(ve, opco, nv1, nv4);
1791 dist = Normalize(ve);
1792 if ((dist < outerfacethickness)&&(dist < mindistedge )){
1793 VECCOPY(coledge,ve);
1806 } /* if(ob->pd && ob->pd->deflect) */
1807 BLI_ghashIterator_step(ihash);
1810 if (deflected == 1){ // no face but 'outer' edge cylinder sees vert
1811 force_mag_norm =(float)exp(-ee*mindistedge);
1812 if (mindistedge > outerfacethickness*ff)
1813 force_mag_norm =(float)force_mag_norm*fa*(mindistedge - outerfacethickness)*(mindistedge - outerfacethickness);
1814 Vec3PlusStVec(force,force_mag_norm,coledge);
1815 *damp=ob->pd->pdef_sbdamp;
1816 if (mindistedge > 0.0f){
1817 *damp *= (1.0f - mindistedge/outerfacethickness);
1821 if (deflected == 2){ // face inner detected
1822 VECADD(force,force,innerforceaccu);
1824 if (deflected == 3){ // face outer detected
1825 VECADD(force,force,outerforceaccu);
1828 BLI_ghashIterator_free(ihash);
1829 if (cavel) VecMulf(avel,1.0f/(float)cavel);
1831 if (ci) *intrusion /= ci;
1833 VECCOPY(facenormal,force);
1834 Normalize(facenormal);
1839 /* not complete yet ..
1840 try to find a pos resolving all inside collisions
1842 #if 0 //mute it for now
1843 int sb_detect_vertex_collisionCachedEx(float opco[3], float facenormal[3], float *damp,
1844 float force[3], unsigned int par_layer,struct Object *vertexowner,
1845 float time,float vel[3], float *intrusion)
1849 GHashIterator *ihash;
1850 float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3],ve[3],avel[3],
1851 vv1[3], vv2[3], vv3[3], vv4[3],
1852 facedist,n_mag,force_mag_norm,minx,miny,minz,maxx,maxy,maxz,
1853 innerfacethickness,outerfacethickness,
1855 ee = 5.0f, ff = 0.1f, fa;
1856 int a, deflected=0, cavel=0;
1859 hash = vertexowner->soft->scratch->colliderhash;
1860 ihash = BLI_ghashIterator_new(hash);
1862 while (!BLI_ghashIterator_isDone(ihash) ) {
1864 ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
1865 ob = BLI_ghashIterator_getKey (ihash);
1866 /* only with deflecting set */
1867 if(ob->pd && ob->pd->deflect) {
1870 MVert *mprevvert= NULL;
1871 ccdf_minmax *mima= NULL;
1876 mprevvert= ccdm->mprevvert;
1880 minx =ccdm->bbmin[0];
1881 miny =ccdm->bbmin[1];
1882 minz =ccdm->bbmin[2];
1884 maxx =ccdm->bbmax[0];
1885 maxy =ccdm->bbmax[1];
1886 maxz =ccdm->bbmax[2];
1888 if ((opco[0] < minx) ||
1893 (opco[2] > maxz) ) {
1894 /* outside the padded boundbox --> collision object is too far away */
1895 BLI_ghashIterator_step(ihash);
1900 /*aye that should be cached*/
1901 printf("missing cache error \n");
1902 BLI_ghashIterator_step(ihash);
1906 /* do object level stuff */
1907 /* need to have user control for that since it depends on model scale */
1908 innerfacethickness =-ob->pd->pdef_sbift;
1909 outerfacethickness =ob->pd->pdef_sboft;
1910 closestinside = innerfacethickness;
1911 fa = (ff*outerfacethickness-outerfacethickness);
1914 avel[0]=avel[1]=avel[2]=0.0f;
1918 (opco[0] < mima->minx) ||
1919 (opco[0] > mima->maxx) ||
1920 (opco[1] < mima->miny) ||
1921 (opco[1] > mima->maxy) ||
1922 (opco[2] < mima->minz) ||
1923 (opco[2] > mima->maxz)
1932 VECCOPY(nv1,mvert[mface->v1].co);
1933 VECCOPY(nv2,mvert[mface->v2].co);
1934 VECCOPY(nv3,mvert[mface->v3].co);
1936 VECCOPY(nv4,mvert[mface->v4].co);
1940 /* grab the average speed of the collider vertices
1942 humm could be done once a SB steps but then we' need to store that too
1943 since the AABB reduced propabitlty to get here drasticallly
1944 it might be a nice tradeof CPU <--> memory
1946 VECSUB(vv1,nv1,mprevvert[mface->v1].co);
1947 VECSUB(vv2,nv2,mprevvert[mface->v2].co);
1948 VECSUB(vv3,nv3,mprevvert[mface->v3].co);
1950 VECSUB(vv4,nv4,mprevvert[mface->v4].co);
1954 Vec3PlusStVec(nv1,(1.0f-time),mprevvert[mface->v1].co);
1957 Vec3PlusStVec(nv2,(1.0f-time),mprevvert[mface->v2].co);
1960 Vec3PlusStVec(nv3,(1.0f-time),mprevvert[mface->v3].co);
1964 Vec3PlusStVec(nv4,(1.0f-time),mprevvert[mface->v4].co);
1969 /* switch origin to be nv2*/
1970 VECSUB(edge1, nv1, nv2);
1971 VECSUB(edge2, nv3, nv2);
1972 VECSUB(dv1,opco,nv2); /* abuse dv1 to have vertex in question at *origin* of triangle */
1974 Crossf(d_nvect, edge2, edge1);
1975 n_mag = Normalize(d_nvect);
1976 facedist = Inpf(dv1,d_nvect);
1978 if ((facedist > closestinside) && (facedist < outerfacethickness)){
1979 // if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
1980 if (point_in_tri_prism(opco, nv1, nv2, nv3) ){
1981 force_mag_norm =(float)exp(-ee*facedist);
1982 if (facedist > outerfacethickness*ff)
1983 force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
1984 *damp=ob->pd->pdef_sbdamp;
1986 if (facedist > 0.0f){
1987 *damp *= (1.0f - facedist/outerfacethickness);
1988 Vec3PlusStVec(force,force_mag_norm,d_nvect);
1991 if ((mprevvert) && (*damp > 0.0f)){
1992 choose_winner(ve,opco,nv1,nv2,nv3,vv1,vv2,vv3);
1993 VECADD(avel,avel,ve);
2000 Vec3PlusStVec(force,force_mag_norm,d_nvect);
2001 VECCOPY(facenormal,d_nvect);
2002 if ((mprevvert) && (*damp > 0.0f)){
2003 choose_winner(avel,opco,nv1,nv2,nv3,vv1,vv2,vv3);
2006 closestinside = facedist;
2009 *intrusion = facedist;
2012 if (mface->v4){ /* quad */
2013 /* switch origin to be nv4 */
2014 VECSUB(edge1, nv3, nv4);
2015 VECSUB(edge2, nv1, nv4);
2016 VECSUB(dv1,opco,nv4); /* abuse dv1 to have vertex in question at *origin* of triangle */
2018 Crossf(d_nvect, edge2, edge1);
2019 n_mag = Normalize(d_nvect);
2020 facedist = Inpf(dv1,d_nvect);
2022 if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
2023 if (point_in_tri_prism(opco, nv1, nv3, nv4) ){
2024 force_mag_norm =(float)exp(-ee*facedist);
2025 if (facedist > outerfacethickness*ff)
2026 force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
2027 Vec3PlusStVec(force,force_mag_norm,d_nvect);
2028 *damp=ob->pd->pdef_sbdamp;
2030 if (facedist > 0.0f){
2031 *damp *= (1.0f - facedist/outerfacethickness);
2032 Vec3PlusStVec(force,force_mag_norm,d_nvect);
2035 if ((mprevvert) && (*damp > 0.0f)){
2036 choose_winner(ve,opco,nv1,nv3,nv4,vv1,vv3,vv4);
2037 VECADD(avel,avel,ve);
2044 Vec3PlusStVec(force,force_mag_norm,d_nvect);
2045 VECCOPY(facenormal,d_nvect);
2046 if ((mprevvert) && (*damp > 0.0f)){
2047 choose_winner(avel,opco,nv1,nv3,nv4,vv1,vv3,vv4);
2050 closestinside = facedist;
2056 *intrusion = facedist;
2064 } /* if(ob->pd && ob->pd->deflect) */
2065 BLI_ghashIterator_step(ihash);
2067 BLI_ghashIterator_free(ihash);
2068 if (cavel) VecMulf(avel,1.0f/(float)cavel);
2071 /* we did stay "outside" but have some close to contact forces
2072 just to be complete fake a face normal
2075 VECCOPY(facenormal,force);
2076 Normalize(facenormal);
2079 facenormal[0] = facenormal[1] = facenormal[2] = 0.0f;
2087 /* sandbox to plug in various deflection algos */
2088 static int sb_deflect_face(Object *ob,float *actpos,float *facenormal,float *force,float *cf,float time,float *vel,float *intrusion)
2092 VECCOPY(s_actpos,actpos);
2093 deflected= sb_detect_vertex_collisionCached(s_actpos, facenormal, cf, force , ob->lay, ob,time,vel,intrusion);
2094 //deflected= sb_detect_vertex_collisionCachedEx(s_actpos, facenormal, cf, force , ob->lay, ob,time,vel,intrusion);
2099 static void softbody_calc_forces(Object *ob, float forcetime, float timenow)
2101 /* rule we never alter free variables :bp->vec bp->pos in here !
2102 * this will ruin adaptive stepsize AKA heun! (BM)
2104 SoftBody *sb= ob->soft; /* is supposed to be there */
2108 ListBase *do_effector;
2109 float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3];
2110 float fieldfactor = 1000.0f, windfactor = 250.0f;
2111 float tune = sb->ballstiff;
2112 int a, b, do_deflector,do_selfcollision,do_springcollision,do_aero;
2115 gravity = sb->grav * sb_grav_force_scale(ob);
2117 /* check conditions for various options */
2118 do_deflector= query_external_colliders(ob);
2119 do_effector= pdInitEffectors(ob,NULL);
2120 do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
2121 do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
2122 do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
2124 iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
2125 bproot= sb->bpoint; /* need this for proper spring addressing */
2129 if (do_springcollision || do_aero) scan_for_ext_spring_forces(ob,timenow);
2132 do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow);
2135 if (do_selfcollision ){
2137 VecMidf(ce,sb->scratch->aabbmax,sb->scratch->aabbmin);
2138 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
2139 bp->octantflag = set_octant_flags(ce,bp->pos,bp->colball);
2143 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
2144 /* clear forces accumulator */
2145 bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
2147 /* naive ball self collision */
2148 /* needs to be done if goal snaps or not */
2149 if(do_selfcollision){
2153 float velcenter[3],dvel[3],def[3];
2157 for(c=sb->totpoint, obp= sb->bpoint; c>=a; c--, obp++) {
2159 if ((bp->octantflag & obp->octantflag) == 0) continue;
2161 compare = (obp->colball + bp->colball);
2162 VecSubf(def, bp->pos, obp->pos);
2164 /* rather check the AABBoxes before ever calulating the real distance */
2165 /* mathematically it is completly nuts, but performace is pretty much (3) times faster */
2166 if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
2168 distance = Normalize(def);
2169 if (distance < compare ){
2170 /* exclude body points attached with a spring */
2172 for(b=obp->nofsprings;b>0;b--){
2173 bs = sb->bspring + obp->springs[b-1];
2174 if (( sb->totpoint-a == bs->v2) || ( sb->totpoint-a == bs->v1)){
2179 float f = tune/(distance) + tune/(compare*compare)*distance - 2.0f*tune/compare ;
2181 VecMidf(velcenter, bp->vec, obp->vec);
2182 VecSubf(dvel,velcenter,bp->vec);
2183 VecMulf(dvel,sb->nodemass);
2185 Vec3PlusStVec(bp->force,sb->balldamp,dvel);
2186 Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def);
2187 /* exploit force(a,b) == -force(b,a) part2/2 */
2188 VecSubf(dvel,velcenter,obp->vec);
2189 VecMulf(dvel,sb->nodemass);
2191 Vec3PlusStVec(obp->force,sb->balldamp,dvel);
2192 Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def);
2198 /* naive ball self collision done */
2200 if(bp->goal < SOFTGOALSNAP){ /* ommit this bp when it snaps */
2203 float absvel =0, projvel= 0;
2206 if(ob->softflag & OB_SB_GOAL) {
2207 /* true elastic goal */
2208 VecSubf(auxvect,bp->origT,bp->pos);
2209 ks = 1.0f/(1.0f- bp->goal*sb->goalspring)-1.0f ;
2210 bp->force[0]+= ks*(auxvect[0]);
2211 bp->force[1]+= ks*(auxvect[1]);
2212 bp->force[2]+= ks*(auxvect[2]);
2213 /* calulate damping forces generated by goals*/
2214 VecSubf(velgoal,bp->origS, bp->origE);
2215 kd = sb->goalfrict * sb_fric_force_scale(ob) ;
2217 if (forcetime > 0.0 ) { /* make sure friction does not become rocket motor on time reversal */
2218 bp->force[0]-= kd * (velgoal[0] + bp->vec[0]);
2219 bp->force[1]-= kd * (velgoal[1] + bp->vec[1]);
2220 bp->force[2]-= kd * (velgoal[2] + bp->vec[2]);
2223 bp->force[0]-= kd * (velgoal[0] - bp->vec[0]);
2224 bp->force[1]-= kd * (velgoal[1] - bp->vec[1]);
2225 bp->force[2]-= kd * (velgoal[2] - bp->vec[2]);
2228 /* done goal stuff */
2232 bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */
2235 /* particle field & vortex */
2237 float force[3]= {0.0f, 0.0f, 0.0f};
2238 float speed[3]= {0.0f, 0.0f, 0.0f};
2239 float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */
2241 pdDoEffectors(do_effector, bp->pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);
2243 /* apply forcefield*/
2244 VecMulf(force,fieldfactor* eval_sb_fric_force_scale);
2245 VECADD(bp->force, bp->force, force);
2247 /* BP friction in moving media */
2248 kd= sb->mediafrict* eval_sb_fric_force_scale;
2249 bp->force[0] -= kd * (bp->vec[0] + windfactor*speed[0]/eval_sb_fric_force_scale);
2250 bp->force[1] -= kd * (bp->vec[1] + windfactor*speed[1]/eval_sb_fric_force_scale);
2251 bp->force[2] -= kd * (bp->vec[2] + windfactor*speed[2]/eval_sb_fric_force_scale);
2252 /* now we'll have nice centrifugal effect for vortex */
2256 /* BP friction in media (not) moving*/
2257 kd= sb->mediafrict* sb_fric_force_scale(ob);
2258 /* assume it to be proportional to actual velocity */
2259 bp->force[0]-= bp->vec[0]*kd;
2260 bp->force[1]-= bp->vec[1]*kd;
2261 bp->force[2]-= bp->vec[2]*kd;
2262 /* friction in media done */
2264 /* +++cached collision targets */
2266 bp->flag &= ~SBF_DOFUZZY;
2268 float cfforce[3],defforce[3] ={0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}, facenormal[3], cf = 1.0f,intrusion;
2271 if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){
2272 if (intrusion < 0.0f){
2273 /*bjornmose: uugh.. what an evil hack
2274 violation of the 'don't touch bp->pos in here' rule
2275 but works nice, like this-->
2276 we predict the solution beeing out of the collider
2277 in heun step No1 and leave the heun step No2 adapt to it
2278 so we kind of introduced a implicit solver for this case
2280 Vec3PlusStVec(bp->pos,-intrusion,facenormal);
2282 sb->scratch->flag |= SBF_DOFUZZY;
2283 bp->flag |= SBF_DOFUZZY;
2284 bp->choke = sb->choke*0.01f;
2287 VECSUB(cfforce,bp->vec,vel);
2288 Vec3PlusStVec(bp->force,-cf*50.0f,cfforce);
2291 Vec3PlusStVec(bp->force,kd,defforce);
2295 /* ---cached collision targets */
2298 if(ob->softflag & OB_SB_EDGES) {
2299 if (sb->bspring){ /* spring list exists at all ? */
2300 for(b=bp->nofsprings;b>0;b--){
2301 bs = sb->bspring + bp->springs[b-1];
2302 if (do_springcollision || do_aero){
2303 VecAddf(bp->force,bp->force,bs->ext_force);
2304 if (bs->flag & BSF_INTERSECT)
2309 if (( (sb->totpoint-a) == bs->v1) ){
2310 VecSubf(sd,(bproot+bs->v2)->pos, bp->pos);
2311 actspringlen=Normalize(sd);
2313 /* friction stuff V1 */
2314 VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec);
2315 kd = sb->infrict * sb_fric_force_scale(ob);
2316 absvel = Normalize(velgoal);
2317 projvel = ABS(Inpf(sd,velgoal));
2318 kd *= absvel * projvel;
2319 Vec3PlusStVec(bp->force,-kd,velgoal);
2321 if(bs->len > 0.0f) /* check for degenerated springs */
2322 forcefactor = (bs->len - actspringlen)/bs->len * iks;
2324 forcefactor = actspringlen * iks;
2325 forcefactor *= bs->strength;
2327 Vec3PlusStVec(bp->force,-forcefactor,sd);
2331 if (( (sb->totpoint-a) == bs->v2) ){
2332 VecSubf(sd,bp->pos,(bproot+bs->v1)->pos);
2333 actspringlen=Normalize(sd);
2335 /* friction stuff V2 */
2336 VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec);
2337 kd = sb->infrict * sb_fric_force_scale(ob);
2338 absvel = Normalize(velgoal);
2339 projvel = ABS(Inpf(sd,velgoal));
2340 kd *= absvel * projvel;
2341 Vec3PlusStVec(bp->force,-kd,velgoal);
2344 forcefactor = (bs->len - actspringlen)/bs->len * iks;
2346 forcefactor = actspringlen * iks;
2347 forcefactor *= bs->strength;
2348 Vec3PlusStVec(bp->force,+forcefactor,sd);
2351 }/* existing spring list */
2358 /* finally add forces caused by face collision */
2359 if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow);
2361 if(do_effector) pdEndEffectors(do_effector);
2366 static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err)
2368 /* time evolution */
2369 /* actually does an explicit euler step mode == 0 */
2370 /* or heun ~ 2nd order runge-kutta steps, mode 1,2 */
2371 SoftBody *sb= ob->soft; /* is supposed to be there */
2373 float dx[3],dv[3],aabbmin[3],aabbmax[3],cm[3]={0.0f,0.0f,0.0f};
2375 float maxerrpos= 0.0f,maxerrvel = 0.0f;
2378 forcetime *= sb_time_scale(ob);
2380 aabbmin[0]=aabbmin[1]=aabbmin[2] = 1e20f;
2381 aabbmax[0]=aabbmax[1]=aabbmax[2] = -1e20f;
2383 /* claim a minimum mass for vertex */
2384 if (sb->nodemass > 0.009999f) timeovermass = forcetime/sb->nodemass;
2385 else timeovermass = forcetime/0.009999f;
2387 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
2388 if(bp->goal < SOFTGOALSNAP){
2390 /* so here is (v)' = a(cceleration) = sum(F_springs)/m + gravitation + some friction forces + more forces*/
2391 /* the ( ... )' operator denotes derivate respective time */
2392 /* the euler step for velocity then becomes */
2393 /* v(t + dt) = v(t) + a(t) * dt */
2394 bp->force[0]*= timeovermass; /* individual mass of node here */
2395 bp->force[1]*= timeovermass;
2396 bp->force[2]*= timeovermass;
2397 /* some nasty if's to have heun in here too */
2398 VECCOPY(dv,bp->force);
2401 VECCOPY(bp->prevvec, bp->vec);
2402 VECCOPY(bp->prevdv, dv);
2406 /* be optimistic and execute step */
2407 bp->vec[0] = bp->prevvec[0] + 0.5f * (dv[0] + bp->prevdv[0]);
2408 bp->vec[1] = bp->prevvec[1] + 0.5f * (dv[1] + bp->prevdv[1]);
2409 bp->vec[2] = bp->prevvec[2] + 0.5f * (dv[2] + bp->prevdv[2]);
2410 /* compare euler to heun to estimate error for step sizing */
2411 maxerrvel = MAX2(maxerrvel,ABS(dv[0] - bp->prevdv[0]));
2412 maxerrvel = MAX2(maxerrvel,ABS(dv[1] - bp->prevdv[1]));
2413 maxerrvel = MAX2(maxerrvel,ABS(dv[2] - bp->prevdv[2]));
2415 else {VECADD(bp->vec, bp->vec, bp->force);}
2417 /* so here is (x)'= v(elocity) */
2418 /* the euler step for location then becomes */
2419 /* x(t + dt) = x(t) + v(t) * dt */
2421 VECCOPY(dx,bp->vec);
2425 /* again some nasty if's to have heun in here too */
2427 VECCOPY(bp->prevpos,bp->pos);
2428 VECCOPY(bp->prevdx ,dx);
2432 bp->pos[0] = bp->prevpos[0] + 0.5f * ( dx[0] + bp->prevdx[0]);
2433 bp->pos[1] = bp->prevpos[1] + 0.5f * ( dx[1] + bp->prevdx[1]);
2434 bp->pos[2] = bp->prevpos[2] + 0.5f* ( dx[2] + bp->prevdx[2]);
2435 maxerrpos = MAX2(maxerrpos,ABS(dx[0] - bp->prevdx[0]));
2436 maxerrpos = MAX2(maxerrpos,ABS(dx[1] - bp->prevdx[1]));
2437 maxerrpos = MAX2(maxerrpos,ABS(dx[2] - bp->prevdx[2]));
2439 /* bp->choke is set when we need to pull a vertex or edge out of the collider.
2440 the collider object signals to get out by pushing hard. on the other hand
2441 we don't want to end up in deep space so we add some <viscosity>
2442 to balance that out */
2443 if (bp->choke > 0.0f){
2444 bp->vec[0] = bp->vec[0]*(1.0f - bp->choke);
2445 bp->vec[1] = bp->vec[1]*(1.0f - bp->choke);
2446 bp->vec[2] = bp->vec[2]*(1.0f - bp->choke);
2450 else { VECADD(bp->pos, bp->pos, dx);}
2452 /* so while we are looping BPs anyway do statistics on the fly */
2453 aabbmin[0] = MIN2(aabbmin[0],bp->pos[0]);
2454 aabbmin[1] = MIN2(aabbmin[1],bp->pos[1]);
2455 aabbmin[2] = MIN2(aabbmin[2],bp->pos[2]);
2456 aabbmax[0] = MAX2(aabbmax[0],bp->pos[0]);
2457 aabbmax[1] = MAX2(aabbmax[1],bp->pos[1]);
2458 aabbmax[2] = MAX2(aabbmax[2],bp->pos[2]);
2459 if (bp->flag & SBF_DOFUZZY) fuzzy =1;
2462 if (sb->totpoint) VecMulf(cm,1.0f/sb->totpoint);
2464 VECCOPY(sb->scratch->aabbmin,aabbmin);
2465 VECCOPY(sb->scratch->aabbmax,aabbmax);
2468 if (err){ /* so step size will be controlled by biggest difference in slope */
2469 if (sb->solverflags & SBSO_OLDERR)
2470 *err = MAX2(maxerrpos,maxerrvel);
2473 //printf("EP %f EV %f \n",maxerrpos,maxerrvel);
2475 *err /= sb->fuzzyness;
2480 /* used by heun when it overshoots */
2481 static void softbody_restore_prev_step(Object *ob)
2483 SoftBody *sb= ob->soft; /* is supposed to be there*/
2487 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
2488 VECCOPY(bp->vec, bp->prevvec);
2489 VECCOPY(bp->pos, bp->prevpos);
2493 /* care for bodypoints taken out of the 'ordinary' solver step
2494 ** because they are screwed to goal by bolts
2495 ** they just need to move along with the goal in time
2496 ** we need to adjust them on sub frame timing in solver
2497 ** so now when frame is done .. put 'em to the position at the end of frame
2499 static void softbody_apply_goalsnap(Object *ob)
2501 SoftBody *sb= ob->soft; /* is supposed to be there */
2505 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
2506 if (bp->goal >= SOFTGOALSNAP){
2507 VECCOPY(bp->prevpos,bp->pos);
2508 VECCOPY(bp->pos,bp->origT);
2513 /* expects full initialized softbody */
2514 static void interpolate_exciter(Object *ob, int timescale, int time)
2516 SoftBody *sb= ob->soft;
2521 f = (float)time/(float)timescale;
2523 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
2524 bp->origT[0] = bp->origS[0] + f*(bp->origE[0] - bp->origS[0]);
2525 bp->origT[1] = bp->origS[1] + f*(bp->origE[1] - bp->origS[1]);
2526 bp->origT[2] = bp->origS[2] + f*(bp->origE[2] - bp->origS[2]);
2527 if (bp->goal >= SOFTGOALSNAP){
2528 bp->vec[0] = bp->origE[0] - bp->origS[0];
2529 bp->vec[1] = bp->origE[1] - bp->origS[1];
2530 bp->vec[2] = bp->origE[2] - bp->origS[2];
2537 /* ************ convertors ********** */
2539 /* for each object type we need;
2540 - xxxx_to_softbody(Object *ob) : a full (new) copy, creates SB geometry
2543 static void get_scalar_from_vertexgroup(Object *ob, int vertID, short groupindex, float *target)
2544 /* result 0 on success, else indicates error number
2545 -- kind of *inverse* result defintion,
2546 -- but this way we can signal error condition to caller
2547 -- and yes this function must not be here but in a *vertex group module*
2550 MDeformVert *dv= NULL;
2553 /* spot the vert in deform vert list at mesh */
2554 if(ob->type==OB_MESH) {
2557 dv = me->dvert + vertID;