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:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2022-03-23 17:33:29 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2022-03-23 17:34:13 +0300
commitd40d5e8d0f56cf5d2838b10007fb3e26b8cf72d4 (patch)
tree165fd00066afe55d1122525ef485fdcebe1a19ea /source/blender/modifiers/intern/MOD_meshsequencecache.cc
parent5ac4e6c911f6c61a33193f0bf796e1ab093a94e7 (diff)
Cleanup: move Mesh Sequence Cache modifier to C++
This moves `MOD_meshsequencecache.c` to C++ and fixes compile warnings introduced from the change. This uses C++ style casts, as well as `nullptr` instead of `NULL`. This will allow to output `GeometrySets` from the modifier, which is C++. Differential Revision: https://developer.blender.org/D13662
Diffstat (limited to 'source/blender/modifiers/intern/MOD_meshsequencecache.cc')
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.cc448
1 files changed, 448 insertions, 0 deletions
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.cc b/source/blender/modifiers/intern/MOD_meshsequencecache.cc
new file mode 100644
index 00000000000..5c895824a01
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.cc
@@ -0,0 +1,448 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup modifiers
+ */
+
+#include <string.h>
+
+#include "BLI_math_vector.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_cachefile_types.h"
+#include "DNA_defaults.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_cachefile.h"
+#include "BKE_context.h"
+#include "BKE_lib_query.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+#include "RNA_prototypes.h"
+
+#include "BLO_read_write.h"
+
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+#include "MOD_modifiertypes.h"
+#include "MOD_ui_common.h"
+
+#if defined(WITH_USD) || defined(WITH_ALEMBIC)
+# include "BKE_global.h"
+# include "BKE_lib_id.h"
+#endif
+
+#ifdef WITH_ALEMBIC
+# include "ABC_alembic.h"
+#endif
+
+#ifdef WITH_USD
+# include "usd.h"
+#endif
+
+static void initData(ModifierData *md)
+{
+ MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
+
+ BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mcmd, modifier));
+
+ mcmd->cache_file = nullptr;
+ mcmd->object_path[0] = '\0';
+ mcmd->read_flag = MOD_MESHSEQ_READ_ALL;
+
+ MEMCPY_STRUCT_AFTER(mcmd, DNA_struct_default_get(MeshSeqCacheModifierData), modifier);
+}
+
+static void copyData(const ModifierData *md, ModifierData *target, const int flag)
+{
+#if 0
+ const MeshSeqCacheModifierData *mcmd = (const MeshSeqCacheModifierData *)md;
+#endif
+ MeshSeqCacheModifierData *tmcmd = (MeshSeqCacheModifierData *)target;
+
+ BKE_modifier_copydata_generic(md, target, flag);
+
+ tmcmd->reader = nullptr;
+ tmcmd->reader_object_path[0] = '\0';
+}
+
+static void freeData(ModifierData *md)
+{
+ MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
+
+ if (mcmd->reader) {
+ mcmd->reader_object_path[0] = '\0';
+ BKE_cachefile_reader_free(mcmd->cache_file, &mcmd->reader);
+ }
+}
+
+static bool isDisabled(const struct Scene *UNUSED(scene),
+ ModifierData *md,
+ bool UNUSED(useRenderParams))
+{
+ MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
+
+ /* leave it up to the modifier to check the file is valid on calculation */
+ return (mcmd->cache_file == nullptr) || (mcmd->object_path[0] == '\0');
+}
+
+static Mesh *generate_bounding_box_mesh(Object *object, Mesh *org_mesh)
+{
+ BoundBox *bb = BKE_object_boundbox_get(object);
+ Mesh *result = BKE_mesh_new_nomain_from_template(org_mesh, 8, 0, 0, 24, 6);
+
+ MVert *mvert = result->mvert;
+ for (int i = 0; i < 8; ++i) {
+ copy_v3_v3(mvert[i].co, bb->vec[i]);
+ }
+
+ /* See DNA_object_types.h for the diagram showing the order of the vertices for a BoundBox. */
+ static unsigned int loops_v[6][4] = {
+ {0, 4, 5, 1},
+ {4, 7, 6, 5},
+ {7, 3, 2, 6},
+ {3, 0, 1, 2},
+ {1, 5, 6, 2},
+ {3, 7, 4, 0},
+ };
+
+ MLoop *mloop = result->mloop;
+ for (int i = 0; i < 6; ++i) {
+ for (int j = 0; j < 4; ++j, ++mloop) {
+ mloop->v = loops_v[i][j];
+ }
+ }
+
+ MPoly *mpoly = result->mpoly;
+ for (int i = 0; i < 6; ++i) {
+ mpoly[i].loopstart = i * 4;
+ mpoly[i].totloop = 4;
+ }
+
+ BKE_mesh_calc_edges(result, false, false);
+
+ return result;
+}
+
+static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
+{
+#if defined(WITH_USD) || defined(WITH_ALEMBIC)
+ MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
+
+ /* Only used to check whether we are operating on org data or not... */
+ Mesh *me = (ctx->object->type == OB_MESH) ? static_cast<Mesh *>(ctx->object->data) : nullptr;
+ Mesh *org_mesh = mesh;
+
+ Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
+ CacheFile *cache_file = mcmd->cache_file;
+ const float frame = DEG_get_ctime(ctx->depsgraph);
+ const float time = BKE_cachefile_time_offset(cache_file, frame, FPS);
+ const char *err_str = nullptr;
+
+ if (!mcmd->reader || !STREQ(mcmd->reader_object_path, mcmd->object_path)) {
+ STRNCPY(mcmd->reader_object_path, mcmd->object_path);
+ BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path);
+ if (!mcmd->reader) {
+ BKE_modifier_set_error(
+ ctx->object, md, "Could not create reader for file %s", cache_file->filepath);
+ return mesh;
+ }
+ }
+
+ /* Do not process data if using a render procedural, return a box instead for displaying in the
+ * viewport. */
+ if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(ctx->depsgraph))) {
+ return generate_bounding_box_mesh(ctx->object, org_mesh);
+ }
+
+ /* If this invocation is for the ORCO mesh, and the mesh hasn't changed topology, we
+ * must return the mesh as-is instead of deforming it. */
+ if (ctx->flag & MOD_APPLY_ORCO) {
+ switch (cache_file->type) {
+ case CACHEFILE_TYPE_ALEMBIC:
+# ifdef WITH_ALEMBIC
+ if (!ABC_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time, &err_str)) {
+ return mesh;
+ }
+# endif
+ break;
+ case CACHEFILE_TYPE_USD:
+# ifdef WITH_USD
+ if (!USD_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time, &err_str)) {
+ return mesh;
+ }
+# endif
+ break;
+ case CACHE_FILE_TYPE_INVALID:
+ break;
+ }
+ }
+
+ if (me != nullptr) {
+ MVert *mvert = mesh->mvert;
+ MEdge *medge = mesh->medge;
+ MPoly *mpoly = mesh->mpoly;
+
+ /* TODO(sybren+bastien): possibly check relevant custom data layers (UV/color depending on
+ * flags) and duplicate those too. */
+ if ((me->mvert == mvert) || (me->medge == medge) || (me->mpoly == mpoly)) {
+ /* We need to duplicate data here, otherwise we'll modify org mesh, see T51701. */
+ mesh = reinterpret_cast<Mesh *>(
+ BKE_id_copy_ex(nullptr,
+ &mesh->id,
+ nullptr,
+ LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW));
+ }
+ }
+
+ Mesh *result = nullptr;
+
+ switch (cache_file->type) {
+ case CACHEFILE_TYPE_ALEMBIC: {
+# ifdef WITH_ALEMBIC
+ /* Time (in frames or seconds) between two velocity samples. Automatically computed to
+ * scale the velocity vectors at render time for generating proper motion blur data. */
+ float velocity_scale = mcmd->velocity_scale;
+ if (mcmd->cache_file->velocity_unit == CACHEFILE_VELOCITY_UNIT_FRAME) {
+ velocity_scale *= FPS;
+ }
+
+ result = ABC_read_mesh(mcmd->reader,
+ ctx->object,
+ mesh,
+ time,
+ &err_str,
+ mcmd->read_flag,
+ mcmd->cache_file->velocity_name,
+ velocity_scale);
+# endif
+ break;
+ }
+ case CACHEFILE_TYPE_USD:
+# ifdef WITH_USD
+ result = USD_read_mesh(
+ mcmd->reader, ctx->object, mesh, time * FPS, &err_str, mcmd->read_flag);
+# endif
+ break;
+ case CACHE_FILE_TYPE_INVALID:
+ break;
+ }
+
+ if (err_str) {
+ BKE_modifier_set_error(ctx->object, md, "%s", err_str);
+ }
+
+ if (!ELEM(result, nullptr, mesh) && (mesh != org_mesh)) {
+ BKE_id_free(nullptr, mesh);
+ mesh = org_mesh;
+ }
+
+ return result ? result : mesh;
+#else
+ UNUSED_VARS(ctx, md, generate_bounding_box_mesh);
+ return mesh;
+#endif
+}
+
+static bool dependsOnTime(Scene *scene, ModifierData *md, const int dag_eval_mode)
+{
+#if defined(WITH_USD) || defined(WITH_ALEMBIC)
+ MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
+ /* Do not evaluate animations if using the render engine procedural. */
+ return (mcmd->cache_file != nullptr) &&
+ !BKE_cache_file_uses_render_procedural(mcmd->cache_file, scene, dag_eval_mode);
+#else
+ UNUSED_VARS(scene, md, dag_eval_mode);
+ return false;
+#endif
+}
+
+static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
+{
+ MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
+
+ walk(userData, ob, reinterpret_cast<ID **>(&mcmd->cache_file), IDWALK_CB_USER);
+}
+
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
+{
+ MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
+
+ if (mcmd->cache_file != nullptr) {
+ DEG_add_object_cache_relation(
+ ctx->node, mcmd->cache_file, DEG_OB_COMP_CACHE, "Mesh Cache File");
+ }
+}
+
+static void panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
+
+ PointerRNA cache_file_ptr = RNA_pointer_get(ptr, "cache_file");
+ bool has_cache_file = !RNA_pointer_is_null(&cache_file_ptr);
+
+ uiLayoutSetPropSep(layout, true);
+
+ uiTemplateCacheFile(layout, C, ptr, "cache_file");
+
+ if (has_cache_file) {
+ uiItemPointerR(
+ layout, ptr, "object_path", &cache_file_ptr, "object_paths", nullptr, ICON_NONE);
+ }
+
+ if (RNA_enum_get(&ob_ptr, "type") == OB_MESH) {
+ uiItemR(layout, ptr, "read_data", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
+ uiItemR(layout, ptr, "use_vertex_interpolation", 0, nullptr, ICON_NONE);
+ }
+
+ modifier_panel_end(layout, ptr);
+}
+
+static void velocity_panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
+
+ PointerRNA fileptr;
+ if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
+ return;
+ }
+
+ uiLayoutSetPropSep(layout, true);
+ uiTemplateCacheFileVelocity(layout, &fileptr);
+ uiItemR(layout, ptr, "velocity_scale", 0, nullptr, ICON_NONE);
+}
+
+static void time_panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
+
+ PointerRNA fileptr;
+ if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
+ return;
+ }
+
+ uiLayoutSetPropSep(layout, true);
+ uiTemplateCacheFileTimeSettings(layout, &fileptr);
+}
+
+static void render_procedural_panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
+
+ PointerRNA fileptr;
+ if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
+ return;
+ }
+
+ uiLayoutSetPropSep(layout, true);
+ uiTemplateCacheFileProcedural(layout, C, &fileptr);
+}
+
+static void override_layers_panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
+
+ PointerRNA fileptr;
+ if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
+ return;
+ }
+
+ uiLayoutSetPropSep(layout, true);
+ uiTemplateCacheFileLayers(layout, C, &fileptr);
+}
+
+static void panelRegister(ARegionType *region_type)
+{
+ PanelType *panel_type = modifier_panel_register(
+ region_type, eModifierType_MeshSequenceCache, panel_draw);
+ modifier_subpanel_register(region_type, "time", "Time", nullptr, time_panel_draw, panel_type);
+ modifier_subpanel_register(region_type,
+ "render_procedural",
+ "Render Procedural",
+ nullptr,
+ render_procedural_panel_draw,
+ panel_type);
+ modifier_subpanel_register(
+ region_type, "velocity", "Velocity", nullptr, velocity_panel_draw, panel_type);
+ modifier_subpanel_register(region_type,
+ "override_layers",
+ "Override Layers",
+ NULL,
+ override_layers_panel_draw,
+ panel_type);
+}
+
+static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md)
+{
+ MeshSeqCacheModifierData *msmcd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
+ msmcd->reader = nullptr;
+ msmcd->reader_object_path[0] = '\0';
+}
+
+ModifierTypeInfo modifierType_MeshSequenceCache = {
+ /* name */ "MeshSequenceCache",
+ /* structName */ "MeshSeqCacheModifierData",
+ /* structSize */ sizeof(MeshSeqCacheModifierData),
+ /* srna */ &RNA_MeshSequenceCacheModifier,
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */
+ static_cast<ModifierTypeFlag>(eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs),
+ /* icon */ ICON_MOD_MESHDEFORM, /* TODO: Use correct icon. */
+
+ /* copyData */ copyData,
+
+ /* deformVerts */ nullptr,
+ /* deformMatrices */ nullptr,
+ /* deformVertsEM */ nullptr,
+ /* deformMatricesEM */ nullptr,
+ /* modifyMesh */ modifyMesh,
+ /* modifyGeometrySet */ nullptr,
+
+ /* initData */ initData,
+ /* requiredDataMask */ nullptr,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ dependsOnTime,
+ /* dependsOnNormals */ nullptr,
+ /* foreachIDLink */ foreachIDLink,
+ /* foreachTexLink */ nullptr,
+ /* freeRuntimeData */ nullptr,
+ /* panelRegister */ panelRegister,
+ /* blendWrite */ nullptr,
+ /* blendRead */ blendRead,
+};