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);
	}
}
Exemple #3
0
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);
			}
		}
	}
}