Dev:Source/Physics/Unified Dynamics Baking

提供: wiki
移動先: 案内検索

General ideas

  • adding a dynamic system to an object also adds BakeableSystem entry to a new list of bakeable systems in the object
    • the BakeableSystem struct allows unified handling of all bakeable systems
    • the struct will also store the baking with a DynamicsKey struct that will hold the data points for all systems, possibly with added custom variables
  • all wanted dynamic systems can be baked in a single run through the wanted time span
    • systems can be manually set "to bake" and when baking is started by the user all of these systems are baked
    • systems that need an autobake (atleast particles) are baked if the systems want it when asked after updating recalc flags through the depsgraph..
  • a unified "bake edit mode" will allow editing of all baked dynamics
    • allthough unified, the edit mode may have differing functionality depending on system sype
    • in case of a "bad bake" the bake can be edited at a certain frame and then rebaked starting from that frame and at the same time preserve the bake before that frame
  • editing of object's data and settings of modifiers before the baked system will be locked after the bake
    • this is nescessary since the baked system can't react to changes mesh structure etc..
    • alternatively atleast a warning of "losing bake" should be issued before modifications are allowed
  • baking can be done with non-integer steps
    • all dynamic systems get current time with bsystem_time(...)
    • a new "bakeoffs" variable will be set by the baking system, similar to the "bluroffs" and "fieldoffs" that are currently in use
  • unified baking is controlled from the outliner
    • "bakeable systems" option for the outliner display to display only bakeable systems
    • each system can be separately flagged "to bake"
    • baked systems display info on the bake (memory usage etc.)
    • option to free a system's bake
    • a "BAKE" button and start/end frame settings to begin unified baking
  • baking should also be available from the commandline like Tony Mullen suggested
    • a command line option to start unified baking with set systems
    • save blend after baking is complete

BakeableSystem sructure

typedef struct BakeableSystem{
	Object *ob;
	void *system;
	DynamicsKey **keys;	/* baked keys for each entity */
	int *totkey;		/* array of amount of keys for each entity */
	int totentity;		/* amount of bakeable entities */
	short type, recalc_flag, flag;
	
	/* starting frame of baking */
	float (*start_frame)(Object *ob, void *system);
	
	/* end frame of baking */
	float (*end_frame)(Object *ob, void *system);
	
	/* timestep needed for next step */
	float (*timestep)(Object *ob, void *system);
	
	int (*is_baked)(Object *ob, void *system);
	int (*set_baking)(Object *ob, void *system);
	int (*needs_autobake)(Object *ob, void *system);
	
	/* return system to unbaked state, regardles of wether baking is complete or not */
	void (*free_bake)(Object *ob, void *system);
	/* prepare system to continue baking from cfra */
	void (*set_rebaking)(Object *ob, void *system, float cfra);
	
	/* info on the bake, like size in memory, amount of baked keys etc. */
	char *(*bake_info)(Object *ob, void *system);
	
	/* initializes and sets an editing mode for the baked data */
	void (*set_bake_edit)(Object *ob, void *system);
	/* clear out temporary stuff left by the edit mode etc. */
	void (*end_bake_edit)(Object *ob, void *system);
	
	/* in addition several edit mode calls can be implemented, like mouse button calls, selections etc..*/
} BakeableSystem;

typedef struct DynamicsKey{
	float co[3];
	float vel[3];
	float time;
	/* custom variables needed by some systems */
	float *custom;
} DynamicsKey;

/* BakeableSystem->type */
#define BAKEABLE_PARTICLE	0
#define BAKEABLE_SOFTBODY	1
#define BAKEABLE_CLOTH		2
#define BAKEABLE_FLUID		3
#define BAKEABLE_BULLET		4

Main functions

void get_all_systems_to_bake(ListBase *bakelist)
{
	Object *ob;
	BakeableSystem *bsys;
	
	for(ob in scene){
		for(bsys in ob->bakelist){
			if(bsys.flag & BSYS_TO_BAKE)
				BLI_addtail(bakelist,bsys);
		}
	}
}

void get_all_autobake_systems(ListBase *bakelist)
{
	Object *ob;
	BakeableSystem *bsys;
	
	for(ob in scene){
		for(bsys in ob->bakelist){
			if(bsys.needs_autobake(..))
				BLI_addtail(bakelist,bsys);
		}
	}
}

void unified_bake(ListBase *bakelist, int from_cfra)
{
	BakeableSystem *bsys;
	float start_frame=from_cfra?CFRA:MAXFRAME;
	float end_frame=-MAXFRAME;
	float step=1.0, cfra;
	int old_cfra=CFRA;
	
	if(bakelist==0) return;
	
	for(bsys in bakelist){
		if(from_cfra==0){
			bsys.free_bake(..);
			start_frame=MIN(start_frame,bsys.start_frame(..));
			bsys.ob->recalc |= bsys.recalc_flag;
			bsys.set_baking(..);
		}
		else
			bsys.set_rebaking(..);
			
		end_frame=MAX(end_frame,bsys.end_frame(..));
	}
	
	cfra=start_frame;
	CFRA=(int)cfra;
	set_bake_offs(cfra-(float)CFRA);
	
	DAG_scene_flush_update();
	
	while(cfra<=end_frame){
		for(ob in scene) {
			object_handle_update(ob);
		}
		update ui to show progress
		
		test for escape from baking
		
		for(bsys in bakelist){
			bsys.ob->recalc |= bsys.recalc_flag
			step=MIN(step,bsys.get_timestep(..))
		}
		
		cfra+=step;
		CFRA=(int)cfra;
		set_bake_offs(cfra-(float)CFRA);
	}
	
	for(bsys in bakelist){
		if(bsys.is_baked()==0){
			bsys.free_bake(..)
			bsys.ob->recalc = dyn.recalc_flag
		}
		else
			bsys.flag &= ~BSYS_TO_BAKE;
	}
	
	
	CFRA=old_cfra;
	
	scene_update_for_newframe()
}