- changed DerivedMesh integration, the fluidsim meshes now
authorNils Thuerey <nils@thuerey.de>
Wed, 23 Nov 2005 12:49:22 +0000 (12:49 +0000)
committerNils Thuerey <nils@thuerey.de>
Wed, 23 Nov 2005 12:49:22 +0000 (12:49 +0000)
  replace the original one. so modifiers now work with them
  (apply modifier, or edit mode still work on original mesh).
  this should fix the three fluidsim bugs in the tracker.
- fixed stupid makesdna problem (writing "char string[160+80]" isnt
  a good idea :)
- changed GUI a bit, now displays an estimate of the required memory,
  there's still a problem with redrawing (currently relies on a call
  to the derived mesh generation)
- the fluidsim struct changed to store the bounding box,
  and the current loaded surface mesh
- temporary simulation files are now removed if env. var.
  BLENDER_DELETEELBEEMFILES is not set or zero
- fluidsimSettingsFree now gets properly called when freeing an object

source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/object.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_object_fluidsim.h
source/blender/src/buttons_object.c
source/blender/src/fluidsim.c

index ee6653d4ef998bf65dd17117fa7025166df65953..ad64aa24e425c362118b1d1acc64c620d34f667e 100644 (file)
@@ -1468,12 +1468,24 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
        float (*deformedVerts)[3] = NULL;
        DerivedMesh *dm;
        int numVerts = me->totvert;
+       int fluidsimMeshUsed = 0;
 
        modifiers_clearErrors(ob);
 
        if (deform_r) *deform_r = NULL;
        *final_r = NULL;
 
+       /* replace original mesh by fluidsim surface mesh for fluidsim domain objects */
+       if((G.obedit!=ob) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
+               if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
+                       loadFluidsimMesh(ob,useRenderParams);
+                       fluidsimMeshUsed = 1;
+                       /* might have changed... */
+                       me = ob->data;
+                       numVerts = me->totvert;
+               }
+       }
+
        if (useDeform) {
                if(do_ob_key(ob))       /* shape key makes deform verts */
                        deformedVerts = mesh_getVertexCos(me, &numVerts);
@@ -1502,16 +1514,6 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
                deformedVerts = inputVertexCos;
        }
 
-       /* N_T 
-        * i dont know why, but somehow the if(useDeform) part
-        * is necessary to get anything displayed
-        */ 
-       if((G.obedit!=ob) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
-               if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
-                       *final_r = getFluidsimDerivedMesh(ob,useRenderParams, NULL,NULL);                                       
-                       if(*final_r) return;
-               }
-       }
 
                /* Now apply all remaining modifiers. If useDeform is off then skip
                 * OnlyDeform ones. 
@@ -1590,6 +1592,8 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
        if (deformedVerts && deformedVerts!=inputVertexCos) {
                MEM_freeN(deformedVerts);
        }
+       // restore mesh in any case
+       if(fluidsimMeshUsed) ob->data = ob->fluidsimSettings->orgMesh;
 }
 
 static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
@@ -2248,44 +2252,54 @@ Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
 
 /* ***************************** fluidsim derived mesh ***************************** */
 
