[Bf-blender-cvs] [cf7b4e3] alembic: Baking API for cache modifiers.

Lukas Tönne noreply at git.blender.org
Sun Mar 29 18:26:39 CEST 2015


Commit: cf7b4e30545c733b44f479de29c9c32a0576bc89
Author: Lukas Tönne
Date:   Sun Mar 29 18:23:11 2015 +0200
Branches: alembic
https://developer.blender.org/rBcf7b4e30545c733b44f479de29c9c32a0576bc89

Baking API for cache modifiers.

Cache baking means the cache modifier should read input caches over the
given frame range and produce the correct output for writing into the
output cache file.

Cache modifiers can optionally implement a 'bake' function. This is used
through a bake operator from the cache modifier panel. Baking is
executed in a job, which will help with cancelling bakes and displaying
status info.

===================================================================

M	release/scripts/startup/bl_ui/properties_object.py
M	source/blender/blenkernel/BKE_cache_library.h
M	source/blender/blenkernel/intern/cache_library.c
M	source/blender/editors/io/io_cache_library.c
M	source/blender/editors/io/io_cache_library.h
M	source/blender/editors/io/io_ops.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index b0a33b5..70fa8f2 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -327,13 +327,16 @@ class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
     bl_label = "Duplication"
 
     def draw_cache_modifier(self, context, layout, cachelib, md):
+        layout.context_pointer_set("cache_modifier", md)
+
         row = layout.row(align=True)
         row.context_pointer_set("cache_modifier", md)
         row.prop(md, "name", text="")
         row.operator("cachelibrary.remove_modifier", icon='X', text="", emboss=False)
 
-        row = layout.row()
-        row.prop(md, "filepath")
+        col = layout.column(align=True)
+        col.prop(md, "filepath")
+        col.operator("cachelibrary.modifier_bake", text="Bake")
 
         # match enum type to our functions, avoids a lookup table.
         getattr(self, md.type)(layout, cachelib, md)
diff --git a/source/blender/blenkernel/BKE_cache_library.h b/source/blender/blenkernel/BKE_cache_library.h
index 32484fc..61ec8ac 100644
--- a/source/blender/blenkernel/BKE_cache_library.h
+++ b/source/blender/blenkernel/BKE_cache_library.h
@@ -36,6 +36,7 @@
 
 struct ListBase;
 struct Main;
+struct bContext;
 struct Object;
 struct Scene;
 struct EvaluationContext;
