Blender V2.61 - r43446

softbody.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) Blender Foundation
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 /*
00034 ******
00035 variables on the UI for now
00036 
00037     float mediafrict;  friction to env
00038     float nodemass;   softbody mass of *vertex*
00039     float grav;        softbody amount of gravitaion to apply
00040 
00041     float goalspring;  softbody goal springs
00042     float goalfrict;   softbody goal springs friction
00043     float mingoal;     quick limits for goal
00044     float maxgoal;
00045 
00046     float inspring;   softbody inner springs
00047     float infrict;     softbody inner springs friction
00048 
00049 *****
00050 */
00051 
00052 
00053 #include <math.h>
00054 #include <stdlib.h>
00055 #include <string.h>
00056 
00057 #include "MEM_guardedalloc.h"
00058 
00059 /* types */
00060 #include "DNA_object_types.h"
00061 #include "DNA_scene_types.h"
00062 #include "DNA_lattice_types.h"
00063 #include "DNA_curve_types.h"
00064 #include "DNA_mesh_types.h"
00065 #include "DNA_meshdata_types.h"
00066 
00067 #include "BLI_math.h"
00068 #include "BLI_utildefines.h"
00069 #include "BLI_listbase.h"
00070 #include "BLI_ghash.h"
00071 #include "BLI_threads.h"
00072 
00073 #include "BKE_curve.h"
00074 #include "BKE_effect.h"
00075 #include "BKE_global.h"
00076 #include "BKE_modifier.h"
00077 #include "BKE_softbody.h"
00078 #include "BKE_DerivedMesh.h"
00079 #include "BKE_pointcache.h"
00080 #include "BKE_deform.h"
00081 //XXX #include  "BIF_editdeform.h"
00082 //XXX #include  "BIF_graphics.h"
00083 #include  "PIL_time.h"
00084 // #include  "ONL_opennl.h" remove linking to ONL for now
00085 
00086 /* callbacks for errors and interrupts and some goo */
00087 static int (*SB_localInterruptCallBack)(void) = NULL;
00088 
00089 
00090 /* ********** soft body engine ******* */
00091 
00092 typedef enum {SB_EDGE=1,SB_BEND=2,SB_STIFFQUAD=3,SB_HANDLE=4} type_spring;
00093 
00094 typedef struct BodySpring {
00095     int v1, v2;
00096     float len,cf,load;
00097     float ext_force[3]; /* edges colliding and sailing */
00098     type_spring springtype;
00099     short flag;
00100 } BodySpring;
00101 
00102 typedef struct BodyFace {
00103     int v1, v2, v3 ,v4;
00104     float ext_force[3]; /* faces colliding */
00105     short flag;
00106 } BodyFace;
00107 
00108 typedef struct ReferenceVert {
00109     float pos[3]; /* position relative to com */
00110     float mass;   /* node mass */
00111 } ReferenceVert;
00112 
00113 typedef struct ReferenceState {
00114     float com[3]; /* center of mass*/
00115     ReferenceVert *ivert; /* list of intial values */
00116 }ReferenceState ;
00117 
00118 
00119 /*private scratch pad for caching and other data only needed when alive*/
00120 typedef struct SBScratch {
00121     GHash *colliderhash;
00122     short needstobuildcollider;
00123     short flag;
00124     BodyFace *bodyface;
00125     int totface;
00126     float aabbmin[3],aabbmax[3];
00127     ReferenceState Ref;
00128 }SBScratch;
00129 
00130 typedef struct  SB_thread_context {
00131         Scene *scene;
00132         Object *ob;
00133         float forcetime;
00134         float timenow;
00135         int ifirst;
00136         int ilast;
00137         ListBase *do_effector;
00138         int do_deflector;
00139         float fieldfactor;
00140         float windfactor;
00141         int nr;
00142         int tot;
00143 }SB_thread_context;
00144 
00145 #define NLF_BUILD  1
00146 #define NLF_SOLVE  2
00147 
00148 #define MID_PRESERVE 1
00149 
00150 #define SOFTGOALSNAP  0.999f
00151 /* if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp
00152    removes *unnecessary* stiffnes from ODE system
00153 */
00154 #define HEUNWARNLIMIT 1 /* 500 would be fine i think for detecting severe *stiff* stuff */
00155 
00156 
00157 #define BSF_INTERSECT   1 /* edge intersects collider face */
00158 
00159 /* private definitions for bodypoint states */
00160 #define SBF_DOFUZZY          1 /* Bodypoint do fuzzy */
00161 #define SBF_OUTOFCOLLISION   2 /* Bodypoint does not collide  */
00162 
00163 
00164 #define BFF_INTERSECT   1 /* collider edge   intrudes face */
00165 #define BFF_CLOSEVERT   2 /* collider vertex repulses face */
00166 
00167 
00168 static float SoftHeunTol = 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
00169 
00170 /* local prototypes */
00171 static void free_softbody_intern(SoftBody *sb);
00172 /* aye this belongs to arith.c */
00173 static void Vec3PlusStVec(float *v, float s, float *v1);
00174 
00175 /*+++ frame based timing +++*/
00176 
00177 /*physical unit of force is [kg * m / sec^2]*/
00178 
00179 static float sb_grav_force_scale(Object *UNUSED(ob))
00180 /* since unit of g is [m/sec^2] and F = mass * g we rescale unit mass of node to 1 gramm
00181   put it to a function here, so we can add user options later without touching simulation code
00182 */
00183 {
00184     return (0.001f);
00185 }
00186 
00187 static float sb_fric_force_scale(Object *UNUSED(ob))
00188 /* rescaling unit of drag [1 / sec] to somehow reasonable
00189   put it to a function here, so we can add user options later without touching simulation code
00190 */
00191 {
00192     return (0.01f);
00193 }
00194 
00195 static float sb_time_scale(Object *ob)
00196 /* defining the frames to *real* time relation */
00197 {
00198     SoftBody *sb= ob->soft; /* is supposed to be there */
00199     if (sb){
00200         return(sb->physics_speed);
00201         /*hrms .. this could be IPO as well :)
00202          estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
00203          1 approx = a unit 1 pendulum at g = 9.8 [earth conditions]  has period 65 frames
00204          theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM)
00205          */
00206     }
00207     return (1.0f);
00208     /*
00209     this would be frames/sec independent timing assuming 25 fps is default
00210     but does not work very well with NLA
00211         return (25.0f/scene->r.frs_sec)
00212     */
00213 }
00214 /*--- frame based timing ---*/
00215 
00216 /* helper functions for everything is animatable jow_go_for2_5 +++++++*/
00217 /* introducing them here, because i know: steps in properties  ( at frame timing )
00218    will cause unwanted responses of the softbody system (which does inter frame calculations )
00219    so first 'cure' would be: interpolate linear in time ..
00220    Q: why do i write this?
00221    A: because it happend once, that some eger coder 'streamlined' code to fail.
00222    We DO linear interpolation for goals .. and i think we should do on animated properties as well
00223 */
00224 
00225 /* animate sb->maxgoal,sb->mingoal */
00226 static float _final_goal(Object *ob,BodyPoint *bp)/*jow_go_for2_5 */
00227 {
00228     float f = -1999.99f;
00229     if (ob){
00230         SoftBody *sb= ob->soft; /* is supposed to be there */
00231         if(!(ob->softflag & OB_SB_GOAL)) return (0.0f);
00232         if (sb&&bp){
00233             if (bp->goal < 0.0f) return (0.0f);
00234             f = sb->mingoal + bp->goal*ABS(sb->maxgoal - sb->mingoal);
00235             f = pow(f, 4.0f);
00236             return (f);
00237         }
00238     }
00239     printf("_final_goal failed! sb or bp ==NULL \n" );
00240     return f; /*using crude but spot able values some times helps debuggin */
00241 }
00242 
00243 static float _final_mass(Object *ob,BodyPoint *bp)
00244 {
00245     if (ob){
00246         SoftBody *sb= ob->soft; /* is supposed to be there */
00247         if (sb&&bp){
00248             return(bp->mass*sb->nodemass);
00249         }
00250     }
00251     printf("_final_mass failed! sb or bp ==NULL \n" );
00252     return 1.0f;
00253 }
00254 /* helper functions for everything is animateble jow_go_for2_5 ------*/
00255 
00256 /*+++ collider caching and dicing +++*/
00257 
00258 /********************
00259 for each target object/face the axis aligned bounding box (AABB) is stored
00260 faces parallel to global axes
00261 so only simple "value" in [min,max] ckecks are used
00262 float operations still
00263 */
00264 
00265 /* just an ID here to reduce the prob for killing objects
00266 ** ob->sumohandle points to we should not kill :)
00267 */
00268 static const int CCD_SAVETY = 190561;
00269 
00270 typedef struct ccdf_minmax{
00271 float minx,miny,minz,maxx,maxy,maxz;
00272 }ccdf_minmax;
00273 
00274 
00275 
00276 typedef struct ccd_Mesh {
00277     int totvert, totface;
00278     MVert *mvert;
00279     MVert *mprevvert;
00280     MFace *mface;
00281     int savety;
00282     ccdf_minmax *mima;
00283     /* Axis Aligned Bounding Box AABB */
00284     float bbmin[3];
00285     float bbmax[3];
00286 }ccd_Mesh;
00287 
00288 
00289 
00290 
00291 static ccd_Mesh *ccd_mesh_make(Object *ob)
00292 {
00293     CollisionModifierData *cmd;
00294     ccd_Mesh *pccd_M = NULL;
00295     ccdf_minmax *mima =NULL;
00296     MFace *mface=NULL;
00297     float v[3],hull;
00298     int i;
00299 
00300     cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
00301 
00302     /* first some paranoia checks */
00303     if (!cmd) return NULL;
00304     if (!cmd->numverts || !cmd->numfaces) return NULL;
00305 
00306     pccd_M = MEM_mallocN(sizeof(ccd_Mesh),"ccd_Mesh");
00307     pccd_M->totvert = cmd->numverts;
00308     pccd_M->totface = cmd->numfaces;
00309     pccd_M->savety  = CCD_SAVETY;
00310     pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
00311     pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
00312     pccd_M->mprevvert=NULL;
00313 
00314 
00315     /* blow it up with forcefield ranges */
00316     hull = MAX2(ob->pd->pdef_sbift,ob->pd->pdef_sboft);
00317 
00318     /* alloc and copy verts*/
00319     pccd_M->mvert = MEM_dupallocN(cmd->xnew);
00320     /* note that xnew coords are already in global space, */
00321     /* determine the ortho BB */
00322     for(i=0; i < pccd_M->totvert; i++){
00323         /* evaluate limits */
00324         copy_v3_v3(v,pccd_M->mvert[i].co);
00325         pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0],v[0]-hull);
00326         pccd_M->bbmin[1] = MIN2(pccd_M->bbmin[1],v[1]-hull);
00327         pccd_M->bbmin[2] = MIN2(pccd_M->bbmin[2],v[2]-hull);
00328 
00329         pccd_M->bbmax[0] = MAX2(pccd_M->bbmax[0],v[0]+hull);
00330         pccd_M->bbmax[1] = MAX2(pccd_M->bbmax[1],v[1]+hull);
00331         pccd_M->bbmax[2] = MAX2(pccd_M->bbmax[2],v[2]+hull);
00332 
00333     }
00334     /* alloc and copy faces*/
00335     pccd_M->mface = MEM_dupallocN(cmd->mfaces);
00336 
00337     /* OBBs for idea1 */
00338     pccd_M->mima = MEM_mallocN(sizeof(ccdf_minmax)*pccd_M->totface,"ccd_Mesh_Faces_mima");
00339     mima  = pccd_M->mima;
00340     mface = pccd_M->mface;
00341 
00342 
00343     /* anyhoo we need to walk the list of faces and find OBB they live in */
00344     for(i=0; i < pccd_M->totface; i++){
00345         mima->minx=mima->miny=mima->minz=1e30f;
00346         mima->maxx=mima->maxy=mima->maxz=-1e30f;
00347 
00348         copy_v3_v3(v,pccd_M->mvert[mface->v1].co);
00349         mima->minx = MIN2(mima->minx,v[0]-hull);
00350         mima->miny = MIN2(mima->miny,v[1]-hull);
00351         mima->minz = MIN2(mima->minz,v[2]-hull);
00352         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00353         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00354         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00355 
00356         copy_v3_v3(v,pccd_M->mvert[mface->v2].co);
00357         mima->minx = MIN2(mima->minx,v[0]-hull);
00358         mima->miny = MIN2(mima->miny,v[1]-hull);
00359         mima->minz = MIN2(mima->minz,v[2]-hull);
00360         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00361         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00362         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00363 
00364         copy_v3_v3(v,pccd_M->mvert[mface->v3].co);
00365         mima->minx = MIN2(mima->minx,v[0]-hull);
00366         mima->miny = MIN2(mima->miny,v[1]-hull);
00367         mima->minz = MIN2(mima->minz,v[2]-hull);
00368         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00369         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00370         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00371 
00372         if(mface->v4){
00373             copy_v3_v3(v,pccd_M->mvert[mface->v4].co);
00374         mima->minx = MIN2(mima->minx,v[0]-hull);
00375         mima->miny = MIN2(mima->miny,v[1]-hull);
00376         mima->minz = MIN2(mima->minz,v[2]-hull);
00377         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00378         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00379         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00380         }
00381 
00382 
00383     mima++;
00384     mface++;
00385 
00386     }
00387     return pccd_M;
00388 }
00389 static void ccd_mesh_update(Object *ob,ccd_Mesh *pccd_M)
00390 {
00391     CollisionModifierData *cmd;
00392     ccdf_minmax *mima =NULL;
00393     MFace *mface=NULL;
00394     float v[3],hull;
00395     int i;
00396 
00397     cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision);
00398 
00399     /* first some paranoia checks */
00400     if (!cmd) return ;
00401     if (!cmd->numverts || !cmd->numfaces) return ;
00402 
00403     if ((pccd_M->totvert != cmd->numverts) ||
00404         (pccd_M->totface != cmd->numfaces)) return;
00405 
00406     pccd_M->bbmin[0]=pccd_M->bbmin[1]=pccd_M->bbmin[2]=1e30f;
00407     pccd_M->bbmax[0]=pccd_M->bbmax[1]=pccd_M->bbmax[2]=-1e30f;
00408 
00409 
00410     /* blow it up with forcefield ranges */
00411     hull = MAX2(ob->pd->pdef_sbift,ob->pd->pdef_sboft);
00412 
00413     /* rotate current to previous */
00414     if(pccd_M->mprevvert) MEM_freeN(pccd_M->mprevvert);
00415     pccd_M->mprevvert = pccd_M->mvert;
00416     /* alloc and copy verts*/
00417     pccd_M->mvert = MEM_dupallocN(cmd->xnew);
00418     /* note that xnew coords are already in global space, */
00419     /* determine the ortho BB */
00420     for(i=0; i < pccd_M->totvert; i++){
00421         /* evaluate limits */
00422         copy_v3_v3(v,pccd_M->mvert[i].co);
00423         pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0],v[0]-hull);
00424         pccd_M->bbmin[1] = MIN2(pccd_M->bbmin[1],v[1]-hull);
00425         pccd_M->bbmin[2] = MIN2(pccd_M->bbmin[2],v[2]-hull);
00426 
00427         pccd_M->bbmax[0] = MAX2(pccd_M->bbmax[0],v[0]+hull);
00428         pccd_M->bbmax[1] = MAX2(pccd_M->bbmax[1],v[1]+hull);
00429         pccd_M->bbmax[2] = MAX2(pccd_M->bbmax[2],v[2]+hull);
00430 
00431         /* evaluate limits */
00432         copy_v3_v3(v,pccd_M->mprevvert[i].co);
00433         pccd_M->bbmin[0] = MIN2(pccd_M->bbmin[0],v[0]-hull);
00434         pccd_M->bbmin[1] = MIN2(pccd_M->bbmin[1],v[1]-hull);
00435         pccd_M->bbmin[2] = MIN2(pccd_M->bbmin[2],v[2]-hull);
00436 
00437         pccd_M->bbmax[0] = MAX2(pccd_M->bbmax[0],v[0]+hull);
00438         pccd_M->bbmax[1] = MAX2(pccd_M->bbmax[1],v[1]+hull);
00439         pccd_M->bbmax[2] = MAX2(pccd_M->bbmax[2],v[2]+hull);
00440 
00441     }
00442 
00443     mima  = pccd_M->mima;
00444     mface = pccd_M->mface;
00445 
00446 
00447     /* anyhoo we need to walk the list of faces and find OBB they live in */
00448     for(i=0; i < pccd_M->totface; i++){
00449         mima->minx=mima->miny=mima->minz=1e30f;
00450         mima->maxx=mima->maxy=mima->maxz=-1e30f;
00451 
00452         copy_v3_v3(v,pccd_M->mvert[mface->v1].co);
00453         mima->minx = MIN2(mima->minx,v[0]-hull);
00454         mima->miny = MIN2(mima->miny,v[1]-hull);
00455         mima->minz = MIN2(mima->minz,v[2]-hull);
00456         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00457         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00458         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00459 
00460         copy_v3_v3(v,pccd_M->mvert[mface->v2].co);
00461         mima->minx = MIN2(mima->minx,v[0]-hull);
00462         mima->miny = MIN2(mima->miny,v[1]-hull);
00463         mima->minz = MIN2(mima->minz,v[2]-hull);
00464         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00465         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00466         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00467 
00468         copy_v3_v3(v,pccd_M->mvert[mface->v3].co);
00469         mima->minx = MIN2(mima->minx,v[0]-hull);
00470         mima->miny = MIN2(mima->miny,v[1]-hull);
00471         mima->minz = MIN2(mima->minz,v[2]-hull);
00472         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00473         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00474         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00475 
00476         if(mface->v4){
00477             copy_v3_v3(v,pccd_M->mvert[mface->v4].co);
00478         mima->minx = MIN2(mima->minx,v[0]-hull);
00479         mima->miny = MIN2(mima->miny,v[1]-hull);
00480         mima->minz = MIN2(mima->minz,v[2]-hull);
00481         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00482         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00483         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00484         }
00485 
00486 
00487         copy_v3_v3(v,pccd_M->mprevvert[mface->v1].co);
00488         mima->minx = MIN2(mima->minx,v[0]-hull);
00489         mima->miny = MIN2(mima->miny,v[1]-hull);
00490         mima->minz = MIN2(mima->minz,v[2]-hull);
00491         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00492         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00493         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00494 
00495         copy_v3_v3(v,pccd_M->mprevvert[mface->v2].co);
00496         mima->minx = MIN2(mima->minx,v[0]-hull);
00497         mima->miny = MIN2(mima->miny,v[1]-hull);
00498         mima->minz = MIN2(mima->minz,v[2]-hull);
00499         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00500         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00501         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00502 
00503         copy_v3_v3(v,pccd_M->mprevvert[mface->v3].co);
00504         mima->minx = MIN2(mima->minx,v[0]-hull);
00505         mima->miny = MIN2(mima->miny,v[1]-hull);
00506         mima->minz = MIN2(mima->minz,v[2]-hull);
00507         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00508         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00509         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00510 
00511         if(mface->v4){
00512             copy_v3_v3(v,pccd_M->mprevvert[mface->v4].co);
00513         mima->minx = MIN2(mima->minx,v[0]-hull);
00514         mima->miny = MIN2(mima->miny,v[1]-hull);
00515         mima->minz = MIN2(mima->minz,v[2]-hull);
00516         mima->maxx = MAX2(mima->maxx,v[0]+hull);
00517         mima->maxy = MAX2(mima->maxy,v[1]+hull);
00518         mima->maxz = MAX2(mima->maxz,v[2]+hull);
00519         }
00520 
00521 
00522     mima++;
00523     mface++;
00524 
00525     }
00526     return ;
00527 }
00528 
00529 static void ccd_mesh_free(ccd_Mesh *ccdm)
00530 {
00531     if(ccdm && (ccdm->savety == CCD_SAVETY )){ /*make sure we're not nuking objects we don't know*/
00532         MEM_freeN(ccdm->mface);
00533         MEM_freeN(ccdm->mvert);
00534         if (ccdm->mprevvert) MEM_freeN(ccdm->mprevvert);
00535         MEM_freeN(ccdm->mima);
00536         MEM_freeN(ccdm);
00537         ccdm = NULL;
00538     }
00539 }
00540 
00541 static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash)
00542 {
00543     Base *base= scene->base.first;
00544     Object *ob;
00545 
00546     if (!hash) return;
00547     while (base) {
00548         /*Only proceed for mesh object in same layer */
00549         if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
00550             ob= base->object;
00551             if((vertexowner) && (ob == vertexowner)) {
00552                 /* if vertexowner is given  we don't want to check collision with owner object */
00553                 base = base->next;
00554                 continue;
00555             }
00556 
00557             /*+++ only with deflecting set */
00558             if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == NULL) {
00559                 ccd_Mesh *ccdmesh = ccd_mesh_make(ob);
00560                 BLI_ghash_insert(hash, ob, ccdmesh);
00561             }/*--- only with deflecting set */
00562 
00563         }/* mesh && layer*/
00564         base = base->next;
00565     } /* while (base) */
00566 }
00567 
00568 static void ccd_update_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash)
00569 {
00570     Base *base= scene->base.first;
00571     Object *ob;
00572 
00573     if ((!hash) || (!vertexowner)) return;
00574     while (base) {
00575         /*Only proceed for mesh object in same layer */
00576         if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
00577             ob= base->object;
00578             if(ob == vertexowner){
00579                 /* if vertexowner is given  we don't want to check collision with owner object */
00580                 base = base->next;
00581                 continue;
00582             }
00583 
00584             /*+++ only with deflecting set */
00585             if(ob->pd && ob->pd->deflect) {
00586                 ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash,ob);
00587                 if (ccdmesh)
00588                     ccd_mesh_update(ob,ccdmesh);
00589             }/*--- only with deflecting set */
00590 
00591         }/* mesh && layer*/
00592         base = base->next;
00593     } /* while (base) */
00594 }
00595 
00596 
00597 
00598 
00599 /*--- collider caching and dicing ---*/
00600 
00601 
00602 static int count_mesh_quads(Mesh *me)
00603 {
00604     int a,result = 0;
00605     MFace *mface= me->mface;
00606 
00607     if(mface) {
00608         for(a=me->totface; a>0; a--, mface++) {
00609             if(mface->v4) result++;
00610         }
00611     }
00612     return result;
00613 }
00614 
00615 static void add_mesh_quad_diag_springs(Object *ob)
00616 {
00617     Mesh *me= ob->data;
00618     MFace *mface= me->mface;
00619     /*BodyPoint *bp;*/ /*UNUSED*/
00620     BodySpring *bs, *bs_new;
00621     int a ;
00622 
00623     if (ob->soft){
00624         int nofquads;
00625         //float s_shear = ob->soft->shearstiff*ob->soft->shearstiff;
00626 
00627         nofquads = count_mesh_quads(me);
00628         if (nofquads) {
00629             /* resize spring-array to hold additional quad springs */
00630             bs_new= MEM_callocN( (ob->soft->totspring + nofquads *2 )*sizeof(BodySpring), "bodyspring");
00631             memcpy(bs_new,ob->soft->bspring,(ob->soft->totspring )*sizeof(BodySpring));
00632 
00633             if(ob->soft->bspring)
00634                 MEM_freeN(ob->soft->bspring); /* do this before reassigning the pointer  or have a 1st class memory leak */
00635             ob->soft->bspring = bs_new;
00636 
00637             /* fill the tail */
00638             a = 0;
00639             bs = bs_new+ob->soft->totspring;
00640             /*bp= ob->soft->bpoint; */ /*UNUSED*/
00641             if(mface ) {
00642                 for(a=me->totface; a>0; a--, mface++) {
00643                     if(mface->v4) {
00644                         bs->v1= mface->v1;
00645                         bs->v2= mface->v3;
00646                         bs->springtype   =SB_STIFFQUAD;
00647                         bs++;
00648                         bs->v1= mface->v2;
00649                         bs->v2= mface->v4;
00650                         bs->springtype   =SB_STIFFQUAD;
00651                         bs++;
00652 
00653                     }
00654                 }
00655             }
00656 
00657             /* now we can announce new springs */
00658             ob->soft->totspring += nofquads *2;
00659         }
00660     }
00661 }
00662 
00663 static void add_2nd_order_roller(Object *ob,float UNUSED(stiffness), int *counter, int addsprings)
00664 {
00665     /*assume we have a softbody*/
00666     SoftBody *sb= ob->soft; /* is supposed to be there */
00667     BodyPoint *bp,*bpo;
00668     BodySpring *bs,*bs2,*bs3= NULL;
00669     int a,b,c,notthis= 0,v0;
00670     if (!sb->bspring){return;} /* we are 2nd order here so 1rst should have been build :) */
00671     /* first run counting  second run adding */
00672     *counter = 0;
00673     if (addsprings) bs3 = ob->soft->bspring+ob->soft->totspring;
00674     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
00675         /*scan for neighborhood*/
00676         bpo = NULL;
00677         v0  = (sb->totpoint-a);
00678         for(b=bp->nofsprings;b>0;b--){
00679             bs = sb->bspring + bp->springs[b-1];
00680             /*nasty thing here that springs have two ends
00681             so here we have to make sure we examine the other */
00682             if (v0 == bs->v1){
00683                 bpo =sb->bpoint+bs->v2;
00684                 notthis = bs->v2;
00685             }
00686             else {
00687             if (v0 == bs->v2){
00688                 bpo =sb->bpoint+bs->v1;
00689                 notthis = bs->v1;
00690             }
00691             else {printf("oops we should not get here -  add_2nd_order_springs");}
00692             }
00693             if (bpo){/* so now we have a 2nd order humpdidump */
00694                 for(c=bpo->nofsprings;c>0;c--){
00695                     bs2 = sb->bspring + bpo->springs[c-1];
00696                     if ((bs2->v1 != notthis)  && (bs2->v1 > v0)){
00697                         (*counter)++;/*hit */
00698                         if (addsprings){
00699                             bs3->v1= v0;
00700                             bs3->v2= bs2->v1;
00701                             bs3->springtype   =SB_BEND;
00702                             bs3++;
00703                         }
00704                     }
00705                     if ((bs2->v2 !=notthis)&&(bs2->v2 > v0)){
00706                     (*counter)++;/*hit */
00707                         if (addsprings){
00708                             bs3->v1= v0;
00709                             bs3->v2= bs2->v2;
00710                             bs3->springtype   =SB_BEND;
00711                             bs3++;
00712                         }
00713 
00714                     }
00715                 }
00716 
00717             }
00718 
00719         }
00720         /*scan for neighborhood done*/
00721     }
00722 }
00723 
00724 
00725 static void add_2nd_order_springs(Object *ob,float stiffness)
00726 {
00727     int counter = 0;
00728     BodySpring *bs_new;
00729     stiffness *=stiffness;
00730 
00731     add_2nd_order_roller(ob,stiffness,&counter,0); /* counting */
00732     if (counter) {
00733         /* resize spring-array to hold additional springs */
00734         bs_new= MEM_callocN( (ob->soft->totspring + counter )*sizeof(BodySpring), "bodyspring");
00735         memcpy(bs_new,ob->soft->bspring,(ob->soft->totspring )*sizeof(BodySpring));
00736 
00737         if(ob->soft->bspring)
00738             MEM_freeN(ob->soft->bspring);
00739         ob->soft->bspring = bs_new;
00740 
00741         add_2nd_order_roller(ob,stiffness,&counter,1); /* adding */
00742         ob->soft->totspring +=counter ;
00743     }
00744 }
00745 
00746 static void add_bp_springlist(BodyPoint *bp,int springID)
00747 {
00748     int *newlist;
00749 
00750     if (bp->springs == NULL) {
00751         bp->springs = MEM_callocN( sizeof(int), "bpsprings");
00752         bp->springs[0] = springID;
00753         bp->nofsprings = 1;
00754     }
00755     else {
00756         bp->nofsprings++;
00757         newlist = MEM_callocN(bp->nofsprings * sizeof(int), "bpsprings");
00758         memcpy(newlist,bp->springs,(bp->nofsprings-1)* sizeof(int));
00759         MEM_freeN(bp->springs);
00760         bp->springs = newlist;
00761         bp->springs[bp->nofsprings-1] = springID;
00762     }
00763 }
00764 
00765 /* do this once when sb is build
00766 it is O(N^2) so scanning for springs every iteration is too expensive
00767 */
00768 static void build_bps_springlist(Object *ob)
00769 {
00770     SoftBody *sb= ob->soft; /* is supposed to be there */
00771     BodyPoint *bp;
00772     BodySpring *bs;
00773     int a,b;
00774 
00775     if (sb==NULL) return; /* paranoya check */
00776 
00777     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
00778         /* throw away old list */
00779         if (bp->springs) {
00780             MEM_freeN(bp->springs);
00781             bp->springs=NULL;
00782         }
00783         /* scan for attached inner springs */
00784         for(b=sb->totspring, bs= sb->bspring; b>0; b--, bs++) {
00785             if (( (sb->totpoint-a) == bs->v1) ){
00786                 add_bp_springlist(bp,sb->totspring -b);
00787             }
00788             if (( (sb->totpoint-a) == bs->v2) ){
00789                 add_bp_springlist(bp,sb->totspring -b);
00790             }
00791         }/*for springs*/
00792     }/*for bp*/
00793 }
00794 
00795 static void calculate_collision_balls(Object *ob)
00796 {
00797     SoftBody *sb= ob->soft; /* is supposed to be there */
00798     BodyPoint *bp;
00799     BodySpring *bs;
00800     int a,b,akku_count;
00801     float min,max,akku;
00802 
00803     if (sb==NULL) return; /* paranoya check */
00804 
00805     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
00806         bp->colball=0;
00807         akku =0.0f;
00808         akku_count=0;
00809         min = 1e22f;
00810         max = -1e22f;
00811         /* first estimation based on attached */
00812         for(b=bp->nofsprings;b>0;b--){
00813             bs = sb->bspring + bp->springs[b-1];
00814             if (bs->springtype == SB_EDGE){
00815             akku += bs->len;
00816             akku_count++,
00817             min = MIN2(bs->len,min);
00818             max = MAX2(bs->len,max);
00819             }
00820         }
00821 
00822         if (akku_count > 0) {
00823             if (sb->sbc_mode == SBC_MODE_MANUAL){
00824                 bp->colball=sb->colball;
00825             }
00826             if (sb->sbc_mode == SBC_MODE_AVG){
00827                 bp->colball = akku/(float)akku_count*sb->colball;
00828             }
00829             if (sb->sbc_mode == SBC_MODE_MIN){
00830                 bp->colball=min*sb->colball;
00831             }
00832             if (sb->sbc_mode == SBC_MODE_MAX){
00833                 bp->colball=max*sb->colball;
00834             }
00835             if (sb->sbc_mode == SBC_MODE_AVGMINMAX){
00836                 bp->colball = (min + max)/2.0f*sb->colball;
00837             }
00838         }
00839         else bp->colball=0;
00840     }/*for bp*/
00841 }
00842 
00843 
00844 /* creates new softbody if didn't exist yet, makes new points and springs arrays */
00845 static void renew_softbody(Scene *scene, Object *ob, int totpoint, int totspring)
00846 {
00847     SoftBody *sb;
00848     int i;
00849     short softflag;
00850     if(ob->soft==NULL) ob->soft= sbNew(scene);
00851     else free_softbody_intern(ob->soft);
00852     sb= ob->soft;
00853     softflag=ob->softflag;
00854 
00855     if(totpoint) {
00856         sb->totpoint= totpoint;
00857         sb->totspring= totspring;
00858 
00859         sb->bpoint= MEM_mallocN( totpoint*sizeof(BodyPoint), "bodypoint");
00860         if(totspring)
00861             sb->bspring= MEM_mallocN( totspring*sizeof(BodySpring), "bodyspring");
00862 
00863             /* initialise BodyPoint array */
00864         for (i=0; i<totpoint; i++) {
00865             BodyPoint *bp = &sb->bpoint[i];
00866 
00867 
00868             /* hum as far as i see this is overridden by _final_goal() now jow_go_for2_5 */
00869             /* sadly breaks compatibility with older versions */
00870             /* but makes goals behave the same for meshes, lattices and curves */
00871             if(softflag & OB_SB_GOAL) {
00872                 bp->goal= sb->defgoal;
00873             }
00874             else {
00875                 bp->goal= 0.0f;
00876                 /* so this will definily be below SOFTGOALSNAP */
00877             }
00878 
00879             bp->nofsprings= 0;
00880             bp->springs= NULL;
00881             bp->choke = 0.0f;
00882             bp->choke2 = 0.0f;
00883             bp->frozen = 1.0f;
00884             bp->colball = 0.0f;
00885             bp->loc_flag = 0;
00886             bp->springweight = 1.0f;
00887             bp->mass = 1.0f;
00888         }
00889     }
00890 }
00891 
00892 static void free_softbody_baked(SoftBody *sb)
00893 {
00894     SBVertex *key;
00895     int k;
00896 
00897     for(k=0; k<sb->totkey; k++) {
00898         key= *(sb->keys + k);
00899         if(key) MEM_freeN(key);
00900     }
00901     if(sb->keys) MEM_freeN(sb->keys);
00902 
00903     sb->keys= NULL;
00904     sb->totkey= 0;
00905 }
00906 static void free_scratch(SoftBody *sb)
00907 {
00908     if(sb->scratch){
00909         /* todo make sure everything is cleaned up nicly */
00910         if (sb->scratch->colliderhash){
00911             BLI_ghash_free(sb->scratch->colliderhash, NULL,
00912                     (GHashValFreeFP) ccd_mesh_free); /*this hoepfully will free all caches*/
00913             sb->scratch->colliderhash = NULL;
00914         }
00915         if (sb->scratch->bodyface){
00916             MEM_freeN(sb->scratch->bodyface);
00917         }
00918         if (sb->scratch->Ref.ivert){
00919             MEM_freeN(sb->scratch->Ref.ivert);
00920         }
00921         MEM_freeN(sb->scratch);
00922         sb->scratch = NULL;
00923     }
00924 
00925 }
00926 
00927 /* only frees internal data */
00928 static void free_softbody_intern(SoftBody *sb)
00929 {
00930     if(sb) {
00931         int a;
00932         BodyPoint *bp;
00933 
00934         if(sb->bpoint){
00935             for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
00936                 /* free spring list */
00937                 if (bp->springs != NULL) {
00938                     MEM_freeN(bp->springs);
00939                 }
00940             }
00941             MEM_freeN(sb->bpoint);
00942         }
00943 
00944         if(sb->bspring) MEM_freeN(sb->bspring);
00945 
00946         sb->totpoint= sb->totspring= 0;
00947         sb->bpoint= NULL;
00948         sb->bspring= NULL;
00949 
00950         free_scratch(sb);
00951         free_softbody_baked(sb);
00952     }
00953 }
00954 
00955 
00956 /* ************ dynamics ********** */
00957 
00958 /* the most general (micro physics correct) way to do collision
00959 ** (only needs the current particle position)
00960 **
00961 ** it actually checks if the particle intrudes a short range force field generated
00962 ** by the faces of the target object and returns a force to drive the particel out
00963 ** the strenght of the field grows exponetially if the particle is on the 'wrong' side of the face
00964 ** 'wrong' side : projection to the face normal is negative (all referred to a vertex in the face)
00965 **
00966 ** flaw of this: 'fast' particles as well as 'fast' colliding faces
00967 ** give a 'tunnel' effect such that the particle passes through the force field
00968 ** without ever 'seeing' it
00969 ** this is fully compliant to heisenberg: h >= fuzzy(location) * fuzzy(time)
00970 ** besides our h is way larger than in QM because forces propagate way slower here
00971 ** we have to deal with fuzzy(time) in the range of 1/25 seconds (typical frame rate)
00972 ** yup collision targets are not known here any better
00973 ** and 1/25 second is looong compared to real collision events
00974 ** Q: why not use 'simple' collision here like bouncing back a particle
00975 **   --> reverting is velocity on the face normal
00976 ** A: because our particles are not alone here
00977 **    and need to tell their neighbours exactly what happens via spring forces
00978 ** unless sbObjectStep( .. ) is called on sub frame timing level
00979 ** BTW that also questions the use of a 'implicit' solvers on softbodies
00980 ** since that would only valid for 'slow' moving collision targets and dito particles
00981 */
00982 
00983 /* aye this belongs to arith.c */
00984 static void Vec3PlusStVec(float *v, float s, float *v1)
00985 {
00986     v[0] += s*v1[0];
00987     v[1] += s*v1[1];
00988     v[2] += s*v1[2];
00989 }
00990 
00991 /* +++ dependancy information functions*/
00992 
00993 static int are_there_deflectors(Scene *scene, unsigned int layer)
00994 {
00995     Base *base;
00996 
00997     for(base = scene->base.first; base; base= base->next) {
00998         if( (base->lay & layer) && base->object->pd) {
00999             if(base->object->pd->deflect)
01000                 return 1;
01001         }
01002     }
01003     return 0;
01004 }
01005 
01006 static int query_external_colliders(Scene *scene, Object *me)
01007 {
01008     return(are_there_deflectors(scene, me->lay));
01009 }
01010 /* --- dependancy information functions*/
01011 
01012 
01013 /* +++ the aabb "force" section*/
01014 static int sb_detect_aabb_collisionCached(  float UNUSED(force[3]), unsigned int UNUSED(par_layer),struct Object *vertexowner,float UNUSED(time))
01015 {
01016     Object *ob;
01017     SoftBody *sb=vertexowner->soft;
01018     GHash *hash;
01019     GHashIterator *ihash;
01020     float  aabbmin[3],aabbmax[3];
01021     int deflected=0;
01022 #if 0
01023     int a;
01024 #endif
01025 
01026     if ((sb == NULL) || (sb->scratch ==NULL)) return 0;
01027     copy_v3_v3(aabbmin,sb->scratch->aabbmin);
01028     copy_v3_v3(aabbmax,sb->scratch->aabbmax);
01029 
01030     hash  = vertexowner->soft->scratch->colliderhash;
01031     ihash = BLI_ghashIterator_new(hash);
01032     while (!BLI_ghashIterator_isDone(ihash) ) {
01033 
01034         ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
01035         ob             = BLI_ghashIterator_getKey   (ihash);
01036             /* only with deflecting set */
01037             if(ob->pd && ob->pd->deflect) {
01038 #if 0           /* UNUSED */
01039                 MFace *mface= NULL;
01040                 MVert *mvert= NULL;
01041                 MVert *mprevvert= NULL;
01042                 ccdf_minmax *mima= NULL;
01043 #endif
01044                 if(ccdm){
01045 #if 0               /* UNUSED */
01046                     mface= ccdm->mface;
01047                     mvert= ccdm->mvert;
01048                     mprevvert= ccdm->mprevvert;
01049                     mima= ccdm->mima;
01050                     a = ccdm->totface;
01051 #endif
01052                     if ((aabbmax[0] < ccdm->bbmin[0]) ||
01053                         (aabbmax[1] < ccdm->bbmin[1]) ||
01054                         (aabbmax[2] < ccdm->bbmin[2]) ||
01055                         (aabbmin[0] > ccdm->bbmax[0]) ||
01056                         (aabbmin[1] > ccdm->bbmax[1]) ||
01057                         (aabbmin[2] > ccdm->bbmax[2]) ) {
01058                         /* boxes dont intersect */
01059                         BLI_ghashIterator_step(ihash);
01060                         continue;
01061                     }
01062 
01063                     /* so now we have the 2 boxes overlapping */
01064                     /* forces actually not used */
01065                     deflected = 2;
01066 
01067                 }
01068                 else{
01069                     /*aye that should be cached*/
01070                     printf("missing cache error \n");
01071                     BLI_ghashIterator_step(ihash);
01072                     continue;
01073                 }
01074             } /* if(ob->pd && ob->pd->deflect) */
01075             BLI_ghashIterator_step(ihash);
01076     } /* while () */
01077     BLI_ghashIterator_free(ihash);
01078     return deflected;
01079 }
01080 /* --- the aabb section*/
01081 
01082 
01083 /* +++ the face external section*/
01084 static int sb_detect_face_pointCached(float face_v1[3],float face_v2[3],float face_v3[3],float *damp,
01085                                    float force[3], unsigned int UNUSED(par_layer),struct Object *vertexowner,float time)
01086                                    {
01087     Object *ob;
01088     GHash *hash;
01089     GHashIterator *ihash;
01090     float nv1[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3],aabbmax[3];
01091     float facedist,outerfacethickness,tune = 10.f;
01092     int a, deflected=0;
01093 
01094     aabbmin[0] = MIN3(face_v1[0],face_v2[0],face_v3[0]);
01095     aabbmin[1] = MIN3(face_v1[1],face_v2[1],face_v3[1]);
01096     aabbmin[2] = MIN3(face_v1[2],face_v2[2],face_v3[2]);
01097     aabbmax[0] = MAX3(face_v1[0],face_v2[0],face_v3[0]);
01098     aabbmax[1] = MAX3(face_v1[1],face_v2[1],face_v3[1]);
01099     aabbmax[2] = MAX3(face_v1[2],face_v2[2],face_v3[2]);
01100 
01101     /* calculate face normal once again SIGH */
01102     sub_v3_v3v3(edge1, face_v1, face_v2);
01103     sub_v3_v3v3(edge2, face_v3, face_v2);
01104     cross_v3_v3v3(d_nvect, edge2, edge1);
01105     normalize_v3(d_nvect);
01106 
01107 
01108     hash  = vertexowner->soft->scratch->colliderhash;
01109     ihash = BLI_ghashIterator_new(hash);
01110     while (!BLI_ghashIterator_isDone(ihash) ) {
01111 
01112         ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
01113         ob             = BLI_ghashIterator_getKey   (ihash);
01114             /* only with deflecting set */
01115             if(ob->pd && ob->pd->deflect) {
01116                 MVert *mvert= NULL;
01117                 MVert *mprevvert= NULL;
01118                 if(ccdm){
01119                     mvert= ccdm->mvert;
01120                     a    = ccdm->totvert;
01121                     mprevvert= ccdm->mprevvert;
01122                     outerfacethickness =ob->pd->pdef_sboft;
01123                     if ((aabbmax[0] < ccdm->bbmin[0]) ||
01124                         (aabbmax[1] < ccdm->bbmin[1]) ||
01125                         (aabbmax[2] < ccdm->bbmin[2]) ||
01126                         (aabbmin[0] > ccdm->bbmax[0]) ||
01127                         (aabbmin[1] > ccdm->bbmax[1]) ||
01128                         (aabbmin[2] > ccdm->bbmax[2]) ) {
01129                         /* boxes dont intersect */
01130                         BLI_ghashIterator_step(ihash);
01131                         continue;
01132                     }
01133 
01134                 }
01135                 else{
01136                     /*aye that should be cached*/
01137                     printf("missing cache error \n");
01138                     BLI_ghashIterator_step(ihash);
01139                     continue;
01140                 }
01141 
01142 
01143                 /* use mesh*/
01144                 if (mvert) {
01145                     while(a){
01146                         copy_v3_v3(nv1,mvert[a-1].co);
01147                         if(mprevvert){
01148                             mul_v3_fl(nv1,time);
01149                             Vec3PlusStVec(nv1,(1.0f-time),mprevvert[a-1].co);
01150                         }
01151                         /* origin to face_v2*/
01152                         sub_v3_v3(nv1, face_v2);
01153                         facedist = dot_v3v3(nv1,d_nvect);
01154                         if (ABS(facedist)<outerfacethickness){
01155                             if (isect_point_tri_prism_v3(nv1, face_v1,face_v2,face_v3) ){
01156                                 float df;
01157                                 if (facedist > 0){
01158                                     df = (outerfacethickness-facedist)/outerfacethickness;
01159                                 }
01160                                 else {
01161                                     df = (outerfacethickness+facedist)/outerfacethickness;
01162                                 }
01163 
01164                                 *damp=df*tune*ob->pd->pdef_sbdamp;
01165 
01166                                 df = 0.01f*exp(- 100.0f*df);
01167                                 Vec3PlusStVec(force,-df,d_nvect);
01168                                 deflected = 3;
01169                             }
01170                         }
01171                         a--;
01172                     }/* while(a)*/
01173                 } /* if (mvert) */
01174             } /* if(ob->pd && ob->pd->deflect) */
01175             BLI_ghashIterator_step(ihash);
01176     } /* while () */
01177     BLI_ghashIterator_free(ihash);
01178     return deflected;
01179 }
01180 
01181 
01182 static int sb_detect_face_collisionCached(float face_v1[3],float face_v2[3],float face_v3[3],float *damp,
01183                                    float force[3], unsigned int UNUSED(par_layer),struct Object *vertexowner,float time)
01184 {
01185     Object *ob;
01186     GHash *hash;
01187     GHashIterator *ihash;
01188     float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3],aabbmax[3];
01189     float t,tune = 10.0f;
01190     int a, deflected=0;
01191 
01192     aabbmin[0] = MIN3(face_v1[0],face_v2[0],face_v3[0]);
01193     aabbmin[1] = MIN3(face_v1[1],face_v2[1],face_v3[1]);
01194     aabbmin[2] = MIN3(face_v1[2],face_v2[2],face_v3[2]);
01195     aabbmax[0] = MAX3(face_v1[0],face_v2[0],face_v3[0]);
01196     aabbmax[1] = MAX3(face_v1[1],face_v2[1],face_v3[1]);
01197     aabbmax[2] = MAX3(face_v1[2],face_v2[2],face_v3[2]);
01198 
01199     hash  = vertexowner->soft->scratch->colliderhash;
01200     ihash = BLI_ghashIterator_new(hash);
01201     while (!BLI_ghashIterator_isDone(ihash) ) {
01202 
01203         ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
01204         ob             = BLI_ghashIterator_getKey   (ihash);
01205             /* only with deflecting set */
01206             if(ob->pd && ob->pd->deflect) {
01207                 MFace *mface= NULL;
01208                 MVert *mvert= NULL;
01209                 MVert *mprevvert= NULL;
01210                 ccdf_minmax *mima= NULL;
01211                 if(ccdm){
01212                     mface= ccdm->mface;
01213                     mvert= ccdm->mvert;
01214                     mprevvert= ccdm->mprevvert;
01215                     mima= ccdm->mima;
01216                     a = ccdm->totface;
01217 
01218                     if ((aabbmax[0] < ccdm->bbmin[0]) ||
01219                         (aabbmax[1] < ccdm->bbmin[1]) ||
01220                         (aabbmax[2] < ccdm->bbmin[2]) ||
01221                         (aabbmin[0] > ccdm->bbmax[0]) ||
01222                         (aabbmin[1] > ccdm->bbmax[1]) ||
01223                         (aabbmin[2] > ccdm->bbmax[2]) ) {
01224                         /* boxes dont intersect */
01225                         BLI_ghashIterator_step(ihash);
01226                         continue;
01227                     }
01228 
01229                 }
01230                 else{
01231                     /*aye that should be cached*/
01232                     printf("missing cache error \n");
01233                     BLI_ghashIterator_step(ihash);
01234                     continue;
01235                 }
01236 
01237 
01238                 /* use mesh*/
01239                 while (a--) {
01240                     if (
01241                         (aabbmax[0] < mima->minx) ||
01242                         (aabbmin[0] > mima->maxx) ||
01243                         (aabbmax[1] < mima->miny) ||
01244                         (aabbmin[1] > mima->maxy) ||
01245                         (aabbmax[2] < mima->minz) ||
01246                         (aabbmin[2] > mima->maxz)
01247                         ) {
01248                         mface++;
01249                         mima++;
01250                         continue;
01251                     }
01252 
01253 
01254                     if (mvert){
01255 
01256                         copy_v3_v3(nv1,mvert[mface->v1].co);
01257                         copy_v3_v3(nv2,mvert[mface->v2].co);
01258                         copy_v3_v3(nv3,mvert[mface->v3].co);
01259                         if (mface->v4){
01260                             copy_v3_v3(nv4,mvert[mface->v4].co);
01261                         }
01262                         if (mprevvert){
01263                             mul_v3_fl(nv1,time);
01264                             Vec3PlusStVec(nv1,(1.0f-time),mprevvert[mface->v1].co);
01265 
01266                             mul_v3_fl(nv2,time);
01267                             Vec3PlusStVec(nv2,(1.0f-time),mprevvert[mface->v2].co);
01268 
01269                             mul_v3_fl(nv3,time);
01270                             Vec3PlusStVec(nv3,(1.0f-time),mprevvert[mface->v3].co);
01271 
01272                             if (mface->v4){
01273                                 mul_v3_fl(nv4,time);
01274                                 Vec3PlusStVec(nv4,(1.0f-time),mprevvert[mface->v4].co);
01275                             }
01276                         }
01277                     }
01278 
01279                     /* switch origin to be nv2*/
01280                     sub_v3_v3v3(edge1, nv1, nv2);
01281                     sub_v3_v3v3(edge2, nv3, nv2);
01282                     cross_v3_v3v3(d_nvect, edge2, edge1);
01283                     normalize_v3(d_nvect);
01284                     if (
01285                         isect_line_tri_v3(nv1, nv2, face_v1, face_v2, face_v3, &t, NULL) ||
01286                         isect_line_tri_v3(nv2, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
01287                         isect_line_tri_v3(nv3, nv1, face_v1, face_v2, face_v3, &t, NULL) ){
01288                         Vec3PlusStVec(force,-0.5f,d_nvect);
01289                         *damp=tune*ob->pd->pdef_sbdamp;
01290                         deflected = 2;
01291                     }
01292                     if (mface->v4){ /* quad */
01293                         /* switch origin to be nv4 */
01294                         sub_v3_v3v3(edge1, nv3, nv4);
01295                         sub_v3_v3v3(edge2, nv1, nv4);
01296                         cross_v3_v3v3(d_nvect, edge2, edge1);
01297                         normalize_v3(d_nvect);
01298                         if (
01299                             /* isect_line_tri_v3(nv1, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
01300                              we did that edge already */
01301                             isect_line_tri_v3(nv3, nv4, face_v1, face_v2, face_v3, &t, NULL) ||
01302                             isect_line_tri_v3(nv4, nv1, face_v1, face_v2, face_v3, &t, NULL) ){
01303                             Vec3PlusStVec(force,-0.5f,d_nvect);
01304                             *damp=tune*ob->pd->pdef_sbdamp;
01305                             deflected = 2;
01306                         }
01307                     }
01308                     mface++;
01309                     mima++;
01310                 }/* while a */
01311             } /* if(ob->pd && ob->pd->deflect) */
01312             BLI_ghashIterator_step(ihash);
01313     } /* while () */
01314     BLI_ghashIterator_free(ihash);
01315     return deflected;
01316 }
01317 
01318 
01319 
01320 static void scan_for_ext_face_forces(Object *ob,float timenow)
01321 {
01322     SoftBody *sb = ob->soft;
01323     BodyFace *bf;
01324     int a;
01325     float damp=0.0f,choke=1.0f;
01326     float tune = -10.0f;
01327     float feedback[3];
01328 
01329     if (sb && sb->scratch->totface){
01330 
01331 
01332         bf = sb->scratch->bodyface;
01333         for(a=0; a<sb->scratch->totface; a++, bf++) {
01334             bf->ext_force[0]=bf->ext_force[1]=bf->ext_force[2]=0.0f;
01335 /*+++edges intruding*/
01336             bf->flag &= ~BFF_INTERSECT;
01337             feedback[0]=feedback[1]=feedback[2]=0.0f;
01338             if (sb_detect_face_collisionCached(sb->bpoint[bf->v1].pos,sb->bpoint[bf->v2].pos, sb->bpoint[bf->v3].pos,
01339                 &damp,  feedback, ob->lay ,ob , timenow)){
01340                 Vec3PlusStVec(sb->bpoint[bf->v1].force,tune,feedback);
01341                 Vec3PlusStVec(sb->bpoint[bf->v2].force,tune,feedback);
01342                 Vec3PlusStVec(sb->bpoint[bf->v3].force,tune,feedback);
01343 //              Vec3PlusStVec(bf->ext_force,tune,feedback);
01344                 bf->flag |= BFF_INTERSECT;
01345                 choke = MIN2(MAX2(damp,choke),1.0f);
01346             }
01347 
01348             feedback[0]=feedback[1]=feedback[2]=0.0f;
01349             if ((bf->v4) && (sb_detect_face_collisionCached(sb->bpoint[bf->v1].pos,sb->bpoint[bf->v3].pos, sb->bpoint[bf->v4].pos,
01350                 &damp,  feedback, ob->lay ,ob , timenow))){
01351                 Vec3PlusStVec(sb->bpoint[bf->v1].force,tune,feedback);
01352                 Vec3PlusStVec(sb->bpoint[bf->v3].force,tune,feedback);
01353                 Vec3PlusStVec(sb->bpoint[bf->v4].force,tune,feedback);
01354 //              Vec3PlusStVec(bf->ext_force,tune,feedback);
01355                 bf->flag |= BFF_INTERSECT;
01356                 choke = MIN2(MAX2(damp,choke),1.0f);
01357             }
01358 /*---edges intruding*/
01359 
01360 /*+++ close vertices*/
01361             if  (( bf->flag & BFF_INTERSECT)==0){
01362                 bf->flag &= ~BFF_CLOSEVERT;
01363                 tune = -1.0f;
01364                 feedback[0]=feedback[1]=feedback[2]=0.0f;
01365                 if (sb_detect_face_pointCached(sb->bpoint[bf->v1].pos,sb->bpoint[bf->v2].pos, sb->bpoint[bf->v3].pos,
01366                     &damp,  feedback, ob->lay ,ob , timenow)){
01367                 Vec3PlusStVec(sb->bpoint[bf->v1].force,tune,feedback);
01368                 Vec3PlusStVec(sb->bpoint[bf->v2].force,tune,feedback);
01369                 Vec3PlusStVec(sb->bpoint[bf->v3].force,tune,feedback);
01370 //                      Vec3PlusStVec(bf->ext_force,tune,feedback);
01371                         bf->flag |= BFF_CLOSEVERT;
01372                         choke = MIN2(MAX2(damp,choke),1.0f);
01373                 }
01374 
01375                 feedback[0]=feedback[1]=feedback[2]=0.0f;
01376                 if ((bf->v4) && (sb_detect_face_pointCached(sb->bpoint[bf->v1].pos,sb->bpoint[bf->v3].pos, sb->bpoint[bf->v4].pos,
01377                     &damp,  feedback, ob->lay ,ob , timenow))){
01378                 Vec3PlusStVec(sb->bpoint[bf->v1].force,tune,feedback);
01379                 Vec3PlusStVec(sb->bpoint[bf->v3].force,tune,feedback);
01380                 Vec3PlusStVec(sb->bpoint[bf->v4].force,tune,feedback);
01381 //                      Vec3PlusStVec(bf->ext_force,tune,feedback);
01382                         bf->flag |= BFF_CLOSEVERT;
01383                         choke = MIN2(MAX2(damp,choke),1.0f);
01384                 }
01385             }
01386 /*--- close vertices*/
01387         }
01388         bf = sb->scratch->bodyface;
01389         for(a=0; a<sb->scratch->totface; a++, bf++) {
01390             if (( bf->flag & BFF_INTERSECT) || ( bf->flag & BFF_CLOSEVERT))
01391             {
01392                 sb->bpoint[bf->v1].choke2=MAX2(sb->bpoint[bf->v1].choke2,choke);
01393                 sb->bpoint[bf->v2].choke2=MAX2(sb->bpoint[bf->v2].choke2,choke);
01394                 sb->bpoint[bf->v3].choke2=MAX2(sb->bpoint[bf->v3].choke2,choke);
01395                 if (bf->v4){
01396                 sb->bpoint[bf->v2].choke2=MAX2(sb->bpoint[bf->v2].choke2,choke);
01397                 }
01398             }
01399         }
01400     }
01401 }
01402 
01403 /*  --- the face external section*/
01404 
01405 
01406 /* +++ the spring external section*/
01407 
01408 static int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp,
01409                                    float force[3], unsigned int UNUSED(par_layer),struct Object *vertexowner,float time)
01410 {
01411     Object *ob;
01412     GHash *hash;
01413     GHashIterator *ihash;
01414     float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3],aabbmax[3];
01415     float t,el;
01416     int a, deflected=0;
01417 
01418     aabbmin[0] = MIN2(edge_v1[0],edge_v2[0]);
01419     aabbmin[1] = MIN2(edge_v1[1],edge_v2[1]);
01420     aabbmin[2] = MIN2(edge_v1[2],edge_v2[2]);
01421     aabbmax[0] = MAX2(edge_v1[0],edge_v2[0]);
01422     aabbmax[1] = MAX2(edge_v1[1],edge_v2[1]);
01423     aabbmax[2] = MAX2(edge_v1[2],edge_v2[2]);
01424 
01425     el = len_v3v3(edge_v1,edge_v2);
01426 
01427     hash  = vertexowner->soft->scratch->colliderhash;
01428     ihash = BLI_ghashIterator_new(hash);
01429     while (!BLI_ghashIterator_isDone(ihash) ) {
01430 
01431         ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
01432         ob             = BLI_ghashIterator_getKey   (ihash);
01433             /* only with deflecting set */
01434             if(ob->pd && ob->pd->deflect) {
01435                 MFace *mface= NULL;
01436                 MVert *mvert= NULL;
01437                 MVert *mprevvert= NULL;
01438                 ccdf_minmax *mima= NULL;
01439                 if(ccdm){
01440                     mface= ccdm->mface;
01441                     mvert= ccdm->mvert;
01442                     mprevvert= ccdm->mprevvert;
01443                     mima= ccdm->mima;
01444                     a = ccdm->totface;
01445 
01446                     if ((aabbmax[0] < ccdm->bbmin[0]) ||
01447                         (aabbmax[1] < ccdm->bbmin[1]) ||
01448                         (aabbmax[2] < ccdm->bbmin[2]) ||
01449                         (aabbmin[0] > ccdm->bbmax[0]) ||
01450                         (aabbmin[1] > ccdm->bbmax[1]) ||
01451                         (aabbmin[2] > ccdm->bbmax[2]) ) {
01452                         /* boxes dont intersect */
01453                         BLI_ghashIterator_step(ihash);
01454                         continue;
01455                     }
01456 
01457                 }
01458                 else{
01459                     /*aye that should be cached*/
01460                     printf("missing cache error \n");
01461                     BLI_ghashIterator_step(ihash);
01462                     continue;
01463                 }
01464 
01465 
01466                 /* use mesh*/
01467                 while (a--) {
01468                     if (
01469                         (aabbmax[0] < mima->minx) ||
01470                         (aabbmin[0] > mima->maxx) ||
01471                         (aabbmax[1] < mima->miny) ||
01472                         (aabbmin[1] > mima->maxy) ||
01473                         (aabbmax[2] < mima->minz) ||
01474                         (aabbmin[2] > mima->maxz)
01475                         ) {
01476                         mface++;
01477                         mima++;
01478                         continue;
01479                     }
01480 
01481 
01482                     if (mvert){
01483 
01484                         copy_v3_v3(nv1,mvert[mface->v1].co);
01485                         copy_v3_v3(nv2,mvert[mface->v2].co);
01486                         copy_v3_v3(nv3,mvert[mface->v3].co);
01487                         if (mface->v4){
01488                             copy_v3_v3(nv4,mvert[mface->v4].co);
01489                         }
01490                         if (mprevvert){
01491                             mul_v3_fl(nv1,time);
01492                             Vec3PlusStVec(nv1,(1.0f-time),mprevvert[mface->v1].co);
01493 
01494                             mul_v3_fl(nv2,time);
01495                             Vec3PlusStVec(nv2,(1.0f-time),mprevvert[mface->v2].co);
01496 
01497                             mul_v3_fl(nv3,time);
01498                             Vec3PlusStVec(nv3,(1.0f-time),mprevvert[mface->v3].co);
01499 
01500                             if (mface->v4){
01501                                 mul_v3_fl(nv4,time);
01502                                 Vec3PlusStVec(nv4,(1.0f-time),mprevvert[mface->v4].co);
01503                             }
01504                         }
01505                     }
01506 
01507                     /* switch origin to be nv2*/
01508                     sub_v3_v3v3(edge1, nv1, nv2);
01509                     sub_v3_v3v3(edge2, nv3, nv2);
01510 
01511                     cross_v3_v3v3(d_nvect, edge2, edge1);
01512                     normalize_v3(d_nvect);
01513                     if ( isect_line_tri_v3(edge_v1, edge_v2, nv1, nv2, nv3, &t, NULL)){
01514                         float v1[3],v2[3];
01515                         float intrusiondepth,i1,i2;
01516                         sub_v3_v3v3(v1, edge_v1, nv2);
01517                         sub_v3_v3v3(v2, edge_v2, nv2);
01518                         i1 = dot_v3v3(v1,d_nvect);
01519                         i2 = dot_v3v3(v2,d_nvect);
01520                         intrusiondepth = -MIN2(i1,i2)/el;
01521                         Vec3PlusStVec(force,intrusiondepth,d_nvect);
01522                         *damp=ob->pd->pdef_sbdamp;
01523                         deflected = 2;
01524                     }
01525                     if (mface->v4){ /* quad */
01526                         /* switch origin to be nv4 */
01527                         sub_v3_v3v3(edge1, nv3, nv4);
01528                         sub_v3_v3v3(edge2, nv1, nv4);
01529 
01530                         cross_v3_v3v3(d_nvect, edge2, edge1);
01531                         normalize_v3(d_nvect);
01532                         if (isect_line_tri_v3( edge_v1, edge_v2,nv1, nv3, nv4, &t, NULL)){
01533                             float v1[3],v2[3];
01534                             float intrusiondepth,i1,i2;
01535                             sub_v3_v3v3(v1, edge_v1, nv4);
01536                             sub_v3_v3v3(v2, edge_v2, nv4);
01537                         i1 = dot_v3v3(v1,d_nvect);
01538                         i2 = dot_v3v3(v2,d_nvect);
01539                         intrusiondepth = -MIN2(i1,i2)/el;
01540 
01541 
01542                             Vec3PlusStVec(force,intrusiondepth,d_nvect);
01543                             *damp=ob->pd->pdef_sbdamp;
01544                             deflected = 2;
01545                         }
01546                     }
01547                     mface++;
01548                     mima++;
01549                 }/* while a */
01550             } /* if(ob->pd && ob->pd->deflect) */
01551             BLI_ghashIterator_step(ihash);
01552     } /* while () */
01553     BLI_ghashIterator_free(ihash);
01554     return deflected;
01555 }
01556 
01557 static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, int ifirst, int ilast, struct ListBase *do_effector)
01558 {
01559     SoftBody *sb = ob->soft;
01560     int a;
01561     float damp;
01562     float feedback[3];
01563 
01564     if (sb && sb->totspring){
01565         for(a=ifirst; a<ilast; a++) {
01566             BodySpring *bs = &sb->bspring[a];
01567             bs->ext_force[0]=bs->ext_force[1]=bs->ext_force[2]=0.0f;
01568             feedback[0]=feedback[1]=feedback[2]=0.0f;
01569             bs->flag &= ~BSF_INTERSECT;
01570 
01571             if (bs->springtype == SB_EDGE){
01572                 /* +++ springs colliding */
01573                 if (ob->softflag & OB_SB_EDGECOLL){
01574                     if ( sb_detect_edge_collisionCached (sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos,
01575                         &damp,feedback,ob->lay,ob,timenow)){
01576                             add_v3_v3(bs->ext_force, feedback);
01577                             bs->flag |= BSF_INTERSECT;
01578                             //bs->cf=damp;
01579                             bs->cf=sb->choke*0.01f;
01580 
01581                     }
01582                 }
01583                 /* ---- springs colliding */
01584 
01585                 /* +++ springs seeing wind ... n stuff depending on their orientation*/
01586                 /* note we don't use sb->mediafrict but use sb->aeroedge for magnitude of effect*/
01587                 if(sb->aeroedge){
01588                     float vel[3],sp[3],pr[3],force[3];
01589                     float f,windfactor  = 0.25f;
01590                     /*see if we have wind*/
01591                     if(do_effector) {
01592                         EffectedPoint epoint;
01593                         float speed[3]={0.0f,0.0f,0.0f};
01594                         float pos[3];
01595                         mid_v3_v3v3(pos, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos);
01596                         mid_v3_v3v3(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec);
01597                         pd_point_from_soft(scene, pos, vel, -1, &epoint);
01598                         pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed);
01599 
01600                         mul_v3_fl(speed,windfactor);
01601                         add_v3_v3(vel, speed);
01602                     }
01603                     /* media in rest */
01604                     else{
01605                         add_v3_v3v3(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec);
01606                     }
01607                     f = normalize_v3(vel);
01608                     f = -0.0001f*f*f*sb->aeroedge;
01609                     /* (todo) add a nice angle dependant function done for now BUT */
01610                     /* still there could be some nice drag/lift function, but who needs it */
01611 
01612                     sub_v3_v3v3(sp, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos);
01613                     project_v3_v3v3(pr,vel,sp);
01614                     sub_v3_v3(vel, pr);
01615                     normalize_v3(vel);
01616                     if (ob->softflag & OB_SB_AERO_ANGLE){
01617                         normalize_v3(sp);
01618                         Vec3PlusStVec(bs->ext_force,f*(1.0f-ABS(dot_v3v3(vel,sp))),vel);
01619                     }
01620                     else{
01621                         Vec3PlusStVec(bs->ext_force,f,vel); // to keep compatible with 2.45 release files
01622                     }
01623                 }
01624                 /* --- springs seeing wind */
01625             }
01626         }
01627     }
01628 }
01629 
01630 
01631 static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow)
01632 {
01633     SoftBody *sb = ob->soft;
01634     ListBase *do_effector = NULL;
01635 
01636     do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights);
01637     _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
01638     pdEndEffectors(&do_effector);
01639 }
01640 
01641 static void *exec_scan_for_ext_spring_forces(void *data)
01642 {
01643     SB_thread_context *pctx = (SB_thread_context*)data;
01644     _scan_for_ext_spring_forces(pctx->scene, pctx->ob, pctx->timenow, pctx->ifirst, pctx->ilast, pctx->do_effector);
01645     return NULL;
01646 }
01647 
01648 static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,int totsprings,int *UNUSED(ptr_to_break_func(void)))
01649 {
01650     ListBase *do_effector = NULL;
01651     ListBase threads;
01652     SB_thread_context *sb_threads;
01653     int i, totthread,left,dec;
01654     int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
01655 
01656     do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights);
01657 
01658     /* figure the number of threads while preventing pretty pointless threading overhead */
01659     if(scene->r.mode & R_FIXED_THREADS)
01660         totthread= scene->r.threads;
01661     else
01662         totthread= BLI_system_thread_count();
01663     /* what if we got zillions of CPUs running but less to spread*/
01664     while ((totsprings/totthread < lowsprings) && (totthread > 1)) {
01665         totthread--;
01666     }
01667 
01668     sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBSpringsThread");
01669     memset(sb_threads, 0, sizeof(SB_thread_context)*totthread);
01670     left = totsprings;
01671     dec = totsprings/totthread +1;
01672     for(i=0; i<totthread; i++) {
01673         sb_threads[i].scene = scene;
01674         sb_threads[i].ob = ob;
01675         sb_threads[i].forcetime = 0.0; // not used here
01676         sb_threads[i].timenow = timenow;
01677         sb_threads[i].ilast   = left;
01678         left = left - dec;
01679         if (left >0){
01680             sb_threads[i].ifirst  = left;
01681         }
01682         else
01683             sb_threads[i].ifirst  = 0;
01684         sb_threads[i].do_effector = do_effector;
01685         sb_threads[i].do_deflector = 0;// not used here
01686         sb_threads[i].fieldfactor = 0.0f;// not used here
01687         sb_threads[i].windfactor  = 0.0f;// not used here
01688         sb_threads[i].nr= i;
01689         sb_threads[i].tot= totthread;
01690     }
01691     if(totthread > 1) {
01692         BLI_init_threads(&threads, exec_scan_for_ext_spring_forces, totthread);
01693 
01694         for(i=0; i<totthread; i++)
01695             BLI_insert_thread(&threads, &sb_threads[i]);
01696 
01697         BLI_end_threads(&threads);
01698     }
01699     else
01700         exec_scan_for_ext_spring_forces(&sb_threads[0]);
01701     /* clean up */
01702     MEM_freeN(sb_threads);
01703 
01704     pdEndEffectors(&do_effector);
01705 }
01706 
01707 
01708 /* --- the spring external section*/
01709 
01710 static int choose_winner(float*w, float* pos,float*a,float*b,float*c,float*ca,float*cb,float*cc)
01711 {
01712     float mindist,cp;
01713     int winner =1;
01714     mindist = ABS(dot_v3v3(pos,a));
01715 
01716     cp = ABS(dot_v3v3(pos,b));
01717     if ( mindist < cp ){
01718         mindist = cp;
01719         winner =2;
01720     }
01721 
01722     cp = ABS(dot_v3v3(pos,c));
01723     if (mindist < cp ){
01724         mindist = cp;
01725         winner =3;
01726     }
01727     switch (winner){
01728         case 1: copy_v3_v3(w,ca); break;
01729         case 2: copy_v3_v3(w,cb); break;
01730         case 3: copy_v3_v3(w,cc);
01731     }
01732     return(winner);
01733 }
01734 
01735 
01736 
01737 static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], float *damp,
01738                                      float force[3], unsigned int UNUSED(par_layer), struct Object *vertexowner,
01739                                      float time,float vel[3], float *intrusion)
01740 {
01741     Object *ob= NULL;
01742     GHash *hash;
01743     GHashIterator *ihash;
01744     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},
01745           vv1[3], vv2[3], vv3[3], vv4[3], coledge[3]={0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f,
01746           outerforceaccu[3], innerforceaccu[3],
01747           facedist, /* n_mag, */ /* UNUSED */ force_mag_norm, minx, miny, minz, maxx, maxy, maxz,
01748           innerfacethickness = -0.5f, outerfacethickness = 0.2f,
01749           ee = 5.0f, ff = 0.1f, fa=1;
01750     int a, deflected=0, cavel=0, ci=0;
01751 /* init */
01752     *intrusion = 0.0f;
01753     hash  = vertexowner->soft->scratch->colliderhash;
01754     ihash = BLI_ghashIterator_new(hash);
01755     outerforceaccu[0]=outerforceaccu[1]=outerforceaccu[2]=0.0f;
01756     innerforceaccu[0]=innerforceaccu[1]=innerforceaccu[2]=0.0f;
01757 /* go */
01758     while (!BLI_ghashIterator_isDone(ihash) ) {
01759 
01760         ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
01761         ob             = BLI_ghashIterator_getKey   (ihash);
01762             /* only with deflecting set */
01763             if(ob->pd && ob->pd->deflect) {
01764                 MFace *mface= NULL;
01765                 MVert *mvert= NULL;
01766                 MVert *mprevvert= NULL;
01767                 ccdf_minmax *mima= NULL;
01768 
01769                 if(ccdm){
01770                     mface= ccdm->mface;
01771                     mvert= ccdm->mvert;
01772                     mprevvert= ccdm->mprevvert;
01773                     mima= ccdm->mima;
01774                     a = ccdm->totface;
01775 
01776                     minx =ccdm->bbmin[0];
01777                     miny =ccdm->bbmin[1];
01778                     minz =ccdm->bbmin[2];
01779 
01780                     maxx =ccdm->bbmax[0];
01781                     maxy =ccdm->bbmax[1];
01782                     maxz =ccdm->bbmax[2];
01783 
01784                     if ((opco[0] < minx) ||
01785                         (opco[1] < miny) ||
01786                         (opco[2] < minz) ||
01787                         (opco[0] > maxx) ||
01788                         (opco[1] > maxy) ||
01789                         (opco[2] > maxz) ) {
01790                             /* outside the padded boundbox --> collision object is too far away */
01791                                                 BLI_ghashIterator_step(ihash);
01792                             continue;
01793                     }
01794                 }
01795                 else{
01796                     /*aye that should be cached*/
01797                     printf("missing cache error \n");
01798                         BLI_ghashIterator_step(ihash);
01799                     continue;
01800                 }
01801 
01802                 /* do object level stuff */
01803                 /* need to have user control for that since it depends on model scale */
01804                 innerfacethickness =-ob->pd->pdef_sbift;
01805                 outerfacethickness =ob->pd->pdef_sboft;
01806                 fa = (ff*outerfacethickness-outerfacethickness);
01807                 fa *= fa;
01808                 fa = 1.0f/fa;
01809                 avel[0]=avel[1]=avel[2]=0.0f;
01810                 /* use mesh*/
01811                 while (a--) {
01812                     if (
01813                         (opco[0] < mima->minx) ||
01814                         (opco[0] > mima->maxx) ||
01815                         (opco[1] < mima->miny) ||
01816                         (opco[1] > mima->maxy) ||
01817                         (opco[2] < mima->minz) ||
01818                         (opco[2] > mima->maxz)
01819                         ) {
01820                             mface++;
01821                             mima++;
01822                             continue;
01823                     }
01824 
01825                     if (mvert){
01826 
01827                         copy_v3_v3(nv1,mvert[mface->v1].co);
01828                         copy_v3_v3(nv2,mvert[mface->v2].co);
01829                         copy_v3_v3(nv3,mvert[mface->v3].co);
01830                         if (mface->v4){
01831                             copy_v3_v3(nv4,mvert[mface->v4].co);
01832                         }
01833 
01834                         if (mprevvert){
01835                             /* grab the average speed of the collider vertices
01836                             before we spoil nvX
01837                             humm could be done once a SB steps but then we' need to store that too
01838                             since the AABB reduced propabitlty to get here drasticallly
01839                             it might be a nice tradeof CPU <--> memory
01840                             */
01841                             sub_v3_v3v3(vv1,nv1,mprevvert[mface->v1].co);
01842                             sub_v3_v3v3(vv2,nv2,mprevvert[mface->v2].co);
01843                             sub_v3_v3v3(vv3,nv3,mprevvert[mface->v3].co);
01844                             if (mface->v4){
01845                                 sub_v3_v3v3(vv4,nv4,mprevvert[mface->v4].co);
01846                             }
01847 
01848                             mul_v3_fl(nv1,time);
01849                             Vec3PlusStVec(nv1,(1.0f-time),mprevvert[mface->v1].co);
01850 
01851                             mul_v3_fl(nv2,time);
01852                             Vec3PlusStVec(nv2,(1.0f-time),mprevvert[mface->v2].co);
01853 
01854                             mul_v3_fl(nv3,time);
01855                             Vec3PlusStVec(nv3,(1.0f-time),mprevvert[mface->v3].co);
01856 
01857                             if (mface->v4){
01858                                 mul_v3_fl(nv4,time);
01859                                 Vec3PlusStVec(nv4,(1.0f-time),mprevvert[mface->v4].co);
01860                             }
01861                         }
01862                     }
01863 
01864                     /* switch origin to be nv2*/
01865                     sub_v3_v3v3(edge1, nv1, nv2);
01866                     sub_v3_v3v3(edge2, nv3, nv2);
01867                     sub_v3_v3v3(dv1,opco,nv2); /* abuse dv1 to have vertex in question at *origin* of triangle */
01868 
01869                     cross_v3_v3v3(d_nvect, edge2, edge1);
01870                     /* n_mag = */ /* UNUSED */ normalize_v3(d_nvect);
01871                     facedist = dot_v3v3(dv1,d_nvect);
01872                     // so rules are
01873                     //
01874 
01875                     if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
01876                         if (isect_point_tri_prism_v3(opco, nv1, nv2, nv3) ){
01877                             force_mag_norm =(float)exp(-ee*facedist);
01878                             if (facedist > outerfacethickness*ff)
01879                                 force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
01880                             *damp=ob->pd->pdef_sbdamp;
01881                             if (facedist > 0.0f){
01882                                 *damp *= (1.0f - facedist/outerfacethickness);
01883                                 Vec3PlusStVec(outerforceaccu,force_mag_norm,d_nvect);
01884                                 deflected = 3;
01885 
01886                             }
01887                             else {
01888                                 Vec3PlusStVec(innerforceaccu,force_mag_norm,d_nvect);
01889                                 if (deflected < 2) deflected = 2;
01890                             }
01891                             if ((mprevvert) && (*damp > 0.0f)){
01892                                 choose_winner(ve,opco,nv1,nv2,nv3,vv1,vv2,vv3);
01893                                 add_v3_v3(avel, ve);
01894                                 cavel ++;
01895                             }
01896                             *intrusion += facedist;
01897                             ci++;
01898                         }
01899                     }
01900                     if (mface->v4){ /* quad */
01901                         /* switch origin to be nv4 */
01902                         sub_v3_v3v3(edge1, nv3, nv4);
01903                         sub_v3_v3v3(edge2, nv1, nv4);
01904                         sub_v3_v3v3(dv1,opco,nv4); /* abuse dv1 to have vertex in question at *origin* of triangle */
01905 
01906                         cross_v3_v3v3(d_nvect, edge2, edge1);
01907                         /* n_mag = */ /* UNUSED */ normalize_v3(d_nvect);
01908                         facedist = dot_v3v3(dv1,d_nvect);
01909 
01910                         if ((facedist > innerfacethickness) && (facedist < outerfacethickness)){
01911                             if (isect_point_tri_prism_v3(opco, nv1, nv3, nv4) ){
01912                                 force_mag_norm =(float)exp(-ee*facedist);
01913                                 if (facedist > outerfacethickness*ff)
01914                                     force_mag_norm =(float)force_mag_norm*fa*(facedist - outerfacethickness)*(facedist - outerfacethickness);
01915                                 *damp=ob->pd->pdef_sbdamp;
01916                             if (facedist > 0.0f){
01917                                 *damp *= (1.0f - facedist/outerfacethickness);
01918                                 Vec3PlusStVec(outerforceaccu,force_mag_norm,d_nvect);
01919                                 deflected = 3;
01920 
01921                             }
01922                             else {
01923                                 Vec3PlusStVec(innerforceaccu,force_mag_norm,d_nvect);
01924                                 if (deflected < 2) deflected = 2;
01925                             }
01926 
01927                                 if ((mprevvert) && (*damp > 0.0f)){
01928                                     choose_winner(ve,opco,nv1,nv3,nv4,vv1,vv3,vv4);
01929                                     add_v3_v3(avel, ve);
01930                                     cavel ++;
01931                                 }
01932                                 *intrusion += facedist;
01933                                 ci++;
01934                             }
01935 
01936                         }
01937                         if ((deflected < 2)&& (G.rt != 444)) // we did not hit a face until now
01938                         { // see if 'outer' hits an edge
01939                             float dist;
01940 
01941                             closest_to_line_segment_v3(ve, opco, nv1, nv2);
01942                              sub_v3_v3v3(ve,opco,ve);
01943                             dist = normalize_v3(ve);
01944                             if ((dist < outerfacethickness)&&(dist < mindistedge )){
01945                                 copy_v3_v3(coledge,ve);
01946                                 mindistedge = dist,
01947                                 deflected=1;
01948                             }
01949 
01950                             closest_to_line_segment_v3(ve, opco, nv2, nv3);
01951                              sub_v3_v3v3(ve,opco,ve);
01952                             dist = normalize_v3(ve);
01953                             if ((dist < outerfacethickness)&&(dist < mindistedge )){
01954                                 copy_v3_v3(coledge,ve);
01955                                 mindistedge = dist,
01956                                 deflected=1;
01957                             }
01958 
01959                             closest_to_line_segment_v3(ve, opco, nv3, nv1);
01960                              sub_v3_v3v3(ve,opco,ve);
01961                             dist = normalize_v3(ve);
01962                             if ((dist < outerfacethickness)&&(dist < mindistedge )){
01963                                 copy_v3_v3(coledge,ve);
01964                                 mindistedge = dist,
01965                                 deflected=1;
01966                             }
01967                             if (mface->v4){ /* quad */
01968                                 closest_to_line_segment_v3(ve, opco, nv3, nv4);
01969                                 sub_v3_v3v3(ve,opco,ve);
01970                                 dist = normalize_v3(ve);
01971                                 if ((dist < outerfacethickness)&&(dist < mindistedge )){
01972                                     copy_v3_v3(coledge,ve);
01973                                     mindistedge = dist,
01974                                         deflected=1;
01975                                 }
01976 
01977                                 closest_to_line_segment_v3(ve, opco, nv1, nv4);
01978                                 sub_v3_v3v3(ve,opco,ve);
01979                                 dist = normalize_v3(ve);
01980                                 if ((dist < outerfacethickness)&&(dist < mindistedge )){
01981                                     copy_v3_v3(coledge,ve);
01982                                     mindistedge = dist,
01983                                         deflected=1;
01984                                 }
01985 
01986                             }
01987 
01988 
01989                         }
01990                     }
01991                     mface++;
01992                     mima++;
01993                 }/* while a */
01994             } /* if(ob->pd && ob->pd->deflect) */
01995             BLI_ghashIterator_step(ihash);
01996     } /* while () */
01997 
01998     if (deflected == 1){ // no face but 'outer' edge cylinder sees vert
01999         force_mag_norm =(float)exp(-ee*mindistedge);
02000         if (mindistedge > outerfacethickness*ff)
02001             force_mag_norm =(float)force_mag_norm*fa*(mindistedge - outerfacethickness)*(mindistedge - outerfacethickness);
02002         Vec3PlusStVec(force,force_mag_norm,coledge);
02003         *damp=ob->pd->pdef_sbdamp;
02004         if (mindistedge > 0.0f){
02005             *damp *= (1.0f - mindistedge/outerfacethickness);
02006         }
02007 
02008     }
02009     if (deflected == 2){ //  face inner detected
02010         add_v3_v3(force, innerforceaccu);
02011     }
02012     if (deflected == 3){ //  face outer detected
02013         add_v3_v3(force, outerforceaccu);
02014     }
02015 
02016     BLI_ghashIterator_free(ihash);
02017     if (cavel) mul_v3_fl(avel,1.0f/(float)cavel);
02018     copy_v3_v3(vel,avel);
02019     if (ci) *intrusion /= ci;
02020     if (deflected){
02021         normalize_v3_v3(facenormal, force);
02022     }
02023     return deflected;
02024 }
02025 
02026 
02027 /* sandbox to plug in various deflection algos */
02028 static int sb_deflect_face(Object *ob,float *actpos,float *facenormal,float *force,float *cf,float time,float *vel,float *intrusion)
02029 {
02030     float s_actpos[3];
02031     int deflected;
02032     copy_v3_v3(s_actpos,actpos);
02033     deflected= sb_detect_vertex_collisionCached(s_actpos, facenormal, cf, force , ob->lay, ob,time,vel,intrusion);
02034     //deflected= sb_detect_vertex_collisionCachedEx(s_actpos, facenormal, cf, force , ob->lay, ob,time,vel,intrusion);
02035     return(deflected);
02036 }
02037 
02038 /* hiding this for now .. but the jacobian may pop up on other tasks .. so i'd like to keep it
02039 static void dfdx_spring(int ia, int ic, int op, float dir[3],float L,float len,float factor)
02040 {
02041     float m,delta_ij;
02042     int i ,j;
02043     if (L < len){
02044         for(i=0;i<3;i++)
02045             for(j=0;j<3;j++){
02046                 delta_ij = (i==j ? (1.0f): (0.0f));
02047                 m=factor*(dir[i]*dir[j] + (1-L/len)*(delta_ij - dir[i]*dir[j]));
02048                 nlMatrixAdd(ia+i,op+ic+j,m);
02049             }
02050     }
02051     else{
02052         for(i=0;i<3;i++)
02053             for(j=0;j<3;j++){
02054                 m=factor*dir[i]*dir[j];
02055                 nlMatrixAdd(ia+i,op+ic+j,m);
02056             }
02057     }
02058 }
02059 
02060 
02061 static void dfdx_goal(int ia, int ic, int op, float factor)
02062 {
02063     int i;
02064     for(i=0;i<3;i++) nlMatrixAdd(ia+i,op+ic+i,factor);
02065 }
02066 
02067 static void dfdv_goal(int ia, int ic,float factor)
02068 {
02069     int i;
02070     for(i=0;i<3;i++) nlMatrixAdd(ia+i,ic+i,factor);
02071 }
02072 */
02073 static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float UNUSED(forcetime), int nl_flags)
02074 {
02075     SoftBody *sb= ob->soft; /* is supposed to be there */
02076     BodyPoint  *bp1,*bp2;
02077 
02078     float dir[3],dvel[3];
02079     float distance,forcefactor,kd,absvel,projvel,kw;
02080 #if 0   /* UNUSED */
02081     int ia,ic;
02082 #endif
02083     /* prepare depending on which side of the spring we are on */
02084     if (bpi == bs->v1){
02085         bp1 = &sb->bpoint[bs->v1];
02086         bp2 = &sb->bpoint[bs->v2];
02087 #if 0   /* UNUSED */
02088         ia =3*bs->v1;
02089         ic =3*bs->v2;
02090 #endif
02091     }
02092     else if (bpi == bs->v2){
02093         bp1 = &sb->bpoint[bs->v2];
02094         bp2 = &sb->bpoint[bs->v1];
02095 #if 0   /* UNUSED */
02096         ia =3*bs->v2;
02097         ic =3*bs->v1;
02098 #endif
02099     }
02100     else{
02101         /* TODO make this debug option */
02102         
02103         printf("bodypoint <bpi> is not attached to spring  <*bs> --> sb_spring_force()\n");
02104         return;
02105     }
02106 
02107     /* do bp1 <--> bp2 elastic */
02108     sub_v3_v3v3(dir,bp1->pos,bp2->pos);
02109     distance = normalize_v3(dir);
02110     if (bs->len < distance)
02111         iks  = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
02112     else
02113         iks  = 1.0f/(1.0f-sb->inpush)-1.0f ;/* inner spring constants function */
02114 
02115     if(bs->len > 0.0f) /* check for degenerated springs */
02116         forcefactor = iks/bs->len;
02117     else
02118         forcefactor = iks;
02119     kw = (bp1->springweight+bp2->springweight)/2.0f;
02120     kw = kw * kw;
02121     kw = kw * kw;
02122     switch (bs->springtype){
02123         case SB_EDGE:
02124         case SB_HANDLE:
02125             forcefactor *=  kw;
02126             break;
02127         case SB_BEND:
02128             forcefactor *=sb->secondspring*kw;
02129             break;
02130         case SB_STIFFQUAD:
02131             forcefactor *=sb->shearstiff*sb->shearstiff* kw;
02132             break;
02133         default:
02134             break;
02135     }
02136 
02137 
02138     Vec3PlusStVec(bp1->force,(bs->len - distance)*forcefactor,dir);
02139 
02140     /* do bp1 <--> bp2 viscous */
02141     sub_v3_v3v3(dvel,bp1->vec,bp2->vec);
02142     kd = sb->infrict * sb_fric_force_scale(ob);
02143     absvel  = normalize_v3(dvel);
02144     projvel = dot_v3v3(dir,dvel);
02145     kd     *= absvel * projvel;
02146     Vec3PlusStVec(bp1->force,-kd,dir);
02147 
02148     /* do jacobian stuff if needed */
02149     if(nl_flags & NLF_BUILD){
02150         //int op =3*sb->totpoint;
02151         //float mvel = -forcetime*kd;
02152         //float mpos = -forcetime*forcefactor;
02153         /* depending on my pos */
02154         // dfdx_spring(ia,ia,op,dir,bs->len,distance,-mpos);
02155         /* depending on my vel */
02156         // dfdv_goal(ia,ia,mvel); // well that ignores geometie
02157         if(bp2->goal < SOFTGOALSNAP){ /* ommit this bp when it snaps */
02158             /* depending on other pos */
02159             // dfdx_spring(ia,ic,op,dir,bs->len,distance,mpos);
02160             /* depending on other vel */
02161             // dfdv_goal(ia,ia,-mvel); // well that ignores geometie
02162         }
02163     }
02164 }
02165 
02166 
02167 /* since this is definitely the most CPU consuming task here .. try to spread it */
02168 /* core function _softbody_calc_forces_slice_in_a_thread */
02169 /* result is int to be able to flag user break */
02170 static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow,int ifirst,int ilast,int *UNUSED(ptr_to_break_func(void)),ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor)
02171 {
02172     float iks;
02173     int bb,do_selfcollision,do_springcollision,do_aero;
02174     int number_of_points_here = ilast - ifirst;
02175     SoftBody *sb= ob->soft; /* is supposed to be there */
02176     BodyPoint  *bp;
02177 
02178     /* intitialize */
02179     if (sb) {
02180     /* check conditions for various options */
02181     /* +++ could be done on object level to squeeze out the last bits of it */
02182     do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
02183     do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
02184     do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
02185     /* --- could be done on object level to squeeze out the last bits of it */
02186     }
02187     else {
02188         printf("Error expected a SB here \n");
02189         return (999);
02190     }
02191 
02192 /* debugerin */
02193     if  (sb->totpoint < ifirst) {
02194         printf("Aye 998");
02195         return (998);
02196     }
02197 /* debugerin */
02198 
02199 
02200     bp = &sb->bpoint[ifirst];
02201     for(bb=number_of_points_here; bb>0; bb--, bp++) {
02202         /* clear forces  accumulator */
02203         bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
02204         /* naive ball self collision */
02205         /* needs to be done if goal snaps or not */
02206         if(do_selfcollision){
02207             int attached;
02208             BodyPoint   *obp;
02209             BodySpring *bs;
02210             int c,b;
02211             float velcenter[3],dvel[3],def[3];
02212             float distance;
02213             float compare;
02214             float bstune = sb->ballstiff;
02215 
02216             for(c=sb->totpoint, obp= sb->bpoint; c>=ifirst+bb; c--, obp++) {
02217                 compare = (obp->colball + bp->colball);
02218                 sub_v3_v3v3(def, bp->pos, obp->pos);
02219                 /* rather check the AABBoxes before ever calulating the real distance */
02220                 /* mathematically it is completly nuts, but performace is pretty much (3) times faster */
02221                 if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
02222                 distance = normalize_v3(def);
02223                 if (distance < compare ){
02224                     /* exclude body points attached with a spring */
02225                     attached = 0;
02226                     for(b=obp->nofsprings;b>0;b--){
02227                         bs = sb->bspring + obp->springs[b-1];
02228                         if (( ilast-bb == bs->v2)  || ( ilast-bb == bs->v1)){
02229                             attached=1;
02230                             continue;}
02231                     }
02232                     if (!attached){
02233                         float f = bstune/(distance) + bstune/(compare*compare)*distance - 2.0f*bstune/compare ;
02234 
02235                         mid_v3_v3v3(velcenter, bp->vec, obp->vec);
02236                         sub_v3_v3v3(dvel,velcenter,bp->vec);
02237                         mul_v3_fl(dvel,_final_mass(ob,bp));
02238 
02239                         Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def);
02240                         Vec3PlusStVec(bp->force,sb->balldamp,dvel);
02241 
02242                         /* exploit force(a,b) == -force(b,a) part2/2 */
02243                         sub_v3_v3v3(dvel,velcenter,obp->vec);
02244                         mul_v3_fl(dvel,_final_mass(ob,bp));
02245 
02246                         Vec3PlusStVec(obp->force,sb->balldamp,dvel);
02247                         Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def);
02248                     }
02249                 }
02250             }
02251         }
02252         /* naive ball self collision done */
02253 
02254         if(_final_goal(ob,bp) < SOFTGOALSNAP){ /* ommit this bp when it snaps */
02255             float auxvect[3];
02256             float velgoal[3];
02257 
02258             /* do goal stuff */
02259             if(ob->softflag & OB_SB_GOAL) {
02260                 /* true elastic goal */
02261                 float ks,kd;
02262                 sub_v3_v3v3(auxvect,bp->pos,bp->origT);
02263                 ks  = 1.0f/(1.0f- _final_goal(ob,bp)*sb->goalspring)-1.0f ;
02264                 bp->force[0]+= -ks*(auxvect[0]);
02265                 bp->force[1]+= -ks*(auxvect[1]);
02266                 bp->force[2]+= -ks*(auxvect[2]);
02267 
02268                 /* calulate damping forces generated by goals*/
02269                 sub_v3_v3v3(velgoal,bp->origS, bp->origE);
02270                 kd =  sb->goalfrict * sb_fric_force_scale(ob) ;
02271                 add_v3_v3v3(auxvect,velgoal,bp->vec);
02272 
02273                 if (forcetime > 0.0f) { /* make sure friction does not become rocket motor on time reversal */
02274                     bp->force[0]-= kd * (auxvect[0]);
02275                     bp->force[1]-= kd * (auxvect[1]);
02276                     bp->force[2]-= kd * (auxvect[2]);
02277                 }
02278                 else {
02279                     bp->force[0]-= kd * (velgoal[0] - bp->vec[0]);
02280                     bp->force[1]-= kd * (velgoal[1] - bp->vec[1]);
02281                     bp->force[2]-= kd * (velgoal[2] - bp->vec[2]);
02282                 }
02283             }
02284             /* done goal stuff */
02285 
02286             /* gravitation */
02287             if (sb && scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY){
02288                 float gravity[3];
02289                 copy_v3_v3(gravity, scene->physics_settings.gravity);
02290                 mul_v3_fl(gravity, sb_grav_force_scale(ob)*_final_mass(ob,bp)*sb->effector_weights->global_gravity); /* individual mass of node here */
02291                 add_v3_v3(bp->force, gravity);
02292             }
02293 
02294             /* particle field & vortex */
02295             if(do_effector) {
02296                 EffectedPoint epoint;
02297                 float kd;
02298                 float force[3]= {0.0f, 0.0f, 0.0f};
02299                 float speed[3]= {0.0f, 0.0f, 0.0f};
02300                 float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */
02301                 pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint-bp, &epoint);
02302                 pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed);
02303 
02304                 /* apply forcefield*/
02305                 mul_v3_fl(force,fieldfactor* eval_sb_fric_force_scale);
02306                 add_v3_v3(bp->force, force);
02307 
02308                 /* BP friction in moving media */
02309                 kd= sb->mediafrict* eval_sb_fric_force_scale;
02310                 bp->force[0] -= kd * (bp->vec[0] + windfactor*speed[0]/eval_sb_fric_force_scale);
02311                 bp->force[1] -= kd * (bp->vec[1] + windfactor*speed[1]/eval_sb_fric_force_scale);
02312                 bp->force[2] -= kd * (bp->vec[2] + windfactor*speed[2]/eval_sb_fric_force_scale);
02313                 /* now we'll have nice centrifugal effect for vortex */
02314 
02315             }
02316             else {
02317                 /* BP friction in media (not) moving*/
02318                 float kd = sb->mediafrict* sb_fric_force_scale(ob);
02319                 /* assume it to be proportional to actual velocity */
02320                 bp->force[0]-= bp->vec[0]*kd;
02321                 bp->force[1]-= bp->vec[1]*kd;
02322                 bp->force[2]-= bp->vec[2]*kd;
02323                 /* friction in media done */
02324             }
02325             /* +++cached collision targets */
02326             bp->choke = 0.0f;
02327             bp->choke2 = 0.0f;
02328             bp->loc_flag &= ~SBF_DOFUZZY;
02329             if(do_deflector && !(bp->loc_flag & SBF_OUTOFCOLLISION) ) {
02330                 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;
02331                 float kd = 1.0f;
02332 
02333                 if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){
02334                         if (intrusion < 0.0f){
02335                             sb->scratch->flag |= SBF_DOFUZZY;
02336                             bp->loc_flag |= SBF_DOFUZZY;
02337                             bp->choke = sb->choke*0.01f;
02338                         }
02339 
02340                             sub_v3_v3v3(cfforce,bp->vec,vel);
02341                             Vec3PlusStVec(bp->force,-cf*50.0f,cfforce);
02342 
02343                     Vec3PlusStVec(bp->force,kd,defforce);
02344                 }
02345 
02346             }
02347             /* ---cached collision targets */
02348 
02349             /* +++springs */
02350             iks  = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
02351             if(ob->softflag & OB_SB_EDGES) {
02352                 if (sb->bspring){ /* spring list exists at all ? */
02353                     int b;
02354                     BodySpring *bs;
02355                     for(b=bp->nofsprings;b>0;b--){
02356                         bs = sb->bspring + bp->springs[b-1];
02357                         if (do_springcollision || do_aero){
02358                             add_v3_v3(bp->force, bs->ext_force);
02359                             if (bs->flag & BSF_INTERSECT)
02360                                 bp->choke = bs->cf;
02361 
02362                         }
02363                         // sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags)
02364                         sb_spring_force(ob,ilast-bb,bs,iks,forcetime,0);
02365                     }/* loop springs */
02366                 }/* existing spring list */
02367             }/*any edges*/
02368             /* ---springs */
02369         }/*omit on snap */
02370     }/*loop all bp's*/
02371     return 0; /*done fine*/
02372 }
02373 
02374 static void *exec_softbody_calc_forces(void *data)
02375 {
02376     SB_thread_context *pctx = (SB_thread_context*)data;
02377     _softbody_calc_forces_slice_in_a_thread(pctx->scene, pctx->ob, pctx->forcetime, pctx->timenow, pctx->ifirst, pctx->ilast, NULL, pctx->do_effector,pctx->do_deflector,pctx->fieldfactor,pctx->windfactor);
02378     return NULL;
02379 }
02380 
02381 static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow,int totpoint,int *UNUSED(ptr_to_break_func(void)),struct ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor)
02382 {
02383     ListBase threads;
02384     SB_thread_context *sb_threads;
02385     int i, totthread,left,dec;
02386     int lowpoints =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
02387 
02388     /* figure the number of threads while preventing pretty pointless threading overhead */
02389     if(scene->r.mode & R_FIXED_THREADS)
02390         totthread= scene->r.threads;
02391     else
02392         totthread= BLI_system_thread_count();
02393     /* what if we got zillions of CPUs running but less to spread*/
02394     while ((totpoint/totthread < lowpoints) && (totthread > 1)) {
02395         totthread--;
02396     }
02397 
02398     /* printf("sb_cf_threads_run spawning %d threads \n",totthread); */
02399 
02400     sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBThread");
02401     memset(sb_threads, 0, sizeof(SB_thread_context)*totthread);
02402     left = totpoint;
02403     dec = totpoint/totthread +1;
02404     for(i=0; i<totthread; i++) {
02405         sb_threads[i].scene = scene;
02406         sb_threads[i].ob = ob;
02407         sb_threads[i].forcetime = forcetime;
02408         sb_threads[i].timenow = timenow;
02409         sb_threads[i].ilast   = left;
02410         left = left - dec;
02411         if (left >0){
02412             sb_threads[i].ifirst  = left;
02413         }
02414         else
02415             sb_threads[i].ifirst  = 0;
02416         sb_threads[i].do_effector = do_effector;
02417         sb_threads[i].do_deflector = do_deflector;
02418         sb_threads[i].fieldfactor = fieldfactor;
02419         sb_threads[i].windfactor  = windfactor;
02420         sb_threads[i].nr= i;
02421         sb_threads[i].tot= totthread;
02422     }
02423 
02424 
02425     if(totthread > 1) {
02426         BLI_init_threads(&threads, exec_softbody_calc_forces, totthread);
02427 
02428         for(i=0; i<totthread; i++)
02429             BLI_insert_thread(&threads, &sb_threads[i]);
02430 
02431         BLI_end_threads(&threads);
02432     }
02433     else
02434         exec_softbody_calc_forces(&sb_threads[0]);
02435     /* clean up */
02436     MEM_freeN(sb_threads);
02437 }
02438 
02439 static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow, int UNUSED(nl_flags))
02440 {
02441 /* rule we never alter free variables :bp->vec bp->pos in here !
02442  * this will ruin adaptive stepsize AKA heun! (BM)
02443  */
02444     SoftBody *sb= ob->soft; /* is supposed to be there */
02445     /*BodyPoint *bproot;*/ /* UNUSED */
02446     ListBase *do_effector = NULL;
02447     /* float gravity; */ /* UNUSED */
02448     /* float iks; */
02449     float fieldfactor = -1.0f, windfactor  = 0.25;
02450     int   do_deflector /*,do_selfcollision*/ ,do_springcollision,do_aero;
02451 
02452     /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
02453 
02454     /* check conditions for various options */
02455     do_deflector= query_external_colliders(scene, ob);
02456     /* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */
02457     do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
02458     do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
02459 
02460     /* iks  = 1.0f/(1.0f-sb->inspring)-1.0f; */ /* inner spring constants function */ /* UNUSED */
02461     /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
02462 
02463     if (do_springcollision || do_aero)
02464     sb_sfesf_threads_run(scene, ob, timenow,sb->totspring,NULL);
02465 
02466     /* after spring scan because it uses Effoctors too */
02467     do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights);
02468 
02469     if (do_deflector) {
02470         float defforce[3];
02471         do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow);
02472     }
02473 
02474     sb_cf_threads_run(scene, ob, forcetime, timenow, sb->totpoint, NULL, do_effector, do_deflector, fieldfactor, windfactor);
02475 
02476     /* finally add forces caused by face collision */
02477     if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow);
02478 
02479     /* finish matrix and solve */
02480     pdEndEffectors(&do_effector);
02481 }
02482 
02483 
02484 
02485 
02486 static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, float timenow, int nl_flags)
02487 {
02488     /* redirection to the new threaded Version */
02489     if (!(G.rt & 0x10)){ // 16
02490         softbody_calc_forcesEx(scene, ob, forcetime, timenow, nl_flags);
02491         return;
02492     }
02493     else{
02494         /* so the following will die  */
02495         /* |||||||||||||||||||||||||| */
02496         /* VVVVVVVVVVVVVVVVVVVVVVVVVV */
02497         /*backward compatibility note:
02498         fixing bug [17428] which forces adaptive step size to tiny steps
02499         in some situations
02500         .. keeping G.rt==17 0x11 option for old files 'needing' the bug*/
02501 
02502         /* rule we never alter free variables :bp->vec bp->pos in here !
02503         * this will ruin adaptive stepsize AKA heun! (BM)
02504         */
02505         SoftBody *sb= ob->soft; /* is supposed to be there */
02506         BodyPoint  *bp;
02507         /* BodyPoint *bproot; */ /* UNUSED */
02508         BodySpring *bs;
02509         ListBase *do_effector = NULL;
02510         float iks, ks, kd, gravity[3] = {0.0f,0.0f,0.0f};
02511         float fieldfactor = -1.0f, windfactor  = 0.25f;
02512         float tune = sb->ballstiff;
02513         int a, b,  do_deflector,do_selfcollision,do_springcollision,do_aero;
02514 
02515 
02516         /* jacobian
02517         NLboolean success;
02518 
02519         if(nl_flags){
02520         nlBegin(NL_SYSTEM);
02521         nlBegin(NL_MATRIX);
02522         }
02523         */
02524 
02525 
02526         if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY){
02527             copy_v3_v3(gravity, scene->physics_settings.gravity);
02528             mul_v3_fl(gravity, sb_grav_force_scale(ob)*sb->effector_weights->global_gravity);
02529         }
02530 
02531         /* check conditions for various options */
02532         do_deflector= query_external_colliders(scene, ob);
02533         do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
02534         do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
02535         do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
02536 
02537         iks  = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
02538         /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
02539 
02540         if (do_springcollision || do_aero)  scan_for_ext_spring_forces(scene, ob, timenow);
02541         /* after spring scan because it uses Effoctors too */
02542         do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights);
02543 
02544         if (do_deflector) {
02545             float defforce[3];
02546             do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow);
02547         }
02548 
02549         for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
02550             /* clear forces  accumulator */
02551             bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
02552             if(nl_flags & NLF_BUILD){
02553                 //int ia =3*(sb->totpoint-a);
02554                 //int op =3*sb->totpoint;
02555                 /* dF/dV = v */
02556                 /* jacobioan
02557                 nlMatrixAdd(op+ia,ia,-forcetime);
02558                 nlMatrixAdd(op+ia+1,ia+1,-forcetime);
02559                 nlMatrixAdd(op+ia+2,ia+2,-forcetime);
02560 
02561                 nlMatrixAdd(ia,ia,1);
02562                 nlMatrixAdd(ia+1,ia+1,1);
02563                 nlMatrixAdd(ia+2,ia+2,1);
02564 
02565                 nlMatrixAdd(op+ia,op+ia,1);
02566                 nlMatrixAdd(op+ia+1,op+ia+1,1);
02567                 nlMatrixAdd(op+ia+2,op+ia+2,1);
02568                 */
02569 
02570 
02571             }
02572 
02573             /* naive ball self collision */
02574             /* needs to be done if goal snaps or not */
02575             if(do_selfcollision){
02576                 int attached;
02577                 BodyPoint   *obp;
02578                 int c,b;
02579                 float velcenter[3],dvel[3],def[3];
02580                 float distance;
02581                 float compare;
02582 
02583                 for(c=sb->totpoint, obp= sb->bpoint; c>=a; c--, obp++) {
02584 
02585                     //if ((bp->octantflag & obp->octantflag) == 0) continue;
02586 
02587                     compare = (obp->colball + bp->colball);
02588                     sub_v3_v3v3(def, bp->pos, obp->pos);
02589 
02590                     /* rather check the AABBoxes before ever calulating the real distance */
02591                     /* mathematically it is completly nuts, but performace is pretty much (3) times faster */
02592                     if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
02593 
02594                     distance = normalize_v3(def);
02595                     if (distance < compare ){
02596                         /* exclude body points attached with a spring */
02597                         attached = 0;
02598                         for(b=obp->nofsprings;b>0;b--){
02599                             bs = sb->bspring + obp->springs[b-1];
02600                             if (( sb->totpoint-a == bs->v2)  || ( sb->totpoint-a == bs->v1)){
02601                                 attached=1;
02602                                 continue;}
02603                         }
02604                         if (!attached){
02605                             float f = tune/(distance) + tune/(compare*compare)*distance - 2.0f*tune/compare ;
02606 
02607                             mid_v3_v3v3(velcenter, bp->vec, obp->vec);
02608                             sub_v3_v3v3(dvel,velcenter,bp->vec);
02609                             mul_v3_fl(dvel,_final_mass(ob,bp));
02610 
02611                             Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def);
02612                             Vec3PlusStVec(bp->force,sb->balldamp,dvel);
02613 
02614                             if(nl_flags & NLF_BUILD){
02615                                 //int ia =3*(sb->totpoint-a);
02616                                 //int ic =3*(sb->totpoint-c);
02617                                 //int op =3*sb->totpoint;
02618                                 //float mvel = forcetime*sb->nodemass*sb->balldamp;
02619                                 //float mpos = forcetime*tune*(1.0f-sb->balldamp);
02620                                 /*some quick and dirty entries to the jacobian*/
02621                                 //dfdx_goal(ia,ia,op,mpos);
02622                                 //dfdv_goal(ia,ia,mvel);
02623                                 /* exploit force(a,b) == -force(b,a) part1/2 */
02624                                 //dfdx_goal(ic,ic,op,mpos);
02625                                 //dfdv_goal(ic,ic,mvel);
02626 
02627 
02628                                 /*TODO sit down an X-out the true jacobian entries*/
02629                                 /*well does not make to much sense because the eigenvalues
02630                                 of the jacobian go negative; and negative eigenvalues
02631                                 on a complex iterative system z(n+1)=A * z(n)
02632                                 give imaginary roots in the charcateristic polynom
02633                                 --> solutions that to z(t)=u(t)* exp ( i omega t) --> oscilations we don't want here
02634                                 where u(t) is a unknown amplitude function (worst case rising fast)
02635                                 */
02636                             }
02637 
02638                             /* exploit force(a,b) == -force(b,a) part2/2 */
02639                             sub_v3_v3v3(dvel,velcenter,obp->vec);
02640                             mul_v3_fl(dvel,(_final_mass(ob,bp)+_final_mass(ob,obp))/2.0f);
02641 
02642                             Vec3PlusStVec(obp->force,sb->balldamp,dvel);
02643                             Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def);
02644 
02645 
02646                         }
02647                     }
02648                 }
02649             }
02650             /* naive ball self collision done */
02651 
02652             if(_final_goal(ob,bp) < SOFTGOALSNAP){ /* ommit this bp when it snaps */
02653                 float auxvect[3];
02654                 float velgoal[3];
02655 
02656                 /* do goal stuff */
02657                 if(ob->softflag & OB_SB_GOAL) {
02658                     /* true elastic goal */
02659                     sub_v3_v3v3(auxvect,bp->pos,bp->origT);
02660                     ks  = 1.0f/(1.0f- _final_goal(ob,bp)*sb->goalspring)-1.0f ;
02661                     bp->force[0]+= -ks*(auxvect[0]);
02662                     bp->force[1]+= -ks*(auxvect[1]);
02663                     bp->force[2]+= -ks*(auxvect[2]);
02664 
02665                     if(nl_flags & NLF_BUILD){
02666                         //int ia =3*(sb->totpoint-a);
02667                         //int op =3*(sb->totpoint);
02668                         /* depending on my pos */
02669                         //dfdx_goal(ia,ia,op,ks*forcetime);
02670                     }
02671 
02672 
02673                     /* calulate damping forces generated by goals*/
02674                     sub_v3_v3v3(velgoal,bp->origS, bp->origE);
02675                     kd =  sb->goalfrict * sb_fric_force_scale(ob) ;
02676                     add_v3_v3v3(auxvect,velgoal,bp->vec);
02677 
02678                     if (forcetime > 0.0f) { /* make sure friction does not become rocket motor on time reversal */
02679                         bp->force[0]-= kd * (auxvect[0]);
02680                         bp->force[1]-= kd * (auxvect[1]);
02681                         bp->force[2]-= kd * (auxvect[2]);
02682                         if(nl_flags & NLF_BUILD){
02683                             //int ia =3*(sb->totpoint-a);
02684                             normalize_v3(auxvect);
02685                             /* depending on my vel */
02686                             //dfdv_goal(ia,ia,kd*forcetime);
02687                         }
02688 
02689                     }
02690                     else {
02691                         bp->force[0]-= kd * (velgoal[0] - bp->vec[0]);
02692                         bp->force[1]-= kd * (velgoal[1] - bp->vec[1]);
02693                         bp->force[2]-= kd * (velgoal[2] - bp->vec[2]);
02694                     }
02695                 }
02696                 /* done goal stuff */
02697 
02698 
02699                 /* gravitation */
02700                 madd_v3_v3fl(bp->force, gravity, _final_mass(ob,bp)); /* individual mass of node here */
02701 
02702 
02703                 /* particle field & vortex */
02704                 if(do_effector) {
02705                     EffectedPoint epoint;
02706                     float force[3]= {0.0f, 0.0f, 0.0f};
02707                     float speed[3]= {0.0f, 0.0f, 0.0f};
02708                     float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */
02709                     pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint-bp, &epoint);
02710                     pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed);
02711 
02712                     /* apply forcefield*/
02713                     mul_v3_fl(force,fieldfactor* eval_sb_fric_force_scale);
02714                     add_v3_v3(bp->force, force);
02715 
02716                     /* BP friction in moving media */
02717                     kd= sb->mediafrict* eval_sb_fric_force_scale;
02718                     bp->force[0] -= kd * (bp->vec[0] + windfactor*speed[0]/eval_sb_fric_force_scale);
02719                     bp->force[1] -= kd * (bp->vec[1] + windfactor*speed[1]/eval_sb_fric_force_scale);
02720                     bp->force[2] -= kd * (bp->vec[2] + windfactor*speed[2]/eval_sb_fric_force_scale);
02721                     /* now we'll have nice centrifugal effect for vortex */
02722 
02723                 }
02724                 else {
02725                     /* BP friction in media (not) moving*/
02726                     kd= sb->mediafrict* sb_fric_force_scale(ob);
02727                     /* assume it to be proportional to actual velocity */
02728                     bp->force[0]-= bp->vec[0]*kd;
02729                     bp->force[1]-= bp->vec[1]*kd;
02730                     bp->force[2]-= bp->vec[2]*kd;
02731                     /* friction in media done */
02732                     if(nl_flags & NLF_BUILD){
02733                         //int ia =3*(sb->totpoint-a);
02734                         /* da/dv =  */
02735 
02736                         //                  nlMatrixAdd(ia,ia,forcetime*kd);
02737                         //                  nlMatrixAdd(ia+1,ia+1,forcetime*kd);
02738                         //                  nlMatrixAdd(ia+2,ia+2,forcetime*kd);
02739                     }
02740 
02741                 }
02742                 /* +++cached collision targets */
02743                 bp->choke = 0.0f;
02744                 bp->choke2 = 0.0f;
02745                 bp->loc_flag &= ~SBF_DOFUZZY;
02746                 if(do_deflector) {
02747                     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;
02748                     kd = 1.0f;
02749 
02750                     if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){
02751                         if ((!nl_flags)&&(intrusion < 0.0f)){
02752                             if(G.rt & 0x01){ // 17 we did check for bit 0x10 before
02753                                 /*fixing bug [17428] this forces adaptive step size to tiny steps
02754                                 in some situations .. keeping G.rt==17 option for old files 'needing' the bug
02755                                 */
02756                                 /*bjornmose:  uugh.. what an evil hack
02757                                 violation of the 'don't touch bp->pos in here' rule
02758                                 but works nice, like this-->
02759                                 we predict the solution beeing out of the collider
02760                                 in heun step No1 and leave the heun step No2 adapt to it
02761                                 so we kind of introduced a implicit solver for this case
02762                                 */
02763                                 Vec3PlusStVec(bp->pos,-intrusion,facenormal);
02764                             }
02765                             else{
02766 
02767                                 sub_v3_v3v3(cfforce,bp->vec,vel);
02768                                 Vec3PlusStVec(bp->force,-cf*50.0f,cfforce);
02769                             }
02770 
02771 
02772                             sb->scratch->flag |= SBF_DOFUZZY;
02773                             bp->loc_flag |= SBF_DOFUZZY;
02774                             bp->choke = sb->choke*0.01f;
02775                         }
02776                         else{
02777                             sub_v3_v3v3(cfforce,bp->vec,vel);
02778                             Vec3PlusStVec(bp->force,-cf*50.0f,cfforce);
02779                         }
02780                         Vec3PlusStVec(bp->force,kd,defforce);
02781                         if (nl_flags & NLF_BUILD){
02782                             // int ia =3*(sb->totpoint-a);
02783                             // int op =3*sb->totpoint;
02784                             //dfdx_goal(ia,ia,op,mpos); // don't do unless you know
02785                             //dfdv_goal(ia,ia,-cf);
02786 
02787                         }
02788 
02789                     }
02790 
02791                 }
02792                 /* ---cached collision targets */
02793 
02794                 /* +++springs */
02795                 if(ob->softflag & OB_SB_EDGES) {
02796                     if (sb->bspring){ /* spring list exists at all ? */
02797                         for(b=bp->nofsprings;b>0;b--){
02798                             bs = sb->bspring + bp->springs[b-1];
02799                             if (do_springcollision || do_aero){
02800                                 add_v3_v3(bp->force, bs->ext_force);
02801                                 if (bs->flag & BSF_INTERSECT)
02802                                     bp->choke = bs->cf;
02803 
02804                             }
02805                             // sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags)
02806                             // rather remove nl_falgs from code .. will make things a lot cleaner
02807                             sb_spring_force(ob,sb->totpoint-a,bs,iks,forcetime,0);
02808                         }/* loop springs */
02809                     }/* existing spring list */
02810                 }/*any edges*/
02811                 /* ---springs */
02812             }/*omit on snap */
02813         }/*loop all bp's*/
02814 
02815 
02816         /* finally add forces caused by face collision */
02817         if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow);
02818 
02819         /* finish matrix and solve */
02820 #if (0) // remove onl linking for now .. still i am not sure .. the jacobian can be useful .. so keep that BM
02821         if(nl_flags & NLF_SOLVE){
02822             //double sct,sst=PIL_check_seconds_timer();
02823             for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
02824                 int iv =3*(sb->totpoint-a);
02825                 int ip =3*(2*sb->totpoint-a);
02826                 int n;
02827                 for (n=0;n<3;n++) {nlRightHandSideSet(0, iv+n, bp->force[0+n]);}
02828                 for (n=0;n<3;n++) {nlRightHandSideSet(0, ip+n, bp->vec[0+n]);}
02829             }
02830             nlEnd(NL_MATRIX);
02831             nlEnd(NL_SYSTEM);
02832 
02833             if ((G.rt == 32) && (nl_flags & NLF_BUILD))
02834             {
02835                 printf("####MEE#####\n");
02836                 nlPrintMatrix();
02837             }
02838 
02839             success= nlSolveAdvanced(NULL, 1);
02840 
02841             // nlPrintMatrix(); /* for debug purpose .. anyhow cropping B vector looks like working */
02842             if(success){
02843                 float f;
02844                 int index =0;
02845                 /* for debug purpose .. anyhow cropping B vector looks like working */
02846                 if (G.rt ==32)
02847                     for(a=2*sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
02848                         f=nlGetVariable(0,index);
02849                         printf("(%f ",f);index++;
02850                         f=nlGetVariable(0,index);
02851                         printf("%f ",f);index++;
02852                         f=nlGetVariable(0,index);
02853                         printf("%f)",f);index++;
02854                     }
02855 
02856                     index =0;
02857                     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
02858                         f=nlGetVariable(0,index);
02859                         bp->impdv[0] = f; index++;
02860                         f=nlGetVariable(0,index);
02861                         bp->impdv[1] = f; index++;
02862                         f=nlGetVariable(0,index);
02863                         bp->impdv[2] = f; index++;
02864                     }
02865                     /*
02866                     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
02867                     f=nlGetVariable(0,index);
02868                     bp->impdx[0] = f; index++;
02869                     f=nlGetVariable(0,index);
02870                     bp->impdx[1] = f; index++;
02871                     f=nlGetVariable(0,index);
02872                     bp->impdx[2] = f; index++;
02873                     }
02874                     */
02875             }
02876             else{
02877                 printf("Matrix inversion failed \n");
02878                 for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
02879                     copy_v3_v3(bp->impdv,bp->force);
02880                 }
02881 
02882             }
02883 
02884             //sct=PIL_check_seconds_timer();
02885             //if (sct-sst > 0.01f) printf(" implicit solver time %f %s \r",sct-sst,ob->id.name);
02886         }
02887         /* cleanup */
02888 #endif
02889         pdEndEffectors(&do_effector);
02890     }
02891 }
02892 
02893 static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err, int mid_flags)
02894 {
02895     /* time evolution */
02896     /* actually does an explicit euler step mode == 0 */
02897     /* or heun ~ 2nd order runge-kutta steps, mode 1,2 */
02898     SoftBody *sb= ob->soft; /* is supposed to be there */
02899     BodyPoint *bp;
02900     float dx[3]={0},dv[3],aabbmin[3],aabbmax[3],cm[3]={0.0f,0.0f,0.0f};
02901     float timeovermass/*,freezeloc=0.00001f,freezeforce=0.00000000001f*/;
02902     float maxerrpos= 0.0f,maxerrvel = 0.0f;
02903     int a,fuzzy=0;
02904 
02905     forcetime *= sb_time_scale(ob);
02906 
02907     aabbmin[0]=aabbmin[1]=aabbmin[2] = 1e20f;
02908     aabbmax[0]=aabbmax[1]=aabbmax[2] = -1e20f;
02909 
02910     /* old one with homogenous masses  */
02911     /* claim a minimum mass for vertex */
02912     /*
02913     if (sb->nodemass > 0.009999f) timeovermass = forcetime/sb->nodemass;
02914     else timeovermass = forcetime/0.009999f;
02915     */
02916 
02917     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
02918 /* now we have individual masses   */
02919 /* claim a minimum mass for vertex */
02920         if (_final_mass(ob,bp) > 0.009999f) timeovermass = forcetime/_final_mass(ob,bp);
02921         else timeovermass = forcetime/0.009999f;
02922 
02923 
02924         if(_final_goal(ob,bp) < SOFTGOALSNAP){
02925             /* this makes t~ = t */
02926             if(mid_flags & MID_PRESERVE) copy_v3_v3(dx,bp->vec);
02927 
02928             /* so here is (v)' = a(cceleration) = sum(F_springs)/m + gravitation + some friction forces  + more forces*/
02929             /* the ( ... )' operator denotes derivate respective time */
02930             /* the euler step for velocity then becomes */
02931             /* v(t + dt) = v(t) + a(t) * dt */
02932             mul_v3_fl(bp->force,timeovermass);/* individual mass of node here */
02933             /* some nasty if's to have heun in here too */
02934             copy_v3_v3(dv,bp->force);
02935 
02936             if (mode == 1){
02937                 copy_v3_v3(bp->prevvec, bp->vec);
02938                 copy_v3_v3(bp->prevdv, dv);
02939             }
02940 
02941             if (mode ==2){
02942                 /* be optimistic and execute step */
02943                 bp->vec[0] = bp->prevvec[0] + 0.5f * (dv[0] + bp->prevdv[0]);
02944                 bp->vec[1] = bp->prevvec[1] + 0.5f * (dv[1] + bp->prevdv[1]);
02945                 bp->vec[2] = bp->prevvec[2] + 0.5f * (dv[2] + bp->prevdv[2]);
02946                 /* compare euler to heun to estimate error for step sizing */
02947                 maxerrvel = MAX2(maxerrvel,ABS(dv[0] - bp->prevdv[0]));
02948                 maxerrvel = MAX2(maxerrvel,ABS(dv[1] - bp->prevdv[1]));
02949                 maxerrvel = MAX2(maxerrvel,ABS(dv[2] - bp->prevdv[2]));
02950             }
02951             else { add_v3_v3(bp->vec, bp->force); }
02952 
02953             /* this makes t~ = t+dt */
02954             if(!(mid_flags & MID_PRESERVE)) copy_v3_v3(dx,bp->vec);
02955 
02956             /* so here is (x)'= v(elocity) */
02957             /* the euler step for location then becomes */
02958             /* x(t + dt) = x(t) + v(t~) * dt */
02959             mul_v3_fl(dx,forcetime);
02960 
02961             /* the freezer coming sooner or later */
02962             /*
02963             if  ((dot_v3v3(dx,dx)<freezeloc )&&(dot_v3v3(bp->force,bp->force)<freezeforce )){
02964                 bp->frozen /=2;
02965             }
02966             else{
02967                 bp->frozen =MIN2(bp->frozen*1.05f,1.0f);
02968             }
02969             mul_v3_fl(dx,bp->frozen);
02970             */
02971             /* again some nasty if's to have heun in here too */
02972             if (mode ==1){
02973                 copy_v3_v3(bp->prevpos,bp->pos);
02974                 copy_v3_v3(bp->prevdx ,dx);
02975             }
02976 
02977             if (mode ==2){
02978                 bp->pos[0] = bp->prevpos[0] + 0.5f * ( dx[0] + bp->prevdx[0]);
02979                 bp->pos[1] = bp->prevpos[1] + 0.5f * ( dx[1] + bp->prevdx[1]);
02980                 bp->pos[2] = bp->prevpos[2] + 0.5f * ( dx[2] + bp->prevdx[2]);
02981                 maxerrpos = MAX2(maxerrpos,ABS(dx[0] - bp->prevdx[0]));
02982                 maxerrpos = MAX2(maxerrpos,ABS(dx[1] - bp->prevdx[1]));
02983                 maxerrpos = MAX2(maxerrpos,ABS(dx[2] - bp->prevdx[2]));
02984 
02985 /* bp->choke is set when we need to pull a vertex or edge out of the collider.
02986    the collider object signals to get out by pushing hard. on the other hand
02987    we don't want to end up in deep space so we add some <viscosity>
02988    to balance that out */
02989                 if (bp->choke2 > 0.0f){
02990                     mul_v3_fl(bp->vec,(1.0f - bp->choke2));
02991                 }
02992                 if (bp->choke > 0.0f){
02993                     mul_v3_fl(bp->vec,(1.0f - bp->choke));
02994                 }
02995 
02996             }
02997             else { add_v3_v3(bp->pos, dx);}
02998         }/*snap*/
02999         /* so while we are looping BPs anyway do statistics on the fly */
03000         aabbmin[0] = MIN2(aabbmin[0],bp->pos[0]);
03001         aabbmin[1] = MIN2(aabbmin[1],bp->pos[1]);
03002         aabbmin[2] = MIN2(aabbmin[2],bp->pos[2]);
03003         aabbmax[0] = MAX2(aabbmax[0],bp->pos[0]);
03004         aabbmax[1] = MAX2(aabbmax[1],bp->pos[1]);
03005         aabbmax[2] = MAX2(aabbmax[2],bp->pos[2]);
03006         if (bp->loc_flag & SBF_DOFUZZY) fuzzy =1;
03007     } /*for*/
03008 
03009     if (sb->totpoint) mul_v3_fl(cm,1.0f/sb->totpoint);
03010     if (sb->scratch){
03011         copy_v3_v3(sb->scratch->aabbmin,aabbmin);
03012         copy_v3_v3(sb->scratch->aabbmax,aabbmax);
03013     }
03014 
03015     if (err){ /* so step size will be controlled by biggest difference in slope */
03016         if (sb->solverflags & SBSO_OLDERR)
03017         *err = MAX2(maxerrpos,maxerrvel);
03018         else
03019         *err = maxerrpos;
03020         //printf("EP %f EV %f \n",maxerrpos,maxerrvel);
03021         if (fuzzy){
03022             *err /= sb->fuzzyness;
03023         }
03024     }
03025 }
03026 
03027 /* used by heun when it overshoots */
03028 static void softbody_restore_prev_step(Object *ob)
03029 {
03030     SoftBody *sb= ob->soft; /* is supposed to be there*/
03031     BodyPoint *bp;
03032     int a;
03033 
03034     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
03035         copy_v3_v3(bp->vec, bp->prevvec);
03036         copy_v3_v3(bp->pos, bp->prevpos);
03037     }
03038 }
03039 
03040 #if 0
03041 static void softbody_store_step(Object *ob)
03042 {
03043     SoftBody *sb= ob->soft; /* is supposed to be there*/
03044     BodyPoint *bp;
03045     int a;
03046 
03047     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
03048         copy_v3_v3(bp->prevvec,bp->vec);
03049         copy_v3_v3(bp->prevpos,bp->pos);
03050     }
03051 }
03052 
03053 
03054 /* used by predictors and correctors */
03055 static void softbody_store_state(Object *ob,float *ppos,float *pvel)
03056 {
03057     SoftBody *sb= ob->soft; /* is supposed to be there*/
03058     BodyPoint *bp;
03059     int a;
03060     float *pp=ppos,*pv=pvel;
03061 
03062     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
03063 
03064         copy_v3_v3(pv, bp->vec);
03065         pv+=3;
03066 
03067         copy_v3_v3(pp, bp->pos);
03068         pp+=3;
03069     }
03070 }
03071 
03072 /* used by predictors and correctors */
03073 static void softbody_retrieve_state(Object *ob,float *ppos,float *pvel)
03074 {
03075     SoftBody *sb= ob->soft; /* is supposed to be there*/
03076     BodyPoint *bp;
03077     int a;
03078     float *pp=ppos,*pv=pvel;
03079 
03080     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
03081 
03082         copy_v3_v3(bp->vec,pv);
03083         pv+=3;
03084 
03085         copy_v3_v3(bp->pos,pp);
03086         pp+=3;
03087     }
03088 }
03089 
03090 /* used by predictors and correctors */
03091 static void softbody_swap_state(Object *ob,float *ppos,float *pvel)
03092 {
03093     SoftBody *sb= ob->soft; /* is supposed to be there*/
03094     BodyPoint *bp;
03095     int a;
03096     float *pp=ppos,*pv=pvel;
03097     float temp[3];
03098 
03099     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
03100 
03101         copy_v3_v3(temp, bp->vec);
03102         copy_v3_v3(bp->vec,pv);
03103         copy_v3_v3(pv,temp);
03104         pv+=3;
03105 
03106         copy_v3_v3(temp, bp->pos);
03107         copy_v3_v3(bp->pos,pp);
03108         copy_v3_v3(pp,temp);
03109         pp+=3;
03110     }
03111 }
03112 #endif
03113 
03114 
03115 /* care for bodypoints taken out of the 'ordinary' solver step
03116 ** because they are screwed to goal by bolts
03117 ** they just need to move along with the goal in time
03118 ** we need to adjust them on sub frame timing in solver
03119 ** so now when frame is done .. put 'em to the position at the end of frame
03120 */
03121 static void softbody_apply_goalsnap(Object *ob)
03122 {
03123     SoftBody *sb= ob->soft; /* is supposed to be there */
03124     BodyPoint *bp;
03125     int a;
03126 
03127     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
03128         if (_final_goal(ob,bp) >= SOFTGOALSNAP){
03129             copy_v3_v3(bp->prevpos,bp->pos);
03130             copy_v3_v3(bp->pos,bp->origT);
03131         }
03132     }
03133 }
03134 
03135 
03136 static void apply_spring_memory(Object *ob)
03137 {
03138     SoftBody *sb = ob->soft;
03139     BodySpring *bs;
03140     BodyPoint *bp1, *bp2;
03141     int a;
03142     float b,l,r;
03143 
03144     if (sb && sb->totspring){
03145         b = sb->plastic;
03146         for(a=0; a<sb->totspring; a++) {
03147             bs  = &sb->bspring[a];
03148             bp1 =&sb->bpoint[bs->v1];
03149             bp2 =&sb->bpoint[bs->v2];
03150             l = len_v3v3(bp1->pos,bp2->pos);
03151             r = bs->len/l;
03152             if (( r > 1.05f) || (r < 0.95f)){
03153             bs->len = ((100.0f - b) * bs->len  + b*l)/100.0f;
03154             }
03155         }
03156     }
03157 }
03158 
03159 /* expects full initialized softbody */
03160 static void interpolate_exciter(Object *ob, int timescale, int time)
03161 {
03162     SoftBody *sb= ob->soft;
03163     BodyPoint *bp;
03164     float f;
03165     int a;
03166 
03167     f = (float)time/(float)timescale;
03168 
03169     for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
03170         bp->origT[0] = bp->origS[0] + f*(bp->origE[0] - bp->origS[0]);
03171         bp->origT[1] = bp->origS[1] + f*(bp->origE[1] - bp->origS[1]);
03172         bp->origT[2] = bp->origS[2] + f*(bp->origE[2] - bp->origS[2]);
03173         if (_final_goal(ob,bp) >= SOFTGOALSNAP){
03174             bp->vec[0] = bp->origE[0] - bp->origS[0];
03175             bp->vec[1] = bp->origE[1] - bp->origS[1];
03176             bp->vec[2] = bp->origE[2] - bp->origS[2];
03177         }
03178     }
03179 
03180 }
03181 
03182 
03183 /* ************ convertors ********** */
03184 
03185 /*  for each object type we need;
03186     - xxxx_to_softbody(Object *ob)      : a full (new) copy, creates SB geometry
03187 */
03188 
03189 static void get_scalar_from_vertexgroup(Object *ob, int vertID, short groupindex, float *target)
03190 /* result 0 on success, else indicates error number
03191 -- kind of *inverse* result defintion,
03192 -- but this way we can signal error condition to caller
03193 -- and yes this function must not be here but in a *vertex group module*
03194 */
03195 {
03196     MDeformVert *dv= NULL;
03197     int i;
03198 
03199     /* spot the vert in deform vert list at mesh */
03200     if(ob->type==OB_MESH) {
03201         Mesh *me= ob->data;
03202         if (me->dvert)
03203             dv = me->dvert + vertID;
03204     }
03205     else if(ob->type==OB_LATTICE) { /* not yet supported in softbody btw */
03206         Lattice *lt= ob->data;
03207         if (lt->dvert)
03208             dv = lt->dvert + vertID;
03209     }
03210     if(dv) {
03211         /* Lets see if this vert is in the weight group */
03212         for (i=0; i<dv->totweight; i++){
03213             if (dv->dw[i].def_nr == groupindex){
03214                 *target= dv->dw[i].weight; /* got it ! */
03215                 break;
03216             }
03217         }
03218     }
03219 }
03220 
03221 /* Resetting a Mesh SB object's springs */
03222 /* Spring length are caculted from'raw' mesh vertices that are NOT altered by modifier stack. */
03223 static void springs_from_mesh(Object *ob)
03224 {
03225     SoftBody *sb;
03226     Mesh *me= ob->data;
03227     BodyPoint *bp;
03228     int a;
03229     float scale =1.0f;
03230 
03231     sb= ob->soft;
03232     if (me && sb)
03233     {
03234     /* using bp->origS as a container for spring calcualtions here
03235     ** will be overwritten sbObjectStep() to receive
03236     ** actual modifier stack positions
03237     */
03238         if(me->totvert) {
03239             bp= ob->soft->bpoint;
03240             for(a=0; a<me->totvert; a++, bp++) {
03241                 copy_v3_v3(bp->origS, me->mvert[a].co);
03242                 mul_m4_v3(ob->obmat, bp->origS);
03243             }
03244 
03245         }
03246         /* recalculate spring length for meshes here */
03247         /* public version shrink to fit */
03248         if (sb->springpreload != 0 ){
03249             scale = sb->springpreload / 100.0f;
03250         }
03251         for(a=0; a<sb->totspring; a++) {
03252             BodySpring *bs = &sb->bspring[a];
03253             bs->len= scale*len_v3v3(sb->bpoint[bs->v1].origS, sb->bpoint[bs->v2].origS);
03254         }
03255     }
03256 }
03257 
03258 
03259 
03260 
03261 /* makes totally fresh start situation */
03262 static void mesh_to_softbody(Scene *scene, Object *ob)
03263 {
03264     SoftBody *sb;
03265     Mesh *me= ob->data;
03266     MEdge *medge= me->medge;
03267     BodyPoint *bp;
03268     BodySpring *bs;
03269     int a, totedge;
03270     if (ob->softflag & OB_SB_EDGES) totedge= me->totedge;
03271     else totedge= 0;
03272 
03273     /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
03274     renew_softbody(scene, ob, me->totvert, totedge);
03275 
03276     /* we always make body points */
03277     sb= ob->soft;
03278     bp= sb->bpoint;
03279 
03280     for(a=0; a<me->totvert; a++, bp++) {
03281         /* get scalar values needed  *per vertex* from vertex group functions,
03282         so we can *paint* them nicly ..
03283         they are normalized [0.0..1.0] so may be we need amplitude for scale
03284         which can be done by caller but still .. i'd like it to go this way
03285         */
03286 
03287         if((ob->softflag & OB_SB_GOAL) && sb->vertgroup) { /* even this is a deprecated evil hack */
03288            /* I'd like to have it  .. if (sb->namedVG_Goal[0]) */
03289 
03290             get_scalar_from_vertexgroup(ob, a,(short) (sb->vertgroup-1), &bp->goal);
03291             /* do this always, regardless successfull read from vertex group */
03292             /* this is where '2.5 every thing is animateable' goes wrong in the first place jow_go_for2_5 */
03293             /* 1st coding action to take : move this to frame level */
03294             /* reads: leave the bp->goal as it was read from vertex group / or default .. we will need it at per frame call */
03295             /* should be fixed for meshes */
03296             // bp->goal= sb->mingoal + bp->goal*goalfac; /* do not do here jow_go_for2_5 */
03297         }
03298         else{
03299             /* in consequence if no group was set .. but we want to animate it laters */
03300             /* logically attach to goal with default first */
03301             if(ob->softflag & OB_SB_GOAL){bp->goal =sb->defgoal;}
03302         }
03303 
03304         /* to proove the concept
03305         this enables per vertex *mass painting*
03306         */
03307 
03308         if (sb->namedVG_Mass[0])
03309         {
03310             int grp= defgroup_name_index (ob,sb->namedVG_Mass);
03311             /* printf("VGN  %s %d \n",sb->namedVG_Mass,grp); */
03312             if(grp > -1){
03313                 get_scalar_from_vertexgroup(ob, a,(short) (grp), &bp->mass);
03314                 /* 2.5  bp->mass = bp->mass * sb->nodemass; */
03315                 /* printf("bp->mass  %f \n",bp->mass); */
03316 
03317             }
03318         }
03319         /* first set the default */
03320         bp->springweight = 1.0f;
03321 
03322         if (sb->namedVG_Spring_K[0])
03323         {
03324             int grp= defgroup_name_index (ob,sb->namedVG_Spring_K);
03325             //printf("VGN  %s %d \n",sb->namedVG_Spring_K,grp);
03326             if(grp > -1){
03327                 get_scalar_from_vertexgroup(ob, a,(short) (grp), &bp->springweight);
03328                 //printf("bp->springweight  %f \n",bp->springweight);
03329 
03330             }
03331         }
03332 
03333 
03334     }
03335 
03336     /* but we only optionally add body edge springs */
03337     if (ob->softflag & OB_SB_EDGES) {
03338         if(medge) {
03339             bs= sb->bspring;
03340             for(a=me->totedge; a>0; a--, medge++, bs++) {
03341                 bs->v1= medge->v1;
03342                 bs->v2= medge->v2;
03343                 bs->springtype=SB_EDGE;
03344             }
03345 
03346 
03347             /* insert *diagonal* springs in quads if desired */
03348             if (ob->softflag & OB_SB_QUADS) {
03349                 add_mesh_quad_diag_springs(ob);
03350             }
03351 
03352             build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */
03353             /* insert *other second order* springs if desired */
03354             if (sb->secondspring > 0.0000001f) {
03355                 add_2nd_order_springs(ob,sb->secondspring); /* exploits the the first run of build_bps_springlist(ob);*/
03356                 build_bps_springlist(ob); /* yes we need to do it again*/
03357             }
03358             springs_from_mesh(ob); /* write the 'rest'-length of the springs */
03359             if (ob->softflag & OB_SB_SELF) {calculate_collision_balls(ob);}
03360 
03361         }
03362 
03363     }
03364 
03365 }
03366 
03367 static void mesh_faces_to_scratch(Object *ob)
03368 {
03369     SoftBody *sb= ob->soft;
03370     Mesh *me= ob->data;
03371     MFace *mface;
03372     BodyFace *bodyface;
03373     int a;
03374     /* alloc and copy faces*/
03375 
03376     bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace)*me->totface,"SB_body_Faces");
03377     //memcpy(sb->scratch->mface,me->mface,sizeof(MFace)*me->totface);
03378     mface = me->mface;
03379     for(a=0; a<me->totface; a++, mface++, bodyface++) {
03380         bodyface->v1 = mface->v1;
03381         bodyface->v2 = mface->v2;
03382         bodyface->v3 = mface->v3;
03383         bodyface->v4 = mface->v4;
03384         bodyface->ext_force[0] = bodyface->ext_force[1] = bodyface->ext_force[2] = 0.0f;
03385         bodyface->flag =0;
03386     }
03387     sb->scratch->totface = me->totface;
03388 }
03389 static void reference_to_scratch(Object *ob)
03390 {
03391     SoftBody *sb= ob->soft;
03392     ReferenceVert *rp;
03393     BodyPoint     *bp;
03394     float accu_pos[3] ={0.f,0.f,0.f};
03395     float accu_mass = 0.f;
03396     int a;
03397 
03398     sb->scratch->Ref.ivert = MEM_mallocN(sizeof(ReferenceVert)*sb->totpoint,"SB_Reference");
03399     bp= ob->soft->bpoint;
03400     rp= sb->scratch->Ref.ivert;
03401     for(a=0; a<sb->totpoint; a++, rp++, bp++) {
03402         copy_v3_v3(rp->pos,bp->pos);
03403         add_v3_v3(accu_pos, bp->pos);
03404         accu_mass += _final_mass(ob,bp);
03405     }
03406     mul_v3_fl(accu_pos,1.0f/accu_mass);
03407     copy_v3_v3(sb->scratch->Ref.com,accu_pos);
03408     /* printf("reference_to_scratch \n"); */
03409 }
03410 
03411 /*
03412 helper function to get proper spring length
03413 when object is rescaled
03414 */
03415 static float globallen(float *v1,float *v2,Object *ob)
03416 {
03417     float p1[3],p2[3];
03418     copy_v3_v3(p1,v1);
03419     mul_m4_v3(ob->obmat, p1);
03420     copy_v3_v3(p2,v2);
03421     mul_m4_v3(ob->obmat, p2);
03422     return len_v3v3(p1,p2);
03423 }
03424 
03425 static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff,Object *ob)
03426 {
03427     BPoint *bp=lt->def, *bpu;
03428     int u, v, w, dv, dw, bpc=0, bpuc;
03429 
03430     dv= lt->pntsu;
03431     dw= dv*lt->pntsv;
03432 
03433     for(w=0; w<lt->pntsw; w++) {
03434 
03435         for(v=0; v<lt->pntsv; v++) {
03436 
03437             for(u=0, bpuc=0, bpu=NULL; u<lt->pntsu; u++, bp++, bpc++) {
03438 
03439                 if(w) {
03440                     bs->v1 = bpc;
03441                     bs->v2 = bpc-dw;
03442                     bs->springtype=SB_EDGE;
03443                     bs->len= globallen((bp-dw)->vec, bp->vec,ob);
03444                     bs++;
03445                 }
03446                 if(v) {
03447                     bs->v1 = bpc;
03448                     bs->v2 = bpc-dv;
03449                     bs->springtype=SB_EDGE;
03450                     bs->len= globallen((bp-dv)->vec, bp->vec,ob);
03451                     bs++;
03452                 }
03453                 if(u) {
03454                     bs->v1 = bpuc;
03455                     bs->v2 = bpc;
03456                     bs->springtype=SB_EDGE;
03457                     bs->len= globallen((bpu)->vec, bp->vec,ob);
03458                     bs++;
03459                 }
03460 
03461                 if (dostiff) {
03462 
03463                     if(w){
03464                         if( v && u ) {
03465                             bs->v1 = bpc;
03466                             bs->v2 = bpc-dw-dv-1;
03467                             bs->springtype=SB_BEND;
03468                             bs->len= globallen((bp-dw-dv-1)->vec, bp->vec,ob);
03469                             bs++;
03470                         }
03471                         if( (v < lt->pntsv-1) && (u != 0) ) {
03472                             bs->v1 = bpc;
03473                             bs->v2 = bpc-dw+dv-1;
03474                             bs->springtype=SB_BEND;
03475                             bs->len= globallen((bp-dw+dv-1)->vec, bp->vec,ob);
03476                             bs++;
03477                         }
03478                     }
03479 
03480                     if(w < lt->pntsw -1){
03481                         if( v && u ) {
03482                             bs->v1 = bpc;
03483                             bs->v2 = bpc+dw-dv-1;
03484                             bs->springtype=SB_BEND;
03485                             bs->len= globallen((bp+dw-dv-1)->vec, bp->vec,ob);
03486                             bs++;
03487                         }
03488                         if( (v < lt->pntsv-1) && (u != 0) ) {
03489                             bs->v1 = bpc;
03490                             bs->v2 = bpc+dw+dv-1;
03491                             bs->springtype=SB_BEND;
03492                              bs->len= globallen((bp+dw+dv-1)->vec, bp->vec,ob);
03493                             bs++;
03494                         }
03495                     }
03496                 }
03497                 bpu = bp;
03498                 bpuc = bpc;
03499             }
03500         }
03501     }
03502 }
03503 
03504 
03505 /* makes totally fresh start situation */
03506 static void lattice_to_softbody(Scene *scene, Object *ob)
03507 {
03508     Lattice *lt= ob->data;
03509     SoftBody *sb;
03510     int totvert, totspring = 0;
03511 
03512     totvert= lt->pntsu*lt->pntsv*lt->pntsw;
03513 
03514     if (ob->softflag & OB_SB_EDGES){
03515         totspring = ((lt->pntsu -1) * lt->pntsv
03516                   + (lt->pntsv -1) * lt->pntsu) * lt->pntsw
03517                   +lt->pntsu*lt->pntsv*(lt->pntsw -1);
03518         if (ob->softflag & OB_SB_QUADS){
03519             totspring += 4*(lt->pntsu -1) *  (lt->pntsv -1)  * (lt->pntsw-1);
03520         }
03521     }
03522 
03523 
03524     /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
03525     renew_softbody(scene, ob, totvert, totspring);
03526     sb= ob->soft;   /* can be created in renew_softbody() */
03527 
03528     /* weights from bpoints, same code used as for mesh vertices */
03529     /* if((ob->softflag & OB_SB_GOAL) && sb->vertgroup) { 2.4x one*/
03530     /* new! take the weights from lattice vertex anyhow */
03531     if(ob->softflag & OB_SB_GOAL){
03532         BodyPoint *bp= sb->bpoint;
03533         BPoint *bpnt= lt->def;
03534         /* jow_go_for2_5 */
03535         int a;
03536 
03537         for(a=0; a<totvert; a++, bp++, bpnt++) {
03538             bp->goal= bpnt->weight;
03539         }
03540     }
03541 
03542     /* create some helper edges to enable SB lattice to be useful at all */
03543     if (ob->softflag & OB_SB_EDGES){
03544         makelatticesprings(lt,ob->soft->bspring,ob->softflag & OB_SB_QUADS,ob);
03545         build_bps_springlist(ob); /* link bps to springs */
03546     }
03547 }
03548 
03549 /* makes totally fresh start situation */
03550 static void curve_surf_to_softbody(Scene *scene, Object *ob)
03551 {
03552     Curve *cu= ob->data;
03553     SoftBody *sb;
03554     BodyPoint *bp;
03555     BodySpring *bs;
03556     Nurb *nu;
03557     BezTriple *bezt;
03558     BPoint *bpnt;
03559     int a, curindex=0;
03560     int totvert, totspring = 0, setgoal=0;
03561 
03562     totvert= count_curveverts(&cu->nurb);
03563 
03564     if (ob->softflag & OB_SB_EDGES){
03565         if(ob->type==OB_CURVE) {
03566             totspring= totvert - BLI_countlist(&cu->nurb);
03567         }
03568     }
03569 
03570     /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
03571     renew_softbody(scene, ob, totvert, totspring);
03572     sb= ob->soft;   /* can be created in renew_softbody() */
03573 
03574     /* set vars now */
03575     bp= sb->bpoint;
03576     bs= sb->bspring;
03577 
03578     /* weights from bpoints, same code used as for mesh vertices */
03579     /* if((ob->softflag & OB_SB_GOAL) && sb->vertgroup) 2.4x hack*/
03580     /* new! take the weights from curve vertex anyhow */
03581     if(ob->softflag & OB_SB_GOAL)
03582         setgoal= 1;
03583 
03584     for(nu= cu->nurb.first; nu; nu= nu->next) {
03585         if(nu->bezt) {
03586             /* bezier case ; this is nicly said naive; who ever wrote this part, it was not me (JOW) :) */
03587             /* a: never ever make tangent handles (sub) and or (ob)ject to collision */
03588             /* b: rather calculate them using some C2 (C2= continous in second derivate -> no jump in bending ) condition */
03589             /* not too hard to do, but needs some more code to care for;  some one may want look at it  JOW 2010/06/12*/
03590             for(bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++, bp+=3, curindex+=3) {
03591                 if(setgoal) {
03592                     bp->goal= bezt->weight;
03593 
03594                     /* all three triples */
03595                     (bp+1)->goal= bp->goal;
03596                     (bp+2)->goal= bp->goal;
03597                     /*do not collide handles */
03598                     (bp+1)->loc_flag |= SBF_OUTOFCOLLISION;
03599                     (bp+2)->loc_flag |= SBF_OUTOFCOLLISION;
03600                 }
03601 
03602                 if(totspring) {
03603                     if(a>0) {
03604                         bs->v1= curindex-3;
03605                         bs->v2= curindex;
03606                         bs->springtype=SB_HANDLE;
03607                         bs->len= globallen( (bezt-1)->vec[0], bezt->vec[0], ob );
03608                         bs++;
03609                     }
03610                     bs->v1= curindex;
03611                     bs->v2= curindex+1;
03612                     bs->springtype=SB_HANDLE;
03613                     bs->len= globallen( bezt->vec[0], bezt->vec[1], ob );
03614                     bs++;
03615 
03616                     bs->v1= curindex+1;
03617                     bs->v2= curindex+2;
03618                     bs->springtype=SB_HANDLE;
03619                     bs->len= globallen( bezt->vec[1], bezt->vec[2], ob );
03620                     bs++;
03621                 }
03622             }
03623         }
03624         else {
03625             for(bpnt=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bpnt++, bp++, curindex++) {
03626                 if(setgoal) {
03627                     bp->goal= bpnt->weight;
03628                 }
03629                 if(totspring && a>0) {
03630                     bs->v1= curindex-1;
03631                     bs->v2= curindex;
03632                     bs->springtype=SB_EDGE;
03633                     bs->len= globallen( (bpnt-1)->vec, bpnt->vec , ob );
03634                     bs++;
03635                 }
03636             }
03637         }
03638     }
03639 
03640     if(totspring)
03641     {
03642         build_bps_springlist(ob); /* link bps to springs */
03643         if (ob->softflag & OB_SB_SELF) {calculate_collision_balls(ob);}
03644     }
03645 }
03646 
03647 /* copies softbody result back in object */
03648 static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, int local)
03649 {
03650     SoftBody *sb= ob->soft;
03651     if(sb){
03652         BodyPoint *bp= sb->bpoint;
03653         int a;
03654         if(sb->solverflags & SBSO_ESTIMATEIPO){SB_estimate_transform(ob,sb->lcom,sb->lrot,sb->lscale);}
03655         /* inverse matrix is not uptodate... */
03656         invert_m4_m4(ob->imat, ob->obmat);
03657 
03658         for(a=0; a<numVerts; a++, bp++) {
03659             copy_v3_v3(vertexCos[a], bp->pos);
03660             if(local==0)
03661                 mul_m4_v3(ob->imat, vertexCos[a]);  /* softbody is in global coords, baked optionally not */
03662         }
03663     }
03664 }
03665 
03666 /* +++ ************ maintaining scratch *************** */
03667 static void sb_new_scratch(SoftBody *sb)
03668 {
03669     if (!sb) return;
03670     sb->scratch = MEM_callocN(sizeof(SBScratch), "SBScratch");
03671     sb->scratch->colliderhash = BLI_ghash_new(BLI_ghashutil_ptrhash,BLI_ghashutil_ptrcmp, "sb_new_scratch gh");
03672     sb->scratch->bodyface = NULL;
03673     sb->scratch->totface = 0;
03674     sb->scratch->aabbmax[0]=sb->scratch->aabbmax[1]=sb->scratch->aabbmax[2] = 1.0e30f;
03675     sb->scratch->aabbmin[0]=sb->scratch->aabbmin[1]=sb->scratch->aabbmin[2] = -1.0e30f;
03676     sb->scratch->Ref.ivert = NULL;
03677 
03678 }
03679 /* --- ************ maintaining scratch *************** */
03680 
03681 /* ************ Object level, exported functions *************** */
03682 
03683 /* allocates and initializes general main data */
03684 SoftBody *sbNew(Scene *scene)
03685 {
03686     SoftBody *sb;
03687 
03688     sb= MEM_callocN(sizeof(SoftBody), "softbody");
03689 
03690     sb->mediafrict= 0.5f;
03691     sb->nodemass= 1.0f;
03692     sb->grav= 9.8f;
03693     sb->physics_speed= 1.0f;
03694     sb->rklimit= 0.1f;
03695 
03696     sb->goalspring= 0.5f;
03697     sb->goalfrict= 0.0f;
03698     sb->mingoal= 0.0f;
03699     sb->maxgoal= 1.0f;
03700     sb->defgoal= 0.7f;
03701 
03702     sb->inspring= 0.5f;
03703     sb->infrict= 0.5f;
03704     /*todo backward file compat should copy inspring to inpush while reading old files*/
03705     sb->inpush = 0.5f;
03706 
03707     sb->interval= 10;
03708     sb->sfra= scene->r.sfra;
03709     sb->efra= scene->r.efra;
03710 
03711     sb->colball  = 0.49f;
03712     sb->balldamp = 0.50f;
03713     sb->ballstiff= 1.0f;
03714     sb->sbc_mode = 1;
03715 
03716 
03717     sb->minloops = 10;
03718     sb->maxloops = 300;
03719 
03720     sb->choke = 3;
03721     sb_new_scratch(sb);
03722     /*todo backward file compat should set sb->shearstiff = 1.0f while reading old files*/
03723     sb->shearstiff = 1.0f;
03724     sb->solverflags |= SBSO_OLDERR;
03725 
03726     sb->pointcache = BKE_ptcache_add(&sb->ptcaches);
03727 
03728     if(!sb->effector_weights)
03729         sb->effector_weights = BKE_add_effector_weights(NULL);
03730 
03731     sb->last_frame= MINFRAME-1;
03732 
03733     return sb;
03734 }
03735 
03736 /* frees all */
03737 void sbFree(SoftBody *sb)
03738 {
03739     free_softbody_intern(sb);
03740     BKE_ptcache_free_list(&sb->ptcaches);
03741     sb->pointcache = NULL;
03742     if(sb->effector_weights)
03743         MEM_freeN(sb->effector_weights);
03744     MEM_freeN(sb);
03745 }
03746 
03747 void sbFreeSimulation(SoftBody *sb)
03748 {
03749     free_softbody_intern(sb);
03750 }
03751 
03752 /* makes totally fresh start situation */
03753 void sbObjectToSoftbody(Object *ob)
03754 {
03755     //ob->softflag |= OB_SB_REDO;
03756 
03757     free_softbody_intern(ob->soft);
03758 }
03759 
03760 static int object_has_edges(Object *ob)
03761 {
03762     if(ob->type==OB_MESH) {
03763         return ((Mesh*) ob->data)->totedge;
03764     }
03765     else if(ob->type==OB_LATTICE) {
03766         return 1;
03767     }
03768     else {
03769         return 0;
03770     }
03771 }
03772 
03773 /* SB global visible functions */
03774 void sbSetInterruptCallBack(int (*f)(void))
03775 {
03776     SB_localInterruptCallBack = f;
03777 }
03778 
03779 static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts)
03780 {
03781     BodyPoint *bp;
03782     int a;
03783 
03784     if(!sb || !sb->bpoint)
03785         return;
03786 
03787     for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
03788         /* store where goals are now */
03789         copy_v3_v3(bp->origS, bp->origE);
03790         /* copy the position of the goals at desired end time */
03791         copy_v3_v3(bp->origE, vertexCos[a]);
03792         /* vertexCos came from local world, go global */
03793         mul_m4_v3(ob->obmat, bp->origE);
03794         /* just to be save give bp->origT a defined value
03795         will be calulated in interpolate_exciter()*/
03796         copy_v3_v3(bp->origT, bp->origE);
03797     }
03798 }
03799 
03800 
03801 /* void SB_estimate_transform */
03802 /* input   Object *ob out (says any object that can do SB like mesh,lattice,curve )
03803    output  float lloc[3],float lrot[3][3],float lscale[3][3]
03804    that is:
03805    a precise position vector denoting the motion of the center of mass
03806    give a rotation/scale matrix using averaging method, that's why estimate and not calculate
03807    see: this is kind of reverse engeneering: having to states of a point cloud and recover what happend
03808    our advantage here we know the identity of the vertex
03809    there are others methods giving other results.
03810    lloc,lrot,lscale are allowed to be NULL, just in case you don't need it.
03811    should be pretty useful for pythoneers :)
03812    not! velocity .. 2nd order stuff
03813    vcloud_estimate_transform see
03814    */
03815 
03816 void SB_estimate_transform(Object *ob,float lloc[3],float lrot[3][3],float lscale[3][3])
03817 {
03818     BodyPoint *bp;
03819     ReferenceVert *rp;
03820     SoftBody *sb = NULL;
03821     float (*opos)[3];
03822     float (*rpos)[3];
03823     float com[3],rcom[3];
03824     int a;
03825 
03826     if(!ob ||!ob->soft) return; /* why did we get here ? */
03827     sb= ob->soft;
03828     if(!sb || !sb->bpoint) return;
03829     opos= MEM_callocN( (sb->totpoint)*3*sizeof(float), "SB_OPOS");
03830     rpos= MEM_callocN( (sb->totpoint)*3*sizeof(float), "SB_RPOS");
03831     /* might filter vertex selection with a vertex group */
03832     for(a=0, bp=sb->bpoint, rp=sb->scratch->Ref.ivert; a<sb->totpoint; a++, bp++, rp++) {
03833         copy_v3_v3(rpos[a],rp->pos);
03834         copy_v3_v3(opos[a],bp->pos);
03835     }
03836 
03837     vcloud_estimate_transform(sb->totpoint, opos, NULL, rpos, NULL, com, rcom,lrot,lscale);
03838     //sub_v3_v3(com,rcom);
03839     if (lloc) copy_v3_v3(lloc,com);
03840     copy_v3_v3(sb->lcom,com);
03841     if (lscale) copy_m3_m3(sb->lscale,lscale);
03842     if (lrot)   copy_m3_m3(sb->lrot,lrot);
03843 
03844 
03845     MEM_freeN(opos);
03846     MEM_freeN(rpos);
03847 }
03848 
03849 static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts)
03850 {
03851     BodyPoint *bp;
03852     int a;
03853 
03854     for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
03855         copy_v3_v3(bp->pos, vertexCos[a]);
03856         mul_m4_v3(ob->obmat, bp->pos);  /* yep, sofbody is global coords*/
03857         copy_v3_v3(bp->origS, bp->pos);
03858         copy_v3_v3(bp->origE, bp->pos);
03859         copy_v3_v3(bp->origT, bp->pos);
03860         bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0f;
03861 
03862         /* the bp->prev*'s are for rolling back from a canceled try to propagate in time
03863         adaptive step size algo in a nutshell:
03864         1.  set sheduled time step to new dtime
03865         2.  try to advance the sheduled time step, beeing optimistic execute it
03866         3.  check for success
03867         3.a we 're fine continue, may be we can increase sheduled time again ?? if so, do so!
03868         3.b we did exceed error limit --> roll back, shorten the sheduled time and try again at 2.
03869         4.  check if we did reach dtime
03870         4.a nope we need to do some more at 2.
03871         4.b yup we're done
03872         */
03873 
03874         copy_v3_v3(bp->prevpos, bp->pos);
03875         copy_v3_v3(bp->prevvec, bp->vec);
03876         copy_v3_v3(bp->prevdx, bp->vec);
03877         copy_v3_v3(bp->prevdv, bp->vec);
03878     }
03879 
03880     /* make a nice clean scratch struc */
03881     free_scratch(sb); /* clear if any */
03882     sb_new_scratch(sb); /* make a new */
03883     sb->scratch->needstobuildcollider=1;
03884     zero_v3(sb->lcom);
03885     unit_m3(sb->lrot);
03886     unit_m3(sb->lscale);
03887 
03888 
03889 
03890     /* copy some info to scratch */
03891             /* we only need that if we want to reconstruct IPO */
03892     if(1) {
03893         reference_to_scratch(ob);
03894         SB_estimate_transform(ob,NULL,NULL,NULL);
03895         SB_estimate_transform(ob,NULL,NULL,NULL);
03896     }
03897     switch(ob->type) {
03898     case OB_MESH:
03899         if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob);
03900         break;
03901     case OB_LATTICE:
03902         break;
03903     case OB_CURVE:
03904     case OB_SURF:
03905         break;
03906     default:
03907         break;
03908     }
03909 }
03910 
03911 static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
03912 {
03913     /* the simulator */
03914     float forcetime;
03915     double sct,sst;
03916 
03917 
03918     sst=PIL_check_seconds_timer();
03919     /* Integration back in time is possible in theory, but pretty useless here.
03920     So we refuse to do so. Since we do not know anything about 'outside' canges
03921     especially colliders we refuse to go more than 10 frames.
03922     */
03923     if(dtime < 0 || dtime > 10.5f) return;
03924 
03925     ccd_update_deflector_hash(scene, ob, sb->scratch->colliderhash);
03926 
03927     if(sb->scratch->needstobuildcollider){
03928         if (query_external_colliders(scene, ob)){
03929             ccd_build_deflector_hash(scene, ob, sb->scratch->colliderhash);
03930         }
03931         sb->scratch->needstobuildcollider=0;
03932     }
03933 
03934     if (sb->solver_ID < 2) {
03935         /* special case of 2nd order Runge-Kutta type AKA Heun */
03936         int mid_flags=0;
03937         float err = 0;
03938         float forcetimemax = 1.0f; /* set defaults guess we shall do one frame */
03939         float forcetimemin = 0.01f; /* set defaults guess 1/100 is tight enough */
03940         float timedone =0.0; /* how far did we get without violating error condition */
03941                              /* loops = counter for emergency brake
03942                              * we don't want to lock up the system if physics fail
03943         */
03944         int loops =0 ;
03945 
03946         SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */
03947         /* adjust loop limits */
03948         if (sb->minloops > 0) forcetimemax = dtime / sb->minloops;
03949         if (sb->maxloops > 0) forcetimemin = dtime / sb->maxloops;
03950 
03951         if(sb->solver_ID>0) mid_flags |= MID_PRESERVE;
03952 
03953         forcetime =forcetimemax; /* hope for integrating in one step */
03954         while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) )
03955         {
03956             /* set goals in time */
03957             interpolate_exciter(ob,200,(int)(200.0f*(timedone/dtime)));
03958 
03959             sb->scratch->flag &= ~SBF_DOFUZZY;
03960             /* do predictive euler step */
03961             softbody_calc_forces(scene, ob, forcetime,timedone/dtime,0);
03962 
03963             softbody_apply_forces(ob, forcetime, 1, NULL,mid_flags);
03964 
03965             /* crop new slope values to do averaged slope step */
03966             softbody_calc_forces(scene, ob, forcetime,timedone/dtime,0);
03967 
03968             softbody_apply_forces(ob, forcetime, 2, &err,mid_flags);
03969             softbody_apply_goalsnap(ob);
03970 
03971             if (err > SoftHeunTol) { /* error needs to be scaled to some quantity */
03972 
03973                 if (forcetime > forcetimemin){
03974                     forcetime = MAX2(forcetime / 2.0f,forcetimemin);
03975                     softbody_restore_prev_step(ob);
03976                     //printf("down,");
03977                 }
03978                 else {
03979                     timedone += forcetime;
03980                 }
03981             }
03982             else {
03983                 float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */
03984 
03985                 if (sb->scratch->flag & SBF_DOFUZZY){
03986                     //if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { /* stay with this stepsize unless err really small */
03987                     newtime = forcetime;
03988                     //}
03989                 }
03990                 else {
03991                     if (err > SoftHeunTol/2.0f) { /* stay with this stepsize unless err really small */
03992                         newtime = forcetime;
03993                     }
03994                 }
03995                 timedone += forcetime;
03996                 newtime=MIN2(forcetimemax,MAX2(newtime,forcetimemin));
03997                 //if (newtime > forcetime) printf("up,");
03998                 if (forcetime > 0.0f)
03999                     forcetime = MIN2(dtime - timedone,newtime);
04000                 else
04001                     forcetime = MAX2(dtime - timedone,newtime);
04002             }
04003             loops++;
04004             if(sb->solverflags & SBSO_MONITOR ){
04005                 sct=PIL_check_seconds_timer();
04006                 if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone/dtime);
04007             }
04008             /* ask for user break */
04009             if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break;
04010 
04011         }
04012         /* move snapped to final position */
04013         interpolate_exciter(ob, 2, 2);
04014         softbody_apply_goalsnap(ob);
04015 
04016         //              if(G.f & G_DEBUG){
04017         if(sb->solverflags & SBSO_MONITOR ){
04018             if (loops > HEUNWARNLIMIT) /* monitor high loop counts */
04019                 printf("\r needed %d steps/frame",loops);
04020         }
04021 
04022     }
04023     else if (sb->solver_ID == 2)
04024     {/* do semi "fake" implicit euler */
04025         //removed
04026     }/*SOLVER SELECT*/
04027     else if (sb->solver_ID == 4)
04028     {
04029         /* do semi "fake" implicit euler */
04030     }/*SOLVER SELECT*/
04031     else if (sb->solver_ID == 3){
04032         /* do "stupid" semi "fake" implicit euler */
04033         //removed
04034 
04035     }/*SOLVER SELECT*/
04036     else{
04037         printf("softbody no valid solver ID!");
04038     }/*SOLVER SELECT*/
04039     if(sb->plastic){ apply_spring_memory(ob);}
04040 
04041     if(sb->solverflags & SBSO_MONITOR ){
04042         sct=PIL_check_seconds_timer();
04043         if ((sct-sst > 0.5f) || (G.f & G_DEBUG)) printf(" solver time %f sec %s \n",sct-sst,ob->id.name);
04044     }
04045 }
04046 
04047 /* simulates one step. framenr is in frames */
04048 void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
04049 {
04050     SoftBody *sb= ob->soft;
04051     PointCache *cache;
04052     PTCacheID pid;
04053     float dtime, timescale;
04054     int framedelta, framenr, startframe, endframe;
04055     int cache_result;
04056 
04057     cache= sb->pointcache;
04058 
04059     framenr= (int)cfra;
04060     framedelta= framenr - cache->simframe;
04061 
04062     BKE_ptcache_id_from_softbody(&pid, ob, sb);
04063     BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
04064 
04065     /* check for changes in mesh, should only happen in case the mesh
04066      * structure changes during an animation */
04067     if(sb->bpoint && numVerts != sb->totpoint) {
04068         BKE_ptcache_invalidate(cache);
04069         return;
04070     }
04071 
04072     /* clamp frame ranges */
04073     if(framenr < startframe) {
04074         BKE_ptcache_invalidate(cache);
04075         return;
04076     }
04077     else if(framenr > endframe) {
04078         framenr = endframe;
04079     }
04080 
04081     /* verify if we need to create the softbody data */
04082     if(sb->bpoint == NULL ||
04083        ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) {
04084 
04085         switch(ob->type) {
04086             case OB_MESH:
04087                 mesh_to_softbody(scene, ob);
04088                 break;
04089             case OB_LATTICE:
04090                 lattice_to_softbody(scene, ob);
04091                 break;
04092             case OB_CURVE:
04093             case OB_SURF:
04094                 curve_surf_to_softbody(scene, ob);
04095                 break;
04096             default:
04097                 renew_softbody(scene, ob, numVerts, 0);
04098                 break;
04099         }
04100 
04101         softbody_update_positions(ob, sb, vertexCos, numVerts);
04102         softbody_reset(ob, sb, vertexCos, numVerts);
04103     }
04104 
04105     /* continue physics special case */
04106     if(BKE_ptcache_get_continue_physics()) {
04107         BKE_ptcache_invalidate(cache);
04108         /* do simulation */
04109         dtime = timescale;
04110         softbody_update_positions(ob, sb, vertexCos, numVerts);
04111         softbody_step(scene, ob, sb, dtime);
04112         softbody_to_object(ob, vertexCos, numVerts, 0);
04113         sb->last_frame = framenr;
04114         return;
04115     }
04116 
04117     /* still no points? go away */
04118     if(sb->totpoint==0) {
04119         return;
04120     }
04121     if(framenr == startframe) {
04122         BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
04123 
04124         /* first frame, no simulation to do, just set the positions */
04125         softbody_update_positions(ob, sb, vertexCos, numVerts);
04126 
04127         BKE_ptcache_validate(cache, framenr);
04128         cache->flag &= ~PTCACHE_REDO_NEEDED;
04129 
04130         sb->last_frame = framenr;
04131 
04132         return;
04133     }
04134 
04135     /* try to read from cache */
04136     cache_result = BKE_ptcache_read(&pid, framenr);
04137 
04138     if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
04139         softbody_to_object(ob, vertexCos, numVerts, sb->local);
04140 
04141         BKE_ptcache_validate(cache, framenr);
04142 
04143         if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
04144             BKE_ptcache_write(&pid, framenr);
04145 
04146         sb->last_frame = framenr;
04147 
04148         return;
04149     }
04150     else if(cache_result==PTCACHE_READ_OLD) {
04151         ; /* do nothing */
04152     }
04153     else if(/*ob->id.lib || */(cache->flag & PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */
04154         /* if baked and nothing in cache, do nothing */
04155         BKE_ptcache_invalidate(cache);
04156         return;
04157     }
04158 
04159     if(framenr!=sb->last_frame+1)
04160         return;
04161 
04162     /* if on second frame, write cache for first frame */
04163     if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
04164         BKE_ptcache_write(&pid, startframe);
04165 
04166     softbody_update_positions(ob, sb, vertexCos, numVerts);
04167 
04168     /* checking time: */
04169     dtime = framedelta*timescale;
04170 
04171     /* do simulation */
04172     softbody_step(scene, ob, sb, dtime);
04173 
04174     softbody_to_object(ob, vertexCos, numVerts, 0);
04175 
04176     BKE_ptcache_validate(cache, framenr);
04177     BKE_ptcache_write(&pid, framenr);
04178 
04179     sb->last_frame = framenr;
04180 }
04181