-typedef struct {
-       MeshDerivedMesh mdm;
-
-       /* release whole mesh? */
-       char freeMesh;
-} FluidsimDerivedMesh;
-
-static void fluidsimDM_release(DerivedMesh *dm)
-{
-       FluidsimDerivedMesh *fsdm = (FluidsimDerivedMesh*) dm;
-       if(fsdm->freeMesh) {
-               // similar to free_mesh(fsdm->mdm.me) , but no things like unlink...
-               if(fsdm->mdm.me->mvert) MEM_freeN(fsdm->mdm.me->mvert);
-               if(fsdm->mdm.me->medge) MEM_freeN(fsdm->mdm.me->medge);
-               if(fsdm->mdm.me->mface) MEM_freeN(fsdm->mdm.me->mface);
-               MEM_freeN(fsdm->mdm.me);
-       }
-
-       if (fsdm->mdm.freeNors) MEM_freeN(fsdm->mdm.nors);
-       if (fsdm->mdm.freeVerts) MEM_freeN(fsdm->mdm.verts);
-       MEM_freeN(fsdm);
-}
-
-DerivedMesh *getFluidsimDerivedMesh(Object *srcob, int useRenderParams, float *extverts, float *nors) 
+/* check which file to load, and replace old mesh of the object with it */
+/* this replacement is undone at the end of mesh_calc_modifiers */
+void loadFluidsimMesh(Object *srcob, int useRenderParams)
 {
        Mesh *mesh = NULL;
-       FluidsimDerivedMesh *fsdm;
        MeshDerivedMesh *mdm = NULL;
        float (*vertCos)[3];
        int displaymode = 0;
        int curFrame = G.scene->r.cfra - 1; /* start with 0 */
        char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
        char debugStrBuffer[256];
-       //snprintf(debugStrBuffer,256,"getFluidsimDerivedMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
+       float *bbStart = NULL, *bbSize = NULL;
+       float lastBB[3];
+       //snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
 
        if((!srcob)||(!srcob->fluidsimSettings)) {
-               fprintf(stderr,"??? DEBUG, strange getFluidsimDerivedMesh call!\n\n"); return NULL;
+               snprintf(debugStrBuffer,256,"DEBUG - Invalid loadFluidsimMesh call, rp %d, dm %d)\n", useRenderParams, displaymode); // debug
+               elbeemDebugOut(debugStrBuffer); // debug
+               return;
+       }
+       // make sure the original mesh data pointer is stored
+       if(!srcob->fluidsimSettings->orgMesh) {
+               srcob->fluidsimSettings->orgMesh = srcob->data;
        }
+
+       // free old mesh, if there is one (todo, check if it's still valid?)
+       if(srcob->fluidsimSettings->meshSurface) {
+               Mesh *freeFsMesh = srcob->fluidsimSettings->meshSurface;
+
+               // similar to free_mesh(...) , but no things like unlink...
+               if(freeFsMesh->mvert) MEM_freeN(freeFsMesh->mvert);
+               if(freeFsMesh->medge) MEM_freeN(freeFsMesh->medge);
+               if(freeFsMesh->mface) MEM_freeN(freeFsMesh->mface);
+               MEM_freeN(freeFsMesh);
+               
+               if(srcob->data == srcob->fluidsimSettings->meshSurface)
+                srcob->data = srcob->fluidsimSettings->orgMesh;
+               srcob->fluidsimSettings->meshSurface = NULL;
+       } 
+
+       // init bounding box
+       bbStart = srcob->fluidsimSettings->bbStart; 
+       bbSize = srcob->fluidsimSettings->bbSize;
+       lastBB[0] = bbSize[0];  // TEST
+       lastBB[1] = bbSize[1]; 
+       lastBB[2] = bbSize[2];
+       fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize);
+       // check free fsmesh... TODO
        
        if(!useRenderParams) {
                displaymode = srcob->fluidsimSettings->guiDisplayMode;
@@ -2293,74 +2307,80 @@ DerivedMesh *getFluidsimDerivedMesh(Object *srcob, int useRenderParams, float *e
                displaymode = srcob->fluidsimSettings->renderDisplayMode;
        }
        
-       snprintf(debugStrBuffer,256,"getFluidsimDerivedMesh call (obid '%s', rp %d, dm %d)\n", srcob->id.name, useRenderParams, displaymode); // debug
+       snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d)\n", srcob->id.name, useRenderParams, displaymode); // debug
        elbeemDebugOut(debugStrBuffer); // debug
 
        strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR);
        // use preview or final mesh?
-       if(displaymode==2) {
+       if(displaymode==1) {
+               // just display original object
+               srcob->data = srcob->fluidsimSettings->orgMesh;
+               return;
+       } else if(displaymode==2) {
                strcat(targetDir,"fluidsurface_preview_#");
-       } else {
+       } else { // 3
                strcat(targetDir,"fluidsurface_final_#");
        }
        BLI_convertstringcode(targetDir, G.sce, curFrame); // fixed #frame-no 
        strcpy(targetFile,targetDir);
        strcat(targetFile, ".bobj.gz");
-       //fprintf(stderr,"getFluidsimDerivedMesh call (obid '', rp %d, dm %d) '%s' \n", useRenderParams, displaymode, targetFile);  // debug
 
-       snprintf(debugStrBuffer,256,"getFluidsimDerivedMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile);  // debug
+       snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile);  // debug
        elbeemDebugOut(debugStrBuffer); // debug
 
-       mesh = readBobjgz(targetFile, (Mesh*)(srcob->data) );
+       mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh );
        if(!mesh) {
                // display org. object upon failure
-               mesh = srcob->data;                     
-               return getMeshDerivedMesh(mesh , srcob, NULL);
+               srcob->data = srcob->fluidsimSettings->orgMesh;
+               return;
        }
 
        if((mesh)&&(mesh->totvert>0)) {
                make_edges(mesh, 0);    // 0 = make all edges draw
        }
