~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to source/blender/blenkernel/intern/softbody.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2005-11-06 12:40:03 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051106124003-3pgs7tcg5rox96xg
Tags: 2.37a-1.1
* Non-maintainer upload.
* Split out parts of 01_SConstruct_debian.dpatch again: root_build_dir
  really needs to get adjusted before the clean target runs - closes: #333958,
  see #288882 for reference

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  softbody.c      
 
2
 * 
 
3
 * $Id: 
 
4
 *
 
5
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License
 
9
 * as published by the Free Software Foundation; either version 2
 
10
 * of the License, or (at your option) any later version. The Blender
 
11
 * Foundation also sells licenses for use in proprietary software under
 
12
 * the Blender License.  See http://www.blender.org/BL/ for information
 
13
 * about this.
 
14
 *
 
15
 * This program is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program; if not, write to the Free Software Foundation,
 
22
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
23
 *
 
24
 * The Original Code is Copyright (C) Blender Foundation
 
25
 * All rights reserved.
 
26
 *
 
27
 * The Original Code is: all of this file.
 
28
 *
 
29
 * Contributor(s): none yet.
 
30
 *
 
31
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 
32
 */
 
33
 
 
34
/*
 
35
******
 
36
variables on the UI for now
 
37
 
 
38
        float mediafrict;  friction to env 
 
39
        float nodemass;   softbody mass of *vertex* 
 
40
        float grav;        softbody amount of gravitaion to apply 
 
41
        
 
42
        float goalspring;  softbody goal springs 
 
43
        float goalfrict;   softbody goal springs friction 
 
44
        float mingoal;     quick limits for goal 
 
45
        float maxgoal;
 
46
 
 
47
        float inspring;   softbody inner springs 
 
48
        float infrict;     softbody inner springs friction 
 
49
 
 
50
*****
 
51
*/
 
52
 
 
53
 
 
54
#include <math.h>
 
55
#include <stdlib.h>
 
56
#include <string.h>
 
57
 
 
58
#include "MEM_guardedalloc.h"
 
59
 
 
60
/* types */
 
61
#include "DNA_curve_types.h"
 
62
#include "DNA_object_types.h"
 
63
#include "DNA_object_force.h"   /* here is the softbody struct */
 
64
#include "DNA_key_types.h"
 
65
#include "DNA_mesh_types.h"
 
66
#include "DNA_meshdata_types.h"
 
67
#include "DNA_lattice_types.h"
 
68
#include "DNA_scene_types.h"
 
69
 
 
70
#include "BLI_blenlib.h"
 
71
#include "BLI_arithb.h"
 
72
 
 
73
#include "BKE_displist.h"
 
74
#include "BKE_effect.h"
 
75
#include "BKE_global.h"
 
76
#include "BKE_key.h"
 
77
#include "BKE_object.h"
 
78
#include "BKE_softbody.h"
 
79
#include "BKE_utildefines.h"
 
80
 
 
81
#include  "BIF_editdeform.h"
 
82
 
 
83
extern bDeformGroup *get_named_vertexgroup(Object *ob, char *name);
 
84
extern int  get_defgroup_num (Object *ob, bDeformGroup        *dg);
 
85
 
 
86
 
 
87
/* ********** soft body engine ******* */
 
88
#define SOFTGOALSNAP  0.999f 
 
89
// if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp
 
90
// removes *unnecessary* stiffnes from ODE system
 
91
#define HEUNWARNLIMIT 1 // 50 would be fine i think for detecting severe *stiff* stuff
 
92
 
 
93
 
 
94
float SoftHeunTol = 1.0f; // humm .. this should be calculated from sb parameters and sizes
 
95
 
 
96
/* local prototypes */
 
97
static void free_softbody_intern(SoftBody *sb);
 
98
 
 
99
 
 
100
/*+++ frame based timing +++*/
 
101
 
 
102
//physical unit of force is [kg * m / sec^2]
 
103
 
 
104
static float sb_grav_force_scale(Object *ob)
 
105
// since unit of g is [m/sec^2] and F = mass * g we rescale unit mass of node to 1 gramm
 
106
// put it to a function here, so we can add user options later without touching simulation code
 
107
{
 
108
        return (0.001f);
 
109
}
 
110
 
 
111
static float sb_fric_force_scale(Object *ob)
 
112
// rescaling unit of drag [1 / sec] to somehow reasonable
 
113
// put it to a function here, so we can add user options later without touching simulation code
 
114
{
 
115
        return (0.01f);
 
116
}
 
117
 
 
118
static float sb_time_scale(Object *ob)
 
119
// defining the frames to *real* time relation
 
120
{
 
121
        SoftBody *sb= ob->soft; // is supposed to be there
 
122
        if (sb){
 
123
                return(sb->physics_speed); //hrms .. this could be IPO as well :) 
 
124
                // estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
 
125
                // 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions]  has period 65 frames
 
126
        // theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM) 
 
127
        }
 
128
        return (1.0f);
 
129
        /* 
 
130
        this would be frames/sec independant timing assuming 25 fps is default
 
131
        but does not work very well with NLA
 
132
                return (25.0f/G.scene->r.frs_sec)
 
133
        */
 
134
}
 
135
/*--- frame based timing ---*/
 
136
 
 
137
 
 
138
static int count_mesh_quads(Mesh *me)
 
139
{
 
140
        int a,result = 0;
 
141
        MFace *mface= me->mface;
 
142
        
 
143
        if(mface) {
 
144
                for(a=me->totface; a>0; a--, mface++) {
 
145
                        if(mface->v4) result++;
 
146
                }
 
147
        }       
 
148
        return result;
 
149
}
 
150
 
 
151
static void add_mesh_quad_diag_springs(Object *ob)
 
152
{
 
153
        Mesh *me= ob->data;
 
154
        MFace *mface= me->mface;
 
155
        BodyPoint *bp;
 
156
        BodySpring *bs, *bs_new;
 
157
        int a ;
 
158
        
 
159
        if (ob->soft){
 
160
                int nofquads;
 
161
                
 
162
                nofquads = count_mesh_quads(me);
 
163
                if (nofquads) {
 
164
                        /* resize spring-array to hold additional quad springs */
 
165
                        bs_new= MEM_callocN( (ob->soft->totspring + nofquads *2 )*sizeof(BodySpring), "bodyspring");
 
166
                        memcpy(bs_new,ob->soft->bspring,(ob->soft->totspring )*sizeof(BodySpring));
 
167
                        
 
168
                        if(ob->soft->bspring)
 
169
                                MEM_freeN(ob->soft->bspring); /* do this before reassigning the pointer  or have a 1st class memory leak */
 
170
                        ob->soft->bspring = bs_new; 
 
171
                        
 
172
                        /* fill the tail */
 
173
                        a = 0;
 
174
                        bs = bs_new+ob->soft->totspring;
 
175
                        bp= ob->soft->bpoint;
 
176
                        if(mface ) {
 
177
                                for(a=me->totface; a>0; a--, mface++) {
 
178
                                        if(mface->v4) {
 
179
                                                bs->v1= mface->v1;
 
180
                                                bs->v2= mface->v3;
 
181
                                                bs->strength= 1.0;
 
182
                                                bs->len= VecLenf( (bp+bs->v1)->origS, (bp+bs->v2)->origS);
 
183
                                                bs++;
 
184
                                                bs->v1= mface->v2;
 
185
                                                bs->v2= mface->v4;
 
186
                                                bs->strength= 1.0;
 
187
                                                bs->len= VecLenf( (bp+bs->v1)->origS, (bp+bs->v2)->origS);
 
188
                                                bs++;
 
189
                                                
 
190
                                        }
 
191
                                }       
 
192
                        }
 
193
                        
 
194
            /* now we can announce new springs */
 
195
                        ob->soft->totspring += nofquads *2;
 
196
                }
 
197
        }
 
198
}
 
199
 
 
200
 
 
201
static void add_bp_springlist(BodyPoint *bp,int springID)
 
