diff options
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 184 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 3 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 6 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_fluidsim.h | 10 | ||||
-rw-r--r-- | source/blender/src/buttons_object.c | 18 | ||||
-rw-r--r-- | source/blender/src/fluidsim.c | 217 |
6 files changed, 267 insertions, 171 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index ee6653d4ef9..ad64aa24e42 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -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; + } } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0b363216a53..d97211b3125 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -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) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index fea9ac87480..9490a4ca5ce 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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); diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h index 6a02680d694..1b5b77591f7 100644 --- a/source/blender/makesdna/DNA_object_fluidsim.h +++ b/source/blender/makesdna/DNA_object_fluidsim.h @@ -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 */ diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 58d10f9dcf3..1864b9c2b1e 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -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; diff --git a/source/blender/src/fluidsim.c b/source/blender/src/fluidsim.c index 546613821f0..d8e47af970c 100644 --- a/source/blender/src/fluidsim.c +++ b/source/blender/src/fluidsim.c @@ -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" @@ -102,6 +103,9 @@ 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 + } } |