+       srcob->fluidsimSettings->meshSurface = mesh;
+       srcob->data = mesh;
+       return;
+}
+
+/* helper function */
+/* init axis aligned BB for mesh object */
+void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
+                /*RET*/ float start[3], /*RET*/ float size[3] )
+{
+       float bbsx=0.0, bbsy=0.0, bbsz=0.0;
+       float bbex=1.0, bbey=1.0, bbez=1.0;
+       int i;
+       float vec[3];
 
-       // WARNING copied from getMeshDerivedMesh
-       fsdm = MEM_callocN(sizeof(*fsdm), "getFluidsimDerivedMesh_fsdm");
-       fsdm->freeMesh = 1;
-       mdm = &fsdm->mdm;
-       vertCos = NULL;
+       VECCOPY(vec, mesh->mvert[0].co); 
+       Mat4MulVecfl(obmat, vec);
+       bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
+       bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
 
-       mdm->dm.getMinMax = meshDM_getMinMax;
-       mdm->dm.convertToDispListMesh = meshDM_convertToDispListMesh;
-       mdm->dm.getNumVerts = meshDM_getNumVerts;
-       mdm->dm.getNumFaces = meshDM_getNumFaces;
-       mdm->dm.getVertCos = meshDM_getVertCos;
-       mdm->dm.getVertCo = meshDM_getVertCo;
-       mdm->dm.getVertNo = meshDM_getVertNo;
-       mdm->dm.drawVerts = meshDM_drawVerts;
-       mdm->dm.drawUVEdges = meshDM_drawUVEdges;
-       mdm->dm.drawEdges = meshDM_drawEdges;
-       mdm->dm.drawLooseEdges = meshDM_drawLooseEdges;
-       mdm->dm.drawFacesSolid = meshDM_drawFacesSolid;
-       mdm->dm.drawFacesColored = meshDM_drawFacesColored;
-       mdm->dm.drawFacesTex = meshDM_drawFacesTex;
-       mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
-       mdm->dm.drawMappedEdges = meshDM_drawMappedEdges;
-       mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
+       for(i=1; i<mesh->totvert;i++) {
+               VECCOPY(vec, mesh->mvert[i].co);
+               Mat4MulVecfl(obmat, vec);
 
-       // use own release function
-       mdm->dm.release = fluidsimDM_release;
-       
-       mdm->ob = srcob;
-       mdm->me = mesh;
-       mdm->verts = mesh->mvert;
-       mdm->nors = NULL;
-       mdm->freeNors = 0;
-       mdm->freeVerts = 0;
-       
-       // if (vertCos) { not needed for fluid meshes... 
-       // this is kinda ... see getMeshDerivedMesh
-       mesh_calc_normals(mdm->verts, mdm->me->totvert, mdm->me->mface, mdm->me->totface, &mdm->nors);
-       mdm->freeNors = 1;
-       return (DerivedMesh*) mdm;
+               if(vec[0] < bbsx){ bbsx= vec[0]; }
+               if(vec[1] < bbsy){ bbsy= vec[1]; }
+               if(vec[2] < bbsz){ bbsz= vec[2]; }
+               if(vec[0] > bbex){ bbex= vec[0]; }
+               if(vec[1] > bbey){ bbey= vec[1]; }
+               if(vec[2] > bbez){ bbez= vec[2]; }
+       }
+
+       // return values...
+       if(start) {
+               start[0] = bbsx;
+               start[1] = bbsy;
+               start[2] = bbsz;
+       } 
+       if(size) {
+               size[0] = bbex-bbsx;
+               size[1] = bbey-bbsy;
+               size[2] = bbez-bbsz;
+       }
 }
 
 
index 0b363216a5304f00f771ce5dfa9d73da31070c55..d97211b3125a39e7de72cd3c79836d5c66435a32 100644 (file)
@@ -57,6 +57,7 @@
 #include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_object_force.h"
+#include "DNA_object_fluidsim.h"
 #include "DNA_oops_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
@@ -216,7 +217,7 @@ void free_object(Object *ob)
        
        if(ob->pd) MEM_freeN(ob->pd);
        if(ob->soft) sbFree(ob->soft);
-       if(ob->fluidsimSettings) MEM_freeN(ob->fluidsimSettings); /* NT */
+       if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings);
 }
 
 static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
index fea9ac87480337ccba9fbec38a2ad8cc51b6c0b2..9490a4ca5ce96bd3f093a5365b7550ce42e95183 100644 (file)
@@ -2402,8 +2402,10 @@ static void direct_link_object(FileData *fd, Object *ob)
        }
        ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
        if(ob->fluidsimSettings) {
-               // not much to do for now... 
-               ob->fluidsimSettings->orgMesh = NULL;
+               // reinit mesh pointers
+               ob->fluidsimSettings->orgMesh = NULL; //ob->data;
+               ob->fluidsimSettings->meshSurface = NULL;
+               ob->fluidsimSettings->meshBB = NULL;
        }
        
        link_list(fd, &ob->prop);
index 6a02680d694a3337b479fd7375ee77751f0ac7fa..1b5b77591f78d2a35add74efd0a85d8f43b2c02d 100644 (file)
@@ -75,10 +75,18 @@ typedef struct FluidsimSettings {
 
        /* store pointer to original mesh (for replacing the current one) */
        struct Mesh *orgMesh;
+       /* pointer to the currently loaded fluidsim mesh */
+       struct Mesh *meshSurface;
+       /* a mesh to display the bounding box used for simulation */
+       struct Mesh *meshBB;
 
        /* store output path, and file prefix for baked fluid surface */
        /* strlens; 80= FILE_MAXFILE, 160= FILE_MAXDIR */
-       char surfdataPath[160+80];
+       char surfdataPath[240];
+
+       /* store start coords of axis aligned bounding box together with size */
+       /* values are inited during derived mesh display */
+       float bbStart[3], bbSize[3];
 } FluidsimSettings;
 
 /* ob->fluidsimSettings defines */