@@ -112,11 +113,25 @@ bool BKE_cache_read_dupli_object(struct Scene *scene, float frame, eCacheLibrary
 
 typedef void (*CacheModifier_IDWalkFunc)(void *userdata, struct CacheLibrary *cachelib, struct CacheModifier *md, struct ID **id_ptr);
 
+typedef struct CacheBakeContext {
+	struct CacheLibrary *cachelib;
+	struct CacheModifier *md;
+	
+	struct Main *bmain;
+	struct Scene *scene;
+	int startframe, endframe;
+	
+	short *stop;
+	short *do_update;
+	float *progress;
+} CacheBakeContext;
+
 typedef void (*CacheModifier_InitFunc)(struct CacheModifier *md);
 typedef void (*CacheModifier_FreeFunc)(struct CacheModifier *md);
 typedef void (*CacheModifier_CopyFunc)(struct CacheModifier *md, struct CacheModifier *target);
 typedef void (*CacheModifier_ForeachIDLinkFunc)(struct CacheModifier *md, struct CacheLibrary *cachelib,
                                                 CacheModifier_IDWalkFunc walk, void *userData);
+typedef void (*CacheModifier_BakeFunc)(struct CacheModifier *md, struct CacheLibrary *cachelib, CacheBakeContext *ctx);
 
 typedef struct CacheModifierTypeInfo {
 	/* The user visible name for this modifier */
@@ -146,6 +161,9 @@ typedef struct CacheModifierTypeInfo {
 	 */
 	CacheModifier_ForeachIDLinkFunc foreachIDLink;
 
+	/* Process data and write results to the modifier's output archive */
+	CacheModifier_BakeFunc bake;
+
 	/********************* Optional functions *********************/
 
 	/* Initialize new instance data for this modifier type, this function
@@ -177,4 +195,6 @@ struct CacheModifier *BKE_cache_modifier_copy(struct CacheLibrary *cachelib, str
 
 void BKE_cache_modifier_foreachIDLink(struct CacheLibrary *cachelib, struct CacheModifier *md, CacheModifier_IDWalkFunc walk, void *userdata);
 
+void BKE_cache_modifier_bake(const struct bContext *C, struct CacheLibrary *cachelib, struct CacheModifier *md, struct Scene *scene, int startframe, int endframe);
+
 #endif
diff --git a/source/blender/blenkernel/intern/cache_library.c b/source/blender/blenkernel/intern/cache_library.c
index fc078cd..705862f 100644
--- a/source/blender/blenkernel/intern/cache_library.c
+++ b/source/blender/blenkernel/intern/cache_library.c
@@ -48,6 +48,7 @@
 
 #include "BKE_anim.h"
 #include "BKE_cache_library.h"
+#include "BKE_context.h"
 #include "BKE_depsgraph.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_global.h"
@@ -55,11 +56,16 @@
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_modifier.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
 
 #include "BLF_translation.h"
 
 #include "PTC_api.h"
 
+#include "WM_api.h"
+#include "WM_types.h"
+
 CacheLibrary *BKE_cache_library_add(Main *bmain, const char *name)
 {
 	CacheLibrary *cachelib;
@@ -827,6 +833,7 @@ CacheModifier *BKE_cache_modifier_add(CacheLibrary *cachelib, const char *name,
 	CacheModifierTypeInfo *mti = cache_modifier_type_get(type);
 	
 	CacheModifier *md = MEM_callocN(mti->struct_size, "cache modifier");
+	md->type = type;
 	
 	if (!name)
 		name = mti->name;
@@ -890,25 +897,103 @@ void BKE_cache_modifier_foreachIDLink(struct CacheLibrary *cachelib, struct Cach
 	
 	if (mti->foreachIDLink)
 		mti->foreachIDLink(md, cachelib, walk, userdata);
+}
+
+/* Warning! Deletes existing files if possible, operator should show confirm dialog! */
+static bool cache_modifier_bake_ensure_file_target(const char *filepath, ID *id)
+{
+	char filename[FILE_MAX];
 	
+	BKE_cache_archive_path(filepath, id, id->lib, filename, sizeof(filename));
 	
+	if (BLI_exists(filename)) {
+		if (BLI_is_dir(filename)) {
+			return false;
+		}
+		else if (BLI_is_file(filename)) {
+			if (BLI_file_is_writable(filename)) {
+				/* returns 0 on success */
+				return (BLI_delete(filename, false, false) == 0);
+			}
+			else {
+				return false;
+			}
+		}
+		else {
+			return false;
+		}
+	}
+	return true;
 }
 
-/* ------------------------------------------------------------------------- */
+static void cache_modifier_bake_freejob(void *customdata)
+{
+	CacheBakeContext *ctx = (CacheBakeContext *)customdata;
+	MEM_freeN(ctx);
+}
 
-#if 0
-void BKE_cache_modifier_type_init(CacheModifierTypeInfo *mti, const char *name, const char *struct_name, int struct_size,
-                                  CacheModifier_InitFunc init, CacheModifier_FreeFunc free, CacheModifier_CopyFunc copy)
+static void cache_modifier_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
+{
+	CacheBakeContext *ctx = (CacheBakeContext *)customdata;
+	CacheModifierTypeInfo *mti = cache_modifier_type_get(ctx->md->type);
+	
+	ctx->stop = stop;
+	ctx->do_update = do_update;
+	ctx->progress = progress;
+	
+	if (mti->bake)
+		mti->bake(ctx->md, ctx->cachelib, ctx);
+	
+	*do_update = true;
+	*stop = 0;
+}
+
+static void cache_modifier_bake_endjob(void *UNUSED(customdata))
 {
-	mti->name = name;
-	mti->struct_name = struct_name;
-	mti->struct_size = struct_size;
+	/*CacheBakeContext *ctx = (CacheBakeContext *)customdata;*/
 	
-	mti->initData = init;
-	mti->freeData = free;
-	mti->copy_data = copy;
+	G.is_rendering = false;
+	BKE_spacedata_draw_locks(false);
 }
-#endif
+
+void BKE_cache_modifier_bake(const bContext *C, CacheLibrary *cachelib, CacheModifier *md, Scene *scene, int startframe, int endframe)
+{
+	CacheBakeContext *ctx;
+	wmJob *wm_job;
+	
+	/* make sure we can write */
+	cache_modifier_bake_ensure_file_target(md->filepath, &cachelib->id);
+	
+	/* XXX annoying hack: needed to prevent data corruption when changing
+		 * scene frame in separate threads
+		 */
+	G.is_rendering = true;
+	
+	BKE_spacedata_draw_locks(true);
+	
+	/* XXX set WM_JOB_EXCL_RENDER to prevent conflicts with render jobs,
+		 * since we need to set G.is_rendering
+		 */
+	wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Cache Modifier Bake",
+	                     WM_JOB_PROGRESS | WM_JOB_EXCL_RENDER, WM_JOB_TYPE_CACHELIBRARY_BAKE);
+	
+	/* setup job */
+	ctx = MEM_callocN(sizeof(CacheBakeContext), "Cache Bake Context");
+	ctx->cachelib = cachelib;
+	ctx->md = md;
+	ctx->bmain = CTX_data_main(C);
+	ctx->scene = scene;
+	ctx->startframe = startframe;
+	ctx->endframe = endframe;
+	
+	WM_jobs_customdata_set(wm_job, ctx, cache_modifier_bake_freejob);
+	WM_jobs_timer(wm_job, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME);
+	WM_jobs_callbacks(wm_job, cache_modifier_bake_startjob, NULL, NULL, cache_modifier_bake_endjob);
+	
+	WM_jobs_start(CTX_wm_manager(C), wm_job);
+}
+
+/* ------------------------------------------------------------------------- */
 
 static void hairsim_init(HairSimCacheModifier *UNUSED(md))
 {
@@ -918,6 +1003,60 @@ static void hairsim_copy(HairSimCacheModifier *UNUSED(md), HairSimCacheModifier
 {
 }
 
+static void hairsim_bake_do(CacheBakeContext *ctx, short *stop, short *do_update, float *progress,
+                            struct PTCWriterArchive *archive, EvaluationContext *eval_ctx)
+{
+	Scene *scene = ctx->scene;
+	struct PTCWriter *writer = NULL;
+	
+	if ((*stop) || (G.is_break))
+		return;
+	
+//	writer = PTC_writer_dupligroup(ctx->group->id.name, &ctx->eval_ctx, scene, ctx->group, ctx->cachelib);
+//	PTC_writer_init(ctx->writer, archive);
+	
+	PTC_bake(ctx->bmain, scene, eval_ctx, writer, ctx->startframe, ctx->endframe, stop, do_update, progress);
+	
+	if (writer) {
+		PTC_writer_free(writer);
+		writer = NULL;
+	}
+}
+
+static void hairsim_bake(HairSimCacheModifier *UNUSED(md), CacheLibrary *cachelib, CacheBakeContext *ctx)
+{
+	Scene *scene = ctx->scene;
+	const int origframe = scene->r.cfra;
+	const float origframelen = scene->r.framelen;
+	
+	struct PTCWriterArchive *archive;
+	char filename[FILE_MAX];
+	EvaluationContext eval_ctx;
+	
+	scene->r.framelen = 1.0f;
+	
+	BKE_cache_archive_path(cachelib->filepath, (ID *)cachelib, cachelib->id.lib, filename, sizeof(filename));
+	archive = PTC_open_writer_archive(scene, filename);
+	
+	if (archive) {
+		
+		G.is_break = false;
+		
+		eval_ctx.mode = DAG_EVAL_VIEWPORT;
+		PTC_writer_archive_use_render(archive, false);
+		hairsim_bake_do(ctx, ctx->stop, ctx->do_update, ctx->progress, archive, &eval_ctx);
+		
+	}
+	
+	if (archive)
+		PTC_close_writer_archive(archive);
+	
+	/* reset scene frame */
+	scene->r.cfra = origframe;
+	scene->r.framelen = origframelen;
+	BKE_scene_update_for_newframe(&eval_ctx, ctx->bmain, scene, scene->lay);
+}
+
 CacheModifierTypeInfo cacheModifierType_HairSimulation = {
     /* name */              "HairSimulation",
     /* structName */        "HairSimCacheModifier",
@@ -925,6 +1064,7 @@ CacheModifierTypeInfo cacheModifierType_HairSimulation = {
 
     /* copy */              (CacheModifier_CopyFunc)hairsim_copy,
     /* foreachIDLink */     (CacheModifier_ForeachIDLinkFunc)NULL,
+    /* bake */              (CacheModifier_BakeFunc)hairsim_bake,
     /* init */              (CacheModifier_InitFunc)hairsim_init,
     /* free */      

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list