diff options
author | Sergey Sharybin <sergey@blender.org> | 2020-11-12 11:26:20 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey@blender.org> | 2020-11-12 11:26:20 +0300 |
commit | de6cee4fc1913982b0b2bd786bfd813c935bbe73 (patch) | |
tree | a726c0c63bbd1d6c47c90c32119ce14c8048cddc /source/blender/modifiers/intern | |
parent | e4d432500a0e2f978fe019da43deb843da405032 (diff) | |
parent | 88bb29dea668df8cc46aa7f55895f229748bdbb4 (diff) |
Merge branch 'master' into codesign_error_tracker
Diffstat (limited to 'source/blender/modifiers/intern')
66 files changed, 2560 insertions, 1145 deletions
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index f42f67417c3..38fb19e3233 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -29,6 +29,7 @@ #include "BLT_translation.h" #include "DNA_armature_types.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" @@ -65,7 +66,9 @@ static void initData(ModifierData *md) { ArmatureModifierData *amd = (ArmatureModifierData *)md; - amd->deformflag = ARM_DEF_VGROUP; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(amd, modifier)); + + MEMCPY_STRUCT_AFTER(amd, DNA_struct_default_get(ArmatureModifierData), modifier); } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -101,11 +104,11 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return !amd->object || amd->object->type != OB_ARMATURE; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { ArmatureModifierData *amd = (ArmatureModifierData *)md; - walk(userData, ob, &amd->object, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&amd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -255,7 +258,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(col, ptr, "use_deform_preserve_volume", 0, NULL, ICON_NONE); uiItemR(col, ptr, "use_multi_modifier", 0, NULL, ICON_NONE); - col = uiLayoutColumnWithHeading(layout, true, IFACE_("Bind to")); + col = uiLayoutColumnWithHeading(layout, true, IFACE_("Bind To")); uiItemR(col, ptr, "use_vertex_groups", 0, IFACE_("Vertex Groups"), ICON_NONE); uiItemR(col, ptr, "use_bone_envelopes", 0, IFACE_("Bone Envelopes"), ICON_NONE); @@ -278,9 +281,11 @@ ModifierTypeInfo modifierType_Armature = { /* name */ "Armature", /* structName */ "ArmatureModifierData", /* structSize */ sizeof(ArmatureModifierData), + /* srna */ &RNA_ArmatureModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_ARMATURE, /* copyData */ copyData, @@ -300,8 +305,7 @@ ModifierTypeInfo modifierType_Armature = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 60e1a3de67e..da1754b8ebd 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -32,6 +32,7 @@ #include "BLT_translation.h" #include "DNA_curve_types.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -63,32 +64,22 @@ static void initData(ModifierData *md) { ArrayModifierData *amd = (ArrayModifierData *)md; - /* default to 2 duplicates distributed along the x-axis by an - * offset of 1 object-width - */ - amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL; - amd->count = 2; - zero_v3(amd->offset); - amd->scale[0] = 1; - amd->scale[1] = amd->scale[2] = 0; - amd->length = 0; - amd->merge_dist = 0.01; - amd->fit_type = MOD_ARR_FIXEDCOUNT; - amd->offset_type = MOD_ARR_OFF_RELATIVE; - amd->flags = 0; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(amd, modifier)); + + MEMCPY_STRUCT_AFTER(amd, DNA_struct_default_get(ArrayModifierData), modifier); /* Open the first subpanel by default, it corresspnds to Relative offset which is enabled too. */ - md->ui_expand_flag = (1 << 0) | (1 << 1); + md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { ArrayModifierData *amd = (ArrayModifierData *)md; - walk(userData, ob, &amd->start_cap, IDWALK_CB_NOP); - walk(userData, ob, &amd->end_cap, IDWALK_CB_NOP); - walk(userData, ob, &amd->curve_ob, IDWALK_CB_NOP); - walk(userData, ob, &amd->offset_ob, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&amd->start_cap, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&amd->end_cap, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&amd->curve_ob, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&amd->offset_ob, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -490,7 +481,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, /* calculate the maximum number of copies which will fit within the * prescribed length */ - if (amd->fit_type == MOD_ARR_FITLENGTH || amd->fit_type == MOD_ARR_FITCURVE) { + if (ELEM(amd->fit_type, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE)) { const float float_epsilon = 1e-6f; bool offset_is_too_small = false; float dist = len_v3(offset[3]); @@ -517,6 +508,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, if (offset_is_too_small) { BKE_modifier_set_error( + ctx->object, &amd->modifier, "The offset is too small, we cannot generate the amount of geometry it would require"); } @@ -527,7 +519,8 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, else if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + (size_t)end_cap_nverts) > max_num_vertices) { count = 1; - BKE_modifier_set_error(&amd->modifier, + BKE_modifier_set_error(ctx->object, + &amd->modifier, "The amount of copies is too high, we cannot generate the amount of " "geometry it would require"); } @@ -1010,10 +1003,12 @@ ModifierTypeInfo modifierType_Array = { /* name */ "Array", /* structName */ "ArrayModifierData", /* structSize */ sizeof(ArrayModifierData), + /* srna */ &RNA_ArrayModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, + /* icon */ ICON_MOD_ARRAY, /* copyData */ BKE_modifier_copydata_generic, @@ -1033,8 +1028,7 @@ ModifierTypeInfo modifierType_Array = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index ab024bd824d..04ddac338e5 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -30,6 +30,7 @@ #include "BLT_translation.h" #include "DNA_curveprofile_types.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -63,22 +64,10 @@ static void initData(ModifierData *md) { BevelModifierData *bmd = (BevelModifierData *)md; - bmd->value = 0.1f; - bmd->res = 1; - bmd->flags = 0; - bmd->val_flags = MOD_BEVEL_AMT_OFFSET; - bmd->lim_flags = 0; - bmd->e_flags = 0; - bmd->edge_flags = 0; - bmd->face_str_mode = MOD_BEVEL_FACE_STRENGTH_NONE; - bmd->miter_inner = MOD_BEVEL_MITER_SHARP; - bmd->miter_outer = MOD_BEVEL_MITER_SHARP; - bmd->affect_type = MOD_BEVEL_AFFECT_EDGES; - bmd->spread = 0.1f; - bmd->mat = -1; - bmd->profile = 0.5f; - bmd->bevel_angle = DEG2RADF(30.0f); - bmd->defgrp_name[0] = '\0'; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(bmd, modifier)); + + MEMCPY_STRUCT_AFTER(bmd, DNA_struct_default_get(BevelModifierData), modifier); + bmd->custom_profile = BKE_curveprofile_add(PROF_PRESET_LINE); } @@ -219,7 +208,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * Object *ob = ctx->object; if (harden_normals && (ob->type == OB_MESH) && !(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) { - BKE_modifier_set_error(md, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error(ob, md, "Enable 'Auto Smooth' in Object Data Properties"); harden_normals = false; } @@ -446,9 +435,11 @@ ModifierTypeInfo modifierType_Bevel = { /* name */ "Bevel", /* structName */ "BevelModifierData", /* structSize */ sizeof(BevelModifierData), + /* srna */ &RNA_BevelModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, + /* icon */ ICON_MOD_BEVEL, /* copyData */ copyData, /* deformVerts */ NULL, /* deformMatrices */ NULL, @@ -465,7 +456,6 @@ ModifierTypeInfo modifierType_Bevel = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index bef7d5d8e4f..7fea06ba955 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -28,16 +28,21 @@ #include "BLI_utildefines.h" #include "BLI_alloca.h" +#include "BLI_array.h" #include "BLI_math_geom.h" #include "BLI_math_matrix.h" #include "BLT_translation.h" +#include "DNA_collection_types.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_global.h" /* only to check G.debug */ #include "BKE_lib_id.h" @@ -65,6 +70,7 @@ #include "tools/bmesh_boolean.h" #include "tools/bmesh_intersect.h" +// #define DEBUG_TIME #ifdef DEBUG_TIME # include "PIL_time.h" # include "PIL_time_utildefines.h" @@ -74,10 +80,9 @@ static void initData(ModifierData *md) { BooleanModifierData *bmd = (BooleanModifierData *)md; - bmd->double_threshold = 1e-6f; - bmd->operation = eBooleanModifierOp_Difference; - bmd->solver = eBooleanModifierSolver_Exact; - bmd->flag = 0; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(bmd, modifier)); + + MEMCPY_STRUCT_AFTER(bmd, DNA_struct_default_get(BooleanModifierData), modifier); } static bool isDisabled(const struct Scene *UNUSED(scene), @@ -85,39 +90,55 @@ static bool isDisabled(const struct Scene *UNUSED(scene), bool UNUSED(useRenderParams)) { BooleanModifierData *bmd = (BooleanModifierData *)md; + Collection *col = bmd->collection; - /* The object type check is only needed here in case we have a placeholder - * object assigned (because the library containing the mesh is missing). - * - * In other cases it should be impossible to have a type mismatch. - */ - return !bmd->object || bmd->object->type != OB_MESH; + if (bmd->flag & eBooleanModifierFlag_Object) { + return !bmd->object || bmd->object->type != OB_MESH; + } + if (bmd->flag & eBooleanModifierFlag_Collection) { + /* The Exact solver tolerates an empty collection. */ + return !col && bmd->solver != eBooleanModifierSolver_Exact; + } + return false; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { BooleanModifierData *bmd = (BooleanModifierData *)md; - walk(userData, ob, &bmd->object, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&bmd->collection, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&bmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) { BooleanModifierData *bmd = (BooleanModifierData *)md; - if (bmd->object != NULL) { + if ((bmd->flag & eBooleanModifierFlag_Object) && bmd->object != NULL) { DEG_add_object_relation(ctx->node, bmd->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); DEG_add_object_relation(ctx->node, bmd->object, DEG_OB_COMP_GEOMETRY, "Boolean Modifier"); } + + Collection *col = bmd->collection; + + if ((bmd->flag & eBooleanModifierFlag_Collection) && col != NULL) { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (col, operand_ob) { + if (operand_ob->type == OB_MESH && operand_ob != ctx->object) { + DEG_add_object_relation(ctx->node, operand_ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); + DEG_add_object_relation(ctx->node, operand_ob, DEG_OB_COMP_GEOMETRY, "Boolean Modifier"); + } + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } /* We need own transformation as well. */ DEG_add_modifier_to_transform_relation(ctx->node, "Boolean Modifier"); } static Mesh *get_quick_mesh( - Object *ob_self, Mesh *mesh_self, Object *ob_other, Mesh *mesh_other, int operation) + Object *ob_self, Mesh *mesh_self, Object *ob_operand_ob, Mesh *mesh_operand_ob, int operation) { Mesh *result = NULL; - if (mesh_self->totpoly == 0 || mesh_other->totpoly == 0) { + if (mesh_self->totpoly == 0 || mesh_operand_ob->totpoly == 0) { switch (operation) { case eBooleanModifierOp_Intersect: result = BKE_mesh_new_nomain(0, 0, 0, 0, 0); @@ -128,13 +149,13 @@ static Mesh *get_quick_mesh( result = mesh_self; } else { - BKE_id_copy_ex(NULL, &mesh_other->id, (ID **)&result, LIB_ID_COPY_LOCALIZE); + result = (Mesh *)BKE_id_copy_ex(NULL, &mesh_operand_ob->id, NULL, LIB_ID_COPY_LOCALIZE); float imat[4][4]; float omat[4][4]; invert_m4_m4(imat, ob_self->obmat); - mul_m4_m4m4(omat, imat, ob_other->obmat); + mul_m4_m4m4(omat, imat, ob_operand_ob->obmat); const int mverts_len = result->totvert; MVert *mv = result->mvert; @@ -168,208 +189,489 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data)) return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0; } -static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static bool BMD_error_messages(const Object *ob, ModifierData *md, Collection *col) { BooleanModifierData *bmd = (BooleanModifierData *)md; - Mesh *result = mesh; - Mesh *mesh_other; + bool error_returns_result = false; + + const bool operand_collection = (bmd->flag & eBooleanModifierFlag_Collection) != 0; + const bool use_exact = bmd->solver == eBooleanModifierSolver_Exact; + const bool operation_intersect = bmd->operation == eBooleanModifierOp_Intersect; + +#ifndef WITH_GMP + /* If compiled without GMP, return a error. */ + if (use_exact) { + BKE_modifier_set_error(ob, md, "Compiled without GMP, using fast solver"); + error_returns_result = false; + } +#endif + + /* If intersect is selected using fast solver, return a error. */ + if (operand_collection && operation_intersect && !use_exact) { + BKE_modifier_set_error(ob, md, "Cannot execute, intersect only available using exact solver"); + error_returns_result = true; + } + + /* If the selected collection is empty and using fast solver, return a error. */ + if (operand_collection) { + if (!use_exact && BKE_collection_is_empty(col)) { + BKE_modifier_set_error(ob, md, "Cannot execute, fast solver and empty collection"); + error_returns_result = true; + } - if (bmd->object == NULL) { - return result; + /* If the selected collection contain non mesh objects, return a error. */ + if (col) { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (col, operand_ob) { + if (operand_ob->type != OB_MESH) { + BKE_modifier_set_error( + ob, md, "Cannot execute, the selected collection contains non mesh objects"); + error_returns_result = true; + } + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } } - Object *other = bmd->object; - mesh_other = BKE_modifier_get_evaluated_mesh_from_evaluated_object(other, false); - if (mesh_other) { - Object *object = ctx->object; + return error_returns_result; +} - /* XXX This is utterly non-optimal, we may go from a bmesh to a mesh back to a bmesh! - * But for 2.90 better not try to be smart here. */ - BKE_mesh_wrapper_ensure_mdata(mesh_other); +static BMesh *BMD_mesh_bm_create( + Mesh *mesh, Object *object, Mesh *mesh_operand_ob, Object *operand_ob, bool *r_is_flip) +{ + BMesh *bm; - /* when one of objects is empty (has got no faces) we could speed up - * calculation a bit returning one of objects' derived meshes (or empty one) - * Returning mesh is depended on modifiers operation (sergey) */ - result = get_quick_mesh(object, mesh, other, mesh_other, bmd->operation); + *r_is_flip = (is_negative_m4(object->obmat) != is_negative_m4(operand_ob->obmat)); - if (result == NULL) { - const bool is_flip = (is_negative_m4(object->obmat) != is_negative_m4(other->obmat)); + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh, mesh_operand_ob); - BMesh *bm; - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh, mesh_other); + bm = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = false, + })); -#ifdef DEBUG_TIME - TIMEIT_START(boolean_bmesh); + BM_mesh_bm_from_me(bm, + mesh_operand_ob, + &((struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + + if (UNLIKELY(*r_is_flip)) { + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + BMIter iter; + BMFace *efa; + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + BM_face_normal_flip_ex(bm, efa, cd_loop_mdisp_offset, true); + } + } + + BM_mesh_bm_from_me(bm, + mesh, + &((struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + + return bm; +} + +static void BMD_mesh_intersection(BMesh *bm, + ModifierData *md, + const ModifierEvalContext *ctx, + Mesh *mesh_operand_ob, + Object *object, + Object *operand_ob, + bool is_flip) +{ + BooleanModifierData *bmd = (BooleanModifierData *)md; + + /* main bmesh intersection setup */ + /* create tessface & intersect */ + const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); + int tottri; + BMLoop *(*looptris)[3]; + + looptris = MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__); + + BM_mesh_calc_tessellation_beauty(bm, looptris, &tottri); + + /* postpone this until after tessellating + * so we can use the original normals before the vertex are moved */ + { + BMIter iter; + int i; + const int i_verts_end = mesh_operand_ob->totvert; + const int i_faces_end = mesh_operand_ob->totpoly; + + float imat[4][4]; + float omat[4][4]; + + invert_m4_m4(imat, object->obmat); + mul_m4_m4m4(omat, imat, operand_ob->obmat); + + BMVert *eve; + i = 0; + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + mul_m4_v3(omat, eve->co); + if (++i == i_verts_end) { + break; + } + } + + /* we need face normals because of 'BM_face_split_edgenet' + * we could calculate on the fly too (before calling split). */ + { + float nmat[3][3]; + copy_m3_m4(nmat, omat); + invert_m3(nmat); + + if (UNLIKELY(is_flip)) { + negate_m3(nmat); + } + + const short ob_src_totcol = operand_ob->totcol; + short *material_remap = BLI_array_alloca(material_remap, ob_src_totcol ? ob_src_totcol : 1); + + /* Using original (not evaluated) object here since we are writing to it. */ + /* XXX Pretty sure comment above is fully wrong now with CoW & co ? */ + BKE_object_material_remap_calc(ctx->object, operand_ob, material_remap); + + BMFace *efa; + i = 0; + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + mul_transposed_m3_v3(nmat, efa->no); + normalize_v3(efa->no); + + /* Temp tag to test which side split faces are from. */ + BM_elem_flag_enable(efa, BM_FACE_TAG); + + /* remap material */ + if (LIKELY(efa->mat_nr < ob_src_totcol)) { + efa->mat_nr = material_remap[efa->mat_nr]; + } + + if (++i == i_faces_end) { + break; + } + } + } + } + + /* not needed, but normals for 'dm' will be invalid, + * currently this is ok for 'BM_mesh_intersect' */ + // BM_mesh_normals_update(bm); + + bool use_separate = false; + bool use_dissolve = true; + bool use_island_connect = true; + + /* change for testing */ + if (G.debug & G_DEBUG) { + use_separate = (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_Separate) != 0; + use_dissolve = (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoDissolve) == 0; + use_island_connect = (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoConnectRegions) == 0; + } + +#ifdef WITH_GMP + const bool use_exact = bmd->solver == eBooleanModifierSolver_Exact; + const bool use_self = (bmd->flag & eBooleanModifierFlag_Self) != 0; +#else + const bool use_exact = false; + const bool use_self = false; #endif - bm = BM_mesh_create(&allocsize, - &((struct BMeshCreateParams){ - .use_toolflags = false, - })); - BM_mesh_bm_from_me(bm, - mesh_other, - &((struct BMeshFromMeshParams){ - .calc_face_normal = true, - })); + if (use_exact) { + BM_mesh_boolean( + bm, looptris, tottri, bm_face_isect_pair, NULL, 2, use_self, false, bmd->operation); + } + else { + BM_mesh_intersect(bm, + looptris, + tottri, + bm_face_isect_pair, + NULL, + false, + use_separate, + use_dissolve, + use_island_connect, + false, + false, + bmd->operation, + bmd->double_threshold); + } + MEM_freeN(looptris); +} +static int bm_face_isect_nary(BMFace *f, void *user_data) +{ + int *shape = (int *)user_data; + return shape[BM_elem_index_get(f)]; +} + +/* The Exact solver can do all operands of a collection at once. */ +static Mesh *collection_boolean_exact(BooleanModifierData *bmd, + const ModifierEvalContext *ctx, + Mesh *mesh) +{ + int i; + Mesh *result = mesh; + Collection *col = bmd->collection; + int num_shapes = 1; + Mesh **meshes = NULL; + Object **objects = NULL; + BLI_array_declare(meshes); + BLI_array_declare(objects); + BMAllocTemplate bat; + bat.totvert = mesh->totvert; + bat.totedge = mesh->totedge; + bat.totloop = mesh->totloop; + bat.totface = mesh->totpoly; + BLI_array_append(meshes, mesh); + BLI_array_append(objects, ctx->object); + Mesh *col_mesh; + /* Allow col to be empty: then target mesh will just remove self-intersections. */ + if (col) { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (col, ob) { + if (ob->type == OB_MESH && ob != ctx->object) { + col_mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob, false); + /* XXX This is utterly non-optimal, we may go from a bmesh to a mesh back to a bmesh! + * But for 2.90 better not try to be smart here. */ + BKE_mesh_wrapper_ensure_mdata(col_mesh); + BLI_array_append(meshes, col_mesh); + BLI_array_append(objects, ob); + bat.totvert += col_mesh->totvert; + bat.totedge += col_mesh->totedge; + bat.totloop += col_mesh->totloop; + bat.totface += col_mesh->totpoly; + ++num_shapes; + } + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } + int *shape_face_end = MEM_mallocN(num_shapes * sizeof(int), __func__); + int *shape_vert_end = MEM_mallocN(num_shapes * sizeof(int), __func__); + bool is_neg_mat0 = is_negative_m4(ctx->object->obmat); + BMesh *bm = BM_mesh_create(&bat, + &((struct BMeshCreateParams){ + .use_toolflags = false, + })); + for (i = 0; i < num_shapes; i++) { + Mesh *me = meshes[i]; + Object *ob = objects[i]; + /* Need normals for triangulation. */ + BM_mesh_bm_from_me(bm, + me, + &((struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + shape_face_end[i] = me->totpoly + (i == 0 ? 0 : shape_face_end[i - 1]); + shape_vert_end[i] = me->totvert + (i == 0 ? 0 : shape_vert_end[i - 1]); + if (i > 0) { + bool is_flip = (is_neg_mat0 != is_negative_m4(ob->obmat)); if (UNLIKELY(is_flip)) { const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); BMIter iter; BMFace *efa; + BM_mesh_elem_index_ensure(bm, BM_FACE); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - BM_face_normal_flip_ex(bm, efa, cd_loop_mdisp_offset, true); + if (BM_elem_index_get(efa) >= shape_face_end[i - 1]) { + BM_face_normal_flip_ex(bm, efa, cd_loop_mdisp_offset, true); + } } } + } + } - BM_mesh_bm_from_me(bm, - mesh, - &((struct BMeshFromMeshParams){ - .calc_face_normal = true, - })); + /* Triangulate the mesh. */ + const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); + int tottri; + BMLoop *(*looptris)[3]; + looptris = MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__); + BM_mesh_calc_tessellation_beauty(bm, looptris, &tottri); + + /* Move the vertices of all but the first shape into transformation space of first mesh. + * Do this after tesselation so don't need to recalculate normals. + * The Exact solver doesn't need normals on the input faces. */ + float imat[4][4]; + float omat[4][4]; + invert_m4_m4(imat, ctx->object->obmat); + int curshape = 0; + int curshape_vert_end = shape_vert_end[0]; + BMVert *eve; + BMIter iter; + i = 0; + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (i == curshape_vert_end) { + curshape++; + curshape_vert_end = shape_vert_end[curshape]; + mul_m4_m4m4(omat, imat, objects[curshape]->obmat); + } + if (curshape > 0) { + mul_m4_v3(omat, eve->co); + } + i++; + } - /* main bmesh intersection setup */ - { - /* create tessface & intersect */ - const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); - int tottri; - BMLoop *(*looptris)[3]; + /* Remap the materials. Fill a shape array for test function. Calculate normals. */ + int *shape = MEM_mallocN(bm->totface * sizeof(int), __func__); + curshape = 0; + int curshape_face_end = shape_face_end[0]; + int curshape_ncol = ctx->object->totcol; + short *material_remap = NULL; + BMFace *efa; + i = 0; + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + if (i == curshape_face_end) { + curshape++; + curshape_face_end = shape_face_end[curshape]; + if (material_remap != NULL) { + MEM_freeN(material_remap); + } + curshape_ncol = objects[curshape]->totcol; + material_remap = MEM_mallocN(curshape_ncol ? curshape_ncol : 1, __func__); + BKE_object_material_remap_calc(ctx->object, objects[curshape], material_remap); + } + shape[i] = curshape; + if (curshape > 0) { + /* Normals for other shapes changed because vertex positions changed. + * Boolean doesn't need these, but post-boolean code (interpolation) does. */ + BM_face_normal_update(efa); + if (LIKELY(efa->mat_nr < curshape_ncol)) { + efa->mat_nr = material_remap[efa->mat_nr]; + } + } + i++; + } - looptris = MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__); + BM_mesh_elem_index_ensure(bm, BM_FACE); + BM_mesh_boolean( + bm, looptris, tottri, bm_face_isect_nary, shape, num_shapes, true, false, bmd->operation); - BM_mesh_calc_tessellation_beauty(bm, looptris, &tottri); + result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); + BM_mesh_free(bm); + result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; - /* postpone this until after tessellating - * so we can use the original normals before the vertex are moved */ - { - BMIter iter; - int i; - const int i_verts_end = mesh_other->totvert; - const int i_faces_end = mesh_other->totpoly; + MEM_freeN(shape); + MEM_freeN(shape_face_end); + MEM_freeN(shape_vert_end); + MEM_freeN(looptris); + if (material_remap != NULL) { + MEM_freeN(material_remap); + } + BLI_array_free(meshes); + BLI_array_free(objects); + return result; +} - float imat[4][4]; - float omat[4][4]; +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +{ + BooleanModifierData *bmd = (BooleanModifierData *)md; + Object *object = ctx->object; + Mesh *result = mesh; + Mesh *mesh_operand_ob; + BMesh *bm; + Collection *col = bmd->collection; - invert_m4_m4(imat, object->obmat); - mul_m4_m4m4(omat, imat, other->obmat); + bool is_flip = false; + const bool confirm_return = true; +#ifdef WITH_GMP + const bool use_exact = bmd->solver == eBooleanModifierSolver_Exact; +#else + const bool use_exact = false; +#endif - BMVert *eve; - i = 0; - BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - mul_m4_v3(omat, eve->co); - if (++i == i_verts_end) { - break; - } - } +#ifdef DEBUG_TIME + TIMEIT_START(boolean_bmesh); +#endif - /* we need face normals because of 'BM_face_split_edgenet' - * we could calculate on the fly too (before calling split). */ - { - float nmat[3][3]; - copy_m3_m4(nmat, omat); - invert_m3(nmat); - - if (UNLIKELY(is_flip)) { - negate_m3(nmat); - } - - const short ob_src_totcol = other->totcol; - short *material_remap = BLI_array_alloca(material_remap, - ob_src_totcol ? ob_src_totcol : 1); - - /* Using original (not evaluated) object here since we are writing to it. */ - /* XXX Pretty sure comment above is fully wrong now with CoW & co ? */ - BKE_object_material_remap_calc(ctx->object, other, material_remap); - - BMFace *efa; - i = 0; - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - mul_transposed_m3_v3(nmat, efa->no); - normalize_v3(efa->no); - - /* Temp tag to test which side split faces are from. */ - BM_elem_flag_enable(efa, BM_FACE_TAG); - - /* remap material */ - if (LIKELY(efa->mat_nr < ob_src_totcol)) { - efa->mat_nr = material_remap[efa->mat_nr]; - } - - if (++i == i_faces_end) { - break; - } - } - } - } + if (bmd->flag & eBooleanModifierFlag_Object) { + if (bmd->object == NULL) { + return result; + } - /* not needed, but normals for 'dm' will be invalid, - * currently this is ok for 'BM_mesh_intersect' */ - // BM_mesh_normals_update(bm); + BMD_error_messages(ctx->object, md, NULL); - bool use_separate = false; - bool use_dissolve = true; - bool use_island_connect = true; + Object *operand_ob = bmd->object; - /* change for testing */ - if (G.debug & G_DEBUG) { - use_separate = (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_Separate) != 0; - use_dissolve = (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoDissolve) == 0; - use_island_connect = (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoConnectRegions) == - 0; - } + mesh_operand_ob = BKE_modifier_get_evaluated_mesh_from_evaluated_object(operand_ob, false); -#ifdef WITH_GMP - const bool use_exact = bmd->solver == eBooleanModifierSolver_Exact; - const bool use_self = (bmd->flag & eBooleanModifierFlag_Self) != 0; -#else - if (bmd->solver == eBooleanModifierSolver_Exact) { - BKE_modifier_set_error(md, "Compiled without GMP, using fast solver"); - } - const bool use_exact = false; - const bool use_self = false; -#endif + if (mesh_operand_ob) { + /* XXX This is utterly non-optimal, we may go from a bmesh to a mesh back to a bmesh! + * But for 2.90 better not try to be smart here. */ + BKE_mesh_wrapper_ensure_mdata(mesh_operand_ob); + /* when one of objects is empty (has got no faces) we could speed up + * calculation a bit returning one of objects' derived meshes (or empty one) + * Returning mesh is depended on modifiers operation (sergey) */ + result = get_quick_mesh(object, mesh, operand_ob, mesh_operand_ob, bmd->operation); - if (use_exact) { - BM_mesh_boolean( - bm, looptris, tottri, bm_face_isect_pair, NULL, use_self, bmd->operation); - } - else { - BM_mesh_intersect(bm, - looptris, - tottri, - bm_face_isect_pair, - NULL, - false, - use_separate, - use_dissolve, - use_island_connect, - false, - false, - bmd->operation, - bmd->double_threshold); - } + if (result == NULL) { + bm = BMD_mesh_bm_create(mesh, object, mesh_operand_ob, operand_ob, &is_flip); + + BMD_mesh_intersection(bm, md, ctx, mesh_operand_ob, object, operand_ob, is_flip); - MEM_freeN(looptris); + result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); + BM_mesh_free(bm); + result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } - result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); + /* if new mesh returned, return it; otherwise there was + * an error, so delete the modifier object */ + if (result == NULL) { + BKE_modifier_set_error(object, md, "Cannot execute boolean operation"); + } + } + } - BM_mesh_free(bm); + else { + if (col == NULL && !use_exact) { + return result; + } - result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + /* Return result for certain errors. */ + if (BMD_error_messages(ctx->object, md, col) == confirm_return) { + return result; + } -#ifdef DEBUG_TIME - TIMEIT_END(boolean_bmesh); -#endif + if (use_exact) { + result = collection_boolean_exact(bmd, ctx, mesh); } + else { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (col, operand_ob) { + if (operand_ob->type == OB_MESH && operand_ob != ctx->object) { + + mesh_operand_ob = BKE_modifier_get_evaluated_mesh_from_evaluated_object(operand_ob, + false); - /* if new mesh returned, return it; otherwise there was - * an error, so delete the modifier object */ - if (result == NULL) { - BKE_modifier_set_error(md, "Cannot execute boolean operation"); + if (mesh_operand_ob) { + /* XXX This is utterly non-optimal, we may go from a bmesh to a mesh back to a bmesh! + * But for 2.90 better not try to be smart here. */ + BKE_mesh_wrapper_ensure_mdata(mesh_operand_ob); + + bm = BMD_mesh_bm_create(mesh, object, mesh_operand_ob, operand_ob, &is_flip); + + BMD_mesh_intersection(bm, md, ctx, mesh_operand_ob, object, operand_ob, is_flip); + + /* Needed for multiple objects to work. */ + BM_mesh_bm_to_me(NULL, + bm, + mesh, + (&(struct BMeshToMeshParams){ + .calc_object_remap = false, + })); + + result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); + BM_mesh_free(bm); + result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; + } + } + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } } +#ifdef DEBUG_TIME + TIMEIT_END(boolean_bmesh); +#endif + return result; } @@ -392,13 +694,26 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); + uiItemR(layout, ptr, "operand_type", 0, NULL, ICON_NONE); + + const bool operand_object = RNA_enum_get(ptr, "operand_type") == eBooleanModifierFlag_Object; + + if (operand_object) { + uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE); + } + else { + uiItemR(layout, ptr, "collection", 0, NULL, ICON_NONE); + } + const bool use_exact = RNA_enum_get(ptr, "solver") == eBooleanModifierSolver_Exact; - uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "solver", UI_ITEM_R_EXPAND, NULL, ICON_NONE); if (use_exact) { - uiItemR(layout, ptr, "use_self", 0, NULL, ICON_NONE); + /* When operand is collection, we always use_self. */ + if (operand_object) { + uiItemR(layout, ptr, "use_self", 0, NULL, ICON_NONE); + } } else { uiItemR(layout, ptr, "double_threshold", 0, NULL, ICON_NONE); @@ -421,8 +736,10 @@ ModifierTypeInfo modifierType_Boolean = { /* name */ "Boolean", /* structName */ "BooleanModifierData", /* structSize */ sizeof(BooleanModifierData), + /* srna */ &RNA_BooleanModifier, /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_BOOLEAN, /* copyData */ BKE_modifier_copydata_generic, @@ -442,8 +759,7 @@ ModifierTypeInfo modifierType_Boolean = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index d3caffb819c..96ed0a5d069 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -29,6 +29,7 @@ #include "BLI_math_vector.h" #include "BLI_rand.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -55,8 +56,9 @@ static void initData(ModifierData *md) { BuildModifierData *bmd = (BuildModifierData *)md; - bmd->start = 1.0; - bmd->length = 100.0; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(bmd, modifier)); + + MEMCPY_STRUCT_AFTER(bmd, DNA_struct_default_get(BuildModifierData), modifier); } static bool dependsOnTime(ModifierData *UNUSED(md)) @@ -331,8 +333,10 @@ ModifierTypeInfo modifierType_Build = { /* name */ "Build", /* structName */ "BuildModifierData", /* structSize */ sizeof(BuildModifierData), + /* srna */ &RNA_BuildModifier, /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, + /* icon */ ICON_MOD_BUILD, /* copyData */ BKE_modifier_copydata_generic, @@ -352,7 +356,6 @@ ModifierTypeInfo modifierType_Build = { /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index 4f2f6d219d8..185c21af7ad 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -56,13 +57,9 @@ static void initData(ModifierData *md) { CastModifierData *cmd = (CastModifierData *)md; - cmd->fac = 0.5f; - cmd->radius = 0.0f; - cmd->size = 0.0f; - cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z | MOD_CAST_SIZE_FROM_RADIUS; - cmd->type = MOD_CAST_TYPE_SPHERE; - cmd->defgrp_name[0] = '\0'; - cmd->object = NULL; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(cmd, modifier)); + + MEMCPY_STRUCT_AFTER(cmd, DNA_struct_default_get(CastModifierData), modifier); } static bool isDisabled(const struct Scene *UNUSED(scene), @@ -93,11 +90,11 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { CastModifierData *cmd = (CastModifierData *)md; - walk(userData, ob, &cmd->object, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&cmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -515,7 +512,7 @@ static void deformVertsEM(ModifierData *md, } if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) { - BLI_assert(mesh_src->totvert == numVerts); + BLI_assert(mesh->totvert == numVerts); } /* TODO(Campbell): use edit-mode data only (remove this line). */ @@ -579,9 +576,11 @@ ModifierTypeInfo modifierType_Cast = { /* name */ "Cast", /* structName */ "CastModifierData", /* structSize */ sizeof(CastModifierData), + /* srna */ &RNA_CastModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_CAST, /* copyData */ BKE_modifier_copydata_generic, @@ -601,8 +600,7 @@ ModifierTypeInfo modifierType_Cast = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 7d0f245ecad..8f876213cd6 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -30,6 +30,7 @@ #include "BLT_translation.h" #include "DNA_cloth_types.h" +#include "DNA_defaults.h" #include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" @@ -65,8 +66,12 @@ static void initData(ModifierData *md) { ClothModifierData *clmd = (ClothModifierData *)md; - clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms"); - clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms"); + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(clmd, modifier)); + + MEMCPY_STRUCT_AFTER(clmd, DNA_struct_default_get(ClothModifierData), modifier); + clmd->sim_parms = DNA_struct_default_alloc(ClothSimSettings); + clmd->coll_parms = DNA_struct_default_alloc(ClothCollSettings); + clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches); /* check for alloc failing */ @@ -74,7 +79,13 @@ static void initData(ModifierData *md) return; } - cloth_init(clmd); + if (!clmd->sim_parms->effector_weights) { + clmd->sim_parms->effector_weights = BKE_effector_add_weights(NULL); + } + + if (clmd->point_cache) { + clmd->point_cache->step = 1; + } } static void deformVerts(ModifierData *md, @@ -102,7 +113,7 @@ static void deformVerts(ModifierData *md, else { /* Not possible to use get_mesh() in this case as we'll modify its vertices * and get_mesh() would return 'mesh' directly. */ - BKE_id_copy_ex(NULL, (ID *)mesh, (ID **)&mesh_src, LIB_ID_COPY_LOCALIZE); + mesh_src = (Mesh *)BKE_id_copy_ex(NULL, (ID *)mesh, NULL, LIB_ID_COPY_LOCALIZE); } /* TODO(sergey): For now it actually duplicates logic from DerivedMesh.c @@ -284,9 +295,11 @@ ModifierTypeInfo modifierType_Cloth = { /* name */ "Cloth", /* structName */ "ClothModifierData", /* structSize */ sizeof(ClothModifierData), + /* srna */ &RNA_ClothModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_UsesPointCache | eModifierTypeFlag_Single, + /* icon */ ICON_MOD_CLOTH, /* copyData */ copyData, @@ -306,7 +319,6 @@ ModifierTypeInfo modifierType_Cloth = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 863e0ab7395..faba08f9613 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -62,16 +63,9 @@ static void initData(ModifierData *md) { CollisionModifierData *collmd = (CollisionModifierData *)md; - collmd->x = NULL; - collmd->xnew = NULL; - collmd->current_x = NULL; - collmd->current_xnew = NULL; - collmd->current_v = NULL; - collmd->time_x = collmd->time_xnew = -1000; - collmd->mvert_num = 0; - collmd->tri_num = 0; - collmd->is_static = false; - collmd->bvhtree = NULL; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(collmd, modifier)); + + MEMCPY_STRUCT_AFTER(collmd, DNA_struct_default_get(CollisionModifierData), modifier); } static void freeData(ModifierData *md) @@ -121,7 +115,7 @@ static void deformVerts(ModifierData *md, else { /* Not possible to use get_mesh() in this case as we'll modify its vertices * and get_mesh() would return 'mesh' directly. */ - BKE_id_copy_ex(NULL, (ID *)mesh, (ID **)&mesh_src, LIB_ID_COPY_LOCALIZE); + mesh_src = (Mesh *)BKE_id_copy_ex(NULL, (ID *)mesh, NULL, LIB_ID_COPY_LOCALIZE); } if (!ob->pd) { @@ -302,8 +296,10 @@ ModifierTypeInfo modifierType_Collision = { /* name */ "Collision", /* structName */ "CollisionModifierData", /* structSize */ sizeof(CollisionModifierData), + /* srna */ &RNA_CollisionModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_Single, + /* icon */ ICON_MOD_PHYSICS, /* copyData */ NULL, @@ -323,7 +319,6 @@ ModifierTypeInfo modifierType_Collision = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 5eee196423e..5884ec0aa17 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -29,6 +29,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -56,8 +57,6 @@ #include "BLO_read_write.h" -#include "BLI_strict_flags.h" - #include "DEG_depsgraph_query.h" // #define DEBUG_TIME @@ -74,20 +73,15 @@ static void initData(ModifierData *md) { CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md; - csmd->bind_coords = NULL; - csmd->bind_coords_num = 0; - - csmd->lambda = 0.5f; - csmd->scale = 1.0f; - csmd->repeat = 5; - csmd->flag = 0; - csmd->smooth_type = MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(csmd, modifier)); - csmd->defgrp_name[0] = '\0'; + MEMCPY_STRUCT_AFTER(csmd, DNA_struct_default_get(CorrectiveSmoothModifierData), modifier); csmd->delta_cache.deltas = NULL; } +#include "BLI_strict_flags.h" + static void copyData(const ModifierData *md, ModifierData *target, const int flag) { const CorrectiveSmoothModifierData *csmd = (const CorrectiveSmoothModifierData *)md; @@ -621,7 +615,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, csmd_orig->bind_coords_num = csmd->bind_coords_num; } else { - BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph"); } } @@ -631,7 +625,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, } if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) && (csmd->bind_coords == NULL)) { - BKE_modifier_set_error(md, "Bind data required"); + BKE_modifier_set_error(ob, md, "Bind data required"); goto error; } @@ -639,14 +633,14 @@ static void correctivesmooth_modifier_do(ModifierData *md, if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { if (csmd->bind_coords_num != numVerts) { BKE_modifier_set_error( - md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts); + ob, md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts); goto error; } } else { /* MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO */ if (ob->type != OB_MESH) { - BKE_modifier_set_error(md, "Object is not a mesh"); + BKE_modifier_set_error(ob, md, "Object is not a mesh"); goto error; } else { @@ -654,7 +648,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, if (me_numVerts != numVerts) { BKE_modifier_set_error( - md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); + ob, md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); goto error; } } @@ -823,7 +817,7 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md) const CorrectiveSmoothModifierData *csmd = (const CorrectiveSmoothModifierData *)md; if (csmd->bind_coords) { - BLO_write_float3_array(writer, (int)csmd->bind_coords_num, (float *)csmd->bind_coords); + BLO_write_float3_array(writer, csmd->bind_coords_num, (float *)csmd->bind_coords); } } @@ -844,8 +838,10 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = { /* name */ "CorrectiveSmooth", /* structName */ "CorrectiveSmoothModifierData", /* structSize */ sizeof(CorrectiveSmoothModifierData), + /* srna */ &RNA_CorrectiveSmoothModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_SMOOTH, /* copyData */ copyData, @@ -865,7 +861,6 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index ccbe8ff94d8..bed53cb0f51 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -60,7 +61,9 @@ static void initData(ModifierData *md) { CurveModifierData *cmd = (CurveModifierData *)md; - cmd->defaxis = MOD_CURVE_POSX; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(cmd, modifier)); + + MEMCPY_STRUCT_AFTER(cmd, DNA_struct_default_get(CurveModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -87,11 +90,11 @@ static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED return !cmd->object || cmd->object->type != OB_CURVE; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { CurveModifierData *cmd = (CurveModifierData *)md; - walk(userData, ob, &cmd->object, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&cmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -218,9 +221,11 @@ ModifierTypeInfo modifierType_Curve = { /* name */ "Curve", /* structName */ "CurveModifierData", /* structSize */ sizeof(CurveModifierData), + /* srna */ &RNA_CurveModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_CURVE, /* copyData */ BKE_modifier_copydata_generic, @@ -240,8 +245,7 @@ ModifierTypeInfo modifierType_Curve = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 6d89b76c9f7..d4c941d144d 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -122,10 +122,10 @@ static bool dependsOnNormals(ModifierData *md) return false; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { DataTransferModifierData *dtmd = (DataTransferModifierData *)md; - walk(userData, ob, &dtmd->ob_source, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&dtmd->ob_source, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -198,7 +198,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * (dtmd->data_types & DT_TYPES_AFFECT_MESH)) { /* We need to duplicate data here, otherwise setting custom normals, edges' sharpness, etc., * could modify org mesh, see T43671. */ - BKE_id_copy_ex(NULL, &me_mod->id, (ID **)&result, LIB_ID_COPY_LOCALIZE); + result = (Mesh *)BKE_id_copy_ex(NULL, &me_mod->id, NULL, LIB_ID_COPY_LOCALIZE); } BKE_reports_init(&reports, RPT_STORE); @@ -232,16 +232,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (BKE_reports_contain(&reports, RPT_ERROR)) { const char *report_str = BKE_reports_string(&reports, RPT_ERROR); - BKE_modifier_set_error(md, "%s", report_str); + BKE_modifier_set_error(ctx->object, md, "%s", report_str); MEM_freeN((void *)report_str); } else if ((dtmd->data_types & DT_TYPE_LNOR) && !(me->flag & ME_AUTOSMOOTH)) { - BKE_modifier_set_error((ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error( + ctx->object, (ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); } else if (result->totvert > HIGH_POLY_WARNING || ((Mesh *)(ob_source->data))->totvert > HIGH_POLY_WARNING) { BKE_modifier_set_error( - md, "Source or destination object has a high polygon count, computation might be slow"); + ctx->object, + md, + "Source or destination object has a high polygon count, computation might be slow"); } return result; @@ -264,11 +267,18 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(sub, ptr, "use_object_transform", 0, "", ICON_ORIENTATION_GLOBAL); uiItemR(layout, ptr, "mix_mode", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "mix_factor", 0, NULL, ICON_NONE); + + row = uiLayoutRow(layout, false); + uiLayoutSetActive(row, + !ELEM(RNA_enum_get(ptr, "mix_mode"), + CDT_MIX_NOMIX, + CDT_MIX_REPLACE_ABOVE_THRESHOLD, + CDT_MIX_REPLACE_BELOW_THRESHOLD)); + uiItemR(row, ptr, "mix_factor", 0, NULL, ICON_NONE); modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); - uiItemO(layout, "Generate Data Layers", ICON_NONE, "OBJECT_OT_datalayout_transfer"); + uiItemO(layout, IFACE_("Generate Data Layers"), ICON_NONE, "OBJECT_OT_datalayout_transfer"); modifier_panel_end(layout, ptr); } @@ -470,9 +480,11 @@ ModifierTypeInfo modifierType_DataTransfer = { /* name */ "DataTransfer", /* structName */ "DataTransferModifierData", /* structSize */ sizeof(DataTransferModifierData), + /* srna */ &RNA_DataTransferModifier, /* type */ eModifierTypeType_NonGeometrical, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, + /* icon */ ICON_MOD_DATA_TRANSFER, /* copyData */ BKE_modifier_copydata_generic, @@ -492,8 +504,7 @@ ModifierTypeInfo modifierType_DataTransfer = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 72a868cc6a7..10ed4f8d80b 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -63,9 +64,9 @@ static void initData(ModifierData *md) { DecimateModifierData *dmd = (DecimateModifierData *)md; - dmd->percent = 1.0; - dmd->angle = DEG2RADF(5.0f); - dmd->defgrp_factor = 1.0; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(dmd, modifier)); + + MEMCPY_STRUCT_AFTER(dmd, DNA_struct_default_get(DecimateModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -139,7 +140,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } if (dmd->face_count <= 3) { - BKE_modifier_set_error(md, "Modifier requires more than 3 input faces"); + BKE_modifier_set_error(ctx->object, md, "Modifier requires more than 3 input faces"); return mesh; } @@ -234,13 +235,13 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) PointerRNA ob_ptr; PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); - uiLayoutSetPropSep(layout, true); - int decimate_type = RNA_enum_get(ptr, "decimate_type"); char count_info[32]; snprintf(count_info, 32, "%s: %d", IFACE_("Face Count"), RNA_int_get(ptr, "face_count")); - uiItemR(layout, ptr, "decimate_type", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "decimate_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + + uiLayoutSetPropSep(layout, true); if (decimate_type == MOD_DECIM_MODE_COLLAPSE) { uiItemR(layout, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE); @@ -267,7 +268,8 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) } else { /* decimate_type == MOD_DECIM_MODE_DISSOLVE. */ uiItemR(layout, ptr, "angle_limit", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "delimit", 0, NULL, ICON_NONE); + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "delimit", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "use_dissolve_boundaries", 0, NULL, ICON_NONE); } uiItemL(layout, count_info, ICON_NONE); @@ -284,8 +286,10 @@ ModifierTypeInfo modifierType_Decimate = { /* name */ "Decimate", /* structName */ "DecimateModifierData", /* structSize */ sizeof(DecimateModifierData), + /* srna */ &RNA_DecimateModifier, /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, + /* icon */ ICON_MOD_DECIM, /* copyData */ BKE_modifier_copydata_generic, @@ -305,7 +309,6 @@ ModifierTypeInfo modifierType_Decimate = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index caee077c475..d432559fcfa 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -28,6 +28,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -60,7 +61,7 @@ #include "MOD_ui_common.h" #include "MOD_util.h" -#include "RE_shader_ext.h" +#include "RE_texture.h" /* Displace */ @@ -68,11 +69,9 @@ static void initData(ModifierData *md) { DisplaceModifierData *dmd = (DisplaceModifierData *)md; - dmd->texture = NULL; - dmd->strength = 1; - dmd->direction = MOD_DISP_DIR_NOR; - dmd->midlevel = 0.5; - dmd->space = MOD_DISP_SPACE_LOCAL; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(dmd, modifier)); + + MEMCPY_STRUCT_AFTER(dmd, DNA_struct_default_get(DisplaceModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -113,20 +112,12 @@ static bool dependsOnNormals(ModifierData *md) return ELEM(dmd->direction, MOD_DISP_DIR_NOR, MOD_DISP_DIR_CLNOR); } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) -{ - DisplaceModifierData *dmd = (DisplaceModifierData *)md; - - walk(userData, ob, &dmd->map_object, IDWALK_CB_NOP); -} - static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { DisplaceModifierData *dmd = (DisplaceModifierData *)md; walk(userData, ob, (ID **)&dmd->texture, IDWALK_CB_USER); - - foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); + walk(userData, ob, (ID **)&dmd->map_object, IDWALK_CB_NOP); } static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) @@ -502,8 +493,10 @@ ModifierTypeInfo modifierType_Displace = { /* name */ "Displace", /* structName */ "DisplaceModifierData", /* structSize */ sizeof(DisplaceModifierData), + /* srna */ &RNA_DisplaceModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_DISPLACE, /* copyData */ BKE_modifier_copydata_generic, @@ -523,7 +516,6 @@ ModifierTypeInfo modifierType_Displace = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index 440b4677411..b69179f464d 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -19,12 +19,14 @@ */ #include <stddef.h> +#include <string.h> #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_dynamicpaint_types.h" #include "DNA_mesh_types.h" #include "DNA_object_force_types.h" @@ -57,9 +59,9 @@ static void initData(ModifierData *md) { DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; - pmd->canvas = NULL; - pmd->brush = NULL; - pmd->type = MOD_DYNAMICPAINT_TYPE_CANVAS; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(pmd, modifier)); + + MEMCPY_STRUCT_AFTER(pmd, DNA_struct_default_get(DynamicPaintModifierData), modifier); } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -203,10 +205,12 @@ ModifierTypeInfo modifierType_DynamicPaint = { /* name */ "Dynamic Paint", /* structName */ "DynamicPaintModifierData", /* structSize */ sizeof(DynamicPaintModifierData), + /* srna */ &RNA_DynamicPaintModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_UsesPointCache | eModifierTypeFlag_Single | eModifierTypeFlag_UsesPreview, + /* icon */ ICON_MOD_DYNAMICPAINT, /* copyData */ copyData, @@ -226,7 +230,6 @@ ModifierTypeInfo modifierType_DynamicPaint = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, /* freeRuntimeData */ freeRuntimeData, diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 2699896ac67..882d080c08d 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -32,6 +32,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" @@ -119,9 +120,9 @@ static void initData(ModifierData *md) { EdgeSplitModifierData *emd = (EdgeSplitModifierData *)md; - /* default to 30-degree split angle, sharpness from both angle & flag */ - emd->split_angle = DEG2RADF(30.0f); - emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(emd, modifier)); + + MEMCPY_STRUCT_AFTER(emd, DNA_struct_default_get(EdgeSplitModifierData), modifier); } static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) @@ -167,10 +168,12 @@ ModifierTypeInfo modifierType_EdgeSplit = { /* name */ "EdgeSplit", /* structName */ "EdgeSplitModifierData", /* structSize */ sizeof(EdgeSplitModifierData), + /* srna */ &RNA_EdgeSplitModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_EDGESPLIT, /* copyData */ BKE_modifier_copydata_generic, @@ -190,7 +193,6 @@ ModifierTypeInfo modifierType_EdgeSplit = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 0858fe9510b..d5e065ad321 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -30,6 +30,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -64,8 +65,9 @@ static void initData(ModifierData *md) { ExplodeModifierData *emd = (ExplodeModifierData *)md; - emd->facepa = NULL; - emd->flag |= eExplodeFlag_Unborn + eExplodeFlag_Alive + eExplodeFlag_Dead; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(emd, modifier)); + + MEMCPY_STRUCT_AFTER(emd, DNA_struct_default_get(ExplodeModifierData), modifier); } static void freeData(ModifierData *md) { @@ -1240,8 +1242,10 @@ ModifierTypeInfo modifierType_Explode = { /* name */ "Explode", /* structName */ "ExplodeModifierData", /* structSize */ sizeof(ExplodeModifierData), + /* srna */ &RNA_ExplodeModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh, + /* icon */ ICON_MOD_EXPLODE, /* copyData */ copyData, /* deformVerts */ NULL, @@ -1260,7 +1264,6 @@ ModifierTypeInfo modifierType_Explode = { /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c index d9bc78df527..6dc4fe79f88 100644 --- a/source/blender/modifiers/intern/MOD_fluid.c +++ b/source/blender/modifiers/intern/MOD_fluid.c @@ -225,8 +225,10 @@ ModifierTypeInfo modifierType_Fluid = { /* name */ "Fluid", /* structName */ "FluidModifierData", /* structSize */ sizeof(FluidModifierData), + /* srna */ &RNA_FluidModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_Single, + /* icon */ ICON_MOD_FLUIDSIM, /* copyData */ copyData, @@ -246,7 +248,6 @@ ModifierTypeInfo modifierType_Fluid = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 94a9a922ff7..e0c362171f2 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -28,6 +28,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -63,10 +64,11 @@ static void initData(ModifierData *md) { HookModifierData *hmd = (HookModifierData *)md; - hmd->force = 1.0; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(hmd, modifier)); + + MEMCPY_STRUCT_AFTER(hmd, DNA_struct_default_get(HookModifierData), modifier); + hmd->curfalloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - hmd->falloff_type = eHook_Falloff_Smooth; - hmd->flag = 0; } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -117,11 +119,11 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return !hmd->object; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { HookModifierData *hmd = (HookModifierData *)md; - walk(userData, ob, &hmd->object, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&hmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -490,11 +492,11 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) if (RNA_enum_get(&ob_ptr, "mode") == OB_MODE_EDIT) { row = uiLayoutRow(layout, true); - uiItemO(row, "Reset", ICON_NONE, "OBJECT_OT_hook_reset"); - uiItemO(row, "Recenter", ICON_NONE, "OBJECT_OT_hook_recenter"); + uiItemO(row, IFACE_("Reset"), ICON_NONE, "OBJECT_OT_hook_reset"); + uiItemO(row, IFACE_("Recenter"), ICON_NONE, "OBJECT_OT_hook_recenter"); row = uiLayoutRow(layout, true); - uiItemO(row, "Select", ICON_NONE, "OBJECT_OT_hook_select"); - uiItemO(row, "Assign", ICON_NONE, "OBJECT_OT_hook_assign"); + uiItemO(row, IFACE_("Select"), ICON_NONE, "OBJECT_OT_hook_select"); + uiItemO(row, IFACE_("Assign"), ICON_NONE, "OBJECT_OT_hook_assign"); } modifier_panel_end(layout, ptr); @@ -558,9 +560,11 @@ ModifierTypeInfo modifierType_Hook = { /* name */ "Hook", /* structName */ "HookModifierData", /* structSize */ sizeof(HookModifierData), + /* srna */ &RNA_HookModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_HOOK, /* copyData */ copyData, /* deformVerts */ deformVerts, @@ -579,8 +583,7 @@ ModifierTypeInfo modifierType_Hook = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index 8c297f11f7d..a484b4d8147 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -31,6 +31,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_screen_types.h" @@ -665,8 +666,7 @@ static void LaplacianDeformModifier_do( sysdif = isSystemDifferent(lmd, ob, mesh, numVerts); sys = lmd->cache_system; if (sysdif) { - if (sysdif == LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS || - sysdif == LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP) { + if (ELEM(sysdif, LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS, LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP)) { filevertexCos = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "TempModDeformCoordinates"); memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * numVerts); MEM_SAFE_FREE(lmd->vertexco); @@ -683,14 +683,15 @@ static void LaplacianDeformModifier_do( else { if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) { BKE_modifier_set_error( - &lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts); + ob, &lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) { BKE_modifier_set_error( - &lmd->modifier, "Edges changed from %d to %d", sys->total_edges, mesh->totedge); + ob, &lmd->modifier, "Edges changed from %d to %d", sys->total_edges, mesh->totedge); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) { - BKE_modifier_set_error(&lmd->modifier, + BKE_modifier_set_error(ob, + &lmd->modifier, "Vertex group '%s' is not valid, or maybe empty", sys->anchor_grp_name); } @@ -703,8 +704,10 @@ static void LaplacianDeformModifier_do( } else { if (!isValidVertexGroup(lmd, ob, mesh)) { - BKE_modifier_set_error( - &lmd->modifier, "Vertex group '%s' is not valid, or maybe empty", lmd->anchor_grp_name); + BKE_modifier_set_error(ob, + &lmd->modifier, + "Vertex group '%s' is not valid, or maybe empty", + lmd->anchor_grp_name); lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND; } else if (lmd->total_verts > 0 && lmd->total_verts == numVerts) { @@ -724,19 +727,17 @@ static void LaplacianDeformModifier_do( } } if (sys && sys->is_matrix_computed && !sys->has_solution) { - BKE_modifier_set_error(&lmd->modifier, "The system did not find a solution"); + BKE_modifier_set_error(ob, &lmd->modifier, "The system did not find a solution"); } } static void initData(ModifierData *md) { LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md; - lmd->anchor_grp_name[0] = '\0'; - lmd->total_verts = 0; - lmd->repeat = 1; - lmd->vertexco = NULL; - lmd->cache_system = NULL; - lmd->flag = 0; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(lmd, modifier)); + + MEMCPY_STRUCT_AFTER(lmd, DNA_struct_default_get(LaplacianDeformModifierData), modifier); } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -875,8 +876,10 @@ ModifierTypeInfo modifierType_LaplacianDeform = { /* name */ "LaplacianDeform", /* structName */ "LaplacianDeformModifierData", /* structSize */ sizeof(LaplacianDeformModifierData), + /* srna */ &RNA_LaplacianDeformModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_MESHDEFORM, /* copyData */ copyData, /* deformVerts */ deformVerts, @@ -895,7 +898,6 @@ ModifierTypeInfo modifierType_LaplacianDeform = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 4c438256661..d51f95bd18d 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -81,7 +82,7 @@ struct BLaplacianSystem { typedef struct BLaplacianSystem LaplacianSystem; static void required_data_mask(Object *ob, ModifierData *md, CustomData_MeshMasks *r_cddata_masks); -static bool is_disabled(const struct Scene *UNUSED(scene), ModifierData *md, bool useRenderParams); +static bool is_disabled(const struct Scene *scene, ModifierData *md, bool useRenderParams); static float compute_volume(const float center[3], float (*vertexCos)[3], const MPoly *mpoly, @@ -497,12 +498,10 @@ static void laplaciansmoothModifier_do( static void init_data(ModifierData *md) { LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *)md; - smd->lambda = 0.01f; - smd->lambda_border = 0.01f; - smd->repeat = 1; - smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | - MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME | MOD_LAPLACIANSMOOTH_NORMALIZED; - smd->defgrp_name[0] = '\0'; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier)); + + MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(LaplacianSmoothModifierData), modifier); } static bool is_disabled(const struct Scene *UNUSED(scene), @@ -622,8 +621,10 @@ ModifierTypeInfo modifierType_LaplacianSmooth = { /* name */ "LaplacianSmooth", /* structName */ "LaplacianSmoothModifierData", /* structSize */ sizeof(LaplacianSmoothModifierData), + /* srna */ &RNA_LaplacianSmoothModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_SMOOTH, /* copyData */ BKE_modifier_copydata_generic, @@ -643,7 +644,6 @@ ModifierTypeInfo modifierType_LaplacianSmooth = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 75c34b3cc89..5aadc171394 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" @@ -55,7 +56,10 @@ static void initData(ModifierData *md) { LatticeModifierData *lmd = (LatticeModifierData *)md; - lmd->strength = 1.0f; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(lmd, modifier)); + + MEMCPY_STRUCT_AFTER(lmd, DNA_struct_default_get(LatticeModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -84,11 +88,11 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return !lmd->object || lmd->object->type != OB_LATTICE; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { LatticeModifierData *lmd = (LatticeModifierData *)md; - walk(userData, ob, &lmd->object, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&lmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -174,9 +178,11 @@ ModifierTypeInfo modifierType_Lattice = { /* name */ "Lattice", /* structName */ "LatticeModifierData", /* structSize */ sizeof(LatticeModifierData), + /* srna */ &RNA_LatticeModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_LATTICE, /* copyData */ BKE_modifier_copydata_generic, @@ -196,8 +202,7 @@ ModifierTypeInfo modifierType_Lattice = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 52d2bd11748..92ee5a84df9 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -31,6 +31,7 @@ #include "BLT_translation.h" #include "DNA_armature_types.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -68,6 +69,15 @@ using blender::MutableSpan; using blender::Span; using blender::Vector; +static void initData(ModifierData *md) +{ + MaskModifierData *mmd = (MaskModifierData *)md; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mmd, modifier)); + + MEMCPY_STRUCT_AFTER(mmd, DNA_struct_default_get(MaskModifierData), modifier); +} + static void requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md), CustomData_MeshMasks *r_cddata_masks) @@ -75,10 +85,10 @@ static void requiredDataMask(Object *UNUSED(ob), r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { MaskModifierData *mmd = reinterpret_cast<MaskModifierData *>(md); - walk(userData, ob, &mmd->ob_arm, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&mmd->ob_arm, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -312,7 +322,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Return empty or input mesh when there are no vertex groups. */ MDeformVert *dvert = (MDeformVert *)CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT); - if (dvert == NULL) { + if (dvert == nullptr) { return invert_mask ? mesh : BKE_mesh_new_nomain_from_template(mesh, 0, 0, 0, 0, 0); } @@ -408,13 +418,13 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) int mode = RNA_enum_get(ptr, "mode"); - uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); uiLayoutSetPropSep(layout, true); if (mode == MOD_MASK_MODE_ARM) { row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "armature", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "armature", 0, nullptr, ICON_NONE); sub = uiLayoutRow(row, true); uiLayoutSetPropDecorate(sub, false); uiItemR(sub, ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT); @@ -423,7 +433,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr); } - uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "threshold", 0, nullptr, ICON_NONE); modifier_panel_end(layout, ptr); } @@ -437,34 +447,35 @@ ModifierTypeInfo modifierType_Mask = { /* name */ "Mask", /* structName */ "MaskModifierData", /* structSize */ sizeof(MaskModifierData), + /* srna */ &RNA_MaskModifier, /* type */ eModifierTypeType_Nonconstructive, /* flags */ (ModifierTypeFlag)(eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode), + /* icon */ ICON_MOD_MASK, /* copyData */ BKE_modifier_copydata_generic, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, + /* deformVerts */ nullptr, + /* deformMatrices */ nullptr, + /* deformVertsEM */ nullptr, + /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, - /* modifyPointCloud */ NULL, - /* modifyVolume */ NULL, + /* modifyHair */ nullptr, + /* modifyPointCloud */ nullptr, + /* modifyVolume */ nullptr, - /* initData */ NULL, + /* initData */ initData, /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, + /* freeData */ nullptr, /* isDisabled */ isDisabled, /* updateDepsgraph */ updateDepsgraph, - /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, - /* freeRuntimeData */ NULL, + /* dependsOnTime */ nullptr, + /* dependsOnNormals */ nullptr, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ nullptr, + /* freeRuntimeData */ nullptr, /* panelRegister */ panelRegister, - /* blendWrite */ NULL, - /* blendRead */ NULL, + /* blendWrite */ nullptr, + /* blendRead */ nullptr, }; diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc new file mode 100644 index 00000000000..61d556a64af --- /dev/null +++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc @@ -0,0 +1,315 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup modifiers + */ + +#include <vector> + +#include "BKE_lib_query.h" +#include "BKE_mesh_runtime.h" +#include "BKE_mesh_wrapper.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_volume.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_volume_types.h" + +#include "DEG_depsgraph.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "BLO_read_write.h" + +#include "MEM_guardedalloc.h" + +#include "MOD_modifiertypes.h" +#include "MOD_ui_common.h" + +#include "BLI_float4x4.hh" +#include "BLI_index_range.hh" +#include "BLI_span.hh" + +#include "RNA_access.h" + +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +# include <openvdb/tools/MeshToVolume.h> +#endif + +#ifdef WITH_OPENVDB +namespace blender { +/* This class follows the MeshDataAdapter interface from openvdb. */ +class OpenVDBMeshAdapter { + private: + Span<MVert> vertices_; + Span<MLoop> loops_; + Span<MLoopTri> looptris_; + float4x4 transform_; + + public: + OpenVDBMeshAdapter(Mesh &mesh, float4x4 transform) + : vertices_(mesh.mvert, mesh.totvert), + loops_(mesh.mloop, mesh.totloop), + transform_(transform) + { + const MLoopTri *looptries = BKE_mesh_runtime_looptri_ensure(&mesh); + const int looptries_len = BKE_mesh_runtime_looptri_len(&mesh); + looptris_ = Span(looptries, looptries_len); + } + + size_t polygonCount() const + { + return static_cast<size_t>(looptris_.size()); + } + + size_t pointCount() const + { + return static_cast<size_t>(vertices_.size()); + } + + size_t vertexCount(size_t UNUSED(polygon_index)) const + { + /* All polygons are triangles. */ + return 3; + } + + void getIndexSpacePoint(size_t polygon_index, size_t vertex_index, openvdb::Vec3d &pos) const + { + const MLoopTri &looptri = looptris_[polygon_index]; + const MVert &vertex = vertices_[loops_[looptri.tri[vertex_index]].v]; + const float3 transformed_co = transform_ * float3(vertex.co); + pos = &transformed_co.x; + } +}; +} // namespace blender +#endif + +static void initData(ModifierData *md) +{ + MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md); + mvmd->object = nullptr; + mvmd->resolution_mode = MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT; + mvmd->voxel_size = 0.1f; + mvmd->voxel_amount = 32; + mvmd->fill_volume = true; + mvmd->interior_band_width = 0.1f; + mvmd->exterior_band_width = 0.1f; + mvmd->density = 1.0f; +} + +static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +{ + MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md); + DEG_add_modifier_to_transform_relation(ctx->node, "Mesh to Volume Modifier"); + if (mvmd->object) { + DEG_add_object_relation( + ctx->node, mvmd->object, DEG_OB_COMP_GEOMETRY, "Mesh to Volume Modifier"); + DEG_add_object_relation( + ctx->node, mvmd->object, DEG_OB_COMP_TRANSFORM, "Mesh to Volume Modifier"); + } +} + +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md); + walk(userData, ob, (ID **)&mvmd->object, IDWALK_CB_NOP); +} + +static void panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, nullptr); + MeshToVolumeModifierData *mvmd = static_cast<MeshToVolumeModifierData *>(ptr->data); + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + + uiItemR(layout, ptr, "object", 0, nullptr, ICON_NONE); + uiItemR(layout, ptr, "density", 0, nullptr, ICON_NONE); + + { + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "use_fill_volume", 0, nullptr, ICON_NONE); + uiItemR(col, ptr, "exterior_band_width", 0, nullptr, ICON_NONE); + + uiLayout *subcol = uiLayoutColumn(col, false); + uiLayoutSetActive(subcol, !mvmd->fill_volume); + uiItemR(subcol, ptr, "interior_band_width", 0, nullptr, ICON_NONE); + } + { + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "resolution_mode", 0, nullptr, ICON_NONE); + if (mvmd->resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT) { + uiItemR(col, ptr, "voxel_amount", 0, nullptr, ICON_NONE); + } + else { + uiItemR(col, ptr, "voxel_size", 0, nullptr, ICON_NONE); + } + } + + modifier_panel_end(layout, ptr); +} + +static void panelRegister(ARegionType *region_type) +{ + modifier_panel_register(region_type, eModifierType_MeshToVolume, panel_draw); +} + +#ifdef WITH_OPENVDB +static float compute_voxel_size(const ModifierEvalContext *ctx, + const MeshToVolumeModifierData *mvmd, + const blender::float4x4 &transform) +{ + using namespace blender; + + float volume_simplify = BKE_volume_simplify_factor(ctx->depsgraph); + if (volume_simplify == 0.0f) { + return 0.0f; + } + + if (mvmd->resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE) { + return mvmd->voxel_size / volume_simplify; + } + if (mvmd->voxel_amount <= 0) { + return 0; + } + /* Compute the voxel size based on the desired number of voxels and the approximated bounding box + * of the volume. */ + const BoundBox *bb = BKE_object_boundbox_get(mvmd->object); + const float diagonal = float3::distance(transform * float3(bb->vec[6]), + transform * float3(bb->vec[0])); + const float approximate_volume_side_length = diagonal + mvmd->exterior_band_width * 2.0f; + const float voxel_size = approximate_volume_side_length / mvmd->voxel_amount / volume_simplify; + return voxel_size; +} +#endif + +static Volume *modifyVolume(ModifierData *md, const ModifierEvalContext *ctx, Volume *input_volume) +{ +#ifdef WITH_OPENVDB + using namespace blender; + + MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md); + Object *object_to_convert = mvmd->object; + + if (object_to_convert == nullptr) { + return input_volume; + } + Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_to_convert, false); + if (mesh == nullptr) { + return input_volume; + } + BKE_mesh_wrapper_ensure_mdata(mesh); + + const float4x4 mesh_to_own_object_space_transform = float4x4(ctx->object->imat) * + float4x4(object_to_convert->obmat); + const float voxel_size = compute_voxel_size(ctx, mvmd, mesh_to_own_object_space_transform); + if (voxel_size == 0.0f) { + return input_volume; + } + + float4x4 mesh_to_index_space_transform; + scale_m4_fl(mesh_to_index_space_transform.values, 1.0f / voxel_size); + mul_m4_m4_post(mesh_to_index_space_transform.values, mesh_to_own_object_space_transform.values); + /* Better align generated grid with the source mesh. */ + add_v3_fl(mesh_to_index_space_transform.values[3], -0.5f); + + OpenVDBMeshAdapter mesh_adapter{*mesh, mesh_to_index_space_transform}; + + /* Convert the bandwidths from object in index space. */ + const float exterior_band_width = MAX2(0.001f, mvmd->exterior_band_width / voxel_size); + const float interior_band_width = MAX2(0.001f, mvmd->interior_band_width / voxel_size); + + openvdb::FloatGrid::Ptr new_grid; + if (mvmd->fill_volume) { + /* Setting the interior bandwidth to FLT_MAX, will make it fill the entire volume. */ + new_grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>( + mesh_adapter, {}, exterior_band_width, FLT_MAX); + } + else { + new_grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>( + mesh_adapter, {}, exterior_band_width, interior_band_width); + } + + /* Create a new volume object and add the density grid. */ + Volume *volume = BKE_volume_new_for_eval(input_volume); + VolumeGrid *c_density_grid = BKE_volume_grid_add(volume, "density", VOLUME_GRID_FLOAT); + openvdb::FloatGrid::Ptr density_grid = openvdb::gridPtrCast<openvdb::FloatGrid>( + BKE_volume_grid_openvdb_for_write(volume, c_density_grid, false)); + + /* Merge the generated grid into the density grid. Should be cheap because density_grid has just + * been created as well. */ + density_grid->merge(*new_grid); + + /* Change transform so that the index space is correctly transformed to object space. */ + density_grid->transform().postScale(voxel_size); + + /* Give each grid cell a fixed density for now. */ + openvdb::tools::foreach ( + density_grid->beginValueOn(), + [&](const openvdb::FloatGrid::ValueOnIter &iter) { iter.setValue(mvmd->density); }); + + return volume; + +#else + UNUSED_VARS(md); + BKE_modifier_set_error(ctx->object, md, "Compiled without OpenVDB"); + return input_volume; +#endif +} + +ModifierTypeInfo modifierType_MeshToVolume = { + /* name */ "Mesh to Volume", + /* structName */ "MeshToVolumeModifierData", + /* structSize */ sizeof(MeshToVolumeModifierData), + /* srna */ &RNA_MeshToVolumeModifier, + /* type */ eModifierTypeType_Constructive, + /* flags */ static_cast<ModifierTypeFlag>(0), + /* icon */ ICON_VOLUME_DATA, /* TODO: Use correct icon. */ + + /* copyData */ BKE_modifier_copydata_generic, + + /* deformVerts */ nullptr, + /* deformMatrices */ nullptr, + /* deformVertsEM */ nullptr, + /* deformMatricesEM */ nullptr, + /* modifyMesh */ nullptr, + /* modifyHair */ nullptr, + /* modifyPointCloud */ nullptr, + /* modifyVolume */ modifyVolume, + + /* initData */ initData, + /* requiredDataMask */ nullptr, + /* freeData */ nullptr, + /* isDisabled */ nullptr, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ nullptr, + /* dependsOnNormals */ nullptr, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ nullptr, + /* freeRuntimeData */ nullptr, + /* panelRegister */ panelRegister, + /* blendWrite */ nullptr, + /* blendRead */ nullptr, +}; diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 456ece7704b..b808d738fe8 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -28,6 +28,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -57,16 +58,9 @@ static void initData(ModifierData *md) { MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; - mcmd->flag = 0; - mcmd->type = MOD_MESHCACHE_TYPE_MDD; - mcmd->interp = MOD_MESHCACHE_INTERP_LINEAR; - mcmd->frame_scale = 1.0f; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mcmd, modifier)); - mcmd->factor = 1.0f; - - /* (Y, Z). Blender default */ - mcmd->forward_axis = 1; - mcmd->up_axis = 2; + MEMCPY_STRUCT_AFTER(mcmd, DNA_struct_default_get(MeshCacheModifierData), modifier); } static bool dependsOnTime(ModifierData *md) @@ -177,13 +171,13 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* we could support any object type */ if (UNLIKELY(ob->type != OB_MESH)) { - BKE_modifier_set_error(&mcmd->modifier, "'Integrate' only valid for Mesh objects"); + BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' only valid for Mesh objects"); } else if (UNLIKELY(me->totvert != numVerts)) { - BKE_modifier_set_error(&mcmd->modifier, "'Integrate' original mesh vertex mismatch"); + BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' original mesh vertex mismatch"); } else if (UNLIKELY(me->totpoly == 0)) { - BKE_modifier_set_error(&mcmd->modifier, "'Integrate' requires faces"); + BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' requires faces"); } else { /* the moons align! */ @@ -222,7 +216,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* -------------------------------------------------------------------- */ /* Apply the transformation matrix (if needed) */ if (UNLIKELY(err_str)) { - BKE_modifier_set_error(&mcmd->modifier, "%s", err_str); + BKE_modifier_set_error(ob, &mcmd->modifier, "%s", err_str); } else if (ok) { bool use_matrix = false; @@ -380,9 +374,11 @@ ModifierTypeInfo modifierType_MeshCache = { /* name */ "MeshCache", /* structName */ "MeshCacheModifierData", /* structSize */ sizeof(MeshCacheModifierData), + /* srna */ &RNA_MeshCacheModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_MESHDEFORM, /* TODO: Use correct icon. */ /* copyData */ BKE_modifier_copydata_generic, @@ -402,7 +398,6 @@ ModifierTypeInfo modifierType_MeshCache = { /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c index 120d1d6d71a..0ef9f26f1d7 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c +++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c @@ -81,7 +81,7 @@ static bool meshcache_read_pc2_head(FILE *fp, } /** - * Gets the index frange and factor + * Gets the index range and factor * * currently same as for MDD */ diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 16b72bb358a..0e530312238 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -28,6 +28,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -68,7 +69,9 @@ static void initData(ModifierData *md) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; - mmd->gridsize = 5; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mmd, modifier)); + + MEMCPY_STRUCT_AFTER(mmd, DNA_struct_default_get(MeshDeformModifierData), modifier); } static void freeData(ModifierData *md) @@ -160,11 +163,11 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return !mmd->object || mmd->object->type != OB_MESH; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; - walk(userData, ob, &mmd->object, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -370,7 +373,7 @@ static void meshdeformModifier_do(ModifierData *md, Object *ob_target = mmd->object; cagemesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); if (cagemesh == NULL) { - BKE_modifier_set_error(md, "Cannot get mesh from cage object"); + BKE_modifier_set_error(ctx->object, md, "Cannot get mesh from cage object"); return; } @@ -385,7 +388,7 @@ static void meshdeformModifier_do(ModifierData *md, if (!mmd->bindcagecos) { /* progress bar redraw can make this recursive .. */ if (!DEG_is_active(ctx->depsgraph)) { - BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph"); goto finally; } if (!recursive_bind_sentinel) { @@ -402,16 +405,16 @@ static void meshdeformModifier_do(ModifierData *md, totcagevert = BKE_mesh_wrapper_vert_len(cagemesh); if (mmd->totvert != totvert) { - BKE_modifier_set_error(md, "Vertices changed from %d to %d", mmd->totvert, totvert); + BKE_modifier_set_error(ob, md, "Vertices changed from %d to %d", mmd->totvert, totvert); goto finally; } else if (mmd->totcagevert != totcagevert) { BKE_modifier_set_error( - md, "Cage vertices changed from %d to %d", mmd->totcagevert, totcagevert); + ob, md, "Cage vertices changed from %d to %d", mmd->totcagevert, totcagevert); goto finally; } else if (mmd->bindcagecos == NULL) { - BKE_modifier_set_error(md, "Bind data missing"); + BKE_modifier_set_error(ob, md, "Bind data missing"); goto finally; } @@ -629,9 +632,11 @@ ModifierTypeInfo modifierType_MeshDeform = { /* name */ "MeshDeform", /* structName */ "MeshDeformModifierData", /* structSize */ sizeof(MeshDeformModifierData), + /* srna */ &RNA_MeshDeformModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_MESHDEFORM, /* copyData */ copyData, @@ -651,8 +656,7 @@ ModifierTypeInfo modifierType_MeshDeform = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index dc465ee941c..73106b2e816 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -26,6 +26,7 @@ #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" @@ -64,15 +65,9 @@ static void initData(ModifierData *md) { MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - mcmd->cache_file = NULL; - mcmd->object_path[0] = '\0'; - mcmd->read_flag = MOD_MESHSEQ_READ_ALL; - mcmd->velocity_scale = 1.0f; - mcmd->vertex_velocities = NULL; - mcmd->num_vertices = 0; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mcmd, modifier)); - mcmd->reader = NULL; - mcmd->reader_object_path[0] = '\0'; + MEMCPY_STRUCT_AFTER(mcmd, DNA_struct_default_get(MeshSeqCacheModifierData), modifier); } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -132,7 +127,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path); if (!mcmd->reader) { BKE_modifier_set_error( - md, "Could not create Alembic reader for file %s", cache_file->filepath); + ctx->object, md, "Could not create Alembic reader for file %s", cache_file->filepath); return mesh; } } @@ -153,11 +148,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * * 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. */ - BKE_id_copy_ex(NULL, - &mesh->id, - (ID **)&mesh, - LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | - LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW); + mesh = (Mesh *)BKE_id_copy_ex(NULL, + &mesh->id, + NULL, + LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW); } } @@ -175,7 +170,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } if (err_str) { - BKE_modifier_set_error(md, "%s", err_str); + BKE_modifier_set_error(ctx->object, md, "%s", err_str); } if (!ELEM(result, NULL, mesh) && (mesh != org_mesh)) { @@ -238,6 +233,7 @@ static void panel_draw(const bContext *C, Panel *panel) if (RNA_enum_get(&ob_ptr, "type") == OB_MESH) { uiItemR(layout, ptr, "read_data", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_vertex_interpolation", 0, NULL, ICON_NONE); } uiItemR(layout, ptr, "velocity_scale", 0, NULL, ICON_NONE); @@ -261,8 +257,10 @@ ModifierTypeInfo modifierType_MeshSequenceCache = { /* name */ "MeshSequenceCache", /* structName */ "MeshSeqCacheModifierData", /* structSize */ sizeof(MeshSeqCacheModifierData), + /* srna */ &RNA_MeshSequenceCacheModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, + /* icon */ ICON_MOD_MESHDEFORM, /* TODO: Use correct icon. */ /* copyData */ copyData, @@ -282,7 +280,6 @@ ModifierTypeInfo modifierType_MeshSequenceCache = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 75c92bfd815..9346f601981 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -25,6 +25,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -59,16 +60,16 @@ static void initData(ModifierData *md) { MirrorModifierData *mmd = (MirrorModifierData *)md; - mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP); - mmd->tolerance = 0.001; - mmd->mirror_ob = NULL; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mmd, modifier)); + + MEMCPY_STRUCT_AFTER(mmd, DNA_struct_default_get(MirrorModifierData), modifier); } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { MirrorModifierData *mmd = (MirrorModifierData *)md; - walk(userData, ob, &mmd->mirror_ob, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&mmd->mirror_ob, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -216,12 +217,14 @@ ModifierTypeInfo modifierType_Mirror = { /* name */ "Mirror", /* structName */ "MirrorModifierData", /* structSize */ sizeof(MirrorModifierData), + /* srna */ &RNA_MirrorModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs | /* this is only the case when 'MOD_MIR_VGROUP' is used */ eModifierTypeFlag_UsesPreview, + /* icon */ ICON_MOD_MIRROR, /* copyData */ BKE_modifier_copydata_generic, @@ -241,8 +244,7 @@ ModifierTypeInfo modifierType_Mirror = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index 9c7ab50cb61..9f99e036601 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -29,6 +29,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -68,16 +69,12 @@ static void initData(ModifierData *md) { MultiresModifierData *mmd = (MultiresModifierData *)md; - mmd->lvl = 0; - mmd->sculptlvl = 0; - mmd->renderlvl = 0; - mmd->totlvl = 0; - mmd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS; - mmd->quality = 4; - mmd->flags |= (eMultiresModifierFlag_UseCrease | eMultiresModifierFlag_ControlEdges); + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mmd, modifier)); + + MEMCPY_STRUCT_AFTER(mmd, DNA_struct_default_get(MultiresModifierData), modifier); /* Open subdivision panels by default. */ - md->ui_expand_flag = (1 << 0) | (1 << 1); + md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1; } static void requiredDataMask(Object *UNUSED(ob), @@ -219,7 +216,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * { Mesh *result = mesh; #if !defined(WITH_OPENSUBDIV) - BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv"); return result; #endif MultiresModifierData *mmd = (MultiresModifierData *)md; @@ -228,7 +225,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (subdiv_settings.level == 0) { return result; } - BKE_subdiv_settings_validate_for_mesh(&subdiv_settings, mesh); MultiresRuntimeData *runtime_data = multires_ensure_runtime(mmd); Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh); if (subdiv == NULL) { @@ -304,7 +300,7 @@ static void deformMatrices(ModifierData *md, { #if !defined(WITH_OPENSUBDIV) - BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv"); return; #endif @@ -325,7 +321,6 @@ static void deformMatrices(ModifierData *md, return; } - BKE_subdiv_settings_validate_for_mesh(&subdiv_settings, mesh); MultiresRuntimeData *runtime_data = multires_ensure_runtime(mmd); Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh); if (subdiv == NULL) { @@ -481,14 +476,14 @@ static void advanced_panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); - uiLayoutSetEnabled(layout, !has_displacement); + uiLayoutSetActive(layout, !has_displacement); - uiItemR(layout, ptr, "subdivision_type", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "quality", 0, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); - uiLayoutSetEnabled(col, true); + uiLayoutSetActive(col, true); uiItemR(col, ptr, "uv_smooth", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "boundary_smooth", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "use_creases", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "use_custom_normals", 0, NULL, ICON_NONE); @@ -510,9 +505,11 @@ ModifierTypeInfo modifierType_Multires = { /* name */ "Multires", /* structName */ "MultiresModifierData", /* structSize */ sizeof(MultiresModifierData), + /* srna */ &RNA_MultiresModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_RequiresOriginalData, + /* icon */ ICON_MOD_MULTIRES, /* copyData */ copyData, @@ -532,7 +529,6 @@ ModifierTypeInfo modifierType_Multires = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ freeRuntimeData, diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c index a84a10f4b6c..02307622d06 100644 --- a/source/blender/modifiers/intern/MOD_none.c +++ b/source/blender/modifiers/intern/MOD_none.c @@ -27,6 +27,10 @@ #include "MOD_modifiertypes.h" +#include "UI_resources.h" + +#include "RNA_access.h" + /* We only need to define isDisabled; because it always returns 1, * no other functions will be called */ @@ -42,8 +46,10 @@ ModifierTypeInfo modifierType_None = { /* name */ "None", /* structName */ "ModifierData", /* structSize */ sizeof(ModifierData), + /* srna */ &RNA_Modifier, /* type */ eModifierTypeType_None, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, + /* icon */ ICON_NONE, /* copyData */ NULL, @@ -63,7 +69,6 @@ ModifierTypeInfo modifierType_None = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 9962d3a55e0..0ec564d2e2d 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -29,6 +29,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -475,7 +476,15 @@ static bool is_valid_target(NormalEditModifierData *enmd) if ((enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) && enmd->target) { return true; } - BKE_modifier_set_error((ModifierData *)enmd, "Invalid target settings"); + return false; +} + +static bool is_valid_target_with_error(const Object *ob, NormalEditModifierData *enmd) +{ + if (is_valid_target(enmd)) { + return true; + } + BKE_modifier_set_error(ob, (ModifierData *)enmd, "Invalid target settings"); return false; } @@ -490,7 +499,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, (enmd->mix_limit == (float)M_PI)); /* Do not run that modifier at all if autosmooth is disabled! */ - if (!is_valid_target(enmd) || mesh->totloop == 0) { + if (!is_valid_target_with_error(ctx->object, enmd) || mesh->totloop == 0) { return mesh; } @@ -505,7 +514,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) #endif { - BKE_modifier_set_error((ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error( + ob, (ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties"); return mesh; } @@ -514,7 +524,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, /* We need to duplicate data here, otherwise setting custom normals * (which may also affect sharp edges) could * modify original mesh, see T43671. */ - BKE_id_copy_ex(NULL, &mesh->id, (ID **)&result, LIB_ID_COPY_LOCALIZE); + result = (Mesh *)BKE_id_copy_ex(NULL, &mesh->id, NULL, LIB_ID_COPY_LOCALIZE); } else { result = mesh; @@ -646,11 +656,9 @@ static void initData(ModifierData *md) { NormalEditModifierData *enmd = (NormalEditModifierData *)md; - enmd->mode = MOD_NORMALEDIT_MODE_RADIAL; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(enmd, modifier)); - enmd->mix_mode = MOD_NORMALEDIT_MIX_COPY; - enmd->mix_factor = 1.0f; - enmd->mix_limit = M_PI; + MEMCPY_STRUCT_AFTER(enmd, DNA_struct_default_get(NormalEditModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -672,11 +680,11 @@ static bool dependsOnNormals(ModifierData *UNUSED(md)) return true; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { NormalEditModifierData *enmd = (NormalEditModifierData *)md; - walk(userData, ob, &enmd->target, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&enmd->target, IDWALK_CB_NOP); } static bool isDisabled(const struct Scene *UNUSED(scene), @@ -782,9 +790,11 @@ ModifierTypeInfo modifierType_NormalEdit = { /* name */ "NormalEdit", /* structName */ "NormalEditModifierData", /* structSize */ sizeof(NormalEditModifierData), + /* srna */ &RNA_NormalEditModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_NORMALEDIT, /* copyData */ BKE_modifier_copydata_generic, @@ -804,8 +814,7 @@ ModifierTypeInfo modifierType_NormalEdit = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index ccd105f8f69..5aef497c0c4 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -30,6 +30,7 @@ #include "BLT_translation.h" #include "DNA_customdata_types.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -87,54 +88,17 @@ static void initData(ModifierData *md) #ifdef WITH_OCEANSIM OceanModifierData *omd = (OceanModifierData *)md; - /* Render resolution */ - omd->resolution = 7; - /* Display resolution for the non-render case */ - omd->viewport_resolution = 7; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(omd, modifier)); - omd->spatial_size = 50; - - omd->wave_alignment = 0.0; - omd->wind_velocity = 30.0; - - omd->damp = 0.5; - omd->smallest_wave = 0.01; - omd->wave_direction = 0.0; - omd->depth = 200.0; - - omd->wave_scale = 1.0; - - omd->chop_amount = 1.0; - - omd->foam_coverage = 0.0; - - omd->seed = 0; - omd->time = 1.0; - - omd->spectrum = MOD_OCEAN_SPECTRUM_PHILLIPS; - omd->sharpen_peak_jonswap = 0.0f; - omd->fetch_jonswap = 120.0f; - - omd->size = 1.0; - omd->repeat_x = 1; - omd->repeat_y = 1; + MEMCPY_STRUCT_AFTER(omd, DNA_struct_default_get(OceanModifierData), modifier); BKE_modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean"); - omd->cached = 0; - omd->bakestart = 1; - omd->bakeend = 250; - omd->oceancache = NULL; - omd->foam_fade = 0.98; - omd->foamlayername[0] = '\0'; /* layer name empty by default */ - omd->spraylayername[0] = '\0'; /* layer name empty by default */ - omd->ocean = BKE_ocean_add(); BKE_ocean_init_from_modifier(omd->ocean, omd, omd->viewport_resolution); simulate_ocean_modifier(omd); #else /* WITH_OCEANSIM */ - /* unused */ - (void)md; + UNUSED_VARS(md); #endif /* WITH_OCEANSIM */ } @@ -409,7 +373,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes BKE_mesh_ensure_normals(result); } else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) { - BKE_id_copy_ex(NULL, &mesh->id, (ID **)&result, LIB_ID_COPY_LOCALIZE); + result = (Mesh *)BKE_id_copy_ex(NULL, &mesh->id, NULL, LIB_ID_COPY_LOCALIZE); } cfra_for_cache = cfra_scene; @@ -758,9 +722,11 @@ ModifierTypeInfo modifierType_Ocean = { /* name */ "Ocean", /* structName */ "OceanModifierData", /* structSize */ sizeof(OceanModifierData), + /* srna */ &RNA_OceanModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_OCEAN, /* copyData */ copyData, /* deformMatrices_DM */ NULL, @@ -780,7 +746,6 @@ ModifierTypeInfo modifierType_Ocean = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 597a61c6c16..f660874a5ea 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -32,6 +32,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_screen_types.h" @@ -61,17 +62,9 @@ static void initData(ModifierData *md) { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; - pimd->flag = eParticleInstanceFlag_Parents | eParticleInstanceFlag_Unborn | - eParticleInstanceFlag_Alive | eParticleInstanceFlag_Dead; - pimd->psys = 1; - pimd->position = 1.0f; - pimd->axis = 2; - pimd->space = eParticleInstanceSpace_World; - pimd->particle_amount = 1.0f; - pimd->particle_offset = 0.0f; - - STRNCPY(pimd->index_layer_name, ""); - STRNCPY(pimd->value_layer_name, ""); + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(pimd, modifier)); + + MEMCPY_STRUCT_AFTER(pimd, DNA_struct_default_get(ParticleInstanceModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -144,11 +137,11 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; - walk(userData, ob, &pimd->ob, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&pimd->ob, IDWALK_CB_NOP); } static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p) @@ -671,9 +664,11 @@ ModifierTypeInfo modifierType_ParticleInstance = { /* name */ "ParticleInstance", /* structName */ "ParticleInstanceModifierData", /* structSize */ sizeof(ParticleInstanceModifierData), + /* srna */ &RNA_ParticleInstanceModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_PARTICLE_INSTANCE, /* copyData */ BKE_modifier_copydata_generic, @@ -693,8 +688,7 @@ ModifierTypeInfo modifierType_ParticleInstance = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index c2f411f5247..86480a17083 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -22,11 +22,13 @@ */ #include <stddef.h> +#include <string.h> #include "BLI_utildefines.h" #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_screen_types.h" @@ -54,10 +56,10 @@ static void initData(ModifierData *md) { ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; - psmd->psys = NULL; - psmd->mesh_final = NULL; - psmd->mesh_original = NULL; - psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(psmd, modifier)); + + MEMCPY_STRUCT_AFTER(psmd, DNA_struct_default_get(ParticleSystemModifierData), modifier); } static void freeData(ModifierData *md) { @@ -312,12 +314,14 @@ ModifierTypeInfo modifierType_ParticleSystem = { /* name */ "ParticleSystem", /* structName */ "ParticleSystemModifierData", /* structSize */ sizeof(ParticleSystemModifierData), + /* srna */ &RNA_ParticleSystemModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_UsesPointCache /* | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode */ , + /* icon */ ICON_MOD_PARTICLES, /* copyData */ copyData, @@ -337,7 +341,6 @@ ModifierTypeInfo modifierType_ParticleSystem = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index 7a58b985429..f8fc4ad658e 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -29,6 +29,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -49,7 +50,6 @@ #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" -#include <assert.h> #include <stdlib.h> #include <string.h> @@ -63,14 +63,9 @@ static void initData(ModifierData *md) { RemeshModifierData *rmd = (RemeshModifierData *)md; - rmd->scale = 0.9; - rmd->depth = 4; - rmd->hermite_num = 1; - rmd->flag = MOD_REMESH_FLOOD_FILL; - rmd->mode = MOD_REMESH_VOXEL; - rmd->threshold = 1; - rmd->voxel_size = 0.1f; - rmd->adaptivity = 0.0f; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(rmd, modifier)); + + MEMCPY_STRUCT_AFTER(rmd, DNA_struct_default_get(RemeshModifierData), modifier); } #ifdef WITH_MOD_REMESH @@ -291,9 +286,11 @@ ModifierTypeInfo modifierType_Remesh = { /* name */ "Remesh", /* structName */ "RemeshModifierData", /* structSize */ sizeof(RemeshModifierData), + /* srna */ &RNA_RemeshModifier, /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_REMESH, /* copyData */ BKE_modifier_copydata_generic, @@ -313,7 +310,6 @@ ModifierTypeInfo modifierType_Remesh = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 5842d05da09..6521a0859e5 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -31,6 +31,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -54,6 +55,15 @@ #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" +static void initData(ModifierData *md) +{ + ScrewModifierData *ltmd = (ScrewModifierData *)md; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(ltmd, modifier)); + + MEMCPY_STRUCT_AFTER(ltmd, DNA_struct_default_get(ScrewModifierData), modifier); +} + #include "BLI_strict_flags.h" /* used for gathering edge connectivity */ @@ -177,19 +187,6 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result, return result; } -static void initData(ModifierData *md) -{ - ScrewModifierData *ltmd = (ScrewModifierData *)md; - ltmd->ob_axis = NULL; - ltmd->angle = (float)(M_PI * 2.0); - ltmd->axis = 2; - ltmd->flag = MOD_SCREW_SMOOTH_SHADING; - ltmd->steps = 16; - ltmd->render_steps = 16; - ltmd->iter = 1; - ltmd->merge_dist = 0.01f; -} - static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) { Mesh *mesh = meshData; @@ -361,7 +358,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1); /* Will the screw be closed? - * Note! smaller then `FLT_EPSILON * 100` + * Note! smaller than `FLT_EPSILON * 100` * gives problems with float precision so its never closed. */ if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) && fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f) && step_tot > 3) { @@ -1161,11 +1158,11 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { ScrewModifierData *ltmd = (ScrewModifierData *)md; - walk(userData, ob, <md->ob_axis, IDWALK_CB_NOP); + walk(userData, ob, (ID **)<md->ob_axis, IDWALK_CB_NOP); } static void panel_draw(const bContext *UNUSED(C), Panel *panel) @@ -1247,10 +1244,12 @@ ModifierTypeInfo modifierType_Screw = { /* name */ "Screw", /* structName */ "ScrewModifierData", /* structSize */ sizeof(ScrewModifierData), + /* srna */ &RNA_ScrewModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_SCREW, /* copyData */ BKE_modifier_copydata_generic, @@ -1270,8 +1269,7 @@ ModifierTypeInfo modifierType_Screw = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index 801995d6dbc..bb267386dfb 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -31,8 +31,12 @@ #include "BKE_key.h" #include "BKE_particle.h" +#include "RNA_access.h" + #include "MOD_modifiertypes.h" +#include "UI_resources.h" + static void deformVerts(ModifierData *UNUSED(md), const ModifierEvalContext *ctx, Mesh *UNUSED(mesh), @@ -121,9 +125,11 @@ ModifierTypeInfo modifierType_ShapeKey = { /* name */ "ShapeKey", /* structName */ "ShapeKeyModifierData", /* structSize */ sizeof(ShapeKeyModifierData), + /* srna */ &RNA_Modifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_DOT, /* copyData */ NULL, @@ -143,7 +149,6 @@ ModifierTypeInfo modifierType_ShapeKey = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index fb045cf8923..dddabb12f61 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" @@ -56,12 +57,10 @@ static bool dependsOnNormals(ModifierData *md); static void initData(ModifierData *md) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; - smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE; - smd->shrinkOpts = MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR; - smd->keepDist = 0.0f; - smd->target = NULL; - smd->auxTarget = NULL; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier)); + + MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(ShrinkwrapModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -102,12 +101,12 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return false; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; - walk(userData, ob, &smd->target, IDWALK_CB_NOP); - walk(userData, ob, &smd->auxTarget, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&smd->target, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&smd->auxTarget, IDWALK_CB_NOP); } static void deformVerts(ModifierData *md, @@ -278,10 +277,12 @@ ModifierTypeInfo modifierType_Shrinkwrap = { /* name */ "Shrinkwrap", /* structName */ "ShrinkwrapModifierData", /* structSize */ sizeof(ShrinkwrapModifierData), + /* srna */ &RNA_ShrinkwrapModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_SHRINKWRAP, /* copyData */ BKE_modifier_copydata_generic, @@ -301,8 +302,7 @@ ModifierTypeInfo modifierType_Shrinkwrap = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index a0bd4e2f20f..ec89176f97e 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -378,14 +379,9 @@ static void initData(ModifierData *md) { SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md; - smd->mode = MOD_SIMPLEDEFORM_MODE_TWIST; - smd->axis = 0; - smd->deform_axis = 0; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier)); - smd->origin = NULL; - smd->factor = DEG2RADF(45.0f); - smd->limit[0] = 0.0f; - smd->limit[1] = 1.0f; + MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SimpleDeformModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -400,10 +396,10 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md; - walk(userData, ob, &smd->origin, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&smd->origin, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -540,11 +536,13 @@ ModifierTypeInfo modifierType_SimpleDeform = { /* name */ "SimpleDeform", /* structName */ "SimpleDeformModifierData", /* structSize */ sizeof(SimpleDeformModifierData), + /* srna */ &RNA_SimpleDeformModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_SIMPLEDEFORM, /* copyData */ BKE_modifier_copydata_generic, @@ -564,8 +562,7 @@ ModifierTypeInfo modifierType_SimpleDeform = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_simulation.cc b/source/blender/modifiers/intern/MOD_simulation.cc index d009eef00e6..0766c59cda6 100644 --- a/source/blender/modifiers/intern/MOD_simulation.cc +++ b/source/blender/modifiers/intern/MOD_simulation.cc @@ -32,6 +32,7 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -64,18 +65,28 @@ using blender::float3; -static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +static void initData(ModifierData *md) +{ + SimulationModifierData *smd = (SimulationModifierData *)md; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier)); + + MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SimulationModifierData), modifier); +} + +static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *UNUSED(ctx)) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - if (smd->simulation) { - DEG_add_simulation_relation(ctx->node, smd->simulation, "Accessed Simulation"); - } + UNUSED_VARS(smd); } -static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, + Object *UNUSED(ob), + IDWalkFunc UNUSED(walk), + void *UNUSED(userData)) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - walk(userData, ob, (ID **)&smd->simulation, IDWALK_CB_USER); + UNUSED_VARS(smd); } static bool isDisabled(const struct Scene *UNUSED(scene), @@ -83,41 +94,16 @@ static bool isDisabled(const struct Scene *UNUSED(scene), bool UNUSED(useRenderParams)) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - return smd->simulation == nullptr; -} - -static const ParticleSimulationState *find_particle_state(SimulationModifierData *smd) -{ - return reinterpret_cast<const ParticleSimulationState *>( - BKE_simulation_state_try_find_by_name_and_type( - smd->simulation, smd->data_path, SIM_TYPE_NAME_PARTICLE_SIMULATION)); + UNUSED_VARS(smd); + return false; } static PointCloud *modifyPointCloud(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), - PointCloud *input_pointcloud) + PointCloud *pointcloud) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - const ParticleSimulationState *state = find_particle_state(smd); - if (state == nullptr) { - return input_pointcloud; - } - - PointCloud *pointcloud = BKE_pointcloud_new_for_eval(input_pointcloud, state->tot_particles); - if (state->tot_particles == 0) { - return pointcloud; - } - - const float3 *positions = static_cast<const float3 *>( - CustomData_get_layer_named(&state->attributes, CD_PROP_FLOAT3, "Position")); - const float *radii = static_cast<const float *>( - CustomData_get_layer_named(&state->attributes, CD_PROP_FLOAT, "Radius")); - memcpy(pointcloud->co, positions, sizeof(float3) * state->tot_particles); - - for (int i = 0; i < state->tot_particles; i++) { - pointcloud->radius[i] = radii[i]; - } - + UNUSED_VARS(smd); return pointcloud; } @@ -131,8 +117,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "simulation", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "data_path", 0, NULL, ICON_NONE); + uiItemL(layout, "This modifier does nothing currently", ICON_INFO); modifier_panel_end(layout, ptr); } @@ -145,63 +130,64 @@ static void panelRegister(ARegionType *region_type) static void blendWrite(BlendWriter *writer, const ModifierData *md) { const SimulationModifierData *smd = reinterpret_cast<const SimulationModifierData *>(md); - BLO_write_string(writer, smd->data_path); + UNUSED_VARS(smd, writer); } static void blendRead(BlendDataReader *reader, ModifierData *md) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - BLO_read_data_address(reader, &smd->data_path); + UNUSED_VARS(smd, reader); } static void copyData(const ModifierData *md, ModifierData *target, const int flag) { const SimulationModifierData *smd = reinterpret_cast<const SimulationModifierData *>(md); SimulationModifierData *tsmd = reinterpret_cast<SimulationModifierData *>(target); + UNUSED_VARS(smd, tsmd); BKE_modifier_copydata_generic(md, target, flag); - if (smd->data_path != nullptr) { - tsmd->data_path = BLI_strdup(smd->data_path); - } } static void freeData(ModifierData *md) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - if (smd->data_path) { - MEM_freeN(smd->data_path); - } + UNUSED_VARS(smd); } ModifierTypeInfo modifierType_Simulation = { /* name */ "Simulation", /* structName */ "SimulationModifierData", /* structSize */ sizeof(SimulationModifierData), +#ifdef WITH_GEOMETRY_NODES + /* srna */ &RNA_SimulationModifier, +#else + /* srna */ &RNA_Modifier, +#endif /* type */ eModifierTypeType_None, /* flags */ (ModifierTypeFlag)0, + /* icon */ ICON_PHYSICS, /* TODO: Use correct icon. */ /* copyData */ copyData, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, - /* modifyMesh */ NULL, - /* modifyHair */ NULL, + /* deformVerts */ nullptr, + /* deformMatrices */ nullptr, + /* deformVertsEM */ nullptr, + /* deformMatricesEM */ nullptr, + /* modifyMesh */ nullptr, + /* modifyHair */ nullptr, /* modifyPointCloud */ modifyPointCloud, - /* modifyVolume */ NULL, + /* modifyVolume */ nullptr, - /* initData */ NULL, - /* requiredDataMask */ NULL, + /* initData */ initData, + /* requiredDataMask */ nullptr, /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepsgraph */ updateDepsgraph, - /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, + /* dependsOnTime */ nullptr, + /* dependsOnNormals */ nullptr, /* foreachIDLink */ foreachIDLink, - /* foreachTexLink */ NULL, - /* freeRuntimeData */ NULL, + /* foreachTexLink */ nullptr, + /* freeRuntimeData */ nullptr, /* panelRegister */ panelRegister, /* blendWrite */ blendWrite, /* blendRead */ blendRead, diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index f9d9e206914..6936f5a53f8 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -63,6 +63,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -802,7 +803,7 @@ static int calc_edge_subdivisions(const MVert *mvert, const MEdge *e, const int *degree) { - /* prevent memory errors [#38003] */ + /* prevent memory errors T38003. */ #define NUM_SUBDIVISIONS_MAX 128 const MVertSkin *evs[2] = {&nodes[e->v1], &nodes[e->v2]}; @@ -997,8 +998,8 @@ static void add_poly(SkinOutput *so, BMVert *v1, BMVert *v2, BMVert *v3, BMVert BMVert *verts[4] = {v1, v2, v3, v4}; BMFace *f; - BLI_assert(v1 != v2 && v1 != v3 && v1 != v4); - BLI_assert(v2 != v3 && v2 != v4); + BLI_assert(!ELEM(v1, v2, v3, v4)); + BLI_assert(!ELEM(v2, v3, v4)); BLI_assert(v3 != v4); BLI_assert(v1 && v2 && v3); @@ -1413,7 +1414,7 @@ static void quad_from_tris(BMEdge *e, BMFace *adj[2], BMVert *ndx[4]) /* Find what the second tri has that the first doesn't */ for (i = 0; i < 3; i++) { - if (tri[1][i] != tri[0][0] && tri[1][i] != tri[0][1] && tri[1][i] != tri[0][2]) { + if (!ELEM(tri[1][i], tri[0][0], tri[0][1], tri[0][2])) { opp = tri[1][i]; break; } @@ -1759,13 +1760,19 @@ static bool skin_output_branch_hulls( return result; } +typedef enum eSkinErrorFlag { + SKIN_ERROR_NO_VALID_ROOT = (1 << 0), + SKIN_ERROR_HULL = (1 << 1), +} eSkinErrorFlag; + static BMesh *build_skin(SkinNode *skin_nodes, int totvert, const MeshElemMap *emap, const MEdge *medge, int totedge, const MDeformVert *input_dvert, - SkinModifierData *smd) + SkinModifierData *smd, + eSkinErrorFlag *r_error) { SkinOutput so; int v; @@ -1801,7 +1808,7 @@ static BMesh *build_skin(SkinNode *skin_nodes, skin_update_merged_vertices(skin_nodes, totvert); if (!skin_output_branch_hulls(&so, skin_nodes, totvert, emap, medge)) { - BKE_modifier_set_error(&smd->modifier, "Hull error"); + *r_error |= SKIN_ERROR_HULL; } /* Merge triangles here in the hope of providing better target @@ -1847,7 +1854,7 @@ static void skin_set_orig_indices(Mesh *mesh) * 2) Generate node frames * 3) Output vertices and polygons from frames, connections, and hulls */ -static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd) +static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_error) { Mesh *result; MVertSkin *nodes; @@ -1877,16 +1884,14 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd) MEM_freeN(emat); emat = NULL; - bm = build_skin(skin_nodes, totvert, emap, medge, totedge, dvert, smd); + bm = build_skin(skin_nodes, totvert, emap, medge, totedge, dvert, smd, r_error); MEM_freeN(skin_nodes); MEM_freeN(emap); MEM_freeN(emapmem); if (!has_valid_root) { - BKE_modifier_set_error( - &smd->modifier, - "No valid root vertex found (you need one per mesh island you want to skin)"); + *r_error |= SKIN_ERROR_NO_VALID_ROOT; } if (!bm) { @@ -1903,7 +1908,7 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd) return result; } -static Mesh *final_skin(SkinModifierData *smd, Mesh *mesh) +static Mesh *final_skin(SkinModifierData *smd, Mesh *mesh, eSkinErrorFlag *r_error) { Mesh *result; @@ -1913,7 +1918,7 @@ static Mesh *final_skin(SkinModifierData *smd, Mesh *mesh) } mesh = subdivide_base(mesh); - result = base_skin(mesh, smd); + result = base_skin(mesh, smd, r_error); BKE_id_free(NULL, mesh); return result; @@ -1925,19 +1930,33 @@ static void initData(ModifierData *md) { SkinModifierData *smd = (SkinModifierData *)md; - /* Enable in editmode by default */ - md->mode |= eModifierMode_Editmode; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier)); + + MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SkinModifierData), modifier); - smd->branch_smoothing = 0; - smd->flag = 0; - smd->symmetry_axes = MOD_SKIN_SYMM_X; + /* Enable in editmode by default. */ + md->mode |= eModifierMode_Editmode; } -static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { - Mesh *result; + eSkinErrorFlag error = 0; + Mesh *result = final_skin((SkinModifierData *)md, mesh, &error); + + if (error & SKIN_ERROR_NO_VALID_ROOT) { + error &= ~SKIN_ERROR_NO_VALID_ROOT; + BKE_modifier_set_error( + ctx->object, + md, + "No valid root vertex found (you need one per mesh island you want to skin)"); + } + if (error & SKIN_ERROR_HULL) { + error &= ~SKIN_ERROR_HULL; + BKE_modifier_set_error(ctx->object, md, "Hull error"); + } + BLI_assert(error == 0); - if (!(result = final_skin((SkinModifierData *)md, mesh))) { + if (result == NULL) { return mesh; } return result; @@ -2011,8 +2030,10 @@ ModifierTypeInfo modifierType_Skin = { /* name */ "Skin", /* structName */ "SkinModifierData", /* structSize */ sizeof(SkinModifierData), + /* srna */ &RNA_SkinModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_SKIN, /* copyData */ BKE_modifier_copydata_generic, @@ -2032,7 +2053,6 @@ ModifierTypeInfo modifierType_Skin = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 1939437d717..e73a59f1ae8 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -29,6 +29,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_screen_types.h" @@ -55,10 +56,9 @@ static void initData(ModifierData *md) { SmoothModifierData *smd = (SmoothModifierData *)md; - smd->fac = 0.5f; - smd->repeat = 1; - smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z; - smd->defgrp_name[0] = '\0'; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier)); + + MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SmoothModifierData), modifier); } static bool isDisabled(const struct Scene *UNUSED(scene), @@ -272,9 +272,11 @@ ModifierTypeInfo modifierType_Smooth = { /* name */ "Smooth", /* structName */ "SmoothModifierData", /* structSize */ sizeof(SmoothModifierData), + /* srna */ &RNA_SmoothModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_SMOOTH, /* copyData */ BKE_modifier_copydata_generic, @@ -294,7 +296,6 @@ ModifierTypeInfo modifierType_Smooth = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index e688ec8470c..4bdb3ba60b1 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -104,10 +104,12 @@ ModifierTypeInfo modifierType_Softbody = { /* name */ "Softbody", /* structName */ "SoftbodyModifierData", /* structSize */ sizeof(SoftbodyModifierData), + /* srna */ &RNA_SoftBodyModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_RequiresOriginalData | eModifierTypeFlag_Single | eModifierTypeFlag_UsesPointCache, + /* icon */ ICON_MOD_SOFT, /* copyData */ NULL, @@ -127,7 +129,6 @@ ModifierTypeInfo modifierType_Softbody = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 2c84def73b0..8886d3718c9 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_screen_types.h" @@ -44,10 +45,6 @@ #include "MOD_solidify_util.h" -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -#endif - static bool dependsOnNormals(ModifierData *md) { const SolidifyModifierData *smd = (SolidifyModifierData *)md; @@ -60,16 +57,16 @@ static bool dependsOnNormals(ModifierData *md) static void initData(ModifierData *md) { SolidifyModifierData *smd = (SolidifyModifierData *)md; - smd->offset = 0.01f; - smd->offset_fac = -1.0f; - smd->flag = MOD_SOLIDIFY_RIM; - smd->mode = MOD_SOLIDIFY_MODE_EXTRUDE; - smd->nonmanifold_offset_mode = MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS; - smd->nonmanifold_boundary_mode = MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE; - smd->merge_tolerance = 0.0001f; - smd->bevel_convex = 0.0f; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier)); + + MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SolidifyModifierData), modifier); } +#ifdef __GNUC__ +# pragma GCC diagnostic error "-Wsign-conversion" +#endif + static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks) @@ -233,8 +230,9 @@ static void vertex_group_panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); col = uiLayoutColumn(layout, false); - uiItemPointerR(col, ptr, "shell_vertex_group", &ob_ptr, "vertex_groups", "Shell", ICON_NONE); - uiItemPointerR(col, ptr, "rim_vertex_group", &ob_ptr, "vertex_groups", "Rim", ICON_NONE); + uiItemPointerR( + col, ptr, "shell_vertex_group", &ob_ptr, "vertex_groups", IFACE_("Shell"), ICON_NONE); + uiItemPointerR(col, ptr, "rim_vertex_group", &ob_ptr, "vertex_groups", IFACE_("Rim"), ICON_NONE); } static void panelRegister(ARegionType *region_type) @@ -260,11 +258,13 @@ ModifierTypeInfo modifierType_Solidify = { /* name */ "Solidify", /* structName */ "SolidifyModifierData", /* structSize */ sizeof(SolidifyModifierData), + /* srna */ &RNA_SolidifyModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_SOLIDIFY, /* copyData */ BKE_modifier_copydata_generic, @@ -284,7 +284,6 @@ ModifierTypeInfo modifierType_Solidify = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index 818327e120b..c8b357b34c8 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -59,7 +59,7 @@ BLI_INLINE void madd_v3v3short_fl(float r[3], const short a[3], const float f) /** \name High Quality Normal Calculation Function * \{ */ -/* skip shell thickness for non-manifold edges, see [#35710] */ +/* skip shell thickness for non-manifold edges, see T35710. */ #define USE_NONMANIFOLD_WORKAROUND /* *** derived mesh high quality normal calculation function *** */ @@ -981,7 +981,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex MEM_freeN(vert_nors); } - /* must recalculate normals with vgroups since they can displace unevenly [#26888] */ + /* must recalculate normals with vgroups since they can displace unevenly T26888. */ if ((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) || do_rim || dvert) { result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } @@ -1004,23 +1004,23 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex &result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, result->totvert); } /* Ultimate security check. */ - if (!dvert) { - return result; - } - result->dvert = dvert; - - if (rim_defgrp_index != -1) { - for (uint i = 0; i < rimVerts; i++) { - BKE_defvert_ensure_index(&result->dvert[new_vert_arr[i]], rim_defgrp_index)->weight = 1.0f; - BKE_defvert_ensure_index(&result->dvert[(do_shell ? new_vert_arr[i] : i) + numVerts], - rim_defgrp_index) - ->weight = 1.0f; + if (dvert != NULL) { + result->dvert = dvert; + + if (rim_defgrp_index != -1) { + for (uint i = 0; i < rimVerts; i++) { + BKE_defvert_ensure_index(&result->dvert[new_vert_arr[i]], rim_defgrp_index)->weight = + 1.0f; + BKE_defvert_ensure_index(&result->dvert[(do_shell ? new_vert_arr[i] : i) + numVerts], + rim_defgrp_index) + ->weight = 1.0f; + } } - } - if (shell_defgrp_index != -1) { - for (uint i = numVerts; i < result->totvert; i++) { - BKE_defvert_ensure_index(&result->dvert[i], shell_defgrp_index)->weight = 1.0f; + if (shell_defgrp_index != -1) { + for (uint i = numVerts; i < result->totvert; i++) { + BKE_defvert_ensure_index(&result->dvert[i], shell_defgrp_index)->weight = 1.0f; + } } } } diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index 1e0269617ec..8acf07f9181 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -366,41 +366,73 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (edge_adj_faces_len[i] > 0) { uint v1 = vm[ed->v1]; uint v2 = vm[ed->v2]; - if (v1 != v2) { - if (v2 < v1) { - SWAP(uint, v1, v2); - } - sub_v3_v3v3(edgedir, orig_mvert_co[v2], orig_mvert_co[v1]); - orig_edge_lengths[i] = len_squared_v3(edgedir); - if (orig_edge_lengths[i] <= merge_tolerance_sqr) { - mul_v3_fl(edgedir, - (combined_verts[v2] + 1) / - (float)(combined_verts[v1] + combined_verts[v2] + 2)); - add_v3_v3(orig_mvert_co[v1], edgedir); - for (uint j = v2; j < numVerts; j++) { - if (vm[j] == v2) { - vm[j] = v1; - } - } - vert_adj_edges_len[v1] += vert_adj_edges_len[v2]; - vert_adj_edges_len[v2] = 0; - combined_verts[v1] += combined_verts[v2] + 1; + if (v1 == v2) { + continue; + } - if (do_shell) { - numNewLoops -= edge_adj_faces_len[i] * 2; + if (v2 < v1) { + SWAP(uint, v1, v2); + } + sub_v3_v3v3(edgedir, orig_mvert_co[v2], orig_mvert_co[v1]); + orig_edge_lengths[i] = len_squared_v3(edgedir); + + if (orig_edge_lengths[i] <= merge_tolerance_sqr) { + /* Merge verts. But first check if that would create a higher poly count. */ + /* This check is very slow. It would need the vertex edge links to get + * accelerated that are not yet available at this point. */ + bool can_merge = true; + for (uint k = 0; k < numEdges && can_merge; k++) { + if (k != i && edge_adj_faces_len[k] > 0 && + (ELEM(vm[orig_medge[k].v1], v1, v2) != ELEM(vm[orig_medge[k].v2], v1, v2))) { + for (uint j = 0; j < edge_adj_faces[k]->faces_len && can_merge; j++) { + mp = orig_mpoly + edge_adj_faces[k]->faces[j]; + uint changes = 0; + int cur = mp->totloop - 1; + for (int next = 0; next < mp->totloop && changes <= 2; next++) { + uint cur_v = vm[orig_mloop[mp->loopstart + cur].v]; + uint next_v = vm[orig_mloop[mp->loopstart + next].v]; + changes += (ELEM(cur_v, v1, v2) != ELEM(next_v, v1, v2)); + cur = next; + } + can_merge = can_merge && changes <= 2; + } } - - edge_adj_faces_len[i] = 0; - MEM_freeN(edge_adj_faces[i]->faces); - MEM_freeN(edge_adj_faces[i]->faces_reversed); - MEM_freeN(edge_adj_faces[i]); - edge_adj_faces[i] = NULL; } - else { - orig_edge_lengths[i] = sqrtf(orig_edge_lengths[i]); + + if (!can_merge) { + orig_edge_lengths[i] = 0.0f; vert_adj_edges_len[v1]++; vert_adj_edges_len[v2]++; + continue; } + + mul_v3_fl(edgedir, + (combined_verts[v2] + 1) / + (float)(combined_verts[v1] + combined_verts[v2] + 2)); + add_v3_v3(orig_mvert_co[v1], edgedir); + for (uint j = v2; j < numVerts; j++) { + if (vm[j] == v2) { + vm[j] = v1; + } + } + vert_adj_edges_len[v1] += vert_adj_edges_len[v2]; + vert_adj_edges_len[v2] = 0; + combined_verts[v1] += combined_verts[v2] + 1; + + if (do_shell) { + numNewLoops -= edge_adj_faces_len[i] * 2; + } + + edge_adj_faces_len[i] = 0; + MEM_freeN(edge_adj_faces[i]->faces); + MEM_freeN(edge_adj_faces[i]->faces_reversed); + MEM_freeN(edge_adj_faces[i]); + edge_adj_faces[i] = NULL; + } + else { + orig_edge_lengths[i] = sqrtf(orig_edge_lengths[i]); + vert_adj_edges_len[v1]++; + vert_adj_edges_len[v2]++; } } } @@ -619,7 +651,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint *e_adj_faces_faces = e_adj_faces->faces; bool *e_adj_faces_reversed = e_adj_faces->faces_reversed; const uint faces_len = e_adj_faces->faces_len; - if (e != i) { + if (e_adj_faces_faces != adj_faces->faces) { /* Find index of e in #adj_faces. */ for (face_index = 0; face_index < faces_len && e_adj_faces_faces[face_index] != face; @@ -684,8 +716,49 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const uint v1 = vm[ed->v1]; const uint v2 = vm[ed->v2]; if (edge_adj_faces_len[i] > 0) { - sub_v3_v3v3(edgedir, orig_mvert_co[v2], orig_mvert_co[v1]); - mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[i]); + if (LIKELY(orig_edge_lengths[i] > FLT_EPSILON)) { + sub_v3_v3v3(edgedir, orig_mvert_co[v2], orig_mvert_co[v1]); + mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[i]); + } + else { + /* Smart fallback. */ + /* This makes merging non essential, but correct + * merging will still give way better results. */ + float pos[3]; + copy_v3_v3(pos, orig_mvert_co[v2]); + + OldVertEdgeRef *link1 = vert_adj_edges[v1]; + float v1_dir[3]; + zero_v3(v1_dir); + for (int j = 0; j < link1->edges_len; j++) { + uint e = link1->edges[j]; + if (edge_adj_faces_len[e] > 0 && e != i) { + uint other_v = + vm[vm[orig_medge[e].v1] == v1 ? orig_medge[e].v2 : orig_medge[e].v1]; + sub_v3_v3v3(edgedir, orig_mvert_co[other_v], pos); + add_v3_v3(v1_dir, edgedir); + } + } + OldVertEdgeRef *link2 = vert_adj_edges[v2]; + float v2_dir[3]; + zero_v3(v2_dir); + for (int j = 0; j < link2->edges_len; j++) { + uint e = link2->edges[j]; + if (edge_adj_faces_len[e] > 0 && e != i) { + uint other_v = + vm[vm[orig_medge[e].v1] == v2 ? orig_medge[e].v2 : orig_medge[e].v1]; + sub_v3_v3v3(edgedir, orig_mvert_co[other_v], pos); + add_v3_v3(v2_dir, edgedir); + } + } + sub_v3_v3v3(edgedir, v2_dir, v1_dir); + float len = normalize_v3(edgedir); + if (len == 0.0f) { + edgedir[0] = 0.0f; + edgedir[1] = 0.0f; + edgedir[2] = 1.0f; + } + } OldEdgeFaceRef *adj_faces = edge_adj_faces[i]; const uint adj_len = adj_faces->faces_len; @@ -1327,6 +1400,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, scalar_vgroup = min_ff(BKE_defvert_find_weight(dv, defgrp_index), scalar_vgroup); } } + scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv); face_weight[i] = scalar_vgroup; } } @@ -2189,8 +2263,10 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, NewEdgeRef *edge1 = new_edges[0]; NewEdgeRef *edge2 = new_edges[1]; - const bool v1_singularity = edge1->link_edge_groups[0]->is_singularity; - const bool v2_singularity = edge1->link_edge_groups[1]->is_singularity; + const bool v1_singularity = edge1->link_edge_groups[0]->is_singularity && + edge2->link_edge_groups[0]->is_singularity; + const bool v2_singularity = edge1->link_edge_groups[1]->is_singularity && + edge2->link_edge_groups[1]->is_singularity; if (v1_singularity && v2_singularity) { continue; } @@ -2391,7 +2467,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, CustomData_copy_data(&mesh->pdata, &result->pdata, (int)(i / 2), (int)poly_index, 1); mpoly[poly_index].loopstart = (int)loop_index; mpoly[poly_index].totloop = (int)k; - mpoly[poly_index].mat_nr = fr->face->mat_nr + (fr->reversed ? mat_ofs : 0); + mpoly[poly_index].mat_nr = fr->face->mat_nr + (fr->reversed != do_flip ? mat_ofs : 0); CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max); mpoly[poly_index].flag = fr->face->flag; if (fr->reversed != do_flip) { @@ -2425,16 +2501,25 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(face_edges); } if (edge_index != numNewEdges) { - BKE_modifier_set_error( - md, "Internal Error: edges array wrong size: %u instead of %u", numNewEdges, edge_index); + BKE_modifier_set_error(ctx->object, + md, + "Internal Error: edges array wrong size: %u instead of %u", + numNewEdges, + edge_index); } if (poly_index != numNewPolys) { - BKE_modifier_set_error( - md, "Internal Error: polys array wrong size: %u instead of %u", numNewPolys, poly_index); + BKE_modifier_set_error(ctx->object, + md, + "Internal Error: polys array wrong size: %u instead of %u", + numNewPolys, + poly_index); } if (loop_index != numNewLoops) { - BKE_modifier_set_error( - md, "Internal Error: loops array wrong size: %u instead of %u", numNewLoops, loop_index); + BKE_modifier_set_error(ctx->object, + md, + "Internal Error: loops array wrong size: %u instead of %u", + numNewLoops, + loop_index); } BLI_assert(edge_index == numNewEdges); BLI_assert(poly_index == numNewPolys); diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 1972f857877..1aa015682dd 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -30,6 +30,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -71,11 +72,9 @@ static void initData(ModifierData *md) { SubsurfModifierData *smd = (SubsurfModifierData *)md; - smd->levels = 1; - smd->renderLevels = 2; - smd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS; - smd->quality = 3; - smd->flags |= (eSubsurfModifierFlag_UseCrease | eSubsurfModifierFlag_ControlEdges); + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier)); + + MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SubsurfModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -154,13 +153,21 @@ static int subdiv_levels_for_modifier_get(const SubsurfModifierData *smd, return get_render_subsurf_level(&scene->r, requested_levels, use_render_params); } -static void subdiv_settings_init(SubdivSettings *settings, const SubsurfModifierData *smd) +static void subdiv_settings_init(SubdivSettings *settings, + const SubsurfModifierData *smd, + const ModifierEvalContext *ctx) { + const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER); + const int requested_levels = (use_render_params) ? smd->renderLevels : smd->levels; + settings->is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE); - settings->is_adaptive = true; - settings->level = settings->is_simple ? 1 : smd->quality; + settings->is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision); + settings->level = settings->is_simple ? + 1 : + (settings->is_adaptive ? smd->quality : requested_levels); settings->use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease); - settings->vtx_boundary_interpolation = SUBDIV_VTX_BOUNDARY_EDGE_ONLY; + settings->vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( + smd->boundary_smooth); settings->fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth( smd->uv_smooth); } @@ -247,16 +254,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * { Mesh *result = mesh; #if !defined(WITH_OPENSUBDIV) - BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv"); return result; #endif SubsurfModifierData *smd = (SubsurfModifierData *)md; SubdivSettings subdiv_settings; - subdiv_settings_init(&subdiv_settings, smd); + subdiv_settings_init(&subdiv_settings, smd, ctx); if (subdiv_settings.level == 0) { return result; } - BKE_subdiv_settings_validate_for_mesh(&subdiv_settings, mesh); SubsurfRuntimeData *runtime_data = subsurf_ensure_runtime(smd); Subdiv *subdiv = subdiv_descriptor_ensure(smd, &subdiv_settings, mesh); if (subdiv == NULL) { @@ -296,14 +302,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } static void deformMatrices(ModifierData *md, - const ModifierEvalContext *UNUSED(ctx), + const ModifierEvalContext *ctx, Mesh *mesh, float (*vertex_cos)[3], float (*deform_matrices)[3][3], int num_verts) { #if !defined(WITH_OPENSUBDIV) - BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv"); return; #endif @@ -312,11 +318,10 @@ static void deformMatrices(ModifierData *md, SubsurfModifierData *smd = (SubsurfModifierData *)md; SubdivSettings subdiv_settings; - subdiv_settings_init(&subdiv_settings, smd); + subdiv_settings_init(&subdiv_settings, smd, ctx); if (subdiv_settings.level == 0) { return; } - BKE_subdiv_settings_validate_for_mesh(&subdiv_settings, mesh); SubsurfRuntimeData *runtime_data = subsurf_ensure_runtime(smd); Subdiv *subdiv = subdiv_descriptor_ensure(smd, &subdiv_settings, mesh); if (subdiv == NULL) { @@ -345,6 +350,11 @@ static bool get_show_adaptive_options(const bContext *C, Panel *panel) return false; } + /* Don't show adaptive options if regular subdivision used*/ + if (!RNA_boolean_get(ptr, "use_limit_surface")) { + return false; + } + /* Don't show adaptive options if the cycles experimental feature set is disabled. */ Scene *scene = CTX_data_scene(C); PointerRNA scene_ptr; @@ -452,8 +462,14 @@ static void advanced_panel_draw(const bContext *C, Panel *panel) uiLayoutSetPropSep(layout, true); uiLayoutSetActive(layout, !(show_adaptive_options && ob_use_adaptive_subdivision)); - uiItemR(layout, ptr, "quality", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_limit_surface", 0, NULL, ICON_NONE); + + uiLayout *col = uiLayoutColumn(layout, true); + uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_limit_surface")); + uiItemR(col, ptr, "quality", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "uv_smooth", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "boundary_smooth", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "use_creases", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "use_custom_normals", 0, NULL, ICON_NONE); } @@ -476,10 +492,12 @@ ModifierTypeInfo modifierType_Subsurf = { /* name */ "Subdivision", /* structName */ "SubsurfModifierData", /* structSize */ sizeof(SubsurfModifierData), + /* srna */ &RNA_SubsurfModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, + /* icon */ ICON_MOD_SUBSURF, /* copyData */ copyData, @@ -499,7 +517,6 @@ ModifierTypeInfo modifierType_Subsurf = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ freeRuntimeData, diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index a20ba3f899e..72f19efe3a4 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -59,10 +60,9 @@ static void initData(ModifierData *md) { SurfaceModifierData *surmd = (SurfaceModifierData *)md; - surmd->bvhtree = NULL; - surmd->mesh = NULL; - surmd->x = NULL; - surmd->v = NULL; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(surmd, modifier)); + + MEMCPY_STRUCT_AFTER(surmd, DNA_struct_default_get(SurfaceModifierData), modifier); } static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int flag) @@ -126,7 +126,7 @@ static void deformVerts(ModifierData *md, if (mesh) { /* Not possible to use get_mesh() in this case as we'll modify its vertices * and get_mesh() would return 'mesh' directly. */ - BKE_id_copy_ex(NULL, (ID *)mesh, (ID **)&surmd->mesh, LIB_ID_COPY_LOCALIZE); + surmd->mesh = (Mesh *)BKE_id_copy_ex(NULL, (ID *)mesh, NULL, LIB_ID_COPY_LOCALIZE); } else { surmd->mesh = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, numVerts, false, false); @@ -226,9 +226,11 @@ ModifierTypeInfo modifierType_Surface = { /* name */ "Surface", /* structName */ "SurfaceModifierData", /* structSize */ sizeof(SurfaceModifierData), + /* srna */ &RNA_SurfaceModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_NoUserAdd, + /* icon */ ICON_MOD_PHYSICS, /* copyData */ copyData, @@ -248,7 +250,6 @@ ModifierTypeInfo modifierType_Surface = { /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 6fc2bd29add..5407397e3bf 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -26,6 +26,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -69,6 +70,9 @@ typedef struct SDefAdjacencyArray { uint num; /* Careful, this is twice the number of polygons (avoids an extra loop) */ } SDefAdjacencyArray; +/** + * Polygons per edge (only 2, any more will exit calculation). + */ typedef struct SDefEdgePolys { uint polys[2], num; } SDefEdgePolys; @@ -82,37 +86,67 @@ typedef struct SDefBindCalcData { const MPoly *const mpoly; const MEdge *const medge; const MLoop *const mloop; + /** Coordinates to bind to, transformed into local space (compatible with `vertexCos`). */ float (*const targetCos)[3]; + /** Coordinates to bind (reference to the modifiers input argument). */ float (*const vertexCos)[3]; float imat[4][4]; const float falloff; int success; } SDefBindCalcData; +/** + * This represents the relationship between a point (a source coordinate) + * and the face-corner it's being bound to (from the target mesh). + * + * \note Some of these values could be de-duplicated however these are only + * needed once when running bind, so optimizing this structure isn't a priority. + */ typedef struct SDefBindPoly { + /** Coordinates copied directly from the modifiers inptut. */ float (*coords)[3]; + /** Coordinates projected into 2D space using `normal`. */ float (*coords_v2)[2]; + /** The point being queried projected into 2D space using `normal`. */ float point_v2[2]; float weight_angular; float weight_dist_proj; float weight_dist; float weight; float scales[2]; + /** Center of `coords` */ float centroid[3]; + /** Center of `coords_v2` */ float centroid_v2[2]; + /** + * The calculated normal of coords (could be shared between faces). + */ float normal[3]; float cent_edgemid_vecs_v2[2][2]; + /** + * The unsigned angle of this face-corner in `[0.0 .. PI]` range, + * where a small value is a thin corner. PI is is a straight line. + * Take care dividing by this value as it can approach zero. + */ float edgemid_angle; float point_edgemid_angles[2]; float corner_edgemid_angles[2]; float dominant_angle_weight; + /** Index of the input polygon. */ uint index; + /** Number of vertices in this face. */ uint numverts; + /** + * This polygons loop-start. + * \note that we could look this up from the polygon. + */ uint loopstart; uint edge_inds[2]; uint edge_vert_inds[2]; + /** The index of this corner in the face (starting at zero). */ uint corner_ind; uint dominant_edge; + /** When true `point_v2` is inside `coords_v2`. */ bool inside; } SDefBindPoly; @@ -150,11 +184,10 @@ enum { static void initData(ModifierData *md) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; - smd->target = NULL; - smd->verts = NULL; - smd->flags = 0; - smd->falloff = 4.0f; - smd->strength = 1.0f; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier)); + + MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SurfaceDeformModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -218,11 +251,11 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla } } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; - walk(userData, ob, &smd->target, IDWALK_NOP); + walk(userData, ob, (ID **)&smd->target, IDWALK_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -256,7 +289,7 @@ static int buildAdjacencyMap(const MPoly *poly, { const MLoop *loop; - /* Fing polygons adjacent to edges */ + /* Find polygons adjacent to edges. */ for (int i = 0; i < numpoly; i++, poly++) { loop = &mloop[poly->loopstart]; @@ -424,15 +457,9 @@ static void freeBindData(SDefBindWeightData *const bwdata) MEM_freeN(bwdata); } -BLI_INLINE float computeAngularWeight(const float point_angle, const float edgemid_angle) +BLI_INLINE float computeAngularWeight(const float point_angle) { - float weight; - - weight = point_angle; - weight /= edgemid_angle; - weight *= M_PI_2; - - return sinf(weight); + return sinf(point_angle * M_PI_2); } BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, @@ -472,7 +499,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, bwdata->bind_polys = bpoly; /* Loop over all adjacent edges, - * and build the SDefBindPoly data for each poly adjacent to those. */ + * and build the #SDefBindPoly data for each poly adjacent to those. */ for (vedge = vert_edges; vedge; vedge = vedge->next) { uint edge_ind = vedge->index; @@ -481,7 +508,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, bpoly = bwdata->bind_polys; for (int j = 0; j < bwdata->numpoly; bpoly++, j++) { - /* If coords isn't allocated, we have reached the first uninitialized bpoly */ + /* If coords isn't allocated, we have reached the first uninitialized `bpoly`. */ if ((bpoly->index == edge_polys[edge_ind].polys[i]) || (!bpoly->coords)) { break; } @@ -536,7 +563,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, } } - /* Compute poly's parametric data */ + /* Compute polygons parametric data. */ mid_v3_v3_array(bpoly->centroid, bpoly->coords, poly->totloop); normal_poly_v3(bpoly->normal, bpoly->coords, poly->totloop); @@ -546,7 +573,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, cross_v3_v3v3(axis, bpoly->normal, world); normalize_v3(axis); - /* Map coords onto 2d normal plane */ + /* Map coords onto 2d normal plane. */ map_to_plane_axis_angle_v2_v3v3fl(bpoly->point_v2, point_co, axis, angle); zero_v2(bpoly->centroid_v2); @@ -601,7 +628,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, bpoly->corner_edgemid_angles[1] = angle_normalized_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[1]); - /* Check for inifnite weights, and compute angular data otherwise */ + /* Check for infinite weights, and compute angular data otherwise. */ if (bpoly->weight_dist < FLT_EPSILON) { inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ; inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST; @@ -658,15 +685,12 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, /* Compute angular weight component */ if (epolys->num == 1) { - ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], - bpolys[0]->edgemid_angle); + ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]]); bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[0]; } else if (epolys->num == 2) { - ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], - bpolys[0]->edgemid_angle); - ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]], - bpolys[1]->edgemid_angle); + ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]]); + ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]]); bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[1]; bpolys[1]->weight_angular *= ang_weights[0] * ang_weights[1]; @@ -674,10 +698,10 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, } } - /* Compute scalings and falloff. - * Scale all weights if no infinite weight is found, - * scale only unprojected weight if projected weight is infinite, - * scale none if both are infinite. */ + /* Compute scaling and falloff: + * - Scale all weights if no infinite weight is found. + * - Scale only un-projected weight if projected weight is infinite. + * - Scale none if both are infinite. */ if (!inf_weight_flags) { bpoly = bwdata->bind_polys; @@ -707,9 +731,14 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, bpoly->dominant_angle_weight = sinf(bpoly->dominant_angle_weight * M_PI_2); /* Compute quadratic angular scale interpolation weight */ - scale_weight = bpoly->point_edgemid_angles[bpoly->dominant_edge] / bpoly->edgemid_angle; - scale_weight /= scale_weight + - (bpoly->point_edgemid_angles[!bpoly->dominant_edge] / bpoly->edgemid_angle); + { + const float edge_angle_a = bpoly->point_edgemid_angles[bpoly->dominant_edge]; + const float edge_angle_b = bpoly->point_edgemid_angles[!bpoly->dominant_edge]; + /* Clamp so skinny faces with near zero `edgemid_angle` + * won't cause numeric problems. see T81988. */ + scale_weight = edge_angle_a / max_ff(edge_angle_a, bpoly->edgemid_angle); + scale_weight /= scale_weight + (edge_angle_b / max_ff(edge_angle_b, bpoly->edgemid_angle)); + } sqr = scale_weight * scale_weight; inv_sqr = 1.0f - scale_weight; @@ -776,6 +805,11 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, bpoly->weight = 1.0f / bpoly->weight_angular / bpoly->weight_dist_proj / bpoly->weight_dist; } + /* Apply after other kinds of scaling so the faces corner angle is always + * scaled in a uniform way, preventing heavily sub-divided triangle fans + * from having a lop-sided influence on the weighting, see T81988. */ + bpoly->weight *= bpoly->edgemid_angle / M_PI; + tot_weight += bpoly->weight; } @@ -891,7 +925,7 @@ static void bindVert(void *__restrict userdata, interp_weights_poly_v2( sdbind->vert_weights, bpoly->coords_v2, bpoly->numverts, bpoly->point_v2); - /* Reproject vert based on weights and original poly verts, + /* Re-project vert based on weights and original poly verts, * to reintroduce poly non-planarity */ zero_v3(point_co_proj); for (int j = 0; j < bpoly->numverts; j++, loop++) { @@ -1009,7 +1043,8 @@ static void bindVert(void *__restrict userdata, freeBindData(bwdata); } -static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, +static bool surfacedeformBind(Object *ob, + SurfaceDeformModifierData *smd_orig, SurfaceDeformModifierData *smd_eval, float (*vertexCos)[3], uint numverts, @@ -1030,20 +1065,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, vert_edges = MEM_calloc_arrayN(tnumverts, sizeof(*vert_edges), "SDefVertEdgeMap"); if (vert_edges == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); return false; } adj_array = MEM_malloc_arrayN(tnumedges, 2 * sizeof(*adj_array), "SDefVertEdge"); if (adj_array == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); return false; } edge_polys = MEM_calloc_arrayN(tnumedges, sizeof(*edge_polys), "SDefEdgeFaceMap"); if (edge_polys == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); MEM_freeN(adj_array); return false; @@ -1051,14 +1086,14 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, smd_orig->verts = MEM_malloc_arrayN(numverts, sizeof(*smd_orig->verts), "SDefBindVerts"); if (smd_orig->verts == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); return false; } BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_LOOPTRI, 2); if (treeData.tree == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); MEM_freeN(smd_orig->verts); smd_orig->verts = NULL; @@ -1069,8 +1104,8 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys); if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, - "Target has edges with more than two polygons"); + BKE_modifier_set_error( + ob, (ModifierData *)smd_eval, "Target has edges with more than two polygons"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); free_bvhtree_from_mesh(&treeData); MEM_freeN(smd_orig->verts); @@ -1097,7 +1132,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, }; if (data.targetCos == NULL) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); return false; } @@ -1116,20 +1151,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, MEM_freeN(data.targetCos); if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, - "Target has edges with more than two polygons"); + BKE_modifier_set_error( + ob, (ModifierData *)smd_eval, "Target has edges with more than two polygons"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains concave polygons"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains concave polygons"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) { - BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains overlapping vertices"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains overlapping vertices"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) { @@ -1137,7 +1172,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, * to explain this with a reasonably sized message. * Though it shouldn't really matter all that much, * because this is very unlikely to occur */ - BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains invalid polygons"); + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains invalid polygons"); freeData((ModifierData *)smd_orig); } @@ -1234,7 +1269,7 @@ static void surfacedeformModifier_do(ModifierData *md, if (!(smd->flags & MOD_SDEF_BIND)) { if (smd->verts != NULL) { if (!DEG_is_active(ctx->depsgraph)) { - BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph"); return; } ModifierData *md_orig = BKE_modifier_get_original(md); @@ -1246,7 +1281,7 @@ static void surfacedeformModifier_do(ModifierData *md, Object *ob_target = smd->target; target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); if (!target) { - BKE_modifier_set_error(md, "No valid target mesh"); + BKE_modifier_set_error(ob, md, "No valid target mesh"); return; } @@ -1256,7 +1291,7 @@ static void surfacedeformModifier_do(ModifierData *md, /* If not bound, execute bind. */ if (smd->verts == NULL) { if (!DEG_is_active(ctx->depsgraph)) { - BKE_modifier_set_error(md, "Attempt to unbind from inactive dependency graph"); + BKE_modifier_set_error(ob, md, "Attempt to unbind from inactive dependency graph"); return; } @@ -1270,7 +1305,7 @@ static void surfacedeformModifier_do(ModifierData *md, /* Avoid converting edit-mesh data, binding is an exception. */ BKE_mesh_wrapper_ensure_mdata(target); - if (!surfacedeformBind(smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target)) { + if (!surfacedeformBind(ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target)) { smd->flags &= ~MOD_SDEF_BIND; } /* Early abort, this is binding 'call', no need to perform whole evaluation. */ @@ -1279,17 +1314,17 @@ static void surfacedeformModifier_do(ModifierData *md, /* Poly count checks */ if (smd->numverts != numverts) { - BKE_modifier_set_error(md, "Vertices changed from %u to %u", smd->numverts, numverts); + BKE_modifier_set_error(ob, md, "Vertices changed from %u to %u", smd->numverts, numverts); return; } if (smd->numpoly != tnumpoly) { - BKE_modifier_set_error(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); + BKE_modifier_set_error( + ob, md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); return; } - /* Early out if modifier would not affect input at all - still *after* the sanity checks (and - * potential binding) above. - */ + /* Early out if modifier would not affect input at all - still *after* the sanity checks + * (and potential binding) above. */ if (smd->strength == 0.0f) { return; } @@ -1453,8 +1488,7 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md) BLO_write_uint32_array( writer, smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_inds); - if (smd->verts[i].binds[j].mode == MOD_SDEF_MODE_CENTROID || - smd->verts[i].binds[j].mode == MOD_SDEF_MODE_LOOPTRI) { + if (ELEM(smd->verts[i].binds[j].mode, MOD_SDEF_MODE_CENTROID, MOD_SDEF_MODE_LOOPTRI)) { BLO_write_float3_array(writer, 1, smd->verts[i].binds[j].vert_weights); } else { @@ -1482,8 +1516,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) BLO_read_uint32_array( reader, smd->verts[i].binds[j].numverts, &smd->verts[i].binds[j].vert_inds); - if (smd->verts[i].binds[j].mode == MOD_SDEF_MODE_CENTROID || - smd->verts[i].binds[j].mode == MOD_SDEF_MODE_LOOPTRI) { + if (ELEM(smd->verts[i].binds[j].mode, MOD_SDEF_MODE_CENTROID, MOD_SDEF_MODE_LOOPTRI)) { BLO_read_float3_array(reader, 1, &smd->verts[i].binds[j].vert_weights); } else { @@ -1500,8 +1533,10 @@ ModifierTypeInfo modifierType_SurfaceDeform = { /* name */ "SurfaceDeform", /* structName */ "SurfaceDeformModifierData", /* structSize */ sizeof(SurfaceDeformModifierData), + /* srna */ &RNA_SurfaceDeformModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_MESHDEFORM, /* copyData */ copyData, @@ -1521,8 +1556,7 @@ ModifierTypeInfo modifierType_SurfaceDeform = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index 87ca067fba9..5a07c4e5e64 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -18,12 +18,15 @@ * \ingroup modifiers */ +#include <string.h> + #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -107,11 +110,12 @@ static void initData(ModifierData *md) { TriangulateModifierData *tmd = (TriangulateModifierData *)md; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(tmd, modifier)); + + MEMCPY_STRUCT_AFTER(tmd, DNA_struct_default_get(TriangulateModifierData), modifier); + /* Enable in editmode by default */ md->mode |= eModifierMode_Editmode; - tmd->quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE; - tmd->ngon_method = MOD_TRIANGULATE_NGON_BEAUTY; - tmd->min_vertices = 4; } static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) @@ -152,10 +156,12 @@ ModifierTypeInfo modifierType_Triangulate = { /* name */ "Triangulate", /* structName */ "TriangulateModifierData", /* structSize */ sizeof(TriangulateModifierData), + /* srna */ &RNA_TriangulateModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, + /* icon */ ICON_MOD_TRIANGULATE, /* copyData */ BKE_modifier_copydata_generic, @@ -175,7 +181,6 @@ ModifierTypeInfo modifierType_Triangulate = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c index a79e270af93..ba43434aeb3 100644 --- a/source/blender/modifiers/intern/MOD_ui_common.c +++ b/source/blender/modifiers/intern/MOD_ui_common.c @@ -17,9 +17,8 @@ * \ingroup modifiers */ -#include <string.h> - #include "BLI_listbase.h" +#include "BLI_string.h" #include "MEM_guardedalloc.h" @@ -230,14 +229,14 @@ static void modifier_ops_extra_draw(bContext *C, uiLayout *layout, void *md_v) /* Apply as shapekey. */ if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) { uiItemBooleanO(layout, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply As Shapekey"), + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"), ICON_SHAPEKEY_DATA, "OBJECT_OT_modifier_apply_as_shapekey", "keep_modifier", false); uiItemBooleanO(layout, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Save As Shapekey"), + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Save as Shape Key"), ICON_SHAPEKEY_DATA, "OBJECT_OT_modifier_apply_as_shapekey", "keep_modifier", @@ -406,10 +405,10 @@ PanelType *modifier_panel_register(ARegionType *region_type, ModifierType type, PanelType *panel_type = MEM_callocN(sizeof(PanelType), panel_idname); - strcpy(panel_type->idname, panel_idname); - strcpy(panel_type->label, ""); - strcpy(panel_type->context, "modifier"); - strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + BLI_strncpy(panel_type->idname, panel_idname, BKE_ST_MAXNAME); + BLI_strncpy(panel_type->label, "", BKE_ST_MAXNAME); + BLI_strncpy(panel_type->context, "modifier", BKE_ST_MAXNAME); + BLI_strncpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA, BKE_ST_MAXNAME); panel_type->draw_header = modifier_panel_header; panel_type->draw = draw; @@ -442,16 +441,14 @@ PanelType *modifier_subpanel_register(ARegionType *region_type, { /* Create the subpanel's ID name. */ char panel_idname[BKE_ST_MAXNAME]; - strcpy(panel_idname, parent->idname); - strcat(panel_idname, "_"); - strcat(panel_idname, name); + BLI_snprintf(panel_idname, BKE_ST_MAXNAME, "%s_%s", parent->idname, name); PanelType *panel_type = MEM_callocN(sizeof(PanelType), panel_idname); - strcpy(panel_type->idname, panel_idname); - strcpy(panel_type->label, label); - strcpy(panel_type->context, "modifier"); - strcpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + BLI_strncpy(panel_type->idname, panel_idname, BKE_ST_MAXNAME); + BLI_strncpy(panel_type->label, label, BKE_ST_MAXNAME); + BLI_strncpy(panel_type->context, "modifier", BKE_ST_MAXNAME); + BLI_strncpy(panel_type->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA, BKE_ST_MAXNAME); panel_type->draw_header = draw_header; panel_type->draw = draw; @@ -459,7 +456,7 @@ PanelType *modifier_subpanel_register(ARegionType *region_type, panel_type->flag = (PNL_DEFAULT_CLOSED | PNL_DRAW_BOX); BLI_assert(parent != NULL); - strcpy(panel_type->parent_id, parent->idname); + BLI_strncpy(panel_type->parent_id, parent->idname, BKE_ST_MAXNAME); panel_type->parent = parent; BLI_addtail(&parent->children, BLI_genericNodeN(panel_type)); BLI_addtail(®ion_type->paneltypes, panel_type); diff --git a/source/blender/modifiers/intern/MOD_ui_common.h b/source/blender/modifiers/intern/MOD_ui_common.h index 24ada426635..e7f801049b8 100644 --- a/source/blender/modifiers/intern/MOD_ui_common.h +++ b/source/blender/modifiers/intern/MOD_ui_common.h @@ -30,8 +30,8 @@ extern "C" { #endif struct ARegionType; -struct bContext; struct PanelType; +struct bContext; struct uiLayout; typedef void (*PanelDrawFn)(const bContext *, struct Panel *); diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index cc844e53603..e0802dc5fb4 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -202,10 +202,10 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, /* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether * we really need a copy here. Maybe the CoW ob->data can be directly used. */ Mesh *mesh_prior_modifiers = BKE_object_get_pre_modified_mesh(ob); - BKE_id_copy_ex(NULL, - &mesh_prior_modifiers->id, - (ID **)&mesh, - (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_CD_REFERENCE)); + mesh = (Mesh *)BKE_id_copy_ex(NULL, + &mesh_prior_modifiers->id, + NULL, + (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_CD_REFERENCE)); mesh->runtime.deformed_only = 1; } @@ -343,5 +343,8 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(SurfaceDeform); INIT_TYPE(WeightedNormal); INIT_TYPE(Simulation); + INIT_TYPE(MeshToVolume); + INIT_TYPE(VolumeDisplace); + INIT_TYPE(VolumeToMesh); #undef INIT_TYPE } diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 426ba640f2f..bfbc27abb88 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -31,6 +31,7 @@ #include "BLT_translation.h" #include "DNA_camera_types.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -61,9 +62,9 @@ static void initData(ModifierData *md) { UVProjectModifierData *umd = (UVProjectModifierData *)md; - umd->num_projectors = 1; - umd->aspectx = umd->aspecty = 1.0f; - umd->scalex = umd->scaley = 1.0f; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(umd, modifier)); + + MEMCPY_STRUCT_AFTER(umd, DNA_struct_default_get(UVProjectModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -74,23 +75,12 @@ static void requiredDataMask(Object *UNUSED(ob), r_cddata_masks->lmask |= CD_MLOOPUV; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) -{ - UVProjectModifierData *umd = (UVProjectModifierData *)md; - int i; - - for (i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; i++) { - walk(userData, ob, &umd->projectors[i], IDWALK_CB_NOP); - } -} - static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { -#if 0 UVProjectModifierData *umd = (UVProjectModifierData *)md; -#endif - - foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); + for (int i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; i++) { + walk(userData, ob, (ID **)&umd->projectors[i], IDWALK_CB_NOP); + } } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -366,9 +356,11 @@ ModifierTypeInfo modifierType_UVProject = { /* name */ "UVProject", /* structName */ "UVProjectModifierData", /* structSize */ sizeof(UVProjectModifierData), + /* srna */ &RNA_UVProjectModifier, /* type */ eModifierTypeType_NonGeometrical, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_UVPROJECT, /* copyData */ BKE_modifier_copydata_generic, @@ -388,7 +380,6 @@ ModifierTypeInfo modifierType_UVProject = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index f583709f311..b326494815e 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -63,10 +64,10 @@ static void uv_warp_from_mat4_pair(float uv_dst[2], static void initData(ModifierData *md) { UVWarpModifierData *umd = (UVWarpModifierData *)md; - umd->axis_u = 0; - umd->axis_v = 1; - copy_v2_fl(umd->center, 0.5f); - copy_v2_fl(umd->scale, 1.0f); + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(umd, modifier)); + + MEMCPY_STRUCT_AFTER(umd, DNA_struct_default_get(UVWarpModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -240,12 +241,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return mesh; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { UVWarpModifierData *umd = (UVWarpModifierData *)md; - walk(userData, ob, &umd->object_dst, IDWALK_CB_NOP); - walk(userData, ob, &umd->object_src, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&umd->object_dst, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&umd->object_src, IDWALK_CB_NOP); } static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) @@ -326,9 +327,11 @@ ModifierTypeInfo modifierType_UVWarp = { /* name */ "UVWarp", /* structName */ "UVWarpModifierData", /* structSize */ sizeof(UVWarpModifierData), + /* srna */ &RNA_UVWarpModifier, /* type */ eModifierTypeType_NonGeometrical, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_UVPROJECT, /* TODO: Use correct icon. */ /* copyData */ BKE_modifier_copydata_generic, @@ -348,8 +351,7 @@ ModifierTypeInfo modifierType_UVWarp = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, /* panelRegister */ panelRegister, diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc new file mode 100644 index 00000000000..f4e1936713c --- /dev/null +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -0,0 +1,348 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup modifiers + */ + +#include "BKE_lib_query.h" +#include "BKE_mesh_runtime.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_texture.h" +#include "BKE_volume.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_texture_types.h" +#include "DNA_volume_types.h" + +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "BLO_read_write.h" + +#include "MEM_guardedalloc.h" + +#include "MOD_modifiertypes.h" +#include "MOD_ui_common.h" + +#include "RE_texture.h" + +#include "RNA_access.h" + +#include "BLI_math_vector.h" + +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +# include <openvdb/tools/Interpolation.h> +# include <openvdb/tools/Morphology.h> +# include <openvdb/tools/Prune.h> +# include <openvdb/tools/ValueTransformer.h> +#endif + +static void initData(ModifierData *md) +{ + VolumeDisplaceModifierData *vdmd = reinterpret_cast<VolumeDisplaceModifierData *>(md); + vdmd->texture = nullptr; + vdmd->strength = 0.5f; + copy_v3_fl(vdmd->texture_mid_level, 0.5f); + vdmd->texture_sample_radius = 1.0f; +} + +static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +{ + VolumeDisplaceModifierData *vdmd = reinterpret_cast<VolumeDisplaceModifierData *>(md); + if (vdmd->texture != nullptr) { + DEG_add_generic_id_relation(ctx->node, &vdmd->texture->id, "Volume Displace Modifier"); + } + if (vdmd->texture_map_mode == MOD_VOLUME_DISPLACE_MAP_OBJECT) { + if (vdmd->texture_map_object != nullptr) { + DEG_add_object_relation( + ctx->node, vdmd->texture_map_object, DEG_OB_COMP_TRANSFORM, "Volume Displace Modifier"); + } + } +} + +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + VolumeDisplaceModifierData *vdmd = reinterpret_cast<VolumeDisplaceModifierData *>(md); + walk(userData, ob, (ID **)&vdmd->texture, IDWALK_CB_USER); + walk(userData, ob, (ID **)&vdmd->texture_map_object, IDWALK_CB_USER); +} + +static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) +{ + walk(userData, ob, md, "texture"); +} + +static bool dependsOnTime(ModifierData *md) +{ + VolumeDisplaceModifierData *vdmd = reinterpret_cast<VolumeDisplaceModifierData *>(md); + if (vdmd->texture) { + return BKE_texture_dependsOnTime(vdmd->texture); + } + return false; +} + +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); + VolumeDisplaceModifierData *vdmd = static_cast<VolumeDisplaceModifierData *>(ptr->data); + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + + uiTemplateID(layout, C, ptr, "texture", "texture.new", nullptr, nullptr, 0, ICON_NONE, nullptr); + uiItemR(layout, ptr, "texture_map_mode", 0, "Texture Mapping", ICON_NONE); + + if (vdmd->texture_map_mode == MOD_VOLUME_DISPLACE_MAP_OBJECT) { + uiItemR(layout, ptr, "texture_map_object", 0, "Object", ICON_NONE); + } + + uiItemR(layout, ptr, "strength", 0, nullptr, ICON_NONE); + uiItemR(layout, ptr, "texture_sample_radius", 0, "Sample Radius", ICON_NONE); + uiItemR(layout, ptr, "texture_mid_level", 0, "Mid Level", ICON_NONE); + + modifier_panel_end(layout, ptr); +} + +static void panelRegister(ARegionType *region_type) +{ + modifier_panel_register(region_type, eModifierType_VolumeDisplace, panel_draw); +} + +#ifdef WITH_OPENVDB + +static openvdb::Mat4s matrix_to_openvdb(const float m[4][4]) +{ + /* OpenVDB matrices are transposed Blender matrices, i.e. the translation is in the last row + * instead of in the last column. However, the layout in memory is the same, because OpenVDB + * matrices are row major (compared to Blender's column major matrices). */ + openvdb::Mat4s new_matrix{reinterpret_cast<const float *>(m)}; + return new_matrix; +} + +template<typename GridType> struct DisplaceOp { + /* Has to be copied for each thread. */ + typename GridType::ConstAccessor accessor; + const openvdb::Mat4s index_to_texture; + + Tex *texture; + const double strength; + const openvdb::Vec3d texture_mid_level; + + void operator()(const typename GridType::ValueOnIter &iter) const + { + const openvdb::Coord coord = iter.getCoord(); + const openvdb::Vec3d displace_vector = this->compute_displace_vector(coord); + /* Subtract vector because that makes the result more similar to advection and the mesh + * displace modifier. */ + const openvdb::Vec3d sample_coord = coord.asVec3d() - displace_vector; + const auto new_value = openvdb::tools::BoxSampler::sample(this->accessor, sample_coord); + iter.setValue(new_value); + } + + openvdb::Vec3d compute_displace_vector(const openvdb::Coord &coord) const + { + if (this->texture != nullptr) { + const openvdb::Vec3f texture_pos = coord.asVec3s() * this->index_to_texture; + const openvdb::Vec3d texture_value = this->evaluate_texture(texture_pos); + const openvdb::Vec3d displacement = (texture_value - this->texture_mid_level) * + this->strength; + return displacement; + } + return openvdb::Vec3d{0, 0, 0}; + } + + openvdb::Vec3d evaluate_texture(const openvdb::Vec3f &pos) const + { + TexResult texture_result = {0}; + BKE_texture_get_value( + nullptr, this->texture, const_cast<float *>(pos.asV()), &texture_result, false); + return {texture_result.tr, texture_result.tg, texture_result.tb}; + } +}; + +static float get_max_voxel_side_length(const openvdb::GridBase &grid) +{ + const openvdb::Vec3d voxel_size = grid.voxelSize(); + const float max_voxel_side_length = std::max({voxel_size[0], voxel_size[1], voxel_size[2]}); + return max_voxel_side_length; +} + +struct DisplaceGridOp { + /* This is the grid that will be displaced. The output is copied back to the original grid. */ + openvdb::GridBase &base_grid; + + VolumeDisplaceModifierData &vdmd; + const ModifierEvalContext &ctx; + + template<typename GridType> void operator()() + { + if constexpr (std::is_same_v<GridType, openvdb::points::PointDataGrid> || + std::is_same_v<GridType, openvdb::StringGrid> || + std::is_same_v<GridType, openvdb::MaskGrid>) { + /* We don't support displacing these grid types yet. */ + return; + } + else { + this->displace_grid<GridType>(); + } + } + + template<typename GridType> void displace_grid() + { + GridType &grid = static_cast<GridType &>(base_grid); + + /* Make a copy of the original grid to work on. This will replace the original grid. */ + typename GridType::Ptr temp_grid = grid.deepCopy(); + + /* Dilate grid, because the currently inactive cells might become active during the displace + * operation. The quality of the approximation of the has a big impact on performance. */ + const float max_voxel_side_length = get_max_voxel_side_length(grid); + const float sample_radius = vdmd.texture_sample_radius * std::abs(vdmd.strength) / + max_voxel_side_length / 2.0f; + openvdb::tools::dilateActiveValues(temp_grid->tree(), + static_cast<int>(std::ceil(sample_radius)), + openvdb::tools::NN_FACE_EDGE, + openvdb::tools::EXPAND_TILES); + + const openvdb::Mat4s index_to_texture = this->get_index_to_texture_transform(); + + /* Construct the operator that will be executed on every cell of the dilated grid. */ + DisplaceOp<GridType> displace_op{grid.getConstAccessor(), + index_to_texture, + vdmd.texture, + vdmd.strength / max_voxel_side_length, + openvdb::Vec3d{vdmd.texture_mid_level}}; + + /* Run the operator. This is multi-threaded. It is important that the operator is not shared + * between the threads, because it contains a non-thread-safe accessor for the old grid. */ + openvdb::tools::foreach (temp_grid->beginValueOn(), + displace_op, + true, + /* Disable sharing of the operator. */ false); + + /* It is likely that we produced too many active cells. Those are removed here, to avoid + * slowing down subsequent operations. */ + typename GridType::ValueType prune_tolerance{0}; + openvdb::tools::deactivate(*temp_grid, temp_grid->background(), prune_tolerance); + openvdb::tools::prune(temp_grid->tree()); + + /* Overwrite the old volume grid with the new grid. */ + grid.clear(); + grid.merge(*temp_grid); + } + + openvdb::Mat4s get_index_to_texture_transform() const + { + const openvdb::Mat4s index_to_object{ + base_grid.transform().baseMap()->getAffineMap()->getMat4()}; + + switch (vdmd.texture_map_mode) { + case MOD_VOLUME_DISPLACE_MAP_LOCAL: { + return index_to_object; + } + case MOD_VOLUME_DISPLACE_MAP_GLOBAL: { + const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->obmat); + return index_to_object * object_to_world; + } + case MOD_VOLUME_DISPLACE_MAP_OBJECT: { + if (vdmd.texture_map_object == nullptr) { + return index_to_object; + } + const openvdb::Mat4s object_to_world = matrix_to_openvdb(ctx.object->obmat); + const openvdb::Mat4s world_to_texture = matrix_to_openvdb(vdmd.texture_map_object->imat); + return index_to_object * object_to_world * world_to_texture; + } + } + BLI_assert(false); + return {}; + } +}; + +#endif + +static Volume *modifyVolume(ModifierData *md, const ModifierEvalContext *ctx, Volume *volume) +{ +#ifdef WITH_OPENVDB + VolumeDisplaceModifierData *vdmd = reinterpret_cast<VolumeDisplaceModifierData *>(md); + + /* Iterate over all grids and displace them one by one. */ + BKE_volume_load(volume, DEG_get_bmain(ctx->depsgraph)); + const int grid_amount = BKE_volume_num_grids(volume); + for (int grid_index = 0; grid_index < grid_amount; grid_index++) { + VolumeGrid *volume_grid = BKE_volume_grid_get(volume, grid_index); + BLI_assert(volume_grid != nullptr); + + openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(volume, volume_grid, false); + VolumeGridType grid_type = BKE_volume_grid_type(volume_grid); + + DisplaceGridOp displace_grid_op{*grid, *vdmd, *ctx}; + BKE_volume_grid_type_operation(grid_type, displace_grid_op); + } + + return volume; +#else + UNUSED_VARS(md, ctx); + BKE_modifier_set_error(ctx->object, md, "Compiled without OpenVDB"); + return volume; +#endif +} + +ModifierTypeInfo modifierType_VolumeDisplace = { + /* name */ "Volume Displace", + /* structName */ "VolumeDisplaceModifierData", + /* structSize */ sizeof(VolumeDisplaceModifierData), + /* srna */ &RNA_VolumeDisplaceModifier, + /* type */ eModifierTypeType_NonGeometrical, + /* flags */ static_cast<ModifierTypeFlag>(0), + /* icon */ ICON_VOLUME_DATA, /* TODO: Use correct icon. */ + + /* copyData */ BKE_modifier_copydata_generic, + + /* deformVerts */ nullptr, + /* deformMatrices */ nullptr, + /* deformVertsEM */ nullptr, + /* deformMatricesEM */ nullptr, + /* modifyMesh */ nullptr, + /* modifyHair */ nullptr, + /* modifyPointCloud */ nullptr, + /* modifyVolume */ modifyVolume, + + /* initData */ initData, + /* requiredDataMask */ nullptr, + /* freeData */ nullptr, + /* isDisabled */ nullptr, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ nullptr, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ foreachTexLink, + /* freeRuntimeData */ nullptr, + /* panelRegister */ panelRegister, + /* blendWrite */ nullptr, + /* blendRead */ nullptr, +}; diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc new file mode 100644 index 00000000000..e008dc3f140 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc @@ -0,0 +1,355 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup modifiers + */ + +#include <vector> + +#include "BKE_lib_query.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_volume.h" + +#include "MOD_modifiertypes.h" +#include "MOD_ui_common.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_volume_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "RNA_access.h" + +#include "BLI_float4x4.hh" +#include "BLI_math_vector.h" +#include "BLI_span.hh" +#include "BLI_timeit.hh" + +#include "DEG_depsgraph_query.h" + +#ifdef WITH_OPENVDB +# include <openvdb/tools/GridTransformer.h> +# include <openvdb/tools/VolumeToMesh.h> +#endif + +using blender::float3; +using blender::float4x4; +using blender::Span; + +static void initData(ModifierData *md) +{ + VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md); + vmmd->object = nullptr; + vmmd->threshold = 0.1f; + strncpy(vmmd->grid_name, "density", MAX_NAME); + vmmd->adaptivity = 0.0f; + vmmd->resolution_mode = VOLUME_TO_MESH_RESOLUTION_MODE_GRID; + vmmd->voxel_amount = 32; + vmmd->voxel_size = 0.1f; + vmmd->flag = 0; +} + +static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +{ + VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md); + DEG_add_modifier_to_transform_relation(ctx->node, "Volume to Mesh Modifier"); + if (vmmd->object) { + DEG_add_object_relation( + ctx->node, vmmd->object, DEG_OB_COMP_GEOMETRY, "Volume to Mesh Modifier"); + DEG_add_object_relation( + ctx->node, vmmd->object, DEG_OB_COMP_TRANSFORM, "Volume to Mesh Modifier"); + } +} + +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md); + walk(userData, ob, (ID **)&vmmd->object, IDWALK_CB_NOP); +} + +static void panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, nullptr); + VolumeToMeshModifierData *vmmd = static_cast<VolumeToMeshModifierData *>(ptr->data); + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + + { + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "object", 0, nullptr, ICON_NONE); + uiItemR(col, ptr, "grid_name", 0, nullptr, ICON_NONE); + } + + { + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "resolution_mode", 0, nullptr, ICON_NONE); + if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT) { + uiItemR(col, ptr, "voxel_amount", 0, nullptr, ICON_NONE); + } + else if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE) { + uiItemR(col, ptr, "voxel_size", 0, nullptr, ICON_NONE); + } + } + + { + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "threshold", 0, nullptr, ICON_NONE); + uiItemR(col, ptr, "adaptivity", 0, nullptr, ICON_NONE); + uiItemR(col, ptr, "use_smooth_shade", 0, nullptr, ICON_NONE); + } + + modifier_panel_end(layout, ptr); +} + +static void panelRegister(ARegionType *region_type) +{ + modifier_panel_register(region_type, eModifierType_VolumeToMesh, panel_draw); +} + +#ifdef WITH_OPENVDB + +struct VolumeToMeshOp { + const openvdb::GridBase &base_grid; + VolumeToMeshModifierData &vmmd; + const ModifierEvalContext &ctx; + std::vector<openvdb::Vec3s> verts; + std::vector<openvdb::Vec3I> tris; + std::vector<openvdb::Vec4I> quads; + + template<typename GridType> bool operator()() + { + if constexpr (std::is_scalar_v<typename GridType::ValueType>) { + this->generate_mesh_data<GridType>(); + return true; + } + else { + return false; + } + } + + template<typename GridType> void generate_mesh_data() + { + /* Make a new transform from the index space into the mesh object space. */ + openvdb::math::Transform::Ptr transform = this->base_grid.transform().copy(); + transform->postMult(openvdb::Mat4d((float *)vmmd.object->obmat)); + openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx.object->imat); + /* `imat` had floating point issues and wasn't affine. */ + imat.setCol(3, openvdb::Vec4d(0, 0, 0, 1)); + transform->postMult(imat); + + /* Create a new grid with a different transform. The underlying tree is shared. */ + typename GridType::ConstPtr grid = openvdb::gridConstPtrCast<GridType>( + this->base_grid.copyGridReplacingTransform(transform)); + + if (this->vmmd.resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_GRID) { + this->grid_to_mesh(*grid); + return; + } + + const float resolution_factor = this->compute_resolution_factor(*grid); + typename GridType::Ptr temp_grid = this->create_grid_with_changed_resolution( + *grid, resolution_factor); + this->grid_to_mesh(*temp_grid); + } + + template<typename GridType> + typename GridType::Ptr create_grid_with_changed_resolution(const GridType &old_grid, + const float resolution_factor) + { + BLI_assert(resolution_factor > 0.0f); + + openvdb::Mat4R xform; + xform.setToScale(openvdb::Vec3d(resolution_factor)); + openvdb::tools::GridTransformer transformer{xform}; + + typename GridType::Ptr new_grid = GridType::create(); + transformer.transformGrid<openvdb::tools::BoxSampler>(old_grid, *new_grid); + new_grid->transform() = old_grid.transform(); + new_grid->transform().preScale(1.0f / resolution_factor); + return new_grid; + } + + float compute_resolution_factor(const openvdb::GridBase &grid) const + { + const openvdb::Vec3s voxel_size{grid.voxelSize()}; + const float current_voxel_size = std::max({voxel_size[0], voxel_size[1], voxel_size[2]}); + const float desired_voxel_size = this->compute_desired_voxel_size(grid); + return current_voxel_size / desired_voxel_size; + } + + float compute_desired_voxel_size(const openvdb::GridBase &grid) const + { + if (this->vmmd.resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE) { + return this->vmmd.voxel_size; + } + const openvdb::CoordBBox coord_bbox = base_grid.evalActiveVoxelBoundingBox(); + const openvdb::BBoxd bbox = grid.transform().indexToWorld(coord_bbox); + const float max_extent = bbox.extents()[bbox.maxExtent()]; + const float voxel_size = max_extent / this->vmmd.voxel_amount; + return voxel_size; + } + + template<typename GridType> void grid_to_mesh(const GridType &grid) + { + openvdb::tools::volumeToMesh( + grid, this->verts, this->tris, this->quads, this->vmmd.threshold, this->vmmd.adaptivity); + } +}; + +static Mesh *new_mesh_from_openvdb_data(Span<openvdb::Vec3s> verts, + Span<openvdb::Vec3I> tris, + Span<openvdb::Vec4I> quads) +{ + const int tot_loops = 3 * tris.size() + 4 * quads.size(); + const int tot_polys = tris.size() + quads.size(); + + Mesh *mesh = BKE_mesh_new_nomain(verts.size(), 0, 0, tot_loops, tot_polys); + + /* Write vertices. */ + for (const int i : verts.index_range()) { + const blender::float3 co = blender::float3(verts[i].asV()); + copy_v3_v3(mesh->mvert[i].co, co); + } + + /* Write triangles. */ + for (const int i : tris.index_range()) { + mesh->mpoly[i].loopstart = 3 * i; + mesh->mpoly[i].totloop = 3; + for (int j = 0; j < 3; j++) { + /* Reverse vertex order to get correct normals. */ + mesh->mloop[3 * i + j].v = tris[i][2 - j]; + } + } + + /* Write quads. */ + const int poly_offset = tris.size(); + const int loop_offset = tris.size() * 3; + for (const int i : quads.index_range()) { + mesh->mpoly[poly_offset + i].loopstart = loop_offset + 4 * i; + mesh->mpoly[poly_offset + i].totloop = 4; + for (int j = 0; j < 4; j++) { + /* Reverse vertex order to get correct normals. */ + mesh->mloop[loop_offset + 4 * i + j].v = quads[i][3 - j]; + } + } + + BKE_mesh_calc_edges(mesh, false, false); + BKE_mesh_calc_normals(mesh); + return mesh; +} +#endif + +static Mesh *create_empty_mesh(const Mesh *input_mesh) +{ + Mesh *new_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0); + BKE_mesh_copy_settings(new_mesh, input_mesh); + return new_mesh; +} + +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *input_mesh) +{ +#ifdef WITH_OPENVDB + VolumeToMeshModifierData *vmmd = reinterpret_cast<VolumeToMeshModifierData *>(md); + if (vmmd->object == nullptr) { + return create_empty_mesh(input_mesh); + } + if (vmmd->object->type != OB_VOLUME) { + return create_empty_mesh(input_mesh); + } + if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE && + vmmd->voxel_size == 0.0f) { + return create_empty_mesh(input_mesh); + } + if (vmmd->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT && + vmmd->voxel_amount == 0) { + return create_empty_mesh(input_mesh); + } + + Volume *volume = static_cast<Volume *>(vmmd->object->data); + + BKE_volume_load(volume, DEG_get_bmain(ctx->depsgraph)); + VolumeGrid *volume_grid = BKE_volume_grid_find(volume, vmmd->grid_name); + if (volume_grid == nullptr) { + BKE_modifier_set_error(ctx->object, md, "Cannot find '%s' grid", vmmd->grid_name); + return create_empty_mesh(input_mesh); + } + + const openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); + + const VolumeGridType grid_type = BKE_volume_grid_type(volume_grid); + VolumeToMeshOp to_mesh_op{*grid, *vmmd, *ctx}; + if (!BKE_volume_grid_type_operation(grid_type, to_mesh_op)) { + BKE_modifier_set_error(ctx->object, md, "Expected a scalar grid"); + return create_empty_mesh(input_mesh); + } + + Mesh *mesh = new_mesh_from_openvdb_data(to_mesh_op.verts, to_mesh_op.tris, to_mesh_op.quads); + BKE_mesh_copy_settings(mesh, input_mesh); + if (vmmd->flag & VOLUME_TO_MESH_USE_SMOOTH_SHADE) { + BKE_mesh_smooth_flag_set(mesh, true); + } + return mesh; +#else + UNUSED_VARS(md); + BKE_modifier_set_error(ctx->object, md, "Compiled without OpenVDB"); + return create_empty_mesh(input_mesh); +#endif +} + +ModifierTypeInfo modifierType_VolumeToMesh = { + /* name */ "Volume to Mesh", + /* structName */ "VolumeToMeshModifierData", + /* structSize */ sizeof(VolumeToMeshModifierData), + /* srna */ &RNA_VolumeToMeshModifier, + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh, + /* icon */ ICON_VOLUME_DATA, /* TODO: Use correct icon. */ + + /* copyData */ BKE_modifier_copydata_generic, + + /* deformVerts */ nullptr, + /* deformMatrices */ nullptr, + /* deformVertsEM */ nullptr, + /* deformMatricesEM */ nullptr, + /* modifyMesh */ modifyMesh, + /* modifyHair */ nullptr, + /* modifyPointCloud */ nullptr, + /* modifyVolume */ nullptr, + + /* initData */ initData, + /* requiredDataMask */ nullptr, + /* freeData */ nullptr, + /* isDisabled */ nullptr, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ nullptr, + /* dependsOnNormals */ nullptr, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ nullptr, + /* freeRuntimeData */ nullptr, + /* panelRegister */ panelRegister, + /* blendWrite */ nullptr, + /* blendRead */ nullptr, +}; diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index bb0896994b1..53e41484606 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -28,6 +28,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -56,7 +57,7 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" -#include "RE_shader_ext.h" +#include "RE_texture.h" #include "MOD_ui_common.h" #include "MOD_util.h" @@ -65,12 +66,11 @@ static void initData(ModifierData *md) { WarpModifierData *wmd = (WarpModifierData *)md; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier)); + + MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WarpModifierData), modifier); + wmd->curfalloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - wmd->texture = NULL; - wmd->strength = 1.0f; - wmd->falloff_radius = 1.0f; - wmd->falloff_type = eWarp_Falloff_Smooth; - wmd->flag = 0; } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -142,22 +142,14 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return !(wmd->object_from && wmd->object_to); } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) -{ - WarpModifierData *wmd = (WarpModifierData *)md; - - walk(userData, ob, &wmd->object_from, IDWALK_CB_NOP); - walk(userData, ob, &wmd->object_to, IDWALK_CB_NOP); - walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP); -} - static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { WarpModifierData *wmd = (WarpModifierData *)md; walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER); - - foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); + walk(userData, ob, (ID **)&wmd->object_from, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&wmd->object_to, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&wmd->map_object, IDWALK_CB_NOP); } static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) @@ -279,8 +271,9 @@ static void warpModifier_do(WarpModifierData *wmd, /* skip if no vert group found */ if (defgrp_index != -1) { dv = &dvert[i]; - weight = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) * strength : - BKE_defvert_find_weight(dv, defgrp_index) * strength; + weight = (invert_vgroup ? (1.0f - BKE_defvert_find_weight(dv, defgrp_index)) : + BKE_defvert_find_weight(dv, defgrp_index)) * + strength; if (weight <= 0.0f) { continue; } @@ -532,9 +525,11 @@ ModifierTypeInfo modifierType_Warp = { /* name */ "Warp", /* structName */ "WarpModifierData", /* structSize */ sizeof(WarpModifierData), + /* srna */ &RNA_WarpModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_WARP, /* copyData */ copyData, /* deformVerts */ deformVerts, @@ -553,7 +548,6 @@ ModifierTypeInfo modifierType_Warp = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index ae0c59ed9ef..45f06a7778c 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -27,6 +27,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -50,7 +51,8 @@ #include "RNA_access.h" #include "MEM_guardedalloc.h" -#include "RE_shader_ext.h" + +#include "RE_texture.h" #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" @@ -61,23 +63,11 @@ static void initData(ModifierData *md) { - WaveModifierData *wmd = (WaveModifierData *)md; // whadya know, moved here from Iraq - - wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | - MOD_WAVE_NORM_Z); - - wmd->objectcenter = NULL; - wmd->texture = NULL; - wmd->map_object = NULL; - wmd->height = 0.5f; - wmd->width = 1.5f; - wmd->speed = 0.25f; - wmd->narrow = 1.5f; - wmd->lifetime = 0.0f; - wmd->damp = 10.0f; - wmd->falloff = 0.0f; - wmd->texmapping = MOD_DISP_MAP_LOCAL; - wmd->defgrp_name[0] = 0; + WaveModifierData *wmd = (WaveModifierData *)md; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier)); + + MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WaveModifierData), modifier); } static bool dependsOnTime(ModifierData *UNUSED(md)) @@ -85,21 +75,13 @@ static bool dependsOnTime(ModifierData *UNUSED(md)) return true; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) -{ - WaveModifierData *wmd = (WaveModifierData *)md; - - walk(userData, ob, &wmd->objectcenter, IDWALK_CB_NOP); - walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP); -} - static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { WaveModifierData *wmd = (WaveModifierData *)md; walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER); - - foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); + walk(userData, ob, (ID **)&wmd->objectcenter, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&wmd->map_object, IDWALK_CB_NOP); } static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) @@ -495,9 +477,11 @@ ModifierTypeInfo modifierType_Wave = { /* name */ "Wave", /* structName */ "WaveModifierData", /* structSize */ sizeof(WaveModifierData), + /* srna */ &RNA_WaveModifier, /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_WAVE, /* copyData */ BKE_modifier_copydata_generic, @@ -517,7 +501,6 @@ ModifierTypeInfo modifierType_Wave = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index fc7ac822874..bd15d909834 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -26,6 +26,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -573,12 +574,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) #endif { - BKE_modifier_set_error((ModifierData *)wnmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error( + ctx->object, (ModifierData *)wnmd, "Enable 'Auto Smooth' in Object Data Properties"); return mesh; } Mesh *result; - BKE_id_copy_ex(NULL, &mesh->id, (ID **)&result, LIB_ID_COPY_LOCALIZE); + result = (Mesh *)BKE_id_copy_ex(NULL, &mesh->id, NULL, LIB_ID_COPY_LOCALIZE); const int numVerts = result->totvert; const int numEdges = result->totedge; @@ -686,10 +688,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * static void initData(ModifierData *md) { WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md; - wnmd->mode = MOD_WEIGHTEDNORMAL_MODE_FACE; - wnmd->weight = 50; - wnmd->thresh = 1e-2f; - wnmd->flag = 0; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wnmd, modifier)); + + MEMCPY_STRUCT_AFTER(wnmd, DNA_struct_default_get(WeightedNormalModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -731,7 +733,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) col = uiLayoutColumn(layout, false); uiItemR(col, ptr, "keep_sharp", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "face_influence", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_face_influence", 0, NULL, ICON_NONE); modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); @@ -747,9 +749,11 @@ ModifierTypeInfo modifierType_WeightedNormal = { /* name */ "WeightedNormal", /* structName */ "WeightedNormalModifierData", /* structSize */ sizeof(WeightedNormalModifierData), + /* srna */ &RNA_WeightedNormalModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, + /* icon */ ICON_MOD_VERTEX_WEIGHT, /* copyData */ BKE_modifier_copydata_generic, @@ -769,7 +773,6 @@ ModifierTypeInfo modifierType_WeightedNormal = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index 4ee1f9f669a..c5e2ecb9660 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -55,7 +55,7 @@ #include "MOD_ui_common.h" #include "MOD_util.h" #include "MOD_weightvg_util.h" -#include "RE_shader_ext.h" /* Texture masking. */ +#include "RE_texture.h" /* Texture masking. */ /* Maps new_w weights in place, using either one of the predefined functions, or a custom curve. * Return values are in new_w. @@ -249,9 +249,10 @@ void weightvg_do_mask(const ModifierEvalContext *ctx, /* For each weight (vertex), make the mix between org and new weights. */ for (i = 0; i < num; i++) { int idx = indices ? indices[i] : i; - const float f = invert_vgroup_mask ? - 1.0f - BKE_defvert_find_weight(&dvert[idx], ref_didx) * fact : - BKE_defvert_find_weight(&dvert[idx], ref_didx) * fact; + const float f = (invert_vgroup_mask ? + (1.0f - BKE_defvert_find_weight(&dvert[idx], ref_didx)) : + BKE_defvert_find_weight(&dvert[idx], ref_didx)) * + fact; org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f - f)); /* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */ } diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 4cc19ab895e..df554f6bc4e 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -21,6 +21,8 @@ * \ingroup modifiers */ +#include <string.h> + #include "BLI_utildefines.h" #include "BLI_ghash.h" @@ -30,6 +32,7 @@ #include "BLT_translation.h" #include "DNA_color_types.h" /* CurveMapping. */ +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -67,19 +70,13 @@ static void initData(ModifierData *md) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; - wmd->edit_flags = 0; - wmd->falloff_type = MOD_WVG_MAPPING_NONE; - wmd->default_weight = 0.0f; - wmd->cmap_curve = BKE_curvemapping_add(1, 0.0, 0.0, 1.0, 1.0); - BKE_curvemapping_init(wmd->cmap_curve); + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier)); - wmd->rem_threshold = 0.01f; - wmd->add_threshold = 0.01f; + MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeightVGEditModifierData), modifier); - wmd->mask_constant = 1.0f; - wmd->mask_tex_use_channel = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */ - wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL; + wmd->cmap_curve = BKE_curvemapping_add(1, 0.0, 0.0, 1.0, 1.0); + BKE_curvemapping_init(wmd->cmap_curve); } static void freeData(ModifierData *md) @@ -125,19 +122,12 @@ static bool dependsOnTime(ModifierData *md) return false; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) -{ - WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; - walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP); -} - static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER); - - foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); + walk(userData, ob, (ID **)&wmd->mask_tex_map_obj, IDWALK_CB_NOP); } static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) @@ -423,9 +413,11 @@ ModifierTypeInfo modifierType_WeightVGEdit = { /* name */ "VertexWeightEdit", /* structName */ "WeightVGEditModifierData", /* structSize */ sizeof(WeightVGEditModifierData), + /* srna */ &RNA_VertexWeightEditModifier, /* type */ eModifierTypeType_NonGeometrical, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, + /* icon */ ICON_MOD_VERTEX_WEIGHT, /* copyData */ copyData, @@ -445,7 +437,6 @@ ModifierTypeInfo modifierType_WeightVGEdit = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 81d4a04fa78..9be36fe6846 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -28,6 +28,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -131,14 +132,9 @@ static void initData(ModifierData *md) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md; - wmd->default_weight_a = 0.0f; - wmd->default_weight_b = 0.0f; - wmd->mix_mode = MOD_WVG_MIX_SET; - wmd->mix_set = MOD_WVG_SET_AND; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier)); - wmd->mask_constant = 1.0f; - wmd->mask_tex_use_channel = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */ - wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL; + MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeightVGMixModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -168,19 +164,12 @@ static bool dependsOnTime(ModifierData *md) return false; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) -{ - WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md; - walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP); -} - static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md; walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER); - - foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); + walk(userData, ob, (ID **)&wmd->mask_tex_map_obj, IDWALK_CB_NOP); } static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) @@ -510,9 +499,11 @@ ModifierTypeInfo modifierType_WeightVGMix = { /* name */ "VertexWeightMix", /* structName */ "WeightVGMixModifierData", /* structSize */ sizeof(WeightVGMixModifierData), + /* srna */ &RNA_VertexWeightMixModifier, /* type */ eModifierTypeType_NonGeometrical, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, + /* icon */ ICON_MOD_VERTEX_WEIGHT, /* copyData */ BKE_modifier_copydata_generic, @@ -532,7 +523,6 @@ ModifierTypeInfo modifierType_WeightVGMix = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 994f2c04921..9b21c77268e 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -31,6 +31,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -45,6 +46,7 @@ #include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_mesh.h" +#include "BKE_mesh_wrapper.h" #include "BKE_modifier.h" #include "BKE_screen.h" #include "BKE_texture.h" /* Texture masking. */ @@ -315,15 +317,9 @@ static void initData(ModifierData *md) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md; - wmd->proximity_mode = MOD_WVG_PROXIMITY_OBJECT; - wmd->proximity_flags = MOD_WVG_PROXIMITY_GEOM_VERTS; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier)); - wmd->falloff_type = MOD_WVG_MAPPING_NONE; - - wmd->mask_constant = 1.0f; - wmd->mask_tex_use_channel = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */ - wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL; - wmd->max_dist = 1.0f; /* vert arbitrary distance, but don't use 0 */ + MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeightVGProximityModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -353,20 +349,13 @@ static bool dependsOnTime(ModifierData *md) return 0; } -static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) -{ - WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md; - walk(userData, ob, &wmd->proximity_ob_target, IDWALK_CB_NOP); - walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP); -} - static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md; walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER); - - foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); + walk(userData, ob, (ID **)&wmd->proximity_ob_target, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&wmd->mask_tex_map_obj, IDWALK_CB_NOP); } static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) @@ -552,6 +541,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* We must check that we do have a valid target_mesh! */ if (target_mesh != NULL) { + + /* TODO: edit-mode versions of the BVH lookup functions are available so it could be + * avoided. */ + BKE_mesh_wrapper_ensure_mdata(target_mesh); + SpaceTransform loc2trgt; float *dists_v = use_trgt_verts ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_v") : NULL; @@ -713,9 +707,11 @@ ModifierTypeInfo modifierType_WeightVGProximity = { /* name */ "VertexWeightProximity", /* structName */ "WeightVGProximityModifierData", /* structSize */ sizeof(WeightVGProximityModifierData), + /* srna */ &RNA_VertexWeightProximityModifier, /* type */ eModifierTypeType_NonGeometrical, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, + /* icon */ ICON_MOD_VERTEX_WEIGHT, /* copyData */ BKE_modifier_copydata_generic, @@ -735,7 +731,6 @@ ModifierTypeInfo modifierType_WeightVGProximity = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index 855f96df82f..1a25c24fedc 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -27,23 +27,32 @@ * - Review weight and vertex color interpolation.; */ +//#define USE_WELD_DEBUG +//#define USE_WELD_NORMALS +//#define USE_BVHTREEKDOP + #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" #include "BLI_alloca.h" -#include "BLI_kdopbvh.h" +#include "BLI_bitmap.h" +#include "BLI_kdtree.h" #include "BLI_math.h" #include "BLT_translation.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_screen_types.h" -#include "BKE_bvhutils.h" +#ifdef USE_BVHTREEKDOP +# include "BKE_bvhutils.h" +#endif + #include "BKE_context.h" #include "BKE_deform.h" #include "BKE_mesh.h" @@ -60,9 +69,6 @@ #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" -//#define USE_WELD_DEBUG -//#define USE_WELD_NORMALS - /* Indicates when the element was not computed. */ #define OUT_OF_CONTEXT (uint)(-1) /* Indicates if the edge or face will be collapsed. */ @@ -136,9 +142,6 @@ typedef struct WeldMesh { /* Group of vertices to be merged. */ struct WeldGroup *vert_groups; uint *vert_groups_buffer; - /* From the original index of the vertex, this indicates which group it is or is going to be - * merged. */ - uint *vert_groups_map; /* Group of edges to be merged. */ struct WeldGroupEdge *edge_groups; @@ -202,21 +205,6 @@ static bool weld_iter_loop_of_poly_begin(WeldLoopOfPolyIter *iter, static bool weld_iter_loop_of_poly_next(WeldLoopOfPolyIter *iter); -static void weld_assert_vert_dest_map_setup(const BVHTreeOverlap *overlap, - const uint overlap_len, - const uint *vert_dest_map) -{ - const BVHTreeOverlap *overlap_iter = &overlap[0]; - for (uint i = overlap_len; i--; overlap_iter++) { - uint indexA = overlap_iter->indexA; - uint indexB = overlap_iter->indexB; - uint va_dst = vert_dest_map[indexA]; - uint vb_dst = vert_dest_map[indexB]; - - BLI_assert(va_dst == vb_dst); - } -} - static void weld_assert_edge_kill_len(const WeldEdge *wedge, const uint wedge_len, const uint supposed_kill_len) @@ -383,69 +371,10 @@ static void weld_assert_poly_len(const WeldPoly *wp, const WeldLoop *wloop) * \{ */ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len, - const BVHTreeOverlap *overlap, - const uint overlap_len, uint *r_vert_dest_map, WeldVert **r_wvert, - uint *r_wvert_len, - uint *r_vert_kill_len) + uint *r_wvert_len) { - uint *v_dest_iter = &r_vert_dest_map[0]; - for (uint i = mvert_len; i--; v_dest_iter++) { - *v_dest_iter = OUT_OF_CONTEXT; - } - - uint vert_kill_len = 0; - const BVHTreeOverlap *overlap_iter = &overlap[0]; - for (uint i = 0; i < overlap_len; i++, overlap_iter++) { - uint indexA = overlap_iter->indexA; - uint indexB = overlap_iter->indexB; - - BLI_assert(indexA < indexB); - - uint va_dst = r_vert_dest_map[indexA]; - uint vb_dst = r_vert_dest_map[indexB]; - if (va_dst == OUT_OF_CONTEXT) { - if (vb_dst == OUT_OF_CONTEXT) { - vb_dst = indexA; - r_vert_dest_map[indexB] = vb_dst; - } - r_vert_dest_map[indexA] = vb_dst; - vert_kill_len++; - } - else if (vb_dst == OUT_OF_CONTEXT) { - r_vert_dest_map[indexB] = va_dst; - vert_kill_len++; - } - else if (va_dst != vb_dst) { - uint v_new, v_old; - if (va_dst < vb_dst) { - v_new = va_dst; - v_old = vb_dst; - } - else { - v_new = vb_dst; - v_old = va_dst; - } - BLI_assert(r_vert_dest_map[v_old] == v_old); - BLI_assert(r_vert_dest_map[v_new] == v_new); - vert_kill_len++; - - const BVHTreeOverlap *overlap_iter_b = &overlap[0]; - for (uint j = i + 1; j--; overlap_iter_b++) { - indexA = overlap_iter_b->indexA; - indexB = overlap_iter_b->indexB; - va_dst = r_vert_dest_map[indexA]; - vb_dst = r_vert_dest_map[indexB]; - if (ELEM(v_old, vb_dst, va_dst)) { - r_vert_dest_map[indexA] = v_new; - r_vert_dest_map[indexB] = v_new; - } - } - BLI_assert(r_vert_dest_map[v_old] == v_new); - } - } - /* Vert Context. */ uint wvert_len = 0; @@ -453,7 +382,7 @@ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len, wvert = MEM_mallocN(sizeof(*wvert) * mvert_len, __func__); wv = &wvert[0]; - v_dest_iter = &r_vert_dest_map[0]; + uint *v_dest_iter = &r_vert_dest_map[0]; for (uint i = 0; i < mvert_len; i++, v_dest_iter++) { if (*v_dest_iter != OUT_OF_CONTEXT) { wv->vert_dest = *v_dest_iter; @@ -463,13 +392,8 @@ static void weld_vert_ctx_alloc_and_setup(const uint mvert_len, } } -#ifdef USE_WELD_DEBUG - weld_assert_vert_dest_map_setup(overlap, overlap_len, r_vert_dest_map); -#endif - *r_wvert = MEM_reallocN(wvert, sizeof(*wvert) * wvert_len); *r_wvert_len = wvert_len; - *r_vert_kill_len = vert_kill_len; } static void weld_vert_groups_setup(const uint mvert_len, @@ -1395,8 +1319,8 @@ static void weld_poly_loop_ctx_setup(const MLoop *mloop, * \{ */ static void weld_mesh_context_create(const Mesh *mesh, - BVHTreeOverlap *overlap, - const uint overlap_len, + uint *vert_dest_map, + const uint vert_kill_len, WeldMesh *r_weld_mesh) { const MEdge *medge = mesh->medge; @@ -1407,19 +1331,13 @@ static void weld_mesh_context_create(const Mesh *mesh, const uint mloop_len = mesh->totloop; const uint mpoly_len = mesh->totpoly; - uint *vert_dest_map = MEM_mallocN(sizeof(*vert_dest_map) * mvert_len, __func__); uint *edge_dest_map = MEM_mallocN(sizeof(*edge_dest_map) * medge_len, __func__); struct WeldGroup *v_links = MEM_callocN(sizeof(*v_links) * mvert_len, __func__); WeldVert *wvert; uint wvert_len; - weld_vert_ctx_alloc_and_setup(mvert_len, - overlap, - overlap_len, - vert_dest_map, - &wvert, - &wvert_len, - &r_weld_mesh->vert_kill_len); + r_weld_mesh->vert_kill_len = vert_kill_len; + weld_vert_ctx_alloc_and_setup(mvert_len, vert_dest_map, &wvert, &wvert_len); uint *edge_ctx_map; WeldEdge *wedge; @@ -1462,7 +1380,6 @@ static void weld_mesh_context_create(const Mesh *mesh, &r_weld_mesh->edge_groups_buffer, &r_weld_mesh->edge_groups); - r_weld_mesh->vert_groups_map = vert_dest_map; r_weld_mesh->edge_groups_map = edge_dest_map; MEM_freeN(v_links); MEM_freeN(wvert); @@ -1474,7 +1391,6 @@ static void weld_mesh_context_free(WeldMesh *weld_mesh) { MEM_freeN(weld_mesh->vert_groups); MEM_freeN(weld_mesh->vert_groups_buffer); - MEM_freeN(weld_mesh->vert_groups_map); MEM_freeN(weld_mesh->edge_groups); MEM_freeN(weld_mesh->edge_groups_buffer); @@ -1633,6 +1549,7 @@ static void customdata_weld( /** \name Weld Modifier Main * \{ */ +#ifdef USE_BVHTREEKDOP struct WeldOverlapData { const MVert *mvert; float merge_dist_sq; @@ -1648,6 +1565,7 @@ static bool bvhtree_weld_overlap_cb(void *userdata, int index_a, int index_b, in } return false; } +#endif static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContext *ctx, Mesh *mesh) { @@ -1661,7 +1579,6 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex const MLoop *mloop; const MPoly *mpoly, *mp; uint totvert, totedge, totloop, totpoly; - uint i; mvert = mesh->mvert; totvert = mesh->totvert; @@ -1675,7 +1592,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex const bool invert_vgroup = (wmd->flag & MOD_WELD_INVERT_VGROUP) != 0; dv = &dvert[0]; v_mask = BLI_BITMAP_NEW(totvert, __func__); - for (i = 0; i < totvert; i++, dv++) { + for (uint i = 0; i < totvert; i++, dv++) { const bool found = BKE_defvert_find_weight(dv, defgrp_index) > 0.0f; if (found != invert_vgroup) { BLI_BITMAP_ENABLE(v_mask, i); @@ -1685,48 +1602,113 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex } } - /* Get overlap map. */ - /* TODO: For a better performanse use KD-Tree. */ - struct BVHTreeFromMesh treedata; - BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata, - mvert, - totvert, - false, - v_mask, - v_mask_act, - wmd->merge_dist / 2, - 2, - 6, - 0, - NULL, - NULL); + /* From the original index of the vertex. + * This indicates which vert it is or is going to be merged. */ + uint *vert_dest_map = MEM_malloc_arrayN(totvert, sizeof(*vert_dest_map), __func__); + uint vert_kill_len = 0; +#ifdef USE_BVHTREEKDOP + { + /* Get overlap map. */ + struct BVHTreeFromMesh treedata; + BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata, + mvert, + totvert, + false, + v_mask, + v_mask_act, + wmd->merge_dist / 2, + 2, + 6, + 0, + NULL, + NULL); + + if (bvhtree) { + struct WeldOverlapData data; + data.mvert = mvert; + data.merge_dist_sq = square_f(wmd->merge_dist); + + uint overlap_len; + BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree, + bvhtree, + &overlap_len, + bvhtree_weld_overlap_cb, + &data, + 1, + BVH_OVERLAP_RETURN_PAIRS); + + free_bvhtree_from_mesh(&treedata); + if (overlap) { + range_vn_u(vert_dest_map, totvert, 0); + + const BVHTreeOverlap *overlap_iter = &overlap[0]; + for (uint i = 0; i < overlap_len; i++, overlap_iter++) { + uint indexA = overlap_iter->indexA; + uint indexB = overlap_iter->indexB; + + BLI_assert(indexA < indexB); + + uint va_dst = vert_dest_map[indexA]; + while (va_dst != vert_dest_map[va_dst]) { + va_dst = vert_dest_map[va_dst]; + } + uint vb_dst = vert_dest_map[indexB]; + while (vb_dst != vert_dest_map[vb_dst]) { + vb_dst = vert_dest_map[vb_dst]; + } + if (va_dst == vb_dst) { + continue; + } + if (va_dst > vb_dst) { + SWAP(uint, va_dst, vb_dst); + } + vert_kill_len++; + vert_dest_map[vb_dst] = va_dst; + } - if (v_mask) { - MEM_freeN(v_mask); - } + /* Fix #r_vert_dest_map for next step. */ + for (uint i = 0; i < totvert; i++) { + if (i == vert_dest_map[i]) { + vert_dest_map[i] = OUT_OF_CONTEXT; + } + else { + uint v = i; + while (v != vert_dest_map[v] && vert_dest_map[v] != OUT_OF_CONTEXT) { + v = vert_dest_map[v]; + } + vert_dest_map[v] = v; + vert_dest_map[i] = v; + } + } - if (bvhtree == NULL) { - return result; + MEM_freeN(overlap); + } + } } +#else + { + KDTree_3d *tree = BLI_kdtree_3d_new(v_mask ? v_mask_act : totvert); + for (uint i = 0; i < totvert; i++) { + if (!v_mask || BLI_BITMAP_TEST(v_mask, i)) { + BLI_kdtree_3d_insert(tree, i, mvert[i].co); + } + vert_dest_map[i] = OUT_OF_CONTEXT; + } - struct WeldOverlapData data; - data.mvert = mvert; - data.merge_dist_sq = square_f(wmd->merge_dist); - - uint overlap_len; - BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree, - bvhtree, - &overlap_len, - bvhtree_weld_overlap_cb, - &data, - wmd->max_interactions, - BVH_OVERLAP_RETURN_PAIRS); + BLI_kdtree_3d_balance(tree); + vert_kill_len = BLI_kdtree_3d_calc_duplicates_fast( + tree, wmd->merge_dist, false, (int *)vert_dest_map); + BLI_kdtree_3d_free(tree); + } +#endif - free_bvhtree_from_mesh(&treedata); + if (v_mask) { + MEM_freeN(v_mask); + } - if (overlap_len) { + if (vert_kill_len) { WeldMesh weld_mesh; - weld_mesh_context_create(mesh, overlap, overlap_len, &weld_mesh); + weld_mesh_context_create(mesh, vert_dest_map, vert_kill_len, &weld_mesh); mloop = mesh->mloop; mpoly = mesh->mpoly; @@ -1745,10 +1727,10 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex /* Vertices */ - uint *vert_final = weld_mesh.vert_groups_map; + uint *vert_final = vert_dest_map; uint *index_iter = &vert_final[0]; int dest_index = 0; - for (i = 0; i < totvert; i++, index_iter++) { + for (uint i = 0; i < totvert; i++, index_iter++) { int source_index = i; int count = 0; while (i < totvert && *index_iter == OUT_OF_CONTEXT) { @@ -1783,7 +1765,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex uint *edge_final = weld_mesh.edge_groups_map; index_iter = &edge_final[0]; dest_index = 0; - for (i = 0; i < totedge; i++, index_iter++) { + for (uint i = 0; i < totedge; i++, index_iter++) { int source_index = i; int count = 0; while (i < totedge && *index_iter == OUT_OF_CONTEXT) { @@ -1831,7 +1813,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex uint r_i = 0; int loop_cur = 0; uint *group_buffer = BLI_array_alloca(group_buffer, weld_mesh.max_poly_len); - for (i = 0; i < totpoly; i++, mp++) { + for (uint i = 0; i < totpoly; i++, mp++) { int loop_start = loop_cur; uint poly_ctx = weld_mesh.poly_map[i]; if (poly_ctx == OUT_OF_CONTEXT) { @@ -1877,7 +1859,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex } WeldPoly *wp = &weld_mesh.wpoly_new[0]; - for (i = 0; i < weld_mesh.wpoly_new_len; i++, wp++) { + for (uint i = 0; i < weld_mesh.wpoly_new_len; i++, wp++) { int loop_start = loop_cur; WeldLoopOfPolyIter iter; if (!weld_iter_loop_of_poly_begin( @@ -1918,7 +1900,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex weld_mesh_context_free(&weld_mesh); } - MEM_freeN(overlap); + MEM_freeN(vert_dest_map); return result; } @@ -1932,9 +1914,9 @@ static void initData(ModifierData *md) { WeldModifierData *wmd = (WeldModifierData *)md; - wmd->merge_dist = 0.001f; - wmd->max_interactions = 1; - wmd->defgrp_name[0] = '\0'; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier)); + + MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeldModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -1959,7 +1941,6 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); uiItemR(layout, ptr, "merge_threshold", 0, IFACE_("Distance"), ICON_NONE); - uiItemR(layout, ptr, "max_interactions", 0, NULL, ICON_NONE); modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); modifier_panel_end(layout, ptr); @@ -1974,10 +1955,12 @@ ModifierTypeInfo modifierType_Weld = { /* name */ "Weld", /* structName */ "WeldModifierData", /* structSize */ sizeof(WeldModifierData), + /* srna */ &RNA_WeldModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, + /* icon */ ICON_AUTOMERGE_OFF, /* TODO: Use correct icon. */ /* copyData */ BKE_modifier_copydata_generic, @@ -1997,7 +1980,6 @@ ModifierTypeInfo modifierType_Weld = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 602e0bf3eda..206c514826c 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -24,6 +24,7 @@ #include "BLT_translation.h" +#include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" @@ -47,9 +48,10 @@ static void initData(ModifierData *md) { WireframeModifierData *wmd = (WireframeModifierData *)md; - wmd->offset = 0.02f; - wmd->flag = MOD_WIREFRAME_REPLACE | MOD_WIREFRAME_OFS_EVEN; - wmd->crease_weight = 1.0f; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier)); + + MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WireframeModifierData), modifier); } static void requiredDataMask(Object *UNUSED(ob), @@ -180,8 +182,10 @@ ModifierTypeInfo modifierType_Wireframe = { /* name */ "Wireframe", /* structName */ "WireframeModifierData", /* structSize */ sizeof(WireframeModifierData), + /* srna */ &RNA_WireframeModifier, /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, + /* icon */ ICON_MOD_WIREFRAME, /* copyData */ BKE_modifier_copydata_generic, @@ -201,7 +205,6 @@ ModifierTypeInfo modifierType_Wireframe = { /* updateDepgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, - /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, /* freeRuntimeData */ NULL, |