Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/object/object_modifier.c')
-rw-r--r--source/blender/editors/object/object_modifier.c415
1 files changed, 415 insertions, 0 deletions
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index ce9693793a4..eb751aabba8 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -42,8 +42,10 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_force.h"
#include "DNA_scene_types.h"
+#include "DNA_smoke_types.h"
#include "BLI_bitmap.h"
+#include "BLI_fileops.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -72,6 +74,9 @@
#include "BKE_ocean.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_screen.h"
+#include "BKE_smoke.h"
#include "BKE_softbody.h"
#include "BKE_editmesh.h"
@@ -89,6 +94,10 @@
#include "object_intern.h"
+#ifdef WITH_OPENVDB
+# include "openvdb_capi.h"
+#endif
+
static void modifier_skin_customdata_delete(struct Object *ob);
/******************************** API ****************************/
@@ -2295,3 +2304,409 @@ void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
+
+/************************ OpenVDB smoke convertor operator *********************/
+
+static int openvdb_cache_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ SmokeModifierData *smd = NULL;
+
+ if (!ob) {
+ return false;
+ }
+
+ smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+
+ if (!smd) {
+ return false;
+ }
+
+ return true;
+}
+
+typedef struct SmokeExportJob {
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+ float *progress;
+ struct SmokeModifierData *smd;
+ struct Scene *scene;
+ struct Object *ob;
+ struct DerivedMesh *dm;
+} SmokeExportJob;
+
+static void smoke_export_free(void *customdata)
+{
+ SmokeExportJob *sej = customdata;
+ MEM_freeN(sej);
+}
+
+/* called by smoke export, only to check job 'stop' value */
+static int smoke_export_breakjob(void *customdata)
+{
+ UNUSED_VARS(customdata);
+ return G.is_break;
+}
+
+/* called by smokeModifier_OpenVDB_export, wmJob sends notifier */
+static void smoke_export_update(void *customdata, float progress, int *cancel)
+{
+ SmokeExportJob *sej = customdata;
+
+ if (smoke_export_breakjob(sej)) {
+ *cancel = 1;
+ }
+
+ *(sej->do_update) = true;
+ *(sej->progress) = progress;
+}
+
+static void smoke_export_startjob(void *customdata, short *stop, short *do_update, float *progress)
+{
+ SmokeExportJob *sej = customdata;
+
+ sej->stop = stop;
+ sej->do_update = do_update;
+ sej->progress = progress;
+
+ G.is_break = false;
+
+ /* XXX annoying hack: needed to prevent data corruption when changing
+ * scene frame in separate threads
+ */
+ G.is_rendering = true;
+ BKE_spacedata_draw_locks(true);
+
+ smokeModifier_OpenVDB_export(sej->smd, sej->scene, sej->ob, sej->dm,
+ smoke_export_update, (void *)sej);
+
+ *do_update = true;
+ *stop = 0;
+}
+
+static void smoke_export_endjob(void *customdata)
+{
+ SmokeExportJob *sej = customdata;
+ Object *ob = sej->ob;
+
+ G.is_rendering = false;
+ BKE_spacedata_draw_locks(false);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
+}
+
+static int smoke_vdb_export_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+ Scene *scene = CTX_data_scene(C);
+ wmJob *wm_job;
+ SmokeExportJob *sej;
+
+ if (!smd) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* setup job */
+ wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "OpenVDB Export",
+ WM_JOB_PROGRESS, WM_JOB_TYPE_SMOKE_EXPORT);
+
+ sej = MEM_callocN(sizeof(SmokeExportJob), "smoke export job");
+ sej->smd = smd;
+ sej->scene = scene;
+ sej->ob = ob;
+ sej->dm = ob->derivedDeform;
+
+ WM_jobs_customdata_set(wm_job, sej, smoke_export_free);
+ WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
+ WM_jobs_callbacks(wm_job, smoke_export_startjob, NULL, NULL, smoke_export_endjob);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+
+ return OPERATOR_FINISHED;
+
+ UNUSED_VARS(op);
+}
+
+static int smoke_vdb_export_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+ SmokeDomainSettings *sds = smd->domain;
+ OpenVDBCache *cache = BKE_openvdb_get_current_cache(sds);
+ const char *relbase = modifier_path_relbase(ob);
+ char filename[FILE_MAX];
+
+ if (!cache)
+ return OPERATOR_CANCELLED;
+
+ BKE_openvdb_cache_filename(filename, cache->path, cache->name, relbase, cache->startframe);
+
+ if (BLI_exists(filename)) {
+ if (BLI_is_file(filename)) {
+ if (BLI_file_is_writable(filename)) {
+ return WM_operator_confirm_message(C, op, "Cache target already exists! Overwrite?");
+ }
+ else {
+ BKE_reportf(op->reports, RPT_ERROR, "Cannot overwrite cache target: %200s", filename);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ BKE_reportf(op->reports, RPT_ERROR, "Invalid cache target: %200s", filename);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ return smoke_vdb_export_exec(C, op);
+ }
+
+ UNUSED_VARS(event);
+}
+
+void OBJECT_OT_smoke_vdb_export(wmOperatorType *ot)
+{
+ ot->name = "Export to OpenVDB";
+ ot->description = "Export simulation to the OpenVDB representation";
+ ot->idname = "OBJECT_OT_smoke_vdb_export";
+
+ ot->invoke = smoke_vdb_export_invoke;
+ ot->poll = openvdb_cache_poll;
+ ot->exec = smoke_vdb_export_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+static void smoke_transform_startjob(void *customdata, short *stop, short *do_update, float *progress)
+{
+ SmokeExportJob *sej = customdata;
+
+ sej->stop = stop;
+ sej->do_update = do_update;
+ sej->progress = progress;
+
+ G.is_break = false;
+
+ smokeModifier_OpenVDB_update_transform(sej->smd, sej->scene, sej->ob,
+ smoke_export_update, (void *)sej);
+
+ *do_update = true;
+ *stop = 0;
+}
+
+static int smoke_transform_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+ Scene *scene = CTX_data_scene(C);
+ wmJob *wm_job;
+ SmokeExportJob *sej;
+
+ if (!smd) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* setup job */
+ wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "OpenVDB Export",
+ WM_JOB_PROGRESS, WM_JOB_TYPE_SMOKE_EXPORT);
+
+ sej = MEM_callocN(sizeof(SmokeExportJob), "smoke export job");
+ sej->smd = smd;
+ sej->scene = scene;
+ sej->ob = ob;
+ sej->dm = ob->derivedDeform;
+
+ WM_jobs_customdata_set(wm_job, sej, smoke_export_free);
+ WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
+ WM_jobs_callbacks(wm_job, smoke_transform_startjob, NULL, NULL, smoke_export_endjob);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+
+ return OPERATOR_FINISHED;
+
+ UNUSED_VARS(op);
+}
+
+void OBJECT_OT_smoke_vdb_transform_update(wmOperatorType *ot)
+{
+ ot->name = "Update Transformation";
+ ot->description = "Update transformation matrices for all grids in every file for this cache";
+ ot->idname = "OBJECT_OT_smoke_vdb_transform_update";
+
+ ot->poll = openvdb_cache_poll;
+ ot->exec = smoke_transform_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/* ************************* OpenVDB cache operators ************************* */
+
+static OpenVDBCache *openvdb_cache_new(void)
+{
+ OpenVDBCache *cache = NULL;
+
+ cache = MEM_callocN(sizeof(OpenVDBCache), "OpenVDBCache");
+ cache->reader = NULL;
+ cache->writer = NULL;
+ cache->startframe = 1;
+ cache->endframe = 250;
+ cache->compression = VDB_COMPRESSION_ZIP;
+
+ BLI_strncpy(cache->name, "openvdb_smoke_export", sizeof(cache->name));
+
+ return cache;
+}
+
+static int openvdb_cache_add_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+ SmokeDomainSettings *sds = smd->domain;
+ OpenVDBCache *cache, *cache_new;
+
+ if (!smd) {
+ return OPERATOR_CANCELLED;
+ }
+
+ cache = BKE_openvdb_get_current_cache(sds);
+
+ if (cache) {
+ cache->flags &= ~VDB_CACHE_CURRENT;
+ }
+
+ cache_new = openvdb_cache_new();
+ cache_new->flags |= VDB_CACHE_CURRENT;
+
+ BLI_addtail(&sds->vdb_caches, cache_new);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
+
+ return OPERATOR_FINISHED;
+
+ UNUSED_VARS(op);
+}
+
+void OBJECT_OT_openvdb_cache_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add an OpenVDB cache";
+ ot->description = "Add an OpenVDB cache";
+ ot->idname = "OBJECT_OT_openvdb_cache_add";
+
+ /* api callbacks */
+ ot->poll = openvdb_cache_poll;
+ ot->exec = openvdb_cache_add_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int openvdb_cache_remove_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+ SmokeDomainSettings *sds = smd->domain;
+ OpenVDBCache *cache, *cache_prev = NULL, *cache_next = NULL;
+
+ if (!smd) {
+ return OPERATOR_CANCELLED;
+ }
+
+ cache = BKE_openvdb_get_current_cache(sds);
+
+ if (cache) {
+ cache_prev = cache->prev;
+ cache_next = cache->next;
+ BLI_remlink(&sds->vdb_caches, cache);
+ MEM_freeN(cache);
+ }
+
+ if (cache_next) {
+ cache_next->flags |= VDB_CACHE_CURRENT;
+ }
+ else if (cache_prev) {
+ cache_prev->flags |= VDB_CACHE_CURRENT;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
+
+ return OPERATOR_FINISHED;
+
+ UNUSED_VARS(op);
+}
+
+void OBJECT_OT_openvdb_cache_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Cache";
+ ot->description = "Remove the currently selected cache";
+ ot->idname = "OBJECT_OT_openvdb_cache_remove";
+
+ /* api callbacks */
+ ot->poll = openvdb_cache_poll;
+ ot->exec = openvdb_cache_remove_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+enum {
+ VDB_CACHE_MOVE_UP = 0,
+ VDB_CACHE_MOVE_DOWN,
+};
+
+static int openvdb_cache_move_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+ SmokeDomainSettings *sds = smd->domain;
+ OpenVDBCache *cache;
+ int direction = RNA_enum_get(op->ptr, "direction");
+
+ if (!smd) {
+ return OPERATOR_CANCELLED;
+ }
+
+ cache = BKE_openvdb_get_current_cache(sds);
+
+ if (direction == VDB_CACHE_MOVE_UP) {
+ if (cache->prev) {
+ BLI_remlink(&sds->vdb_caches, cache);
+ BLI_insertlinkbefore(&sds->vdb_caches, cache->prev, cache);
+ }
+ }
+ else if (direction == VDB_CACHE_MOVE_DOWN) {
+ if (cache->next) {
+ BLI_remlink(&sds->vdb_caches, cache);
+ BLI_insertlinkafter(&sds->vdb_caches, cache->next, cache);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_openvdb_cache_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem cache_move[] = {
+ {VDB_CACHE_MOVE_UP, "UP", 0, "Up", ""},
+ {VDB_CACHE_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ ot->name = "Move Cache";
+ ot->description = "Move cache up or down the list";
+ ot->idname = "OBJECT_OT_openvdb_cache_move";
+
+ ot->poll = openvdb_cache_poll;
+ ot->exec = openvdb_cache_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->prop = RNA_def_enum(ot->srna, "direction", cache_move, VDB_CACHE_MOVE_UP, "Direction", "");
+}