static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects) { Scene *scene = CTX_data_scene(C); Base *base; int i; int length = channels->length; float eval_time; /* init time values (assuming that time moves at a constant speed; may be overridden later) */ init_time(domainSettings, channels); /* allocate domain animation channels */ 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->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime"); /* allocate fluid objects */ for (base=scene->base.first; base; base= base->next) { Object *ob = base->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); if (fluidmd) { FluidObject *fobj = MEM_callocN(sizeof(FluidObject), "Fluid Object"); fobj->object = ob; if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) { BLI_addtail(fobjects, fobj); continue; } fobj->Translation = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Translation"); fobj->Rotation = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Rotation"); fobj->Scale = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Scale"); fobj->Active = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject Active"); fobj->InitialVelocity = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject InitialVelocity"); if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) { fobj->AttractforceStrength = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceStrength"); fobj->AttractforceRadius = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceRadius"); fobj->VelocityforceStrength = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceStrength"); fobj->VelocityforceRadius = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceRadius"); } if (fluid_is_animated_mesh(fluidmd->fss)) { float *verts=NULL; int *tris=NULL, modifierIndex = BLI_findindex(&ob->modifiers, (ModifierData *)fluidmd); initElbeemMesh(scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex); fobj->VertexCache = MEM_callocN(length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache"); MEM_freeN(verts); MEM_freeN(tris); } BLI_addtail(fobjects, fobj); } } /* now we loop over the frames and fill the allocated channels with data */ for (i=0; i < channels->length; i++) { FluidObject *fobj; float viscosity, gravity[3]; float timeAtFrame, time; 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... :/ ) * --> BKE_animsys_evaluate_all_animation(G.main, eval_time); * This doesn't work with drivers: * --> 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 */ scene->r.cfra = (int)eval_time; 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 */ /* Domain time */ // TODO: have option for not running sim, time mangling, in which case second case comes in handy if (channels->DomainTime) { time = get_fluid_rate(domainSettings) * (float)channels->aniFrameTime; timeAtFrame = channels->timeAtFrame[i] + time; channels->timeAtFrame[i+1] = timeAtFrame; set_channel(channels->DomainTime, i, &time, i, CHANNEL_FLOAT); } else { timeAtFrame = channels->timeAtFrame[i+1]; } /* Domain properties - gravity/viscosity */ get_fluid_gravity(gravity, scene, domainSettings); set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC); viscosity = get_fluid_viscosity(domainSettings); set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT); /* object movement */ for (fobj=fobjects->first; fobj; fobj=fobj->next) { Object *ob = fobj->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); float active= (float) ((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) > 0 ? 1 : 0); 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)) continue; /* 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) { copy_v3_v3(old_rot, fobj->Rotation + 4*(i-1)); mul_v3_fl(old_rot, (float)-M_PI / 180.f); } mat4_to_compatible_eulO(rot_d, old_rot, 0, ob->obmat); mul_v3_fl(rot_d, -180.0f / (float)M_PI); set_channel(fobj->Translation, timeAtFrame, ob->loc, i, CHANNEL_VEC); set_channel(fobj->Rotation, timeAtFrame, rot_d, i, CHANNEL_VEC); set_channel(fobj->Scale, timeAtFrame, ob->size, i, CHANNEL_VEC); set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT); set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC); // printf("Active: %f, Frame: %f\n", active, timeAtFrame); if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) { set_channel(fobj->AttractforceStrength, timeAtFrame, &fluidmd->fss->attractforceStrength, i, CHANNEL_FLOAT); set_channel(fobj->AttractforceRadius, timeAtFrame, &fluidmd->fss->attractforceRadius, i, CHANNEL_FLOAT); set_channel(fobj->VelocityforceStrength, timeAtFrame, &fluidmd->fss->velocityforceStrength, i, CHANNEL_FLOAT); set_channel(fobj->VelocityforceRadius, timeAtFrame, &fluidmd->fss->velocityforceRadius, i, CHANNEL_FLOAT); } if (fluid_is_animated_mesh(fluidmd->fss)) { set_vertex_channel(fobj->VertexCache, timeAtFrame, scene, fobj, i); } } } }
static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length) { FluidObject *fobj; for (fobj=fobjects->first; fobj; fobj=fobj->next) { Object *ob = fobj->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd); float *verts=NULL; int *tris=NULL; int numVerts=0, numTris=0; bool deform = fluid_is_animated_mesh(fluidmd->fss); elbeemMesh fsmesh; if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) continue; elbeemResetMesh(&fsmesh); fsmesh.type = fluidmd->fss->type; fsmesh.name = ob->id.name; initElbeemMesh(scene, ob, &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 = length; fsmesh.channelTranslation = fobj->Translation; fsmesh.channelRotation = fobj->Rotation; fsmesh.channelScale = fobj->Scale; fsmesh.channelActive = fobj->Active; if ( ELEM(fsmesh.type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) { fsmesh.channelInitialVel = fobj->InitialVelocity; fsmesh.localInivelCoords = ((fluidmd->fss->typeFlags & OB_FSINFLOW_LOCALCOORD) ? 1 : 0); } if (fluidmd->fss->typeFlags & OB_FSBND_NOSLIP) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; else if (fluidmd->fss->typeFlags & OB_FSBND_PARTSLIP) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP; else if (fluidmd->fss->typeFlags & OB_FSBND_FREESLIP) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP; fsmesh.obstaclePartslip = fluidmd->fss->partSlipValue; fsmesh.volumeInitType = fluidmd->fss->volumeInitType; fsmesh.obstacleImpactFactor = fluidmd->fss->surfaceSmoothing; // misused value if (fsmesh.type == OB_FLUIDSIM_CONTROL) { fsmesh.cpsTimeStart = fluidmd->fss->cpsTimeStart; fsmesh.cpsTimeEnd = fluidmd->fss->cpsTimeEnd; fsmesh.cpsQuality = fluidmd->fss->cpsQuality; fsmesh.obstacleType = (fluidmd->fss->flag & OB_FLUIDSIM_REVERSE); fsmesh.channelSizeAttractforceRadius = fsmesh.channelSizeVelocityforceStrength = fsmesh.channelSizeVelocityforceRadius = fsmesh.channelSizeAttractforceStrength = length; fsmesh.channelAttractforceStrength = fobj->AttractforceStrength; fsmesh.channelAttractforceRadius = fobj->AttractforceRadius; fsmesh.channelVelocityforceStrength = fobj->VelocityforceStrength; fsmesh.channelVelocityforceRadius = fobj->VelocityforceRadius; } else { fsmesh.channelAttractforceStrength = fsmesh.channelAttractforceRadius = fsmesh.channelVelocityforceStrength = fsmesh.channelVelocityforceRadius = NULL; } /* animated meshes */ if (deform) { fsmesh.channelSizeVertices = length; fsmesh.channelVertices = fobj->VertexCache; /* remove channels */ fsmesh.channelTranslation = fsmesh.channelRotation = fsmesh.channelScale = NULL; /* Override user settings, only noslip is supported here! */ if (fsmesh.type != OB_FLUIDSIM_CONTROL) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; } elbeemAddMesh(&fsmesh); if (verts) MEM_freeN(verts); if (tris) MEM_freeN(tris); } }
static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects) { Scene *scene = CTX_data_scene(C); Base *base; int i; int length = channels->length; float eval_time; /* XXX: first init time channel - temporary for now */ /* init time values (should be done after evaluating animated time curve) */ init_time(domainSettings, channels); /* allocate domain animation channels */ 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->DomainTime = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime"); /* allocate fluid objects */ for (base=scene->base.first; base; base= base->next) { Object *ob = base->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); if (fluidmd) { FluidObject *fobj = MEM_callocN(sizeof(FluidObject), "Fluid Object"); fobj->object = ob; if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) { BLI_addtail(fobjects, fobj); continue; } fobj->Translation = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Translation"); fobj->Rotation = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Rotation"); fobj->Scale = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Scale"); fobj->Active = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject Active"); fobj->InitialVelocity = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject InitialVelocity"); if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) { fobj->AttractforceStrength = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceStrength"); fobj->AttractforceRadius = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceRadius"); fobj->VelocityforceStrength = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceStrength"); fobj->VelocityforceRadius = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceRadius"); } if (fluid_is_animated_mesh(fluidmd->fss)) { float *verts=NULL; int *tris=NULL, modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd); initElbeemMesh(scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex); fobj->VertexCache = MEM_callocN( length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache"); MEM_freeN(verts); MEM_freeN(tris); } BLI_addtail(fobjects, fobj); } } /* now we loop over the frames and fill the allocated channels with data */ for (i=0; i<channels->length; i++) { FluidObject *fobj; float viscosity, gravity[3]; float timeAtFrame; eval_time = domainSettings->bakeStart + i; timeAtFrame = channels->timeAtFrame[i+1]; /* XXX: This can't be used due to an anim sys optimisation that ignores recalc object animation, * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ ) * --> BKE_animsys_evaluate_all_animation(G.main, eval_time); * This doesn't work with drivers: * --> 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 */ scene->r.cfra = (int)eval_time; ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1); /* now scene data should be current according to animation system, so we fill the channels */ /* Domain properties - gravity/viscosity/time */ get_fluid_gravity(gravity, scene, domainSettings); set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC); viscosity = get_fluid_viscosity(domainSettings); set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT); // XXX : set_channel(channels->DomainTime, timeAtFrame, &time, i, CHANNEL_VEC); /* object movement */ for (fobj=fobjects->first; fobj; fobj=fobj->next) { Object *ob = fobj->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); float active= (float)(fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE); float rot_d[3], rot_360[3] = {360.f, 360.f, 360.f}; if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) continue; /* init euler rotation values and convert to elbeem format */ BKE_rotMode_change_values(ob->quat, ob->rot, ob->rotAxis, &ob->rotAngle, ob->rotmode, ROT_MODE_EUL); mul_v3_v3fl(rot_d, ob->rot, 180.f/M_PI); sub_v3_v3v3(rot_d, rot_360, rot_d); set_channel(fobj->Translation, timeAtFrame, ob->loc, i, CHANNEL_VEC); set_channel(fobj->Rotation, timeAtFrame, rot_d, i, CHANNEL_VEC); set_channel(fobj->Scale, timeAtFrame, ob->size, i, CHANNEL_VEC); set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT); set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC); if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) { set_channel(fobj->AttractforceStrength, timeAtFrame, &fluidmd->fss->attractforceStrength, i, CHANNEL_FLOAT); set_channel(fobj->AttractforceRadius, timeAtFrame, &fluidmd->fss->attractforceRadius, i, CHANNEL_FLOAT); set_channel(fobj->VelocityforceStrength, timeAtFrame, &fluidmd->fss->velocityforceStrength, i, CHANNEL_FLOAT); set_channel(fobj->VelocityforceRadius, timeAtFrame, &fluidmd->fss->velocityforceRadius, i, CHANNEL_FLOAT); } if (fluid_is_animated_mesh(fluidmd->fss)) { set_vertex_channel(fobj->VertexCache, timeAtFrame, scene, fobj, i); } } } }