202
{
 
203
        int *newlist;
 
204
        
 
205
        if (bp->springs == NULL) {
 
206
                bp->springs = MEM_callocN( sizeof(int), "bpsprings");
 
207
                bp->springs[0] = springID;
 
208
                bp->nofsprings = 1;
 
209
        }
 
210
        else {
 
211
                bp->nofsprings++;
 
212
                newlist = MEM_callocN(bp->nofsprings * sizeof(int), "bpsprings");
 
213
                memcpy(newlist,bp->springs,(bp->nofsprings-1)* sizeof(int));
 
214
                MEM_freeN(bp->springs);
 
215
                bp->springs = newlist;
 
216
                bp->springs[bp->nofsprings-1] = springID;
 
217
        }
 
218
}
 
219
 
 
220
/* do this once when sb is build
 
221
it is O(N^2) so scanning for springs every iteration is too expensive
 
222
*/
 
223
static void build_bps_springlist(Object *ob)
 
224
{
 
225
        SoftBody *sb= ob->soft; // is supposed to be there
 
226
        BodyPoint *bp;  
 
227
        BodySpring *bs; 
 
228
        int a,b;
 
229
        
 
230
        if (sb==NULL) return; // paranoya check
 
231
        
 
232
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
 
233
                /* scan for attached inner springs */   
 
234
                for(b=sb->totspring, bs= sb->bspring; b>0; b--, bs++) {
 
235
                        if (( (sb->totpoint-a) == bs->v1) ){ 
 
236
                                add_bp_springlist(bp,sb->totspring -b);
 
237
                        }
 
238
                        if (( (sb->totpoint-a) == bs->v2) ){ 
 
239
                                add_bp_springlist(bp,sb->totspring -b);
 
240
                        }
 
241
                }//for springs
 
242
                // if (bp->nofsprings) printf(" node %d has %d spring links\n",a,bp->nofsprings);
 
243
        }//for bp               
 
244
}
 
245
 
 
246
 
 
247
/* creates new softbody if didn't exist yet, makes new points and springs arrays */
 
248
/* called in mesh_to_softbody */
 
249
static void renew_softbody(Object *ob, int totpoint, int totspring)  
 
250
{
 
251
        SoftBody *sb;
 
252
        
 
253
        if(ob->soft==NULL) ob->soft= sbNew();
 
254
        else free_softbody_intern(ob->soft);
 
255
        sb= ob->soft;
 
256
           
 
257
        if(totpoint) {
 
258
                sb->totpoint= totpoint;
 
259
                sb->totspring= totspring;
 
260
                
 
261
                sb->bpoint= MEM_mallocN( totpoint*sizeof(BodyPoint), "bodypoint");
 
262
                if(totspring) 
 
263
                        sb->bspring= MEM_mallocN( totspring*sizeof(BodySpring), "bodyspring");
 
264
        }
 
265
}
 
266
 
 
267
static void free_softbody_baked(SoftBody *sb)
 
268
{
 
269
        SBVertex *key;
 
270
        int k;
 
271
        
 
272
        for(k=0; k<sb->totkey; k++) {
 
273
                key= *(sb->keys + k);
 
274
                if(key) MEM_freeN(key);
 
275
        }
 
276
        if(sb->keys) MEM_freeN(sb->keys);
 
277
        
 
278
        sb->keys= NULL;
 
279
        sb->totkey= 0;
 
280
        
 
281
}
 
282
 
 
283
/* only frees internal data */
 
284
static void free_softbody_intern(SoftBody *sb)
 
285
{
 
286
        if(sb) {
 
287
                int a;
 
288
                BodyPoint *bp;
 
289
                
 
290
                if(sb->bpoint){
 
291
                        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
 
292
                                /* free spring list */ 
 
293
                                if (bp->springs != NULL) {
 
294
                                        MEM_freeN(bp->springs);
 
295
                                }
 
296
                        }
 
297
                        MEM_freeN(sb->bpoint);
 
298
                }
 
299
                
 
300
                if(sb->bspring) MEM_freeN(sb->bspring);
 
301
                
 
302
                sb->totpoint= sb->totspring= 0;
 
303
                sb->bpoint= NULL;
 
304
                sb->bspring= NULL;
 
305
                
 
306
                free_softbody_baked(sb);
 
307
        }
 
308
}
 
309
 
 
310
 
 
311
/* ************ dynamics ********** */
 
312
 
 
313
/* aye this belongs to arith.c */
 
314
static void Vec3PlusStVec(float *v, float s, float *v1)
 
315
{
 
316
        v[0] += s*v1[0];
 
317
        v[1] += s*v1[1];
 
318
        v[2] += s*v1[2];
 
319
}
 
320
 
 
321
static int sb_deflect_face(Object *ob,float *actpos, float *futurepos,float *collisionpos, float *facenormal,float *force,float *cf ,float *bounce)
 
322
{
 
323
        int deflected;
 
324
        float s_actpos[3], s_futurepos[3];
 
325
        VECCOPY(s_actpos,actpos);
 
326
        if(futurepos)
 
327
        VECCOPY(s_futurepos,futurepos);
 
328
        if (bounce) *bounce *= 1.5f;
 
329
                                
 
330
                                
 
331
        deflected= SoftBodyDetectCollision(s_actpos, s_futurepos, collisionpos,
 
332
                                        facenormal, cf, force , 1,
 
333
                                        G.scene->r.cfra, ob->lay, ob);
 
334
        return(deflected);
 
335
                                
 
336
}
 
337
 
 
338
/* for future use (BM)
 
339
static int sb_deflect_edge_face(Object *ob,float *actpos, float *futurepos,float *collisionpos, float *facenormal,float *slip ,float *bounce)
 
340
{
 
341
        int deflected;
 
342
        float dummy[3],s_actpos[3], s_futurepos[3];
 
343
        SoftBody *sb= ob->soft; // is supposed to be there
 
344
        VECCOPY(s_actpos,actpos);
 
345
        VECCOPY(s_futurepos,futurepos);
 
346
        if (slip)   *slip   *= 0.98f;
 
347
        if (bounce) *bounce *= 1.5f;
 
348
                                
 
349
                                
 
350
        deflected= SoftBodyDetectCollision(s_actpos, s_futurepos, collisionpos,
 
351
                                        facenormal, dummy, dummy , 2,
 
352
                                        G.scene->r.cfra, ob->lay, ob);
 
353
        return(deflected);
 
354
                                
 
355
}
 
356
*/
 
357
// some functions removed here .. to help HOS on next merge (BM)
 
358
 
 
359
#define USES_FIELD              1
 
360
#define USES_DEFLECT    2
 
361
static int is_there_deflection(unsigned int layer)
 
362
{
 
363
        Base *base;
 
364
        int retval= 0;
 
365
        
 
366
        for(base = G.scene->base.first; base; base= base->next) {
 
367
                if( (base->lay & layer) && base->object->pd) {
 
368
                        if(base->object->pd->forcefield) retval |= USES_FIELD;
 
369
                        if(base->object->pd->deflect) retval |= USES_DEFLECT;
 
370
                }
 
371
        }
 
372
        return retval;
 
373
}
 
374
 
 
375
static void softbody_calc_forces(Object *ob, float forcetime)
 
376
{
 
377
/* rule we never alter free variables :bp->vec bp->pos in here ! 
 
378
 * this will ruin adaptive stepsize AKA heun! (BM) 
 
379
 */
 
380
        SoftBody *sb= ob->soft; // is supposed to be there
 
381
        BodyPoint  *bp;
 
382
        BodyPoint *bproot;
 
383
        BodySpring *bs; 
 
384
        float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3],
 
385
        fieldfactor = 1000.0f, 
 
386
        windfactor  = 250.0f;   
 
387
        int a, b, do_effector;
 
388
        
 
389
        /* clear forces */
 
390
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
 
391
                bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
 
392
        }
 
393
        
 
394
        gravity = sb->grav * sb_grav_force_scale(ob);   
 
395
        /* check! */
 
