Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/physics/physics_fluid.c
| Show First 20 Lines • Show All 254 Lines • ▼ Show 20 Lines | static void set_vertex_channel(float *channel, float time, struct Scene *scene, struct FluidObject *fobj, int i) | ||||
| int framesize = (3*fobj->numVerts) + 1; | int framesize = (3*fobj->numVerts) + 1; | ||||
| int j; | int j; | ||||
| if (channel == NULL) | if (channel == NULL) | ||||
| return; | return; | ||||
| initElbeemMesh(scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex); | initElbeemMesh(scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex); | ||||
| /* don't allow mesh to change number of verts in anim sequence */ | |||||
| if (numVerts != fobj->numVerts) { | if (numVerts != fobj->numVerts) { | ||||
| MEM_freeN(channel); | MEM_freeN(channel); | ||||
| channel = NULL; | channel = NULL; | ||||
| return; | return; | ||||
| } | } | ||||
| /* fill frame of channel with vertex locations */ | |||||
| for (j=0; j < (3*numVerts); j++) { | for (j=0; j < (3*numVerts); j++) { | ||||
| channel[i*framesize + j] = verts[j]; | channel[i*framesize + j] = verts[j]; | ||||
| } | } | ||||
| channel[i*framesize + framesize-1] = time; | channel[i*framesize + framesize-1] = time; | ||||
| MEM_freeN(verts); | MEM_freeN(verts); | ||||
| MEM_freeN(tris); | MEM_freeN(tris); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
| static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects) | static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| Base *base; | Base *base; | ||||
| int i; | int i; | ||||
| int length = channels->length; | int length = channels->length; | ||||
| float eval_time; | float eval_time; | ||||
| /* init time values (assuming that time moves at a constant speed; may be overridden later) */ | |||||
| init_time(domainSettings, channels); | init_time(domainSettings, channels); | ||||
| /* allocate domain animation channels */ | |||||
| channels->DomainGravity = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "channel DomainGravity"); | channels->DomainGravity = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "channel DomainGravity"); | ||||
| channels->DomainViscosity = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainViscosity"); | channels->DomainViscosity = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainViscosity"); | ||||
| channels->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime"); | channels->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime"); | ||||
| /* allocate fluid objects */ | |||||
| for (base=scene->base.first; base; base= base->next) { | for (base=scene->base.first; base; base= base->next) { | ||||
| Object *ob = base->object; | Object *ob = base->object; | ||||
| FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); | FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); | ||||
| if (fluidmd) { | if (fluidmd) { | ||||
| FluidObject *fobj = MEM_callocN(sizeof(FluidObject), "Fluid Object"); | FluidObject *fobj = MEM_callocN(sizeof(FluidObject), "Fluid Object"); | ||||
| fobj->object = ob; | fobj->object = ob; | ||||
| Show All 25 Lines | if (fluidmd) { | ||||
| MEM_freeN(verts); | MEM_freeN(verts); | ||||
| MEM_freeN(tris); | MEM_freeN(tris); | ||||
| } | } | ||||
| BLI_addtail(fobjects, fobj); | BLI_addtail(fobjects, fobj); | ||||
| } | } | ||||
| } | } | ||||
| /* now we loop over the frames and fill the allocated channels with data */ | |||||
| for (i=0; i < channels->length; i++) { | for (i=0; i < channels->length; i++) { | ||||
| FluidObject *fobj; | FluidObject *fobj; | ||||
| float viscosity, gravity[3]; | float viscosity, gravity[3]; | ||||
| float timeAtFrame, time; | float timeAtFrame, time; | ||||
| eval_time = domainSettings->bakeStart + i; | eval_time = domainSettings->bakeStart + i; | ||||
| /* XXX: This can't be used due to an anim sys optimization that ignores recalc object animation, | |||||
| * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ ) | * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ ) | ||||
| * --> BKE_animsys_evaluate_all_animation(CTX_data_main(C), eval_time); | * --> BKE_animsys_evaluate_all_animation(G.main, eval_time); | ||||
| * This doesn't work with drivers: | * This doesn't work with drivers: | ||||
| * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL); | * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL); | ||||
| */ | */ | ||||
| /* Modifying the global scene isn't nice, but we can do it in | |||||
| * this part of the process before a threaded job is created */ | * this part of the process before a threaded job is created */ | ||||
| scene->r.cfra = (int)eval_time; | scene->r.cfra = (int)eval_time; | ||||
| ED_update_for_newframe(CTX_data_main(C), scene, 1); | ED_update_for_newframe(CTX_data_main(C), scene, 1); | ||||
| /* now scene data should be current according to animation system, so we fill the channels */ | /* now scene data should be current according to animation system, so we fill the channels */ | ||||
| /* Domain time */ | |||||
| // TODO: have option for not running sim, time mangling, in which case second case comes in handy | |||||
| if (channels->DomainTime) { | if (channels->DomainTime) { | ||||
| time = get_fluid_rate(domainSettings) * (float)channels->aniFrameTime; | time = get_fluid_rate(domainSettings) * (float)channels->aniFrameTime; | ||||
| timeAtFrame = channels->timeAtFrame[i] + time; | timeAtFrame = channels->timeAtFrame[i] + time; | ||||
| channels->timeAtFrame[i+1] = timeAtFrame; | channels->timeAtFrame[i+1] = timeAtFrame; | ||||
| set_channel(channels->DomainTime, i, &time, i, CHANNEL_FLOAT); | set_channel(channels->DomainTime, i, &time, i, CHANNEL_FLOAT); | ||||
| } | } | ||||
| else { | else { | ||||
| timeAtFrame = channels->timeAtFrame[i+1]; | timeAtFrame = channels->timeAtFrame[i+1]; | ||||
| } | } | ||||
| /* Domain properties - gravity/viscosity */ | |||||
| get_fluid_gravity(gravity, scene, domainSettings); | get_fluid_gravity(gravity, scene, domainSettings); | ||||
| set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC); | set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC); | ||||
| viscosity = get_fluid_viscosity(domainSettings); | viscosity = get_fluid_viscosity(domainSettings); | ||||
| set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT); | set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT); | ||||
| /* object movement */ | |||||
| for (fobj=fobjects->first; fobj; fobj=fobj->next) { | for (fobj=fobjects->first; fobj; fobj=fobj->next) { | ||||
| Object *ob = fobj->object; | Object *ob = fobj->object; | ||||
| FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); | FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); | ||||
| float active = (float) ((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) ? 1 : 0); | float active = (float) ((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) ? 1 : 0); | ||||
| float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f}; | float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f}; | ||||
| if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) | if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) | ||||
| continue; | continue; | ||||
| /* init euler rotation values and convert to elbeem format */ | /* init euler rotation values and convert to elbeem format */ | ||||
| /* get the rotation from ob->obmat rather than ob->rot to account for parent animations */ | |||||
| if (i) { | if (i) { | ||||
| copy_v3_v3(old_rot, fobj->Rotation + 4*(i-1)); | copy_v3_v3(old_rot, fobj->Rotation + 4*(i-1)); | ||||
| mul_v3_fl(old_rot, (float)-M_PI / 180.f); | mul_v3_fl(old_rot, (float)-M_PI / 180.f); | ||||
| } | } | ||||
| mat4_to_compatible_eulO(rot_d, old_rot, 0, ob->obmat); | mat4_to_compatible_eulO(rot_d, old_rot, 0, ob->obmat); | ||||
| mul_v3_fl(rot_d, -180.0f / (float)M_PI); | mul_v3_fl(rot_d, -180.0f / (float)M_PI); | ||||
| ▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | for (fobj=fobjects->first; fobj; fobj=fobj->next) { | ||||
| } | } | ||||
| else { | else { | ||||
| fsmesh.channelAttractforceStrength = | fsmesh.channelAttractforceStrength = | ||||
| fsmesh.channelAttractforceRadius = | fsmesh.channelAttractforceRadius = | ||||
| fsmesh.channelVelocityforceStrength = | fsmesh.channelVelocityforceStrength = | ||||
| fsmesh.channelVelocityforceRadius = NULL; | fsmesh.channelVelocityforceRadius = NULL; | ||||
| } | } | ||||
| /* animated meshes */ | |||||
| if (deform) { | if (deform) { | ||||
| fsmesh.channelSizeVertices = length; | fsmesh.channelSizeVertices = length; | ||||
| fsmesh.channelVertices = fobj->VertexCache; | fsmesh.channelVertices = fobj->VertexCache; | ||||
| /* remove channels */ | |||||
| fsmesh.channelTranslation = | fsmesh.channelTranslation = | ||||
| fsmesh.channelRotation = | fsmesh.channelRotation = | ||||
| fsmesh.channelScale = NULL; | fsmesh.channelScale = NULL; | ||||
| /* Override user settings, only noslip is supported here! */ | |||||
| if (fsmesh.type != OB_FLUIDSIM_CONTROL) | if (fsmesh.type != OB_FLUIDSIM_CONTROL) | ||||
| fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; | fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; | ||||
| } | } | ||||
| elbeemAddMesh(&fsmesh); | elbeemAddMesh(&fsmesh); | ||||
| if (verts) MEM_freeN(verts); | if (verts) MEM_freeN(verts); | ||||
| if (tris) MEM_freeN(tris); | if (tris) MEM_freeN(tris); | ||||
| Show All 21 Lines | if (fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) { | ||||
| } | } | ||||
| /* if there's more than one domain, cancel */ | /* if there's more than one domain, cancel */ | ||||
| else if (fsDomain && ob != fsDomain) { | else if (fsDomain && ob != fsDomain) { | ||||
| BKE_report(reports, RPT_ERROR, "There should be only one domain object"); | BKE_report(reports, RPT_ERROR, "There should be only one domain object"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| /* count number of objects needed for animation channels */ | |||||
| if ( !ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE) ) | if ( !ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE) ) | ||||
| channelObjCount++; | channelObjCount++; | ||||
| /* count number of fluid input objects */ | |||||
| if (ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) | if (ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) | ||||
| fluidInputCount++; | fluidInputCount++; | ||||
| } | } | ||||
| if (newdomain) | if (newdomain) | ||||
| fsDomain = newdomain; | fsDomain = newdomain; | ||||
| if (!fsDomain) { | if (!fsDomain) { | ||||
| ▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | |||||
| /* called by fluidbake, only to check job 'stop' value */ | /* called by fluidbake, only to check job 'stop' value */ | ||||
| static int fluidbake_breakjob(void *customdata) | static int fluidbake_breakjob(void *customdata) | ||||
| { | { | ||||
| FluidBakeJob *fb= (FluidBakeJob *)customdata; | FluidBakeJob *fb= (FluidBakeJob *)customdata; | ||||
| if (fb->stop && *(fb->stop)) | if (fb->stop && *(fb->stop)) | ||||
| return 1; | return 1; | ||||
| /* this is not nice yet, need to make the jobs list template better | |||||
| * for identifying/acting upon various different jobs */ | * for identifying/acting upon various different jobs */ | ||||
| /* but for now we'll reuse the render break... */ | /* but for now we'll reuse the render break... */ | ||||
| return (G.is_break); | return (G.is_break); | ||||
| } | } | ||||
| /* called by fluidbake, wmJob sends notifier */ | /* called by fluidbake, wmJob sends notifier */ | ||||
| static void fluidbake_updatejob(void *customdata, float progress) | static void fluidbake_updatejob(void *customdata, float progress) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, short do_job) | ||||
| FluidsimModifierData *fluidmd = NULL; | FluidsimModifierData *fluidmd = NULL; | ||||
| Mesh *mesh = NULL; | Mesh *mesh = NULL; | ||||
| FluidBakeJob *fb; | FluidBakeJob *fb; | ||||
| elbeemSimulationSettings *fsset= MEM_callocN(sizeof(elbeemSimulationSettings), "Fluid sim settings"); | elbeemSimulationSettings *fsset= MEM_callocN(sizeof(elbeemSimulationSettings), "Fluid sim settings"); | ||||
| fb= MEM_callocN(sizeof(FluidBakeJob), "fluid bake job"); | fb= MEM_callocN(sizeof(FluidBakeJob), "fluid bake job"); | ||||
| if (getenv(strEnvName)) { | if (BLI_getenv(strEnvName)) { | ||||
| int dlevel = atoi(getenv(strEnvName)); | int dlevel = atoi(BLI_getenv(strEnvName)); | ||||
| elbeemSetDebugLevel(dlevel); | elbeemSetDebugLevel(dlevel); | ||||
| BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Debug messages activated due to envvar '%s'\n", strEnvName); | BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Debug messages activated due to envvar '%s'\n", strEnvName); | ||||
| elbeemDebugOut(debugStrBuffer); | elbeemDebugOut(debugStrBuffer); | ||||
| } | } | ||||
| /* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */; | /* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */; | ||||
| noFrames = scene->r.efra - 0; | noFrames = scene->r.efra - 0; | ||||
| if (noFrames<=0) { | if (noFrames<=0) { | ||||
| BKE_report(reports, RPT_ERROR, "No frames to export (check your animation range settings)"); | BKE_report(reports, RPT_ERROR, "No frames to export (check your animation range settings)"); | ||||
| fluidbake_free_data(channels, fobjects, fsset, fb); | fluidbake_free_data(channels, fobjects, fsset, fb); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* check scene for sane object/modifier settings */ | |||||
| if (!fluid_validate_scene(reports, scene, fsDomain)) { | if (!fluid_validate_scene(reports, scene, fsDomain)) { | ||||
| fluidbake_free_data(channels, fobjects, fsset, fb); | fluidbake_free_data(channels, fobjects, fsset, fb); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* these both have to be valid, otherwise we wouldn't be here */ | |||||
| fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim); | fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim); | ||||
| domainSettings = fluidmd->fss; | domainSettings = fluidmd->fss; | ||||
| mesh = fsDomain->data; | mesh = fsDomain->data; | ||||
| domainSettings->bakeStart = 1; | domainSettings->bakeStart = 1; | ||||
| domainSettings->bakeEnd = scene->r.efra; | domainSettings->bakeEnd = scene->r.efra; | ||||
| // calculate bounding box | |||||
| fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize); | fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize); | ||||
| // reset last valid frame | |||||
| domainSettings->lastgoodframe = -1; | domainSettings->lastgoodframe = -1; | ||||
| /* delete old baked files */ | /* delete old baked files */ | ||||
| fluidsim_delete_until_lastframe(domainSettings, relbase); | fluidsim_delete_until_lastframe(domainSettings, relbase); | ||||
| /* rough check of settings... */ | |||||
| if (domainSettings->previewresxyz > domainSettings->resolutionxyz) { | if (domainSettings->previewresxyz > domainSettings->resolutionxyz) { | ||||
| BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz, domainSettings->resolutionxyz); | BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz, domainSettings->resolutionxyz); | ||||
| elbeemDebugOut(debugStrBuffer); | elbeemDebugOut(debugStrBuffer); | ||||
| domainSettings->previewresxyz = domainSettings->resolutionxyz; | domainSettings->previewresxyz = domainSettings->resolutionxyz; | ||||
| } | } | ||||
| // set adaptive coarsening according to resolutionxyz | // set adaptive coarsening according to resolutionxyz | ||||
| // this should do as an approximation, with in/outflow | // this should do as an approximation, with in/outflow | ||||
| // doing this more accurate would be overkill | // doing this more accurate would be overkill | ||||
| Show All 12 Lines | static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, short do_job) | ||||
| else { | else { | ||||
| gridlevels = domainSettings->maxRefine; | gridlevels = domainSettings->maxRefine; | ||||
| } | } | ||||
| BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name, gridlevels); | BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name, gridlevels); | ||||
| elbeemDebugOut(debugStrBuffer); | elbeemDebugOut(debugStrBuffer); | ||||
| /* ******** prepare output file paths ******** */ | |||||
| if (!fluid_init_filepaths(bmain, reports, domainSettings, fsDomain, targetDir, targetFile)) { | if (!fluid_init_filepaths(bmain, reports, domainSettings, fsDomain, targetDir, targetFile)) { | ||||
| fluidbake_free_data(channels, fobjects, fsset, fb); | fluidbake_free_data(channels, fobjects, fsset, fb); | ||||
| return false; | return false; | ||||
| } | } | ||||
| channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra) | channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra) | ||||
| channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames; | channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames; | ||||
| /* ******** initialize and allocate animation channels ******** */ | |||||
| fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects); | fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects); | ||||
| /* reset to original current frame */ | /* reset to original current frame */ | ||||
| scene->r.cfra = origFrame; | scene->r.cfra = origFrame; | ||||
| ED_update_for_newframe(CTX_data_main(C), scene, 1); | ED_update_for_newframe(CTX_data_main(C), scene, 1); | ||||
| /* ******** init domain object's matrix ******** */ | |||||
| copy_m4_m4(domainMat, fsDomain->obmat); | copy_m4_m4(domainMat, fsDomain->obmat); | ||||
| if (!invert_m4_m4(invDomMat, domainMat)) { | if (!invert_m4_m4(invDomMat, domainMat)) { | ||||
| BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::error - Invalid obj matrix?\n"); | BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::error - Invalid obj matrix?\n"); | ||||
| elbeemDebugOut(debugStrBuffer); | elbeemDebugOut(debugStrBuffer); | ||||
| BKE_report(reports, RPT_ERROR, "Invalid object matrix"); | BKE_report(reports, RPT_ERROR, "Invalid object matrix"); | ||||
| fluidbake_free_data(channels, fobjects, fsset, fb); | fluidbake_free_data(channels, fobjects, fsset, fb); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* ******** start writing / exporting ******** */ | /* ******** start writing / exporting ******** */ | ||||
| // use .tmp, don't overwrite/delete original file | // use .tmp, don't overwrite/delete original file | ||||
| BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp); | BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp); | ||||
| /* ******** export domain to elbeem ******** */ | /* ******** export domain to elbeem ******** */ | ||||
| elbeemResetSettings(fsset); | elbeemResetSettings(fsset); | ||||
| fsset->version = 1; | fsset->version = 1; | ||||
| fsset->threads = (domainSettings->threads == 0) ? BKE_scene_num_threads(scene) : domainSettings->threads; | fsset->threads = (domainSettings->threads == 0) ? BKE_scene_num_threads(scene) : domainSettings->threads; | ||||
| // setup global settings | // setup global settings | ||||
| copy_v3_v3(fsset->geoStart, domainSettings->bbStart); | copy_v3_v3(fsset->geoStart, domainSettings->bbStart); | ||||
| copy_v3_v3(fsset->geoSize, domainSettings->bbSize); | copy_v3_v3(fsset->geoSize, domainSettings->bbSize); | ||||
| // simulate with 50^3 | |||||
| fsset->resolutionxyz = (int)domainSettings->resolutionxyz; | fsset->resolutionxyz = (int)domainSettings->resolutionxyz; | ||||
| fsset->previewresxyz = (int)domainSettings->previewresxyz; | fsset->previewresxyz = (int)domainSettings->previewresxyz; | ||||
| fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings); | fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings); | ||||
| fsset->viscosity = get_fluid_viscosity(domainSettings); | fsset->viscosity = get_fluid_viscosity(domainSettings); | ||||
| get_fluid_gravity(fsset->gravity, scene, domainSettings); | get_fluid_gravity(fsset->gravity, scene, domainSettings); | ||||
| // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz | // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | for (j=0; j<4; j++) { | ||||
| fsset->surfaceTrafo[i*4+j] = invDomMat[j][i]; | fsset->surfaceTrafo[i*4+j] = invDomMat[j][i]; | ||||
| } | } | ||||
| } } | } } | ||||
| /* ******** init solver with settings ******** */ | /* ******** init solver with settings ******** */ | ||||
| elbeemInit(); | elbeemInit(); | ||||
| elbeemAddDomain(fsset); | elbeemAddDomain(fsset); | ||||
| /* ******** export all fluid objects to elbeem ******** */ | |||||
| export_fluid_objects(fobjects, scene, channels->length); | export_fluid_objects(fobjects, scene, channels->length); | ||||
| /* custom data for fluid bake job */ | |||||
| fb->settings = fsset; | fb->settings = fsset; | ||||
| if (do_job) { | if (do_job) { | ||||
| wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation", | wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation", | ||||
| WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_FLUID); | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_FLUID); | ||||
| /* setup job */ | /* setup job */ | ||||
| WM_jobs_customdata_set(wm_job, fb, fluidbake_free); | WM_jobs_customdata_set(wm_job, fb, fluidbake_free); | ||||
| ▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
| void FLUID_OT_bake(wmOperatorType *ot) | void FLUID_OT_bake(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "Fluid Simulation Bake"; | ot->name = "Fluid Simulation Bake"; | ||||
| ot->description = "Bake fluid simulation"; | ot->description = "Bake fluid simulation"; | ||||
| ot->idname = "FLUID_OT_bake"; | ot->idname = "FLUID_OT_bake"; | ||||
| /* api callbacks */ | |||||
| ot->invoke = fluid_bake_invoke; | ot->invoke = fluid_bake_invoke; | ||||
| ot->exec = fluid_bake_exec; | ot->exec = fluid_bake_exec; | ||||
| ot->poll = ED_operator_object_active_editable; | ot->poll = ED_operator_object_active_editable; | ||||
| } | } | ||||