index 58d10f9dcf3c1a82dde59d5035c2c4f9e300117f..1864b9c2b1e6358d489d2728c27bb32421d46095 100644 (file)
@@ -2104,18 +2104,26 @@ static void object_panel_fluidsim(Object *ob)
 
                        /* display specific settings for each type */
                        if(fss->type == OB_FLUIDSIM_DOMAIN) {
-                               const int maxRes = 200;
+                               const int maxRes = 512;
+                               char memString[32];
 
-                       /* domain "advanced" settings */
-                       if(fss->type == OB_FLUIDSIM_DOMAIN) { }
+                               // use mesh bounding box and object scaling
+                               // TODO fix redraw issue
+                               elbeemEstimateMemreq(fss->resolutionxyz, 
+                                               ob->fluidsimSettings->bbSize[0],ob->fluidsimSettings->bbSize[1],ob->fluidsimSettings->bbSize[2], fss->maxRefine, memString);
+                               
                                uiDefButBitS(block, TOG, 1, REDRAWBUTSOBJECT, "Advanced>>",      0,yline, 75,objHeight, &fss->show_advancedoptions, 0, 0, 0, 0, "Show advanced domain options.");
                                uiDefBut(block, BUT, B_FLUIDSIM_BAKE, "BAKE",90, yline,210,objHeight, NULL, 0.0, 0.0, 10, 0, "Perform simulation and output and surface&preview meshes for each frame.");
                                yline -= lineHeight;
                                yline -= 2*separateHeight;
 
                                if(fss->show_advancedoptions == 0) {
-                                       uiDefButS(block, NUM, B_DIFF, "Resolution:", 0, yline,150,objHeight, &fss->resolutionxyz, 1, maxRes, 10, 0, "Domain resolution in X,Y and Z direction");
-                                       uiDefButS(block, NUM, B_DIFF, "Preview-Res.:", 150, yline,150,objHeight, &fss->previewresxyz, 1, 100, 10, 0, "Resolution of the preview meshes to generate, also in X,Y and Z direction");
+                                       uiDefBut(block, LABEL,   0, "Req. BAKE Memory:",  0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
+                                       uiDefBut(block, LABEL,   0, memString,  200,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
+                                       yline -= lineHeight;
+
+                                       uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Resolution:", 0, yline,150,objHeight, &fss->resolutionxyz, 1, maxRes, 10, 0, "Domain resolution in X,Y and Z direction");
+                                       uiDefButS(block, NUM, B_DIFF,           "Preview-Res.:", 150, yline,150,objHeight, &fss->previewresxyz, 1, 100, 10, 0, "Resolution of the preview meshes to generate, also in X,Y and Z direction");
                                        yline -= lineHeight;
                                        yline -= 1*separateHeight;
 
index 546613821f0b322e6766b6a1bfc7b1f6b15d7b5e..d8e47af970c04a7f1bffcff722fe0ceda22d1a81 100644 (file)
@@ -67,6 +67,7 @@
 #include "BKE_softbody.h"
 #include "BKE_utildefines.h"
 #include "BKE_DerivedMesh.h"
+#include "BKE_ipo.h"
 #include "LBM_fluidsim.h"
 
 #include "BLI_editVert.h"
 extern int start_progress_bar(void);
 extern void end_progress_bar(void);
 extern int progress_bar(float done, char *busy_info);
+// global solver state
+extern int gElbeemState;
+extern char gElbeemErrorString[];
 
 double fluidsimViscosityPreset[6] = {
        -1.0,   /* unused */
@@ -169,18 +173,37 @@ FluidsimSettings *fluidsimSettingsNew(struct Object *srcob)
 
        strcpy(fss->surfdataPath,""); // leave blank, init upon first bake
        fss->orgMesh = (Mesh *)srcob->data;
+       fss->meshSurface = NULL;
+       fss->meshBB = NULL;
+
+       // first init of bounding box
+       fss->bbStart[0] = 0.0;
+       fss->bbStart[1] = 0.0;
+       fss->bbStart[2] = 0.0;
+       fss->bbSize[0] = 1.0;
+       fss->bbSize[1] = 1.0;
+       fss->bbSize[2] = 1.0;
+       fluidsimGetAxisAlignedBB(srcob->data, srcob->obmat, fss->bbStart, fss->bbSize);
        return fss;
 }
 
 /* free struct */
 void fluidsimSettingsFree(FluidsimSettings *fss)
 {
+       Mesh *freeFsMesh = fss->meshSurface;
+       if(freeFsMesh) {
+               if(freeFsMesh->mvert) MEM_freeN(freeFsMesh->mvert);
+               if(freeFsMesh->medge) MEM_freeN(freeFsMesh->medge);
+               if(freeFsMesh->mface) MEM_freeN(freeFsMesh->mface);
+               MEM_freeN(freeFsMesh);
+       }
+
        MEM_freeN(fss);
 }
 
 
 /* helper function */
-void getGeometryObjFilename(struct Object *ob, char *dst) { //, char *srcname) {
+void fluidsimGetGeometryObjFilename(struct Object *ob, char *dst) { //, char *srcname) {
        //snprintf(dst,FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
        snprintf(dst,FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
 }
@@ -192,13 +215,16 @@ int                       globalBakeState = 0; // 0 everything ok, -1 abort simulation, 1 sim done
 int                    globalBakeFrame = 0;
 
 // run simulation in seperate thread
-int simulateThread(void *ptr) {
+int fluidsimSimulateThread(void *ptr) {
        char* fnameCfgPath = (char*)(ptr);
        int ret;
        
        ret = performElbeemSimulation(fnameCfgPath);
        SDL_mutexP(globalBakeLock);
-       globalBakeState = 1;
+       if(globalBakeState==0) {
+               // if no error, set to normal exit
+               globalBakeState = 1;
+       }
        SDL_mutexV(globalBakeLock);
        return ret;
 }
@@ -206,29 +232,41 @@ int simulateThread(void *ptr) {
 // called by simulation to set frame no.
 void simulateThreadIncreaseFrame(void) {
        if(!globalBakeLock) return;
-       if(globalBakeState<0) return; // this means abort...
+       if(globalBakeState!=0) return; // this means abort...
        SDL_mutexP(globalBakeLock);
        globalBakeFrame++;
        SDL_mutexV(globalBakeLock);
 }
 
+/* remember files created during bake for deletion */
+       //createdFiles[numCreatedFiles] = (char *)malloc(strlen(str)+1); 
+       //strcpy(createdFiles[numCreatedFiles] ,str); 
+#define ADD_CREATEDFILE(str) \
+       if(numCreatedFiles<255) {\
+               createdFiles[numCreatedFiles] = strdup(str); \
+               numCreatedFiles++; }
+
 /* ********************** write fluidsim config to file ************************* */
 void fluidsimBake(struct Object *ob)
 {
        FILE *fileCfg;
+       int i;
        struct Object *fsDomain = NULL;
        FluidsimSettings *fssDomain;
        struct Object *obit = NULL; /* object iterator */
        int origFrame = G.scene->r.cfra;
-       char blendDir[FILE_MAXDIR], blendFile[FILE_MAXFILE];
-       char curWd[FILE_MAXDIR];
        char debugStrBuffer[256];
        int dirExist = 0;
-       const int maxRes = 200;
        int gridlevels = 0;
+       char *createdFiles[256];
+       int  numCreatedFiles = 0;
+       int  doDeleteCreatedFiles = 1;
+       int simAborted = 0; // was the simulation aborted by user?
+       char *delEnvStr = "BLENDER_DELETEELBEEMFILES";
 
        char *suffixConfig = "fluidsim.cfg";
        char *suffixSurface = "fluidsurface";
+       char newSurfdataPath[FILE_MAXDIR+FILE_MAXFILE]; // modified output settings
        char targetDir[FILE_MAXDIR+FILE_MAXFILE];  // store & modify output settings
        char targetFile[FILE_MAXDIR+FILE_MAXFILE]; // temp. store filename from targetDir for access
        int  outStringsChanged = 0;             // modified? copy back before baking
@@ -258,11 +296,6 @@ void fluidsimBake(struct Object *ob)
        fsDomain = ob;
        fssDomain = ob->fluidsimSettings;
        /* rough check of settings... */
-       if(fssDomain->resolutionxyz>maxRes) {
-               fssDomain->resolutionxyz = maxRes;
-               snprintf(debugStrBuffer,256,"fluidsimBake::warning - Resolution (%d) > %d^3, this requires more than 600MB of memory... restricting to %d^3 for now.\n",  fssDomain->resolutionxyz, maxRes, maxRes); 
-               elbeemDebugOut(debugStrBuffer);
-       }
        if(fssDomain->previewresxyz > fssDomain->resolutionxyz) {
                snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", fssDomain->previewresxyz ,  fssDomain->resolutionxyz); 
                elbeemDebugOut(debugStrBuffer);
@@ -304,13 +337,15 @@ void fluidsimBake(struct Object *ob)
        }
 
        // prepare names...
-       strncpy(targetDir, fsDomain->fluidsimSettings->surfdataPath, FILE_MAXDIR);
+       strncpy(targetDir, fssDomain->surfdataPath, FILE_MAXDIR);
+       strncpy(newSurfdataPath, fssDomain->surfdataPath, FILE_MAXDIR);
        BLI_convertstringcode(targetDir, G.sce, 0); // fixed #frame-no 
 
        strcpy(targetFile, targetDir);
        strcat(targetFile, suffixConfig);
        // check selected directory
        // simply try to open cfg file for writing to test validity of settings
+       ADD_CREATEDFILE(targetFile);
        fileCfg = fopen(targetFile, "w");
        if(fileCfg) { dirExist = 1; fclose(fileCfg); }
 
@@ -327,9 +362,9 @@ void fluidsimBake(struct Object *ob)
                        }
                }
                // todo... strip .blend ?
-               snprintf(targetDir,FILE_MAXFILE+FILE_MAXDIR,"//%s_%s_", blendFile, fsDomain->id.name);
+               snprintf(newSurfdataPath,FILE_MAXFILE+FILE_MAXDIR,"//%s_%s_", blendFile, fsDomain->id.name);
 
-               snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", targetDir);
+               snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
                elbeemDebugOut(debugStrBuffer);
                outStringsChanged=1;
        }
@@ -339,17 +374,18 @@ void fluidsimBake(struct Object *ob)
                char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256];
                int  selection=0;
                strcpy(dispmsg,"Output settings set to: '");
-               strcat(dispmsg, targetDir);
+               strcat(dispmsg, newSurfdataPath);
                strcat(dispmsg, "'%t|Continue with changed settings%x1|Discard and abort%x0");
 
                // ask user if thats what he/she wants...
                selection = pupmenu(dispmsg);
                if(selection<1) return; // 0 from menu, or -1 aborted
+               strcpy(targetDir, newSurfdataPath);
                BLI_convertstringcode(targetDir, G.sce, 0); // fixed #frame-no 
        }
        
        // dump data for frame 0
-  G.scene->r.cfra = 0;
+  G.scene->r.cfra = 1;
   scene_update_for_newframe(G.scene, G.scene->lay);
 
        // start writing
@@ -366,44 +402,32 @@ void fluidsimBake(struct Object *ob)
 
        fprintf(fileCfg, "# Blender ElBeem File , Source %s , Frame %d, to %s \n\n\n", G.sce, -1, targetFile );
        // file open -> valid settings -> store
-       strncpy(fsDomain->fluidsimSettings->surfdataPath, targetDir, FILE_MAXDIR);
-       //strncpy(fsDomain->fluidsimSettings->urfdataPrefix, outPrefix, FILE_MAXFILE);
+       strncpy(fssDomain->surfdataPath, newSurfdataPath, FILE_MAXDIR);
 
-       // FIXME set aniframetime from no. frames and duration
        /* output simulation  settings */
        {
                int noFrames = G.scene->r.efra - G.scene->r.sfra;
                double calcViscosity = 0.0;
-               double animFrameTime = (fssDomain->animEnd - fssDomain->animStart)/(double)noFrames;
+               double aniFrameTime = (fssDomain->animEnd - fssDomain->animStart)/(double)noFrames;
                char *simString = "\n"
                "attribute \"simulation1\" { \n" 
-               
-               "  p_domainsize  = " "%f" /* 0 realsize */ "; \n" 
-               "  p_anistart    = " "%f" /* 1 aniStart*/ "; #cfgset \n" 
-               "  p_aniframetime = " "%f" /* 2 aniFrameTime*/ "; #cfgset \n" 
                "  solver = \"fsgr\"; \n"  "\n" 
-               "  initsurfsmooth = 0; \n"  "\n" 
-               "  debugvelscale = 0.005; \n"  "\n" 
-               "  isovalue =  0.4900; \n" 
-               "  isoweightmethod = 1; \n"  "\n" 
-               "  disable_stfluidinit = 0; \n"  "\n" 
-               
-               "  geoinit   = 1; \n" 
-               "  geoinitid = 1;  \n"  "\n" 
-               "  p_gravity = " "%f %f %f" /* 3,4,5 pGravity*/ "; #cfgset \n"  "\n" 
+               "  p_domainsize  = " "%f"   /* realsize */ "; \n" 
+               "  p_anistart    = " "%f"   /* aniStart*/ "; \n" 
+               "  p_gravity = " "%f %f %f" /* pGravity*/ "; \n"  "\n" 
+               "  p_normgstar = %f; \n"    /* use gstar param? */
+               "  p_viscosity = " "%f"     /* pViscosity*/ "; \n"  "\n" 
                
-               "  timeadap = 1;  \n" 
-               "  p_tadapmaxomega = 2.0; \n" 
-               "  p_normgstar = %f; \n"  /* 6b use gstar param? */
-               "  p_viscosity = " "%f" /* 7 pViscosity*/ "; #cfgset \n"  "\n" 
-               
-               "  maxrefine = " "%d" /* 8 maxRefine*/ "; #cfgset  \n" 
-               "  size = " "%d" /* 9 gridSize*/ "; #cfgset  \n" 
-               "  surfacepreview = " "%d" /* 10 previewSize*/ "; #cfgset \n" 
+               "  maxrefine = " "%d" /* maxRefine*/ ";  \n" 
+               "  size = " "%d"      /* gridSize*/ ";  \n" 
+               "  surfacepreview = " "%d" /* previewSize*/ "; \n" 
                "  smoothsurface = 1.0;  \n"
-               "\n" 
-               //"  //forcetadaprefine = 0; maxrefine = 0; \n" 
-               "} \n" ;
+
+                 "  geoinitid = 1;  \n"  "\n" 
+                       "  isovalue =  0.4900; \n" 
+                       "  isoweightmethod = 1; \n"  "\n"    
+
+               "\n" ;
     
                if(fssDomain->viscosityMode==1) {
                        /* manual mode */
@@ -413,12 +437,41 @@ void fluidsimBake(struct Object *ob)
                }
                fprintf(fileCfg, simString,
                                (double)fssDomain->realsize, 
-                               (double)fssDomain->animStart, animFrameTime ,
+                               (double)fssDomain->animStart, 
                                (double)fssDomain->gravx, (double)fssDomain->gravy, (double)fssDomain->gravz,
                                (double)fssDomain->gstar,
                                calcViscosity,
                                gridlevels, (int)fssDomain->resolutionxyz, (int)fssDomain->previewresxyz 
                                );
+
+               // export animatable params
+               if(fsDomain->ipo) {
+                       int i;
+                       float tsum=0.0, shouldbe=0.0;
+                       fprintf(fileCfg, "  CHANNEL p_aniframetime = ");
+                       for(i=G.scene->r.sfra; i<G.scene->r.efra; i++) {
+                               float anit = (calc_ipo_time(fsDomain->ipo, i+1) -
+                                       calc_ipo_time(fsDomain->ipo, i)) * aniFrameTime;
+                               if(anit<0.0) anit = 0.0;
+                               tsum += anit;
+                       }
+                       // make sure inaccurate integration doesnt modify end time
+                       shouldbe = ((float)(G.scene->r.efra - G.scene->r.sfra)) *aniFrameTime;
+                       for(i=G.scene->r.sfra; i<G.scene->r.efra; i++) {
+                               float anit = (calc_ipo_time(fsDomain->ipo, i+1) -
+                                       calc_ipo_time(fsDomain->ipo, i)) * aniFrameTime;
+                               if(anit<0.0) anit = 0.0;
+                               anit *= (shouldbe/tsum);
+                               fprintf(fileCfg," %f %d  \n",anit, (i-1)); // start with 0
+                       }
+                       fprintf(fileCfg, "; #cfgset, base=%f \n", aniFrameTime );
+                       //fprintf(stderr, "DEBUG base=%f tsum=%f, sb=%f, ts2=%f \n", aniFrameTime, tsum,shouldbe,tsum2 );
+               } else {
+                       fprintf(fileCfg, "  p_aniframetime = " "%f" /* 2 aniFrameTime*/ "; #cfgset \n" ,
+                               aniFrameTime ); 
+               }
+                       
+               fprintf(fileCfg,  "} \n" );
        }
 
        // output blender object transformation
@@ -520,8 +573,6 @@ void fluidsimBake(struct Object *ob)
 
        /* output fluid domain */
        {
-               float bbsx=0.0, bbsy=0.0, bbsz=0.0;
-               float bbex=1.0, bbey=1.0, bbez=1.0;
                char * domainString = "\n" 
                        "  geometry { \n" 
                        "    type= fluidlbm; \n" 
@@ -533,35 +584,14 @@ void fluidsimBake(struct Object *ob)
                        "    end  = " "%f %f %f" /*bbend  */ "; #cfgset \n" 
                        "  } \n" 
                        "\n";
-               Mesh *mesh = fsDomain->data; 
-               //BoundBox *bb = fsDomain->bb;
-               //if(!bb) { bb = mesh->bb; }
-               //bb = NULL; // TODO test existing bounding box...
+               float *bbStart = fsDomain->fluidsimSettings->bbStart; 
+               float *bbSize = fsDomain->fluidsimSettings->bbSize;
+               fluidsimGetAxisAlignedBB(fsDomain->data, fsDomain->obmat, bbStart, bbSize);
 
-               //if(!bb && (mesh->totvert>0) ) 
-               { 
-                       int i;
-                       float vec[3];
-                       VECCOPY(vec, mesh->mvert[0].co); 
-                       Mat4MulVecfl(fsDomain->obmat, vec);
-                       bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
-                       bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
-                       for(i=1; i<mesh->totvert;i++) {
-                               VECCOPY(vec, mesh->mvert[i].co); /* get transformed point */
-                               Mat4MulVecfl(fsDomain->obmat, vec);
-
-                               if(vec[0] < bbsx){ bbsx= vec[0]; }
-                               if(vec[1] < bbsy){ bbsy= vec[1]; }
-                               if(vec[2] < bbsz){ bbsz= vec[2]; }
-                               if(vec[0] > bbex){ bbex= vec[0]; }
-                               if(vec[1] > bbey){ bbey= vec[1]; }
-                               if(vec[2] > bbez){ bbez= vec[2]; }
-                       }
-               }
                fprintf(fileCfg, domainString,
                        fsDomain->id.name, 
-                       bbsx, bbsy, bbsz,
-                       bbex, bbey, bbez
+                       bbStart[0],           bbStart[1],           bbStart[2],
+                       bbStart[0]+bbSize[0], bbStart[1]+bbSize[1], bbStart[2]+bbSize[2]
                );
        }
 
@@ -596,7 +626,7 @@ void fluidsimBake(struct Object *ob)
                                        (obit->type==OB_MESH) &&
                                  (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN)
                                ) {
-                                       getGeometryObjFilename(obit, fnameObjdat); //, outPrefix);
+                                       fluidsimGetGeometryObjFilename(obit, fnameObjdat); //, outPrefix);
                                        strcpy(targetFile, targetDir);
                                        strcat(targetFile, fnameObjdat);
                                        fprintf(fileCfg, objectStringStart, obit->id.name ); // abs path
@@ -616,6 +646,7 @@ void fluidsimBake(struct Object *ob)
                                                fprintf(fileCfg, obstacleString, "bnd_no" , targetFile); // abs path
                                        }
                                        fprintf(fileCfg, objectStringEnd ); // abs path
+                                       ADD_CREATEDFILE(targetFile);
                                        writeBobjgz(targetFile, obit);
                        }
                }
@@ -635,6 +666,9 @@ void fluidsimBake(struct Object *ob)
 
        fprintf(fileCfg, "} // end raytracing\n");
        fclose(fileCfg);
+
+       strcpy(targetFile, targetDir);
+       strcat(targetFile, suffixConfig);
        snprintf(debugStrBuffer,256,"fluidsimBake::msg: Wrote %s\n", targetFile); 
        elbeemDebugOut(debugStrBuffer);
 
@@ -642,11 +676,10 @@ void fluidsimBake(struct Object *ob)
        {
                SDL_Thread *simthr = NULL;
                globalBakeLock = SDL_CreateMutex();
+               // set to neutral, -1 means user abort, -2 means init error
                globalBakeState = 0;
                globalBakeFrame = 1;
-               strcpy(targetFile, targetDir);
-               strcat(targetFile, suffixConfig);
-               simthr = SDL_CreateThread(simulateThread, targetFile);
+               simthr = SDL_CreateThread(fluidsimSimulateThread, targetFile);
 #ifndef WIN32
                // DEBUG for win32 debugging, dont use threads...
 #endif // WIN32
@@ -677,7 +710,7 @@ void fluidsimBake(struct Object *ob)
                                
                                SDL_Delay(2000); // longer delay to prevent frequent redrawing
                                SDL_mutexP(globalBakeLock);
-                               if(globalBakeState == 1) done = 1;
+                               if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort
                                SDL_mutexV(globalBakeLock);
 
                                while(qtest()) {
@@ -688,6 +721,7 @@ void fluidsimBake(struct Object *ob)
                                                done = -1;
                                                globalBakeFrame = 0;
                                                globalBakeState = -1;
+                                               simAborted = 1;
                                                SDL_mutexV(globalBakeLock);
                                                break;
                                        }
@@ -713,13 +747,36 @@ void fluidsimBake(struct Object *ob)
                globalBakeLock = NULL;
        } // thread creation
 
-       // TODO cleanup sim files?
+       // cleanup sim files
+       if(getenv(delEnvStr)) {
+               doDeleteCreatedFiles = atoi(getenv(delEnvStr));
+       }
+       for(i=0; i<numCreatedFiles; i++) {
+               if(doDeleteCreatedFiles>0) {
+                       fprintf(stderr," CREATED '%s' deleting... \n", createdFiles[i]);
+                       BLI_delete(createdFiles[i], 0,0);
+               }
+               free(createdFiles[i]);
+       }
+
        // go back to "current" blender time
        waitcursor(0);
   G.scene->r.cfra = origFrame;
   scene_update_for_newframe(G.scene, G.scene->lay);
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWBUTSOBJECT, 0);
+
+       if(!simAborted) {
+               char fsmessage[512];
+               strcpy(fsmessage,"Fluidsim Bake Error: ");
+               // check if some error occurred
+               if(globalBakeState==-2) {
+                       strcat(fsmessage,"Failed to initialize [Msg: ");
+                       strcat(fsmessage,gElbeemErrorString);
+                       strcat(fsmessage,"]|OK%x0");
+                       pupmenu(fsmessage);
+               } // init error
+       }
 }