396
        do_effector= is_there_deflection(ob->lay);
 
397
        iks  = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
 
398
        bproot= sb->bpoint; /* need this for proper spring addressing */
 
399
        
 
400
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
 
401
                if(bp->goal < SOFTGOALSNAP){ // ommit this bp when i snaps
 
402
                        float auxvect[3]; // aux unit vector  
 
403
                        float velgoal[3];
 
404
                        float absvel =0, projvel= 0;
 
405
                        
 
406
                        /* do goal stuff */
 
407
                        if(ob->softflag & OB_SB_GOAL) {
 
408
                                /* true elastic goal */
 
409
                                VecSubf(auxvect,bp->origT,bp->pos);
 
410
                                ks  = 1.0f/(1.0f- bp->goal*sb->goalspring)-1.0f ;
 
411
                                bp->force[0]= ks*(auxvect[0]);
 
412
                                bp->force[1]= ks*(auxvect[1]);
 
413
                                bp->force[2]= ks*(auxvect[2]);
 
414
                                /* calulate damping forces generated by goals*/
 
415
                                VecSubf(velgoal,bp->origS, bp->origE);
 
416
                                kd =  sb->goalfrict * sb_fric_force_scale(ob) ;
 
417
                                
 
418
                                if (forcetime > 0.0 ) { // make sure friction does not become rocket motor on time reversal
 
419
                                        bp->force[0]-= kd * (velgoal[0] + bp->vec[0]);
 
420
                                        bp->force[1]-= kd * (velgoal[1] + bp->vec[1]);
 
421
                                        bp->force[2]-= kd * (velgoal[2] + bp->vec[2]);
 
422
                                }
 
423
                                else {
 
424
                                        bp->force[0]-= kd * (velgoal[0] - bp->vec[0]);
 
425
                                        bp->force[1]-= kd * (velgoal[1] - bp->vec[1]);
 
426
                                        bp->force[2]-= kd * (velgoal[2] - bp->vec[2]);
 
427
                                }
 
428
                        }
 
429
                        /* done goal stuff */
 
430
                        
 
431
                        
 
432
                        /* gravitation */
 
433
                        bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */
 
434
                        
 
435
                        /* particle field & vortex */
 
436
                        if(do_effector & USES_FIELD) {
 
437
                                float force[3]= {0.0f, 0.0f, 0.0f};
 
438
                                float speed[3]= {0.0f, 0.0f, 0.0f};
 
439
                                float eval_sb_fric_force_scale = sb_fric_force_scale(ob); // just for calling functio once
 
440
                                
 
441
                                pdDoEffector(bp->pos, force, speed, (float)G.scene->r.cfra, ob->lay,PE_WIND_AS_SPEED);
 
442
                                // note: now we have wind as motion of media, so we can do anisotropic stuff here, 
 
443
                                // if we had vertex normals here(BM)
 
444
                                /* apply forcefield*/
 
445
                                VecMulf(force,fieldfactor* eval_sb_fric_force_scale); 
 
446
                                VECADD(bp->force, bp->force, force);
 
447
                                
 
448
                                /* friction in moving media */  
 
449
                                kd= sb->mediafrict* eval_sb_fric_force_scale;  
 
450
                                bp->force[0] -= kd * (bp->vec[0] + windfactor*speed[0]/eval_sb_fric_force_scale);
 
451
                                bp->force[1] -= kd * (bp->vec[1] + windfactor*speed[1]/eval_sb_fric_force_scale);
 
452
                                bp->force[2] -= kd * (bp->vec[2] + windfactor*speed[2]/eval_sb_fric_force_scale);
 
453
                                /* now we'll have nice centrifugal effect for vortex */
 
454
                                
 
455
                        }
 
456
                        else {
 
457
                                /* friction in media (not) moving*/
 
458
                                kd= sb->mediafrict* sb_fric_force_scale(ob);  
 
459
                                /* assume it to be proportional to actual velocity */
 
460
                                bp->force[0]-= bp->vec[0]*kd;
 
461
                                bp->force[1]-= bp->vec[1]*kd;
 
462
                                bp->force[2]-= bp->vec[2]*kd;
 
463
                                /* friction in media done */
 
464
                        }
 
465
                        
 
466
                        /*other forces*/
 
467
                        /* this is the place where other forces can be added
 
468
                        yes, constraints and collision stuff should go here too (read baraff papers on that!)
 
469
                        */
 
470
                        /* try to match moving collision targets */
 
471
                        /* master switch to turn collision off (BM)*/
 
472
                        //if(0) {
 
473
                        if(do_effector & USES_DEFLECT) {
 
474
                                /*sorry for decl. here i'll move 'em up when WIP is done (BM) */
 
475
                                float defforce[3];
 
476
                                float collisionpos[3],facenormal[3];
 
477
                                float cf = 1.0f;
 
478
                                float bounce = 0.5f;
 
479
                                kd = 1.0f;
 
480
                                defforce[0] = 0.0f;
 
481
                                defforce[1] = 0.0f;
 
482
                                defforce[2] = 0.0f;
 
483
                                
 
484
                                if (sb_deflect_face(ob,bp->pos, bp->pos, collisionpos, facenormal,defforce,&cf,&bounce)){
 
485
                                        bp->force[0] += defforce[0]*kd;
 
486
                                        bp->force[1] += defforce[1]*kd;
 
487
                                        bp->force[2] += defforce[2]*kd;
 
488
                                        bp->contactfrict = cf;
 
489
                                }
 
490
                                else{ 
 
491
                                        bp->contactfrict = 0.0f;
 
492
                                }
 
493
                                
 
494
                        }
 
495
                        
 
496
                        /*other forces done*/
 
497
                        /* nice things could be done with anisotropic friction
 
498
                        like wind/air resistance in normal direction
 
499
                        --> having a piece of cloth sailing down 
 
500
                        but this needs to have a *valid* vertex normal
 
501
                        *valid* means to be calulated on time axis
 
502
                        hrms .. may be a rough one could be used as well .. let's see 
 
503
                        */
 
504
                        
 
505
                        if(ob->softflag & OB_SB_EDGES) {
 
506
                                if (sb->bspring){ // spring list exists at all ? 
 
507
                                        for(b=bp->nofsprings;b>0;b--){
 
508
                                                bs = sb->bspring + bp->springs[b-1];
 
509
                                                if (( (sb->totpoint-a) == bs->v1) ){ 
 
510
                                                        actspringlen= VecLenf( (bproot+bs->v2)->pos, bp->pos);
 
511
                                                        VecSubf(sd,(bproot+bs->v2)->pos, bp->pos);
 
512
                                                        Normalise(sd);
 
513
                                                        
 
514
                                                        // friction stuff V1
 
515
                                                        VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec);
 
516
                                                        kd = sb->infrict * sb_fric_force_scale(ob);
 
517
                                                        absvel  = Normalise(velgoal);
 
518
                                                        projvel = ABS(Inpf(sd,velgoal));
 
519
                                                        kd *= absvel * projvel;
 
520
                                                        Vec3PlusStVec(bp->force,-kd,velgoal);
 
521
                                                        
 
522
                                                        if(bs->len > 0.0) /* check for degenerated springs */
 
523
                                                                forcefactor = (bs->len - actspringlen)/bs->len * iks;
 
524
                                                        else
 
525
                                                                forcefactor = actspringlen * iks;
 
526
                                                        
 
527
                                                        Vec3PlusStVec(bp->force,-forcefactor,sd);
 
528
                                                        
 
529
                                                }
 
530
                                                
 
531
                                                if (( (sb->totpoint-a) == bs->v2) ){ 
 
532
                                                        actspringlen= VecLenf( (bproot+bs->v1)->pos, bp->pos);
 
533
                                                        VecSubf(sd,bp->pos,(bproot+bs->v1)->pos);
 
534
                                                        Normalise(sd);
 
535
                                                        
 
536
                                                        // friction stuff V2
 
537
                                                        VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec);
 
538
                                                        kd = sb->infrict * sb_fric_force_scale(ob);
 
539
                                                        absvel  = Normalise(velgoal);
 
540
                                                        projvel = ABS(Inpf(sd,velgoal));
 
541
                                                        kd *= absvel * projvel;
 
542
                                                        Vec3PlusStVec(bp->force,-kd,velgoal);
 
543
                                                        
 
544
                                                        if(bs->len > 0.0)
 
545
                                                                forcefactor = (bs->len - actspringlen)/bs->len * iks;
 
546
                                                        else
 
547
                                                                forcefactor = actspringlen * iks;
 
548
                                                        Vec3PlusStVec(bp->force,+forcefactor,sd);                                                       
 
549
                                                }
 
550
                                        }/* loop springs */
 
551
                                }/* existing spring list */ 
 
