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:
-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
+ }
}