From 2edfe5307bf7560d9d2bc5553d8367ae5306e51b Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sat, 24 Jan 2009 14:24:59 +0000 Subject: 2.5 - writeimage.c back, put in space_file now... - renamed fluidsim.c to distinguish from bke version --- source/blender/editors/physics/ed_fluidsim.c | 1149 ++++++++++++++++++++++++++ source/blender/editors/physics/fluidsim.c | 1149 -------------------------- 2 files changed, 1149 insertions(+), 1149 deletions(-) create mode 100644 source/blender/editors/physics/ed_fluidsim.c delete mode 100644 source/blender/editors/physics/fluidsim.c (limited to 'source/blender/editors/physics') diff --git a/source/blender/editors/physics/ed_fluidsim.c b/source/blender/editors/physics/ed_fluidsim.c new file mode 100644 index 00000000000..902979e0775 --- /dev/null +++ b/source/blender/editors/physics/ed_fluidsim.c @@ -0,0 +1,1149 @@ +/** + * fluidsim.c + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + + + +#include +#include +#include +#include + +#ifdef WIN32 /* Windos */ +#ifndef snprintf +#define snprintf _snprintf +#endif +#endif + +#include "MEM_guardedalloc.h" + +/* types */ +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_object_fluidsim.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_lattice_types.h" +#include "DNA_scene_types.h" +#include "DNA_camera_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_userdef_types.h" +#include "DNA_ipo_types.h" +#include "DNA_key_types.h" + +#include "BLI_blenlib.h" +#include "BLI_threads.h" +#include "BLI_arithb.h" + +#include "BKE_blender.h" +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_fluidsim.h" +#include "BKE_global.h" +#include "BKE_modifier.h" +#include "BKE_main.h" +#include "BKE_key.h" +#include "BKE_scene.h" +#include "BKE_object.h" +#include "BKE_softbody.h" +#include "BKE_DerivedMesh.h" +#include "BKE_ipo.h" + +#include "PIL_time.h" + +#include "LBM_fluidsim.h" + +#include "BIF_gl.h" + +#include "ED_anim_api.h" +#include "ED_fluidsim.h" + +/* XXX */ +/* from header info.c */ +static int start_progress_bar(void) {return 0;}; +static void end_progress_bar(void) {}; +static void waitcursor() {}; +static int progress_bar(float done, char *busy_info) {return 0;} +static int pupmenu() {return 0;} +/* XXX */ + + +double fluidsimViscosityPreset[6] = { + -1.0, /* unused */ + -1.0, /* manual */ + 1.0e-6, /* water */ + 5.0e-5, /* some (thick) oil */ + 2.0e-3, /* ca. honey */ + -1.0 /* end */ +}; + +char* fluidsimViscosityPresetString[6] = { + "UNUSED", /* unused */ + "UNUSED", /* manual */ + " = 1.0 * 10^-6", /* water */ + " = 5.0 * 10^-5", /* some (thick) oil */ + " = 2.0 * 10^-3", /* ca. honey */ + "INVALID" /* end */ +}; + +/* enable/disable overall compilation */ +#ifndef DISABLE_ELBEEM + + +/* ********************** fluid sim settings struct functions ********************** */ + +/* helper function */ +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); +} + + + + +/* ******************************************************************************** */ +/* ********************** fluid sim channel helper functions ********************** */ +/* ******************************************************************************** */ + +// no. of entries for the two channel sizes +#define CHANNEL_FLOAT 1 +#define CHANNEL_VEC 3 + +#define FS_FREE_ONECHANNEL(c,str) { \ + if(c){ MEM_freeN(c); c=NULL; } \ +} // end ONE CHANN, debug: fprintf(stderr,"freeing " str " \n"); + +#define FS_FREE_CHANNELS { \ + FS_FREE_ONECHANNEL(timeAtIndex,"timeAtIndex");\ + FS_FREE_ONECHANNEL(timeAtFrame,"timeAtFrame");\ + FS_FREE_ONECHANNEL(channelDomainTime,"channelDomainTime"); \ + FS_FREE_ONECHANNEL(channelDomainGravity,"channelDomainGravity");\ + FS_FREE_ONECHANNEL(channelDomainViscosity,"channelDomainViscosity");\ + for(i=0;i<256;i++) { \ + FS_FREE_ONECHANNEL(channelObjMove[i][0],"channelObjMove0"); \ + FS_FREE_ONECHANNEL(channelObjMove[i][1],"channelObjMove1"); \ + FS_FREE_ONECHANNEL(channelObjMove[i][2],"channelObjMove2"); \ + FS_FREE_ONECHANNEL(channelObjInivel[i],"channelObjInivel"); \ + FS_FREE_ONECHANNEL(channelObjActive[i],"channelObjActive"); \ + FS_FREE_ONECHANNEL(channelAttractforceStrength[i],"channelAttractforceStrength"); \ + FS_FREE_ONECHANNEL(channelAttractforceRadius[i],"channelAttractforceRadius"); \ + FS_FREE_ONECHANNEL(channelVelocityforceStrength[i],"channelVelocityforceStrength"); \ + FS_FREE_ONECHANNEL(channelVelocityforceRadius[i],"channelVelocityforceRadius"); \ + } \ +} // end FS FREE CHANNELS + + +// simplify channels before printing +// for API this is done anyway upon init +#if 0 +static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries) +{ + int i,j; + int channelSize = paramsize; + + if(entries==3) { + elbeemSimplifyChannelVec3( channel, &channelSize); + } else if(entries==1) { + elbeemSimplifyChannelFloat( channel, &channelSize); + } else { + // invalid, cant happen? + } + + fprintf(file, " CHANNEL %s = \n", str); + for(i=0; ir.framelen; + int current_frame = scene->r.cfra; + if((entries<1) || (entries>3)) { + printf("fluidsimInitChannel::Error - invalid no. of entries: %d\n",entries); + entries = 1; + } + + cstr = "fluidsiminit_channelfloat"; + if(entries>1) cstr = "fluidsiminit_channelvec"; + channel = MEM_callocN( size* (entries+1)* sizeof(float), cstr ); + + if(ipo) { + for(j=0; jr.cfra = floor(aniFrlen*((float)i)); + + // XXX calc_icu(icus[j], aniFrlen*((float)i) ); + channel[(i-1)*(entries+1) + j] = icus[j]->curval; + } + } else { + for(i=1; i<=size; i++) { channel[(i-1)*(entries+1) + j] = defaults[j]; } + } + //printf("fluidsimInitChannel entry:%d , ",j); for(i=1; i<=size; i++) { printf(" val%d:%f ",i, channel[(i-1)*(entries+1) + j] ); } printf(" \n"); // DEBUG + } + // set time values + for(i=1; i<=size; i++) { + channel[(i-1)*(entries+1) + entries] = time[i]; + } + scene->r.cfra = current_frame; + *setchannel = channel; +#endif +} + +static void fluidsimInitMeshChannel(bContext *C, float **setchannel, int size, Object *obm, int vertices, + float *time, int modifierIndex) +{ + Scene *scene= CTX_data_scene(C); + float *channel = NULL; + int mallsize = size* (3*vertices+1); + int frame,i; + int numVerts=0, numTris=0; + int setsize = 3*vertices+1; + + channel = MEM_callocN( mallsize* sizeof(float), "fluidsim_meshchannel" ); + + //fprintf(stderr,"\n\nfluidsimInitMeshChannel size%d verts%d mallsize%d \n\n\n",size,vertices,mallsize); + for(frame=1; frame<=size; frame++) { + float *verts=NULL; + int *tris=NULL; + scene->r.cfra = frame; + ED_update_for_newframe(C, 0); + + initElbeemMesh(scene, obm, &numVerts, &verts, &numTris, &tris, 1, modifierIndex); + //fprintf(stderr,"\nfluidsimInitMeshChannel frame%d verts%d/%d \n\n",frame,vertices,numVerts); + for(i=0; i<3*vertices;i++) { + channel[(frame-1)*setsize + i] = verts[i]; + //fprintf(stdout," frame%d vert%d=%f \n",frame,i,verts[i]); + //if(i%3==2) fprintf(stdout,"\n"); + } + channel[(frame-1)*setsize + setsize-1] = time[frame]; + + MEM_freeN(verts); + MEM_freeN(tris); + } + *setchannel = channel; +} + + +/* ******************************************************************************** */ +/* ********************** simulation thread ************************* */ +/* ******************************************************************************** */ + +static volatile int globalBakeState = 0; // 0 everything ok, -1 abort simulation, -2 sim error, 1 sim done +static volatile int globalBakeFrame = 0; +static volatile int g_break= 0; + +// run simulation in seperate thread +static void *fluidsimSimulateThread(void *unused) { // *ptr) { + //char* fnameCfgPath = (char*)(ptr); + int ret=0; + + ret = elbeemSimulate(); + BLI_lock_thread(LOCK_CUSTOM1); + if(globalBakeState==0) { + if(ret==0) { + // if no error, set to normal exit + globalBakeState = 1; + } else { + // simulation failed, display error + globalBakeState = -2; + } + } + BLI_unlock_thread(LOCK_CUSTOM1); + return NULL; +} + + +int runSimulationCallback(void *data, int status, int frame) { + //elbeemSimulationSettings *settings = (elbeemSimulationSettings*)data; + //printf("elbeem blender cb s%d, f%d, domainid:%d \n", status,frame, settings->domainId ); // DEBUG + int state = 0; + if(status==FLUIDSIM_CBSTATUS_NEWFRAME) { + BLI_lock_thread(LOCK_CUSTOM1); + globalBakeFrame = frame-1; + BLI_unlock_thread(LOCK_CUSTOM1); + } + + //if((frameCounter==3) && (!frameStop)) { frameStop=1; return 1; } + + BLI_lock_thread(LOCK_CUSTOM1); + state = globalBakeState; + BLI_unlock_thread(LOCK_CUSTOM1); + + if(state!=0) { + return FLUIDSIM_CBRET_ABORT; + } + + return FLUIDSIM_CBRET_CONTINUE; +} + + +/* ******************************************************************************** */ +/* ********************** write fluidsim config to file ************************* */ +/* ******************************************************************************** */ + +void fluidsimBake(bContext *C, struct Object *ob) +{ + Scene *scene= CTX_data_scene(C); + FILE *fileCfg; + int i; + struct Object *fsDomain = NULL; + FluidsimSettings *domainSettings; + struct Object *obit = NULL; /* object iterator */ + Base *base; + int origFrame = scene->r.cfra; + char debugStrBuffer[256]; + int dirExist = 0; + int gridlevels = 0; + int simAborted = 0; // was the simulation aborted by user? + int doExportOnly = 0; + char *exportEnvStr = "BLENDER_ELBEEMEXPORTONLY"; + const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp + //char *channelNames[3] = { "translation","rotation","scale" }; + + 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 + int haveSomeFluid = 0; // check if any fluid objects are set + + // config vars, inited before either export or run... + double calcViscosity = 0.0; + int noFrames; + double aniFrameTime; + float aniFrlen; + int channelObjCount; + float *bbStart = NULL; + float *bbSize = NULL; + float domainMat[4][4]; + float invDomMat[4][4]; + // channel data + int allchannelSize; // fixed by no. of frames + int startFrame = 1; // dont use scene->r.sfra here, always start with frame 1 + // easy frame -> sim time calc + float *timeAtFrame=NULL, *timeAtIndex=NULL; + // domain + float *channelDomainTime = NULL; + float *channelDomainViscosity = NULL; + float *channelDomainGravity = NULL; + // objects (currently max. 256 objs) + float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale + float *channelObjInivel[256]; // initial velocities + float *channelObjActive[256]; // obj active channel + + /* fluid control channels */ + float *channelAttractforceStrength[256]; + float *channelAttractforceRadius[256]; + float *channelVelocityforceStrength[256]; + float *channelVelocityforceRadius[256]; + FluidsimModifierData *fluidmd = NULL; + Mesh *mesh = NULL; + + if(getenv(strEnvName)) { + int dlevel = atoi(getenv(strEnvName)); + elbeemSetDebugLevel(dlevel); + snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName); + elbeemDebugOut(debugStrBuffer); + } + if(getenv(exportEnvStr)) { + doExportOnly = atoi(getenv(exportEnvStr)); + snprintf(debugStrBuffer,256,"fluidsimBake::msg: Exporting mode set to '%d' due to envvar '%s'\n",doExportOnly, exportEnvStr); + elbeemDebugOut(debugStrBuffer); + } + + // make sure it corresponds to startFrame setting + // old: noFrames = scene->r.efra - scene->r.sfra +1; + noFrames = scene->r.efra - 0; + if(noFrames<=0) { + pupmenu("Fluidsim Bake Error%t|No frames to export - check your animation range settings. Aborted%x0"); + return; + } + + /* no object pointer, find in selected ones.. */ + if(!ob) { + for(base=scene->base.first; base; base= base->next) { + if ((base)->flag & SELECT) + { + FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); + + if(fluidmdtmp && (base->object->type==OB_MESH)) + { + if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) + { + ob = base->object; + break; + } + } + } + } + // no domains found? + if(!ob) return; + } + + channelObjCount = 0; + for(base=scene->base.first; base; base= base->next) + { + FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); + obit = base->object; + if( fluidmdtmp && + (obit->type==OB_MESH) && + (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH + (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) + { + channelObjCount++; + } + } + + if (channelObjCount>=255) { + pupmenu("Fluidsim Bake Error%t|Cannot bake with more then 256 objects"); + return; + } + + /* check if there's another domain... */ + for(base=scene->base.first; base; base= base->next) + { + FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); + obit = base->object; + if( fluidmdtmp &&(obit->type==OB_MESH)) + { + if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) + { + if(obit != ob) + { + pupmenu("Fluidsim Bake Error%t|There should be only one domain object! Aborted%x0"); + return; + } + } + } + } + + // check if theres any fluid + // abort baking if not... + for(base=scene->base.first; base; base= base->next) + { + FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); + obit = base->object; + if( fluidmdtmp && + (obit->type==OB_MESH) && + ((fluidmdtmp->fss->type == OB_FLUIDSIM_FLUID) || + (fluidmdtmp->fss->type == OB_FLUIDSIM_INFLOW) )) + { + haveSomeFluid = 1; + break; + } + } + if(!haveSomeFluid) { + pupmenu("Fluidsim Bake Error%t|No fluid objects in scene... Aborted%x0"); + return; + } + + /* these both have to be valid, otherwise we wouldnt be here */ + /* dont use ob here after...*/ + fsDomain = ob; + fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); + domainSettings = fluidmd->fss; + ob = NULL; + mesh = fsDomain->data; + + // calculate bounding box + fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize); + + // reset last valid frame + domainSettings->lastgoodframe = -1; + + /* rough check of settings... */ + if(domainSettings->previewresxyz > domainSettings->resolutionxyz) { + snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz , domainSettings->resolutionxyz); + elbeemDebugOut(debugStrBuffer); + domainSettings->previewresxyz = domainSettings->resolutionxyz; + } + // set adaptive coarsening according to resolutionxyz + // this should do as an approximation, with in/outflow + // doing this more accurate would be overkill + // perhaps add manual setting? + if(domainSettings->maxRefine <0) { + if(domainSettings->resolutionxyz>128) { + gridlevels = 2; + } else + if(domainSettings->resolutionxyz>64) { + gridlevels = 1; + } else { + gridlevels = 0; + } + } else { + gridlevels = domainSettings->maxRefine; + } + snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels ); + elbeemDebugOut(debugStrBuffer); + + // prepare names... + strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR); + strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); + BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no + + strcpy(targetFile, targetDir); + strcat(targetFile, suffixConfig); + if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file + // make sure all directories exist + // as the bobjs use the same dir, this only needs to be checked + // for the cfg output + BLI_make_existing_file(targetFile); + + // check selected directory + // simply try to open cfg file for writing to test validity of settings + fileCfg = fopen(targetFile, "w"); + if(fileCfg) { + dirExist = 1; fclose(fileCfg); + // remove cfg dummy from directory test + if(!doExportOnly) { BLI_delete(targetFile, 0,0); } + } + + if((strlen(targetDir)<1) || (!dirExist)) { + char blendDir[FILE_MAXDIR+FILE_MAXFILE], blendFile[FILE_MAXDIR+FILE_MAXFILE]; + // invalid dir, reset to current/previous + strcpy(blendDir, G.sce); + BLI_splitdirstring(blendDir, blendFile); + if(strlen(blendFile)>6){ + int len = strlen(blendFile); + if( (blendFile[len-6]=='.')&& (blendFile[len-5]=='b')&& (blendFile[len-4]=='l')&& + (blendFile[len-3]=='e')&& (blendFile[len-2]=='n')&& (blendFile[len-1]=='d') ){ + blendFile[len-6] = '\0'; + } + } + // todo... strip .blend ? + snprintf(newSurfdataPath,FILE_MAXFILE+FILE_MAXDIR,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name); + + snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath); + elbeemDebugOut(debugStrBuffer); + outStringsChanged=1; + } + + // check if modified output dir is ok + if(outStringsChanged) { + char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256]; + int selection=0; + strcpy(dispmsg,"Output settings set to: '"); + 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); + strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR); + BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no + } + + // -------------------------------------------------------------------------------------------- + // dump data for start frame + // CHECK more reasonable to number frames according to blender? + // dump data for frame 0 + scene->r.cfra = startFrame; + ED_update_for_newframe(C, 0); + + // init common export vars for both file export and run + for(i=0; i<256; i++) { + channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL; + channelObjInivel[i] = NULL; + channelObjActive[i] = NULL; + channelAttractforceStrength[i] = NULL; + channelAttractforceRadius[i] = NULL; + channelVelocityforceStrength[i] = NULL; + channelVelocityforceRadius[i] = NULL; + } + allchannelSize = scene->r.efra; // always use till last frame + aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames; + // blender specific - scale according to map old/new settings in anim panel: + aniFrlen = scene->r.framelen; + if(domainSettings->viscosityMode==1) { + /* manual mode, visc=value/(10^-vexp) */ + calcViscosity = (1.0/pow(10.0,domainSettings->viscosityExponent)) * domainSettings->viscosityValue; + } else { + calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ]; + } + + bbStart = domainSettings->bbStart; + bbSize = domainSettings->bbSize; + + // always init + { int timeIcu[1] = { FLUIDSIM_TIME }; + float timeDef[1] = { 1. }; + int gravIcu[3] = { FLUIDSIM_GRAV_X, FLUIDSIM_GRAV_Y, FLUIDSIM_GRAV_Z }; + float gravDef[3]; + int viscIcu[1] = { FLUIDSIM_VISC }; + float viscDef[1] = { 1. }; + + gravDef[0] = domainSettings->gravx; + gravDef[1] = domainSettings->gravy; + gravDef[2] = domainSettings->gravz; + + // time channel is a bit special, init by hand... + timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex"); + for(i=0; i<=scene->r.efra; i++) { + timeAtIndex[i] = (float)(i-startFrame); + } + fluidsimInitChannel(scene, &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB + // time channel is a multiplicator for aniFrameTime + if(channelDomainTime) { + for(i=0; ianimStart; // start at index 1 + if(channelDomainTime) { + for(i=2; i<=allchannelSize; i++) { + timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0]; + } + } else { + for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; } + } + + fluidsimInitChannel(scene, &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB + if(channelDomainViscosity) { + for(i=0; iipo, CHANNEL_VEC ); + } // domain channel init + + // init obj movement channels + channelObjCount=0; + for(base=scene->base.first; base; base= base->next) + { + FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); + obit = base->object; + + if( fluidmdtmp && + (obit->type==OB_MESH) && + (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH + (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) { + + // cant use fluidsimInitChannel for obj channels right now, due + // to the special DXXX channels, and the rotation specialities + IpoCurve *icuex[3][3]; + //IpoCurve *par_icuex[3][3]; +#if 0 + int icuIds[3][3] = { + {OB_LOC_X, OB_LOC_Y, OB_LOC_Z}, + {OB_ROT_X, OB_ROT_Y, OB_ROT_Z}, + {OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z} + }; + int icudIds[3][3] = { + {OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z}, + {OB_DROT_X, OB_DROT_Y, OB_DROT_Z}, + {OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z} + }; +#endif + // relative ipos + IpoCurve *icudex[3][3]; + //IpoCurve *par_icudex[3][3]; + int j,k; + float vals[3] = {0.0,0.0,0.0}; + int o = channelObjCount; + int inivelIcu[3] = { FLUIDSIM_VEL_X, FLUIDSIM_VEL_Y, FLUIDSIM_VEL_Z }; + float inivelDefs[3]; + int activeIcu[1] = { FLUIDSIM_ACTIVE }; + float activeDefs[1] = { 1 }; // default to on + + inivelDefs[0] = fluidmdtmp->fss->iniVelx; + inivelDefs[1] = fluidmdtmp->fss->iniVely; + inivelDefs[2] = fluidmdtmp->fss->iniVelz; + + // check & init loc,rot,size + for(j=0; j<3; j++) { + for(k=0; k<3; k++) { + // XXX icuex[j][k] = find_ipocurve(obit->ipo, icuIds[j][k] ); + // XXX icudex[j][k] = find_ipocurve(obit->ipo, icudIds[j][k] ); + // XXX lines below were already disabled! + //if(obit->parent) { + //par_icuex[j][k] = find_ipocurve(obit->parent->ipo, icuIds[j][k] ); + //par_icudex[j][k] = find_ipocurve(obit->parent->ipo, icudIds[j][k] ); + //} + } + } + + for(j=0; j<3; j++) { + channelObjMove[o][j] = MEM_callocN( allchannelSize*4*sizeof(float), "fluidsiminit_objmovchannel"); + for(i=1; i<=allchannelSize; i++) { + + for(k=0; k<3; k++) { + if(icuex[j][k]) { + // IPO exists, use it ... + // XXX calc_icu(icuex[j][k], aniFrlen*((float)i) ); + vals[k] = icuex[j][k]->curval; + if(obit->parent) { + // add parent transform, multiply scaling, add trafo&rot + //calc_icu(par_icuex[j][k], aniFrlen*((float)i) ); + //if(j==2) { vals[k] *= par_icuex[j][k]->curval; } + //else { vals[k] += par_icuex[j][k]->curval; } + } + } else { + // use defaults from static values + float setval=0.0; + if(j==0) { + setval = obit->loc[k]; + if(obit->parent){ setval += obit->parent->loc[k]; } + } else if(j==1) { + setval = ( 180.0*obit->rot[k] )/( 10.0*M_PI ); + if(obit->parent){ setval = ( 180.0*(obit->rot[k]+obit->parent->rot[k]) )/( 10.0*M_PI ); } + } else { + setval = obit->size[k]; + if(obit->parent){ setval *= obit->parent->size[k]; } + } + vals[k] = setval; + } + if(icudex[j][k]) { + // XXX calc_icu(icudex[j][k], aniFrlen*((float)i) ); + //vals[k] += icudex[j][k]->curval; + // add transform, multiply scaling, add trafo&rot + if(j==2) { vals[k] *= icudex[j][k]->curval; } + else { vals[k] += icudex[j][k]->curval; } + if(obit->parent) { + // add parent transform, multiply scaling, add trafo&rot + //calc_icu(par_icuex[j][k], aniFrlen*((float)i) ); + //if(j==2) { vals[k] *= par_icudex[j][k]->curval; } + //else { vals[k] += par_icudex[j][k]->curval; } + } + } + } // k + + for(k=0; k<3; k++) { + float set = vals[k]; + if(j==1) { // rot is downscaled by 10 for ipo !? + set = 360.0 - (10.0*set); + } + channelObjMove[o][j][(i-1)*4 + k] = set; + } // k + channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i]; + } + } + + { + int attrFSIcu[1] = { FLUIDSIM_ATTR_FORCE_STR }; + int attrFRIcu[1] = { FLUIDSIM_ATTR_FORCE_RADIUS }; + int velFSIcu[1] = { FLUIDSIM_VEL_FORCE_STR }; + int velFRIcu[1] = { FLUIDSIM_VEL_FORCE_RADIUS }; + + float attrFSDefs[1]; + float attrFRDefs[1]; + float velFSDefs[1]; + float velFRDefs[1]; + + attrFSDefs[0] = fluidmdtmp->fss->attractforceStrength; + attrFRDefs[0] = fluidmdtmp->fss->attractforceRadius; + velFSDefs[0] = fluidmdtmp->fss->velocityforceStrength; + velFRDefs[0] = fluidmdtmp->fss->velocityforceRadius; + + fluidsimInitChannel(scene, &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); + fluidsimInitChannel(scene, &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); + fluidsimInitChannel(scene, &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); + fluidsimInitChannel(scene, &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); + } + + fluidsimInitChannel(scene, &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, fluidmdtmp->fss->ipo, CHANNEL_VEC ); + fluidsimInitChannel(scene, &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); + + + channelObjCount++; + + } + } + + // init trafo matrix + Mat4CpyMat4(domainMat, fsDomain->obmat); + if(!Mat4Invert(invDomMat, domainMat)) { + snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n"); + elbeemDebugOut(debugStrBuffer); + // FIXME add fatal msg + FS_FREE_CHANNELS; + return; + } + + + // -------------------------------------------------------------------------------------------- + // start writing / exporting + strcpy(targetFile, targetDir); + strcat(targetFile, suffixConfig); + if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file + // make sure these directories exist as well + if(outStringsChanged) { + BLI_make_existing_file(targetFile); + } + + if(!doExportOnly) { + ListBase threads; + + // perform simulation with El'Beem api and threads + elbeemSimulationSettings fsset; + elbeemResetSettings(&fsset); + fsset.version = 1; + + // setup global settings + for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i]; + for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i]; + + // simulate with 50^3 + fsset.resolutionxyz = (int)domainSettings->resolutionxyz; + fsset.previewresxyz = (int)domainSettings->previewresxyz; + // 10cm water domain + fsset.realsize = domainSettings->realsize; + fsset.viscosity = calcViscosity; + // earth gravity + fsset.gravity[0] = domainSettings->gravx; + fsset.gravity[1] = domainSettings->gravy; + fsset.gravity[2] = domainSettings->gravz; + // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz + fsset.animStart = domainSettings->animStart; + fsset.aniFrameTime = aniFrameTime; + fsset.noOfFrames = noFrames; // is otherwise subtracted in parser + strcpy(targetFile, targetDir); + strcat(targetFile, suffixSurface); + // defaults for compressibility and adaptive grids + fsset.gstar = domainSettings->gstar; + fsset.maxRefine = domainSettings->maxRefine; // check <-> gridlevels + fsset.generateParticles = domainSettings->generateParticles; + fsset.numTracerParticles = domainSettings->generateTracers; + fsset.surfaceSmoothing = domainSettings->surfaceSmoothing; + fsset.surfaceSubdivs = domainSettings->surfaceSubdivs; + fsset.farFieldSize = domainSettings->farFieldSize; + strcpy( fsset.outputPath, targetFile); + + // domain channels + fsset.channelSizeFrameTime = + fsset.channelSizeViscosity = + fsset.channelSizeGravity = allchannelSize; + fsset.channelFrameTime = channelDomainTime; + fsset.channelViscosity = channelDomainViscosity; + fsset.channelGravity = channelDomainGravity; + + fsset.runsimCallback = &runSimulationCallback; + fsset.runsimUserData = &fsset; + + if( (domainSettings->typeFlags&OB_FSBND_NOSLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_NOSLIP; + else if((domainSettings->typeFlags&OB_FSBND_PARTSLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP; + else if((domainSettings->typeFlags&OB_FSBND_FREESLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_FREESLIP; + fsset.domainobsPartslip = domainSettings->partSlipValue; + fsset.generateVertexVectors = (domainSettings->domainNovecgen==0); + + // init blender trafo matrix + // fprintf(stderr,"elbeemInit - mpTrafo:\n"); + { int j; + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + fsset.surfaceTrafo[i*4+j] = invDomMat[j][i]; + // fprintf(stderr,"elbeemInit - mpTrafo %d %d = %f (%d) \n", i,j, fsset.surfaceTrafo[i*4+j] , (i*4+j) ); + } + } } + + // init solver with settings + elbeemInit(); + elbeemAddDomain(&fsset); + + // init objects + channelObjCount = 0; + for(base=scene->base.first; base; base= base->next) { + FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); + obit = base->object; + //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG + if( fluidmdtmp && // if has to match 3 places! // CHECKMATCH + (obit->type==OB_MESH) && + (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && + (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE)) + { + float *verts=NULL; + int *tris=NULL; + int numVerts=0, numTris=0; + int o = channelObjCount; + int deform = (fluidmdtmp->fss->domainNovecgen); // misused value + // todo - use blenderInitElbeemMesh + int modifierIndex = modifiers_indexInObject(obit, (ModifierData *)fluidmdtmp); + + elbeemMesh fsmesh; + elbeemResetMesh( &fsmesh ); + fsmesh.type = fluidmdtmp->fss->type; + // get name of object for debugging solver + fsmesh.name = obit->id.name; + + initElbeemMesh(scene, obit, &numVerts, &verts, &numTris, &tris, 0, modifierIndex); + fsmesh.numVertices = numVerts; + fsmesh.numTriangles = numTris; + fsmesh.vertices = verts; + fsmesh.triangles = tris; + + fsmesh.channelSizeTranslation = + fsmesh.channelSizeRotation = + fsmesh.channelSizeScale = + fsmesh.channelSizeInitialVel = + fsmesh.channelSizeActive = allchannelSize; + + fsmesh.channelTranslation = channelObjMove[o][0]; + fsmesh.channelRotation = channelObjMove[o][1]; + fsmesh.channelScale = channelObjMove[o][2]; + fsmesh.channelActive = channelObjActive[o]; + if( (fsmesh.type == OB_FLUIDSIM_FLUID) || + (fsmesh.type == OB_FLUIDSIM_INFLOW)) { + fsmesh.channelInitialVel = channelObjInivel[o]; + fsmesh.localInivelCoords = ((fluidmdtmp->fss->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0); + } + + if( (fluidmdtmp->fss->typeFlags&OB_FSBND_NOSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; + else if((fluidmdtmp->fss->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP; + else if((fluidmdtmp->fss->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP; + fsmesh.obstaclePartslip = fluidmdtmp->fss->partSlipValue; + fsmesh.volumeInitType = fluidmdtmp->fss->volumeInitType; + fsmesh.obstacleImpactFactor = fluidmdtmp->fss->surfaceSmoothing; // misused value + + if(fsmesh.type == OB_FLUIDSIM_CONTROL) + { + // control fluids will get exported as whole + deform = 1; + + fsmesh.cpsTimeStart = fluidmdtmp->fss->cpsTimeStart; + fsmesh.cpsTimeEnd = fluidmdtmp->fss->cpsTimeEnd; + fsmesh.cpsQuality = fluidmdtmp->fss->cpsQuality; + fsmesh.obstacleType = (fluidmdtmp->fss->flag & OB_FLUIDSIM_REVERSE); + + fsmesh.channelSizeAttractforceRadius = + fsmesh.channelSizeVelocityforceStrength = + fsmesh.channelSizeVelocityforceRadius = + fsmesh.channelSizeAttractforceStrength = allchannelSize; + + fsmesh.channelAttractforceStrength = channelAttractforceStrength[o]; + fsmesh.channelAttractforceRadius = channelAttractforceRadius[o]; + fsmesh.channelVelocityforceStrength = channelVelocityforceStrength[o]; + fsmesh.channelVelocityforceRadius = channelVelocityforceRadius[o]; + } + else + { + // set channels to 0 + fsmesh.channelAttractforceStrength = + fsmesh.channelAttractforceRadius = + fsmesh.channelVelocityforceStrength = + fsmesh.channelVelocityforceRadius = NULL; + } + + // animated meshes + if(deform) { + fsmesh.channelSizeVertices = allchannelSize; + fluidsimInitMeshChannel(C, &fsmesh.channelVertices, allchannelSize, obit, numVerts, timeAtFrame, modifierIndex); + scene->r.cfra = startFrame; + ED_update_for_newframe(C, 0); + // remove channels + fsmesh.channelTranslation = + fsmesh.channelRotation = + fsmesh.channelScale = NULL; + } + + elbeemAddMesh(&fsmesh); + + if(verts) MEM_freeN(verts); + if(tris) MEM_freeN(tris); + if(fsmesh.channelVertices) MEM_freeN(fsmesh.channelVertices); + channelObjCount++; + } // valid mesh + } // objects + //domainSettings->type = OB_FLUIDSIM_DOMAIN; // enable for bake display again + //fsDomain->fluidsimFlag = OB_FLUIDSIM_ENABLE; // disable during bake + + // set to neutral, -1 means user abort, -2 means init error + globalBakeState = 0; + globalBakeFrame = 0; + BLI_init_threads(&threads, fluidsimSimulateThread, 1); + BLI_insert_thread(&threads, targetFile); + + { + int done = 0; + float noFramesf = (float)noFrames; + float percentdone = 0.0; + int lastRedraw = -1; + + g_break= 0; + G.afbreek= 0; /* blender_test_break uses this global */ + + start_progress_bar(); + + while(done==0) { + char busy_mess[80]; + + waitcursor(1); + + // lukep we add progress bar as an interim mesure + percentdone = globalBakeFrame / noFramesf; + sprintf(busy_mess, "baking fluids %d / %d |||", globalBakeFrame, (int) noFramesf); + progress_bar(percentdone, busy_mess ); + + // longer delay to prevent frequent redrawing + PIL_sleep_ms(2000); + + BLI_lock_thread(LOCK_CUSTOM1); + if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort + BLI_unlock_thread(LOCK_CUSTOM1); + + if (!G.background) { + g_break= blender_test_break(); + + if(g_break) + { + // abort... + BLI_lock_thread(LOCK_CUSTOM1); + + if(domainSettings) + domainSettings->lastgoodframe = startFrame+globalBakeFrame; + + done = -1; + globalBakeFrame = 0; + globalBakeState = -1; + simAborted = 1; + BLI_unlock_thread(LOCK_CUSTOM1); + break; + } + } + + // redraw the 3D for showing progress once in a while... + if(lastRedraw!=globalBakeFrame) { +#if 0 + ScrArea *sa; + scene->r.cfra = startFrame+globalBakeFrame; + lastRedraw = globalBakeFrame; + ED_update_for_newframe(C, 0); + sa= G.curscreen->areabase.first; + while(sa) { + if(sa->spacetype == SPACE_VIEW3D) { scrarea_do_windraw(sa); } + sa= sa->next; + } + screen_swapbuffers(); +#endif + } // redraw + } + end_progress_bar(); + } + BLI_end_threads(&threads); + } // El'Beem API init, thread creation + // -------------------------------------------------------------------------------------------- + else + { // write config file to be run with command line simulator + pupmenu("Fluidsim Bake Message%t|Config file export not supported.%x0"); + } // config file export done! + + // -------------------------------------------------------------------------------------------- + FS_FREE_CHANNELS; + + // go back to "current" blender time + waitcursor(0); + + if(globalBakeState >= 0) + { + if(domainSettings) + domainSettings->lastgoodframe = startFrame+globalBakeFrame; + } + + scene->r.cfra = origFrame; + ED_update_for_newframe(C, 0); + + if(!simAborted) { + char fsmessage[512]; + char elbeemerr[256]; + strcpy(fsmessage,"Fluidsim Bake Error: "); + // check if some error occurred + if(globalBakeState==-2) { + strcat(fsmessage,"Failed to initialize [Msg: "); + + elbeemGetErrorString(elbeemerr); + strcat(fsmessage,elbeemerr); + + strcat(fsmessage,"] |OK%x0"); + pupmenu(fsmessage); + } // init error + } + + // elbeemFree(); +} + +void fluidsimFreeBake(struct Object *ob) +{ + /* not implemented yet */ +} + + +#else /* DISABLE_ELBEEM */ + +/* compile dummy functions for disabled fluid sim */ + +FluidsimSettings *fluidsimSettingsNew(struct Object *srcob) { + return NULL; +} + +void fluidsimSettingsFree(FluidsimSettings *fss) { +} + +FluidsimSettings* fluidsimSettingsCopy(FluidsimSettings *fss) { + return NULL; +} + +/* only compile dummy functions */ +void fluidsimBake(bContext *C, struct Object *ob) +} + +void fluidsimFreeBake(struct Object *ob) { +} + +#endif /* DISABLE_ELBEEM */ + diff --git a/source/blender/editors/physics/fluidsim.c b/source/blender/editors/physics/fluidsim.c deleted file mode 100644 index 902979e0775..00000000000 --- a/source/blender/editors/physics/fluidsim.c +++ /dev/null @@ -1,1149 +0,0 @@ -/** - * fluidsim.c - * - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) Blender Foundation - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - - - -#include -#include -#include -#include - -#ifdef WIN32 /* Windos */ -#ifndef snprintf -#define snprintf _snprintf -#endif -#endif - -#include "MEM_guardedalloc.h" - -/* types */ -#include "DNA_curve_types.h" -#include "DNA_object_types.h" -#include "DNA_object_fluidsim.h" -#include "DNA_key_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_lattice_types.h" -#include "DNA_scene_types.h" -#include "DNA_camera_types.h" -#include "DNA_screen_types.h" -#include "DNA_space_types.h" -#include "DNA_userdef_types.h" -#include "DNA_ipo_types.h" -#include "DNA_key_types.h" - -#include "BLI_blenlib.h" -#include "BLI_threads.h" -#include "BLI_arithb.h" - -#include "BKE_blender.h" -#include "BKE_context.h" -#include "BKE_customdata.h" -#include "BKE_displist.h" -#include "BKE_effect.h" -#include "BKE_fluidsim.h" -#include "BKE_global.h" -#include "BKE_modifier.h" -#include "BKE_main.h" -#include "BKE_key.h" -#include "BKE_scene.h" -#include "BKE_object.h" -#include "BKE_softbody.h" -#include "BKE_DerivedMesh.h" -#include "BKE_ipo.h" - -#include "PIL_time.h" - -#include "LBM_fluidsim.h" - -#include "BIF_gl.h" - -#include "ED_anim_api.h" -#include "ED_fluidsim.h" - -/* XXX */ -/* from header info.c */ -static int start_progress_bar(void) {return 0;}; -static void end_progress_bar(void) {}; -static void waitcursor() {}; -static int progress_bar(float done, char *busy_info) {return 0;} -static int pupmenu() {return 0;} -/* XXX */ - - -double fluidsimViscosityPreset[6] = { - -1.0, /* unused */ - -1.0, /* manual */ - 1.0e-6, /* water */ - 5.0e-5, /* some (thick) oil */ - 2.0e-3, /* ca. honey */ - -1.0 /* end */ -}; - -char* fluidsimViscosityPresetString[6] = { - "UNUSED", /* unused */ - "UNUSED", /* manual */ - " = 1.0 * 10^-6", /* water */ - " = 5.0 * 10^-5", /* some (thick) oil */ - " = 2.0 * 10^-3", /* ca. honey */ - "INVALID" /* end */ -}; - -/* enable/disable overall compilation */ -#ifndef DISABLE_ELBEEM - - -/* ********************** fluid sim settings struct functions ********************** */ - -/* helper function */ -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); -} - - - - -/* ******************************************************************************** */ -/* ********************** fluid sim channel helper functions ********************** */ -/* ******************************************************************************** */ - -// no. of entries for the two channel sizes -#define CHANNEL_FLOAT 1 -#define CHANNEL_VEC 3 - -#define FS_FREE_ONECHANNEL(c,str) { \ - if(c){ MEM_freeN(c); c=NULL; } \ -} // end ONE CHANN, debug: fprintf(stderr,"freeing " str " \n"); - -#define FS_FREE_CHANNELS { \ - FS_FREE_ONECHANNEL(timeAtIndex,"timeAtIndex");\ - FS_FREE_ONECHANNEL(timeAtFrame,"timeAtFrame");\ - FS_FREE_ONECHANNEL(channelDomainTime,"channelDomainTime"); \ - FS_FREE_ONECHANNEL(channelDomainGravity,"channelDomainGravity");\ - FS_FREE_ONECHANNEL(channelDomainViscosity,"channelDomainViscosity");\ - for(i=0;i<256;i++) { \ - FS_FREE_ONECHANNEL(channelObjMove[i][0],"channelObjMove0"); \ - FS_FREE_ONECHANNEL(channelObjMove[i][1],"channelObjMove1"); \ - FS_FREE_ONECHANNEL(channelObjMove[i][2],"channelObjMove2"); \ - FS_FREE_ONECHANNEL(channelObjInivel[i],"channelObjInivel"); \ - FS_FREE_ONECHANNEL(channelObjActive[i],"channelObjActive"); \ - FS_FREE_ONECHANNEL(channelAttractforceStrength[i],"channelAttractforceStrength"); \ - FS_FREE_ONECHANNEL(channelAttractforceRadius[i],"channelAttractforceRadius"); \ - FS_FREE_ONECHANNEL(channelVelocityforceStrength[i],"channelVelocityforceStrength"); \ - FS_FREE_ONECHANNEL(channelVelocityforceRadius[i],"channelVelocityforceRadius"); \ - } \ -} // end FS FREE CHANNELS - - -// simplify channels before printing -// for API this is done anyway upon init -#if 0 -static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries) -{ - int i,j; - int channelSize = paramsize; - - if(entries==3) { - elbeemSimplifyChannelVec3( channel, &channelSize); - } else if(entries==1) { - elbeemSimplifyChannelFloat( channel, &channelSize); - } else { - // invalid, cant happen? - } - - fprintf(file, " CHANNEL %s = \n", str); - for(i=0; ir.framelen; - int current_frame = scene->r.cfra; - if((entries<1) || (entries>3)) { - printf("fluidsimInitChannel::Error - invalid no. of entries: %d\n",entries); - entries = 1; - } - - cstr = "fluidsiminit_channelfloat"; - if(entries>1) cstr = "fluidsiminit_channelvec"; - channel = MEM_callocN( size* (entries+1)* sizeof(float), cstr ); - - if(ipo) { - for(j=0; jr.cfra = floor(aniFrlen*((float)i)); - - // XXX calc_icu(icus[j], aniFrlen*((float)i) ); - channel[(i-1)*(entries+1) + j] = icus[j]->curval; - } - } else { - for(i=1; i<=size; i++) { channel[(i-1)*(entries+1) + j] = defaults[j]; } - } - //printf("fluidsimInitChannel entry:%d , ",j); for(i=1; i<=size; i++) { printf(" val%d:%f ",i, channel[(i-1)*(entries+1) + j] ); } printf(" \n"); // DEBUG - } - // set time values - for(i=1; i<=size; i++) { - channel[(i-1)*(entries+1) + entries] = time[i]; - } - scene->r.cfra = current_frame; - *setchannel = channel; -#endif -} - -static void fluidsimInitMeshChannel(bContext *C, float **setchannel, int size, Object *obm, int vertices, - float *time, int modifierIndex) -{ - Scene *scene= CTX_data_scene(C); - float *channel = NULL; - int mallsize = size* (3*vertices+1); - int frame,i; - int numVerts=0, numTris=0; - int setsize = 3*vertices+1; - - channel = MEM_callocN( mallsize* sizeof(float), "fluidsim_meshchannel" ); - - //fprintf(stderr,"\n\nfluidsimInitMeshChannel size%d verts%d mallsize%d \n\n\n",size,vertices,mallsize); - for(frame=1; frame<=size; frame++) { - float *verts=NULL; - int *tris=NULL; - scene->r.cfra = frame; - ED_update_for_newframe(C, 0); - - initElbeemMesh(scene, obm, &numVerts, &verts, &numTris, &tris, 1, modifierIndex); - //fprintf(stderr,"\nfluidsimInitMeshChannel frame%d verts%d/%d \n\n",frame,vertices,numVerts); - for(i=0; i<3*vertices;i++) { - channel[(frame-1)*setsize + i] = verts[i]; - //fprintf(stdout," frame%d vert%d=%f \n",frame,i,verts[i]); - //if(i%3==2) fprintf(stdout,"\n"); - } - channel[(frame-1)*setsize + setsize-1] = time[frame]; - - MEM_freeN(verts); - MEM_freeN(tris); - } - *setchannel = channel; -} - - -/* ******************************************************************************** */ -/* ********************** simulation thread ************************* */ -/* ******************************************************************************** */ - -static volatile int globalBakeState = 0; // 0 everything ok, -1 abort simulation, -2 sim error, 1 sim done -static volatile int globalBakeFrame = 0; -static volatile int g_break= 0; - -// run simulation in seperate thread -static void *fluidsimSimulateThread(void *unused) { // *ptr) { - //char* fnameCfgPath = (char*)(ptr); - int ret=0; - - ret = elbeemSimulate(); - BLI_lock_thread(LOCK_CUSTOM1); - if(globalBakeState==0) { - if(ret==0) { - // if no error, set to normal exit - globalBakeState = 1; - } else { - // simulation failed, display error - globalBakeState = -2; - } - } - BLI_unlock_thread(LOCK_CUSTOM1); - return NULL; -} - - -int runSimulationCallback(void *data, int status, int frame) { - //elbeemSimulationSettings *settings = (elbeemSimulationSettings*)data; - //printf("elbeem blender cb s%d, f%d, domainid:%d \n", status,frame, settings->domainId ); // DEBUG - int state = 0; - if(status==FLUIDSIM_CBSTATUS_NEWFRAME) { - BLI_lock_thread(LOCK_CUSTOM1); - globalBakeFrame = frame-1; - BLI_unlock_thread(LOCK_CUSTOM1); - } - - //if((frameCounter==3) && (!frameStop)) { frameStop=1; return 1; } - - BLI_lock_thread(LOCK_CUSTOM1); - state = globalBakeState; - BLI_unlock_thread(LOCK_CUSTOM1); - - if(state!=0) { - return FLUIDSIM_CBRET_ABORT; - } - - return FLUIDSIM_CBRET_CONTINUE; -} - - -/* ******************************************************************************** */ -/* ********************** write fluidsim config to file ************************* */ -/* ******************************************************************************** */ - -void fluidsimBake(bContext *C, struct Object *ob) -{ - Scene *scene= CTX_data_scene(C); - FILE *fileCfg; - int i; - struct Object *fsDomain = NULL; - FluidsimSettings *domainSettings; - struct Object *obit = NULL; /* object iterator */ - Base *base; - int origFrame = scene->r.cfra; - char debugStrBuffer[256]; - int dirExist = 0; - int gridlevels = 0; - int simAborted = 0; // was the simulation aborted by user? - int doExportOnly = 0; - char *exportEnvStr = "BLENDER_ELBEEMEXPORTONLY"; - const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp - //char *channelNames[3] = { "translation","rotation","scale" }; - - 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 - int haveSomeFluid = 0; // check if any fluid objects are set - - // config vars, inited before either export or run... - double calcViscosity = 0.0; - int noFrames; - double aniFrameTime; - float aniFrlen; - int channelObjCount; - float *bbStart = NULL; - float *bbSize = NULL; - float domainMat[4][4]; - float invDomMat[4][4]; - // channel data - int allchannelSize; // fixed by no. of frames - int startFrame = 1; // dont use scene->r.sfra here, always start with frame 1 - // easy frame -> sim time calc - float *timeAtFrame=NULL, *timeAtIndex=NULL; - // domain - float *channelDomainTime = NULL; - float *channelDomainViscosity = NULL; - float *channelDomainGravity = NULL; - // objects (currently max. 256 objs) - float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale - float *channelObjInivel[256]; // initial velocities - float *channelObjActive[256]; // obj active channel - - /* fluid control channels */ - float *channelAttractforceStrength[256]; - float *channelAttractforceRadius[256]; - float *channelVelocityforceStrength[256]; - float *channelVelocityforceRadius[256]; - FluidsimModifierData *fluidmd = NULL; - Mesh *mesh = NULL; - - if(getenv(strEnvName)) { - int dlevel = atoi(getenv(strEnvName)); - elbeemSetDebugLevel(dlevel); - snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName); - elbeemDebugOut(debugStrBuffer); - } - if(getenv(exportEnvStr)) { - doExportOnly = atoi(getenv(exportEnvStr)); - snprintf(debugStrBuffer,256,"fluidsimBake::msg: Exporting mode set to '%d' due to envvar '%s'\n",doExportOnly, exportEnvStr); - elbeemDebugOut(debugStrBuffer); - } - - // make sure it corresponds to startFrame setting - // old: noFrames = scene->r.efra - scene->r.sfra +1; - noFrames = scene->r.efra - 0; - if(noFrames<=0) { - pupmenu("Fluidsim Bake Error%t|No frames to export - check your animation range settings. Aborted%x0"); - return; - } - - /* no object pointer, find in selected ones.. */ - if(!ob) { - for(base=scene->base.first; base; base= base->next) { - if ((base)->flag & SELECT) - { - FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); - - if(fluidmdtmp && (base->object->type==OB_MESH)) - { - if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) - { - ob = base->object; - break; - } - } - } - } - // no domains found? - if(!ob) return; - } - - channelObjCount = 0; - for(base=scene->base.first; base; base= base->next) - { - FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); - obit = base->object; - if( fluidmdtmp && - (obit->type==OB_MESH) && - (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH - (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) - { - channelObjCount++; - } - } - - if (channelObjCount>=255) { - pupmenu("Fluidsim Bake Error%t|Cannot bake with more then 256 objects"); - return; - } - - /* check if there's another domain... */ - for(base=scene->base.first; base; base= base->next) - { - FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); - obit = base->object; - if( fluidmdtmp &&(obit->type==OB_MESH)) - { - if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) - { - if(obit != ob) - { - pupmenu("Fluidsim Bake Error%t|There should be only one domain object! Aborted%x0"); - return; - } - } - } - } - - // check if theres any fluid - // abort baking if not... - for(base=scene->base.first; base; base= base->next) - { - FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); - obit = base->object; - if( fluidmdtmp && - (obit->type==OB_MESH) && - ((fluidmdtmp->fss->type == OB_FLUIDSIM_FLUID) || - (fluidmdtmp->fss->type == OB_FLUIDSIM_INFLOW) )) - { - haveSomeFluid = 1; - break; - } - } - if(!haveSomeFluid) { - pupmenu("Fluidsim Bake Error%t|No fluid objects in scene... Aborted%x0"); - return; - } - - /* these both have to be valid, otherwise we wouldnt be here */ - /* dont use ob here after...*/ - fsDomain = ob; - fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); - domainSettings = fluidmd->fss; - ob = NULL; - mesh = fsDomain->data; - - // calculate bounding box - fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize); - - // reset last valid frame - domainSettings->lastgoodframe = -1; - - /* rough check of settings... */ - if(domainSettings->previewresxyz > domainSettings->resolutionxyz) { - snprintf(debugStrBuffer,256,"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz , domainSettings->resolutionxyz); - elbeemDebugOut(debugStrBuffer); - domainSettings->previewresxyz = domainSettings->resolutionxyz; - } - // set adaptive coarsening according to resolutionxyz - // this should do as an approximation, with in/outflow - // doing this more accurate would be overkill - // perhaps add manual setting? - if(domainSettings->maxRefine <0) { - if(domainSettings->resolutionxyz>128) { - gridlevels = 2; - } else - if(domainSettings->resolutionxyz>64) { - gridlevels = 1; - } else { - gridlevels = 0; - } - } else { - gridlevels = domainSettings->maxRefine; - } - snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels ); - elbeemDebugOut(debugStrBuffer); - - // prepare names... - strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR); - strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); - BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no - - strcpy(targetFile, targetDir); - strcat(targetFile, suffixConfig); - if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file - // make sure all directories exist - // as the bobjs use the same dir, this only needs to be checked - // for the cfg output - BLI_make_existing_file(targetFile); - - // check selected directory - // simply try to open cfg file for writing to test validity of settings - fileCfg = fopen(targetFile, "w"); - if(fileCfg) { - dirExist = 1; fclose(fileCfg); - // remove cfg dummy from directory test - if(!doExportOnly) { BLI_delete(targetFile, 0,0); } - } - - if((strlen(targetDir)<1) || (!dirExist)) { - char blendDir[FILE_MAXDIR+FILE_MAXFILE], blendFile[FILE_MAXDIR+FILE_MAXFILE]; - // invalid dir, reset to current/previous - strcpy(blendDir, G.sce); - BLI_splitdirstring(blendDir, blendFile); - if(strlen(blendFile)>6){ - int len = strlen(blendFile); - if( (blendFile[len-6]=='.')&& (blendFile[len-5]=='b')&& (blendFile[len-4]=='l')&& - (blendFile[len-3]=='e')&& (blendFile[len-2]=='n')&& (blendFile[len-1]=='d') ){ - blendFile[len-6] = '\0'; - } - } - // todo... strip .blend ? - snprintf(newSurfdataPath,FILE_MAXFILE+FILE_MAXDIR,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name); - - snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath); - elbeemDebugOut(debugStrBuffer); - outStringsChanged=1; - } - - // check if modified output dir is ok - if(outStringsChanged) { - char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256]; - int selection=0; - strcpy(dispmsg,"Output settings set to: '"); - 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); - strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR); - BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no - } - - // -------------------------------------------------------------------------------------------- - // dump data for start frame - // CHECK more reasonable to number frames according to blender? - // dump data for frame 0 - scene->r.cfra = startFrame; - ED_update_for_newframe(C, 0); - - // init common export vars for both file export and run - for(i=0; i<256; i++) { - channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL; - channelObjInivel[i] = NULL; - channelObjActive[i] = NULL; - channelAttractforceStrength[i] = NULL; - channelAttractforceRadius[i] = NULL; - channelVelocityforceStrength[i] = NULL; - channelVelocityforceRadius[i] = NULL; - } - allchannelSize = scene->r.efra; // always use till last frame - aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames; - // blender specific - scale according to map old/new settings in anim panel: - aniFrlen = scene->r.framelen; - if(domainSettings->viscosityMode==1) { - /* manual mode, visc=value/(10^-vexp) */ - calcViscosity = (1.0/pow(10.0,domainSettings->viscosityExponent)) * domainSettings->viscosityValue; - } else { - calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ]; - } - - bbStart = domainSettings->bbStart; - bbSize = domainSettings->bbSize; - - // always init - { int timeIcu[1] = { FLUIDSIM_TIME }; - float timeDef[1] = { 1. }; - int gravIcu[3] = { FLUIDSIM_GRAV_X, FLUIDSIM_GRAV_Y, FLUIDSIM_GRAV_Z }; - float gravDef[3]; - int viscIcu[1] = { FLUIDSIM_VISC }; - float viscDef[1] = { 1. }; - - gravDef[0] = domainSettings->gravx; - gravDef[1] = domainSettings->gravy; - gravDef[2] = domainSettings->gravz; - - // time channel is a bit special, init by hand... - timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex"); - for(i=0; i<=scene->r.efra; i++) { - timeAtIndex[i] = (float)(i-startFrame); - } - fluidsimInitChannel(scene, &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB - // time channel is a multiplicator for aniFrameTime - if(channelDomainTime) { - for(i=0; ianimStart; // start at index 1 - if(channelDomainTime) { - for(i=2; i<=allchannelSize; i++) { - timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0]; - } - } else { - for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; } - } - - fluidsimInitChannel(scene, &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB - if(channelDomainViscosity) { - for(i=0; iipo, CHANNEL_VEC ); - } // domain channel init - - // init obj movement channels - channelObjCount=0; - for(base=scene->base.first; base; base= base->next) - { - FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); - obit = base->object; - - if( fluidmdtmp && - (obit->type==OB_MESH) && - (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH - (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) { - - // cant use fluidsimInitChannel for obj channels right now, due - // to the special DXXX channels, and the rotation specialities - IpoCurve *icuex[3][3]; - //IpoCurve *par_icuex[3][3]; -#if 0 - int icuIds[3][3] = { - {OB_LOC_X, OB_LOC_Y, OB_LOC_Z}, - {OB_ROT_X, OB_ROT_Y, OB_ROT_Z}, - {OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z} - }; - int icudIds[3][3] = { - {OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z}, - {OB_DROT_X, OB_DROT_Y, OB_DROT_Z}, - {OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z} - }; -#endif - // relative ipos - IpoCurve *icudex[3][3]; - //IpoCurve *par_icudex[3][3]; - int j,k; - float vals[3] = {0.0,0.0,0.0}; - int o = channelObjCount; - int inivelIcu[3] = { FLUIDSIM_VEL_X, FLUIDSIM_VEL_Y, FLUIDSIM_VEL_Z }; - float inivelDefs[3]; - int activeIcu[1] = { FLUIDSIM_ACTIVE }; - float activeDefs[1] = { 1 }; // default to on - - inivelDefs[0] = fluidmdtmp->fss->iniVelx; - inivelDefs[1] = fluidmdtmp->fss->iniVely; - inivelDefs[2] = fluidmdtmp->fss->iniVelz; - - // check & init loc,rot,size - for(j=0; j<3; j++) { - for(k=0; k<3; k++) { - // XXX icuex[j][k] = find_ipocurve(obit->ipo, icuIds[j][k] ); - // XXX icudex[j][k] = find_ipocurve(obit->ipo, icudIds[j][k] ); - // XXX lines below were already disabled! - //if(obit->parent) { - //par_icuex[j][k] = find_ipocurve(obit->parent->ipo, icuIds[j][k] ); - //par_icudex[j][k] = find_ipocurve(obit->parent->ipo, icudIds[j][k] ); - //} - } - } - - for(j=0; j<3; j++) { - channelObjMove[o][j] = MEM_callocN( allchannelSize*4*sizeof(float), "fluidsiminit_objmovchannel"); - for(i=1; i<=allchannelSize; i++) { - - for(k=0; k<3; k++) { - if(icuex[j][k]) { - // IPO exists, use it ... - // XXX calc_icu(icuex[j][k], aniFrlen*((float)i) ); - vals[k] = icuex[j][k]->curval; - if(obit->parent) { - // add parent transform, multiply scaling, add trafo&rot - //calc_icu(par_icuex[j][k], aniFrlen*((float)i) ); - //if(j==2) { vals[k] *= par_icuex[j][k]->curval; } - //else { vals[k] += par_icuex[j][k]->curval; } - } - } else { - // use defaults from static values - float setval=0.0; - if(j==0) { - setval = obit->loc[k]; - if(obit->parent){ setval += obit->parent->loc[k]; } - } else if(j==1) { - setval = ( 180.0*obit->rot[k] )/( 10.0*M_PI ); - if(obit->parent){ setval = ( 180.0*(obit->rot[k]+obit->parent->rot[k]) )/( 10.0*M_PI ); } - } else { - setval = obit->size[k]; - if(obit->parent){ setval *= obit->parent->size[k]; } - } - vals[k] = setval; - } - if(icudex[j][k]) { - // XXX calc_icu(icudex[j][k], aniFrlen*((float)i) ); - //vals[k] += icudex[j][k]->curval; - // add transform, multiply scaling, add trafo&rot - if(j==2) { vals[k] *= icudex[j][k]->curval; } - else { vals[k] += icudex[j][k]->curval; } - if(obit->parent) { - // add parent transform, multiply scaling, add trafo&rot - //calc_icu(par_icuex[j][k], aniFrlen*((float)i) ); - //if(j==2) { vals[k] *= par_icudex[j][k]->curval; } - //else { vals[k] += par_icudex[j][k]->curval; } - } - } - } // k - - for(k=0; k<3; k++) { - float set = vals[k]; - if(j==1) { // rot is downscaled by 10 for ipo !? - set = 360.0 - (10.0*set); - } - channelObjMove[o][j][(i-1)*4 + k] = set; - } // k - channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i]; - } - } - - { - int attrFSIcu[1] = { FLUIDSIM_ATTR_FORCE_STR }; - int attrFRIcu[1] = { FLUIDSIM_ATTR_FORCE_RADIUS }; - int velFSIcu[1] = { FLUIDSIM_VEL_FORCE_STR }; - int velFRIcu[1] = { FLUIDSIM_VEL_FORCE_RADIUS }; - - float attrFSDefs[1]; - float attrFRDefs[1]; - float velFSDefs[1]; - float velFRDefs[1]; - - attrFSDefs[0] = fluidmdtmp->fss->attractforceStrength; - attrFRDefs[0] = fluidmdtmp->fss->attractforceRadius; - velFSDefs[0] = fluidmdtmp->fss->velocityforceStrength; - velFRDefs[0] = fluidmdtmp->fss->velocityforceRadius; - - fluidsimInitChannel(scene, &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); - fluidsimInitChannel(scene, &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); - fluidsimInitChannel(scene, &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); - fluidsimInitChannel(scene, &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); - } - - fluidsimInitChannel(scene, &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, fluidmdtmp->fss->ipo, CHANNEL_VEC ); - fluidsimInitChannel(scene, &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT ); - - - channelObjCount++; - - } - } - - // init trafo matrix - Mat4CpyMat4(domainMat, fsDomain->obmat); - if(!Mat4Invert(invDomMat, domainMat)) { - snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n"); - elbeemDebugOut(debugStrBuffer); - // FIXME add fatal msg - FS_FREE_CHANNELS; - return; - } - - - // -------------------------------------------------------------------------------------------- - // start writing / exporting - strcpy(targetFile, targetDir); - strcat(targetFile, suffixConfig); - if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file - // make sure these directories exist as well - if(outStringsChanged) { - BLI_make_existing_file(targetFile); - } - - if(!doExportOnly) { - ListBase threads; - - // perform simulation with El'Beem api and threads - elbeemSimulationSettings fsset; - elbeemResetSettings(&fsset); - fsset.version = 1; - - // setup global settings - for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i]; - for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i]; - - // simulate with 50^3 - fsset.resolutionxyz = (int)domainSettings->resolutionxyz; - fsset.previewresxyz = (int)domainSettings->previewresxyz; - // 10cm water domain - fsset.realsize = domainSettings->realsize; - fsset.viscosity = calcViscosity; - // earth gravity - fsset.gravity[0] = domainSettings->gravx; - fsset.gravity[1] = domainSettings->gravy; - fsset.gravity[2] = domainSettings->gravz; - // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz - fsset.animStart = domainSettings->animStart; - fsset.aniFrameTime = aniFrameTime; - fsset.noOfFrames = noFrames; // is otherwise subtracted in parser - strcpy(targetFile, targetDir); - strcat(targetFile, suffixSurface); - // defaults for compressibility and adaptive grids - fsset.gstar = domainSettings->gstar; - fsset.maxRefine = domainSettings->maxRefine; // check <-> gridlevels - fsset.generateParticles = domainSettings->generateParticles; - fsset.numTracerParticles = domainSettings->generateTracers; - fsset.surfaceSmoothing = domainSettings->surfaceSmoothing; - fsset.surfaceSubdivs = domainSettings->surfaceSubdivs; - fsset.farFieldSize = domainSettings->farFieldSize; - strcpy( fsset.outputPath, targetFile); - - // domain channels - fsset.channelSizeFrameTime = - fsset.channelSizeViscosity = - fsset.channelSizeGravity = allchannelSize; - fsset.channelFrameTime = channelDomainTime; - fsset.channelViscosity = channelDomainViscosity; - fsset.channelGravity = channelDomainGravity; - - fsset.runsimCallback = &runSimulationCallback; - fsset.runsimUserData = &fsset; - - if( (domainSettings->typeFlags&OB_FSBND_NOSLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_NOSLIP; - else if((domainSettings->typeFlags&OB_FSBND_PARTSLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP; - else if((domainSettings->typeFlags&OB_FSBND_FREESLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_FREESLIP; - fsset.domainobsPartslip = domainSettings->partSlipValue; - fsset.generateVertexVectors = (domainSettings->domainNovecgen==0); - - // init blender trafo matrix - // fprintf(stderr,"elbeemInit - mpTrafo:\n"); - { int j; - for(i=0; i<4; i++) { - for(j=0; j<4; j++) { - fsset.surfaceTrafo[i*4+j] = invDomMat[j][i]; - // fprintf(stderr,"elbeemInit - mpTrafo %d %d = %f (%d) \n", i,j, fsset.surfaceTrafo[i*4+j] , (i*4+j) ); - } - } } - - // init solver with settings - elbeemInit(); - elbeemAddDomain(&fsset); - - // init objects - channelObjCount = 0; - for(base=scene->base.first; base; base= base->next) { - FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim); - obit = base->object; - //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG - if( fluidmdtmp && // if has to match 3 places! // CHECKMATCH - (obit->type==OB_MESH) && - (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && - (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE)) - { - float *verts=NULL; - int *tris=NULL; - int numVerts=0, numTris=0; - int o = channelObjCount; - int deform = (fluidmdtmp->fss->domainNovecgen); // misused value - // todo - use blenderInitElbeemMesh - int modifierIndex = modifiers_indexInObject(obit, (ModifierData *)fluidmdtmp); - - elbeemMesh fsmesh; - elbeemResetMesh( &fsmesh ); - fsmesh.type = fluidmdtmp->fss->type; - // get name of object for debugging solver - fsmesh.name = obit->id.name; - - initElbeemMesh(scene, obit, &numVerts, &verts, &numTris, &tris, 0, modifierIndex); - fsmesh.numVertices = numVerts; - fsmesh.numTriangles = numTris; - fsmesh.vertices = verts; - fsmesh.triangles = tris; - - fsmesh.channelSizeTranslation = - fsmesh.channelSizeRotation = - fsmesh.channelSizeScale = - fsmesh.channelSizeInitialVel = - fsmesh.channelSizeActive = allchannelSize; - - fsmesh.channelTranslation = channelObjMove[o][0]; - fsmesh.channelRotation = channelObjMove[o][1]; - fsmesh.channelScale = channelObjMove[o][2]; - fsmesh.channelActive = channelObjActive[o]; - if( (fsmesh.type == OB_FLUIDSIM_FLUID) || - (fsmesh.type == OB_FLUIDSIM_INFLOW)) { - fsmesh.channelInitialVel = channelObjInivel[o]; - fsmesh.localInivelCoords = ((fluidmdtmp->fss->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0); - } - - if( (fluidmdtmp->fss->typeFlags&OB_FSBND_NOSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; - else if((fluidmdtmp->fss->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP; - else if((fluidmdtmp->fss->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP; - fsmesh.obstaclePartslip = fluidmdtmp->fss->partSlipValue; - fsmesh.volumeInitType = fluidmdtmp->fss->volumeInitType; - fsmesh.obstacleImpactFactor = fluidmdtmp->fss->surfaceSmoothing; // misused value - - if(fsmesh.type == OB_FLUIDSIM_CONTROL) - { - // control fluids will get exported as whole - deform = 1; - - fsmesh.cpsTimeStart = fluidmdtmp->fss->cpsTimeStart; - fsmesh.cpsTimeEnd = fluidmdtmp->fss->cpsTimeEnd; - fsmesh.cpsQuality = fluidmdtmp->fss->cpsQuality; - fsmesh.obstacleType = (fluidmdtmp->fss->flag & OB_FLUIDSIM_REVERSE); - - fsmesh.channelSizeAttractforceRadius = - fsmesh.channelSizeVelocityforceStrength = - fsmesh.channelSizeVelocityforceRadius = - fsmesh.channelSizeAttractforceStrength = allchannelSize; - - fsmesh.channelAttractforceStrength = channelAttractforceStrength[o]; - fsmesh.channelAttractforceRadius = channelAttractforceRadius[o]; - fsmesh.channelVelocityforceStrength = channelVelocityforceStrength[o]; - fsmesh.channelVelocityforceRadius = channelVelocityforceRadius[o]; - } - else - { - // set channels to 0 - fsmesh.channelAttractforceStrength = - fsmesh.channelAttractforceRadius = - fsmesh.channelVelocityforceStrength = - fsmesh.channelVelocityforceRadius = NULL; - } - - // animated meshes - if(deform) { - fsmesh.channelSizeVertices = allchannelSize; - fluidsimInitMeshChannel(C, &fsmesh.channelVertices, allchannelSize, obit, numVerts, timeAtFrame, modifierIndex); - scene->r.cfra = startFrame; - ED_update_for_newframe(C, 0); - // remove channels - fsmesh.channelTranslation = - fsmesh.channelRotation = - fsmesh.channelScale = NULL; - } - - elbeemAddMesh(&fsmesh); - - if(verts) MEM_freeN(verts); - if(tris) MEM_freeN(tris); - if(fsmesh.channelVertices) MEM_freeN(fsmesh.channelVertices); - channelObjCount++; - } // valid mesh - } // objects - //domainSettings->type = OB_FLUIDSIM_DOMAIN; // enable for bake display again - //fsDomain->fluidsimFlag = OB_FLUIDSIM_ENABLE; // disable during bake - - // set to neutral, -1 means user abort, -2 means init error - globalBakeState = 0; - globalBakeFrame = 0; - BLI_init_threads(&threads, fluidsimSimulateThread, 1); - BLI_insert_thread(&threads, targetFile); - - { - int done = 0; - float noFramesf = (float)noFrames; - float percentdone = 0.0; - int lastRedraw = -1; - - g_break= 0; - G.afbreek= 0; /* blender_test_break uses this global */ - - start_progress_bar(); - - while(done==0) { - char busy_mess[80]; - - waitcursor(1); - - // lukep we add progress bar as an interim mesure - percentdone = globalBakeFrame / noFramesf; - sprintf(busy_mess, "baking fluids %d / %d |||", globalBakeFrame, (int) noFramesf); - progress_bar(percentdone, busy_mess ); - - // longer delay to prevent frequent redrawing - PIL_sleep_ms(2000); - - BLI_lock_thread(LOCK_CUSTOM1); - if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort - BLI_unlock_thread(LOCK_CUSTOM1); - - if (!G.background) { - g_break= blender_test_break(); - - if(g_break) - { - // abort... - BLI_lock_thread(LOCK_CUSTOM1); - - if(domainSettings) - domainSettings->lastgoodframe = startFrame+globalBakeFrame; - - done = -1; - globalBakeFrame = 0; - globalBakeState = -1; - simAborted = 1; - BLI_unlock_thread(LOCK_CUSTOM1); - break; - } - } - - // redraw the 3D for showing progress once in a while... - if(lastRedraw!=globalBakeFrame) { -#if 0 - ScrArea *sa; - scene->r.cfra = startFrame+globalBakeFrame; - lastRedraw = globalBakeFrame; - ED_update_for_newframe(C, 0); - sa= G.curscreen->areabase.first; - while(sa) { - if(sa->spacetype == SPACE_VIEW3D) { scrarea_do_windraw(sa); } - sa= sa->next; - } - screen_swapbuffers(); -#endif - } // redraw - } - end_progress_bar(); - } - BLI_end_threads(&threads); - } // El'Beem API init, thread creation - // -------------------------------------------------------------------------------------------- - else - { // write config file to be run with command line simulator - pupmenu("Fluidsim Bake Message%t|Config file export not supported.%x0"); - } // config file export done! - - // -------------------------------------------------------------------------------------------- - FS_FREE_CHANNELS; - - // go back to "current" blender time - waitcursor(0); - - if(globalBakeState >= 0) - { - if(domainSettings) - domainSettings->lastgoodframe = startFrame+globalBakeFrame; - } - - scene->r.cfra = origFrame; - ED_update_for_newframe(C, 0); - - if(!simAborted) { - char fsmessage[512]; - char elbeemerr[256]; - strcpy(fsmessage,"Fluidsim Bake Error: "); - // check if some error occurred - if(globalBakeState==-2) { - strcat(fsmessage,"Failed to initialize [Msg: "); - - elbeemGetErrorString(elbeemerr); - strcat(fsmessage,elbeemerr); - - strcat(fsmessage,"] |OK%x0"); - pupmenu(fsmessage); - } // init error - } - - // elbeemFree(); -} - -void fluidsimFreeBake(struct Object *ob) -{ - /* not implemented yet */ -} - - -#else /* DISABLE_ELBEEM */ - -/* compile dummy functions for disabled fluid sim */ - -FluidsimSettings *fluidsimSettingsNew(struct Object *srcob) { - return NULL; -} - -void fluidsimSettingsFree(FluidsimSettings *fss) { -} - -FluidsimSettings* fluidsimSettingsCopy(FluidsimSettings *fss) { - return NULL; -} - -/* only compile dummy functions */ -void fluidsimBake(bContext *C, struct Object *ob) -} - -void fluidsimFreeBake(struct Object *ob) { -} - -#endif /* DISABLE_ELBEEM */ - -- cgit v1.2.3