552
                        }/*any edges*/
 
553
                }/*omit on snap */
 
554
        }/*loop all bp's*/
 
555
}
 
556
 
 
557
static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err)
 
558
{
 
559
        /* time evolution */
 
560
        /* actually does an explicit euler step mode == 0 */
 
561
        /* or heun ~ 2nd order runge-kutta steps, mode 1,2 */
 
562
        SoftBody *sb= ob->soft; // is supposed to be there
 
563
        BodyPoint *bp;
 
564
        float dx[3],dv[3];
 
565
        float timeovermass;
 
566
        float maxerr = 0.0;
 
567
        int a, do_effector;
 
568
 
 
569
    forcetime *= sb_time_scale(ob);
 
570
        /* check! */
 
571
        do_effector= is_there_deflection(ob->lay);
 
572
    
 
573
        // claim a minimum mass for vertex 
 
574
        if (sb->nodemass > 0.09999f) timeovermass = forcetime/sb->nodemass;
 
575
        else timeovermass = forcetime/0.09999f;
 
576
        
 
577
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
 
578
                if(bp->goal < SOFTGOALSNAP){
 
579
                        
 
580
                        /* so here is (v)' = a(cceleration) = sum(F_springs)/m + gravitation + some friction forces  + more forces*/
 
581
                        /* the ( ... )' operator denotes derivate respective time */
 
582
                        /* the euler step for velocity then becomes */
 
583
                        /* v(t + dt) = v(t) + a(t) * dt */ 
 
584
                        bp->force[0]*= timeovermass; /* individual mass of node here */ 
 
585
                        bp->force[1]*= timeovermass;
 
586
                        bp->force[2]*= timeovermass;
 
587
                        /* some nasty if's to have heun in here too */
 
588
                        VECCOPY(dv,bp->force); 
 
589
                        if (mode == 1){
 
590
                                VECCOPY(bp->prevvec, bp->vec);
 
591
                                VECCOPY(bp->prevdv, dv);
 
592
                        }
 
593
                        if (mode ==2){
 
594
                                /* be optimistic and execute step */
 
595
                                bp->vec[0] = bp->prevvec[0] + 0.5f * (dv[0] + bp->prevdv[0]);
 
596
                                bp->vec[1] = bp->prevvec[1] + 0.5f * (dv[1] + bp->prevdv[1]);
 
597
                                bp->vec[2] = bp->prevvec[2] + 0.5f * (dv[2] + bp->prevdv[2]);
 
598
                                /* compare euler to heun to estimate error for step sizing */
 
599
                                maxerr = MAX2(maxerr,ABS(dv[0] - bp->prevdv[0]));
 
600
                                maxerr = MAX2(maxerr,ABS(dv[1] - bp->prevdv[1]));
 
601
                                maxerr = MAX2(maxerr,ABS(dv[2] - bp->prevdv[2]));
 
602
                        }
 
603
                        else {VECADD(bp->vec, bp->vec, bp->force);}
 
604
 
 
605
                        /* so here is (x)'= v(elocity) */
 
606
                        /* the euler step for location then becomes */
 
607
                        /* x(t + dt) = x(t) + v(t) * dt */ 
 
608
                        
 
609
                        VECCOPY(dx,bp->vec);
 
610
                        dx[0]*=forcetime ; 
 
611
                        dx[1]*=forcetime ; 
 
612
                        dx[2]*=forcetime ; 
 
613
                        
 
614
                        /* again some nasty if's to have heun in here too */
 
615
                        if (mode ==1){
 
616
                                VECCOPY(bp->prevpos,bp->pos);
 
617
                                VECCOPY(bp->prevdx ,dx);
 
618
                        }
 
619
                        
 
620
                        if (mode ==2){
 
621
                                bp->pos[0] = bp->prevpos[0] + 0.5f * ( dx[0] + bp->prevdx[0]);
 
622
                                bp->pos[1] = bp->prevpos[1] + 0.5f * ( dx[1] + bp->prevdx[1]);
 
623
                                bp->pos[2] = bp->prevpos[2] + 0.5f* ( dx[2] + bp->prevdx[2]);
 
624
                                maxerr = MAX2(maxerr,ABS(dx[0] - bp->prevdx[0]));
 
625
                                maxerr = MAX2(maxerr,ABS(dx[1] - bp->prevdx[1]));
 
626
                                maxerr = MAX2(maxerr,ABS(dx[2] - bp->prevdx[2]));
 
627
/* kind of hack .. while inside collision target .. make movement more *viscous* */
 
628
                                if (bp->contactfrict > 0.0f){
 
629
                                        bp->vec[0] *= (1.0 - bp->contactfrict);
 
630
                                        bp->vec[1] *= (1.0 - bp->contactfrict);
 
631
                                        bp->vec[2] *= (1.0 - bp->contactfrict);
 
632
                                }
 
633
                        }
 
634
                        else { VECADD(bp->pos, bp->pos, dx);}
 
635
// experimental particle collision suff was here .. just to help HOS on next merge (BM)
 
636
                }//snap
 
637
        } //for
 
638
        if (err){ /* so step size will be controlled by biggest difference in slope */
 
639
                *err = maxerr;
 
640
        }
 
641
}
 
642
 
 
643
/* used by heun when it overshoots */
 
644
static void softbody_restore_prev_step(Object *ob)
 
645
{
 
646
        SoftBody *sb= ob->soft; // is supposed to be there
 
647
        BodyPoint *bp;
 
648
        int a;
 
649
        
 
650
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
 
651
                VECCOPY(bp->vec, bp->prevvec);
 
652
                VECCOPY(bp->pos, bp->prevpos);
 
653
        }
 
654
}
 
655
 
 
656
 
 
657
static void softbody_apply_goalsnap(Object *ob)
 
658
{
 
659
        SoftBody *sb= ob->soft; // is supposed to be there
 
660
        BodyPoint *bp;
 
661
        int a;
 
662
        
 
663
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
 
664
                if (bp->goal >= SOFTGOALSNAP){
 
665
                        VECCOPY(bp->prevpos,bp->pos);
 
666
                        VECCOPY(bp->pos,bp->origT);
 
667
                }               
 
668
        }
 
669
}
 
670
 
 
671
/* unused */
 
672
#if 0
 
673
static void softbody_force_goal(Object *ob)
 
674
{
 
675
        SoftBody *sb= ob->soft; // is supposed to be there
 
676
        BodyPoint *bp;
 
677
        int a;
 
678
        
 
679
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {           
 
680
                VECCOPY(bp->pos,bp->origT);
 
681
                bp->vec[0] = bp->origE[0] - bp->origS[0];
 
682
                bp->vec[1] = bp->origE[1] - bp->origS[1];
 
683
                bp->vec[2] = bp->origE[2] - bp->origS[2];               
 
684
        }
 
685
}
 
686
#endif
 
687
 
 
688
/* expects full initialized softbody */
 
689
static void interpolate_exciter(Object *ob, int timescale, int time)
 
