diff options
Diffstat (limited to 'source/blender/editors/object/object_modifier.c')
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 415 |
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", ""); +} |