~ubuntu-branches/ubuntu/maverick/blender/maverick

« back to all changes in this revision

Viewing changes to source/blender/src/fluidsim.c

  • Committer: Bazaar Package Importer
  • Author(s): Khashayar Naderehvandi, Khashayar Naderehvandi, Alessio Treglia
  • Date: 2009-01-22 16:53:59 UTC
  • mfrom: (14.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090122165359-v0996tn7fbit64ni
Tags: 2.48a+dfsg-1ubuntu1
[ Khashayar Naderehvandi ]
* Merge from debian experimental (LP: #320045), Ubuntu remaining changes:
  - Add patch correcting header file locations.
  - Add libvorbis-dev and libgsm1-dev to Build-Depends.
  - Use avcodec_decode_audio2() in source/blender/src/hddaudio.c

[ Alessio Treglia ]
* Add missing previous changelog entries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**
2
2
 * fluidsim.c
3
3
 * 
4
 
 * $Id: fluidsim.c 14669 2008-05-04 09:41:15Z campbellbarton $
 
4
 * $Id: fluidsim.c 17013 2008-10-11 04:30:09Z campbellbarton $
5
5
 *
6
6
 * ***** BEGIN GPL LICENSE BLOCK *****
7
7
 *
55
55
#include "DNA_key_types.h" 
56
56
 
57
57
#include "BLI_blenlib.h"
 
58
#include "BLI_threads.h"
58
59
#include "BLI_arithb.h"
59
60
#include "MTC_matrixops.h"
60
61
 
61
62
#include "BKE_customdata.h"
62
63
#include "BKE_displist.h"
63
64
#include "BKE_effect.h"
 
65
#include "BKE_fluidsim.h"
64
66
#include "BKE_global.h"
 
67
#include "BKE_modifier.h"
65
68
#include "BKE_main.h"
66
69
#include "BKE_key.h"
67
70
#include "BKE_scene.h"
84
87
 
85
88
#include "mydevice.h"
86
89
#include "blendef.h"
87
 
#include "SDL.h"
88
 
#include "SDL_thread.h"
89
 
#include "SDL_mutex.h"
90
90
#include <sys/stat.h>
91
91
 
92
92
#ifdef WIN32    /* Windos */
95
95
#define snprintf _snprintf
96
96
#endif
97
97
#endif
98
 
// SDL redefines main for SDL_main, not needed here...
99
 
#undef main
100
 
 
101
 
#ifdef __APPLE__        /* MacOS X */
102
 
#undef main
103
 
#endif
104
 
 
105
 
// from DerivedMesh.c
106
 
void initElbeemMesh(struct Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords);
107
98
 
108
99
/* from header info.c */
109
100
extern int start_progress_bar(void);
128
119
        "INVALID"       /* end */
129
120
};
130
121
 
131
 
typedef struct {
132
 
        DerivedMesh dm;
133
 
 
134
 
        // similar to MeshDerivedMesh
135
 
        struct Object *ob;      // pointer to parent object
136
 
        float *extverts, *nors; // face normals, colors?
137
 
        Mesh *fsmesh;   // mesh struct to display (either surface, or original one)
138
 
        char meshFree;  // free the mesh afterwards? (boolean)
139
 
} fluidsimDerivedMesh;
140
 
 
141
 
 
142
 
 
143
122
/* enable/disable overall compilation */
144
123
#ifndef DISABLE_ELBEEM
145
124
 
146
125
 
147
126
/* ********************** fluid sim settings struct functions ********************** */
148
127
 
149
 
/* allocates and initializes general main data */
150
 
 
151
 
FluidsimSettings *fluidsimSettingsNew(struct Object *srcob)
152
 
{
153
 
        //char blendDir[FILE_MAXDIR], blendFile[FILE_MAXFILE];
154
 
        FluidsimSettings *fss;
155
 
        
156
 
        /* this call uses derivedMesh methods... */
157
 
        if(srcob->type!=OB_MESH) return NULL;
158
 
        
159
 
        fss= MEM_callocN( sizeof(FluidsimSettings), "fluidsimsettings memory");
160
 
        
161
 
        fss->type = 0;
162
 
        fss->show_advancedoptions = 0;
163
 
 
164
 
        fss->resolutionxyz = 50;
165
 
        fss->previewresxyz = 25;
166
 
        fss->realsize = 0.03;
167
 
        fss->guiDisplayMode = 2; // preview
168
 
        fss->renderDisplayMode = 3; // render
169
 
 
170
 
        fss->viscosityMode = 2; // default to water
171
 
        fss->viscosityValue = 1.0;
172
 
        fss->viscosityExponent = 6;
173
 
        fss->gravx = 0.0;
174
 
        fss->gravy = 0.0;
175
 
        fss->gravz = -9.81;
176
 
        fss->animStart = 0.0; 
177
 
        fss->animEnd = 0.30;
178
 
        fss->gstar = 0.005; // used as normgstar
179
 
        fss->maxRefine = -1;
180
 
        // maxRefine is set according to resolutionxyz during bake
181
 
 
182
 
        // fluid/inflow settings
183
 
        fss->iniVelx = 
184
 
        fss->iniVely = 
185
 
        fss->iniVelz = 0.0;
186
 
 
187
 
        /*  elubie: changed this to default to the same dir as the render output
188
 
                to prevent saving to C:\ on Windows */
189
 
        BLI_strncpy(fss->surfdataPath, btempdir, FILE_MAX); 
190
 
        fss->orgMesh = (Mesh *)srcob->data;
191
 
        fss->meshSurface = NULL;
192
 
        fss->meshBB = NULL;
193
 
        fss->meshSurfNormals = NULL;
194
 
 
195
 
        // first init of bounding box
196
 
        fss->bbStart[0] = 0.0;
197
 
        fss->bbStart[1] = 0.0;
198
 
        fss->bbStart[2] = 0.0;
199
 
        fss->bbSize[0] = 1.0;
200
 
        fss->bbSize[1] = 1.0;
201
 
        fss->bbSize[2] = 1.0;
202
 
        fluidsimGetAxisAlignedBB(srcob->data, srcob->obmat, fss->bbStart, fss->bbSize, &fss->meshBB);
203
 
        
204
 
        // todo - reuse default init from elbeem!
205
 
        fss->typeFlags = 0;
206
 
        fss->domainNovecgen = 0;
207
 
        fss->volumeInitType = 1; // volume
208
 
        fss->partSlipValue = 0.0;
209
 
 
210
 
        fss->generateTracers = 0;
211
 
        fss->generateParticles = 0.0;
212
 
        fss->surfaceSmoothing = 1.0;
213
 
        fss->surfaceSubdivs = 1.0;
214
 
        fss->particleInfSize = 0.0;
215
 
        fss->particleInfAlpha = 0.0;
216
 
 
217
 
        return fss;
218
 
}
219
 
 
220
 
/* duplicate struct, analogous to free */
221
 
static Mesh *fluidsimCopyMesh(Mesh *me)
222
 
{
223
 
        Mesh *dup = MEM_dupallocN(me);
224
 
 
225
 
        CustomData_copy(&me->vdata, &dup->vdata, CD_MASK_MESH, CD_DUPLICATE, me->totvert);
226
 
        CustomData_copy(&me->edata, &dup->edata, CD_MASK_MESH, CD_DUPLICATE, me->totedge);
227
 
        CustomData_copy(&me->fdata, &dup->fdata, CD_MASK_MESH, CD_DUPLICATE, me->totface);
228
 
 
229
 
        return dup;
230
 
}
231
 
 
232
 
FluidsimSettings* fluidsimSettingsCopy(FluidsimSettings *fss)
233
 
{
234
 
        FluidsimSettings *dupfss;
235
 
 
236
 
        if(!fss) return NULL;
237
 
        dupfss = MEM_dupallocN(fss);
238
 
 
239
 
        if(fss->meshSurface)
240
 
                dupfss->meshSurface = fluidsimCopyMesh(fss->meshSurface);
241
 
        if(fss->meshBB)
242
 
                dupfss->meshBB = fluidsimCopyMesh(fss->meshBB);
243
 
 
244
 
        if(fss->meshSurfNormals) dupfss->meshSurfNormals = MEM_dupallocN(fss->meshSurfNormals);
245
 
 
246
 
        return dupfss;
247
 
}
248
 
 
249
 
/* free struct */
250
 
static void fluidsimFreeMesh(Mesh *me)
251
 
{
252
 
        CustomData_free(&me->vdata, me->totvert);
253
 
        CustomData_free(&me->edata, me->totedge);
254
 
        CustomData_free(&me->fdata, me->totface);
255
 
 
256
 
        MEM_freeN(me);
257
 
}
258
 
 
259
 
void fluidsimSettingsFree(FluidsimSettings *fss)
260
 
{
261
 
        if(fss->meshSurface) {
262
 
                fluidsimFreeMesh(fss->meshSurface);
263
 
                fss->meshSurface = NULL;
264
 
        }
265
 
        if(fss->meshBB) {
266
 
                fluidsimFreeMesh(fss->meshBB);
267
 
                fss->meshBB = NULL;
268
 
        }
269
 
 
270
 
        if(fss->meshSurfNormals){ MEM_freeN(fss->meshSurfNormals); fss->meshSurfNormals=NULL; } 
271
 
 
272
 
        MEM_freeN(fss);
273
 
}
274
 
 
275
 
 
276
128
/* helper function */
277
129
void fluidsimGetGeometryObjFilename(struct Object *ob, char *dst) { //, char *srcname) {
278
130
        //snprintf(dst,FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
306
158
                FS_FREE_ONECHANNEL(channelObjMove[i][2],"channelObjMove2"); \
307
159
                FS_FREE_ONECHANNEL(channelObjInivel[i],"channelObjInivel"); \
308
160
                FS_FREE_ONECHANNEL(channelObjActive[i],"channelObjActive"); \
 
161
                FS_FREE_ONECHANNEL(channelAttractforceStrength[i],"channelAttractforceStrength"); \
 
162
                FS_FREE_ONECHANNEL(channelAttractforceRadius[i],"channelAttractforceRadius"); \
 
163
                FS_FREE_ONECHANNEL(channelVelocityforceStrength[i],"channelVelocityforceStrength"); \
 
164
                FS_FREE_ONECHANNEL(channelVelocityforceRadius[i],"channelVelocityforceRadius"); \
309
165
        }  \
310
166
} // end FS FREE CHANNELS
311
167
 