690
{
 
691
        SoftBody *sb= ob->soft;
 
692
        BodyPoint *bp;
 
693
        float f;
 
694
        int a;
 
695
 
 
696
        // note: i removed Mesh usage here, softbody should remain generic! (ton)
 
697
        
 
698
        f = (float)time/(float)timescale;
 
699
        
 
700
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {   
 
701
                bp->origT[0] = bp->origS[0] + f*(bp->origE[0] - bp->origS[0]); 
 
702
                bp->origT[1] = bp->origS[1] + f*(bp->origE[1] - bp->origS[1]); 
 
703
                bp->origT[2] = bp->origS[2] + f*(bp->origE[2] - bp->origS[2]); 
 
704
                if (bp->goal >= SOFTGOALSNAP){
 
705
                        bp->vec[0] = bp->origE[0] - bp->origS[0];
 
706
                        bp->vec[1] = bp->origE[1] - bp->origS[1];
 
707
                        bp->vec[2] = bp->origE[2] - bp->origS[2];
 
708
                }
 
709
        }
 
710
        
 
711
        if(ob->softflag & OB_SB_EDGES) {
 
712
                /* hrms .. do springs alter their lenght ?
 
713
                bs= ob->soft->bspring;
 
714
                bp= ob->soft->bpoint;
 
715
                for(a=0; (a<me->totedge && a < ob->soft->totspring ); a++, bs++) {
 
716
                        bs->len= VecLenf( (bp+bs->v1)->origT, (bp+bs->v2)->origT);
 
717
                }
 
718
                */
 
719
        }
 
720
}
 
721
 
 
722
 
 
723
/* ************ convertors ********** */
 
724
 
 
725
/*  for each object type we need;
 
726
    - xxxx_to_softbody(Object *ob)      : a full (new) copy
 
727
        - xxxx_update_softbody(Object *ob)  : update refreshes current positions
 
728
    - softbody_to_xxxx(Object *ob)      : after simulation, copy vertex locations back
 
729
*/
 
730
 
 
731
/* helper  call */
 
732
static int object_has_edges(Object *ob) 
 
733
{
 
734
        if(ob->type==OB_MESH) {
 
735
                Mesh *me= ob->data;
 
736
                if(me->medge) return 1;
 
737
        }
 
738
        else if(ob->type==OB_LATTICE) {
 
739
                ;
 
740
        }
 
741
        
 
742
        return 0;
 
743
}
 
744
 
 
745
/* helper  call */
 
746
static void set_body_point(Object *ob, BodyPoint *bp, float *vec)
 
747
{
 
748
        
 
749
        VECCOPY(bp->pos, vec);
 
750
        Mat4MulVecfl(ob->obmat, bp->pos);  // yep, sofbody is global coords
 
751
        VECCOPY(bp->origS, bp->pos);
 
752
        VECCOPY(bp->origE, bp->pos);
 
753
        VECCOPY(bp->origT, bp->pos);
 
754
        
 
755
        bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0;
 
756
        bp->weight= 1.0;
 
757
        if(ob->softflag & OB_SB_GOAL) {
 
758
                bp->goal= ob->soft->defgoal;
 
759
        }
 
760
        else { 
 
761
                bp->goal= 0.0f; 
 
762
                /* so this will definily be below SOFTGOALSNAP */
 
763
        }
 
764
        
 
765
        bp->nofsprings= 0;
 
766
        bp->springs= NULL;
 
767
        bp->contactfrict = 0.0f;
 
768
}
 
769
 
 
770
 
 
771
/* copy original (new) situation in softbody, as result of matrices or deform */
 
772
/* is assumed to enter function with ob->soft, but can be without points */
 
773
static void mesh_update_softbody(Object *ob)
 
774
{
 
775
        Mesh *me= ob->data;
 
776
        MVert *mvert= me->mvert;
 
777
/*      MEdge *medge= me->medge;  */ /*unused*/
 
778
        BodyPoint *bp;
 
779
        int a;
 
780
        
 
781
        /* possible after a file read... */
 
782
        if(ob->soft->bpoint==NULL) sbObjectToSoftbody(ob);
 
783
        
 
784
        if(me->totvert) {
 
785
        
 
786
                bp= ob->soft->bpoint;
 
787
                for(a=0; a<me->totvert; a++, mvert++, bp++) {
 
788
                        VECCOPY(bp->origS, bp->origE);
 
789
                        VECCOPY(bp->origE, mvert->co);
 
790
                        Mat4MulVecfl(ob->obmat, bp->origE);
 
791
                        VECCOPY(bp->origT, bp->origE);
 
792
                }
 
793
                
 
794
                if(ob->softflag & OB_SB_EDGES) {
 
795
                        
 
796
                        /* happens when in UI edges was set */
 
797
                        if(ob->soft->bspring==NULL) 
 
798
                                if(object_has_edges(ob)) sbObjectToSoftbody(ob);
 
799
                
 
800
                        /* hrms .. do springs alter their lenght ? (yes, mesh keys would (ton))
 
801
                        if(medge) {
 
802
                                bs= ob->soft->bspring;
 
803
                                bp= ob->soft->bpoint;
 
804
                                for(a=0; (a<me->totedge && a < ob->soft->totspring ); a++, medge++, bs++) { 
 
805
                                        bs->len= VecLenf( (bp+bs->v1)->origE, (bp+bs->v2)->origE);
 
806
                                }
 
807
                        }
 
808
                        */
 
809
                }
 
810
        }
 
811
}
 
812
 
 
813
 
 
814
static void get_scalar_from_vertexgroup(Object *ob, int vertID, short groupindex, float *target)
 
815
/* result 0 on success, else indicates error number
 
816
-- kind of *inverse* result defintion,
 
817
-- but this way we can signal error condition to caller  
 
818
-- and yes this function must not be here but in a *vertex group module*
 
819
*/
 
