Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNils Thuerey <nils@thuerey.de>2005-11-23 15:49:22 +0300
committerNils Thuerey <nils@thuerey.de>2005-11-23 15:49:22 +0300
commit5c56ca11802ca803b4466134f0f7cf48cfe76b28 (patch)
tree291ba4848629a74412f30053167165e7cc54ead5
parentc35a8fe4635305f442e843d41270e94773afbd0c (diff)
- changed DerivedMesh integration, the fluidsim meshes now
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
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c184
-rw-r--r--source/blender/blenkernel/intern/object.c3
-rw-r--r--source/blender/blenloader/intern/readfile.c6
-rw-r--r--source/blender/makesdna/DNA_object_fluidsim.h10
-rw-r--r--source/blender/src/buttons_object.c18
-rw-r--r--source/blender/src/fluidsim.c217
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
+ }
}