387
243
        *setchannel = channel;
388
244
}
389
245
 
390
 
static void fluidsimInitMeshChannel(float **setchannel, int size, Object *obm, int vertices, float *time) {
 
246
static void fluidsimInitMeshChannel(float **setchannel, int size, Object *obm, int vertices, float *time, int modifierIndex) {
391
247
        float *channel = NULL;
392
248
        int mallsize = size* (3*vertices+1);
393
249
        int frame,i;
403
259
                G.scene->r.cfra = frame;
404
260
                scene_update_for_newframe(G.scene, G.scene->lay);
405
261
 
406
 
                initElbeemMesh(obm, &numVerts, &verts, &numTris, &tris, 1);
 
262
                initElbeemMesh(obm, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
407
263
                //fprintf(stderr,"\nfluidsimInitMeshChannel frame%d verts%d/%d \n\n",frame,vertices,numVerts);
408
264
                for(i=0; i<3*vertices;i++) {
409
265
                        channel[(frame-1)*setsize + i] = verts[i];
423
279
/* ********************** simulation thread             ************************* */
424
280
/* ******************************************************************************** */
425
281
 
426
 
SDL_mutex       *globalBakeLock=NULL;
427
 
int                     globalBakeState = 0; // 0 everything ok, -1 abort simulation, -2 sim error, 1 sim done
428
 
int                     globalBakeFrame = 0;
 
282
static volatile int     globalBakeState = 0; // 0 everything ok, -1 abort simulation, -2 sim error, 1 sim done
 
283
static volatile int     globalBakeFrame = 0;
 
284
static volatile int g_break= 0;
429
285
 
430
286
// run simulation in seperate thread
431
 
static int fluidsimSimulateThread(void *unused) { // *ptr) {
 
287
static void *fluidsimSimulateThread(void *unused) { // *ptr) {
432
288
        //char* fnameCfgPath = (char*)(ptr);
433
289
        int ret=0;
434
290
        
435
291
        ret = elbeemSimulate();
436
 
        SDL_mutexP(globalBakeLock);
 
292
        BLI_lock_thread(LOCK_CUSTOM1);
437
293
        if(globalBakeState==0) {
438
294
                if(ret==0) {
439
295
                        // if no error, set to normal exit
443
299
                        globalBakeState = -2;
444
300
                }
445
301
        }
446
 
        SDL_mutexV(globalBakeLock);
447
 
        return ret;
 
302
        BLI_unlock_thread(LOCK_CUSTOM1);
 
303
        return NULL;
448
304
}
449
305
 
450
306
 
451
307
int runSimulationCallback(void *data, int status, int frame) {
452
308
        //elbeemSimulationSettings *settings = (elbeemSimulationSettings*)data;
453
309
        //printf("elbeem blender cb s%d, f%d, domainid:%d \n", status,frame, settings->domainId ); // DEBUG
454
 
        
455
 
        if(!globalBakeLock) return FLUIDSIM_CBRET_ABORT;
 
310
        int state = 0;
456
311
        if(status==FLUIDSIM_CBSTATUS_NEWFRAME) {
457
 
                SDL_mutexP(globalBakeLock);
 
312
                BLI_lock_thread(LOCK_CUSTOM1);
458
313
                globalBakeFrame = frame-1;
459
 
                SDL_mutexV(globalBakeLock);
 
314
                BLI_unlock_thread(LOCK_CUSTOM1);
460
315
        }
461
316
        
462
317
        //if((frameCounter==3) && (!frameStop)) { frameStop=1; return 1; }
463
318
                
464
 
        SDL_mutexP(globalBakeLock);
465
 
        if(globalBakeState!=0) {
 
319
        BLI_lock_thread(LOCK_CUSTOM1);
 
320
        state = globalBakeState;
 
321
        BLI_unlock_thread(LOCK_CUSTOM1);
 
322
        
 
323
        if(state!=0) {
466
324
                return FLUIDSIM_CBRET_ABORT;
467
325
        }
468
 
        SDL_mutexV(globalBakeLock);
 
326
        
469
327
        return FLUIDSIM_CBRET_CONTINUE;
470
328
}
471
329
 
481
339
        struct Object *fsDomain = NULL;
482
340
        FluidsimSettings *domainSettings;
483
341
        struct Object *obit = NULL; /* object iterator */
 
342
        Base *base;
484
343
        int origFrame = G.scene->r.cfra;
485
344
        char debugStrBuffer[256];
486
345
        int dirExist = 0;
522
381
        float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale
523
382
        float *channelObjInivel[256];    // initial velocities
524
383
        float *channelObjActive[256];    // obj active channel
525
 
 
 
384
        
 
385
        /* fluid control channels */
 
386
        float *channelAttractforceStrength[256];
 
387
        float *channelAttractforceRadius[256];
 
388
        float *channelVelocityforceStrength[256];
 
389
        float *channelVelocityforceRadius[256];
 
390
        FluidsimModifierData *fluidmd = NULL;
 
391
        Mesh *mesh = NULL;
 
392
        
526
393
        if(getenv(strEnvName)) {
527
394
                int dlevel = atoi(getenv(strEnvName));
528
395
                elbeemSetDebugLevel(dlevel);
545
412
 
546
413
        /* no object pointer, find in selected ones.. */
547
414
        if(!ob) {
548
 
                Base *base;
549
415
                for(base=G.scene->base.first; base; base= base->next) {
550
 
                        if ( ((base)->flag & SELECT) 
551
 
                                        // ignore layer setting for now? && ((base)->lay & G.vd->lay) 
552
 
                                 ) {
553
 
                                if((!ob)&&(base->object->fluidsimFlag & OB_FLUIDSIM_ENABLE)&&(base->object->type==OB_MESH)) {
554
 
                                        if(base->object->fluidsimSettings->type == OB_FLUIDSIM_DOMAIN) {
 
416
                        if ((base)->flag & SELECT) 
 
417
                        {
 
418
                                FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
 
419
                                
 
420
                                if(fluidmdtmp && (base->object->type==OB_MESH)) 
 
421
                                {
 
422
                                        if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) 
 
423
                                        {
555
424
                                                ob = base->object;
 
425
                                                break;
556
426
                                        }
557
427
                                }
558
428
                        }
560
430
                // no domains found?
561
431
                if(!ob) return;
562
432
        }
 
433
        
 
434
        channelObjCount = 0;
 
435
        for(base=G.scene->base.first; base; base= base->next) 
 
436
        {
 
437
                FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
 
438
                obit = base->object;
 
439
                if( fluidmdtmp && 
 
440
                        (obit->type==OB_MESH) &&
 
441
                        (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&  // if has to match 3 places! // CHECKMATCH
 
442
                        (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) 
 
443
                {
 
444
                        channelObjCount++;
 
445
                }
 
446
        }
 
447
        
 
448
        if (channelObjCount>=255) {
 
449
                pupmenu("Fluidsim Bake Error%t|Cannot bake with more then 256 objects");
 
450
                return;
 
451
        }
563
452
 
564
453
        /* check if there's another domain... */
565
 
        for(obit= G.main->object.first; obit; obit= obit->id.next) {
566
 
                if((obit->fluidsimFlag & OB_FLUIDSIM_ENABLE)&&(obit->type==OB_MESH)) {
567
 
                        if(obit->fluidsimSettings->type == OB_FLUIDSIM_DOMAIN) {
568
 
                                if(obit != ob) {
569
 
                                        //snprintf(debugStrBuffer,256,"fluidsimBake::warning - More than one domain!\n"); elbeemDebugOut(debugStrBuffer);
 
454
        for(base=G.scene->base.first; base; base= base->next) 
 
455
        {
 
456
                FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
 
457
                obit = base->object;
 
458
                if( fluidmdtmp &&(obit->type==OB_MESH)) 
 
459
                {
 
460
                        if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) 
 
461
                        {
 
462
                                if(obit != ob) 
 
463
                                {
570
464
                                        pupmenu("Fluidsim Bake Error%t|There should be only one domain object! Aborted%x0");
571
465
                                        return;
572
466
                                }
573
467
                        }
574
468
                }
575
469
        }
 
470
        
 
471
        // check if theres any fluid
 
472
        // abort baking if not...
 
473
        for(base=G.scene->base.first; base; base= base->next) 
 
474
        {
 
475
                FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
 
476
                obit = base->object;
 
477
                if( fluidmdtmp && 
 
478
                        (obit->type==OB_MESH) && 
 
479
                        ((fluidmdtmp->fss->type == OB_FLUIDSIM_FLUID) ||
 
480
                        (fluidmdtmp->fss->type == OB_FLUIDSIM_INFLOW) ))
 
481
                {
 
482
                        haveSomeFluid = 1;
 
483
                        break;
 
484
                }
 
485
        }
 
486
        if(!haveSomeFluid) {
 
487
                pupmenu("Fluidsim Bake Error%t|No fluid objects in scene... Aborted%x0");
 
488
                return;
 
489
        }
 
490
        
576
491
        /* these both have to be valid, otherwise we wouldnt be here */
577
492
        /* dont use ob here after...*/
578
493
        fsDomain = ob;
579
 
        domainSettings = ob->fluidsimSettings;
 
494
        fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
 
495
        domainSettings = fluidmd->fss;
580
496
        ob = NULL;
 
497
        mesh = fsDomain->data;
 
498
        
 
499
        // calculate bounding box
 
500
        fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize);
 
501
        
 
502
        // reset last valid frame
 
503
        domainSettings->lastgoodframe = -1;
 
504
        
581
505
        /* rough check of settings... */
582
506
        if(domainSettings->previewresxyz > domainSettings->resolutionxyz) {
583
507
                snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz ,  domainSettings->resolutionxyz); 
602
526
        }
603
527
        snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels ); 
604
528
        elbeemDebugOut(debugStrBuffer);
605
 
        
606
 
        // check if theres any fluid
607
 
        // abort baking if not...
608
 
        for(obit= G.main->object.first; obit; obit= obit->id.next) {
609
 
                if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && 
610
 
                                (obit->type==OB_MESH) && (
611
 
                          (obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) ||
612
 
                          (obit->fluidsimSettings->type == OB_FLUIDSIM_INFLOW) )
613
 
                                ) {
614
 
                        haveSomeFluid = 1;
615
 
                }
616
 
        }
617
 
        if(!haveSomeFluid) {
618
 
                pupmenu("Fluidsim Bake Error%t|No fluid objects in scene... Aborted%x0");
619
 
                return;
620
 
        }
621
529
 
622
530
        // prepare names...
623
531
        strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
681
589
        // dump data for start frame 
682
590
        // CHECK more reasonable to number frames according to blender?
683
591
        // dump data for frame 0
684
 
  G.scene->r.cfra = startFrame;
685
 
  scene_update_for_newframe(G.scene, G.scene->lay);
 
592
        G.scene->r.cfra = startFrame;
 
593
        scene_update_for_newframe(G.scene, G.scene->lay);
686
594
        
687
595
        // init common export vars for both file export and run
688
596
        for(i=0; i<256; i++) {
689
597
                channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL;
690
598
                channelObjInivel[i] = NULL;
691
599
                channelObjActive[i] = NULL;
 
600
                channelAttractforceStrength[i] = NULL;
 
601
                channelAttractforceRadius[i] = NULL;
 
602
                channelVelocityforceStrength[i] = NULL;
 
603
                channelVelocityforceRadius[i] = NULL;
692
604
        }
693
605
        allchannelSize = G.scene->r.efra; // always use till last frame
694
606
        aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames;
701
613
                calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ];
702
614
        }
703
615
 
704
 
        bbStart = fsDomain->fluidsimSettings->bbStart; 
705
 
        bbSize = fsDomain->fluidsimSettings->bbSize;
706
 
        fluidsimGetAxisAlignedBB(fsDomain->data, fsDomain->obmat, bbStart, bbSize, &domainSettings->meshBB);
 
616
        bbStart = domainSettings->bbStart;
 
617
        bbSize = domainSettings->bbSize;
707
618
 
708
619
        // always init
709
620
        { int timeIcu[1] = { FLUIDSIM_TIME };
749
660
        
750
661
        // init obj movement channels
751
662
        channelObjCount=0;
752
 
        for(obit= G.main->object.first; obit; obit= obit->id.next) {
753
 
                //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
754
 
                if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && 
755
 
                                (obit->type==OB_MESH) &&
756
 
                                (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) &&  // if has to match 3 places! // CHECKMATCH
757
 
                                (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE) ) {
 
663
        for(base=G.scene->base.first; base; base= base->next) 
 
664
        {
 
665
                FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
 
666
                obit = base->object;
 
667
                
 
668
                if( fluidmdtmp && 
 
669
                        (obit->type==OB_MESH) &&
 
670
                        (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&  // if has to match 3 places! // CHECKMATCH
 
671
                        (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) {
758
672
 
759
673
                        //  cant use fluidsimInitChannel for obj channels right now, due
760
674
                        //  to the special DXXX channels, and the rotation specialities
781
695
                        int   activeIcu[1] =  { FLUIDSIM_ACTIVE };
782
696
                        float activeDefs[1] = { 1 }; // default to on
783
697
 
784
 
                        inivelDefs[0] = obit->fluidsimSettings->iniVelx;
785
 
                        inivelDefs[1] = obit->fluidsimSettings->iniVely;
786
 
                        inivelDefs[2] = obit->fluidsimSettings->iniVelz;
 
698
                        inivelDefs[0] = fluidmdtmp->fss->iniVelx;
 
699
                        inivelDefs[1] = fluidmdtmp->fss->iniVely;
 
700
                        inivelDefs[2] = fluidmdtmp->fss->iniVelz;
787
701
 
788
702
                        // check & init loc,rot,size
789
703
                        for(j=0; j<3; j++) {
852
766
                                        channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i];
853
767
                                }
854
768
                        }
 
769
                        
 
770
                        {
 
771
                                int   attrFSIcu[1] =  { FLUIDSIM_ATTR_FORCE_STR };
 
772
                                int   attrFRIcu[1] =  { FLUIDSIM_ATTR_FORCE_RADIUS };
 
773
                                int   velFSIcu[1] =  { FLUIDSIM_VEL_FORCE_STR };
 
774
                                int   velFRIcu[1] =  { FLUIDSIM_VEL_FORCE_RADIUS };
855
775
 
856
 
                        fluidsimInitChannel( &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, obit->fluidsimSettings->ipo, CHANNEL_VEC );
857
 
                        fluidsimInitChannel( &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, obit->fluidsimSettings->ipo, CHANNEL_FLOAT );
 
776
                                float attrFSDefs[1];
 
777
                                float attrFRDefs[1];
 
778
                                float velFSDefs[1];
 
779
                                float velFRDefs[1];
 
780
                                
 
781
                                attrFSDefs[0] = fluidmdtmp->fss->attractforceStrength;
 
782
                                attrFRDefs[0] = fluidmdtmp->fss->attractforceRadius;
 
783
                                velFSDefs[0] = fluidmdtmp->fss->velocityforceStrength;
 
784
                                velFRDefs[0] = fluidmdtmp->fss->velocityforceRadius;
 
785
                                
 
786
                                fluidsimInitChannel( &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
 
787
                                fluidsimInitChannel( &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
 
788
                                fluidsimInitChannel( &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
 
789
                                fluidsimInitChannel( &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
 
790
                        }
 
791
                        
 
792
                        fluidsimInitChannel( &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, fluidmdtmp->fss->ipo, CHANNEL_VEC );
 
793
                        fluidsimInitChannel( &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
 
794
                
858
795
 
859
796
                        channelObjCount++;
860
797
 
883
820
        }
884
821
 
885
822
        if(!doExportOnly) {
886
 
                SDL_Thread *simthr = NULL;
 
823
                ListBase threads;
887
824
 
888
 
                // perform simulation with El'Beem api and SDL threads
 
825
                // perform simulation with El'Beem api and threads
889
826
                elbeemSimulationSettings fsset;
890
827
                elbeemResetSettings(&fsset);
891
828
                fsset.version = 1;
893
830
                // setup global settings
894
831
                for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i];
895
832
                for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i];
 
833
                
896
834
                // simulate with 50^3
897
835
                fsset.resolutionxyz = (int)domainSettings->resolutionxyz;
898
836
                fsset.previewresxyz = (int)domainSettings->previewresxyz;
906
844
                // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
907
845
                fsset.animStart = domainSettings->animStart;
908
846
                fsset.aniFrameTime = aniFrameTime;
909
 
                fsset.noOfFrames = noFrames - 1; // is otherwise subtracted in parser
 
847
                fsset.noOfFrames = noFrames; // is otherwise subtracted in parser
910
848
                strcpy(targetFile, targetDir);
911
849
                strcat(targetFile, suffixSurface);
912
850
                // defaults for compressibility and adaptive grids
952
890
                
953
891
                // init objects
954
892
                channelObjCount = 0;
955
 
                for(obit= G.main->object.first; obit; obit= obit->id.next) {
 
893
                for(base=G.scene->base.first; base; base= base->next) {
 
894
                        FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
 
895
                        obit = base->object;
956
896
                        //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
957
 
                        if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&  // if has to match 3 places! // CHECKMATCH
958
 
                                        (obit->type==OB_MESH) &&
959
 
                                        (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) &&
960
 
                                        (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE)
961
 
                                ) {
 
897
                        if( fluidmdtmp &&  // if has to match 3 places! // CHECKMATCH
 
898
                                (obit->type==OB_MESH) &&
 
899
                                (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&
 
900
                                (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE)) 
 
901
                        {
962
902
                                float *verts=NULL;
963
903
                                int *tris=NULL;
964
904
                                int numVerts=0, numTris=0;
965
905
                                int o = channelObjCount;
966
 
                                int     deform = (obit->fluidsimSettings->domainNovecgen); // misused value
 
906
                                int     deform = (fluidmdtmp->fss->domainNovecgen); // misused value
967
907
                                // todo - use blenderInitElbeemMesh
 
908
                                int modifierIndex = modifiers_indexInObject(obit, (ModifierData *)fluidmdtmp);
 
909
                                
968
910
                                elbeemMesh fsmesh;
969
911
                                elbeemResetMesh( &fsmesh );
970
 
                                fsmesh.type = obit->fluidsimSettings->type;;
 
912
                                fsmesh.type = fluidmdtmp->fss->type;
971
913
                                // get name of object for debugging solver
972
914
                                fsmesh.name = obit->id.name; 
973
915
 
974
 
                                initElbeemMesh(obit, &numVerts, &verts, &numTris, &tris, 0);
 
916
                                initElbeemMesh(obit, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
975
917
                                fsmesh.numVertices   = numVerts;
976
918
                                fsmesh.numTriangles  = numTris;
977
919
                                fsmesh.vertices      = verts;
988
930
                                fsmesh.channelScale            = channelObjMove[o][2];
989
931
                                fsmesh.channelActive           = channelObjActive[o];
990
932
                                if( (fsmesh.type == OB_FLUIDSIM_FLUID) ||
991
 
                                                (fsmesh.type == OB_FLUIDSIM_INFLOW) ) {
 
933
                                (fsmesh.type == OB_FLUIDSIM_INFLOW)) {
992
934
                                        fsmesh.channelInitialVel       = channelObjInivel[o];
993
 
                                  fsmesh.localInivelCoords = ((obit->fluidsimSettings->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0);
 
935
                                        fsmesh.localInivelCoords = ((fluidmdtmp->fss->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0);
994
936
                                } 
995
937
 
996
 
                                if(     (obit->fluidsimSettings->typeFlags&OB_FSBND_NOSLIP))   fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
997
 
                                else if((obit->fluidsimSettings->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
998
 
                                else if((obit->fluidsimSettings->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
999
 
                                fsmesh.obstaclePartslip = obit->fluidsimSettings->partSlipValue;
1000
 
                                fsmesh.volumeInitType = obit->fluidsimSettings->volumeInitType;
1001
 
                                fsmesh.obstacleImpactFactor = obit->fluidsimSettings->surfaceSmoothing; // misused value
 
938
                                if(     (fluidmdtmp->fss->typeFlags&OB_FSBND_NOSLIP))   fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
 
939
                                else if((fluidmdtmp->fss->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
 
940
                                else if((fluidmdtmp->fss->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
 
941
                                fsmesh.obstaclePartslip = fluidmdtmp->fss->partSlipValue;
 
942
                                fsmesh.volumeInitType = fluidmdtmp->fss->volumeInitType;
 
943
                                fsmesh.obstacleImpactFactor = fluidmdtmp->fss->surfaceSmoothing; // misused value
 
944
                                
 
945
                                if(fsmesh.type == OB_FLUIDSIM_CONTROL)
 
946
                                {
 
947
                                        // control fluids will get exported as whole
 
948
                                        deform = 1;
 
949
                                        
 
950
                                        fsmesh.cpsTimeStart = fluidmdtmp->fss->cpsTimeStart;
 
951
                                        fsmesh.cpsTimeEnd = fluidmdtmp->fss->cpsTimeEnd;
 
952
                                        fsmesh.cpsQuality = fluidmdtmp->fss->cpsQuality;
 
953
                                        fsmesh.obstacleType = (fluidmdtmp->fss->flag & OB_FLUIDSIM_REVERSE);
 
954
                                        
 
955
                                        fsmesh.channelSizeAttractforceRadius = 
 
956
                                        fsmesh.channelSizeVelocityforceStrength = 
 
957
                                        fsmesh.channelSizeVelocityforceRadius = 
 
958
                                        fsmesh.channelSizeAttractforceStrength = allchannelSize;
 
959
                                        
 
960
                                        fsmesh.channelAttractforceStrength = channelAttractforceStrength[o];
 
961
                                        fsmesh.channelAttractforceRadius = channelAttractforceRadius[o];
 
962
                                        fsmesh.channelVelocityforceStrength = channelVelocityforceStrength[o];
 
963
                                        fsmesh.channelVelocityforceRadius = channelVelocityforceRadius[o];
 
964
                                }
 
965
                                else 
 
966
                                {
 
967
                                        // set channels to 0
 
968
                                        fsmesh.channelAttractforceStrength =
 
969
                                        fsmesh.channelAttractforceRadius = 
 
970
                                        fsmesh.channelVelocityforceStrength = 
 
971
                                        fsmesh.channelVelocityforceRadius = NULL; 
 
972
                                }
1002
973
 
1003
974
                                // animated meshes
1004
975
                                if(deform) {
1005
976
                                        fsmesh.channelSizeVertices = allchannelSize;
1006
 
                                        fluidsimInitMeshChannel( &fsmesh.channelVertices, allchannelSize, obit, numVerts, timeAtFrame);
 
977
                                        fluidsimInitMeshChannel( &fsmesh.channelVertices, allchannelSize, obit, numVerts, timeAtFrame, modifierIndex);
1007
978
                                        G.scene->r.cfra = startFrame;
1008
979
                                        scene_update_for_newframe(G.scene, G.scene->lay);
1009
980
                                        // remove channels
1023
994
                //domainSettings->type = OB_FLUIDSIM_DOMAIN; // enable for bake display again
1024
995
                //fsDomain->fluidsimFlag = OB_FLUIDSIM_ENABLE; // disable during bake
1025
996
                
1026
 
                globalBakeLock = SDL_CreateMutex();
1027
997
                // set to neutral, -1 means user abort, -2 means init error
1028
998
                globalBakeState = 0;
1029
999
                globalBakeFrame = 0;
1030
 
                simthr = SDL_CreateThread(fluidsimSimulateThread, targetFile);
1031
 
 
1032
 
                if(!simthr) {
1033
 
                        snprintf(debugStrBuffer,256,"fluidsimBake::error: Unable to create thread... running without one.\n"); 
1034
 
                        elbeemDebugOut(debugStrBuffer);
1035
 
                        set_timecursor(0);
1036
 
                        elbeemSimulate();
1037
 
                } else {
 
1000
                BLI_init_threads(&threads, fluidsimSimulateThread, 1);
 
1001
                BLI_insert_thread(&threads, targetFile);
 
1002
                
 
1003
                {
1038
1004
                        int done = 0;
1039
1005
                        unsigned short event=0;
1040
1006
                        short val;
1042
1008
                        float percentdone = 0.0;
1043
1009
                        int lastRedraw = -1;
1044
1010
                        
 
1011
                        g_break= 0;
 
1012
                        G.afbreek= 0;   /* blender_test_break uses this global */
 
1013
                        
1045
1014
                        start_progress_bar();
1046
1015
 
1047
 
                        while(done==0) {            
 
1016
                        while(done==0) {
1048
1017
                                char busy_mess[80];
1049
1018
                                
1050
1019
                                waitcursor(1);
1054
1023
                                sprintf(busy_mess, "baking fluids %d / %d       |||", globalBakeFrame, (int) noFramesf);
1055
1024
                                progress_bar(percentdone, busy_mess );
1056
1025
                                
1057
 
                                SDL_Delay(2000); // longer delay to prevent frequent redrawing
1058
 
                                SDL_mutexP(globalBakeLock);
 
1026
                                // longer delay to prevent frequent redrawing
 
1027
                                PIL_sleep_ms(2000);
 
1028
                                
 
1029
                                BLI_lock_thread(LOCK_CUSTOM1);
1059
1030
                                if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort
1060
 
                                SDL_mutexV(globalBakeLock);
 
1031
                                BLI_unlock_thread(LOCK_CUSTOM1);
1061
1032
 
1062
 
                                while(qtest()) {
1063
 
                                        event = extern_qread(&val);
1064
 
                                        if(event == ESCKEY) {
 
1033
                                if (!G.background) {
 
1034
                                        g_break= blender_test_break();
 
1035
                                        
 
1036
                                        if(g_break)
 
1037
                                        {
1065
1038
                                                // abort...
1066
 
                                                SDL_mutexP(globalBakeLock);
 
1039
                                                BLI_lock_thread(LOCK_CUSTOM1);
 
1040
                                                
 
1041
                                                if(domainSettings)
 
1042
                                                        domainSettings->lastgoodframe = startFrame+globalBakeFrame;
 
1043
                                                
1067
1044
                                                done = -1;
1068
1045
                                                globalBakeFrame = 0;
1069
1046
                                                globalBakeState = -1;
1070
1047
                                                simAborted = 1;
1071
 
                                                SDL_mutexV(globalBakeLock);
 
1048
                                                BLI_unlock_thread(LOCK_CUSTOM1);
1072
1049
                                                break;
1073
1050
                                        }
1074
1051
                                } 
1087
1064
                                        screen_swapbuffers();
1088
1065
                                } // redraw
1089
1066
                        }
1090
 
                        SDL_WaitThread(simthr,NULL);
1091
1067
                        end_progress_bar();
1092
1068
                }
1093
 
                SDL_DestroyMutex(globalBakeLock);
1094
 
                globalBakeLock = NULL;
 
1069
                BLI_end_threads(&threads);
1095
1070
        } // El'Beem API init, thread creation 
1096
1071
        // --------------------------------------------------------------------------------------------
1097
1072
        else
1104
1079
 
1105
1080
        // go back to "current" blender time
1106
1081
        waitcursor(0);
 
1082
        
 
1083
        if(globalBakeState >= 0)
 
1084
        {
 
1085
                if(domainSettings)
 
1086
                        domainSettings->lastgoodframe = startFrame+globalBakeFrame;
 
1087
        }
 
1088
        
1107
1089
  G.scene->r.cfra = origFrame;
1108
1090
  scene_update_for_newframe(G.scene, G.scene->lay);
1109
1091
        allqueue(REDRAWVIEW3D, 0);
1124
1106
                        pupmenu(fsmessage);
1125
1107
                } // init error
1126
1108
        }
 
1109
        
 
1110
        // elbeemFree();
1127
1111
}
1128
1112
 
1129
1113
void fluidsimFreeBake(struct Object *ob)