820
{
 
821
        MDeformVert *dv;
 
822
        int i;
 
823
        
 
824
        /* spot the vert in deform vert list at mesh */
 
825
        if(ob->type==OB_MESH) {
 
826
                if (((Mesh *)ob->data)->dvert) {
 
827
                        dv = ((Mesh*)ob->data)->dvert + vertID; 
 
828
                        /* Lets see if this vert is in the weight group */
 
829
                        for (i=0; i<dv->totweight; i++){
 
830
                                if (dv->dw[i].def_nr == groupindex){
 
831
                                        *target= dv->dw[i].weight; /* got it ! */
 
832
                                        break;
 
833
                                }
 
834
                        }
 
835
                }
 
836
        }
 
837
 
838
 
 
839
/* makes totally fresh start situation */
 
840
static void mesh_to_softbody(Object *ob)
 
841
{
 
842
        SoftBody *sb;
 
843
        Mesh *me= ob->data;
 
844
        MVert *mvert= me->mvert;
 
845
        MEdge *medge= me->medge;
 
846
        BodyPoint *bp;
 
847
        BodySpring *bs;
 
848
        float goalfac;
 
849
        int a, totedge;
 
850
        
 
851
        if (ob->softflag & OB_SB_EDGES) totedge= me->totedge;
 
852
        else totedge= 0;
 
853
        
 
854
        /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
 
855
        renew_softbody(ob, me->totvert, totedge);
 
856
                
 
857
        /* we always make body points */
 
858
        sb= ob->soft;   
 
859
        bp= sb->bpoint;
 
860
        goalfac= ABS(sb->maxgoal - sb->mingoal);
 
861
        
 
862
        for(a=me->totvert; a>0; a--, mvert++, bp++) {
 
863
                
 
864
                set_body_point(ob, bp, mvert->co);
 
865
                
 
866
                /* get scalar values needed  *per vertex* from vertex group functions,
 
867
                so we can *paint* them nicly .. 
 
868
                they are normalized [0.0..1.0] so may be we need amplitude for scale
 
869
                which can be done by caller but still .. i'd like it to go this way 
 
870
                */ 
 
871
                
 
872
                if((ob->softflag & OB_SB_GOAL) && sb->vertgroup) {
 
873
                        get_scalar_from_vertexgroup(ob, me->totvert - a, sb->vertgroup-1, &bp->goal);
 
874
                        // do this always, regardless successfull read from vertex group
 
875
                        bp->goal= sb->mingoal + bp->goal*goalfac;
 
876
                }
 
877
                /* a little ad hoc changing the goal control to be less *sharp* */
 
878
                bp->goal = (float)pow(bp->goal, 4.0f);
 
879
                        
 
880
                /* to proove the concept
 
881
                this would enable per vertex *mass painting*
 
882
                strcpy(name,"SOFTMASS");
 
883
                error = get_scalar_from_named_vertexgroup(ob,name,me->totvert - a,&temp);
 
884
                if (!error) bp->mass = temp * ob->rangeofmass;
 
885
                */
 
886
        }
 
887
 
 
888
        /* but we only optionally add body edge springs */
 
889
        if (ob->softflag & OB_SB_EDGES) {
 
890
                if(medge) {
 
891
                        bs= sb->bspring;
 
892
                        bp= sb->bpoint;
 
893
                        for(a=me->totedge; a>0; a--, medge++, bs++) {
 
894
                                bs->v1= medge->v1;
 
895
                                bs->v2= medge->v2;
 
896
                                bs->strength= 1.0;
 
897
                                bs->len= VecLenf( (bp+bs->v1)->origS, (bp+bs->v2)->origS);
 
898
                        }
 
899
 
 
900
                
 
901
                        /* insert *diagonal* springs in quads if desired */
 
902
                        if (ob->softflag & OB_SB_QUADS) {
 
903
                                add_mesh_quad_diag_springs(ob);
 
904
                        }
 
905
 
 
906
                        build_bps_springlist(ob); /* big mesh optimization */
 
907
                }
 
908
        }
 
909
        
 
910
}
 
911
 
 
912
/* copies current sofbody position in mesh, so do this within modifier stacks! */
 
913
static void softbody_to_mesh(Object *ob)
 
914
{
 
915
        Mesh *me= ob->data;
 
916
        MVert *mvert;
 
917
        BodyPoint *bp;
 
918
        int a;
 
919
 
 
920
        bp= ob->soft->bpoint;
 
921
        mvert= me->mvert;
 
922
        for(a=me->totvert; a>0; a--, mvert++, bp++) {
 
923
                VECCOPY(mvert->co, bp->pos);
 
924
                Mat4MulVecfl(ob->imat, mvert->co);      // softbody is in global coords
 
925
        }
 
926
 
 
927
}
 
928
 
 
929
/* makes totally fresh start situation */
 
930
static void lattice_to_softbody(Object *ob)
 
931
{
 
932
        SoftBody *sb;
 
933
        Lattice *lt= ob->data;
 
934
        BodyPoint *bop;
 
935
        BPoint *bp;
 
936
        int a, totvert;
 
937
        
 
938
        totvert= lt->pntsu*lt->pntsv*lt->pntsw;
 
939
        
 
940
        /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
 
941
        renew_softbody(ob, totvert, 0);
 
942
        
 
943
        /* we always make body points */
 
944
        sb= ob->soft;   
 
945
        
 
946
        for(a= totvert, bp= lt->def, bop= sb->bpoint; a>0; a--, bp++, bop++) {
 
947
                set_body_point(ob, bop, bp->vec);
 
948
        }
 
949
}
 
950
 
 
951
/* copies current sofbody position */
 
952
static void softbody_to_lattice(Object *ob)
 
953
{
 
954
        SoftBody *sb;
 
955
        Lattice *lt= ob->data;
 
956
        BodyPoint *bop;
 
957
        BPoint *bp;
 
958
        int a, totvert;
 
959
        
 
960
        totvert= lt->pntsu*lt->pntsv*lt->pntsw;
 
961
        sb= ob->soft;   
 
962
        
 
963
        for(a= totvert, bp= lt->def, bop= sb->bpoint; a>0; a--, bp++, bop++) {
 
964
                VECCOPY(bp->vec, bop->pos);
 
965
                Mat4MulVecfl(ob->imat, bp->vec);        // softbody is in global coords
 
966
        }
 
967
}
 
968
 
 
969
/* copy original (new) situation in softbody, as result of matrices or deform */
 
970
/* is assumed to enter function with ob->soft, but can be without points */
 
971
static void lattice_update_softbody(Object *ob)
 
972
{
 
973
        Lattice *lt= ob->data;
 
974
        BodyPoint *bop;
 
975
        BPoint *bp;
 
976
        int a, totvert;
 
977
        
 
978
        totvert= lt->pntsu*lt->pntsv*lt->pntsw;
 
979
        
 
980
        /* possible after a file read... */
 
981
        if(ob->soft->bpoint==NULL) sbObjectToSoftbody(ob);
 
982
        
 
983
        for(a= totvert, bp= lt->def, bop= ob->soft->bpoint; a>0; a--, bp++, bop++) {
 
984
                VECCOPY(bop->origS, bop->origE);
 
985
                VECCOPY(bop->origE, bp->vec);
 
986
                Mat4MulVecfl(ob->obmat, bop->origE);
 
987
                VECCOPY(bop->origT, bop->origE);
 
988
        }       
 
989
}
 
990
 
 
991
 
 
992
/* copies softbody result back in object */
 
993
/* only used in sbObjectStep() */
 
994
static void softbody_to_object(Object *ob)
 
995
{
 
996
        
 
997
        if(ob->soft==NULL) return;
 
998
        
 
999
        /* inverse matrix is not uptodate... */
 
1000
        Mat4Invert(ob->imat, ob->obmat);
 
1001
        
 
1002
        switch(ob->type) {
 
1003
        case OB_MESH:
 
1004
                softbody_to_mesh(ob);
 
1005
                break;
 
1006
        case OB_LATTICE:
 
1007
                softbody_to_lattice(ob);
 
1008
                break;
 
1009
        }
 
1010
}
 
1011
 
 
1012
/* copy original (new) situation in softbody, as result of matrices or deform */
 
1013
/* used in sbObjectStep() and sbObjectReset() */
 
1014
/* assumes to have ob->soft, but can be entered without points */
 
1015
static void object_update_softbody(Object *ob)
 
1016
{
 
1017
        
 
1018
        switch(ob->type) {
 
1019
        case OB_MESH:
 
1020
                mesh_update_softbody(ob);
 
1021
                break;
 
1022
        case OB_LATTICE:
 
1023
                lattice_update_softbody(ob);
 
1024
                break;
 
1025
        }
 
1026
        
 
1027
}
 
1028
 
 
1029
/* return 1 if succesfully baked and applied step */
 
1030
static int softbody_baked_step(Object *ob, float framenr)
 
1031
{
 
1032
        SoftBody *sb= ob->soft;
 
1033
        SBVertex *key0, *key1, *key2, *key3;
 
1034
        BodyPoint *bp;
 
1035
        float data[4], sfra, efra, cfra, dfra, fac;     // start, end, current, delta 
 
1036
        int ofs1, a;
 
1037
 
 
1038
        /* precondition check */
 
1039
        if(sb==NULL || sb->keys==NULL || sb->totkey==0) return 0;
 
1040
        /* so we got keys, but no bodypoints... even without simul we need it for the bake */
 
1041
        if(sb->bpoint==NULL) sb->bpoint= MEM_callocN( sb->totpoint*sizeof(BodyPoint), "bodypoint");
 
1042
        
 
1043
        /* convert cfra time to system time */
 
1044
        sfra= (float)sb->sfra;
 
1045
        cfra= bsystem_time(ob, NULL, framenr, 0.0);
 
1046
        efra= (float)sb->efra;
 
1047
        dfra= (float)sb->interval;
 
1048
 
 
1049
        /* offset in keys array */
 
1050
        ofs1= floor( (cfra-sfra)/dfra );
 
1051
 
 
1052
        if(ofs1 < 0) {
 
1053
                key0=key1=key2=key3= *sb->keys;
 
1054
        }
 
1055
        else if(ofs1 >= sb->totkey-1) {
 
1056
                key0=key1=key2=key3= *(sb->keys+sb->totkey-1);
 
1057
        }
 
1058
        else {
 
1059
                key1= *(sb->keys+ofs1);
 
1060
                key2= *(sb->keys+ofs1+1);
 
1061
 
 
1062
                if(ofs1>0) key0= *(sb->keys+ofs1-1);
 
1063
                else key0= key1;
 
1064
                
 
1065
                if(ofs1<sb->totkey-2) key3= *(sb->keys+ofs1+2);
 
1066
                else key3= key2;
 
1067
        }
 
1068
        
 
1069
        sb->ctime= cfra;        // needed?
 
1070
        
 
1071
        /* timing */
 
1072
        fac= ((cfra-sfra)/dfra) - (float)ofs1;
 
1073
        CLAMP(fac, 0.0, 1.0);
 
1074
        set_four_ipo(fac, data, KEY_BSPLINE);
 
1075
        
 
1076
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++, key0++, key1++, key2++, key3++) {
 
1077
                bp->pos[0]= data[0]*key0->vec[0] +  data[1]*key1->vec[0] + data[2]*key2->vec[0] + data[3]*key3->vec[0];
 
1078
                bp->pos[1]= data[0]*key0->vec[1] +  data[1]*key1->vec[1] + data[2]*key2->vec[1] + data[3]*key3->vec[1];
 
1079
                bp->pos[2]= data[0]*key0->vec[2] +  data[1]*key1->vec[2] + data[2]*key2->vec[2] + data[3]*key3->vec[2];
 
1080
        }
 
1081
        
 
1082
        softbody_to_object(ob);
 
1083
        
 
1084
        return 1;
 
1085
}
 
1086
 
 
1087
/* only gets called after succesfully doing softbody_step */
 
1088
/* already checked for OB_SB_BAKE flag */
 
1089
static void softbody_baked_add(Object *ob, float framenr)
 
1090
{
 
1091
        SoftBody *sb= ob->soft;
 
1092
        SBVertex *key;
 
1093
        BodyPoint *bp;
 
1094
        float sfra, efra, cfra, dfra, fac1;     // start, end, current, delta 
 
1095
        int ofs1, a;
 
1096
        
 
1097
        /* convert cfra time to system time */
 
1098
        sfra= (float)sb->sfra;
 
1099
        cfra= bsystem_time(ob, NULL, framenr, 0.0);
 
1100
        efra= (float)sb->efra;
 
1101
        dfra= (float)sb->interval;
 
1102
        
 
1103
        if(sb->totkey==0) {
 
1104
                if(sb->sfra >= sb->efra) return;                // safety, UI or py setting allows
 
1105
                if(sb->interval<1) sb->interval= 1;             // just be sure
 
1106
                
 
1107
                sb->totkey= 1 + (int)(ceil( (efra-sfra)/dfra ) );
 
1108
                sb->keys= MEM_callocN( sizeof(void *)*sb->totkey, "sb keys");
 
1109
        }
 
1110
        
 
1111
        /* now find out if we have to store a key */
 
1112
        
 
1113
        /* offset in keys array */
 
1114
        if(cfra==efra) {
 
1115
                ofs1= sb->totkey-1;
 
1116
                fac1= 0.0;
 
1117
        }
 
1118
        else {
 
1119
                ofs1= floor( (cfra-sfra)/dfra );
 
1120
                fac1= ((cfra-sfra)/dfra) - (float)ofs1;
 
1121
        }       
 
1122
        if( fac1 < 1.0/dfra ) {
 
1123
                
 
1124
                key= *(sb->keys+ofs1);
 
1125
                if(key == NULL) {
 
1126
                        *(sb->keys+ofs1)= key= MEM_mallocN(sb->totpoint*sizeof(SBVertex), "softbody key");
 
1127
                        
 
1128
                        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++, key++) {
 
1129
                                VECCOPY(key->vec, bp->pos);
 
1130
                        }
 
1131
                }
 
1132
        }
 
1133
}
 
1134
 
 
1135
/* ************ Object level, exported functions *************** */
 
1136
 
 
1137
/* allocates and initializes general main data */
 
1138
SoftBody *sbNew(void)
 
1139
{
 
1140
        SoftBody *sb;
 
1141
        
 
1142
        sb= MEM_callocN(sizeof(SoftBody), "softbody");
 
1143
        
 
1144
        sb->mediafrict= 0.5; 
 
1145
        sb->nodemass= 1.0;
 
1146
        sb->grav= 0.0; 
 
1147
        sb->physics_speed= 1.0;
 
1148
        sb->rklimit= 0.1;
 
1149
 
 
1150
        sb->goalspring= 0.5; 
 
1151
        sb->goalfrict= 0.0; 
 
1152
        sb->mingoal= 0.0;  
 
1153
        sb->maxgoal= 1.0;
 
1154
        sb->defgoal= 0.7;
 
1155
        
 
1156
        sb->inspring= 0.5;
 
1157
        sb->infrict= 0.5; 
 
1158
        
 
1159
        sb->interval= 10;
 
1160
        sb->sfra= G.scene->r.sfra;
 
1161
        sb->efra= G.scene->r.efra;
 
1162
        
 
1163
        return sb;
 
1164
}
 
1165
 
 
1166
/* frees all */
 
1167
void sbFree(SoftBody *sb)
 
1168
{
 
1169
        free_softbody_intern(sb);
 
1170
        MEM_freeN(sb);
 
1171
}
 
1172
 
 
1173
 
 
1174
/* makes totally fresh start situation */
 
1175
void sbObjectToSoftbody(Object *ob)
 
1176
{
 
1177
 
 
1178
        switch(ob->type) {
 
1179
        case OB_MESH:
 
1180
                mesh_to_softbody(ob);
 
1181
                break;
 
1182
        case OB_LATTICE:
 
1183
                lattice_to_softbody(ob);
 
1184
                break;
 
1185
        }
 
1186
        
 
1187
        if(ob->soft) ob->soft->ctime= bsystem_time(ob, NULL, (float)G.scene->r.cfra, 0.0);
 
1188
        ob->softflag &= ~OB_SB_REDO;
 
1189
}
 
1190
 
 
1191
/* reset all motion */
 
1192
void sbObjectReset(Object *ob)
 
1193
{
 
1194
        SoftBody *sb= ob->soft;
 
1195
        BodyPoint *bp;
 
1196
        int a;
 
1197
        
 
1198
        if(sb==NULL) return;
 
1199
        if(sb->keys && sb->totkey) return; // only as cpu time saver
 
1200
        
 
1201
        sb->ctime= bsystem_time(ob, NULL, (float)G.scene->r.cfra, 0.0);
 
1202
        
 
1203
        object_update_softbody(ob);
 
1204
        
 
1205
        for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
 
1206
                // origS is previous timestep
 
1207
                VECCOPY(bp->origS, bp->origE);
 
1208
                VECCOPY(bp->pos, bp->origE);
 
1209
                VECCOPY(bp->origT, bp->origE);
 
1210
                bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0f;
 
1211
 
 
1212
                // no idea about the Heun stuff! (ton)
 
1213
                VECCOPY(bp->prevpos, bp->pos);
 
1214
                VECCOPY(bp->prevvec, bp->vec);
 
1215
                VECCOPY(bp->prevdx, bp->vec);
 
1216
                VECCOPY(bp->prevdv, bp->vec);
 
1217
        }
 
1218
}
 
1219
 
 
1220
 
 
1221
/* simulates one step. framenr is in frames */
 
1222
/* copies result back to object, displist */
 
1223
void sbObjectStep(Object *ob, float framenr)
 
1224
{
 
1225
        SoftBody *sb;
 
1226
        Base *base;
 
1227
        float dtime;
 
1228
        int timescale,t;
 
1229
        float ctime, forcetime;
 
1230
        float err;
 
1231
 
 
1232
        /* this variable is set while transform(). with lattices also having a softbody, 
 
1233
           it calls lattice_modifier() all the time... has no displist yet. Is temporal
 
1234
           hack which should be resolved with proper depgraph usage + storage of deformed
 
1235
           vertices in lattice (ton) */
 
1236
        if(G.moving) return;
 
1237
        
 
1238
        /* baking works with global time */
 
1239
        if(!(ob->softflag & OB_SB_BAKEDO) )
 
1240
                if(softbody_baked_step(ob, framenr) ) return;
 
1241
        
 
1242
        /* remake softbody if: */
 
1243
        if( (ob->softflag & OB_SB_REDO) ||              // signal after weightpainting
 
1244
                (ob->soft==NULL) ||                                     // just to be nice we allow full init
 
1245
                (ob->soft->bpoint==NULL) )                      // after reading new file, or acceptable as signal to refresh
 
1246
                        sbObjectToSoftbody(ob);
 
1247
        
 
1248
        sb= ob->soft;
 
1249
 
 
1250
        /* still no points? go away */
 
1251
        if(sb->totpoint==0) return;
 
1252
        
 
1253
        /* reset deflector cache, sumohandle is free, but its still sorta abuse... (ton) */
 
1254
        for(base= G.scene->base.first; base; base= base->next) {
 
1255
                base->object->sumohandle= NULL;
 
1256
        }
 
1257
 
 
1258
        /* checking time: */
 
1259
        ctime= bsystem_time(ob, NULL, framenr, 0.0);
 
1260
        dtime= ctime - sb->ctime;
 
1261
                // bail out for negative or for large steps
 
1262
        if(dtime<0.0 || dtime >= 9.9*G.scene->r.framelen) { // G.scene->r.framelen corrects for frame-mapping, so this is actually 10 frames for UI
 
1263
                sbObjectReset(ob);
 
1264
                return;
 
1265
        }
 
1266
        
 
1267
        /* the simulator */
 
1268
        
 
1269
        if(dtime > 0.0) {       // note: what does this mean now? (ton)
 
1270
                //answer (BM) :
 
1271
                //dtime is still in [frames]
 
1272
                //we made sure dtime is >= 0.0
 
1273
                //but still need to handle dtime == 0.0 -> just return sb as is, just to be nice
 
1274
                object_update_softbody(ob);
 
1275
                
 
1276
                if (TRUE) {     // RSOL1 always true now (ton)
 
1277
                        /* special case of 2nd order Runge-Kutta type AKA Heun */
 
1278
                        float timedone =0.0; // how far did we get without violating error condition
 
1279
                        /* loops = counter for emergency brake
 
1280
                         * we don't want to lock up the system if physics fail
 
1281
                         */
 
1282
                        int loops =0 ; 
 
1283
                        SoftHeunTol = sb->rklimit; // humm .. this should be calculated from sb parameters and sizes
 
1284
 
 
1285
                        forcetime = dtime; /* hope for integrating in one step */
 
1286
                        while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) )
 
1287
                        {
 
1288
                                if (ABS(dtime) > 9.0 ){
 
1289
                                        if(G.f & G_DEBUG) printf("SB_STEPSIZE \n");
 
1290
                                        break; // sorry but i must assume goal movement can't be interpolated any more
 
1291
                                }
 
1292
                                //set goals in time
 
1293
                                interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime)));
 
1294
                                // do predictive euler step
 
1295
                                softbody_calc_forces(ob, forcetime);
 
1296
                                softbody_apply_forces(ob, forcetime, 1, NULL);
 
1297
                                // crop new slope values to do averaged slope step
 
1298
                                softbody_calc_forces(ob, forcetime);
 
1299
                                softbody_apply_forces(ob, forcetime, 2, &err);
 
1300
                                softbody_apply_goalsnap(ob);
 
1301
 
 
1302
                                if (err > SoftHeunTol){ // error needs to be scaled to some quantity
 
1303
                                        softbody_restore_prev_step(ob);
 
1304
                                        forcetime /= 2.0;
 
1305
                                }
 
1306
                                else {
 
1307
                                        float newtime = forcetime * 1.1f; // hope for 1.1 times better conditions in next step
 
1308
                                        
 
1309
                                        if (err > SoftHeunTol/2.0){ // stay with this stepsize unless err really small
 
1310
                                                newtime = forcetime;
 
1311
                                        }
 
1312
                                        timedone += forcetime;
 
1313
                                        if (forcetime > 0.0)
 
1314
                                                forcetime = MIN2(dtime - timedone,newtime);
 
1315
                                        else 
 
1316
                                                forcetime = MAX2(dtime - timedone,newtime);
 
1317
                                }
 
1318
                                loops++;
 
1319
                        }
 
1320
                        // move snapped to final position
 
1321
                        interpolate_exciter(ob, 2, 2);
 
1322
                        softbody_apply_goalsnap(ob);
 
1323
                        
 
1324
                        if(G.f & G_DEBUG) {
 
1325
                                if (loops > HEUNWARNLIMIT) /* monitor high loop counts say 1000 after testing */
 
1326
                                        printf("%d heun integration loops/frame \n",loops);
 
1327
                        }
 
1328
                }
 
1329
                else{
 
1330
                        /* do brute force explicit euler */
 
1331
                        /* inner intagration loop */
 
1332
                        /* */
 
1333
                        // loop n times so that n*h = duration of one frame := 1
 
1334
                        // x(t+h) = x(t) + h*v(t);
 
1335
                        // v(t+h) = v(t) + h*f(x(t),t);
 
1336
                        timescale = (int)(sb->rklimit * ABS(dtime)); 
 
1337
                        for(t=1 ; t <= timescale; t++) {
 
1338
                                if (ABS(dtime) > 15 ) break;
 
1339
                                
 
1340
                                /* the *goal* mesh must use the n*h timing too !
 
1341
                                use *cheap* linear intepolation for that  */
 
1342
                                interpolate_exciter(ob,timescale,t);                    
 
1343
                                if (timescale > 0 ) {
 
1344
                                        forcetime = dtime/timescale;
 
1345
                                        
 
1346
                                        /* does not fit the concept sloving ODEs :) */
 
1347
                                        /*                      softbody_apply_goal(ob,forcetime );  */
 
1348
                                        
 
1349
                                        /* explicit Euler integration */
 
1350
                                        /* we are not controling a nuclear power plant! 
 
1351
                                        so rought *almost* physical behaviour is acceptable.
 
1352
                                        in cases of *mild* stiffnes cranking up timscale -> decreasing stepsize *h*
 
1353
                                        avoids instability      */
 
1354
                                        softbody_calc_forces(ob,forcetime);
 
1355
                                        softbody_apply_forces(ob,forcetime,0, NULL);
 
1356
                                        softbody_apply_goalsnap(ob);
 
1357
                                        
 
1358
                                        //      if (0){
 
1359
                                        /* ok here comes the �berhammer
 
1360
                                        use a semi implicit euler integration to tackle *all* stiff conditions 
 
1361
                                        but i doubt the cost/benifit holds for most of the cases
 
1362
                                        -- to be coded*/
 
1363
                                        //      }
 
1364
                                        
 
1365
                                }
 
1366
                        }
 
1367
                }
 
1368
                
 
1369
                /* and apply to vertices */
 
1370
                 softbody_to_object(ob);
 
1371
                
 
1372
                sb->ctime= ctime;
 
1373
        } // if(ABS(dtime) > 0.0) 
 
1374
        else {
 
1375
                // rule : you have asked for the current state of the softobject 
 
1376
                // since dtime= ctime - ob->soft->ctime== 0.0;
 
1377
                // and we were not notifified about any other time changes 
 
1378
                // so here it is !
 
1379
                softbody_to_object(ob);
 
1380
        }
 
1381
 
 
1382
        /* reset deflector cache */
 
1383
        for(base= G.scene->base.first; base; base= base->next) {
 
1384
                if(base->object->sumohandle) {
 
1385
                        MEM_freeN(base->object->sumohandle);
 
1386
                        base->object->sumohandle= NULL;
 
1387
                }
 
1388
        }
 
1389
        
 
1390
        if(ob->softflag & OB_SB_BAKEDO) softbody_baked_add(ob, framenr);
 
1391
}
 
1392