diff options
Diffstat (limited to 'source/blender/modifiers')
61 files changed, 1233 insertions, 3125 deletions
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 73daabec9b3..8bace2e048c 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -65,7 +65,6 @@ set(SRC intern/MOD_mirror.c intern/MOD_multires.c intern/MOD_nodes.cc - intern/MOD_nodes_evaluator.cc intern/MOD_none.c intern/MOD_normal_edit.c intern/MOD_ocean.c @@ -105,7 +104,6 @@ set(SRC MOD_modifiertypes.h MOD_nodes.h intern/MOD_meshcache_util.h - intern/MOD_nodes_evaluator.hh intern/MOD_solidify_util.h intern/MOD_ui_common.h intern/MOD_util.h diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 43f650e025c..8e627f9964d 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -68,9 +68,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tamd->vert_coords_prev = NULL; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *UNUSED(md), - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *UNUSED(md), CustomData_MeshMasks *r_cddata_masks) { /* ask for vertexgroups */ r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index b29b34436ca..bf534b0d586 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -279,18 +279,20 @@ static void mesh_merge_transform(Mesh *result, MEdge *me; MLoop *ml; MPoly *mp; + MVert *result_verts = BKE_mesh_verts_for_write(result); + MEdge *result_edges = BKE_mesh_edges_for_write(result); + MPoly *result_polys = BKE_mesh_polys_for_write(result); + MLoop *result_loops = BKE_mesh_loops_for_write(result); CustomData_copy_data(&cap_mesh->vdata, &result->vdata, 0, cap_verts_index, cap_nverts); CustomData_copy_data(&cap_mesh->edata, &result->edata, 0, cap_edges_index, cap_nedges); CustomData_copy_data(&cap_mesh->ldata, &result->ldata, 0, cap_loops_index, cap_nloops); CustomData_copy_data(&cap_mesh->pdata, &result->pdata, 0, cap_polys_index, cap_npolys); - mv = result->mvert + cap_verts_index; + mv = result_verts + cap_verts_index; for (i = 0; i < cap_nverts; i++, mv++) { mul_m4_v3(cap_offset, mv->co); - /* Reset MVert flags for caps */ - mv->flag = mv->bweight = 0; } /* We have to correct normals too, if we do not tag them as dirty later! */ @@ -303,26 +305,26 @@ static void mesh_merge_transform(Mesh *result, } /* remap the vertex groups if necessary */ - if (result->dvert != NULL) { - BKE_object_defgroup_index_map_apply( - &result->dvert[cap_verts_index], cap_nverts, remap, remap_len); + if (BKE_mesh_deform_verts(result) != NULL) { + MDeformVert *dvert = BKE_mesh_deform_verts_for_write(result); + BKE_object_defgroup_index_map_apply(&dvert[cap_verts_index], cap_nverts, remap, remap_len); } /* adjust cap edge vertex indices */ - me = result->medge + cap_edges_index; + me = result_edges + cap_edges_index; for (i = 0; i < cap_nedges; i++, me++) { me->v1 += cap_verts_index; me->v2 += cap_verts_index; } /* adjust cap poly loopstart indices */ - mp = result->mpoly + cap_polys_index; + mp = result_polys + cap_polys_index; for (i = 0; i < cap_npolys; i++, mp++) { mp->loopstart += cap_loops_index; } /* adjust cap loop vertex and edge indices */ - ml = result->mloop + cap_loops_index; + ml = result_loops + cap_loops_index; for (i = 0; i < cap_nloops; i++, ml++) { ml->v += cap_verts_index; ml->e += cap_edges_index; @@ -352,11 +354,8 @@ static void mesh_merge_transform(Mesh *result, static Mesh *arrayModifier_doArray(ArrayModifierData *amd, const ModifierEvalContext *ctx, - Mesh *mesh) + const Mesh *mesh) { - const MVert *src_mvert; - MVert *result_dm_verts; - MEdge *me; MLoop *ml; MPoly *mp; @@ -429,7 +428,10 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, /* Build up offset array, accumulating all settings options. */ unit_m4(offset); - src_mvert = mesh->mvert; + const MVert *src_verts = BKE_mesh_verts(mesh); + const MEdge *src_edges = BKE_mesh_edges(mesh); + const MPoly *src_polys = BKE_mesh_polys(mesh); + const MLoop *src_loops = BKE_mesh_loops(mesh); if (amd->offset_type & MOD_ARR_OFF_CONST) { add_v3_v3(offset[3], amd->offset); @@ -440,7 +442,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, const MVert *src_mv; INIT_MINMAX(min, max); - for (src_mv = src_mvert, j = chunk_nverts; j--; src_mv++) { + for (src_mv = src_verts, j = chunk_nverts; j--; src_mv++) { minmax_v3v3_v3(min, max, src_mv->co); } @@ -478,7 +480,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } /* About 67 million vertices max seems a decent limit for now. */ - const size_t max_vertices_num = 1 << 26; + const size_t max_verts_num = 1 << 26; /* calculate the maximum number of copies which will fit within the * prescribed length */ @@ -496,7 +498,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, * vertices. */ if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + - (size_t)end_cap_nverts) > max_vertices_num) { + (size_t)end_cap_nverts) > max_verts_num) { count = 1; offset_is_too_small = true; } @@ -518,7 +520,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, * vertices. */ else if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + - (size_t)end_cap_nverts) > max_vertices_num) { + (size_t)end_cap_nverts) > max_verts_num) { count = 1; BKE_modifier_set_error(ctx->object, &amd->modifier, @@ -539,7 +541,10 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, /* Initialize a result dm */ result = BKE_mesh_new_nomain_from_template( mesh, result_nverts, result_nedges, 0, result_nloops, result_npolys); - result_dm_verts = result->mvert; + MVert *result_verts = BKE_mesh_verts_for_write(result); + MEdge *result_edges = BKE_mesh_edges_for_write(result); + MPoly *result_polys = BKE_mesh_polys_for_write(result); + MLoop *result_loops = BKE_mesh_loops_for_write(result); if (use_merge) { /* Will need full_doubles_map for handling merge */ @@ -553,17 +558,17 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, chunk_nloops); CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, chunk_npolys); - /* Subsurf for eg won't have mesh data in the custom data arrays. - * now add mvert/medge/mpoly layers. */ + /* Subdivision-surface for eg won't have mesh data in the custom-data arrays. + * Now add #MVert/#MEdge/#MPoly layers. */ if (!CustomData_has_layer(&mesh->vdata, CD_MVERT)) { - memcpy(result->mvert, mesh->mvert, sizeof(*result->mvert) * mesh->totvert); + memcpy(result_verts, src_verts, sizeof(MVert) * mesh->totvert); } if (!CustomData_has_layer(&mesh->edata, CD_MEDGE)) { - memcpy(result->medge, mesh->medge, sizeof(*result->medge) * mesh->totedge); + memcpy(result_edges, src_edges, sizeof(MEdge) * mesh->totedge); } if (!CustomData_has_layer(&mesh->pdata, CD_MPOLY)) { - memcpy(result->mloop, mesh->mloop, sizeof(*result->mloop) * mesh->totloop); - memcpy(result->mpoly, mesh->mpoly, sizeof(*result->mpoly) * mesh->totpoly); + memcpy(result_loops, src_loops, sizeof(MLoop) * mesh->totloop); + memcpy(result_polys, src_polys, sizeof(MPoly) * mesh->totpoly); } /* Remember first chunk, in case of cap merge */ @@ -594,7 +599,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, /* apply offset to all new verts */ for (i = 0; i < chunk_nverts; i++) { const int i_dst = vert_offset + i; - mul_m4_v3(current_offset, result_dm_verts[i_dst].co); + mul_m4_v3(current_offset, result_verts[i_dst].co); /* We have to correct normals too, if we do not tag them as dirty! */ if (!use_recalc_normals) { @@ -605,19 +610,19 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } /* adjust edge vertex indices */ - me = result->medge + c * chunk_nedges; + me = result_edges + c * chunk_nedges; for (i = 0; i < chunk_nedges; i++, me++) { me->v1 += c * chunk_nverts; me->v2 += c * chunk_nverts; } - mp = result->mpoly + c * chunk_npolys; + mp = result_polys + c * chunk_npolys; for (i = 0; i < chunk_npolys; i++, mp++) { mp->loopstart += c * chunk_nloops; } /* adjust loop vertex and edge indices */ - ml = result->mloop + c * chunk_nloops; + ml = result_loops + c * chunk_nloops; for (i = 0; i < chunk_nloops; i++, ml++) { ml->v += c * chunk_nverts; ml->e += c * chunk_nedges; @@ -638,8 +643,8 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, while (target != -1 && !ELEM(full_doubles_map[target], -1, target)) { /* If target is already mapped, we only follow that mapping if final target remains * close enough from current vert (otherwise no mapping at all). */ - if (compare_len_v3v3(result_dm_verts[this_chunk_index].co, - result_dm_verts[full_doubles_map[target]].co, + if (compare_len_v3v3(result_verts[this_chunk_index].co, + result_verts[full_doubles_map[target]].co, amd->merge_dist)) { target = full_doubles_map[target]; } @@ -653,7 +658,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } else { dm_mvert_map_doubles(full_doubles_map, - result_dm_verts, + result_verts, (c - 1) * chunk_nverts, chunk_nverts, c * chunk_nverts, @@ -691,7 +696,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, if (use_merge && (amd->flags & MOD_ARR_MERGEFINAL) && (count > 1)) { /* Merge first and last copies */ dm_mvert_map_doubles(full_doubles_map, - result_dm_verts, + result_verts, last_chunk_start, last_chunk_nverts, first_chunk_start, @@ -721,7 +726,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, /* Identify doubles with first chunk */ if (use_merge) { dm_mvert_map_doubles(full_doubles_map, - result_dm_verts, + result_verts, first_chunk_start, first_chunk_nverts, start_cap_start, @@ -751,7 +756,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, /* Identify doubles with last chunk */ if (use_merge) { dm_mvert_map_doubles(full_doubles_map, - result_dm_verts, + result_verts, last_chunk_start, last_chunk_nverts, end_cap_start, diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 94f2090e081..48d355d8ca7 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -64,9 +64,7 @@ static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int bmd_dst->custom_profile = BKE_curveprofile_copy(bmd_src->custom_profile); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { BevelModifierData *bmd = (BevelModifierData *)md; @@ -74,6 +72,10 @@ static void requiredDataMask(Object *UNUSED(ob), if (bmd->defgrp_name[0] != '\0') { r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; } + if (bmd->lim_flags & MOD_BEVEL_WEIGHT) { + r_cddata_masks->vmask |= CD_MASK_BWEIGHT; + r_cddata_masks->emask |= CD_MASK_BWEIGHT; + } } /* @@ -88,7 +90,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BMVert *v; float weight, weight2; int vgroup = -1; - MDeformVert *dvert = NULL; + const MDeformVert *dvert = NULL; BevelModifierData *bmd = (BevelModifierData *)md; const float threshold = cosf(bmd->bevel_angle + 0.000000175f); const bool do_clamp = !(bmd->flags & MOD_BEVEL_OVERLAP_OK); diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc index 685338cf351..7316baebfb6 100644 --- a/source/blender/modifiers/intern/MOD_boolean.cc +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -144,11 +144,9 @@ static Mesh *get_quick_mesh( invert_m4_m4(imat, ob_self->obmat); mul_m4_m4m4(omat, imat, ob_operand_ob->obmat); - const int mverts_len = result->totvert; - MVert *mv = result->mvert; - - for (int i = 0; i < mverts_len; i++, mv++) { - mul_m4_v3(omat, mv->co); + MutableSpan<MVert> verts = result->verts_for_write(); + for (const int i : verts.index_range()) { + mul_m4_v3(omat, verts[i].co); } BKE_mesh_tag_coords_changed(result); @@ -572,9 +570,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return result; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *UNUSED(md), - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *UNUSED(md), CustomData_MeshMasks *r_cddata_masks) { r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; r_cddata_masks->emask |= CD_MASK_MEDGE; diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index a9b6af967be..78724d6a2a1 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -62,7 +62,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct int *vertMap, *edgeMap, *faceMap; float frac; MPoly *mpoly_dst; - MLoop *ml_dst, *ml_src /*, *mloop_dst */; + MLoop *ml_dst; + const MLoop *ml_src; GHashIterator gh_iter; /* maps vert indices in old mesh to indices in new mesh */ GHash *vertHash = BLI_ghash_int_new("build ve apply gh"); @@ -74,10 +75,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct const int vert_src_num = mesh->totvert; const int edge_src_num = mesh->totedge; const int poly_src_num = mesh->totpoly; - MPoly *mpoly_src = mesh->mpoly; - MLoop *mloop_src = mesh->mloop; - MEdge *medge_src = mesh->medge; - MVert *mvert_src = mesh->mvert; + const MVert *mvert_src = BKE_mesh_verts(mesh); + const MEdge *medge_src = BKE_mesh_edges(mesh); + const MPoly *mpoly_src = BKE_mesh_polys(mesh); + const MLoop *mloop_src = BKE_mesh_loops(mesh); vertMap = MEM_malloc_arrayN(vert_src_num, sizeof(*vertMap), "build modifier vertMap"); edgeMap = MEM_malloc_arrayN(edge_src_num, sizeof(*edgeMap), "build modifier edgeMap"); @@ -99,8 +100,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct /* if there's at least one face, build based on faces */ if (faces_dst_num) { - MPoly *mpoly, *mp; - MLoop *ml, *mloop; + const MPoly *mpoly, *mp; + const MLoop *ml, *mloop; uintptr_t hash_num, hash_num_alt; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { @@ -135,7 +136,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct hash_num = 0; hash_num_alt = 0; for (i = 0; i < edge_src_num; i++, hash_num_alt++) { - MEdge *me = medge_src + i; + const MEdge *me = medge_src + i; if (BLI_ghash_haskey(vertHash, POINTER_FROM_INT(me->v1)) && BLI_ghash_haskey(vertHash, POINTER_FROM_INT(me->v2))) { @@ -147,7 +148,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct BLI_assert(hash_num == BLI_ghash_len(edgeHash)); } else if (edges_dst_num) { - MEdge *medge, *me; + const MEdge *medge, *me; uintptr_t hash_num; if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) { @@ -201,6 +202,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct /* now we know the number of verts, edges and faces, we can create the mesh. */ result = BKE_mesh_new_nomain_from_template( mesh, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), 0, loops_dst_num, faces_dst_num); + MVert *result_verts = BKE_mesh_verts_for_write(result); + MEdge *result_edges = BKE_mesh_edges_for_write(result); + MPoly *result_polys = BKE_mesh_polys_for_write(result); + MLoop *result_loops = BKE_mesh_loops_for_write(result); /* copy the vertices across */ GHASH_ITER (gh_iter, vertHash) { @@ -210,7 +215,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct int newIndex = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter)); source = mvert_src[oldIndex]; - dest = &result->mvert[newIndex]; + dest = &result_verts[newIndex]; CustomData_copy_data(&mesh->vdata, &result->vdata, oldIndex, newIndex, 1); *dest = source; @@ -223,7 +228,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct int oldIndex = POINTER_AS_INT(BLI_ghash_lookup(edgeHash, POINTER_FROM_INT(i))); source = medge_src[oldIndex]; - dest = &result->medge[i]; + dest = &result_edges[i]; source.v1 = POINTER_AS_INT(BLI_ghash_lookup(vertHash, POINTER_FROM_INT(source.v1))); source.v2 = POINTER_AS_INT(BLI_ghash_lookup(vertHash, POINTER_FROM_INT(source.v2))); @@ -232,13 +237,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct *dest = source; } - mpoly_dst = result->mpoly; - ml_dst = result->mloop; + mpoly_dst = result_polys; + ml_dst = result_loops; /* copy the faces across, remapping indices */ k = 0; for (i = 0; i < faces_dst_num; i++) { - MPoly *source; + const MPoly *source; MPoly *dest; source = mpoly_src + faceMap[i]; diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index e17a612376d..1a4942fcaf1 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -63,9 +63,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return false; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { CastModifierData *cmd = (CastModifierData *)md; @@ -98,7 +96,7 @@ static void sphere_do(CastModifierData *cmd, float (*vertexCos)[3], int verts_num) { - MDeformVert *dvert = NULL; + const MDeformVert *dvert = NULL; const bool invert_vgroup = (cmd->flag & MOD_CAST_INVERT_VGROUP) != 0; Object *ctrl_ob = NULL; @@ -239,7 +237,7 @@ static void cuboid_do(CastModifierData *cmd, float (*vertexCos)[3], int verts_num) { - MDeformVert *dvert = NULL; + const MDeformVert *dvert = NULL; int defgrp_index; const bool invert_vgroup = (cmd->flag & MOD_CAST_INVERT_VGROUP) != 0; diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 11bbe8dc83e..dcb4803b08a 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -115,7 +115,7 @@ static void deformVerts(ModifierData *md, float(*layerorco)[3]; if (!(layerorco = CustomData_get_layer(&mesh_src->vdata, CD_CLOTH_ORCO))) { layerorco = CustomData_add_layer( - &mesh_src->vdata, CD_CLOTH_ORCO, CD_CALLOC, NULL, mesh_src->totvert); + &mesh_src->vdata, CD_CLOTH_ORCO, CD_SET_DEFAULT, NULL, mesh_src->totvert); } memcpy(layerorco, kb->data, sizeof(float[3]) * verts_num); @@ -147,9 +147,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte DEG_add_depends_on_transform_relation(ctx->node, "Cloth Modifier"); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { ClothModifierData *clmd = (ClothModifierData *)md; @@ -254,7 +252,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *u } if (clmd->sim_parms && clmd->sim_parms->effector_weights) { - walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_CB_USER); } } diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 42a8ba804ed..e38bf96500e 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -145,7 +145,7 @@ static void deformVerts(ModifierData *md, if (collmd->time_xnew == -1000) { /* first time */ - collmd->x = MEM_dupallocN(mesh_src->mvert); /* frame start position */ + collmd->x = MEM_dupallocN(BKE_mesh_verts(mesh_src)); /* frame start position */ for (uint i = 0; i < mvert_num; i++) { /* we save global positions */ @@ -160,7 +160,7 @@ static void deformVerts(ModifierData *md, collmd->mvert_num = mvert_num; { - const MLoop *mloop = mesh_src->mloop; + const MLoop *mloop = BKE_mesh_loops(mesh_src); const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh_src); collmd->tri_num = BKE_mesh_runtime_looptri_len(mesh_src); MVertTri *tri = MEM_mallocN(sizeof(*tri) * collmd->tri_num, __func__); @@ -182,7 +182,7 @@ static void deformVerts(ModifierData *md, collmd->xnew = tempVert; collmd->time_x = collmd->time_xnew; - memcpy(collmd->xnew, mesh_src->mvert, mvert_num * sizeof(MVert)); + memcpy(collmd->xnew, BKE_mesh_verts(mesh_src), mvert_num * sizeof(MVert)); bool is_static = true; diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 4df0479372f..5a9f7c657eb 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -49,10 +49,10 @@ #include "PIL_time.h" #ifdef DEBUG_TIME # include "PIL_time_utildefines.h" + #endif -/* minor optimization, calculate this inline */ -#define USE_TANGENT_CALC_INLINE +#include "BLI_strict_flags.h" static void initData(ModifierData *md) { @@ -65,8 +65,6 @@ static void initData(ModifierData *md) 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; @@ -79,7 +77,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla } tcsmd->delta_cache.deltas = NULL; - tcsmd->delta_cache.totverts = 0; + tcsmd->delta_cache.deltas_num = 0; } static void freeBind(CorrectiveSmoothModifierData *csmd) @@ -96,9 +94,7 @@ static void freeData(ModifierData *md) freeBind(csmd); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md; @@ -109,7 +105,7 @@ static void requiredDataMask(Object *UNUSED(ob), } /* check individual weights for changes and cache values */ -static void mesh_get_weights(MDeformVert *dvert, +static void mesh_get_weights(const MDeformVert *dvert, const int defgrp_index, const uint verts_num, const bool use_invert_vgroup, @@ -131,28 +127,27 @@ static void mesh_get_weights(MDeformVert *dvert, static void mesh_get_boundaries(Mesh *mesh, float *smooth_weights) { - const MPoly *mpoly = mesh->mpoly; - const MLoop *mloop = mesh->mloop; - const MEdge *medge = mesh->medge; - uint mpoly_num, medge_num, i; - ushort *boundaries; + const MEdge *medge = BKE_mesh_edges(mesh); + const MPoly *mpoly = BKE_mesh_polys(mesh); + const MLoop *mloop = BKE_mesh_loops(mesh); - mpoly_num = (uint)mesh->totpoly; - medge_num = (uint)mesh->totedge; + const uint mpoly_num = (uint)mesh->totpoly; + const uint medge_num = (uint)mesh->totedge; - boundaries = MEM_calloc_arrayN(medge_num, sizeof(*boundaries), __func__); + /* Flag boundary edges so only boundaries are set to 1. */ + uint8_t *boundaries = MEM_calloc_arrayN(medge_num, sizeof(*boundaries), __func__); - /* count the number of adjacent faces */ - for (i = 0; i < mpoly_num; i++) { + for (uint i = 0; i < mpoly_num; i++) { const MPoly *p = &mpoly[i]; const int totloop = p->totloop; int j; for (j = 0; j < totloop; j++) { - boundaries[mloop[p->loopstart + j].e]++; + uint8_t *e_value = &boundaries[mloop[p->loopstart + j].e]; + *e_value |= (uint8_t)((*e_value) + 1); } } - for (i = 0; i < medge_num; i++) { + for (uint i = 0; i < medge_num; i++) { if (boundaries[i] == 1) { smooth_weights[medge[i].v1] = 0.0f; smooth_weights[medge[i].v2] = 0.0f; @@ -178,7 +173,7 @@ static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd, uint i; const uint edges_num = (uint)mesh->totedge; - const MEdge *edges = mesh->medge; + const MEdge *edges = BKE_mesh_edges(mesh); float *vertex_edge_count_div; struct SmoothingData_Simple { @@ -255,7 +250,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd, /* NOTE: the way this smoothing method works, its approx half as strong as the simple-smooth, * and 2.0 rarely spikes, double the value for consistent behavior. */ const float lambda = csmd->lambda * 2.0f; - const MEdge *edges = mesh->medge; + const MEdge *edges = BKE_mesh_edges(mesh); float *vertex_edge_count; uint i; @@ -358,7 +353,7 @@ static void smooth_iter(CorrectiveSmoothModifierData *csmd, static void smooth_verts(CorrectiveSmoothModifierData *csmd, Mesh *mesh, - MDeformVert *dvert, + const MDeformVert *dvert, const int defgrp_index, float (*vertexCos)[3], uint verts_num) @@ -393,69 +388,61 @@ static void smooth_verts(CorrectiveSmoothModifierData *csmd, } /** - * finalize after accumulation. + * Calculate an orthogonal 3x3 matrix from 2 edge vectors. + * \return false if this loop should be ignored (have zero influence). */ -static void calc_tangent_ortho(float ts[3][3]) +static bool calc_tangent_loop(const float v_dir_prev[3], + const float v_dir_next[3], + float r_tspace[3][3]) { - float v_tan_a[3], v_tan_b[3]; - float t_vec_a[3], t_vec_b[3]; - - normalize_v3(ts[2]); - - copy_v3_v3(v_tan_a, ts[0]); - copy_v3_v3(v_tan_b, ts[1]); - - cross_v3_v3v3(ts[1], ts[2], v_tan_a); - mul_v3_fl(ts[1], dot_v3v3(ts[1], v_tan_b) < 0.0f ? -1.0f : 1.0f); - - /* Orthogonalize tangent. */ - mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], v_tan_a)); - sub_v3_v3v3(ts[0], v_tan_a, t_vec_a); - - /* Orthogonalize bi-tangent. */ - mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], ts[1])); - mul_v3_v3fl(t_vec_b, ts[0], dot_v3v3(ts[0], ts[1]) / dot_v3v3(v_tan_a, v_tan_a)); - sub_v3_v3(ts[1], t_vec_a); - sub_v3_v3(ts[1], t_vec_b); - - normalize_v3(ts[0]); - normalize_v3(ts[1]); + if (UNLIKELY(compare_v3v3(v_dir_prev, v_dir_next, FLT_EPSILON * 10.0f))) { + /* As there are no weights, the value doesn't matter just initialize it. */ + unit_m3(r_tspace); + return false; + } + + copy_v3_v3(r_tspace[0], v_dir_prev); + copy_v3_v3(r_tspace[1], v_dir_next); + + cross_v3_v3v3(r_tspace[2], v_dir_prev, v_dir_next); + normalize_v3(r_tspace[2]); + + /* Make orthogonal using `r_tspace[2]` as a basis. + * + * NOTE: while it seems more logical to use `v_dir_prev` & `v_dir_next` as separate X/Y axis + * (instead of combining them as is done here). It's not necessary as the directions of the + * axis aren't important as long as the difference between tangent matrices is equivalent. + * Some computations can be skipped by combining the two directions, + * using the cross product for the 3rd axes. */ + add_v3_v3(r_tspace[0], r_tspace[1]); + normalize_v3(r_tspace[0]); + cross_v3_v3v3(r_tspace[1], r_tspace[2], r_tspace[0]); + + return true; } /** - * accumulate edge-vectors from all polys. + * \param r_tangent_spaces: Loop aligned array of tangents. + * \param r_tangent_weights: Loop aligned array of weights (may be NULL). + * \param r_tangent_weights_per_vertex: Vertex aligned array, accumulating weights for each loop + * (may be NULL). */ -static void calc_tangent_loop_accum(const float v_dir_prev[3], - const float v_dir_next[3], - float r_tspace[3][3]) -{ - add_v3_v3v3(r_tspace[1], v_dir_prev, v_dir_next); - - if (compare_v3v3(v_dir_prev, v_dir_next, FLT_EPSILON * 10.0f) == false) { - const float weight = fabsf(acosf(dot_v3v3(v_dir_next, v_dir_prev))); - float nor[3]; - - cross_v3_v3v3(nor, v_dir_prev, v_dir_next); - normalize_v3(nor); - - cross_v3_v3v3(r_tspace[0], r_tspace[1], nor); - - mul_v3_fl(nor, weight); - /* accumulate weighted normals */ - add_v3_v3(r_tspace[2], nor); - } -} - -static void calc_tangent_spaces(Mesh *mesh, float (*vertexCos)[3], float (*r_tangent_spaces)[3][3]) +static void calc_tangent_spaces(const Mesh *mesh, + const float (*vertexCos)[3], + float (*r_tangent_spaces)[3][3], + float *r_tangent_weights, + float *r_tangent_weights_per_vertex) { const uint mpoly_num = (uint)mesh->totpoly; -#ifndef USE_TANGENT_CALC_INLINE - const uint mvert_num = (uint)dm->getNumVerts(dm); -#endif - const MPoly *mpoly = mesh->mpoly; - const MLoop *mloop = mesh->mloop; + const uint mvert_num = (uint)mesh->totvert; + const MPoly *mpoly = BKE_mesh_polys(mesh); + const MLoop *mloop = BKE_mesh_loops(mesh); uint i; + if (r_tangent_weights_per_vertex != NULL) { + copy_vn_fl(r_tangent_weights_per_vertex, (int)mvert_num, 0.0f); + } + for (i = 0; i < mpoly_num; i++) { const MPoly *mp = &mpoly[i]; const MLoop *l_next = &mloop[mp->loopstart]; @@ -471,7 +458,8 @@ static void calc_tangent_spaces(Mesh *mesh, float (*vertexCos)[3], float (*r_tan normalize_v3(v_dir_prev); for (; l_next != l_term; l_prev = l_curr, l_curr = l_next, l_next++) { - float(*ts)[3] = r_tangent_spaces[l_curr->v]; + uint l_index = (uint)(l_curr - mloop); + float(*ts)[3] = r_tangent_spaces[l_index]; /* re-use the previous value */ #if 0 @@ -481,19 +469,22 @@ static void calc_tangent_spaces(Mesh *mesh, float (*vertexCos)[3], float (*r_tan sub_v3_v3v3(v_dir_next, vertexCos[l_curr->v], vertexCos[l_next->v]); normalize_v3(v_dir_next); - calc_tangent_loop_accum(v_dir_prev, v_dir_next, ts); + if (calc_tangent_loop(v_dir_prev, v_dir_next, ts)) { + if (r_tangent_weights != NULL) { + const float weight = fabsf(acosf(dot_v3v3(v_dir_next, v_dir_prev))); + r_tangent_weights[l_index] = weight; + r_tangent_weights_per_vertex[l_curr->v] += weight; + } + } + else { + if (r_tangent_weights != NULL) { + r_tangent_weights[l_index] = 0; + } + } copy_v3_v3(v_dir_prev, v_dir_next); } } - - /* do inline */ -#ifndef USE_TANGENT_CALC_INLINE - for (i = 0; i < mvert_num; i++) { - float(*ts)[3] = r_tangent_spaces[i]; - calc_tangent_ortho(ts); - } -#endif } static void store_cache_settings(CorrectiveSmoothModifierData *csmd) @@ -519,43 +510,47 @@ static bool cache_settings_equal(CorrectiveSmoothModifierData *csmd) */ static void calc_deltas(CorrectiveSmoothModifierData *csmd, Mesh *mesh, - MDeformVert *dvert, + const MDeformVert *dvert, const int defgrp_index, const float (*rest_coords)[3], uint verts_num) { + const MLoop *mloop = BKE_mesh_loops(mesh); + const uint loops_num = (uint)mesh->totloop; + float(*smooth_vertex_coords)[3] = MEM_dupallocN(rest_coords); float(*tangent_spaces)[3][3]; - uint i; - tangent_spaces = MEM_calloc_arrayN(verts_num, sizeof(float[3][3]), __func__); + uint l_index; - if (csmd->delta_cache.totverts != verts_num) { + tangent_spaces = MEM_malloc_arrayN(loops_num, sizeof(float[3][3]), __func__); + + if (csmd->delta_cache.deltas_num != loops_num) { MEM_SAFE_FREE(csmd->delta_cache.deltas); } /* allocate deltas if they have not yet been allocated, otherwise we will just write over them */ if (!csmd->delta_cache.deltas) { - csmd->delta_cache.totverts = verts_num; - csmd->delta_cache.deltas = MEM_malloc_arrayN(verts_num, sizeof(float[3]), __func__); + csmd->delta_cache.deltas_num = loops_num; + csmd->delta_cache.deltas = MEM_malloc_arrayN(loops_num, sizeof(float[3]), __func__); } smooth_verts(csmd, mesh, dvert, defgrp_index, smooth_vertex_coords, verts_num); - calc_tangent_spaces(mesh, smooth_vertex_coords, tangent_spaces); + calc_tangent_spaces(mesh, smooth_vertex_coords, tangent_spaces, NULL, NULL); - for (i = 0; i < verts_num; i++) { - float imat[3][3], delta[3]; + copy_vn_fl(&csmd->delta_cache.deltas[0][0], (int)loops_num * 3, 0.0f); -#ifdef USE_TANGENT_CALC_INLINE - calc_tangent_ortho(tangent_spaces[i]); -#endif + for (l_index = 0; l_index < loops_num; l_index++) { + const int v_index = (int)mloop[l_index].v; + float delta[3]; + sub_v3_v3v3(delta, rest_coords[v_index], smooth_vertex_coords[v_index]); - sub_v3_v3v3(delta, rest_coords[i], smooth_vertex_coords[i]); - if (UNLIKELY(!invert_m3_m3(imat, tangent_spaces[i]))) { - transpose_m3_m3(imat, tangent_spaces[i]); + float imat[3][3]; + if (UNLIKELY(!invert_m3_m3(imat, tangent_spaces[l_index]))) { + transpose_m3_m3(imat, tangent_spaces[l_index]); } - mul_v3_m3v3(csmd->delta_cache.deltas[i], imat, delta); + mul_v3_m3v3(csmd->delta_cache.deltas[l_index], imat, delta); } MEM_freeN(tangent_spaces); @@ -578,8 +573,11 @@ static void correctivesmooth_modifier_do(ModifierData *md, ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO) && (((ID *)ob->data)->recalc & ID_RECALC_ALL)); + const MLoop *mloop = BKE_mesh_loops(mesh); + const uint loops_num = (uint)mesh->totloop; + bool use_only_smooth = (csmd->flag & MOD_CORRECTIVESMOOTH_ONLY_SMOOTH) != 0; - MDeformVert *dvert = NULL; + const MDeformVert *dvert = NULL; int defgrp_index; MOD_get_vgroup(ob, mesh, csmd->defgrp_name, &dvert, &defgrp_index); @@ -640,7 +638,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, } /* check to see if our deltas are still valid */ - if (!csmd->delta_cache.deltas || (csmd->delta_cache.totverts != verts_num) || + if (!csmd->delta_cache.deltas || (csmd->delta_cache.deltas_num != loops_num) || force_delta_cache_update) { const float(*rest_coords)[3]; bool is_rest_coords_alloc = false; @@ -688,27 +686,38 @@ static void correctivesmooth_modifier_do(ModifierData *md, smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, verts_num); { - uint i; + uint l_index; float(*tangent_spaces)[3][3]; + float *tangent_weights; + + float *tangent_weights_per_vertex; const float scale = csmd->scale; - /* calloc, since values are accumulated */ - tangent_spaces = MEM_calloc_arrayN(verts_num, sizeof(float[3][3]), __func__); - calc_tangent_spaces(mesh, vertexCos, tangent_spaces); + tangent_spaces = MEM_malloc_arrayN(loops_num, sizeof(float[3][3]), __func__); + tangent_weights = MEM_malloc_arrayN(loops_num, sizeof(float), __func__); + tangent_weights_per_vertex = MEM_malloc_arrayN(verts_num, sizeof(float), __func__); - for (i = 0; i < verts_num; i++) { - float delta[3]; + calc_tangent_spaces( + mesh, vertexCos, tangent_spaces, tangent_weights, tangent_weights_per_vertex); -#ifdef USE_TANGENT_CALC_INLINE - calc_tangent_ortho(tangent_spaces[i]); -#endif + for (l_index = 0; l_index < loops_num; l_index++) { + const uint v_index = mloop[l_index].v; + const float weight = tangent_weights[l_index] / tangent_weights_per_vertex[v_index]; + if (UNLIKELY(!(weight > 0.0f))) { + /* Catches zero & divide by zero. */ + continue; + } - mul_v3_m3v3(delta, tangent_spaces[i], csmd->delta_cache.deltas[i]); - madd_v3_v3fl(vertexCos[i], delta, scale); + float delta[3]; + mul_v3_m3v3(delta, tangent_spaces[l_index], csmd->delta_cache.deltas[l_index]); + mul_v3_fl(delta, weight); + madd_v3_v3fl(vertexCos[v_index], delta, scale); } MEM_freeN(tangent_spaces); + MEM_freeN(tangent_weights); + MEM_freeN(tangent_weights_per_vertex); } #ifdef DEBUG_TIME @@ -720,7 +729,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, /* when the modifier fails to execute */ error: MEM_SAFE_FREE(csmd->delta_cache.deltas); - csmd->delta_cache.totverts = 0; + csmd->delta_cache.deltas_num = 0; } static void deformVerts(ModifierData *md, @@ -829,7 +838,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) /* runtime only */ csmd->delta_cache.deltas = NULL; - csmd->delta_cache.totverts = 0; + csmd->delta_cache.deltas_num = 0; } ModifierTypeInfo modifierType_CorrectiveSmooth = { diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index af639915bd8..16c97d486da 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -51,9 +51,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(cmd, DNA_struct_default_get(CurveModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { CurveModifierData *cmd = (CurveModifierData *)md; @@ -114,7 +112,7 @@ static void deformVerts(ModifierData *md, mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false); } - struct MDeformVert *dvert = NULL; + const MDeformVert *dvert = NULL; int defgrp_index = -1; MOD_get_vgroup(ctx->object, mesh_src, cmd->name, &dvert, &defgrp_index); diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 7cd6b829d37..613d3d5196f 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -22,6 +22,7 @@ #include "BKE_data_transfer.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" +#include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_remap.h" #include "BKE_modifier.h" @@ -72,9 +73,7 @@ static void initData(ModifierData *md) dtmd->flags = MOD_DATATRANSFER_OBSRC_TRANSFORM; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { DataTransferModifierData *dtmd = (DataTransferModifierData *)md; @@ -178,7 +177,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BLI_SPACE_TRANSFORM_SETUP(space_transform, ctx->object, ob_source); } - if (((result == me) || (me->mvert == result->mvert) || (me->medge == result->medge)) && + const MVert *me_verts = BKE_mesh_verts(me); + const MEdge *me_edges = BKE_mesh_edges(me); + const MVert *result_verts = BKE_mesh_verts(result); + const MEdge *result_edges = BKE_mesh_edges(result); + + if (((result == me) || (me_verts == result_verts) || (me_edges == result_edges)) && (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. */ @@ -211,7 +215,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * dtmd->defgrp_name, invert_vgroup, &reports)) { - result->runtime.is_original = false; + result->runtime.is_original_bmesh = false; } if (BKE_reports_contain(&reports, RPT_ERROR)) { diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 55d9d148d10..059ded4f873 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -54,9 +54,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(dmd, DNA_struct_default_get(DecimateModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { DecimateModifierData *dmd = (DecimateModifierData *)md; @@ -135,7 +133,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (dmd->mode == MOD_DECIM_MODE_COLLAPSE) { if (dmd->defgrp_name[0] && (dmd->defgrp_factor > 0.0f)) { - MDeformVert *dvert; + const MDeformVert *dvert; int defgrp_index; MOD_get_vgroup(ctx->object, mesh, dmd->defgrp_name, &dvert, &defgrp_index); @@ -203,7 +201,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* make sure we never alloc'd these */ BLI_assert(bm->vtoolflagpool == NULL && bm->etoolflagpool == NULL && bm->ftoolflagpool == NULL); - BLI_assert(bm->vtable == NULL && bm->etable == NULL && bm->ftable == NULL); result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 367809953b6..ad5be57ad68 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -59,9 +59,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(dmd, DNA_struct_default_get(DisplaceModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { DisplaceModifierData *dmd = (DisplaceModifierData *)md; @@ -150,7 +148,7 @@ typedef struct DisplaceUserdata { /*const*/ DisplaceModifierData *dmd; struct Scene *scene; struct ImagePool *pool; - MDeformVert *dvert; + const MDeformVert *dvert; float weight; int defgrp_index; int direction; @@ -170,7 +168,7 @@ static void displaceModifier_do_task(void *__restrict userdata, { DisplaceUserdata *data = (DisplaceUserdata *)userdata; DisplaceModifierData *dmd = data->dmd; - MDeformVert *dvert = data->dvert; + const MDeformVert *dvert = data->dvert; const bool invert_vgroup = (dmd->flag & MOD_DISP_INVERT_VGROUP) != 0; float weight = data->weight; int defgrp_index = data->defgrp_index; @@ -270,7 +268,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, { Object *ob = ctx->object; MVert *mvert; - MDeformVert *dvert; + const MDeformVert *dvert; int direction = dmd->direction; int defgrp_index; float(*tex_co)[3]; @@ -286,7 +284,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, return; } - mvert = mesh->mvert; + mvert = BKE_mesh_verts_for_write(mesh); MOD_get_vgroup(ob, mesh, dmd->defgrp_name, &dvert, &defgrp_index); if (defgrp_index >= 0 && dvert == NULL) { @@ -316,7 +314,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, float(*clnors)[3] = CustomData_get_layer(ldata, CD_NORMAL); vert_clnors = MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__); BKE_mesh_normals_loop_to_vertex( - verts_num, mesh->mloop, mesh->totloop, (const float(*)[3])clnors, vert_clnors); + verts_num, BKE_mesh_loops(mesh), mesh->totloop, (const float(*)[3])clnors, vert_clnors); } else { direction = MOD_DISP_DIR_NOR; diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index 4afb81c04a9..c19c231d44c 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -74,9 +74,7 @@ static void freeData(ModifierData *md) dynamicPaint_Modifier_free(pmd); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; @@ -158,7 +156,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *u walk(userData, ob, (ID **)&surface->brush_group, IDWALK_CB_NOP); walk(userData, ob, (ID **)&surface->init_texture, IDWALK_CB_USER); if (surface->effector_weights) { - walk(userData, ob, (ID **)&surface->effector_weights->group, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&surface->effector_weights->group, IDWALK_CB_USER); } } } diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index e243c32173d..af167bf9b32 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -5,6 +5,8 @@ * \ingroup modifiers */ +#define DNA_DEPRECATED_ALLOW /* For #ME_FACE_SEL. */ + #include "BLI_utildefines.h" #include "BLI_edgehash.h" @@ -76,9 +78,7 @@ static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md)) { return true; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { ExplodeModifierData *emd = (ExplodeModifierData *)md; @@ -100,8 +100,8 @@ static void createFacepa(ExplodeModifierData *emd, ParticleSystemModifierData *p int i, p, v1, v2, v3, v4 = 0; const bool invert_vgroup = (emd->flag & eExplodeFlag_INVERT_VGROUP) != 0; - mvert = mesh->mvert; - mface = mesh->mface; + mvert = BKE_mesh_verts_for_write(mesh); + mface = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE); totvert = mesh->totvert; totface = mesh->totface; totpart = psmd->psys->totpart; @@ -216,7 +216,8 @@ static const short add_faces[24] = { static MFace *get_dface(Mesh *mesh, Mesh *split, int cur, int i, MFace *mf) { - MFace *df = &split->mface[cur]; + MFace *mfaces = CustomData_get_layer(&split->fdata, CD_MFACE); + MFace *df = &mfaces[cur]; CustomData_copy_data(&mesh->fdata, &split->fdata, i, cur, 1); *df = *mf; return df; @@ -639,7 +640,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) { Mesh *split_m; MFace *mf = NULL, *df1 = NULL; - MFace *mface = mesh->mface; + MFace *mface = CustomData_get_layer(&mesh->fdata, CD_MFACE); MVert *dupve, *mv; EdgeHash *edgehash; EdgeHashIterator *ehi; @@ -729,12 +730,15 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) layers_num = CustomData_number_of_layers(&split_m->fdata, CD_MTFACE); + const MVert *mesh_verts = BKE_mesh_verts(mesh); + MVert *split_m_verts = BKE_mesh_verts_for_write(split_m); + /* copy new faces & verts (is it really this painful with custom data??) */ for (i = 0; i < totvert; i++) { MVert source; MVert *dest; - source = mesh->mvert[i]; - dest = &split_m->mvert[i]; + source = mesh_verts[i]; + dest = &split_m_verts[i]; CustomData_copy_data(&mesh->vdata, &split_m->vdata, i, i, 1); *dest = source; @@ -755,14 +759,14 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2); esplit = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi)); - mv = &split_m->mvert[ed_v2]; - dupve = &split_m->mvert[esplit]; + mv = &split_m_verts[ed_v2]; + dupve = &split_m_verts[esplit]; CustomData_copy_data(&split_m->vdata, &split_m->vdata, ed_v2, esplit, 1); *dupve = *mv; - mv = &split_m->mvert[ed_v1]; + mv = &split_m_verts[ed_v1]; mid_v3_v3v3(dupve->co, dupve->co, mv->co); } @@ -772,7 +776,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) curdupface = 0; //=totface; // curdupin=totesplit; for (i = 0, fs = facesplit; i < totface; i++, fs++) { - mf = &mesh->mface[i]; + mf = &mface[i]; switch (*fs) { case 3: @@ -876,8 +880,9 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) curdupface += add_faces[*fs] + 1; } + MFace *split_mface = CustomData_get_layer(&split_m->fdata, CD_MFACE); for (i = 0; i < curdupface; i++) { - mf = &split_m->mface[i]; + mf = &split_mface[i]; BKE_mesh_mface_index_validate(mf, &split_m->fdata, i, ((mf->flag & ME_FACE_SEL) ? 4 : 3)); } @@ -915,7 +920,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, totface = mesh->totface; totvert = mesh->totvert; - mface = mesh->mface; + mface = CustomData_get_layer(&mesh->fdata, CD_MFACE); totpart = psmd->psys->totpart; sim.depsgraph = ctx->depsgraph; @@ -984,6 +989,9 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + const MVert *mesh_verts = BKE_mesh_verts(mesh); + MVert *explode_verts = BKE_mesh_verts_for_write(explode); + /* duplicate & displace vertices */ ehi = BLI_edgehashIterator_new(vertpahash); for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { @@ -995,8 +1003,8 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, ed_v2 -= totvert; v = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi)); - source = mesh->mvert[ed_v1]; - dest = &explode->mvert[v]; + source = mesh_verts[ed_v1]; + dest = &explode_verts[v]; CustomData_copy_data(&mesh->vdata, &explode->vdata, ed_v1, v, 1); @@ -1011,7 +1019,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, state.time = ctime; psys_get_particle_state(&sim, ed_v2, &state, 1); - vertco = explode->mvert[v].co; + vertco = explode_verts[v].co; mul_m4_v3(ctx->object->obmat, vertco); sub_v3_v3(vertco, birth.co); @@ -1035,6 +1043,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, BLI_edgehashIterator_free(ehi); /* Map new vertices to faces. */ + MFace *explode_mface = CustomData_get_layer(&explode->fdata, CD_MFACE); for (i = 0, u = 0; i < totface; i++) { MFace source; int orig_v4; @@ -1056,8 +1065,8 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, pa = NULL; } - source = mesh->mface[i]; - mf = &explode->mface[u]; + source = mface[i]; + mf = &explode_mface[u]; orig_v4 = source.v4; diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c index a3e9cd083d2..0a2b01fe101 100644 --- a/source/blender/modifiers/intern/MOD_fluid.c +++ b/source/blender/modifiers/intern/MOD_fluid.c @@ -78,9 +78,7 @@ static void freeData(ModifierData *md) #endif /* WITH_FLUID */ } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { FluidModifierData *fmd = (FluidModifierData *)md; @@ -215,7 +213,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *u } if (fmd->domain->effector_weights) { - walk(userData, ob, (ID **)&fmd->domain->effector_weights->group, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&fmd->domain->effector_weights->group, IDWALK_CB_USER); } } diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 979a08483e1..11bc9ee9574 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -68,9 +68,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla thmd->indexar = MEM_dupallocN(hmd->indexar); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { HookModifierData *hmd = (HookModifierData *)md; @@ -281,7 +279,7 @@ static void deformVerts_do(HookModifierData *hmd, bPoseChannel *pchan = BKE_pose_channel_find_name(ob_target->pose, hmd->subtarget); float dmat[4][4]; int i, *index_pt; - MDeformVert *dvert; + const MDeformVert *dvert; struct HookData_cb hd; const bool invert_vgroup = (hmd->flag & MOD_HOOK_INVERT_VGROUP) != 0; diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index 6333eb699b3..b2b97bc0d08 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -512,7 +512,7 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3]) static bool isValidVertexGroup(LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh) { int defgrp_index; - MDeformVert *dvert = NULL; + const MDeformVert *dvert = NULL; MOD_get_vgroup(ob, mesh, lmd->anchor_grp_name, &dvert, &defgrp_index); @@ -526,8 +526,8 @@ static void initSystem( int defgrp_index; int anchors_num; float wpaint; - MDeformVert *dvert = NULL; - MDeformVert *dv = NULL; + const MDeformVert *dvert = NULL; + const MDeformVert *dv = NULL; LaplacianSystem *sys; const bool invert_vgroup = (lmd->flag & MOD_LAPLACIANDEFORM_INVERT_VGROUP) != 0; @@ -570,14 +570,14 @@ static void initSystem( createFaceRingMap(mesh->totvert, BKE_mesh_runtime_looptri_ensure(mesh), BKE_mesh_runtime_looptri_len(mesh), - mesh->mloop, + BKE_mesh_loops(mesh), &sys->ringf_map, &sys->ringf_indices); createVertRingMap( - mesh->totvert, mesh->medge, mesh->totedge, &sys->ringv_map, &sys->ringv_indices); + mesh->totvert, BKE_mesh_edges(mesh), mesh->totedge, &sys->ringv_map, &sys->ringv_indices); mlooptri = BKE_mesh_runtime_looptri_ensure(mesh); - mloop = mesh->mloop; + mloop = BKE_mesh_loops(mesh); for (i = 0; i < sys->tris_num; i++) { sys->tris[i][0] = mloop[mlooptri[i].tri[0]].v; @@ -596,8 +596,8 @@ static int isSystemDifferent(LaplacianDeformModifierData *lmd, int defgrp_index; int anchors_num = 0; float wpaint; - MDeformVert *dvert = NULL; - MDeformVert *dv = NULL; + const MDeformVert *dvert = NULL; + const MDeformVert *dv = NULL; LaplacianSystem *sys = (LaplacianSystem *)lmd->cache_system; const bool invert_vgroup = (lmd->flag & MOD_LAPLACIANDEFORM_INVERT_VGROUP) != 0; @@ -747,9 +747,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return 1; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index c42f7b33919..1534708ac72 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -66,8 +66,6 @@ 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 *scene, ModifierData *md, bool useRenderParams); static float compute_volume(const float center[3], float (*vertexCos)[3], const MPoly *mpoly, @@ -376,8 +374,8 @@ static void laplaciansmoothModifier_do( LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num) { LaplacianSystem *sys; - MDeformVert *dvert = NULL; - MDeformVert *dv = NULL; + const MDeformVert *dvert = NULL; + const MDeformVert *dv = NULL; float w, wpaint; int i, iter; int defgrp_index; @@ -388,9 +386,9 @@ static void laplaciansmoothModifier_do( return; } - sys->mpoly = mesh->mpoly; - sys->mloop = mesh->mloop; - sys->medges = mesh->medge; + sys->mpoly = BKE_mesh_polys(mesh); + sys->mloop = BKE_mesh_loops(mesh); + sys->medges = BKE_mesh_edges(mesh); sys->vertexCos = vertexCos; sys->min_area = 0.00001f; MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index); @@ -511,9 +509,7 @@ static bool is_disabled(const struct Scene *UNUSED(scene), return 0; } -static void required_data_mask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 81b60b660c6..ede2d7b581e 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -47,9 +47,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(lmd, DNA_struct_default_get(LatticeModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { LatticeModifierData *lmd = (LatticeModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index e48a949baf4..6209985ecff 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -64,9 +64,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(mmd, DNA_struct_default_get(MaskModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *UNUSED(md), - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *UNUSED(md), CustomData_MeshMasks *r_cddata_masks) { r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; } @@ -143,9 +141,9 @@ static void invert_boolean_array(MutableSpan<bool> array) } } -static void compute_masked_vertices(Span<bool> vertex_mask, - MutableSpan<int> r_vertex_map, - uint *r_verts_masked_num) +static void compute_masked_verts(Span<bool> vertex_mask, + MutableSpan<int> r_vertex_map, + uint *r_verts_masked_num) { BLI_assert(vertex_mask.size() == r_vertex_map.size()); @@ -169,10 +167,11 @@ static void computed_masked_edges(const Mesh *mesh, uint *r_edges_masked_num) { BLI_assert(mesh->totedge == r_edge_map.size()); + const Span<MEdge> edges = mesh->edges(); uint edges_masked_num = 0; for (int i : IndexRange(mesh->totedge)) { - const MEdge &edge = mesh->medge[i]; + const MEdge &edge = edges[i]; /* only add if both verts will be in new mesh */ if (vertex_mask[edge.v1] && vertex_mask[edge.v2]) { @@ -194,11 +193,12 @@ static void computed_masked_edges_smooth(const Mesh *mesh, uint *r_verts_add_num) { BLI_assert(mesh->totedge == r_edge_map.size()); + const Span<MEdge> edges = mesh->edges(); uint edges_masked_num = 0; uint verts_add_num = 0; for (int i : IndexRange(mesh->totedge)) { - const MEdge &edge = mesh->medge[i]; + const MEdge &edge = edges[i]; /* only add if both verts will be in new mesh */ bool v1 = vertex_mask[edge.v1]; @@ -221,24 +221,26 @@ static void computed_masked_edges_smooth(const Mesh *mesh, *r_verts_add_num = verts_add_num; } -static void computed_masked_polygons(const Mesh *mesh, - Span<bool> vertex_mask, - Vector<int> &r_masked_poly_indices, - Vector<int> &r_loop_starts, - uint *r_polys_masked_num, - uint *r_loops_masked_num) +static void computed_masked_polys(const Mesh *mesh, + Span<bool> vertex_mask, + Vector<int> &r_masked_poly_indices, + Vector<int> &r_loop_starts, + uint *r_polys_masked_num, + uint *r_loops_masked_num) { BLI_assert(mesh->totvert == vertex_mask.size()); + const Span<MPoly> polys = mesh->polys(); + const Span<MLoop> loops = mesh->loops(); r_masked_poly_indices.reserve(mesh->totpoly); r_loop_starts.reserve(mesh->totpoly); uint loops_masked_num = 0; for (int i : IndexRange(mesh->totpoly)) { - const MPoly &poly_src = mesh->mpoly[i]; + const MPoly &poly_src = polys[i]; bool all_verts_in_mask = true; - Span<MLoop> loops_src(&mesh->mloop[poly_src.loopstart], poly_src.totloop); + Span<MLoop> loops_src = loops.slice(poly_src.loopstart, poly_src.totloop); for (const MLoop &loop : loops_src) { if (!vertex_mask[loop.v]) { all_verts_in_mask = false; @@ -257,15 +259,15 @@ static void computed_masked_polygons(const Mesh *mesh, *r_loops_masked_num = loops_masked_num; } -static void compute_interpolated_polygons(const Mesh *mesh, - Span<bool> vertex_mask, - uint verts_add_num, - uint loops_masked_num, - Vector<int> &r_masked_poly_indices, - Vector<int> &r_loop_starts, - uint *r_edges_add_num, - uint *r_polys_add_num, - uint *r_loops_add_num) +static void compute_interpolated_polys(const Mesh *mesh, + Span<bool> vertex_mask, + uint verts_add_num, + uint loops_masked_num, + Vector<int> &r_masked_poly_indices, + Vector<int> &r_loop_starts, + uint *r_edges_add_num, + uint *r_polys_add_num, + uint *r_loops_add_num) { BLI_assert(mesh->totvert == vertex_mask.size()); @@ -273,17 +275,19 @@ static void compute_interpolated_polygons(const Mesh *mesh, /* NOTE: this reserve can only lift the capacity if there are ngons, which get split. */ r_masked_poly_indices.reserve(r_masked_poly_indices.size() + verts_add_num); r_loop_starts.reserve(r_loop_starts.size() + verts_add_num); + const Span<MPoly> polys = mesh->polys(); + const Span<MLoop> loops = mesh->loops(); uint edges_add_num = 0; uint polys_add_num = 0; uint loops_add_num = 0; for (int i : IndexRange(mesh->totpoly)) { - const MPoly &poly_src = mesh->mpoly[i]; + const MPoly &poly_src = polys[i]; int in_count = 0; int start = -1; int dst_totloop = -1; - Span<MLoop> loops_src(&mesh->mloop[poly_src.loopstart], poly_src.totloop); + const Span<MLoop> loops_src = loops.slice(poly_src.loopstart, poly_src.totloop); for (const int j : loops_src.index_range()) { const MLoop &loop = loops_src[j]; if (vertex_mask[loop.v]) { @@ -327,19 +331,22 @@ static void compute_interpolated_polygons(const Mesh *mesh, *r_loops_add_num = loops_add_num; } -static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, - Mesh &dst_mesh, - Span<int> vertex_map) +static void copy_masked_verts_to_new_mesh(const Mesh &src_mesh, + Mesh &dst_mesh, + Span<int> vertex_map) { BLI_assert(src_mesh.totvert == vertex_map.size()); + const Span<MVert> src_verts = src_mesh.verts(); + MutableSpan<MVert> dst_verts = dst_mesh.verts_for_write(); + for (const int i_src : vertex_map.index_range()) { const int i_dst = vertex_map[i_src]; if (i_dst == -1) { continue; } - const MVert &v_src = src_mesh.mvert[i_src]; - MVert &v_dst = dst_mesh.mvert[i_dst]; + const MVert &v_src = src_verts[i_src]; + MVert &v_dst = dst_verts[i_dst]; v_dst = v_src; CustomData_copy_data(&src_mesh.vdata, &dst_mesh.vdata, i_src, i_dst, 1); @@ -369,6 +376,10 @@ static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh, { BLI_assert(src_mesh.totvert == vertex_mask.size()); BLI_assert(src_mesh.totedge == r_edge_map.size()); + const Span<MVert> src_verts = src_mesh.verts(); + const Span<MEdge> src_edges = src_mesh.edges(); + MutableSpan<MVert> dst_verts = dst_mesh.verts_for_write(); + MutableSpan<MEdge> dst_edges = dst_mesh.edges_for_write(); uint vert_index = dst_mesh.totvert - verts_add_num; uint edge_index = edges_masked_num - verts_add_num; @@ -378,8 +389,8 @@ static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh, if (i_dst == -2) { i_dst = edge_index; } - const MEdge &e_src = src_mesh.medge[i_src]; - MEdge &e_dst = dst_mesh.medge[i_dst]; + const MEdge &e_src = src_edges[i_src]; + MEdge &e_dst = dst_edges[i_dst]; CustomData_copy_data(&src_mesh.edata, &dst_mesh.edata, i_src, i_dst, 1); e_dst = e_src; @@ -389,9 +400,9 @@ static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh, if (r_edge_map[i_src] == -2) { const int i_dst = edge_index++; r_edge_map[i_src] = i_dst; - const MEdge &e_src = src_mesh.medge[i_src]; + const MEdge &e_src = src_edges[i_src]; /* Cut destination edge and make v1 the new vertex. */ - MEdge &e_dst = dst_mesh.medge[i_dst]; + MEdge &e_dst = dst_edges[i_dst]; if (!vertex_mask[e_src.v1]) { e_dst.v1 = vert_index; } @@ -407,9 +418,9 @@ static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh, float weights[2] = {1.0f - fac, fac}; CustomData_interp( &src_mesh.vdata, &dst_mesh.vdata, (int *)&e_src.v1, weights, nullptr, 2, vert_index); - MVert &v = dst_mesh.mvert[vert_index]; - MVert &v1 = src_mesh.mvert[e_src.v1]; - MVert &v2 = src_mesh.mvert[e_src.v2]; + MVert &v = dst_verts[vert_index]; + const MVert &v1 = src_verts[e_src.v1]; + const MVert &v2 = src_verts[e_src.v2]; interp_v3_v3v3(v.co, v1.co, v2.co, fac); vert_index++; @@ -424,6 +435,9 @@ static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, Span<int> vertex_map, Span<int> edge_map) { + const Span<MEdge> src_edges = src_mesh.edges(); + MutableSpan<MEdge> dst_edges = dst_mesh.edges_for_write(); + BLI_assert(src_mesh.totvert == vertex_map.size()); BLI_assert(src_mesh.totedge == edge_map.size()); for (const int i_src : IndexRange(src_mesh.totedge)) { @@ -432,8 +446,8 @@ static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, continue; } - const MEdge &e_src = src_mesh.medge[i_src]; - MEdge &e_dst = dst_mesh.medge[i_dst]; + const MEdge &e_src = src_edges[i_src]; + MEdge &e_dst = dst_edges[i_dst]; CustomData_copy_data(&src_mesh.edata, &dst_mesh.edata, i_src, i_dst, 1); e_dst = e_src; @@ -450,19 +464,24 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Span<int> new_loop_starts, int polys_masked_num) { + const Span<MPoly> src_polys = src_mesh.polys(); + const Span<MLoop> src_loops = src_mesh.loops(); + MutableSpan<MPoly> dst_polys = dst_mesh.polys_for_write(); + MutableSpan<MLoop> dst_loops = dst_mesh.loops_for_write(); + for (const int i_dst : IndexRange(polys_masked_num)) { const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_mesh.mpoly[i_src]; - MPoly &mp_dst = dst_mesh.mpoly[i_dst]; + const MPoly &mp_src = src_polys[i_src]; + MPoly &mp_dst = dst_polys[i_dst]; const int i_ml_src = mp_src.loopstart; const int i_ml_dst = new_loop_starts[i_dst]; CustomData_copy_data(&src_mesh.pdata, &dst_mesh.pdata, i_src, i_dst, 1); CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src, i_ml_dst, mp_src.totloop); - const MLoop *ml_src = src_mesh.mloop + i_ml_src; - MLoop *ml_dst = dst_mesh.mloop + i_ml_dst; + const MLoop *ml_src = src_loops.data() + i_ml_src; + MLoop *ml_dst = dst_loops.data() + i_ml_dst; mp_dst = mp_src; mp_dst.loopstart = i_ml_dst; @@ -486,6 +505,12 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, int polys_masked_num, int edges_add_num) { + const Span<MPoly> src_polys = src_mesh.polys(); + const Span<MLoop> src_loops = src_mesh.loops(); + MutableSpan<MEdge> dst_edges = dst_mesh.edges_for_write(); + MutableSpan<MPoly> dst_polys = dst_mesh.polys_for_write(); + MutableSpan<MLoop> dst_loops = dst_mesh.loops_for_write(); + int edge_index = dst_mesh.totedge - edges_add_num; int sub_poly_index = 0; int last_i_src = -1; @@ -500,8 +525,8 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, last_i_src = i_src; } - const MPoly &mp_src = src_mesh.mpoly[i_src]; - MPoly &mp_dst = dst_mesh.mpoly[i_dst]; + const MPoly &mp_src = src_polys[i_src]; + MPoly &mp_dst = dst_polys[i_dst]; const int i_ml_src = mp_src.loopstart; int i_ml_dst = new_loop_starts[i_dst]; const int mp_totloop = (i_dst + 1 < new_loop_starts.size() ? new_loop_starts[i_dst + 1] : @@ -517,7 +542,7 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, /* Ring search starting at a vertex which is not included in the mask. */ int start = -sub_poly_index - 1; bool skip = false; - Span<MLoop> loops_src(&src_mesh.mloop[i_ml_src], mp_src.totloop); + Span<MLoop> loops_src(&src_loops[i_ml_src], mp_src.totloop); for (const int j : loops_src.index_range()) { if (!vertex_mask[loops_src[j].v]) { if (start == -1) { @@ -552,13 +577,13 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, int indices[2] = {i_ml_src + last_index, i_ml_src + index}; CustomData_interp( &src_mesh.ldata, &dst_mesh.ldata, indices, weights, nullptr, 2, i_ml_dst); - MLoop &cut_dst_loop = dst_mesh.mloop[i_ml_dst]; + MLoop &cut_dst_loop = dst_loops[i_ml_dst]; cut_dst_loop.e = edge_map[last_loop->e]; - cut_dst_loop.v = dst_mesh.medge[cut_dst_loop.e].v1; + cut_dst_loop.v = dst_edges[cut_dst_loop.e].v1; i_ml_dst++; CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src + index, i_ml_dst, 1); - MLoop &next_dst_loop = dst_mesh.mloop[i_ml_dst]; + MLoop &next_dst_loop = dst_loops[i_ml_dst]; next_dst_loop.v = vertex_map[loop.v]; next_dst_loop.e = edge_map[loop.e]; i_ml_dst++; @@ -572,14 +597,14 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, int indices[2] = {i_ml_src + last_index, i_ml_src + index}; CustomData_interp( &src_mesh.ldata, &dst_mesh.ldata, indices, weights, nullptr, 2, i_ml_dst); - MLoop &cut_dst_loop = dst_mesh.mloop[i_ml_dst]; + MLoop &cut_dst_loop = dst_loops[i_ml_dst]; cut_dst_loop.e = edge_index; - cut_dst_loop.v = dst_mesh.medge[edge_map[last_loop->e]].v1; + cut_dst_loop.v = dst_edges[edge_map[last_loop->e]].v1; i_ml_dst++; /* Create closing edge. */ - MEdge &cut_edge = dst_mesh.medge[edge_index]; - cut_edge.v1 = dst_mesh.mloop[mp_dst.loopstart].v; + MEdge &cut_edge = dst_edges[edge_index]; + cut_edge.v1 = dst_loops[mp_dst.loopstart].v; cut_edge.v2 = cut_dst_loop.v; BLI_assert(cut_edge.v1 != cut_edge.v2); cut_edge.flag = ME_EDGEDRAW | ME_EDGERENDER; @@ -592,7 +617,7 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, BLI_assert(i_ml_dst != mp_dst.loopstart); /* Extend active poly. */ CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src + index, i_ml_dst, 1); - MLoop &dst_loop = dst_mesh.mloop[i_ml_dst]; + MLoop &dst_loop = dst_loops[i_ml_dst]; dst_loop.v = vertex_map[loop.v]; dst_loop.e = edge_map[loop.e]; i_ml_dst++; @@ -619,9 +644,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) (mmd->flag & MOD_MASK_SMOOTH); /* Return empty or input mesh when there are no vertex groups. */ - const MDeformVert *dvert = (const MDeformVert *)CustomData_get_layer(&mesh->vdata, - CD_MDEFORMVERT); - if (dvert == nullptr) { + const Span<MDeformVert> dverts = mesh->deform_verts(); + if (dverts.is_empty()) { return invert_mask ? mesh : BKE_mesh_new_nomain_from_template(mesh, 0, 0, 0, 0, 0); } @@ -643,7 +667,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) } vertex_mask = Array<bool>(mesh->totvert); - compute_vertex_mask__armature_mode(dvert, mesh, armature_ob, mmd->threshold, vertex_mask); + compute_vertex_mask__armature_mode( + dverts.data(), mesh, armature_ob, mmd->threshold, vertex_mask); } else { BLI_assert(mmd->mode == MOD_MASK_MODE_VGROUP); @@ -655,7 +680,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) } vertex_mask = Array<bool>(mesh->totvert); - compute_vertex_mask__vertex_group_mode(dvert, defgrp_index, mmd->threshold, vertex_mask); + compute_vertex_mask__vertex_group_mode( + dverts.data(), defgrp_index, mmd->threshold, vertex_mask); } if (invert_mask) { @@ -664,7 +690,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) Array<int> vertex_map(mesh->totvert); uint verts_masked_num; - compute_masked_vertices(vertex_mask, vertex_map, &verts_masked_num); + compute_masked_verts(vertex_mask, vertex_map, &verts_masked_num); Array<int> edge_map(mesh->totedge); uint edges_masked_num; @@ -681,26 +707,26 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) Vector<int> new_loop_starts; uint polys_masked_num; uint loops_masked_num; - computed_masked_polygons(mesh, - vertex_mask, - masked_poly_indices, - new_loop_starts, - &polys_masked_num, - &loops_masked_num); + computed_masked_polys(mesh, + vertex_mask, + masked_poly_indices, + new_loop_starts, + &polys_masked_num, + &loops_masked_num); uint edges_add_num = 0; uint polys_add_num = 0; uint loops_add_num = 0; if (use_interpolation) { - compute_interpolated_polygons(mesh, - vertex_mask, - verts_add_num, - loops_masked_num, - masked_poly_indices, - new_loop_starts, - &edges_add_num, - &polys_add_num, - &loops_add_num); + compute_interpolated_polys(mesh, + vertex_mask, + verts_add_num, + loops_masked_num, + masked_poly_indices, + new_loop_starts, + &edges_add_num, + &polys_add_num, + &loops_add_num); } Mesh *result = BKE_mesh_new_nomain_from_template(mesh, @@ -710,13 +736,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) loops_masked_num + loops_add_num, polys_masked_num + polys_add_num); - copy_masked_vertices_to_new_mesh(*mesh, *result, vertex_map); + copy_masked_verts_to_new_mesh(*mesh, *result, vertex_map); if (use_interpolation) { add_interp_verts_copy_edges_to_new_mesh(*mesh, *result, vertex_mask, vertex_map, - dvert, + dverts.data(), defgrp_index, mmd->threshold, edges_masked_num, @@ -739,7 +765,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) vertex_mask, vertex_map, edge_map, - dvert, + dverts.data(), defgrp_index, mmd->threshold, masked_poly_indices, diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 3e81f987da3..822da40edb7 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -79,7 +79,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, { const bool use_factor = mcmd->factor < 1.0f; int influence_group_index; - MDeformVert *dvert; + const MDeformVert *dvert; MOD_get_vgroup(ob, mesh, mcmd->defgrp_name, &dvert, &influence_group_index); float(*vertexCos_Store)[3] = (use_factor || influence_group_index != -1 || @@ -182,16 +182,16 @@ static void meshcache_do(MeshCacheModifierData *mcmd, float(*vertexCos_Source)[3] = MEM_malloc_arrayN( verts_num, sizeof(*vertexCos_Source), __func__); float(*vertexCos_New)[3] = MEM_malloc_arrayN(verts_num, sizeof(*vertexCos_New), __func__); - MVert *mv = me->mvert; + const MVert *mv = BKE_mesh_verts(me); for (i = 0; i < verts_num; i++, mv++) { copy_v3_v3(vertexCos_Source[i], mv->co); } BKE_mesh_calc_relative_deform( - me->mpoly, + BKE_mesh_polys(me), me->totpoly, - me->mloop, + BKE_mesh_loops(me), me->totvert, (const float(*)[3])vertexCos_Source, /* From the original Mesh. */ @@ -257,7 +257,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, const float global_offset = (mcmd->flag & MOD_MESHCACHE_INVERT_VERTEX_GROUP) ? mcmd->factor : 0.0f; - if (mesh->dvert != NULL) { + if (BKE_mesh_deform_verts(mesh) != NULL) { for (int i = 0; i < verts_num; i++) { /* For each vertex, compute its blending factor between the mesh cache (for `fac = 0`) * and the former position of the vertex (for `fac = 1`). */ diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.h b/source/blender/modifiers/intern/MOD_meshcache_util.h index 276bdf72bc3..2726f2d7efb 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_util.h +++ b/source/blender/modifiers/intern/MOD_meshcache_util.h @@ -8,12 +8,8 @@ /* MOD_meshcache_mdd.c */ -bool MOD_meshcache_read_mdd_index(FILE *fp, - float (*vertexCos)[3], - int vertex_tot, - int index, - float factor, - const char **err_str); +bool MOD_meshcache_read_mdd_index( + FILE *fp, float (*vertexCos)[3], int verts_tot, int index, float factor, const char **err_str); bool MOD_meshcache_read_mdd_frame(FILE *fp, float (*vertexCos)[3], int verts_tot, diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index d1df86b1010..d7ed346a61f 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -119,9 +119,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla } } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; @@ -330,7 +328,7 @@ static void meshdeformModifier_do(ModifierData *md, Object *ob = ctx->object; Mesh *cagemesh; - MDeformVert *dvert = NULL; + const MDeformVert *dvert = NULL; float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4]; float(*dco)[3] = NULL, (*bindcagecos)[3]; int a, cage_verts_num, defgrp_index; diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.cc b/source/blender/modifiers/intern/MOD_meshsequencecache.cc index 1c35160d3ef..f30e6a95787 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.cc +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.cc @@ -60,6 +60,8 @@ # include "usd.h" #endif +using blender::Span; + static void initData(ModifierData *md) { MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md); @@ -176,13 +178,18 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } if (me != nullptr) { - MVert *mvert = mesh->mvert; - MEdge *medge = mesh->medge; - MPoly *mpoly = mesh->mpoly; + const Span<MVert> mesh_verts = mesh->verts(); + const Span<MEdge> mesh_edges = mesh->edges(); + const Span<MPoly> mesh_polys = mesh->polys(); + const Span<MVert> me_verts = me->verts(); + const Span<MEdge> me_edges = me->edges(); + const Span<MPoly> me_polys = me->polys(); /* TODO(sybren+bastien): possibly check relevant custom data layers (UV/color depending on - * flags) and duplicate those too. */ - if ((me->mvert == mvert) || (me->medge == medge) || (me->mpoly == mpoly)) { + * flags) and duplicate those too. + * XXX(Hans): This probably isn't true anymore with various CoW improvements, etc. */ + if ((me_verts.data() == mesh_verts.data()) || (me_edges.data() == mesh_edges.data()) || + (me_polys.data() == mesh_polys.data())) { /* We need to duplicate data here, otherwise we'll modify org mesh, see T51701. */ mesh = reinterpret_cast<Mesh *>( BKE_id_copy_ex(nullptr, diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index cdad834f9b4..87108836a90 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -62,9 +62,7 @@ static void initData(ModifierData *md) md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { MultiresModifierData *mmd = (MultiresModifierData *)md; if (mmd->flags & eMultiresModifierFlag_UseCustomNormals) { diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 9c95561904a..a878793a34d 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -36,6 +36,7 @@ #include "DNA_windowmanager_types.h" #include "BKE_attribute_math.hh" +#include "BKE_compute_contexts.hh" #include "BKE_customdata.h" #include "BKE_geometry_fields.hh" #include "BKE_geometry_set_instances.hh" @@ -73,7 +74,6 @@ #include "MOD_modifiertypes.h" #include "MOD_nodes.h" -#include "MOD_nodes_evaluator.hh" #include "MOD_ui_common.h" #include "ED_object.h" @@ -81,15 +81,18 @@ #include "ED_spreadsheet.h" #include "ED_undo.h" -#include "NOD_derived_node_tree.hh" #include "NOD_geometry.h" -#include "NOD_geometry_nodes_eval_log.hh" +#include "NOD_geometry_nodes_lazy_function.hh" #include "NOD_node_declaration.hh" #include "FN_field.hh" #include "FN_field_cpp_type.hh" +#include "FN_lazy_function_execute.hh" +#include "FN_lazy_function_graph_executor.hh" #include "FN_multi_function.hh" +namespace lf = blender::fn::lazy_function; + using blender::Array; using blender::ColorGeometry4f; using blender::CPPType; @@ -106,22 +109,31 @@ using blender::MultiValueMap; using blender::MutableSpan; using blender::Set; using blender::Span; +using blender::Stack; using blender::StringRef; using blender::StringRefNull; using blender::Vector; using blender::bke::AttributeMetaData; +using blender::bke::AttributeValidator; using blender::fn::Field; +using blender::fn::FieldOperation; using blender::fn::GField; using blender::fn::ValueOrField; using blender::fn::ValueOrFieldCPPType; using blender::nodes::FieldInferencingInterface; using blender::nodes::GeoNodeExecParams; using blender::nodes::InputSocketFieldType; +using blender::nodes::geo_eval_log::GeoModifierLog; using blender::threading::EnumerableThreadSpecific; using namespace blender::fn::multi_function_types; -using namespace blender::nodes::derived_node_tree_types; -using geo_log::eNamedAttrUsage; -using geo_log::GeometryAttributeInfo; +using blender::nodes::geo_eval_log::GeometryAttributeInfo; +using blender::nodes::geo_eval_log::GeometryInfoLog; +using blender::nodes::geo_eval_log::GeoNodeLog; +using blender::nodes::geo_eval_log::GeoTreeLog; +using blender::nodes::geo_eval_log::NamedAttributeUsage; +using blender::nodes::geo_eval_log::NodeWarning; +using blender::nodes::geo_eval_log::NodeWarningType; +using blender::nodes::geo_eval_log::ValueLog; static void initData(ModifierData *md) { @@ -191,6 +203,9 @@ static bool node_needs_own_transform_relation(const bNode &node) return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE; } + if (node.type == GEO_NODE_SELF_OBJECT) { + return true; + } if (node.type == GEO_NODE_DEFORM_CURVES_ON_SURFACE) { return true; } @@ -297,6 +312,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte case ID_IM: case ID_TE: { DEG_add_generic_id_relation(ctx->node, id, "Nodes Modifier"); + break; } default: { /* Purposefully don't add relations for materials. While there are material sockets, @@ -755,36 +771,37 @@ void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd) } static void initialize_group_input(NodesModifierData &nmd, - const OutputSocketRef &socket, + const bNodeSocket &interface_socket, + const int input_index, void *r_value) { - const bNodeSocketType &socket_type = *socket.typeinfo(); - const bNodeSocket &bsocket = *socket.bsocket(); - const eNodeSocketDatatype socket_data_type = static_cast<eNodeSocketDatatype>(bsocket.type); + const bNodeSocketType &socket_type = *interface_socket.typeinfo; + const eNodeSocketDatatype socket_data_type = static_cast<eNodeSocketDatatype>( + interface_socket.type); if (nmd.settings.properties == nullptr) { - socket_type.get_geometry_nodes_cpp_value(bsocket, r_value); + socket_type.get_geometry_nodes_cpp_value(interface_socket, r_value); return; } const IDProperty *property = IDP_GetPropertyFromGroup(nmd.settings.properties, - socket.identifier().c_str()); + interface_socket.identifier); if (property == nullptr) { - socket_type.get_geometry_nodes_cpp_value(bsocket, r_value); + socket_type.get_geometry_nodes_cpp_value(interface_socket, r_value); return; } - if (!id_property_type_matches_socket(bsocket, *property)) { - socket_type.get_geometry_nodes_cpp_value(bsocket, r_value); + if (!id_property_type_matches_socket(interface_socket, *property)) { + socket_type.get_geometry_nodes_cpp_value(interface_socket, r_value); return; } - if (!input_has_attribute_toggle(*nmd.node_group, socket.index())) { + if (!input_has_attribute_toggle(*nmd.node_group, input_index)) { init_socket_cpp_value_from_property(*property, socket_data_type, r_value); return; } const IDProperty *property_use_attribute = IDP_GetPropertyFromGroup( - nmd.settings.properties, (socket.identifier() + use_attribute_suffix).c_str()); + nmd.settings.properties, (interface_socket.identifier + use_attribute_suffix).c_str()); const IDProperty *property_attribute_name = IDP_GetPropertyFromGroup( - nmd.settings.properties, (socket.identifier() + attribute_name_suffix).c_str()); + nmd.settings.properties, (interface_socket.identifier + attribute_name_suffix).c_str()); if (property_use_attribute == nullptr || property_attribute_name == nullptr) { init_socket_cpp_value_from_property(*property, socket_data_type, r_value); return; @@ -830,13 +847,25 @@ static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain) return spreadsheets; } -static void find_sockets_to_preview_for_spreadsheet(SpaceSpreadsheet *sspreadsheet, - NodesModifierData *nmd, - const ModifierEvalContext *ctx, - const DerivedNodeTree &tree, - Set<DSocket> &r_sockets_to_preview) +static const lf::FunctionNode &find_viewer_lf_node(const bNode &viewer_bnode) +{ + return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(viewer_bnode.owner_tree()) + ->mapping.viewer_node_map.lookup(&viewer_bnode); +} +static const lf::FunctionNode &find_group_lf_node(const bNode &group_bnode) +{ + return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(group_bnode.owner_tree()) + ->mapping.group_node_map.lookup(&group_bnode); +} + +static void find_side_effect_nodes_for_spreadsheet( + const SpaceSpreadsheet &sspreadsheet, + const NodesModifierData &nmd, + const ModifierEvalContext &ctx, + const bNodeTree &root_tree, + MultiValueMap<blender::ComputeContextHash, const lf::FunctionNode *> &r_side_effect_nodes) { - Vector<SpreadsheetContext *> context_path = sspreadsheet->context_path; + Vector<SpreadsheetContext *> context_path = sspreadsheet.context_path; if (context_path.size() < 3) { return; } @@ -847,11 +876,11 @@ static void find_sockets_to_preview_for_spreadsheet(SpaceSpreadsheet *sspreadshe return; } SpreadsheetContextObject *object_context = (SpreadsheetContextObject *)context_path[0]; - if (object_context->object != DEG_get_original_object(ctx->object)) { + if (object_context->object != DEG_get_original_object(ctx.object)) { return; } SpreadsheetContextModifier *modifier_context = (SpreadsheetContextModifier *)context_path[1]; - if (StringRef(modifier_context->modifier_name) != nmd->modifier.name) { + if (StringRef(modifier_context->modifier_name) != nmd.modifier.name) { return; } for (SpreadsheetContext *context : context_path.as_span().drop_front(2)) { @@ -860,61 +889,77 @@ static void find_sockets_to_preview_for_spreadsheet(SpaceSpreadsheet *sspreadshe } } - Span<SpreadsheetContextNode *> nested_group_contexts = + blender::ComputeContextBuilder compute_context_builder; + compute_context_builder.push<blender::bke::ModifierComputeContext>(nmd.modifier.name); + + const Span<SpreadsheetContextNode *> nested_group_contexts = context_path.as_span().drop_front(2).drop_back(1).cast<SpreadsheetContextNode *>(); - SpreadsheetContextNode *last_context = (SpreadsheetContextNode *)context_path.last(); + const SpreadsheetContextNode *last_context = (SpreadsheetContextNode *)context_path.last(); - const DTreeContext *context = &tree.root_context(); + Stack<const bNode *> group_node_stack; + const bNodeTree *group = &root_tree; for (SpreadsheetContextNode *node_context : nested_group_contexts) { - const NodeTreeRef &tree_ref = context->tree(); - const NodeRef *found_node = nullptr; - for (const NodeRef *node_ref : tree_ref.nodes()) { - if (node_ref->name() == node_context->node_name) { - found_node = node_ref; + const bNode *found_node = nullptr; + for (const bNode *node : group->group_nodes()) { + if (STREQ(node->name, node_context->node_name)) { + found_node = node; break; } } if (found_node == nullptr) { return; } - context = context->child_context(*found_node); - if (context == nullptr) { + if (found_node->id == nullptr) { return; } + group_node_stack.push(found_node); + group = reinterpret_cast<const bNodeTree *>(found_node->id); + compute_context_builder.push<blender::bke::NodeGroupComputeContext>(node_context->node_name); } - const NodeTreeRef &tree_ref = context->tree(); - for (const NodeRef *node_ref : tree_ref.nodes_by_type("GeometryNodeViewer")) { - if (node_ref->name() == last_context->node_name) { - const DNode viewer_node{context, node_ref}; - for (const InputSocketRef *input_socket : node_ref->inputs()) { - if (input_socket->is_available() && input_socket->is_logically_linked()) { - r_sockets_to_preview.add(DSocket{context, input_socket}); - } - } + const bNode *found_viewer_node = nullptr; + for (const bNode *viewer_node : group->nodes_by_type("GeometryNodeViewer")) { + if (STREQ(viewer_node->name, last_context->node_name)) { + found_viewer_node = viewer_node; + break; } } + if (found_viewer_node == nullptr) { + return; + } + + /* Not only mark the viewer node as having side effects, but also all group nodes it is contained + * in. */ + r_side_effect_nodes.add(compute_context_builder.hash(), + &find_viewer_lf_node(*found_viewer_node)); + compute_context_builder.pop(); + while (!compute_context_builder.is_empty()) { + r_side_effect_nodes.add(compute_context_builder.hash(), + &find_group_lf_node(*group_node_stack.pop())); + compute_context_builder.pop(); + } } -static void find_sockets_to_preview(NodesModifierData *nmd, - const ModifierEvalContext *ctx, - const DerivedNodeTree &tree, - Set<DSocket> &r_sockets_to_preview) +static void find_side_effect_nodes( + const NodesModifierData &nmd, + const ModifierEvalContext &ctx, + const bNodeTree &tree, + MultiValueMap<blender::ComputeContextHash, const lf::FunctionNode *> &r_side_effect_nodes) { - Main *bmain = DEG_get_bmain(ctx->depsgraph); + Main *bmain = DEG_get_bmain(ctx.depsgraph); /* Based on every visible spreadsheet context path, get a list of sockets that need to have their * intermediate geometries cached for display. */ Vector<SpaceSpreadsheet *> spreadsheets = find_spreadsheet_editors(bmain); for (SpaceSpreadsheet *sspreadsheet : spreadsheets) { - find_sockets_to_preview_for_spreadsheet(sspreadsheet, nmd, ctx, tree, r_sockets_to_preview); + find_side_effect_nodes_for_spreadsheet(*sspreadsheet, nmd, ctx, tree, r_side_effect_nodes); } } static void clear_runtime_data(NodesModifierData *nmd) { if (nmd->runtime_eval_log != nullptr) { - delete (geo_log::ModifierLog *)nmd->runtime_eval_log; + delete static_cast<GeoModifierLog *>(nmd->runtime_eval_log); nmd->runtime_eval_log = nullptr; } } @@ -936,15 +981,15 @@ struct OutputAttributeToStore { * can be evaluated together. */ static MultiValueMap<eAttrDomain, OutputAttributeInfo> find_output_attributes_to_store( - const NodesModifierData &nmd, const NodeRef &output_node, Span<GMutablePointer> output_values) + const NodesModifierData &nmd, const bNode &output_node, Span<GMutablePointer> output_values) { MultiValueMap<eAttrDomain, OutputAttributeInfo> outputs_by_domain; - for (const InputSocketRef *socket : output_node.inputs().drop_front(1).drop_back(1)) { - if (!socket_type_has_attribute_toggle(*socket->bsocket())) { + for (const bNodeSocket *socket : output_node.input_sockets().drop_front(1).drop_back(1)) { + if (!socket_type_has_attribute_toggle(*socket)) { continue; } - const std::string prop_name = socket->identifier() + attribute_name_suffix; + const std::string prop_name = socket->identifier + attribute_name_suffix; const IDProperty *prop = IDP_GetPropertyFromGroup(nmd.settings.properties, prop_name.c_str()); if (prop == nullptr) { continue; @@ -964,7 +1009,7 @@ static MultiValueMap<eAttrDomain, OutputAttributeInfo> find_output_attributes_to const GField field = cpp_type->as_field(value.get()); const bNodeSocket *interface_socket = (const bNodeSocket *)BLI_findlink( - &nmd.node_group->outputs, socket->index()); + &nmd.node_group->outputs, index); const eAttrDomain domain = (eAttrDomain)interface_socket->attribute_domain; OutputAttributeInfo output_info; output_info.field = std::move(field); @@ -1002,17 +1047,19 @@ static Vector<OutputAttributeToStore> compute_attributes_to_store( continue; } const int domain_size = attributes.domain_size(domain); - blender::bke::GeometryComponentFieldContext field_context{component, domain}; + blender::bke::GeometryFieldContext field_context{component, domain}; blender::fn::FieldEvaluator field_evaluator{field_context, domain_size}; for (const OutputAttributeInfo &output_info : outputs_info) { const CPPType &type = output_info.field.cpp_type(); + const AttributeValidator validator = attributes.lookup_validator(output_info.name); OutputAttributeToStore store{ component_type, domain, output_info.name, GMutableSpan{ type, MEM_malloc_arrayN(domain_size, type.size(), __func__), domain_size}}; - field_evaluator.add_with_destination(output_info.field, store.data); + GField field = validator.validate_field_if_necessary(output_info.field); + field_evaluator.add_with_destination(std::move(field), store.data); attributes_to_store.append(store); } field_evaluator.evaluate(); @@ -1044,7 +1091,7 @@ static void store_computed_output_attributes( if (attributes.add(store.name, store.domain, blender::bke::cpp_type_to_custom_data_type(store.data.type()), - blender::bke::AttributeInitMove(store.data.data()))) { + blender::bke::AttributeInitMoveArray(store.data.data()))) { continue; } @@ -1063,7 +1110,7 @@ static void store_computed_output_attributes( static void store_output_attributes(GeometrySet &geometry, const NodesModifierData &nmd, - const NodeRef &output_node, + const bNode &output_node, Span<GMutablePointer> output_values) { /* All new attribute values have to be computed before the geometry is actually changed. This is @@ -1078,91 +1125,103 @@ static void store_output_attributes(GeometrySet &geometry, /** * Evaluate a node group to compute the output geometry. */ -static GeometrySet compute_geometry(const DerivedNodeTree &tree, - Span<const NodeRef *> group_input_nodes, - const NodeRef &output_node, - GeometrySet input_geometry_set, - NodesModifierData *nmd, - const ModifierEvalContext *ctx) +static GeometrySet compute_geometry( + const bNodeTree &btree, + const blender::nodes::GeometryNodesLazyFunctionGraphInfo &lf_graph_info, + const bNode &output_node, + GeometrySet input_geometry_set, + NodesModifierData *nmd, + const ModifierEvalContext *ctx) { - blender::ResourceScope scope; - blender::LinearAllocator<> &allocator = scope.linear_allocator(); - blender::nodes::NodeMultiFunctions mf_by_node{tree}; + const blender::nodes::GeometryNodeLazyFunctionGraphMapping &mapping = lf_graph_info.mapping; - Map<DOutputSocket, GMutablePointer> group_inputs; + Span<const lf::OutputSocket *> graph_inputs = mapping.group_input_sockets; + Vector<const lf::InputSocket *> graph_outputs; + for (const bNodeSocket *bsocket : output_node.input_sockets().drop_back(1)) { + const lf::InputSocket &socket = mapping.dummy_socket_map.lookup(bsocket)->as_input(); + graph_outputs.append(&socket); + } - const DTreeContext *root_context = &tree.root_context(); - for (const NodeRef *group_input_node : group_input_nodes) { - Span<const OutputSocketRef *> group_input_sockets = group_input_node->outputs().drop_back(1); - if (group_input_sockets.is_empty()) { - continue; - } + Array<GMutablePointer> param_inputs(graph_inputs.size()); + Array<GMutablePointer> param_outputs(graph_outputs.size()); + Array<std::optional<lf::ValueUsage>> param_input_usages(graph_inputs.size()); + Array<lf::ValueUsage> param_output_usages(graph_outputs.size(), lf::ValueUsage::Used); + Array<bool> param_set_outputs(graph_outputs.size(), false); - Span<const OutputSocketRef *> remaining_input_sockets = group_input_sockets; + blender::nodes::GeometryNodesLazyFunctionLogger lf_logger(lf_graph_info); + blender::nodes::GeometryNodesLazyFunctionSideEffectProvider lf_side_effect_provider; - /* If the group expects a geometry as first input, use the geometry that has been passed to - * modifier. */ - const OutputSocketRef *first_input_socket = group_input_sockets[0]; - if (first_input_socket->bsocket()->type == SOCK_GEOMETRY) { - GeometrySet *geometry_set_in = - allocator.construct<GeometrySet>(input_geometry_set).release(); - group_inputs.add_new({root_context, first_input_socket}, geometry_set_in); - remaining_input_sockets = remaining_input_sockets.drop_front(1); - } + lf::GraphExecutor graph_executor{ + lf_graph_info.graph, graph_inputs, graph_outputs, &lf_logger, &lf_side_effect_provider}; - /* Initialize remaining group inputs. */ - for (const OutputSocketRef *socket : remaining_input_sockets) { - const CPPType &cpp_type = *socket->typeinfo()->geometry_nodes_cpp_type; - void *value_in = allocator.allocate(cpp_type.size(), cpp_type.alignment()); - initialize_group_input(*nmd, *socket, value_in); - group_inputs.add_new({root_context, socket}, {cpp_type, value_in}); + blender::nodes::GeoNodesModifierData geo_nodes_modifier_data; + geo_nodes_modifier_data.depsgraph = ctx->depsgraph; + geo_nodes_modifier_data.self_object = ctx->object; + auto eval_log = std::make_unique<GeoModifierLog>(); + if (logging_enabled(ctx)) { + geo_nodes_modifier_data.eval_log = eval_log.get(); + } + MultiValueMap<blender::ComputeContextHash, const lf::FunctionNode *> r_side_effect_nodes; + find_side_effect_nodes(*nmd, *ctx, btree, r_side_effect_nodes); + geo_nodes_modifier_data.side_effect_nodes = &r_side_effect_nodes; + blender::nodes::GeoNodesLFUserData user_data; + user_data.modifier_data = &geo_nodes_modifier_data; + blender::bke::ModifierComputeContext modifier_compute_context{nullptr, nmd->modifier.name}; + user_data.compute_context = &modifier_compute_context; + + blender::LinearAllocator<> allocator; + Vector<GMutablePointer> inputs_to_destruct; + + int input_index; + LISTBASE_FOREACH_INDEX (bNodeSocket *, interface_socket, &btree.inputs, input_index) { + if (interface_socket->type == SOCK_GEOMETRY && input_index == 0) { + param_inputs[input_index] = &input_geometry_set; + continue; } - } - Vector<DInputSocket> group_outputs; - for (const InputSocketRef *socket_ref : output_node.inputs().drop_back(1)) { - group_outputs.append({root_context, socket_ref}); + const CPPType *type = interface_socket->typeinfo->geometry_nodes_cpp_type; + BLI_assert(type != nullptr); + void *value = allocator.allocate(type->size(), type->alignment()); + initialize_group_input(*nmd, *interface_socket, input_index, value); + param_inputs[input_index] = {type, value}; + inputs_to_destruct.append({type, value}); } - std::optional<geo_log::GeoLogger> geo_logger; - - blender::modifiers::geometry_nodes::GeometryNodesEvaluationParams eval_params; - - if (logging_enabled(ctx)) { - Set<DSocket> preview_sockets; - find_sockets_to_preview(nmd, ctx, tree, preview_sockets); - eval_params.force_compute_sockets.extend(preview_sockets.begin(), preview_sockets.end()); - geo_logger.emplace(std::move(preview_sockets)); - - geo_logger->log_input_geometry(input_geometry_set); + for (const int i : graph_outputs.index_range()) { + const lf::InputSocket &socket = *graph_outputs[i]; + const CPPType &type = socket.type(); + void *buffer = allocator.allocate(type.size(), type.alignment()); + param_outputs[i] = {type, buffer}; } - /* Don't keep a reference to the input geometry components to avoid copies during evaluation. */ - input_geometry_set.clear(); + lf::Context lf_context; + lf_context.storage = graph_executor.init_storage(allocator); + lf_context.user_data = &user_data; + lf::BasicParams lf_params{graph_executor, + param_inputs, + param_outputs, + param_input_usages, + param_output_usages, + param_set_outputs}; + graph_executor.execute(lf_params, lf_context); + graph_executor.destruct_storage(lf_context.storage); - eval_params.input_values = group_inputs; - eval_params.output_sockets = group_outputs; - eval_params.mf_by_node = &mf_by_node; - eval_params.modifier_ = nmd; - eval_params.depsgraph = ctx->depsgraph; - eval_params.self_object = ctx->object; - eval_params.geo_logger = geo_logger.has_value() ? &*geo_logger : nullptr; - blender::modifiers::geometry_nodes::evaluate_geometry_nodes(eval_params); + for (GMutablePointer &ptr : inputs_to_destruct) { + ptr.destruct(); + } - GeometrySet output_geometry_set = std::move(*eval_params.r_output_values[0].get<GeometrySet>()); + GeometrySet output_geometry_set = std::move(*static_cast<GeometrySet *>(param_outputs[0].get())); + store_output_attributes(output_geometry_set, *nmd, output_node, param_outputs); - if (geo_logger.has_value()) { - geo_logger->log_output_geometry(output_geometry_set); - NodesModifierData *nmd_orig = (NodesModifierData *)BKE_modifier_get_original(ctx->object, - &nmd->modifier); - clear_runtime_data(nmd_orig); - nmd_orig->runtime_eval_log = new geo_log::ModifierLog(*geo_logger); + for (GMutablePointer &ptr : param_outputs) { + ptr.destruct(); } - store_output_attributes(output_geometry_set, *nmd, output_node, eval_params.r_output_values); - - for (GMutablePointer value : eval_params.r_output_values) { - value.destruct(); + if (logging_enabled(ctx)) { + NodesModifierData *nmd_orig = reinterpret_cast<NodesModifierData *>( + BKE_modifier_get_original(ctx->object, &nmd->modifier)); + delete static_cast<GeoModifierLog *>(nmd_orig->runtime_eval_log); + nmd_orig->runtime_eval_log = eval_log.release(); } return output_geometry_set; @@ -1223,37 +1282,35 @@ static void modifyGeometry(ModifierData *md, return; } + const bNodeTree &tree = *nmd->node_group; + tree.ensure_topology_cache(); check_property_socket_sync(ctx->object, md); - NodeTreeRefMap tree_refs; - DerivedNodeTree tree{*nmd->node_group, tree_refs}; - - if (tree.has_link_cycles()) { - BKE_modifier_set_error(ctx->object, md, "Node group has cycles"); + const bNode *output_node = tree.group_output_node(); + if (output_node == nullptr) { + BKE_modifier_set_error(ctx->object, md, "Node group must have a group output node"); geometry_set.clear(); return; } - const NodeTreeRef &root_tree_ref = tree.root_context().tree(); - Span<const NodeRef *> input_nodes = root_tree_ref.nodes_by_type("NodeGroupInput"); - Span<const NodeRef *> output_nodes = root_tree_ref.nodes_by_type("NodeGroupOutput"); - if (output_nodes.size() != 1) { - BKE_modifier_set_error(ctx->object, md, "Node group must have a single output node"); + Span<const bNodeSocket *> group_outputs = output_node->input_sockets().drop_back(1); + if (group_outputs.is_empty()) { + BKE_modifier_set_error(ctx->object, md, "Node group must have an output socket"); geometry_set.clear(); return; } - const NodeRef &output_node = *output_nodes[0]; - Span<const InputSocketRef *> group_outputs = output_node.inputs().drop_back(1); - if (group_outputs.is_empty()) { - BKE_modifier_set_error(ctx->object, md, "Node group must have an output socket"); + const bNodeSocket *first_output_socket = group_outputs[0]; + if (!STREQ(first_output_socket->idname, "NodeSocketGeometry")) { + BKE_modifier_set_error(ctx->object, md, "Node group's first output must be a geometry"); geometry_set.clear(); return; } - const InputSocketRef *first_output_socket = group_outputs[0]; - if (first_output_socket->idname() != "NodeSocketGeometry") { - BKE_modifier_set_error(ctx->object, md, "Node group's first output must be a geometry"); + const blender::nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info = + blender::nodes::ensure_geometry_nodes_lazy_function_graph(tree); + if (lf_graph_info == nullptr) { + BKE_modifier_set_error(ctx->object, md, "Cannot evaluate node group"); geometry_set.clear(); return; } @@ -1269,7 +1326,7 @@ static void modifyGeometry(ModifierData *md, } geometry_set = compute_geometry( - tree, input_nodes, output_node, std::move(geometry_set), nmd, ctx); + tree, *lf_graph_info, *output_node, std::move(geometry_set), nmd, ctx); if (geometry_set.has_mesh()) { /* Add #CD_ORIGINDEX layers if they don't exist already. This is required because the @@ -1277,13 +1334,13 @@ static void modifyGeometry(ModifierData *md, * assumed that the output mesh does not have a mapping to the original mesh. */ Mesh &mesh = *geometry_set.get_mesh_for_write(); if (use_orig_index_verts) { - CustomData_add_layer(&mesh.vdata, CD_ORIGINDEX, CD_DEFAULT, nullptr, mesh.totvert); + CustomData_add_layer(&mesh.vdata, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, mesh.totvert); } if (use_orig_index_edges) { - CustomData_add_layer(&mesh.edata, CD_ORIGINDEX, CD_DEFAULT, nullptr, mesh.totedge); + CustomData_add_layer(&mesh.edata, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, mesh.totedge); } if (use_orig_index_polys) { - CustomData_add_layer(&mesh.pdata, CD_ORIGINDEX, CD_DEFAULT, nullptr, mesh.totpoly); + CustomData_add_layer(&mesh.pdata, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, mesh.totpoly); } } } @@ -1341,6 +1398,16 @@ static NodesModifierData *get_modifier_data(Main &bmain, return reinterpret_cast<NodesModifierData *>(md); } +static GeoTreeLog *get_root_tree_log(const NodesModifierData &nmd) +{ + if (nmd.runtime_eval_log == nullptr) { + return nullptr; + } + GeoModifierLog &modifier_log = *static_cast<GeoModifierLog *>(nmd.runtime_eval_log); + blender::bke::ModifierComputeContext compute_context{nullptr, nmd.modifier.name}; + return &modifier_log.get_tree_log(compute_context.hash()); +} + static void attribute_search_update_fn( const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first) { @@ -1349,27 +1416,52 @@ static void attribute_search_update_fn( if (nmd == nullptr) { return; } - const geo_log::ModifierLog *modifier_log = static_cast<const geo_log::ModifierLog *>( - nmd->runtime_eval_log); - if (modifier_log == nullptr) { + if (nmd->node_group == nullptr) { return; } - const geo_log::GeometryValueLog *geometry_log = data.is_output ? - modifier_log->output_geometry_log() : - modifier_log->input_geometry_log(); - if (geometry_log == nullptr) { + GeoTreeLog *tree_log = get_root_tree_log(*nmd); + if (tree_log == nullptr) { return; } + tree_log->ensure_existing_attributes(); + nmd->node_group->ensure_topology_cache(); - Span<GeometryAttributeInfo> infos = geometry_log->attributes(); - - /* The shared attribute search code expects a span of pointers, so convert to that. */ - Array<const GeometryAttributeInfo *> info_ptrs(infos.size()); - for (const int i : infos.index_range()) { - info_ptrs[i] = &infos[i]; + Vector<const bNodeSocket *> sockets_to_check; + if (data.is_output) { + for (const bNode *node : nmd->node_group->nodes_by_type("NodeGroupOutput")) { + for (const bNodeSocket *socket : node->input_sockets()) { + if (socket->type == SOCK_GEOMETRY) { + sockets_to_check.append(socket); + } + } + } + } + else { + for (const bNode *node : nmd->node_group->nodes_by_type("NodeGroupInput")) { + for (const bNodeSocket *socket : node->output_sockets()) { + if (socket->type == SOCK_GEOMETRY) { + sockets_to_check.append(socket); + } + } + } + } + Set<StringRef> names; + Vector<const GeometryAttributeInfo *> attributes; + for (const bNodeSocket *socket : sockets_to_check) { + const ValueLog *value_log = tree_log->find_socket_value_log(*socket); + if (value_log == nullptr) { + continue; + } + if (const GeometryInfoLog *geo_log = dynamic_cast<const GeometryInfoLog *>(value_log)) { + for (const GeometryAttributeInfo &attribute : geo_log->attributes) { + if (names.add(attribute.name)) { + attributes.append(&attribute); + } + } + } } blender::ui::attribute_search_add_items( - str, data.is_output, info_ptrs.as_span(), items, is_first); + str, data.is_output, attributes.as_span(), items, is_first); } static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v) @@ -1400,8 +1492,7 @@ static void add_attribute_search_button(const bContext &C, const bNodeSocket &socket, const bool is_output) { - const geo_log::ModifierLog *log = static_cast<geo_log::ModifierLog *>(nmd.runtime_eval_log); - if (log == nullptr) { + if (nmd.runtime_eval_log == nullptr) { uiItemR(layout, md_ptr, rna_path_attribute_name.c_str(), 0, "", ICON_NONE); return; } @@ -1626,15 +1717,14 @@ static void panel_draw(const bContext *C, Panel *panel) } /* Draw node warnings. */ - if (nmd->runtime_eval_log != nullptr) { - const geo_log::ModifierLog &log = *static_cast<geo_log::ModifierLog *>(nmd->runtime_eval_log); - log.foreach_node_log([&](const geo_log::NodeLog &node_log) { - for (const geo_log::NodeWarning &warning : node_log.warnings()) { - if (warning.type != geo_log::NodeWarningType::Info) { - uiItemL(layout, warning.message.c_str(), ICON_ERROR); - } + GeoTreeLog *tree_log = get_root_tree_log(*nmd); + if (tree_log != nullptr) { + tree_log->ensure_node_warnings(); + for (const NodeWarning &warning : tree_log->all_warnings) { + if (warning.type != NodeWarningType::Info) { + uiItemL(layout, warning.message.c_str(), ICON_ERROR); } - }); + } } modifier_panel_end(layout, ptr); @@ -1671,17 +1761,14 @@ static void internal_dependencies_panel_draw(const bContext *UNUSED(C), Panel *p PointerRNA *ptr = modifier_panel_get_property_pointers(panel, nullptr); NodesModifierData *nmd = static_cast<NodesModifierData *>(ptr->data); - if (nmd->runtime_eval_log == nullptr) { + GeoTreeLog *tree_log = get_root_tree_log(*nmd); + if (tree_log == nullptr) { return; } - const geo_log::ModifierLog &log = *static_cast<geo_log::ModifierLog *>(nmd->runtime_eval_log); - Map<std::string, eNamedAttrUsage> usage_by_attribute; - log.foreach_node_log([&](const geo_log::NodeLog &node_log) { - for (const geo_log::UsedNamedAttribute &used_attribute : node_log.used_named_attributes()) { - usage_by_attribute.lookup_or_add_as(used_attribute.name, - used_attribute.usage) |= used_attribute.usage; - } - }); + + tree_log->ensure_used_named_attributes(); + const Map<StringRefNull, NamedAttributeUsage> &usage_by_attribute = + tree_log->used_named_attributes; if (usage_by_attribute.is_empty()) { uiItemL(layout, IFACE_("No named attributes used"), ICON_INFO); @@ -1690,7 +1777,7 @@ static void internal_dependencies_panel_draw(const bContext *UNUSED(C), Panel *p struct NameWithUsage { StringRefNull name; - eNamedAttrUsage usage; + NamedAttributeUsage usage; }; Vector<NameWithUsage> sorted_used_attribute; @@ -1705,20 +1792,20 @@ static void internal_dependencies_panel_draw(const bContext *UNUSED(C), Panel *p for (const NameWithUsage &attribute : sorted_used_attribute) { const StringRefNull attribute_name = attribute.name; - const eNamedAttrUsage usage = attribute.usage; + const NamedAttributeUsage usage = attribute.usage; /* #uiLayoutRowWithHeading doesn't seem to work in this case. */ uiLayout *split = uiLayoutSplit(layout, 0.4f, false); std::stringstream ss; Vector<std::string> usages; - if ((usage & eNamedAttrUsage::Read) != eNamedAttrUsage::None) { + if ((usage & NamedAttributeUsage::Read) != NamedAttributeUsage::None) { usages.append(TIP_("Read")); } - if ((usage & eNamedAttrUsage::Write) != eNamedAttrUsage::None) { + if ((usage & NamedAttributeUsage::Write) != NamedAttributeUsage::None) { usages.append(TIP_("Write")); } - if ((usage & eNamedAttrUsage::Remove) != eNamedAttrUsage::None) { + if ((usage & NamedAttributeUsage::Remove) != NamedAttributeUsage::None) { usages.append(TIP_("Remove")); } for (const int i : usages.index_range()) { @@ -1806,9 +1893,7 @@ static void freeData(ModifierData *md) clear_runtime_data(nmd); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *UNUSED(md), - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *UNUSED(md), CustomData_MeshMasks *r_cddata_masks) { /* We don't know what the node tree will need. If there are vertex groups, it is likely that the * node tree wants to access them. */ diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc deleted file mode 100644 index 5cf4e21ea68..00000000000 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ /dev/null @@ -1,1929 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "MOD_nodes_evaluator.hh" - -#include "BKE_type_conversions.hh" - -#include "NOD_geometry_exec.hh" -#include "NOD_socket_declarations.hh" - -#include "DEG_depsgraph_query.h" - -#include "FN_field.hh" -#include "FN_field_cpp_type.hh" -#include "FN_multi_function.hh" - -#include "BLT_translation.h" - -#include "BLI_enumerable_thread_specific.hh" -#include "BLI_generic_value_map.hh" -#include "BLI_stack.hh" -#include "BLI_task.h" -#include "BLI_task.hh" -#include "BLI_vector_set.hh" - -#include <chrono> - -namespace blender::modifiers::geometry_nodes { - -using fn::Field; -using fn::GField; -using fn::ValueOrField; -using fn::ValueOrFieldCPPType; -using nodes::GeoNodeExecParams; -using namespace fn::multi_function_types; - -enum class ValueUsage : uint8_t { - /* The value is definitely used. */ - Required, - /* The value may be used. */ - Maybe, - /* The value will definitely not be used. */ - Unused, -}; - -struct SingleInputValue { - /** - * Points either to null or to a value of the type of input. - */ - void *value = nullptr; -}; - -struct MultiInputValue { - /** - * Ordered sockets connected to this multi-input. - */ - Vector<DSocket> origins; - /** - * A value for every origin socket. The order is determined by #origins. - * Note, the same origin can occur multiple times. However, it is guaranteed that values coming - * from the same origin have the same value (the pointer is different, but they point to values - * that would compare equal). - */ - Vector<void *> values; - /** - * Number of non-null values. - */ - int provided_value_count = 0; - - bool all_values_available() const - { - return this->missing_values() == 0; - } - - int missing_values() const - { - return this->values.size() - this->provided_value_count; - } - - void add_value(const DSocket origin, void *value) - { - const int index = this->find_available_index(origin); - this->values[index] = value; - this->provided_value_count++; - } - - private: - int find_available_index(DSocket origin) const - { - for (const int i : origins.index_range()) { - if (values[i] != nullptr) { - continue; - } - if (origins[i] != origin) { - continue; - } - return i; - } - BLI_assert_unreachable(); - return -1; - } -}; - -struct InputState { - - /** - * Type of the socket. If this is null, the socket should just be ignored. - */ - const CPPType *type = nullptr; - - /** - * Value of this input socket. By default, the value is empty. When other nodes are done - * computing their outputs, the computed values will be forwarded to linked input sockets. - * The value will then live here until it is consumed by the node or it was found that the value - * is not needed anymore. - * Whether the `single` or `multi` value is used depends on the socket. - */ - union { - SingleInputValue *single; - MultiInputValue *multi; - } value; - - /** - * How the node intends to use this input. By default all inputs may be used. Based on which - * outputs are used, a node can tell the evaluator that an input will definitely be used or is - * never used. This allows the evaluator to free values early, avoid copies and other unnecessary - * computations. - */ - ValueUsage usage = ValueUsage::Maybe; - - /** - * True when this input is/was used for an execution. While a node is running, only the inputs - * that have this set to true are allowed to be used. This makes sure that inputs created while - * the node is running correctly trigger the node to run again. Furthermore, it gives the node a - * consistent view of which inputs are available that does not change unexpectedly. - * - * While the node is running, this can be checked without a lock, because no one is writing to - * it. If this is true, the value can be read without a lock as well, because the value is not - * changed by others anymore. - */ - bool was_ready_for_execution = false; - - /** - * True when this input has to be computed for logging/debugging purposes, regardless of whether - * it is needed for some output. - */ - bool force_compute = false; -}; - -struct OutputState { - /** - * If this output has been computed and forwarded already. If this is true, the value is not - * computed/forwarded again. - */ - bool has_been_computed = false; - - /** - * Keeps track of how the output value is used. If a connected input becomes required, this - * output has to become required as well. The output becomes ignored when it has zero potential - * users that are counted below. - */ - ValueUsage output_usage = ValueUsage::Maybe; - - /** - * This is a copy of `output_usage` that is done right before node execution starts. This is - * done so that the node gets a consistent view of what outputs are used, even when this changes - * while the node is running (the node might be reevaluated in that case). - * - * While the node is running, this can be checked without a lock, because no one is writing to - * it. - */ - ValueUsage output_usage_for_execution = ValueUsage::Maybe; - - /** - * Counts how many times the value from this output might be used. If this number reaches zero, - * the output is not needed anymore. - */ - int potential_users = 0; -}; - -enum class NodeScheduleState { - /** - * Default state of every node. - */ - NotScheduled, - /** - * The node has been added to the task group and will be executed by it in the future. - */ - Scheduled, - /** - * The node is currently running. - */ - Running, - /** - * The node is running and has been rescheduled while running. In this case the node will run - * again. However, we don't add it to the task group immediately, because then the node might run - * twice at the same time, which is not allowed. Instead, once the node is done running, it will - * reschedule itself. - */ - RunningAndRescheduled, -}; - -struct NodeState { - /** - * Needs to be locked when any data in this state is accessed that is not explicitly marked as - * otherwise. - */ - std::mutex mutex; - - /** - * States of the individual input and output sockets. One can index into these arrays without - * locking. However, to access the data inside a lock is generally necessary. - * - * These spans have to be indexed with the socket index. Unavailable sockets have a state as - * well. Maybe we can handle unavailable sockets differently in Blender in general, so I did not - * want to add complexity around it here. - */ - MutableSpan<InputState> inputs; - MutableSpan<OutputState> outputs; - - /** - * Most nodes have inputs that are always required. Those have special handling to avoid an extra - * call to the node execution function. - */ - bool non_lazy_inputs_handled = false; - - /** - * Used to check that nodes that don't support laziness do not run more than once. - */ - bool has_been_executed = false; - - /** - * Becomes true when the node will never be executed again and its inputs are destructed. - * Generally, a node has finished once all of its outputs with (potential) users have been - * computed. - */ - bool node_has_finished = false; - - /** - * Counts the number of values that still have to be forwarded to this node until it should run - * again. It counts values from a multi input socket separately. - * This is used as an optimization so that nodes are not scheduled unnecessarily in many cases. - */ - int missing_required_inputs = 0; - - /** - * A node is always in one specific schedule state. This helps to ensure that the same node does - * not run twice at the same time accidentally. - */ - NodeScheduleState schedule_state = NodeScheduleState::NotScheduled; -}; - -/** - * Container for a node and its state. Packing them into a single struct allows the use of - * `VectorSet` instead of a `Map` for `node_states_` which simplifies parallel loops over all - * states. - * - * Equality operators and a hash function for `DNode` are provided so that one can lookup this type - * in `node_states_` just with a `DNode`. - */ -struct NodeWithState { - DNode node; - /* Store a pointer instead of `NodeState` directly to keep it small and movable. */ - NodeState *state = nullptr; - - friend bool operator==(const NodeWithState &a, const NodeWithState &b) - { - return a.node == b.node; - } - - friend bool operator==(const NodeWithState &a, const DNode &b) - { - return a.node == b; - } - - friend bool operator==(const DNode &a, const NodeWithState &b) - { - return a == b.node; - } - - uint64_t hash() const - { - return node.hash(); - } - - static uint64_t hash_as(const DNode &node) - { - return node.hash(); - } -}; - -class GeometryNodesEvaluator; - -/** - * Utility class that wraps a node whose state is locked. Having this is a separate class is useful - * because it allows methods to communicate that they expect the node to be locked. - */ -class LockedNode : NonCopyable, NonMovable { - public: - /** - * This is the node that is currently locked. - */ - const DNode node; - NodeState &node_state; - - /** - * Used to delay notifying (and therefore locking) other nodes until the current node is not - * locked anymore. This might not be strictly necessary to avoid deadlocks in the current code, - * but it is a good measure to avoid accidentally adding a deadlock later on. By not locking - * more than one node per thread at a time, deadlocks are avoided. - * - * The notifications will be send right after the node is not locked anymore. - */ - Vector<DOutputSocket> delayed_required_outputs; - Vector<DOutputSocket> delayed_unused_outputs; - Vector<DNode> delayed_scheduled_nodes; - - LockedNode(const DNode node, NodeState &node_state) : node(node), node_state(node_state) - { - } -}; - -static const CPPType *get_socket_cpp_type(const SocketRef &socket) -{ - const bNodeSocketType *typeinfo = socket.typeinfo(); - if (typeinfo->geometry_nodes_cpp_type == nullptr) { - return nullptr; - } - const CPPType *type = typeinfo->geometry_nodes_cpp_type; - if (type == nullptr) { - return nullptr; - } - /* The evaluator only supports types that have special member functions. */ - if (!type->has_special_member_functions()) { - return nullptr; - } - return type; -} - -static const CPPType *get_socket_cpp_type(const DSocket socket) -{ - return get_socket_cpp_type(*socket.socket_ref()); -} - -/** - * \note This is not supposed to be a long term solution. Eventually we want that nodes can - * specify more complex defaults (other than just single values) in their socket declarations. - */ -static bool get_implicit_socket_input(const SocketRef &socket, void *r_value) -{ - const NodeRef &node = socket.node(); - const nodes::NodeDeclaration *node_declaration = node.declaration(); - if (node_declaration == nullptr) { - return false; - } - const nodes::SocketDeclaration &socket_declaration = *node_declaration->inputs()[socket.index()]; - if (socket_declaration.input_field_type() == nodes::InputSocketFieldType::Implicit) { - const bNode &bnode = *socket.bnode(); - if (socket.typeinfo()->type == SOCK_VECTOR) { - if (bnode.type == GEO_NODE_SET_CURVE_HANDLES) { - StringRef side = ((NodeGeometrySetCurveHandlePositions *)bnode.storage)->mode == - GEO_NODE_CURVE_HANDLE_LEFT ? - "handle_left" : - "handle_right"; - new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>(side)); - return true; - } - if (bnode.type == GEO_NODE_EXTRUDE_MESH) { - new (r_value) - ValueOrField<float3>(Field<float3>(std::make_shared<bke::NormalFieldInput>())); - return true; - } - new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>("position")); - return true; - } - if (socket.typeinfo()->type == SOCK_INT) { - if (ELEM(bnode.type, FN_NODE_RANDOM_VALUE, GEO_NODE_INSTANCE_ON_POINTS)) { - new (r_value) - ValueOrField<int>(Field<int>(std::make_shared<bke::IDAttributeFieldInput>())); - return true; - } - new (r_value) ValueOrField<int>(Field<int>(std::make_shared<fn::IndexFieldInput>())); - return true; - } - } - return false; -} - -static void get_socket_value(const SocketRef &socket, void *r_value) -{ - if (get_implicit_socket_input(socket, r_value)) { - return; - } - - const bNodeSocketType *typeinfo = socket.typeinfo(); - typeinfo->get_geometry_nodes_cpp_value(*socket.bsocket(), r_value); -} - -static bool node_supports_laziness(const DNode node) -{ - return node->typeinfo()->geometry_node_execute_supports_laziness; -} - -struct NodeTaskRunState { - /** The node that should be run on the same thread after the current node finished. */ - DNode next_node_to_run; -}; - -/** Implements the callbacks that might be called when a node is executed. */ -class NodeParamsProvider : public nodes::GeoNodeExecParamsProvider { - private: - GeometryNodesEvaluator &evaluator_; - NodeState &node_state_; - NodeTaskRunState *run_state_; - - public: - NodeParamsProvider(GeometryNodesEvaluator &evaluator, - DNode dnode, - NodeState &node_state, - NodeTaskRunState *run_state); - - bool can_get_input(StringRef identifier) const override; - bool can_set_output(StringRef identifier) const override; - GMutablePointer extract_input(StringRef identifier) override; - Vector<GMutablePointer> extract_multi_input(StringRef identifier) override; - GPointer get_input(StringRef identifier) const override; - GMutablePointer alloc_output_value(const CPPType &type) override; - void set_output(StringRef identifier, GMutablePointer value) override; - void set_input_unused(StringRef identifier) override; - bool output_is_required(StringRef identifier) const override; - - bool lazy_require_input(StringRef identifier) override; - bool lazy_output_is_required(StringRef identifier) const override; - - void set_default_remaining_outputs() override; -}; - -class GeometryNodesEvaluator { - private: - /** - * This allocator lives on after the evaluator has been destructed. Therefore outputs of the - * entire evaluator should be allocated here. - */ - LinearAllocator<> &outer_allocator_; - /** - * A local linear allocator for each thread. Only use this for values that do not need to live - * longer than the lifetime of the evaluator itself. Considerations for the future: - * - We could use an allocator that can free here, some temporary values don't live long. - * - If we ever run into false sharing bottlenecks, we could use local allocators that allocate - * on cache line boundaries. Note, just because a value is allocated in one specific thread, - * does not mean that it will only be used by that thread. - */ - threading::EnumerableThreadSpecific<LinearAllocator<>> local_allocators_; - - /** - * Every node that is reachable from the output gets its own state. Once all states have been - * constructed, this map can be used for lookups from multiple threads. - */ - VectorSet<NodeWithState> node_states_; - - /** - * Contains all the tasks for the nodes that are currently scheduled. - */ - TaskPool *task_pool_ = nullptr; - - GeometryNodesEvaluationParams ¶ms_; - const blender::bke::DataTypeConversions &conversions_; - - friend NodeParamsProvider; - - public: - GeometryNodesEvaluator(GeometryNodesEvaluationParams ¶ms) - : outer_allocator_(params.allocator), - params_(params), - conversions_(blender::bke::get_implicit_type_conversions()) - { - } - - void execute() - { - task_pool_ = BLI_task_pool_create(this, TASK_PRIORITY_HIGH); - - this->create_states_for_reachable_nodes(); - this->forward_group_inputs(); - this->schedule_initial_nodes(); - - /* This runs until all initially requested inputs have been computed. */ - BLI_task_pool_work_and_wait(task_pool_); - BLI_task_pool_free(task_pool_); - - this->extract_group_outputs(); - this->destruct_node_states(); - } - - void create_states_for_reachable_nodes() - { - /* This does a depth first search for all the nodes that are reachable from the group - * outputs. This finds all nodes that are relevant. */ - Stack<DNode> nodes_to_check; - /* Start at the output sockets. */ - for (const DInputSocket &socket : params_.output_sockets) { - nodes_to_check.push(socket.node()); - } - for (const DSocket &socket : params_.force_compute_sockets) { - nodes_to_check.push(socket.node()); - } - /* Use the local allocator because the states do not need to outlive the evaluator. */ - LinearAllocator<> &allocator = local_allocators_.local(); - while (!nodes_to_check.is_empty()) { - const DNode node = nodes_to_check.pop(); - if (node_states_.contains_as(node)) { - /* This node has been handled already. */ - continue; - } - /* Create a new state for the node. */ - NodeState &node_state = *allocator.construct<NodeState>().release(); - node_states_.add_new({node, &node_state}); - - /* Push all linked origins on the stack. */ - for (const InputSocketRef *input_ref : node->inputs()) { - const DInputSocket input{node.context(), input_ref}; - input.foreach_origin_socket( - [&](const DSocket origin) { nodes_to_check.push(origin.node()); }); - } - } - - /* Initialize the more complex parts of the node states in parallel. At this point no new - * node states are added anymore, so it is safe to lookup states from `node_states_` from - * multiple threads. */ - threading::parallel_for( - IndexRange(node_states_.size()), 50, [&, this](const IndexRange range) { - LinearAllocator<> &allocator = this->local_allocators_.local(); - for (const NodeWithState &item : node_states_.as_span().slice(range)) { - this->initialize_node_state(item.node, *item.state, allocator); - } - }); - - /* Mark input sockets that have to be computed. */ - for (const DSocket &socket : params_.force_compute_sockets) { - NodeState &node_state = *node_states_.lookup_key_as(socket.node()).state; - if (socket->is_input()) { - node_state.inputs[socket->index()].force_compute = true; - } - } - } - - void initialize_node_state(const DNode node, NodeState &node_state, LinearAllocator<> &allocator) - { - /* Construct arrays of the correct size. */ - node_state.inputs = allocator.construct_array<InputState>(node->inputs().size()); - node_state.outputs = allocator.construct_array<OutputState>(node->outputs().size()); - - /* Initialize input states. */ - for (const int i : node->inputs().index_range()) { - InputState &input_state = node_state.inputs[i]; - const DInputSocket socket = node.input(i); - if (!socket->is_available()) { - /* Unavailable sockets should never be used. */ - input_state.type = nullptr; - input_state.usage = ValueUsage::Unused; - continue; - } - const CPPType *type = get_socket_cpp_type(socket); - input_state.type = type; - if (type == nullptr) { - /* This is not a known data socket, it shouldn't be used. */ - input_state.usage = ValueUsage::Unused; - continue; - } - /* Construct the correct struct that can hold the input(s). */ - if (socket->is_multi_input_socket()) { - input_state.value.multi = allocator.construct<MultiInputValue>().release(); - MultiInputValue &multi_value = *input_state.value.multi; - /* Count how many values should be added until the socket is complete. */ - socket.foreach_origin_socket([&](DSocket origin) { multi_value.origins.append(origin); }); - /* If no links are connected, we do read the value from socket itself. */ - if (multi_value.origins.is_empty()) { - multi_value.origins.append(socket); - } - multi_value.values.resize(multi_value.origins.size(), nullptr); - } - else { - input_state.value.single = allocator.construct<SingleInputValue>().release(); - } - } - /* Initialize output states. */ - for (const int i : node->outputs().index_range()) { - OutputState &output_state = node_state.outputs[i]; - const DOutputSocket socket = node.output(i); - if (!socket->is_available()) { - /* Unavailable outputs should never be used. */ - output_state.output_usage = ValueUsage::Unused; - continue; - } - const CPPType *type = get_socket_cpp_type(socket); - if (type == nullptr) { - /* Non data sockets should never be used. */ - output_state.output_usage = ValueUsage::Unused; - continue; - } - /* Count the number of potential users for this socket. */ - socket.foreach_target_socket( - [&, this](const DInputSocket target_socket, - const DOutputSocket::TargetSocketPathInfo &UNUSED(path_info)) { - const DNode target_node = target_socket.node(); - if (!this->node_states_.contains_as(target_node)) { - /* The target node is not computed because it is not computed to the output. */ - return; - } - output_state.potential_users += 1; - }); - if (output_state.potential_users == 0) { - /* If it does not have any potential users, it is unused. It might become required again in - * `schedule_initial_nodes`. */ - output_state.output_usage = ValueUsage::Unused; - } - } - } - - void destruct_node_states() - { - threading::parallel_for( - IndexRange(node_states_.size()), 50, [&, this](const IndexRange range) { - for (const NodeWithState &item : node_states_.as_span().slice(range)) { - this->destruct_node_state(item.node, *item.state); - } - }); - } - - void destruct_node_state(const DNode node, NodeState &node_state) - { - /* Need to destruct stuff manually, because it's allocated by a custom allocator. */ - for (const int i : node->inputs().index_range()) { - InputState &input_state = node_state.inputs[i]; - if (input_state.type == nullptr) { - continue; - } - const InputSocketRef &socket_ref = node->input(i); - if (socket_ref.is_multi_input_socket()) { - MultiInputValue &multi_value = *input_state.value.multi; - for (void *value : multi_value.values) { - if (value != nullptr) { - input_state.type->destruct(value); - } - } - multi_value.~MultiInputValue(); - } - else { - SingleInputValue &single_value = *input_state.value.single; - void *value = single_value.value; - if (value != nullptr) { - input_state.type->destruct(value); - } - single_value.~SingleInputValue(); - } - } - - destruct_n(node_state.inputs.data(), node_state.inputs.size()); - destruct_n(node_state.outputs.data(), node_state.outputs.size()); - - node_state.~NodeState(); - } - - void forward_group_inputs() - { - for (auto &&item : params_.input_values.items()) { - const DOutputSocket socket = item.key; - GMutablePointer value = item.value; - - const DNode node = socket.node(); - if (!node_states_.contains_as(node)) { - /* The socket is not connected to any output. */ - this->log_socket_value({socket}, value); - value.destruct(); - continue; - } - this->forward_output(socket, value, nullptr); - } - } - - void schedule_initial_nodes() - { - for (const DInputSocket &socket : params_.output_sockets) { - const DNode node = socket.node(); - NodeState &node_state = this->get_node_state(node); - this->with_locked_node(node, node_state, nullptr, [&](LockedNode &locked_node) { - /* Setting an input as required will schedule any linked node. */ - this->set_input_required(locked_node, socket); - }); - } - for (const DSocket socket : params_.force_compute_sockets) { - const DNode node = socket.node(); - NodeState &node_state = this->get_node_state(node); - this->with_locked_node(node, node_state, nullptr, [&](LockedNode &locked_node) { - if (socket->is_input()) { - this->set_input_required(locked_node, DInputSocket(socket)); - } - else { - OutputState &output_state = node_state.outputs[socket->index()]; - output_state.output_usage = ValueUsage::Required; - this->schedule_node(locked_node); - } - }); - } - } - - void schedule_node(LockedNode &locked_node) - { - switch (locked_node.node_state.schedule_state) { - case NodeScheduleState::NotScheduled: { - /* The node will be scheduled once it is not locked anymore. We could schedule the node - * right here, but that would result in a deadlock if the task pool decides to run the task - * immediately (this only happens when Blender is started with a single thread). */ - locked_node.node_state.schedule_state = NodeScheduleState::Scheduled; - locked_node.delayed_scheduled_nodes.append(locked_node.node); - break; - } - case NodeScheduleState::Scheduled: { - /* Scheduled already, nothing to do. */ - break; - } - case NodeScheduleState::Running: { - /* Reschedule node while it is running. - * The node will reschedule itself when it is done. */ - locked_node.node_state.schedule_state = NodeScheduleState::RunningAndRescheduled; - break; - } - case NodeScheduleState::RunningAndRescheduled: { - /* Scheduled already, nothing to do. */ - break; - } - } - } - - static void run_node_from_task_pool(TaskPool *task_pool, void *task_data) - { - void *user_data = BLI_task_pool_user_data(task_pool); - GeometryNodesEvaluator &evaluator = *(GeometryNodesEvaluator *)user_data; - const NodeWithState *root_node_with_state = (const NodeWithState *)task_data; - - /* First, the node provided by the task pool is executed. During the execution other nodes - * might be scheduled. One of those nodes is not added to the task pool but is executed in the - * loop below directly. This has two main benefits: - * - Fewer round trips through the task pool which add threading overhead. - * - Helps with cpu cache efficiency, because a thread is more likely to process data that it - * has processed shortly before. - */ - DNode next_node_to_run = root_node_with_state->node; - while (next_node_to_run) { - NodeTaskRunState run_state; - evaluator.node_task_run(next_node_to_run, &run_state); - next_node_to_run = run_state.next_node_to_run; - } - } - - void node_task_run(const DNode node, NodeTaskRunState *run_state) - { - /* These nodes are sometimes scheduled. We could also check for them in other places, but - * it's the easiest to do it here. */ - if (node->is_group_input_node() || node->is_group_output_node()) { - return; - } - - NodeState &node_state = *node_states_.lookup_key_as(node).state; - - const bool do_execute_node = this->node_task_preprocessing(node, node_state, run_state); - - /* Only execute the node if all prerequisites are met. There has to be an output that is - * required and all required inputs have to be provided already. */ - if (do_execute_node) { - this->execute_node(node, node_state, run_state); - } - - this->node_task_postprocessing(node, node_state, do_execute_node, run_state); - } - - bool node_task_preprocessing(const DNode node, - NodeState &node_state, - NodeTaskRunState *run_state) - { - bool do_execute_node = false; - this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) { - BLI_assert(node_state.schedule_state == NodeScheduleState::Scheduled); - node_state.schedule_state = NodeScheduleState::Running; - - /* Early return if the node has finished already. */ - if (locked_node.node_state.node_has_finished) { - return; - } - /* Prepare outputs and check if actually any new outputs have to be computed. */ - if (!this->prepare_node_outputs_for_execution(locked_node)) { - return; - } - /* Initialize inputs that don't support laziness. This is done after at least one output is - * required and before we check that all required inputs are provided. This reduces the - * number of "round-trips" through the task pool by one for most nodes. */ - if (!node_state.non_lazy_inputs_handled) { - this->require_non_lazy_inputs(locked_node); - node_state.non_lazy_inputs_handled = true; - } - /* Prepare inputs and check if all required inputs are provided. */ - if (!this->prepare_node_inputs_for_execution(locked_node)) { - return; - } - do_execute_node = true; - }); - return do_execute_node; - } - - /* A node is finished when it has computed all outputs that may be used have been computed and - * when no input is still forced to be computed. */ - bool finish_node_if_possible(LockedNode &locked_node) - { - if (locked_node.node_state.node_has_finished) { - /* Early return in case this node is known to have finished already. */ - return true; - } - - /* Check if there is any output that might be used but has not been computed yet. */ - for (OutputState &output_state : locked_node.node_state.outputs) { - if (output_state.has_been_computed) { - continue; - } - if (output_state.output_usage != ValueUsage::Unused) { - return false; - } - } - - /* Check if there is an input that still has to be computed. */ - for (InputState &input_state : locked_node.node_state.inputs) { - if (input_state.force_compute) { - if (!input_state.was_ready_for_execution) { - return false; - } - } - } - - /* If there are no remaining outputs, all the inputs can be destructed and/or can become - * unused. This can also trigger a chain reaction where nodes to the left become finished - * too. */ - for (const int i : locked_node.node->inputs().index_range()) { - const DInputSocket socket = locked_node.node.input(i); - InputState &input_state = locked_node.node_state.inputs[i]; - if (input_state.usage == ValueUsage::Maybe) { - this->set_input_unused(locked_node, socket); - } - else if (input_state.usage == ValueUsage::Required) { - /* The value was required, so it cannot become unused. However, we can destruct the - * value. */ - this->destruct_input_value_if_exists(locked_node, socket); - } - } - locked_node.node_state.node_has_finished = true; - return true; - } - - bool prepare_node_outputs_for_execution(LockedNode &locked_node) - { - bool execution_is_necessary = false; - for (OutputState &output_state : locked_node.node_state.outputs) { - /* Update the output usage for execution to the latest value. */ - output_state.output_usage_for_execution = output_state.output_usage; - if (!output_state.has_been_computed) { - if (output_state.output_usage == ValueUsage::Required) { - /* Only evaluate when there is an output that is required but has not been computed. */ - execution_is_necessary = true; - } - } - } - return execution_is_necessary; - } - - void require_non_lazy_inputs(LockedNode &locked_node) - { - this->foreach_non_lazy_input(locked_node, [&](const DInputSocket socket) { - this->set_input_required(locked_node, socket); - }); - } - - void foreach_non_lazy_input(LockedNode &locked_node, FunctionRef<void(DInputSocket socket)> fn) - { - if (node_supports_laziness(locked_node.node)) { - /* In the future only some of the inputs may support laziness. */ - return; - } - /* Nodes that don't support laziness require all inputs. */ - for (const int i : locked_node.node->inputs().index_range()) { - InputState &input_state = locked_node.node_state.inputs[i]; - if (input_state.type == nullptr) { - /* Ignore unavailable/non-data sockets. */ - continue; - } - fn(locked_node.node.input(i)); - } - } - - /** - * Checks if requested inputs are available and "marks" all the inputs that are available - * during the node execution. Inputs that are provided after this function ends but before the - * node is executed, cannot be read by the node in the execution (note that this only affects - * nodes that support lazy inputs). - */ - bool prepare_node_inputs_for_execution(LockedNode &locked_node) - { - for (const int i : locked_node.node_state.inputs.index_range()) { - InputState &input_state = locked_node.node_state.inputs[i]; - if (input_state.type == nullptr) { - /* Ignore unavailable and non-data sockets. */ - continue; - } - const DInputSocket socket = locked_node.node.input(i); - const bool is_required = input_state.usage == ValueUsage::Required; - - /* No need to check this socket again. */ - if (input_state.was_ready_for_execution) { - continue; - } - - if (socket->is_multi_input_socket()) { - MultiInputValue &multi_value = *input_state.value.multi; - /* Checks if all the linked sockets have been provided already. */ - if (multi_value.all_values_available()) { - input_state.was_ready_for_execution = true; - } - else if (is_required) { - /* The input is required but is not fully provided yet. Therefore the node cannot be - * executed yet. */ - return false; - } - } - else { - SingleInputValue &single_value = *input_state.value.single; - if (single_value.value != nullptr) { - input_state.was_ready_for_execution = true; - } - else if (is_required) { - /* The input is required but has not been provided yet. Therefore the node cannot be - * executed yet. */ - return false; - } - } - } - /* All required inputs have been provided. */ - return true; - } - - /** - * Actually execute the node. All the required inputs are available and at least one output is - * required. - */ - void execute_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state) - { - const bNode &bnode = *node->bnode(); - - if (node_state.has_been_executed) { - if (!node_supports_laziness(node)) { - /* Nodes that don't support laziness must not be executed more than once. */ - BLI_assert_unreachable(); - } - } - node_state.has_been_executed = true; - - /* Use the geometry node execute callback if it exists. */ - if (bnode.typeinfo->geometry_node_execute != nullptr) { - this->execute_geometry_node(node, node_state, run_state); - return; - } - - /* Use the multi-function implementation if it exists. */ - const nodes::NodeMultiFunctions::Item &fn_item = params_.mf_by_node->try_get(node); - if (fn_item.fn != nullptr) { - this->execute_multi_function_node(node, fn_item, node_state, run_state); - return; - } - - this->execute_unknown_node(node, node_state, run_state); - } - - void execute_geometry_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state) - { - using Clock = std::chrono::steady_clock; - const bNode &bnode = *node->bnode(); - - NodeParamsProvider params_provider{*this, node, node_state, run_state}; - GeoNodeExecParams params{params_provider}; - Clock::time_point begin = Clock::now(); - bnode.typeinfo->geometry_node_execute(params); - Clock::time_point end = Clock::now(); - const std::chrono::microseconds duration = - std::chrono::duration_cast<std::chrono::microseconds>(end - begin); - if (params_.geo_logger != nullptr) { - params_.geo_logger->local().log_execution_time(node, duration); - } - } - - void execute_multi_function_node(const DNode node, - const nodes::NodeMultiFunctions::Item &fn_item, - NodeState &node_state, - NodeTaskRunState *run_state) - { - LinearAllocator<> &allocator = local_allocators_.local(); - - bool any_input_is_field = false; - Vector<const void *, 16> input_values; - Vector<const ValueOrFieldCPPType *, 16> input_types; - for (const int i : node->inputs().index_range()) { - const InputSocketRef &socket_ref = node->input(i); - if (!socket_ref.is_available()) { - continue; - } - BLI_assert(!socket_ref.is_multi_input_socket()); - InputState &input_state = node_state.inputs[i]; - BLI_assert(input_state.was_ready_for_execution); - SingleInputValue &single_value = *input_state.value.single; - BLI_assert(single_value.value != nullptr); - const ValueOrFieldCPPType &field_cpp_type = static_cast<const ValueOrFieldCPPType &>( - *input_state.type); - input_values.append(single_value.value); - input_types.append(&field_cpp_type); - if (field_cpp_type.is_field(single_value.value)) { - any_input_is_field = true; - } - } - - if (any_input_is_field) { - this->execute_multi_function_node__field( - node, fn_item, node_state, allocator, input_values, input_types, run_state); - } - else { - this->execute_multi_function_node__value( - node, *fn_item.fn, node_state, allocator, input_values, input_types, run_state); - } - } - - void execute_multi_function_node__field(const DNode node, - const nodes::NodeMultiFunctions::Item &fn_item, - NodeState &node_state, - LinearAllocator<> &allocator, - Span<const void *> input_values, - Span<const ValueOrFieldCPPType *> input_types, - NodeTaskRunState *run_state) - { - Vector<GField> input_fields; - for (const int i : input_values.index_range()) { - const void *input_value_or_field = input_values[i]; - const ValueOrFieldCPPType &field_cpp_type = *input_types[i]; - input_fields.append(field_cpp_type.as_field(input_value_or_field)); - } - - std::shared_ptr<fn::FieldOperation> operation; - if (fn_item.owned_fn) { - operation = std::make_shared<fn::FieldOperation>(fn_item.owned_fn, std::move(input_fields)); - } - else { - operation = std::make_shared<fn::FieldOperation>(*fn_item.fn, std::move(input_fields)); - } - - int output_index = 0; - for (const int i : node->outputs().index_range()) { - const OutputSocketRef &socket_ref = node->output(i); - if (!socket_ref.is_available()) { - continue; - } - OutputState &output_state = node_state.outputs[i]; - const DOutputSocket socket{node.context(), &socket_ref}; - const ValueOrFieldCPPType *cpp_type = static_cast<const ValueOrFieldCPPType *>( - get_socket_cpp_type(socket_ref)); - GField new_field{operation, output_index}; - void *buffer = allocator.allocate(cpp_type->size(), cpp_type->alignment()); - cpp_type->construct_from_field(buffer, std::move(new_field)); - this->forward_output(socket, {cpp_type, buffer}, run_state); - output_state.has_been_computed = true; - output_index++; - } - } - - void execute_multi_function_node__value(const DNode node, - const MultiFunction &fn, - NodeState &node_state, - LinearAllocator<> &allocator, - Span<const void *> input_values, - Span<const ValueOrFieldCPPType *> input_types, - NodeTaskRunState *run_state) - { - MFParamsBuilder params{fn, 1}; - for (const int i : input_values.index_range()) { - const void *input_value_or_field = input_values[i]; - const ValueOrFieldCPPType &field_cpp_type = *input_types[i]; - const CPPType &base_type = field_cpp_type.base_type(); - const void *input_value = field_cpp_type.get_value_ptr(input_value_or_field); - params.add_readonly_single_input(GVArray::ForSingleRef(base_type, 1, input_value)); - } - - Vector<GMutablePointer, 16> output_buffers; - for (const int i : node->outputs().index_range()) { - const DOutputSocket socket = node.output(i); - if (!socket->is_available()) { - output_buffers.append({}); - continue; - } - const ValueOrFieldCPPType *value_or_field_type = static_cast<const ValueOrFieldCPPType *>( - get_socket_cpp_type(socket)); - const CPPType &base_type = value_or_field_type->base_type(); - void *value_or_field_buffer = allocator.allocate(value_or_field_type->size(), - value_or_field_type->alignment()); - value_or_field_type->default_construct(value_or_field_buffer); - void *value_buffer = value_or_field_type->get_value_ptr(value_or_field_buffer); - base_type.destruct(value_buffer); - params.add_uninitialized_single_output(GMutableSpan{base_type, value_buffer, 1}); - output_buffers.append({value_or_field_type, value_or_field_buffer}); - } - - MFContextBuilder context; - fn.call(IndexRange(1), params, context); - - for (const int i : output_buffers.index_range()) { - GMutablePointer buffer = output_buffers[i]; - if (buffer.get() == nullptr) { - continue; - } - const DOutputSocket socket = node.output(i); - this->forward_output(socket, buffer, run_state); - - OutputState &output_state = node_state.outputs[i]; - output_state.has_been_computed = true; - } - } - - void execute_unknown_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state) - { - LinearAllocator<> &allocator = local_allocators_.local(); - for (const OutputSocketRef *socket : node->outputs()) { - if (!socket->is_available()) { - continue; - } - const CPPType *type = get_socket_cpp_type(*socket); - if (type == nullptr) { - continue; - } - /* Just forward the default value of the type as a fallback. That's typically better than - * crashing or doing nothing. */ - OutputState &output_state = node_state.outputs[socket->index()]; - output_state.has_been_computed = true; - void *buffer = allocator.allocate(type->size(), type->alignment()); - this->construct_default_value(*type, buffer); - this->forward_output({node.context(), socket}, {*type, buffer}, run_state); - } - } - - void node_task_postprocessing(const DNode node, - NodeState &node_state, - bool was_executed, - NodeTaskRunState *run_state) - { - this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) { - const bool node_has_finished = this->finish_node_if_possible(locked_node); - const bool reschedule_requested = node_state.schedule_state == - NodeScheduleState::RunningAndRescheduled; - node_state.schedule_state = NodeScheduleState::NotScheduled; - if (reschedule_requested && !node_has_finished) { - /* Either the node rescheduled itself or another node tried to schedule it while it ran. */ - this->schedule_node(locked_node); - } - if (was_executed) { - this->assert_expected_outputs_have_been_computed(locked_node); - } - }); - } - - void assert_expected_outputs_have_been_computed(LockedNode &locked_node) - { -#ifdef DEBUG - /* Outputs can only be computed when all required inputs have been provided. */ - if (locked_node.node_state.missing_required_inputs > 0) { - return; - } - /* If the node is still scheduled, it is not necessary that all its expected outputs are - * computed yet. */ - if (locked_node.node_state.schedule_state == NodeScheduleState::Scheduled) { - return; - } - - const bool supports_laziness = node_supports_laziness(locked_node.node); - /* Iterating over sockets instead of the states directly, because that makes it easier to - * figure out which socket is missing when one of the asserts is hit. */ - for (const OutputSocketRef *socket_ref : locked_node.node->outputs()) { - OutputState &output_state = locked_node.node_state.outputs[socket_ref->index()]; - if (supports_laziness) { - /* Expected that at least all required sockets have been computed. If more outputs become - * required later, the node will be executed again. */ - if (output_state.output_usage_for_execution == ValueUsage::Required) { - BLI_assert(output_state.has_been_computed); - } - } - else { - /* Expect that all outputs that may be used have been computed, because the node cannot - * be executed again. */ - if (output_state.output_usage_for_execution != ValueUsage::Unused) { - BLI_assert(output_state.has_been_computed); - } - } - } -#else - UNUSED_VARS(locked_node); -#endif - } - - void extract_group_outputs() - { - for (const DInputSocket &socket : params_.output_sockets) { - BLI_assert(socket->is_available()); - BLI_assert(!socket->is_multi_input_socket()); - - const DNode node = socket.node(); - NodeState &node_state = this->get_node_state(node); - InputState &input_state = node_state.inputs[socket->index()]; - - SingleInputValue &single_value = *input_state.value.single; - void *value = single_value.value; - - /* The value should have been computed by now. If this assert is hit, it means that there - * was some scheduling issue before. */ - BLI_assert(value != nullptr); - - /* Move value into memory owned by the outer allocator. */ - const CPPType &type = *input_state.type; - void *buffer = outer_allocator_.allocate(type.size(), type.alignment()); - type.move_construct(value, buffer); - - params_.r_output_values.append({type, buffer}); - } - } - - /** - * Load the required input from the socket or trigger nodes to the left to compute the value. - * \return True when the node will be triggered by another node again when the value is computed. - */ - bool set_input_required(LockedNode &locked_node, const DInputSocket input_socket) - { - BLI_assert(locked_node.node == input_socket.node()); - InputState &input_state = locked_node.node_state.inputs[input_socket->index()]; - - /* Value set as unused cannot become used again. */ - BLI_assert(input_state.usage != ValueUsage::Unused); - - if (input_state.was_ready_for_execution) { - return false; - } - - if (input_state.usage == ValueUsage::Required) { - /* If the input was not ready for execution but is required, the node will be triggered again - * once the input has been computed. */ - return true; - } - input_state.usage = ValueUsage::Required; - - /* Count how many values still have to be added to this input until it is "complete". */ - int missing_values = 0; - if (input_socket->is_multi_input_socket()) { - MultiInputValue &multi_value = *input_state.value.multi; - missing_values = multi_value.missing_values(); - } - else { - SingleInputValue &single_value = *input_state.value.single; - if (single_value.value == nullptr) { - missing_values = 1; - } - } - if (missing_values == 0) { - return false; - } - /* Increase the total number of missing required inputs. This ensures that the node will be - * scheduled correctly when all inputs have been provided. */ - locked_node.node_state.missing_required_inputs += missing_values; - - /* Get all origin sockets, because we have to tag those as required as well. */ - Vector<DSocket> origin_sockets; - input_socket.foreach_origin_socket( - [&](const DSocket origin_socket) { origin_sockets.append(origin_socket); }); - - if (origin_sockets.is_empty()) { - /* If there are no origin sockets, just load the value from the socket directly. */ - this->load_unlinked_input_value(locked_node, input_socket, input_state, input_socket); - locked_node.node_state.missing_required_inputs -= 1; - return false; - } - bool requested_from_other_node = false; - for (const DSocket &origin_socket : origin_sockets) { - if (origin_socket->is_input()) { - /* Load the value directly from the origin socket. In most cases this is an unlinked - * group input. */ - this->load_unlinked_input_value(locked_node, input_socket, input_state, origin_socket); - locked_node.node_state.missing_required_inputs -= 1; - } - else { - /* The value has not been computed yet, so when it will be forwarded by another node, this - * node will be triggered. */ - requested_from_other_node = true; - locked_node.delayed_required_outputs.append(DOutputSocket(origin_socket)); - } - } - /* If this node will be triggered by another node, we don't have to schedule it now. */ - if (requested_from_other_node) { - return true; - } - return false; - } - - void set_input_unused(LockedNode &locked_node, const DInputSocket socket) - { - InputState &input_state = locked_node.node_state.inputs[socket->index()]; - - /* A required socket cannot become unused. */ - BLI_assert(input_state.usage != ValueUsage::Required); - - if (input_state.usage == ValueUsage::Unused) { - /* Nothing to do in this case. */ - return; - } - input_state.usage = ValueUsage::Unused; - - /* If the input is unused, its value can be destructed now. */ - this->destruct_input_value_if_exists(locked_node, socket); - - if (input_state.was_ready_for_execution) { - /* If the value was already computed, we don't need to notify origin nodes. */ - return; - } - - /* Notify origin nodes that might want to set its inputs as unused as well. */ - socket.foreach_origin_socket([&](const DSocket origin_socket) { - if (origin_socket->is_input()) { - /* Values from these sockets are loaded directly from the sockets, so there is no node to - * notify. */ - return; - } - /* Delay notification of the other node until this node is not locked anymore. */ - locked_node.delayed_unused_outputs.append(DOutputSocket(origin_socket)); - }); - } - - void send_output_required_notification(const DOutputSocket socket, NodeTaskRunState *run_state) - { - const DNode node = socket.node(); - NodeState &node_state = this->get_node_state(node); - OutputState &output_state = node_state.outputs[socket->index()]; - - this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) { - if (output_state.output_usage == ValueUsage::Required) { - /* Output is marked as required already. So the node is scheduled already. */ - return; - } - /* The origin node needs to be scheduled so that it provides the requested input - * eventually. */ - output_state.output_usage = ValueUsage::Required; - this->schedule_node(locked_node); - }); - } - - void send_output_unused_notification(const DOutputSocket socket, NodeTaskRunState *run_state) - { - const DNode node = socket.node(); - NodeState &node_state = this->get_node_state(node); - OutputState &output_state = node_state.outputs[socket->index()]; - - this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) { - output_state.potential_users -= 1; - if (output_state.potential_users == 0) { - /* The socket might be required even though the output is not used by other sockets. That - * can happen when the socket is forced to be computed. */ - if (output_state.output_usage != ValueUsage::Required) { - /* The output socket has no users anymore. */ - output_state.output_usage = ValueUsage::Unused; - /* Schedule the origin node in case it wants to set its inputs as unused as well. */ - this->schedule_node(locked_node); - } - } - }); - } - - void add_node_to_task_pool(const DNode node) - { - /* Push the task to the pool while it is not locked to avoid a deadlock in case when the task - * is executed immediately. */ - const NodeWithState *node_with_state = node_states_.lookup_key_ptr_as(node); - BLI_task_pool_push( - task_pool_, run_node_from_task_pool, (void *)node_with_state, false, nullptr); - } - - /** - * Moves a newly computed value from an output socket to all the inputs that might need it. - * Takes ownership of the value and destructs if it is unused. - */ - void forward_output(const DOutputSocket from_socket, - GMutablePointer value_to_forward, - NodeTaskRunState *run_state) - { - BLI_assert(value_to_forward.get() != nullptr); - - LinearAllocator<> &allocator = local_allocators_.local(); - - Vector<DSocket> log_original_value_sockets; - Vector<DInputSocket> forward_original_value_sockets; - log_original_value_sockets.append(from_socket); - - from_socket.foreach_target_socket( - [&](const DInputSocket to_socket, const DOutputSocket::TargetSocketPathInfo &path_info) { - if (!this->should_forward_to_socket(to_socket)) { - return; - } - BLI_assert(to_socket == path_info.sockets.last()); - GMutablePointer current_value = value_to_forward; - for (const DSocket &next_socket : path_info.sockets) { - const DNode next_node = next_socket.node(); - const bool is_last_socket = to_socket == next_socket; - const bool do_conversion_if_necessary = is_last_socket || - next_node->is_group_output_node() || - (next_node->is_group_node() && - !next_node->is_muted()); - if (do_conversion_if_necessary) { - const CPPType &next_type = *get_socket_cpp_type(next_socket); - if (*current_value.type() != next_type) { - void *buffer = allocator.allocate(next_type.size(), next_type.alignment()); - this->convert_value(*current_value.type(), next_type, current_value.get(), buffer); - if (current_value.get() != value_to_forward.get()) { - current_value.destruct(); - } - current_value = {next_type, buffer}; - } - } - if (current_value.get() == value_to_forward.get()) { - /* Log the original value at the current socket. */ - log_original_value_sockets.append(next_socket); - } - else { - /* Multi-input sockets are logged when all values are available. */ - if (!(next_socket->is_input() && next_socket->as_input().is_multi_input_socket())) { - /* Log the converted value at the socket. */ - this->log_socket_value({next_socket}, current_value); - } - } - } - if (current_value.get() == value_to_forward.get()) { - /* The value has not been converted, so forward the original value. */ - forward_original_value_sockets.append(to_socket); - } - else { - /* The value has been converted. */ - this->add_value_to_input_socket(to_socket, from_socket, current_value, run_state); - } - }); - this->log_socket_value(log_original_value_sockets, value_to_forward); - this->forward_to_sockets_with_same_type( - allocator, forward_original_value_sockets, value_to_forward, from_socket, run_state); - } - - bool should_forward_to_socket(const DInputSocket socket) - { - const DNode to_node = socket.node(); - const NodeWithState *target_node_with_state = node_states_.lookup_key_ptr_as(to_node); - if (target_node_with_state == nullptr) { - /* If the socket belongs to a node that has no state, the entire node is not used. */ - return false; - } - NodeState &target_node_state = *target_node_with_state->state; - InputState &target_input_state = target_node_state.inputs[socket->index()]; - - std::lock_guard lock{target_node_state.mutex}; - /* Do not forward to an input socket whose value won't be used. */ - return target_input_state.usage != ValueUsage::Unused; - } - - void forward_to_sockets_with_same_type(LinearAllocator<> &allocator, - Span<DInputSocket> to_sockets, - GMutablePointer value_to_forward, - const DOutputSocket from_socket, - NodeTaskRunState *run_state) - { - if (to_sockets.is_empty()) { - /* Value is not used anymore, so it can be destructed. */ - value_to_forward.destruct(); - } - else if (to_sockets.size() == 1) { - /* Value is only used by one input socket, no need to copy it. */ - const DInputSocket to_socket = to_sockets[0]; - this->add_value_to_input_socket(to_socket, from_socket, value_to_forward, run_state); - } - else { - /* Multiple inputs use the value, make a copy for every input except for one. */ - /* First make the copies, so that the next node does not start modifying the value while we - * are still making copies. */ - const CPPType &type = *value_to_forward.type(); - for (const DInputSocket &to_socket : to_sockets.drop_front(1)) { - void *buffer = allocator.allocate(type.size(), type.alignment()); - type.copy_construct(value_to_forward.get(), buffer); - this->add_value_to_input_socket(to_socket, from_socket, {type, buffer}, run_state); - } - /* Forward the original value to one of the targets. */ - const DInputSocket to_socket = to_sockets[0]; - this->add_value_to_input_socket(to_socket, from_socket, value_to_forward, run_state); - } - } - - void add_value_to_input_socket(const DInputSocket socket, - const DOutputSocket origin, - GMutablePointer value, - NodeTaskRunState *run_state) - { - BLI_assert(socket->is_available()); - - const DNode node = socket.node(); - NodeState &node_state = this->get_node_state(node); - InputState &input_state = node_state.inputs[socket->index()]; - - this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) { - if (socket->is_multi_input_socket()) { - /* Add a new value to the multi-input. */ - MultiInputValue &multi_value = *input_state.value.multi; - multi_value.add_value(origin, value.get()); - - if (multi_value.all_values_available()) { - this->log_socket_value({socket}, input_state, multi_value.values); - } - } - else { - /* Assign the value to the input. */ - SingleInputValue &single_value = *input_state.value.single; - BLI_assert(single_value.value == nullptr); - single_value.value = value.get(); - } - - if (input_state.usage == ValueUsage::Required) { - node_state.missing_required_inputs--; - if (node_state.missing_required_inputs == 0) { - /* Schedule node if all the required inputs have been provided. */ - this->schedule_node(locked_node); - } - } - }); - } - - /** - * Loads the value of a socket that is not computed by another node. Note that the socket may - * still be linked to e.g. a Group Input node, but the socket on the outside is not connected to - * anything. - * - * \param input_socket: The socket of the node that wants to use the value. - * \param origin_socket: The socket that we want to load the value from. - */ - void load_unlinked_input_value(LockedNode &locked_node, - const DInputSocket input_socket, - InputState &input_state, - const DSocket origin_socket) - { - /* Only takes locked node as parameter, because the node needs to be locked. */ - UNUSED_VARS(locked_node); - - GMutablePointer value = this->get_value_from_socket(origin_socket, *input_state.type); - if (input_socket->is_multi_input_socket()) { - MultiInputValue &multi_value = *input_state.value.multi; - multi_value.add_value(origin_socket, value.get()); - if (multi_value.all_values_available()) { - this->log_socket_value({input_socket}, input_state, multi_value.values); - } - } - else { - SingleInputValue &single_value = *input_state.value.single; - single_value.value = value.get(); - Vector<DSocket> sockets_to_log_to = {input_socket}; - if (origin_socket != input_socket) { - /* This might log the socket value for the #origin_socket more than once, but this is - * handled by the logging system gracefully. */ - sockets_to_log_to.append(origin_socket); - } - /* TODO: Log to the intermediate sockets between the group input and where the value is - * actually used as well. */ - this->log_socket_value(sockets_to_log_to, value); - } - } - - void destruct_input_value_if_exists(LockedNode &locked_node, const DInputSocket socket) - { - InputState &input_state = locked_node.node_state.inputs[socket->index()]; - if (socket->is_multi_input_socket()) { - MultiInputValue &multi_value = *input_state.value.multi; - for (void *&value : multi_value.values) { - if (value != nullptr) { - input_state.type->destruct(value); - value = nullptr; - } - } - multi_value.provided_value_count = 0; - } - else { - SingleInputValue &single_value = *input_state.value.single; - if (single_value.value != nullptr) { - input_state.type->destruct(single_value.value); - single_value.value = nullptr; - } - } - } - - GMutablePointer get_value_from_socket(const DSocket socket, const CPPType &required_type) - { - LinearAllocator<> &allocator = local_allocators_.local(); - - const CPPType &type = *get_socket_cpp_type(socket); - void *buffer = allocator.allocate(type.size(), type.alignment()); - get_socket_value(*socket.socket_ref(), buffer); - - if (type == required_type) { - return {type, buffer}; - } - void *converted_buffer = allocator.allocate(required_type.size(), required_type.alignment()); - this->convert_value(type, required_type, buffer, converted_buffer); - type.destruct(buffer); - return {required_type, converted_buffer}; - } - - void convert_value(const CPPType &from_type, - const CPPType &to_type, - const void *from_value, - void *to_value) - { - if (from_type == to_type) { - from_type.copy_construct(from_value, to_value); - return; - } - const ValueOrFieldCPPType *from_field_type = dynamic_cast<const ValueOrFieldCPPType *>( - &from_type); - const ValueOrFieldCPPType *to_field_type = dynamic_cast<const ValueOrFieldCPPType *>(&to_type); - - if (from_field_type != nullptr && to_field_type != nullptr) { - const CPPType &from_base_type = from_field_type->base_type(); - const CPPType &to_base_type = to_field_type->base_type(); - if (conversions_.is_convertible(from_base_type, to_base_type)) { - if (from_field_type->is_field(from_value)) { - const GField &from_field = *from_field_type->get_field_ptr(from_value); - to_field_type->construct_from_field(to_value, - conversions_.try_convert(from_field, to_base_type)); - } - else { - to_field_type->default_construct(to_value); - const void *from_value_ptr = from_field_type->get_value_ptr(from_value); - void *to_value_ptr = to_field_type->get_value_ptr(to_value); - conversions_.get_conversion_functions(from_base_type, to_base_type) - ->convert_single_to_initialized(from_value_ptr, to_value_ptr); - } - return; - } - } - if (conversions_.is_convertible(from_type, to_type)) { - /* Do the conversion if possible. */ - conversions_.convert_to_uninitialized(from_type, to_type, from_value, to_value); - } - else { - /* Cannot convert, use default value instead. */ - this->construct_default_value(to_type, to_value); - } - } - - void construct_default_value(const CPPType &type, void *r_value) - { - type.value_initialize(r_value); - } - - NodeState &get_node_state(const DNode node) - { - return *node_states_.lookup_key_as(node).state; - } - - void log_socket_value(DSocket socket, InputState &input_state, Span<void *> values) - { - if (params_.geo_logger == nullptr) { - return; - } - - Vector<GPointer, 16> value_pointers; - value_pointers.reserve(values.size()); - const CPPType &type = *input_state.type; - for (const void *value : values) { - value_pointers.append({type, value}); - } - params_.geo_logger->local().log_multi_value_socket(socket, value_pointers); - } - - void log_socket_value(Span<DSocket> sockets, GPointer value) - { - if (params_.geo_logger == nullptr) { - return; - } - params_.geo_logger->local().log_value_for_sockets(sockets, value); - } - - void log_debug_message(DNode node, std::string message) - { - if (params_.geo_logger == nullptr) { - return; - } - params_.geo_logger->local().log_debug_message(node, std::move(message)); - } - - /* In most cases when `NodeState` is accessed, the node has to be locked first to avoid race - * conditions. */ - template<typename Function> - void with_locked_node(const DNode node, - NodeState &node_state, - NodeTaskRunState *run_state, - const Function &function) - { - LockedNode locked_node{node, node_state}; - - node_state.mutex.lock(); - /* Isolate this thread because we don't want it to start executing another node. This other - * node might want to lock the same mutex leading to a deadlock. */ - threading::isolate_task([&] { function(locked_node); }); - node_state.mutex.unlock(); - - /* Then send notifications to the other nodes after the node state is unlocked. This avoids - * locking two nodes at the same time on this thread and helps to prevent deadlocks. */ - for (const DOutputSocket &socket : locked_node.delayed_required_outputs) { - this->send_output_required_notification(socket, run_state); - } - for (const DOutputSocket &socket : locked_node.delayed_unused_outputs) { - this->send_output_unused_notification(socket, run_state); - } - for (const DNode &node_to_schedule : locked_node.delayed_scheduled_nodes) { - if (run_state != nullptr && !run_state->next_node_to_run) { - /* Execute the node on the same thread after the current node finished. */ - /* Currently, this assumes that it is always best to run the first node that is scheduled - * on the same thread. That is usually correct, because the geometry socket which carries - * the most data usually comes first in nodes. */ - run_state->next_node_to_run = node_to_schedule; - } - else { - /* Push the node to the task pool so that another thread can start working on it. */ - this->add_node_to_task_pool(node_to_schedule); - } - } - } -}; - -NodeParamsProvider::NodeParamsProvider(GeometryNodesEvaluator &evaluator, - DNode dnode, - NodeState &node_state, - NodeTaskRunState *run_state) - : evaluator_(evaluator), node_state_(node_state), run_state_(run_state) -{ - this->dnode = dnode; - this->self_object = evaluator.params_.self_object; - this->modifier = &evaluator.params_.modifier_->modifier; - this->depsgraph = evaluator.params_.depsgraph; - this->logger = evaluator.params_.geo_logger; -} - -bool NodeParamsProvider::can_get_input(StringRef identifier) const -{ - const DInputSocket socket = this->dnode.input_by_identifier(identifier); - BLI_assert(socket); - - InputState &input_state = node_state_.inputs[socket->index()]; - if (!input_state.was_ready_for_execution) { - return false; - } - - if (socket->is_multi_input_socket()) { - MultiInputValue &multi_value = *input_state.value.multi; - return multi_value.all_values_available(); - } - SingleInputValue &single_value = *input_state.value.single; - return single_value.value != nullptr; -} - -bool NodeParamsProvider::can_set_output(StringRef identifier) const -{ - const DOutputSocket socket = this->dnode.output_by_identifier(identifier); - BLI_assert(socket); - - OutputState &output_state = node_state_.outputs[socket->index()]; - return !output_state.has_been_computed; -} - -GMutablePointer NodeParamsProvider::extract_input(StringRef identifier) -{ - const DInputSocket socket = this->dnode.input_by_identifier(identifier); - BLI_assert(socket); - BLI_assert(!socket->is_multi_input_socket()); - BLI_assert(this->can_get_input(identifier)); - - InputState &input_state = node_state_.inputs[socket->index()]; - SingleInputValue &single_value = *input_state.value.single; - void *value = single_value.value; - single_value.value = nullptr; - return {*input_state.type, value}; -} - -Vector<GMutablePointer> NodeParamsProvider::extract_multi_input(StringRef identifier) -{ - const DInputSocket socket = this->dnode.input_by_identifier(identifier); - BLI_assert(socket); - BLI_assert(socket->is_multi_input_socket()); - BLI_assert(this->can_get_input(identifier)); - - InputState &input_state = node_state_.inputs[socket->index()]; - MultiInputValue &multi_value = *input_state.value.multi; - - Vector<GMutablePointer> ret_values; - for (void *&value : multi_value.values) { - BLI_assert(value != nullptr); - ret_values.append({*input_state.type, value}); - value = nullptr; - } - return ret_values; -} - -GPointer NodeParamsProvider::get_input(StringRef identifier) const -{ - const DInputSocket socket = this->dnode.input_by_identifier(identifier); - BLI_assert(socket); - BLI_assert(!socket->is_multi_input_socket()); - BLI_assert(this->can_get_input(identifier)); - - InputState &input_state = node_state_.inputs[socket->index()]; - SingleInputValue &single_value = *input_state.value.single; - return {*input_state.type, single_value.value}; -} - -GMutablePointer NodeParamsProvider::alloc_output_value(const CPPType &type) -{ - LinearAllocator<> &allocator = evaluator_.local_allocators_.local(); - return {type, allocator.allocate(type.size(), type.alignment())}; -} - -void NodeParamsProvider::set_output(StringRef identifier, GMutablePointer value) -{ - const DOutputSocket socket = this->dnode.output_by_identifier(identifier); - BLI_assert(socket); - - OutputState &output_state = node_state_.outputs[socket->index()]; - BLI_assert(!output_state.has_been_computed); - evaluator_.forward_output(socket, value, run_state_); - output_state.has_been_computed = true; -} - -bool NodeParamsProvider::lazy_require_input(StringRef identifier) -{ - BLI_assert(node_supports_laziness(this->dnode)); - const DInputSocket socket = this->dnode.input_by_identifier(identifier); - BLI_assert(socket); - - InputState &input_state = node_state_.inputs[socket->index()]; - if (input_state.was_ready_for_execution) { - return false; - } - evaluator_.with_locked_node(this->dnode, node_state_, run_state_, [&](LockedNode &locked_node) { - if (!evaluator_.set_input_required(locked_node, socket)) { - /* Schedule the currently executed node again because the value is available now but was not - * ready for the current execution. */ - evaluator_.schedule_node(locked_node); - } - }); - return true; -} - -void NodeParamsProvider::set_input_unused(StringRef identifier) -{ - BLI_assert(node_supports_laziness(this->dnode)); - const DInputSocket socket = this->dnode.input_by_identifier(identifier); - BLI_assert(socket); - - evaluator_.with_locked_node(this->dnode, node_state_, run_state_, [&](LockedNode &locked_node) { - evaluator_.set_input_unused(locked_node, socket); - }); -} - -bool NodeParamsProvider::output_is_required(StringRef identifier) const -{ - const DOutputSocket socket = this->dnode.output_by_identifier(identifier); - BLI_assert(socket); - - OutputState &output_state = node_state_.outputs[socket->index()]; - if (output_state.has_been_computed) { - return false; - } - return output_state.output_usage_for_execution != ValueUsage::Unused; -} - -bool NodeParamsProvider::lazy_output_is_required(StringRef identifier) const -{ - BLI_assert(node_supports_laziness(this->dnode)); - const DOutputSocket socket = this->dnode.output_by_identifier(identifier); - BLI_assert(socket); - - OutputState &output_state = node_state_.outputs[socket->index()]; - if (output_state.has_been_computed) { - return false; - } - return output_state.output_usage_for_execution == ValueUsage::Required; -} - -void NodeParamsProvider::set_default_remaining_outputs() -{ - LinearAllocator<> &allocator = evaluator_.local_allocators_.local(); - - for (const int i : this->dnode->outputs().index_range()) { - OutputState &output_state = node_state_.outputs[i]; - if (output_state.has_been_computed) { - continue; - } - if (output_state.output_usage_for_execution == ValueUsage::Unused) { - continue; - } - - const DOutputSocket socket = this->dnode.output(i); - const CPPType *type = get_socket_cpp_type(socket); - BLI_assert(type != nullptr); - void *buffer = allocator.allocate(type->size(), type->alignment()); - type->value_initialize(buffer); - evaluator_.forward_output(socket, {type, buffer}, run_state_); - output_state.has_been_computed = true; - } -} - -void evaluate_geometry_nodes(GeometryNodesEvaluationParams ¶ms) -{ - GeometryNodesEvaluator evaluator{params}; - evaluator.execute(); -} - -} // namespace blender::modifiers::geometry_nodes diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh deleted file mode 100644 index cbcbcab5679..00000000000 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -#include "BLI_generic_pointer.hh" -#include "BLI_map.hh" - -#include "NOD_derived_node_tree.hh" -#include "NOD_geometry_nodes_eval_log.hh" -#include "NOD_multi_function.hh" - -#include "DNA_modifier_types.h" - -#include "FN_multi_function.hh" - -namespace geo_log = blender::nodes::geometry_nodes_eval_log; - -namespace blender::modifiers::geometry_nodes { - -using namespace nodes::derived_node_tree_types; - -struct GeometryNodesEvaluationParams { - blender::LinearAllocator<> allocator; - - Map<DOutputSocket, GMutablePointer> input_values; - Vector<DInputSocket> output_sockets; - /* These sockets will be computed but are not part of the output. Their value can be retrieved in - * `log_socket_value_fn`. These sockets are not part of `output_sockets` because then the - * evaluator would have to keep the socket values in memory until the end, which might not be - * necessary in all cases. Sometimes `log_socket_value_fn` might just want to look at the value - * and then it can be freed. */ - Vector<DSocket> force_compute_sockets; - nodes::NodeMultiFunctions *mf_by_node; - const NodesModifierData *modifier_; - Depsgraph *depsgraph; - Object *self_object; - geo_log::GeoLogger *geo_logger; - - Vector<GMutablePointer> r_output_values; -}; - -void evaluate_geometry_nodes(GeometryNodesEvaluationParams ¶ms); - -} // namespace blender::modifiers::geometry_nodes diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 94b48f65a66..caada225e75 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -53,7 +53,7 @@ static void generate_vert_coordinates(Mesh *mesh, INIT_MINMAX(min_co, max_co); - MVert *mv = mesh->mvert; + const MVert *mv = BKE_mesh_verts(mesh); for (int i = 0; i < mesh->totvert; i++, mv++) { copy_v3_v3(r_cos[i], mv->co); if (r_size != NULL && ob_center == NULL) { @@ -117,13 +117,13 @@ static void generate_vert_coordinates(Mesh *mesh, /* Note this modifies nos_new in-place. */ static void mix_normals(const float mix_factor, - MDeformVert *dvert, + const MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup, const float mix_limit, const short mix_mode, const int verts_num, - MLoop *mloop, + const MLoop *mloop, float (*nos_old)[3], float (*nos_new)[3], const int loops_num) @@ -175,11 +175,11 @@ static void mix_normals(const float mix_factor, static bool polygons_check_flip(MLoop *mloop, float (*nos)[3], CustomData *ldata, - MPoly *mpoly, + const MPoly *mpoly, float (*polynors)[3], const int polys_num) { - MPoly *mp; + const MPoly *mp; MDisps *mdisp = CustomData_get_layer(ldata, CD_MDISPS); int i; bool flipped = false; @@ -218,16 +218,16 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, const short mix_mode, const float mix_factor, const float mix_limit, - MDeformVert *dvert, + const MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup, - MVert *mvert, + const MVert *mvert, const int verts_num, MEdge *medge, const int edges_num, MLoop *mloop, const int loops_num, - MPoly *mpoly, + const MPoly *mpoly, const int polys_num) { Object *ob_target = enmd->target; @@ -279,7 +279,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, const float m2 = (b * b) / (a * a); const float n2 = (c * c) / (a * a); - MLoop *ml; + const MLoop *ml; float(*no)[3]; /* We reuse cos to now store the ellipsoid-normal of the verts! */ @@ -355,16 +355,16 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, const short mix_mode, const float mix_factor, const float mix_limit, - MDeformVert *dvert, + const MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup, - MVert *mvert, + const MVert *mvert, const int verts_num, MEdge *medge, const int edges_num, MLoop *mloop, const int loops_num, - MPoly *mpoly, + const MPoly *mpoly, const int polys_num) { Object *ob_target = enmd->target; @@ -399,7 +399,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, generate_vert_coordinates(mesh, ob, ob_target, NULL, verts_num, cos, NULL); BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)verts_num, __func__); - MLoop *ml; + const MLoop *ml; float(*no)[3]; /* We reuse cos to now store the 'to target' normal of the verts! */ @@ -509,7 +509,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, } Mesh *result; - if (mesh->medge == ((Mesh *)ob->data)->medge) { + if (BKE_mesh_edges(mesh) == BKE_mesh_edges(((Mesh *)ob->data))) { /* We need to duplicate data here, otherwise setting custom normals * (which may also affect sharp edges) could * modify original mesh, see T43671. */ @@ -523,13 +523,13 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, const int edges_num = result->totedge; const int loops_num = result->totloop; const int polys_num = result->totpoly; - MVert *mvert = result->mvert; - MEdge *medge = result->medge; - MLoop *mloop = result->mloop; - MPoly *mpoly = result->mpoly; + const MVert *verts = BKE_mesh_verts(result); + MEdge *edges = BKE_mesh_edges_for_write(result); + const MPoly *polys = BKE_mesh_polys(result); + MLoop *loops = BKE_mesh_loops_for_write(result); int defgrp_index; - MDeformVert *dvert; + const MDeformVert *dvert; float(*loopnors)[3] = NULL; @@ -543,15 +543,15 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, clnors = CustomData_duplicate_referenced_layer(ldata, CD_CUSTOMLOOPNORMAL, loops_num); loopnors = MEM_malloc_arrayN((size_t)loops_num, sizeof(*loopnors), __func__); - BKE_mesh_normals_loop_split(mvert, + BKE_mesh_normals_loop_split(verts, vert_normals, verts_num, - medge, + edges, edges_num, - mloop, + loops, loopnors, loops_num, - mpoly, + polys, poly_normals, polys_num, true, @@ -562,7 +562,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, } if (clnors == NULL) { - clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, loops_num); + clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, NULL, loops_num); } MOD_get_vgroup(ob, result, enmd->defgrp_name, &dvert, &defgrp_index); @@ -581,13 +581,13 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, dvert, defgrp_index, use_invert_vgroup, - mvert, + verts, verts_num, - medge, + edges, edges_num, - mloop, + loops, loops_num, - mpoly, + polys, polys_num); } else if (enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) { @@ -604,19 +604,19 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, dvert, defgrp_index, use_invert_vgroup, - mvert, + verts, verts_num, - medge, + edges, edges_num, - mloop, + loops, loops_num, - mpoly, + polys, polys_num); } MEM_SAFE_FREE(loopnors); - result->runtime.is_original = false; + result->runtime.is_original_bmesh = false; return result; } @@ -630,9 +630,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(enmd, DNA_struct_default_get(NormalEditModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { NormalEditModifierData *enmd = (NormalEditModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index ea9049200cc..bee1bd7795a 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -130,9 +130,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla } #ifdef WITH_OCEANSIM -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { OceanModifierData *omd = (OceanModifierData *)md; @@ -141,8 +139,7 @@ static void requiredDataMask(Object *UNUSED(ob), } } #else /* WITH_OCEANSIM */ -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *UNUSED(md), +static void requiredDataMask(ModifierData *UNUSED(md), CustomData_MeshMasks *UNUSED(r_cddata_masks)) { } @@ -169,9 +166,9 @@ typedef struct GenerateOceanGeometryData { float ix, iy; } GenerateOceanGeometryData; -static void generate_ocean_geometry_vertices(void *__restrict userdata, - const int y, - const TaskParallelTLS *__restrict UNUSED(tls)) +static void generate_ocean_geometry_verts(void *__restrict userdata, + const int y, + const TaskParallelTLS *__restrict UNUSED(tls)) { GenerateOceanGeometryData *gogd = userdata; int x; @@ -185,9 +182,9 @@ static void generate_ocean_geometry_vertices(void *__restrict userdata, } } -static void generate_ocean_geometry_polygons(void *__restrict userdata, - const int y, - const TaskParallelTLS *__restrict UNUSED(tls)) +static void generate_ocean_geometry_polys(void *__restrict userdata, + const int y, + const TaskParallelTLS *__restrict UNUSED(tls)) { GenerateOceanGeometryData *gogd = userdata; int x; @@ -273,26 +270,26 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co result = BKE_mesh_new_nomain(verts_num, 0, 0, polys_num * 4, polys_num); BKE_mesh_copy_parameters_for_eval(result, mesh_orig); - gogd.mverts = result->mvert; - gogd.mpolys = result->mpoly; - gogd.mloops = result->mloop; + gogd.mverts = BKE_mesh_verts_for_write(result); + gogd.mpolys = BKE_mesh_polys_for_write(result); + gogd.mloops = BKE_mesh_loops_for_write(result); TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = use_threading; /* create vertices */ - BLI_task_parallel_range(0, gogd.res_y + 1, &gogd, generate_ocean_geometry_vertices, &settings); + BLI_task_parallel_range(0, gogd.res_y + 1, &gogd, generate_ocean_geometry_verts, &settings); /* create faces */ - BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_polygons, &settings); + BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_polys, &settings); BKE_mesh_calc_edges(result, false, false); /* add uvs */ if (CustomData_number_of_layers(&result->ldata, CD_MLOOPUV) < MAX_MTFACE) { gogd.mloopuvs = CustomData_add_layer( - &result->ldata, CD_MLOOPUV, CD_CALLOC, NULL, polys_num * 4); + &result->ldata, CD_MLOOPUV, CD_SET_DEFAULT, NULL, polys_num * 4); if (gogd.mloopuvs) { /* unlikely to fail */ gogd.ix = 1.0 / gogd.rx; @@ -322,8 +319,6 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes const int resolution = (ctx->flag & MOD_APPLY_RENDER) ? omd->resolution : omd->viewport_resolution; - MVert *mverts; - int cfra_for_cache; int i, j; @@ -368,73 +363,75 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes CLAMP(cfra_for_cache, omd->bakestart, omd->bakeend); cfra_for_cache -= omd->bakestart; /* shift to 0 based */ - mverts = result->mvert; + MVert *verts = BKE_mesh_verts_for_write(result); + MPoly *polys = BKE_mesh_polys_for_write(result); /* add vcols before displacement - allows lookup based on position */ if (omd->flag & MOD_OCEAN_GENERATE_FOAM) { - if (CustomData_number_of_layers(&result->ldata, CD_PROP_BYTE_COLOR) < MAX_MCOL) { - const int polys_num = result->totpoly; - const int loops_num = result->totloop; - MLoop *mloops = result->mloop; - MLoopCol *mloopcols = CustomData_add_layer_named( - &result->ldata, CD_PROP_BYTE_COLOR, CD_CALLOC, NULL, loops_num, omd->foamlayername); - - MLoopCol *mloopcols_spray = NULL; - if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) { - mloopcols_spray = CustomData_add_layer_named( - &result->ldata, CD_PROP_BYTE_COLOR, CD_CALLOC, NULL, loops_num, omd->spraylayername); - } + const int polys_num = result->totpoly; + const int loops_num = result->totloop; + MLoop *mloops = BKE_mesh_loops_for_write(result); + MLoopCol *mloopcols = CustomData_add_layer_named( + &result->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, NULL, loops_num, omd->foamlayername); + + MLoopCol *mloopcols_spray = NULL; + if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) { + mloopcols_spray = CustomData_add_layer_named(&result->ldata, + CD_PROP_BYTE_COLOR, + CD_SET_DEFAULT, + NULL, + loops_num, + omd->spraylayername); + } - if (mloopcols) { /* unlikely to fail */ - MPoly *mpolys = result->mpoly; - MPoly *mp; + if (mloopcols) { /* unlikely to fail */ + MPoly *mp; - for (i = 0, mp = mpolys; i < polys_num; i++, mp++) { - MLoop *ml = &mloops[mp->loopstart]; - MLoopCol *mlcol = &mloopcols[mp->loopstart]; + for (i = 0, mp = polys; i < polys_num; i++, mp++) { + MLoop *ml = &mloops[mp->loopstart]; + MLoopCol *mlcol = &mloopcols[mp->loopstart]; - MLoopCol *mlcolspray = NULL; - if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) { - mlcolspray = &mloopcols_spray[mp->loopstart]; + MLoopCol *mlcolspray = NULL; + if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) { + mlcolspray = &mloopcols_spray[mp->loopstart]; + } + + for (j = mp->totloop; j--; ml++, mlcol++) { + const float *vco = verts[ml->v].co; + const float u = OCEAN_CO(size_co_inv, vco[0]); + const float v = OCEAN_CO(size_co_inv, vco[1]); + float foam; + + if (omd->oceancache && omd->cached == true) { + BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra_for_cache, u, v); + foam = ocr.foam; + CLAMP(foam, 0.0f, 1.0f); + } + else { + BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); + foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage); } - for (j = mp->totloop; j--; ml++, mlcol++) { - const float *vco = mverts[ml->v].co; - const float u = OCEAN_CO(size_co_inv, vco[0]); - const float v = OCEAN_CO(size_co_inv, vco[1]); - float foam; + mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255); + /* This needs to be set (render engine uses) */ + mlcol->a = 255; - if (omd->oceancache && omd->cached == true) { - BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra_for_cache, u, v); - foam = ocr.foam; - CLAMP(foam, 0.0f, 1.0f); + if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) { + if (omd->flag & MOD_OCEAN_INVERT_SPRAY) { + mlcolspray->r = ocr.Eminus[0] * 255; } else { - BKE_ocean_eval_uv(omd->ocean, &ocr, u, v); - foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage); + mlcolspray->r = ocr.Eplus[0] * 255; } - - mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255); - /* This needs to be set (render engine uses) */ - mlcol->a = 255; - - if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) { - if (omd->flag & MOD_OCEAN_INVERT_SPRAY) { - mlcolspray->r = ocr.Eminus[0] * 255; - } - else { - mlcolspray->r = ocr.Eplus[0] * 255; - } - mlcolspray->g = 0; - if (omd->flag & MOD_OCEAN_INVERT_SPRAY) { - mlcolspray->b = ocr.Eminus[2] * 255; - } - else { - mlcolspray->b = ocr.Eplus[2] * 255; - } - mlcolspray->a = 255; + mlcolspray->g = 0; + if (omd->flag & MOD_OCEAN_INVERT_SPRAY) { + mlcolspray->b = ocr.Eminus[2] * 255; + } + else { + mlcolspray->b = ocr.Eplus[2] * 255; } + mlcolspray->a = 255; } } } @@ -449,7 +446,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes const int verts_num = result->totvert; for (i = 0; i < verts_num; i++) { - float *vco = mverts[i].co; + float *vco = verts[i].co; const float u = OCEAN_CO(size_co_inv, vco[0]); const float v = OCEAN_CO(size_co_inv, vco[1]); @@ -595,7 +592,7 @@ static void spray_panel_draw_header(const bContext *UNUSED(C), Panel *panel) row = uiLayoutRow(layout, false); uiLayoutSetActive(row, use_foam); - uiItemR(row, ptr, "use_spray", 0, IFACE_("Spray"), ICON_NONE); + uiItemR(row, ptr, "use_spray", 0, CTX_IFACE_(BLT_I18NCONTEXT_ID_MESH, "Spray"), ICON_NONE); } static void spray_panel_draw(const bContext *UNUSED(C), Panel *panel) diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index d6435c55211..aab48101351 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -52,9 +52,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(pimd, DNA_struct_default_get(ParticleInstanceModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; @@ -200,9 +198,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * ParticleSimulationData sim; ParticleSystem *psys = NULL; ParticleData *pa = NULL; - MPoly *mpoly, *orig_mpoly; - MLoop *mloop, *orig_mloop; - MVert *mvert, *orig_mvert; int totvert, totpoly, totloop, totedge; int maxvert, maxpoly, maxloop, maxedge, part_end = 0, part_start; int k, p, p_skip; @@ -320,12 +315,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = BKE_mesh_new_nomain_from_template(mesh, maxvert, maxedge, 0, maxloop, maxpoly); - mvert = result->mvert; - orig_mvert = mesh->mvert; - mpoly = result->mpoly; - orig_mpoly = mesh->mpoly; - mloop = result->mloop; - orig_mloop = mesh->mloop; + const MVert *orig_mvert = BKE_mesh_verts(mesh); + const MPoly *orig_mpoly = BKE_mesh_polys(mesh); + const MLoop *orig_mloop = BKE_mesh_loops(mesh); + MVert *mvert = BKE_mesh_verts_for_write(result); + MEdge *edges = BKE_mesh_edges_for_write(result); + MPoly *mpoly = BKE_mesh_polys_for_write(result); + MLoop *mloop = BKE_mesh_loops_for_write(result); MLoopCol *mloopcols_index = CustomData_get_layer_named( &result->ldata, CD_PROP_BYTE_COLOR, pimd->index_layer_name); @@ -353,7 +349,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* set vertices coordinates */ for (k = 0; k < totvert; k++) { ParticleKey state; - MVert *inMV; + const MVert *inMV; int vindex = p_skip * totvert + k; MVert *mv = mvert + vindex; @@ -477,7 +473,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Create edges and adjust edge vertex indices. */ CustomData_copy_data(&mesh->edata, &result->edata, 0, p_skip * totedge, totedge); - MEdge *me = &result->medge[p_skip * totedge]; + MEdge *me = &edges[p_skip * totedge]; for (k = 0; k < totedge; k++, me++) { me->v1 += p_skip * totvert; me->v2 += p_skip * totvert; @@ -486,7 +482,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* create polys and loops */ for (k = 0; k < totpoly; k++) { - MPoly *inMP = orig_mpoly + k; + const MPoly *inMP = orig_mpoly + k; MPoly *mp = mpoly + p_skip * totpoly + k; CustomData_copy_data(&mesh->pdata, &result->pdata, k, p_skip * totpoly + k, 1); @@ -494,7 +490,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * mp->loopstart += p_skip * totloop; { - MLoop *inML = orig_mloop + inMP->loopstart; + const MLoop *inML = orig_mloop + inMP->loopstart; MLoop *ml = mloop + mp->loopstart; int j = mp->totloop; diff --git a/source/blender/modifiers/intern/MOD_particlesystem.cc b/source/blender/modifiers/intern/MOD_particlesystem.cc index 0c04c6fc062..7d3d384d3a8 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.cc +++ b/source/blender/modifiers/intern/MOD_particlesystem.cc @@ -87,9 +87,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index f21d536fadf..4241ca5a591 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -60,11 +60,11 @@ static void init_dualcon_mesh(DualConInput *input, Mesh *mesh) { memset(input, 0, sizeof(DualConInput)); - input->co = (void *)mesh->mvert; + input->co = (void *)BKE_mesh_verts(mesh); input->co_stride = sizeof(MVert); input->totco = mesh->totvert; - input->mloop = (void *)mesh->mloop; + input->mloop = (void *)BKE_mesh_loops(mesh); input->loop_stride = sizeof(MLoop); BKE_mesh_runtime_looptri_ensure(mesh); @@ -80,6 +80,9 @@ static void init_dualcon_mesh(DualConInput *input, Mesh *mesh) * keep track of the current elements */ typedef struct { Mesh *mesh; + MVert *verts; + MPoly *polys; + MLoop *loops; int curvert, curface; } DualConOutput; @@ -93,17 +96,20 @@ static void *dualcon_alloc_output(int totvert, int totquad) } output->mesh = BKE_mesh_new_nomain(totvert, 0, 0, 4 * totquad, totquad); + output->verts = BKE_mesh_verts_for_write(output->mesh); + output->polys = BKE_mesh_polys_for_write(output->mesh); + output->loops = BKE_mesh_loops_for_write(output->mesh); + return output; } static void dualcon_add_vert(void *output_v, const float co[3]) { DualConOutput *output = output_v; - Mesh *mesh = output->mesh; - BLI_assert(output->curvert < mesh->totvert); + BLI_assert(output->curvert < output->mesh->totvert); - copy_v3_v3(mesh->mvert[output->curvert].co, co); + copy_v3_v3(output->verts[output->curvert].co, co); output->curvert++; } @@ -111,14 +117,13 @@ static void dualcon_add_quad(void *output_v, const int vert_indices[4]) { DualConOutput *output = output_v; Mesh *mesh = output->mesh; - MLoop *mloop; - MPoly *cur_poly; int i; BLI_assert(output->curface < mesh->totpoly); + UNUSED_VARS_NDEBUG(mesh); - mloop = mesh->mloop; - cur_poly = &mesh->mpoly[output->curface]; + MLoop *mloop = output->loops; + MPoly *cur_poly = &output->polys[output->curface]; cur_poly->loopstart = output->curface * 4; cur_poly->totloop = 4; @@ -195,7 +200,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) } if (rmd->flag & MOD_REMESH_SMOOTH_SHADING) { - MPoly *mpoly = result->mpoly; + MPoly *mpoly = BKE_mesh_polys_for_write(result); int i, totpoly = result->totpoly; /* Apply smooth shading to output faces */ diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 6095be48f8f..71ffe91f364 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -41,6 +41,8 @@ #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" +#include "BLI_strict_flags.h" + static void initData(ModifierData *md) { ScrewModifierData *ltmd = (ScrewModifierData *)md; @@ -50,8 +52,6 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(ltmd, DNA_struct_default_get(ScrewModifierData), modifier); } -#include "BLI_strict_flags.h" - /** Used for gathering edge connectivity. */ typedef struct ScrewVertConnect { /** Distance from the center axis. */ @@ -182,7 +182,7 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result, static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) { - Mesh *mesh = meshData; + const Mesh *mesh = meshData; Mesh *result; ScrewModifierData *ltmd = (ScrewModifierData *)md; const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER) != 0; @@ -241,11 +241,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * uint edge_offset; - MPoly *mpoly_orig, *mpoly_new, *mp_new; - MLoop *mloop_orig, *mloop_new, *ml_new; - MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new; - MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base; - + MPoly *mp_new; + MLoop *ml_new; + MEdge *med_new, *med_new_firstloop; + MVert *mv_new, *mv_new_base; + const MVert *mv_orig; Object *ob_axis = ltmd->ob_axis; ScrewVertConnect *vc, *vc_tmp, *vert_connect = NULL; @@ -388,17 +388,18 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = BKE_mesh_new_nomain_from_template( mesh, (int)maxVerts, (int)maxEdges, 0, (int)maxPolys * 4, (int)maxPolys); - /* copy verts from mesh */ - mvert_orig = mesh->mvert; - medge_orig = mesh->medge; + const MVert *mvert_orig = BKE_mesh_verts(mesh); + const MEdge *medge_orig = BKE_mesh_edges(mesh); + const MPoly *mpoly_orig = BKE_mesh_polys(mesh); + const MLoop *mloop_orig = BKE_mesh_loops(mesh); - mvert_new = result->mvert; - mpoly_new = result->mpoly; - mloop_new = result->mloop; - medge_new = result->medge; + MVert *mvert_new = BKE_mesh_verts_for_write(result); + MEdge *medge_new = BKE_mesh_edges_for_write(result); + MPoly *mpoly_new = BKE_mesh_polys_for_write(result); + MLoop *mloop_new = BKE_mesh_loops_for_write(result); if (!CustomData_has_layer(&result->pdata, CD_ORIGINDEX)) { - CustomData_add_layer(&result->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, (int)maxPolys); + CustomData_add_layer(&result->pdata, CD_ORIGINDEX, CD_SET_DEFAULT, NULL, (int)maxPolys); } int *origindex = CustomData_get_layer(&result->pdata, CD_ORIGINDEX); @@ -438,12 +439,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BLI_bitmap *vert_tag = BLI_BITMAP_NEW(totvert, __func__); /* Copy the first set of edges */ - med_orig = medge_orig; + const MEdge *med_orig = medge_orig; med_new = medge_new; for (i = 0; i < totedge; i++, med_orig++, med_new++) { med_new->v1 = med_orig->v1; med_new->v2 = med_orig->v2; - med_new->crease = med_orig->crease; med_new->flag = med_orig->flag & ~ME_LOOSEEDGE; /* Tag #MVert as not loose. */ @@ -453,10 +453,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* build polygon -> edge map */ if (totpoly) { - MPoly *mp_orig; + const MPoly *mp_orig; - mpoly_orig = mesh->mpoly; - mloop_orig = mesh->mloop; edge_poly_map = MEM_malloc_arrayN(totedge, sizeof(*edge_poly_map), __func__); memset(edge_poly_map, 0xff, sizeof(*edge_poly_map) * totedge); @@ -467,7 +465,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * uint loopstart = (uint)mp_orig->loopstart; uint loopend = loopstart + (uint)mp_orig->totloop; - MLoop *ml_orig = &mloop_orig[loopstart]; + const MLoop *ml_orig = &mloop_orig[loopstart]; uint k; for (k = loopstart; k < loopend; k++, ml_orig++) { edge_poly_map[ml_orig->e] = i; @@ -947,6 +945,9 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* more of an offset in this case */ edge_offset = totedge + (totvert * (step_tot - (close ? 0 : 1))); + const int *src_material_index = BKE_mesh_material_indices(mesh); + int *dst_material_index = BKE_mesh_material_indices_for_write(result); + for (i = 0; i < totedge; i++, med_new_firstloop++) { const uint step_last = step_tot - (close ? 1 : 2); const uint mpoly_index_orig = totpoly ? edge_poly_map[i] : UINT_MAX; @@ -959,14 +960,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * }; const bool has_mloop_orig = mloop_index_orig[0] != UINT_MAX; - short mat_nr; + int mat_nr; /* for each edge, make a cylinder of quads */ i1 = med_new_firstloop->v1; i2 = med_new_firstloop->v2; if (has_mpoly_orig) { - mat_nr = mpoly_orig[mpoly_index_orig].mat_nr; + mat_nr = src_material_index == NULL ? 0 : src_material_index[mpoly_index_orig]; } else { mat_nr = 0; @@ -992,8 +993,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } else { origindex[mpoly_index] = ORIGINDEX_NONE; + dst_material_index[mpoly_index] = mat_nr; mp_new->flag = mpoly_flag; - mp_new->mat_nr = mat_nr; } mp_new->loopstart = mpoly_index * 4; mp_new->totloop = 4; @@ -1062,7 +1063,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * med_new->v1 = i1; med_new->v2 = i2; med_new->flag = med_new_firstloop->flag; - med_new->crease = med_new_firstloop->crease; med_new++; } i1 += totvert; @@ -1090,7 +1090,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * med_new->v1 = i1; med_new->v2 = i2; med_new->flag = med_new_firstloop->flag & ~ME_LOOSEEDGE; - med_new->crease = med_new_firstloop->crease; med_new++; } diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index 56dd1fc50f8..3649a108ed4 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -49,11 +49,11 @@ static void deformMatrices(ModifierData *md, { Key *key = BKE_key_from_object(ctx->object); KeyBlock *kb = BKE_keyblock_from_object(ctx->object); - float scale[3][3]; (void)vertexCos; /* unused */ if (kb && kb->totelem == verts_num && kb != key->refkey) { + float scale[3][3]; int a; if (ctx->object->shapeflag & OB_SHAPE_LOCK) { @@ -95,15 +95,14 @@ static void deformMatricesEM(ModifierData *UNUSED(md), { Key *key = BKE_key_from_object(ctx->object); KeyBlock *kb = BKE_keyblock_from_object(ctx->object); - float scale[3][3]; (void)vertexCos; /* unused */ if (kb && kb->totelem == verts_num && kb != key->refkey) { - int a; + float scale[3][3]; scale_m3_fl(scale, kb->curval); - for (a = 0; a < verts_num; a++) { + for (int a = 0; a < verts_num; a++) { copy_m3_m3(defMats[a], scale); } } diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index 4a927d92956..df8b9d53a2f 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -48,9 +48,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(ShrinkwrapModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; @@ -111,7 +109,7 @@ static void deformVerts(ModifierData *md, mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false); } - struct MDeformVert *dvert = NULL; + const MDeformVert *dvert = NULL; int defgrp_index = -1; MOD_get_vgroup(ctx->object, mesh_src, swmd->vgroup_name, &dvert, &defgrp_index); @@ -143,7 +141,7 @@ static void deformVertsEM(ModifierData *md, BKE_mesh_wrapper_ensure_mdata(mesh_src); } - struct MDeformVert *dvert = NULL; + const MDeformVert *dvert = NULL; int defgrp_index = -1; if (swmd->vgroup_name[0] != '\0') { MOD_get_vgroup(ctx->object, mesh_src, swmd->vgroup_name, &dvert, &defgrp_index); diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index 1fc4f11bc66..0de89850bc9 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -294,7 +294,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, float smd_limit[2], smd_factor; SpaceTransform *transf = NULL, tmp_transf; int vgroup; - MDeformVert *dvert; + const MDeformVert *dvert; /* This is historically the lock axis, _not_ the deform axis as the name would imply */ const int deform_axis = smd->deform_axis; @@ -414,9 +414,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SimpleDeformModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 84795cdb2d9..b01bcec0bc1 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -889,9 +889,9 @@ static Mesh *subdivide_base(const Mesh *orig) float radrat; const MVertSkin *orignode = CustomData_get_layer(&orig->vdata, CD_MVERT_SKIN); - const MVert *origvert = orig->mvert; - const MEdge *origedge = orig->medge; - const MDeformVert *origdvert = orig->dvert; + const MVert *origvert = BKE_mesh_verts(orig); + const MEdge *origedge = BKE_mesh_edges(orig); + const MDeformVert *origdvert = BKE_mesh_deform_verts(orig); int orig_vert_num = orig->totvert; int orig_edge_num = orig->totedge; @@ -916,10 +916,13 @@ static Mesh *subdivide_base(const Mesh *orig) Mesh *result = BKE_mesh_new_nomain_from_template( orig, orig_vert_num + subd_num, orig_edge_num + subd_num, 0, 0, 0); - MVert *outvert = result->mvert; - MEdge *outedge = result->medge; + MVert *outvert = BKE_mesh_verts_for_write(result); + MEdge *outedge = BKE_mesh_edges_for_write(result); MVertSkin *outnode = CustomData_get_layer(&result->vdata, CD_MVERT_SKIN); - MDeformVert *outdvert = result->dvert; + MDeformVert *outdvert = NULL; + if (origdvert) { + outdvert = BKE_mesh_deform_verts_for_write(result); + } /* Copy original vertex data */ CustomData_copy_data(&orig->vdata, &result->vdata, 0, 0, orig_vert_num); @@ -1731,7 +1734,7 @@ static void skin_smooth_hulls(BMesh *bm, } } - /* Add temporary shapekey layer to store original coordinates */ + /* Add temporary shape-key layer to store original coordinates. */ BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY); skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -1888,7 +1891,7 @@ static void skin_set_orig_indices(Mesh *mesh) int *orig, totpoly; totpoly = mesh->totpoly; - orig = CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, totpoly); + orig = CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_CONSTRUCT, NULL, totpoly); copy_vn_i(orig, totpoly, ORIGINDEX_NONE); } @@ -1907,17 +1910,17 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_ SkinNode *skin_nodes; MeshElemMap *emap; int *emapmem; - MVert *mvert; - MEdge *medge; - MDeformVert *dvert; + const MVert *mvert; + const MEdge *medge; + const MDeformVert *dvert; int verts_num, edges_num; bool has_valid_root = false; nodes = CustomData_get_layer(&origmesh->vdata, CD_MVERT_SKIN); - mvert = origmesh->mvert; - dvert = origmesh->dvert; - medge = origmesh->medge; + mvert = BKE_mesh_verts(origmesh); + dvert = BKE_mesh_deform_verts(origmesh); + medge = BKE_mesh_edges(origmesh); verts_num = origmesh->totvert; edges_num = origmesh->totedge; @@ -2004,9 +2007,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return result; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *UNUSED(md), - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *UNUSED(md), CustomData_MeshMasks *r_cddata_masks) { r_cddata_masks->vmask |= CD_MASK_MVERT_SKIN | CD_MASK_MDEFORMVERT; } diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 6dd3d491283..72fc945675c 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -63,9 +63,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return false; } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { SmoothModifierData *smd = (SmoothModifierData *)md; @@ -99,10 +97,10 @@ static void smoothModifier_do( const float fac_orig = 1.0f - fac_new; const bool invert_vgroup = (smd->flag & MOD_SMOOTH_INVERT_VGROUP) != 0; - MEdge *medges = mesh->medge; + const MEdge *medges = BKE_mesh_edges(mesh); const int edges_num = mesh->totedge; - MDeformVert *dvert; + const MDeformVert *dvert; int defgrp_index; MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index); @@ -128,7 +126,7 @@ static void smoothModifier_do( const short flag = smd->flag; if (dvert) { - MDeformVert *dv = dvert; + const MDeformVert *dv = dvert; for (int i = 0; i < verts_num; i++, dv++) { float *vco_orig = vertexCos[i]; if (accumulated_vecs_count[i] > 0) { diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 3e2d590c928..1c7369d9158 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -53,9 +53,7 @@ static void initData(ModifierData *md) # pragma GCC diagnostic error "-Wsign-conversion" #endif -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { SolidifyModifierData *smd = (SolidifyModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index 47277577d3e..f1758b91a91 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -61,27 +61,16 @@ static void mesh_calc_hq_normal(Mesh *mesh, #endif ) { - int i, verts_num, edges_num, polys_num; - MPoly *mpoly, *mp; - MLoop *mloop, *ml; - MEdge *medge, *ed; + int i; - verts_num = mesh->totvert; - edges_num = mesh->totedge; - polys_num = mesh->totpoly; - mpoly = mesh->mpoly; - medge = mesh->medge; - mloop = mesh->mloop; + const int verts_num = mesh->totvert; + const int edges_num = mesh->totedge; + const int polys_num = mesh->totpoly; + const MPoly *mpoly = BKE_mesh_polys(mesh); + const MLoop *mloop = BKE_mesh_loops(mesh); + const MEdge *medge = BKE_mesh_edges(mesh); - /* we don't want to overwrite any referenced layers */ - - /* Doesn't work here! */ -#if 0 - mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, verts_num); - cddm->mvert = mv; -#endif - - mp = mpoly; + const MPoly *mp = mpoly; { EdgeFaceRef *edge_ref_array = MEM_calloc_arrayN( @@ -93,7 +82,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, for (i = 0; i < polys_num; i++, mp++) { int j; - ml = mloop + mp->loopstart; + const MLoop *ml = mloop + mp->loopstart; for (j = 0; j < mp->totloop; j++, ml++) { /* --- add edge ref to face --- */ @@ -116,6 +105,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, } } + const MEdge *ed; for (i = 0, ed = medge, edge_ref = edge_ref_array; i < edges_num; i++, ed++, edge_ref++) { /* Get the edge vert indices, and edge value (the face indices that use it) */ @@ -166,10 +156,6 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex Mesh *result; const SolidifyModifierData *smd = (SolidifyModifierData *)md; - MVert *mv, *mvert, *orig_mvert; - MEdge *ed, *medge, *orig_medge; - MLoop *ml, *mloop, *orig_mloop; - MPoly *mp, *mpoly, *orig_mpoly; const uint verts_num = (uint)mesh->totvert; const uint edges_num = (uint)mesh->totedge; const uint polys_num = (uint)mesh->totpoly; @@ -216,7 +202,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex const bool do_shell = !(do_rim && (smd->flag & MOD_SOLIDIFY_NOSHELL) != 0); /* weights */ - MDeformVert *dvert; + const MDeformVert *dvert; const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; const int shell_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->shell_defgrp_name); @@ -229,10 +215,10 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex MOD_get_vgroup(ctx->object, mesh, smd->defgrp_name, &dvert, &defgrp_index); - orig_mvert = mesh->mvert; - orig_medge = mesh->medge; - orig_mloop = mesh->mloop; - orig_mpoly = mesh->mpoly; + const MVert *orig_mvert = BKE_mesh_verts(mesh); + const MEdge *orig_medge = BKE_mesh_edges(mesh); + const MPoly *orig_mpoly = BKE_mesh_polys(mesh); + const MLoop *orig_mloop = BKE_mesh_loops(mesh); if (need_poly_normals) { /* calculate only face normals */ @@ -262,16 +248,17 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex copy_vn_i(edge_users, edges_num, INVALID_UNUSED); #endif + const MEdge *ed; for (eidx = 0, ed = orig_medge; eidx < edges_num; eidx++, ed++) { edge_users[eidx] = INVALID_UNUSED; } + const MPoly *mp; for (i = 0, mp = orig_mpoly; i < polys_num; i++, mp++) { - MLoop *ml_prev; int j; - ml = orig_mloop + mp->loopstart; - ml_prev = ml + (mp->totloop - 1); + const MLoop *ml = orig_mloop + mp->loopstart; + const MLoop *ml_prev = ml + (mp->totloop - 1); for (j = 0; j < mp->totloop; j++, ml++) { /* add edge user */ @@ -348,15 +335,10 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex (int)((loops_num * stride) + newLoops), (int)((polys_num * stride) + newPolys)); - mpoly = result->mpoly; - mloop = result->mloop; - medge = result->medge; - mvert = result->mvert; - - if (do_bevel_convex) { - /* Make sure bweight is enabled. */ - result->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; - } + MVert *mvert = BKE_mesh_verts_for_write(result); + MEdge *medge = BKE_mesh_edges_for_write(result); + MPoly *mpoly = BKE_mesh_polys_for_write(result); + MLoop *mloop = BKE_mesh_loops_for_write(result); if (do_shell) { CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)verts_num); @@ -405,6 +387,12 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)polys_num); } + float *result_edge_bweight = NULL; + if (do_bevel_convex) { + result_edge_bweight = CustomData_add_layer( + &result->edata, CD_BWEIGHT, CD_SET_DEFAULT, NULL, result->totedge); + } + /* initializes: (i_end, do_shell_align, mv). */ #define INIT_VERT_ARRAY_OFFSETS(test) \ if (((ofs_new >= ofs_orig) == do_flip) == test) { \ @@ -425,12 +413,14 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } \ (void)0 + int *dst_material_index = BKE_mesh_material_indices_for_write(result); + /* flip normals */ if (do_shell) { uint i; - mp = mpoly + polys_num; + MPoly *mp = mpoly + polys_num; for (i = 0; i < mesh->totpoly; i++, mp++) { const int loop_end = mp->totloop - 1; MLoop *ml2; @@ -462,8 +452,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex #endif if (mat_ofs) { - mp->mat_nr += mat_ofs; - CLAMP(mp->mat_nr, 0, mat_nr_max); + dst_material_index[mp - mpoly] += mat_ofs; + CLAMP(dst_material_index[mp - mpoly], 0, mat_nr_max); } e = ml2[0].e; @@ -480,6 +470,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } } + MEdge *ed; for (i = 0, ed = medge + edges_num; i < edges_num; i++, ed++) { ed->v1 += verts_num; ed->v2 += verts_num; @@ -528,15 +519,15 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex edge_user_pairs[eidx][0] = INVALID_UNUSED; edge_user_pairs[eidx][1] = INVALID_UNUSED; } - mp = orig_mpoly; + const MPoly *mp = orig_mpoly; for (uint i = 0; i < polys_num; i++, mp++) { - ml = orig_mloop + mp->loopstart; - MLoop *ml_prev = ml + (mp->totloop - 1); + const MLoop *ml = orig_mloop + mp->loopstart; + const MLoop *ml_prev = ml + (mp->totloop - 1); for (uint j = 0; j < mp->totloop; j++, ml++) { /* add edge user */ eidx = ml_prev->e; - ed = orig_medge + eidx; + const MEdge *ed = orig_medge + eidx; BLI_assert(ELEM(ml_prev->v, ed->v1, ed->v2) && ELEM(ml->v, ed->v1, ed->v2)); char flip = (char)((ml_prev->v > ml->v) == (ed->v1 < ed->v2)); if (edge_user_pairs[eidx][flip] == INVALID_UNUSED) { @@ -549,7 +540,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex ml_prev = ml; } } - ed = orig_medge; + const MEdge *ed = orig_medge; float e[3]; for (uint i = 0; i < edges_num; i++, ed++) { if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) && @@ -580,12 +571,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex ofs_new_vgroup = ofs_new; + MVert *mv; INIT_VERT_ARRAY_OFFSETS(false); for (i_orig = 0; i_orig < i_end; i_orig++, mv++) { const uint i = do_shell_align ? i_orig : new_vert_arr[i_orig]; if (dvert) { - MDeformVert *dv = &dvert[i]; + const MDeformVert *dv = &dvert[i]; if (defgrp_invert) { ofs_new_vgroup = 1.0f - BKE_defvert_find_weight(dv, defgrp_index); } @@ -631,12 +623,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex ofs_new_vgroup = ofs_orig; /* as above but swapped */ + MVert *mv; INIT_VERT_ARRAY_OFFSETS(true); for (i_orig = 0; i_orig < i_end; i_orig++, mv++) { const uint i = do_shell_align ? i_orig : new_vert_arr[i_orig]; if (dvert) { - MDeformVert *dv = &dvert[i]; + const MDeformVert *dv = &dvert[i]; if (defgrp_invert) { ofs_new_vgroup = 1.0f - BKE_defvert_find_weight(dv, defgrp_index); } @@ -679,20 +672,18 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex for (uint i = 0; i < edges_num; i++) { if (edge_users[i] == INVALID_PAIR) { float angle = edge_angs[i]; - medge[i].bweight = (char)clamp_i( - (int)medge[i].bweight + (int)((angle < M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : - clamp_f(bevel_convex, -1.0f, 0.0f)) * - 255), - 0, - 255); + result_edge_bweight[i] = clamp_f(result_edge_bweight[i] + + (angle < M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : + clamp_f(bevel_convex, -1.0f, 0.0f)), + 0.0f, + 1.0f); if (do_shell) { - medge[i + edges_num].bweight = (char)clamp_i( - (int)medge[i + edges_num].bweight + - (int)((angle > M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : - clamp_f(bevel_convex, -1.0f, 0.0f)) * - 255), + result_edge_bweight[i + edges_num] = clamp_f( + result_edge_bweight[i + edges_num] + (angle > M_PI ? + clamp_f(bevel_convex, 0.0f, 1.0f) : + clamp_f(bevel_convex, -1.0f, 0.0f)), 0, - 255); + 1.0f); } } } @@ -722,11 +713,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (vert_nors == NULL) { vert_nors = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "mod_solid_vno"); + const MVert *mv; for (i = 0, mv = mvert; i < verts_num; i++, mv++) { copy_v3_v3(vert_nors[i], mesh_vert_normals[i]); } } + const MPoly *mp; for (i = 0, mp = mpoly; i < polys_num; i++, mp++) { /* #BKE_mesh_calc_poly_angles logic is inlined here */ float nor_prev[3]; @@ -735,7 +728,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex int i_curr = mp->totloop - 1; int i_next = 0; - ml = &mloop[mp->loopstart]; + const MLoop *ml = &mloop[mp->loopstart]; sub_v3_v3v3(nor_prev, mvert[ml[i_curr - 1].v].co, mvert[ml[i_curr].v].co); normalize_v3(nor_prev); @@ -779,7 +772,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* vertex group support */ if (dvert) { - MDeformVert *dv = dvert; + const MDeformVert *dv = dvert; float scalar; if (defgrp_invert) { @@ -822,13 +815,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex edge_user_pairs[eidx][1] = INVALID_UNUSED; } for (i = 0, mp = orig_mpoly; i < polys_num; i++, mp++) { - ml = orig_mloop + mp->loopstart; - MLoop *ml_prev = ml + (mp->totloop - 1); + const MLoop *ml = orig_mloop + mp->loopstart; + const MLoop *ml_prev = ml + (mp->totloop - 1); for (int j = 0; j < mp->totloop; j++, ml++) { /* add edge user */ eidx = ml_prev->e; - ed = orig_medge + eidx; + const MEdge *ed = orig_medge + eidx; BLI_assert(ELEM(ml_prev->v, ed->v1, ed->v2) && ELEM(ml->v, ed->v1, ed->v2)); char flip = (char)((ml_prev->v > ml->v) == (ed->v1 < ed->v2)); if (edge_user_pairs[eidx][flip] == INVALID_UNUSED) { @@ -841,7 +834,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex ml_prev = ml; } } - ed = orig_medge; + const MEdge *ed = orig_medge; float e[3]; for (i = 0; i < edges_num; i++, ed++) { if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) && @@ -906,20 +899,17 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex for (i = 0; i < edges_num; i++) { if (edge_users[i] == INVALID_PAIR) { float angle = edge_angs[i]; - medge[i].bweight = (char)clamp_i( - (int)medge[i].bweight + (int)((angle < M_PI ? clamp_f(bevel_convex, 0, 1) : - clamp_f(bevel_convex, -1, 0)) * - 255), - 0, - 255); + result_edge_bweight[i] = clamp_f(result_edge_bweight[i] + + (angle < M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : + clamp_f(bevel_convex, -1.0f, 0.0f)), + 0.0f, + 1.0f); if (do_shell) { - medge[i + edges_num].bweight = (char)clamp_i( - (int)medge[i + edges_num].bweight + - (int)((angle > M_PI ? clamp_f(bevel_convex, 0, 1) : - clamp_f(bevel_convex, -1, 0)) * - 255), - 0, - 255); + result_edge_bweight[i + edges_num] = clamp_f( + result_edge_bweight[i + edges_num] + + (angle > M_PI ? clamp_f(bevel_convex, 0, 1) : clamp_f(bevel_convex, -1, 0)), + 0.0f, + 1.0f); } } } @@ -936,6 +926,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex uint i_orig, i_end; bool do_shell_align; + MVert *mv; INIT_VERT_ARRAY_OFFSETS(false); for (i_orig = 0; i_orig < i_end; i_orig++, mv++) { @@ -952,6 +943,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex bool do_shell_align; /* same as above but swapped, intentional use of 'ofs_new' */ + MVert *mv; INIT_VERT_ARRAY_OFFSETS(true); for (i_orig = 0; i_orig < i_end; i_orig++, mv++) { @@ -981,7 +973,6 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex else if (do_shell) { uint i; /* flip vertex normals for copied verts */ - mv = mvert + verts_num; for (i = 0; i < verts_num; i++) { negate_v3((float *)mesh_vert_normals[i]); } @@ -989,22 +980,15 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* Add vertex weights for rim and shell vgroups. */ if (shell_defgrp_index != -1 || rim_defgrp_index != -1) { - dvert = CustomData_duplicate_referenced_layer(&result->vdata, CD_MDEFORMVERT, result->totvert); - /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ - if (dvert == NULL) { - /* Add a valid data layer! */ - dvert = CustomData_add_layer( - &result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, result->totvert); - } + MDeformVert *dst_dvert = BKE_mesh_deform_verts_for_write(result); + /* Ultimate security check. */ - if (dvert != NULL) { - result->dvert = dvert; + if (dst_dvert != NULL) { 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) + verts_num], + BKE_defvert_ensure_index(&dst_dvert[new_vert_arr[i]], rim_defgrp_index)->weight = 1.0f; + BKE_defvert_ensure_index(&dst_dvert[(do_shell ? new_vert_arr[i] : i) + verts_num], rim_defgrp_index) ->weight = 1.0f; } @@ -1012,7 +996,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (shell_defgrp_index != -1) { for (uint i = verts_num; i < result->totvert; i++) { - BKE_defvert_ensure_index(&result->dvert[i], shell_defgrp_index)->weight = 1.0f; + BKE_defvert_ensure_index(&dst_dvert[i], shell_defgrp_index)->weight = 1.0f; } } } @@ -1040,22 +1024,23 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex NULL; float nor[3]; #endif - const uchar crease_rim = smd->crease_rim * 255.0f; - const uchar crease_outer = smd->crease_outer * 255.0f; - const uchar crease_inner = smd->crease_inner * 255.0f; + const float crease_rim = smd->crease_rim; + const float crease_outer = smd->crease_outer; + const float crease_inner = smd->crease_inner; int *origindex_edge; int *orig_ed; uint j; + float *result_edge_crease = NULL; if (crease_rim || crease_outer || crease_inner) { - result->cd_flag |= ME_CDFLAG_EDGE_CREASE; + result_edge_crease = (float *)CustomData_get_layer(&result->edata, CD_CREASE); } /* add faces & edges */ origindex_edge = CustomData_get_layer(&result->edata, CD_ORIGINDEX); orig_ed = (origindex_edge) ? &origindex_edge[(edges_num * stride) + newEdges] : NULL; - ed = &medge[(edges_num * stride) + newEdges]; /* start after copied edges */ + MEdge *ed = &medge[(edges_num * stride) + newEdges]; /* start after copied edges */ for (i = 0; i < rimVerts; i++, ed++) { ed->v1 = new_vert_arr[i]; ed->v2 = (do_shell ? new_vert_arr[i] : i) + verts_num; @@ -1067,13 +1052,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } if (crease_rim) { - ed->crease = crease_rim; + result_edge_crease[ed - medge] = crease_rim; } } /* faces */ - mp = mpoly + (polys_num * stride); - ml = mloop + (loops_num * stride); + MPoly *mp = mpoly + (polys_num * stride); + MLoop *ml = mloop + (loops_num * stride); j = 0; for (i = 0; i < newPolys; i++, mp++) { uint eidx = new_edge_arr[i]; @@ -1151,21 +1136,21 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex /* use the next material index if option enabled */ if (mat_ofs_rim) { - mp->mat_nr += mat_ofs_rim; - CLAMP(mp->mat_nr, 0, mat_nr_max); + dst_material_index[mp - mpoly] += mat_ofs_rim; + CLAMP(dst_material_index[mp - mpoly], 0, mat_nr_max); } if (crease_outer) { /* crease += crease_outer; without wrapping */ - char *cr = &(ed->crease); - int tcr = *cr + crease_outer; - *cr = tcr > 255 ? 255 : tcr; + float *cr = &(result_edge_crease[ed - medge]); + float tcr = *cr + crease_outer; + *cr = tcr > 1.0f ? 1.0f : tcr; } if (crease_inner) { /* crease += crease_inner; without wrapping */ - char *cr = &(medge[edges_num + (do_shell ? eidx : i)].crease); - int tcr = *cr + crease_inner; - *cr = tcr > 255 ? 255 : tcr; + float *cr = &(result_edge_crease[edges_num + (do_shell ? eidx : i)]); + float tcr = *cr + crease_inner; + *cr = tcr > 1.0f ? 1.0f : tcr; } #ifdef SOLIDIFY_SIDE_NORMALS diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index 8a5b600974c..c41a9e8f828 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -76,7 +76,7 @@ static float clamp_nonzero(const float value, const float epsilon) /* Data structures for manifold solidify. */ typedef struct NewFaceRef { - MPoly *face; + const MPoly *face; uint index; bool reversed; struct NewEdgeRef **link_edges; @@ -137,10 +137,6 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, Mesh *result; const SolidifyModifierData *smd = (SolidifyModifierData *)md; - MVert *mv, *mvert, *orig_mvert; - MEdge *ed, *medge, *orig_medge; - MLoop *ml, *mloop, *orig_mloop; - MPoly *mp, *mpoly, *orig_mpoly; const uint verts_num = (uint)mesh->totvert; const uint edges_num = (uint)mesh->totedge; const uint polys_num = (uint)mesh->totpoly; @@ -178,7 +174,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const float bevel_convex = smd->bevel_convex; - MDeformVert *dvert; + const MDeformVert *dvert; const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; const int shell_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->shell_defgrp_name); @@ -188,10 +184,15 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const bool do_flat_faces = dvert && (smd->flag & MOD_SOLIDIFY_NONMANIFOLD_FLAT_FACES); - orig_mvert = mesh->mvert; - orig_medge = mesh->medge; - orig_mloop = mesh->mloop; - orig_mpoly = mesh->mpoly; + const MVert *orig_mvert = BKE_mesh_verts(mesh); + const MEdge *orig_medge = BKE_mesh_edges(mesh); + const MPoly *orig_mpoly = BKE_mesh_polys(mesh); + const MLoop *orig_mloop = BKE_mesh_loops(mesh); + + /* These might be null. */ + const float *orig_vert_bweight = CustomData_get_layer(&mesh->vdata, CD_BWEIGHT); + const float *orig_edge_bweight = CustomData_get_layer(&mesh->edata, CD_BWEIGHT); + const float *orig_edge_crease = CustomData_get_layer(&mesh->edata, CD_CREASE); uint new_verts_num = 0; uint new_edges_num = 0; @@ -213,11 +214,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint largest_ngon = 3; /* Calculate face to #NewFaceRef map. */ { - mp = orig_mpoly; + const MPoly *mp = orig_mpoly; for (uint i = 0; i < polys_num; i++, mp++) { /* Make normals for faces without area (should really be avoided though). */ if (len_squared_v3(poly_nors[i]) < 0.5f) { - MEdge *e = orig_medge + orig_mloop[mp->loopstart].e; + const MEdge *e = orig_medge + orig_mloop[mp->loopstart].e; float edgedir[3]; sub_v3_v3v3(edgedir, orig_mvert[e->v2].co, orig_mvert[e->v1].co); if (fabsf(edgedir[2]) < fabsf(edgedir[1])) { @@ -254,9 +255,9 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, edges_num, sizeof(*edge_adj_faces_len), "edge_adj_faces_len in solidify"); /* Count for each edge how many faces it has adjacent. */ { - mp = orig_mpoly; + const MPoly *mp = orig_mpoly; for (uint i = 0; i < polys_num; i++, mp++) { - ml = orig_mloop + mp->loopstart; + const MLoop *ml = orig_mloop + mp->loopstart; for (uint j = 0; j < mp->totloop; j++, ml++) { edge_adj_faces_len[ml->e]++; } @@ -304,9 +305,9 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Create link_faces for edges. */ { - mp = orig_mpoly; + const MPoly *mp = orig_mpoly; for (uint i = 0; i < polys_num; i++, mp++) { - ml = orig_mloop + mp->loopstart; + const MLoop *ml = orig_mloop + mp->loopstart; for (uint j = 0; j < mp->totloop; j++, ml++) { const uint edge = ml->e; const bool reversed = orig_medge[edge].v2 != ml->v; @@ -353,7 +354,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint *combined_verts = MEM_calloc_arrayN( verts_num, sizeof(*combined_verts), "combined_verts in solidify"); - ed = orig_medge; + const MEdge *ed = orig_medge; for (uint i = 0; i < edges_num; i++, ed++) { if (edge_adj_faces_len[i] > 0) { uint v1 = vm[ed->v1]; @@ -377,7 +378,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, 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]; + const MPoly *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++) { @@ -473,7 +474,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Create vert_adj_edges for verts. */ { - ed = orig_medge; + const MEdge *ed = orig_medge; for (uint i = 0; i < edges_num; i++, ed++) { if (edge_adj_faces_len[i] > 0) { const uint vs[2] = {vm[ed->v1], vm[ed->v2]}; @@ -592,7 +593,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Filter duplicate polys. */ { - ed = orig_medge; + const MEdge *ed = orig_medge; /* Iterate over edges and only check the faces around an edge for duplicates * (performance optimization). */ for (uint i = 0; i < edges_num; i++, ed++) { @@ -615,7 +616,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Find first face first loop vert in second face loops. */ const int k_loopstart = orig_mpoly[adj_faces->faces[k]].loopstart; int l; - ml = orig_mloop + k_loopstart; + const MLoop *ml = orig_mloop + k_loopstart; for (l = 0; l < totloop && vm[ml->v] != j_first_v; l++, ml++) { /* Pass. */ } @@ -703,7 +704,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, /* Create #NewEdgeRef array. */ { - ed = orig_medge; + const MEdge *ed = orig_medge; for (uint i = 0; i < edges_num; i++, ed++) { const uint v1 = vm[ed->v1]; const uint v2 = vm[ed->v2]; @@ -848,7 +849,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, new_edges[j] = edge_data; for (uint k = 0; k < 2; k++) { if (faces[k] != NULL) { - ml = orig_mloop + faces[k]->face->loopstart; + const MLoop *ml = orig_mloop + faces[k]->face->loopstart; for (int l = 0; l < faces[k]->face->totloop; l++, ml++) { if (edge_adj_faces[ml->e] == edge_adj_faces[i]) { if (ml->e != i && orig_edge_data_arr[ml->e] == NULL) { @@ -1377,13 +1378,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (do_flat_faces) { face_weight = MEM_malloc_arrayN(polys_num, sizeof(*face_weight), "face_weight in solidify"); - mp = orig_mpoly; + const MPoly *mp = orig_mpoly; for (uint i = 0; i < polys_num; i++, mp++) { float scalar_vgroup = 1.0f; int loopend = mp->loopstart + mp->totloop; - ml = orig_mloop + mp->loopstart; + const MLoop *ml = orig_mloop + mp->loopstart; for (int j = mp->loopstart; j < loopend; j++, ml++) { - MDeformVert *dv = &dvert[ml->v]; + const MDeformVert *dv = &dvert[ml->v]; if (defgrp_invert) { scalar_vgroup = min_ff(1.0f - BKE_defvert_find_weight(dv, defgrp_index), scalar_vgroup); @@ -1397,7 +1398,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } } - mv = orig_mvert; + const MVert *mv = orig_mvert; gs_ptr = orig_vert_groups_arr; for (uint i = 0; i < verts_num; i++, mv++, gs_ptr++) { if (*gs_ptr) { @@ -1655,9 +1656,9 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN) { - MLoop *ml_next = orig_mloop + face->face->loopstart; - ml = ml_next + (face->face->totloop - 1); - MLoop *ml_prev = ml - 1; + const MLoop *ml_next = orig_mloop + face->face->loopstart; + const MLoop *ml = ml_next + (face->face->totloop - 1); + const MLoop *ml_prev = ml - 1; for (int m = 0; m < face->face->totloop && vm[ml->v] != i; m++, ml_next++) { ml_prev = ml; @@ -1766,7 +1767,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, float tmp[3]; int k; for (k = 1; k + 1 < g->edges_len; k++, edge_ptr++) { - MEdge *e = orig_medge + (*edge_ptr)->old_edge; + const MEdge *e = orig_medge + (*edge_ptr)->old_edge; sub_v3_v3v3(tmp, orig_mvert_co[vm[e->v1] == i ? e->v2 : e->v1], orig_mvert_co[i]); add_v3_v3(move_nor, tmp); } @@ -1781,8 +1782,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (!disable_boundary_fix) { /* Constraint normal, nor * constr_nor == 0 after this fix. */ float constr_nor[3]; - MEdge *e0_edge = orig_medge + g->edges[0]->old_edge; - MEdge *e1_edge = orig_medge + g->edges[g->edges_len - 1]->old_edge; + const MEdge *e0_edge = orig_medge + g->edges[0]->old_edge; + const MEdge *e1_edge = orig_medge + g->edges[g->edges_len - 1]->old_edge; float e0[3]; float e1[3]; sub_v3_v3v3(e0, @@ -1831,7 +1832,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, float scalar_vgroup = 1; /* Use vertex group. */ if (dvert && !do_flat_faces) { - MDeformVert *dv = &dvert[i]; + const MDeformVert *dv = &dvert[i]; if (defgrp_invert) { scalar_vgroup = 1.0f - BKE_defvert_find_weight(dv, defgrp_index); } @@ -1961,40 +1962,36 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, (int)(new_loops_num), (int)(new_polys_num)); - mpoly = result->mpoly; - mloop = result->mloop; - medge = result->medge; - mvert = result->mvert; + MVert *mvert = BKE_mesh_verts_for_write(result); + MEdge *medge = BKE_mesh_edges_for_write(result); + MPoly *mpoly = BKE_mesh_polys_for_write(result); + MLoop *mloop = BKE_mesh_loops_for_write(result); int *origindex_edge = CustomData_get_layer(&result->edata, CD_ORIGINDEX); int *origindex_poly = CustomData_get_layer(&result->pdata, CD_ORIGINDEX); - if (bevel_convex != 0.0f || (result->cd_flag & ME_CDFLAG_VERT_BWEIGHT) != 0) { - /* make sure bweight is enabled */ - result->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; + float *result_edge_bweight = CustomData_get_layer(&result->edata, CD_BWEIGHT); + if (bevel_convex != 0.0f || orig_vert_bweight != NULL) { + result_edge_bweight = CustomData_add_layer( + &result->edata, CD_BWEIGHT, CD_SET_DEFAULT, NULL, result->totedge); } /* Checks that result has dvert data. */ + MDeformVert *dst_dvert = NULL; if (shell_defgrp_index != -1 || rim_defgrp_index != -1) { - dvert = CustomData_duplicate_referenced_layer(&result->vdata, CD_MDEFORMVERT, result->totvert); - /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ - if (dvert == NULL) { - /* Add a valid data layer! */ - dvert = CustomData_add_layer( - &result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, result->totvert); - } - result->dvert = dvert; + dst_dvert = BKE_mesh_deform_verts_for_write(result); } /* Get vertex crease layer and ensure edge creases are active if vertex creases are found, since * they will introduce edge creases in the used custom interpolation method. */ const float *vertex_crease = CustomData_get_layer(&mesh->vdata, CD_CREASE); + float *result_edge_crease = NULL; if (vertex_crease) { - result->cd_flag |= ME_CDFLAG_EDGE_CREASE; + result_edge_crease = (float *)CustomData_add_layer( + &result->edata, CD_CREASE, CD_SET_DEFAULT, NULL, result->totedge); /* delete all vertex creases in the result if a rim is used. */ if (do_rim) { CustomData_free_layers(&result->vdata, CD_CREASE, result->totvert); - result->cd_flag &= (char)(~ME_CDFLAG_VERT_CREASE); } } @@ -2009,7 +2006,6 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (g->new_vert != MOD_SOLIDIFY_EMPTY_TAG) { CustomData_copy_data(&mesh->vdata, &result->vdata, (int)i, (int)g->new_vert, 1); copy_v3_v3(mvert[g->new_vert].co, g->co); - mvert[g->new_vert].flag = orig_mvert[i].flag; } } } @@ -2047,18 +2043,22 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, medge[insert].v1 = v1; medge[insert].v2 = v2; medge[insert].flag = orig_medge[(*l)->old_edge].flag | ME_EDGEDRAW | ME_EDGERENDER; - medge[insert].crease = orig_medge[(*l)->old_edge].crease; - medge[insert].bweight = orig_medge[(*l)->old_edge].bweight; + if (result_edge_crease) { + result_edge_crease[insert] = orig_edge_crease ? orig_edge_crease[(*l)->old_edge] : + 0.0f; + } + if (result_edge_bweight) { + result_edge_bweight[insert] = orig_edge_bweight[(*l)->old_edge]; + } if (bevel_convex != 0.0f && (*l)->faces[1] != NULL) { - medge[insert].bweight = (char)clamp_i( - (int)medge[insert].bweight + (int)(((*l)->angle > M_PI + FLT_EPSILON ? - clamp_f(bevel_convex, 0.0f, 1.0f) : - ((*l)->angle < M_PI - FLT_EPSILON ? - clamp_f(bevel_convex, -1.0f, 0.0f) : - 0)) * - 255), - 0, - 255); + result_edge_bweight[insert] = clamp_f( + result_edge_bweight[insert] + + ((*l)->angle > M_PI + FLT_EPSILON ? + clamp_f(bevel_convex, 0.0f, 1.0f) : + ((*l)->angle < M_PI - FLT_EPSILON ? clamp_f(bevel_convex, -1.0f, 0.0f) : + 0)), + 0.0f, + 1.0f); } (*l)->new_edge = insert; } @@ -2108,10 +2108,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } #endif + const int *src_material_index = BKE_mesh_material_indices(mesh); + int *dst_material_index = BKE_mesh_material_indices_for_write(result); + /* Make boundary edges/faces. */ { gs_ptr = orig_vert_groups_arr; - mv = orig_mvert; + const MVert *mv = orig_mvert; for (uint i = 0; i < verts_num; i++, gs_ptr++, mv++) { EdgeGroup *gs = *gs_ptr; if (gs) { @@ -2119,14 +2122,15 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, EdgeGroup *g2 = gs; EdgeGroup *last_g = NULL; EdgeGroup *first_g = NULL; - char mv_crease = vertex_crease ? (char)(vertex_crease[i] * 255.0f) : 0; + float mv_crease = vertex_crease ? vertex_crease[i] : 0.0f; + float mv_bweight = orig_vert_bweight ? orig_vert_bweight[i] : 0.0f; /* Data calculation cache. */ - char max_crease; - char last_max_crease = 0; - char first_max_crease = 0; - char max_bweight; - char last_max_bweight = 0; - char first_max_bweight = 0; + float max_crease; + float last_max_crease = 0.0f; + float first_max_crease = 0.0f; + float max_bweight; + float last_max_bweight = 0.0f; + float first_max_bweight = 0.0f; short flag; short last_flag = 0; short first_flag = 0; @@ -2139,30 +2143,44 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, BLI_assert(g->edges_len >= 2); if (g->edges_len == 2) { - max_crease = min_cc(orig_medge[g->edges[0]->old_edge].crease, - orig_medge[g->edges[1]->old_edge].crease); + if (result_edge_crease) { + if (orig_edge_crease) { + max_crease = min_ff(orig_edge_crease[g->edges[0]->old_edge], + orig_edge_crease[g->edges[1]->old_edge]); + } + else { + max_crease = 0.0f; + } + } } else { for (uint k = 1; k < g->edges_len - 1; k++) { - ed = orig_medge + g->edges[k]->old_edge; - if (ed->crease > max_crease) { - max_crease = ed->crease; + const uint orig_edge_index = g->edges[k]->old_edge; + const MEdge *ed = &orig_medge[orig_edge_index]; + if (result_edge_crease) { + if (orig_edge_crease && orig_edge_crease[orig_edge_index] > max_crease) { + max_crease = orig_edge_crease[orig_edge_index]; + } } if (g->edges[k]->new_edge != MOD_SOLIDIFY_EMPTY_TAG) { - char bweight = medge[g->edges[k]->new_edge].bweight; - if (bweight > max_bweight) { - max_bweight = bweight; + if (result_edge_bweight) { + float bweight = result_edge_bweight[g->edges[k]->new_edge]; + if (bweight > max_bweight) { + max_bweight = bweight; + } } } flag |= ed->flag; } } - const char bweight_open_edge = min_cc( - orig_medge[g->edges[0]->old_edge].bweight, - orig_medge[g->edges[g->edges_len - 1]->old_edge].bweight); + const float bweight_open_edge = + orig_edge_bweight ? + min_ff(orig_edge_bweight[g->edges[0]->old_edge], + orig_edge_bweight[g->edges[g->edges_len - 1]->old_edge]) : + 0.0f; if (bweight_open_edge > 0) { - max_bweight = min_cc(bweight_open_edge, max_bweight); + max_bweight = min_ff(bweight_open_edge, max_bweight); } else { if (bevel_convex < 0.0f) { @@ -2189,9 +2207,15 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, medge[edge_index].v2 = g->new_vert; medge[edge_index].flag = ME_EDGEDRAW | ME_EDGERENDER | ((last_flag | flag) & (ME_SEAM | ME_SHARP)); - medge[edge_index].crease = max_cc(mv_crease, min_cc(last_max_crease, max_crease)); - medge[edge_index++].bweight = max_cc(mv->bweight, - min_cc(last_max_bweight, max_bweight)); + if (result_edge_crease) { + result_edge_crease[edge_index] = max_ff(mv_crease, + min_ff(last_max_crease, max_crease)); + } + if (result_edge_bweight) { + result_edge_bweight[edge_index] = max_ff(mv_bweight, + min_ff(last_max_bweight, max_bweight)); + } + edge_index++; } last_g = g; last_max_crease = max_crease; @@ -2217,14 +2241,19 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, medge[edge_index].v2 = first_g->new_vert; medge[edge_index].flag = ME_EDGEDRAW | ME_EDGERENDER | ((last_flag | first_flag) & (ME_SEAM | ME_SHARP)); - medge[edge_index].crease = max_cc(mv_crease, - min_cc(last_max_crease, first_max_crease)); - medge[edge_index++].bweight = max_cc(mv->bweight, - min_cc(last_max_bweight, first_max_bweight)); + if (result_edge_crease) { + result_edge_crease[edge_index] = max_ff(mv_crease, + min_ff(last_max_crease, first_max_crease)); + } + if (result_edge_bweight) { + result_edge_bweight[edge_index] = max_ff( + mv_bweight, min_ff(last_max_bweight, first_max_bweight)); + } + edge_index++; /* Loop data. */ int *loops = MEM_malloc_arrayN(j, sizeof(*loops), "loops in solidify"); - /* The #mat_nr is from consensus. */ + /* The result material index is from consensus. */ short most_mat_nr = 0; uint most_mat_nr_face = 0; uint most_mat_nr_count = 0; @@ -2235,16 +2264,20 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, for (EdgeGroup *g3 = g2; g3->valid && k < j; g3++) { if ((do_rim && !g3->is_orig_closed) || (do_shell && g3->split)) { /* Check both far ends in terms of faces of an edge group. */ - if (g3->edges[0]->faces[0]->face->mat_nr == l) { + if ((src_material_index ? src_material_index[g3->edges[0]->faces[0]->index] : + 0) == l) { face = g3->edges[0]->faces[0]->index; count++; } NewEdgeRef *le = g3->edges[g3->edges_len - 1]; - if (le->faces[1] && le->faces[1]->face->mat_nr == l) { + if (le->faces[1] && + (src_material_index ? src_material_index[le->faces[1]->index] : 0) == l) { face = le->faces[1]->index; count++; } - else if (!le->faces[1] && le->faces[0]->face->mat_nr == l) { + else if (!le->faces[1] && + (src_material_index ? src_material_index[le->faces[0]->index] : 0) == + l) { face = le->faces[0]->index; count++; } @@ -2264,16 +2297,16 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } mpoly[poly_index].loopstart = (int)loop_index; mpoly[poly_index].totloop = (int)j; - mpoly[poly_index].mat_nr = most_mat_nr + - (g->is_orig_closed || !do_rim ? 0 : mat_ofs_rim); - CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max); + dst_material_index[poly_index] = most_mat_nr + + (g->is_orig_closed || !do_rim ? 0 : mat_ofs_rim); + CLAMP(dst_material_index[poly_index], 0, mat_nr_max); mpoly[poly_index].flag = orig_mpoly[most_mat_nr_face].flag; poly_index++; for (uint k = 0; g2->valid && k < j; g2++) { if ((do_rim && !g2->is_orig_closed) || (do_shell && g2->split)) { - MPoly *face = g2->edges[0]->faces[0]->face; - ml = orig_mloop + face->loopstart; + const MPoly *face = g2->edges[0]->faces[0]->face; + const MLoop *ml = orig_mloop + face->loopstart; for (int l = 0; l < face->totloop; l++, ml++) { if (vm[ml->v] == i) { loops[k] = face->loopstart + l; @@ -2334,19 +2367,21 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, continue; } - MPoly *face = (*new_edges)->faces[0]->face; + const uint orig_face_index = (*new_edges)->faces[0]->index; + const MPoly *face = (*new_edges)->faces[0]->face; CustomData_copy_data( &mesh->pdata, &result->pdata, (int)(*new_edges)->faces[0]->index, (int)poly_index, 1); mpoly[poly_index].loopstart = (int)loop_index; mpoly[poly_index].totloop = 4 - (int)(v1_singularity || v2_singularity); - mpoly[poly_index].mat_nr = face->mat_nr + mat_ofs_rim; - CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max); + dst_material_index[poly_index] = + (src_material_index ? src_material_index[orig_face_index] : 0) + mat_ofs_rim; + CLAMP(dst_material_index[poly_index], 0, mat_nr_max); mpoly[poly_index].flag = face->flag; poly_index++; int loop1 = -1; int loop2 = -1; - ml = orig_mloop + face->loopstart; + const MLoop *ml = orig_mloop + face->loopstart; const uint old_v1 = vm[orig_medge[edge1->old_edge].v1]; const uint old_v2 = vm[orig_medge[edge1->old_edge].v2]; for (uint j = 0; j < face->totloop; j++, ml++) { @@ -2362,7 +2397,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint open_face_edge_index; if (!do_flip) { if (rim_defgrp_index != -1) { - BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v1], rim_defgrp_index) + BKE_defvert_ensure_index(&dst_dvert[medge[edge1->new_edge].v1], rim_defgrp_index) ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1); @@ -2372,7 +2407,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (!v2_singularity) { open_face_edge_index = edge1->link_edge_groups[1]->open_face_edge; if (rim_defgrp_index != -1) { - BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v2], rim_defgrp_index) + BKE_defvert_ensure_index(&dst_dvert[medge[edge1->new_edge].v2], rim_defgrp_index) ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1); @@ -2387,7 +2422,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } if (rim_defgrp_index != -1) { - BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v2], rim_defgrp_index) + BKE_defvert_ensure_index(&dst_dvert[medge[edge2->new_edge].v2], rim_defgrp_index) ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1); @@ -2397,7 +2432,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (!v1_singularity) { open_face_edge_index = edge2->link_edge_groups[0]->open_face_edge; if (rim_defgrp_index != -1) { - BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v1], rim_defgrp_index) + BKE_defvert_ensure_index(&dst_dvert[medge[edge2->new_edge].v1], rim_defgrp_index) ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1); @@ -2415,7 +2450,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (!v1_singularity) { open_face_edge_index = edge1->link_edge_groups[0]->open_face_edge; if (rim_defgrp_index != -1) { - BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v1], rim_defgrp_index) + BKE_defvert_ensure_index(&dst_dvert[medge[edge1->new_edge].v1], rim_defgrp_index) ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1); @@ -2430,7 +2465,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } if (rim_defgrp_index != -1) { - BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v1], rim_defgrp_index) + BKE_defvert_ensure_index(&dst_dvert[medge[edge2->new_edge].v1], rim_defgrp_index) ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1); @@ -2440,7 +2475,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, if (!v2_singularity) { open_face_edge_index = edge2->link_edge_groups[1]->open_face_edge; if (rim_defgrp_index != -1) { - BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v2], rim_defgrp_index) + BKE_defvert_ensure_index(&dst_dvert[medge[edge2->new_edge].v2], rim_defgrp_index) ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1); @@ -2455,7 +2490,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, } if (rim_defgrp_index != -1) { - BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v2], rim_defgrp_index) + BKE_defvert_ensure_index(&dst_dvert[medge[edge1->new_edge].v2], rim_defgrp_index) ->weight = 1.0f; } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1); @@ -2530,14 +2565,16 @@ 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 != do_flip ? mat_ofs : 0); - CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max); + dst_material_index[poly_index] = (src_material_index ? src_material_index[fr->index] : + 0) + + (fr->reversed != do_flip ? mat_ofs : 0); + CLAMP(dst_material_index[poly_index], 0, mat_nr_max); mpoly[poly_index].flag = fr->face->flag; if (fr->reversed != do_flip) { for (int l = (int)k - 1; l >= 0; l--) { if (shell_defgrp_index != -1) { - BKE_defvert_ensure_index(&result->dvert[face_verts[l]], shell_defgrp_index) - ->weight = 1.0f; + BKE_defvert_ensure_index(&dst_dvert[face_verts[l]], shell_defgrp_index)->weight = + 1.0f; } CustomData_copy_data( &mesh->ldata, &result->ldata, (int)face_loops[l], (int)loop_index, 1); diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 8faf2bdbea2..95bbc5ea8cc 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -61,9 +61,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SubsurfModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { SubsurfModifierData *smd = (SubsurfModifierData *)md; if (smd->flags & eSubsurfModifierFlag_UseCustomNormals) { diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index 3e5a577a806..c5e117635b5 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -125,7 +125,6 @@ static void deformVerts(ModifierData *md, if (surmd->mesh) { uint mesh_verts_num = 0, i = 0; int init = 0; - float *vec; MVert *x, *v; BKE_mesh_vert_coords_apply(surmd->mesh, vertexCos); @@ -152,8 +151,9 @@ static void deformVerts(ModifierData *md, } /* convert to global coordinates and calculate velocity */ + MVert *verts = BKE_mesh_verts_for_write(surmd->mesh); for (i = 0, x = surmd->x, v = surmd->v; i < mesh_verts_num; i++, x++, v++) { - vec = surmd->mesh->mvert[i].co; + float *vec = verts[i].co; mul_m4_v3(ctx->object->obmat, vec); if (init) { diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 3c0842a6e93..be864d30445 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -192,9 +192,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SurfaceDeformModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; @@ -1171,10 +1169,10 @@ static bool surfacedeformBind(Object *ob, Mesh *mesh) { BVHTreeFromMesh treeData = {NULL}; - const MVert *mvert = target->mvert; - const MPoly *mpoly = target->mpoly; - const MEdge *medge = target->medge; - const MLoop *mloop = target->mloop; + const MVert *mvert = BKE_mesh_verts(target); + const MPoly *mpoly = BKE_mesh_polys(target); + const MEdge *medge = BKE_mesh_edges(target); + const MLoop *mloop = BKE_mesh_loops(target); uint tedges_num = target->totedge; int adj_result; SDefAdjacencyArray *vert_edges; @@ -1236,7 +1234,7 @@ static bool surfacedeformBind(Object *ob, smd_orig->target_polys_num = target_polys_num; int defgrp_index; - MDeformVert *dvert; + const MDeformVert *dvert; MOD_get_vgroup(ob, mesh, smd_orig->defgrp_name, &dvert, &defgrp_index); const bool invert_vgroup = (smd_orig->flags & MOD_SDEF_INVERT_VGROUP) != 0; const bool sparse_bind = (smd_orig->flags & MOD_SDEF_SPARSE_BIND) != 0; @@ -1505,7 +1503,7 @@ static void surfacedeformModifier_do(ModifierData *md, ob, md, "Target polygons changed from %u to %u", smd->target_polys_num, target_polys_num); return; } - if (smd->target_verts_num != 0 && smd->target_verts_num != target_verts_num) { + if (!ELEM(smd->target_verts_num, 0, target_verts_num)) { if (smd->target_verts_num > target_verts_num) { /* Number of vertices on the target did reduce. There is no usable recovery from this. */ BKE_modifier_set_error(ob, @@ -1538,7 +1536,7 @@ static void surfacedeformModifier_do(ModifierData *md, } int defgrp_index; - MDeformVert *dvert; + const MDeformVert *dvert; MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index); const bool invert_vgroup = (smd->flags & MOD_SDEF_INVERT_VGROUP) != 0; @@ -1602,6 +1600,11 @@ static void deformVertsEM(ModifierData *md, mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, verts_num, false); } + /* TODO(@campbellbarton): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + surfacedeformModifier_do(md, ctx, vertexCos, verts_num, ctx->object, mesh_src); if (!ELEM(mesh_src, NULL, mesh)) { diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index d4faf682cdc..e8280bc9c97 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -82,7 +82,7 @@ static Mesh *triangulate_mesh(Mesh *mesh, } edges_num = result->totedge; - me = result->medge; + me = BKE_mesh_edges_for_write(result); /* force drawing of all edges (seems to be omitted in CDDM_from_bmesh) */ for (i = 0; i < edges_num; i++, me++) { diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index fc17ddffa87..bc1a04d65ce 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -94,9 +94,9 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, /* UVs need special handling, since they come from faces */ if (texmapping == MOD_DISP_MAP_UV) { if (CustomData_has_layer(&mesh->ldata, CD_MLOOPUV)) { - MPoly *mpoly = mesh->mpoly; - MPoly *mp; - MLoop *mloop = mesh->mloop; + const MPoly *mpoly = BKE_mesh_polys(mesh); + const MPoly *mp; + const MLoop *mloop = BKE_mesh_loops(mesh); BLI_bitmap *done = BLI_BITMAP_NEW(verts_num, __func__); const int polys_num = mesh->totpoly; char uvname[MAX_CUSTOMDATA_LAYER_NAME]; @@ -130,7 +130,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd, texmapping = MOD_DISP_MAP_LOCAL; } - MVert *mv = mesh->mvert; + const MVert *mv = BKE_mesh_verts(mesh); for (i = 0; i < verts_num; i++, mv++, r_texco++) { switch (texmapping) { case MOD_DISP_MAP_LOCAL: @@ -224,12 +224,12 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, } void MOD_get_vgroup( - Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index) + Object *ob, struct Mesh *mesh, const char *name, const MDeformVert **dvert, int *defgrp_index) { if (mesh) { *defgrp_index = BKE_id_defgroup_name_index(&mesh->id, name); if (*defgrp_index != -1) { - *dvert = mesh->dvert; + *dvert = BKE_mesh_deform_verts(mesh); } else { *dvert = NULL; diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h index b675c11b370..5f9bd97744b 100644 --- a/source/blender/modifiers/intern/MOD_util.h +++ b/source/blender/modifiers/intern/MOD_util.h @@ -47,7 +47,7 @@ struct Mesh *MOD_deform_mesh_eval_get(struct Object *ob, void MOD_get_vgroup(struct Object *ob, struct Mesh *mesh, const char *name, - struct MDeformVert **dvert, + const struct MDeformVert **dvert, int *defgrp_index); void MOD_depsgraph_update_object_bone_relation(struct DepsNodeHandle *node, diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index a318a82fe64..64e025ea56e 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -52,9 +52,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(umd, DNA_struct_default_get(UVProjectModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *UNUSED(md), - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *UNUSED(md), CustomData_MeshMasks *r_cddata_masks) { /* ask for UV coordinates */ r_cddata_masks->lmask |= CD_MASK_MLOOPUV; @@ -99,8 +97,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, float(*coords)[3], (*co)[3]; MLoopUV *mloop_uv; int i, verts_num, polys_num, loops_num; - MPoly *mpoly, *mp; - MLoop *mloop; + const MPoly *mp; Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; int projectors_num = 0; char uvname[MAX_CUSTOMDATA_LAYER_NAME]; @@ -124,7 +121,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, * (e.g. if a preceding modifier could not preserve it). */ if (!CustomData_has_layer(&mesh->ldata, CD_MLOOPUV)) { CustomData_add_layer_named( - &mesh->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, mesh->totloop, umd->uvlayer_name); + &mesh->ldata, CD_MLOOPUV, CD_SET_DEFAULT, NULL, mesh->totloop, umd->uvlayer_name); } /* make sure we're using an existing layer */ @@ -205,17 +202,17 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, } } - mpoly = mesh->mpoly; - mloop = mesh->mloop; + const MPoly *polys = BKE_mesh_polys(mesh); + const MLoop *loops = BKE_mesh_loops(mesh); /* apply coords as UVs */ - for (i = 0, mp = mpoly; i < polys_num; i++, mp++) { + for (i = 0, mp = polys; i < polys_num; i++, mp++) { if (projectors_num == 1) { if (projectors[0].uci) { uint fidx = mp->totloop - 1; do { uint lidx = mp->loopstart + fidx; - uint vidx = mloop[lidx].v; + uint vidx = loops[lidx].v; BLI_uvproject_from_camera(mloop_uv[lidx].uv, coords[vidx], projectors[0].uci); } while (fidx--); } @@ -224,7 +221,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, uint fidx = mp->totloop - 1; do { uint lidx = mp->loopstart + fidx; - uint vidx = mloop[lidx].v; + uint vidx = loops[lidx].v; copy_v2_v2(mloop_uv[lidx].uv, coords[vidx]); } while (fidx--); } @@ -238,7 +235,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, /* get the untransformed face normal */ BKE_mesh_calc_poly_normal_coords( - mp, mloop + mp->loopstart, (const float(*)[3])coords, face_no); + mp, loops + mp->loopstart, (const float(*)[3])coords, face_no); /* find the projector which the face points at most directly * (projector normal with largest dot product is best) @@ -258,7 +255,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, uint fidx = mp->totloop - 1; do { uint lidx = mp->loopstart + fidx; - uint vidx = mloop[lidx].v; + uint vidx = loops[lidx].v; BLI_uvproject_from_camera(mloop_uv[lidx].uv, coords[vidx], best_projector->uci); } while (fidx--); } @@ -266,7 +263,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, uint fidx = mp->totloop - 1; do { uint lidx = mp->loopstart + fidx; - uint vidx = mloop[lidx].v; + uint vidx = loops[lidx].v; mul_v2_project_m4_v3(mloop_uv[lidx].uv, best_projector->projmat, coords[vidx]); } while (fidx--); } @@ -284,7 +281,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, } } - mesh->runtime.is_original = false; + mesh->runtime.is_original_bmesh = false; return mesh; } diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index 4178f1dd33e..b72a15ef1ec 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -23,6 +23,7 @@ #include "BKE_context.h" #include "BKE_deform.h" #include "BKE_lib_query.h" +#include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_screen.h" @@ -57,9 +58,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(umd, DNA_struct_default_get(UVWarpModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { UVWarpModifierData *umd = (UVWarpModifierData *)md; @@ -81,11 +80,11 @@ static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonen } typedef struct UVWarpData { - MPoly *mpoly; - MLoop *mloop; + const MPoly *mpoly; + const MLoop *mloop; MLoopUV *mloopuv; - MDeformVert *dvert; + const MDeformVert *dvert; int defgrp_index; float (*warp_mat)[4]; @@ -131,10 +130,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * { UVWarpModifierData *umd = (UVWarpModifierData *)md; int polys_num, loops_num; - MPoly *mpoly; - MLoop *mloop; MLoopUV *mloopuv; - MDeformVert *dvert; + const MDeformVert *dvert; int defgrp_index; char uvname[MAX_CUSTOMDATA_LAYER_NAME]; float warp_mat[4][4]; @@ -196,19 +193,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* make sure we're using an existing layer */ CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, umd->uvlayer_name, uvname); + const MPoly *polys = BKE_mesh_polys(mesh); + const MLoop *loops = BKE_mesh_loops(mesh); polys_num = mesh->totpoly; loops_num = mesh->totloop; - mpoly = mesh->mpoly; - mloop = mesh->mloop; /* make sure we are not modifying the original UV map */ mloopuv = CustomData_duplicate_referenced_layer_named( &mesh->ldata, CD_MLOOPUV, uvname, loops_num); MOD_get_vgroup(ctx->object, mesh, umd->vgroup_name, &dvert, &defgrp_index); UVWarpData data = { - .mpoly = mpoly, - .mloop = mloop, + .mpoly = polys, + .mloop = loops, .mloopuv = mloopuv, .dvert = dvert, .defgrp_index = defgrp_index, @@ -220,7 +217,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * settings.use_threading = (polys_num > 1000); BLI_task_parallel_range(0, polys_num, &data, uv_warp_compute, &settings); - mesh->runtime.is_original = false; + mesh->runtime.is_original_bmesh = false; return mesh; } diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc index 215436e4a8d..0065012db97 100644 --- a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc +++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc @@ -51,7 +51,7 @@ 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); + STRNCPY(vmmd->grid_name, "density"); vmmd->adaptivity = 0.0f; vmmd->resolution_mode = VOLUME_TO_MESH_RESOLUTION_MODE_GRID; vmmd->voxel_amount = 32; diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 0968d0646a5..3fafbd97fee 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -70,9 +70,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla twmd->curfalloff = BKE_curvemapping_copy(wmd->curfalloff); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { WarpModifierData *wmd = (WarpModifierData *)md; @@ -196,7 +194,7 @@ static void warpModifier_do(WarpModifierData *wmd, float fac = 1.0f, weight; int i; int defgrp_index; - MDeformVert *dvert, *dv = NULL; + const MDeformVert *dvert, *dv = NULL; const bool invert_vgroup = (wmd->flag & MOD_WARP_INVERT_VGROUP) != 0; float(*tex_co)[3] = NULL; diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index 9647f47c6e0..b49a47b0fb4 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -102,9 +102,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { WaveModifierData *wmd = (WaveModifierData *)md; @@ -134,8 +132,7 @@ static void waveModifier_do(WaveModifierData *md, int verts_num) { WaveModifierData *wmd = (WaveModifierData *)md; - MVert *mvert = NULL; - MDeformVert *dvert; + const MDeformVert *dvert; int defgrp_index; float ctime = DEG_get_ctime(ctx->depsgraph); float minfac = (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow)); @@ -148,7 +145,6 @@ static void waveModifier_do(WaveModifierData *md, const float(*vert_normals)[3] = NULL; if ((wmd->flag & MOD_WAVE_NORM) && (mesh != NULL)) { - mvert = mesh->mvert; vert_normals = BKE_mesh_vertex_normals_ensure(mesh); } @@ -269,7 +265,7 @@ static void waveModifier_do(WaveModifierData *md, /* Apply weight & falloff. */ amplit *= def_weight * falloff_fac; - if (mvert) { + if (vert_normals) { /* move along normals */ if (wmd->flag & MOD_WAVE_NORM_X) { co[0] += (lifefac * amplit) * vert_normals[i][0]; diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index af992c00097..69210c85862 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -71,20 +71,20 @@ typedef struct WeightedNormalData { const int loops_num; const int polys_num; - MVert *mvert; + const MVert *mvert; const float (*vert_normals)[3]; MEdge *medge; - MLoop *mloop; + const MLoop *mloop; short (*clnors)[2]; const bool has_clnors; /* True if clnors already existed, false if we had to create them. */ const float split_angle; - MPoly *mpoly; + const MPoly *mpoly; const float (*polynors)[3]; const int *poly_strength; - MDeformVert *dvert; + const MDeformVert *dvert; const int defgrp_index; const bool use_invert_vgroup; @@ -133,7 +133,7 @@ static void aggregate_item_normal(WeightedNormalModifierData *wnmd, { const float(*polynors)[3] = wn_data->polynors; - MDeformVert *dvert = wn_data->dvert; + const MDeformVert *dvert = wn_data->dvert; const int defgrp_index = wn_data->defgrp_index; const bool use_invert_vgroup = wn_data->use_invert_vgroup; @@ -186,18 +186,18 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, const int loops_num = wn_data->loops_num; const int polys_num = wn_data->polys_num; - MVert *mvert = wn_data->mvert; + const MVert *mvert = wn_data->mvert; MEdge *medge = wn_data->medge; - MLoop *mloop = wn_data->mloop; + const MLoop *mloop = wn_data->mloop; short(*clnors)[2] = wn_data->clnors; int *loop_to_poly = wn_data->loop_to_poly; - MPoly *mpoly = wn_data->mpoly; + const MPoly *mpoly = wn_data->mpoly; const float(*polynors)[3] = wn_data->polynors; const int *poly_strength = wn_data->poly_strength; - MDeformVert *dvert = wn_data->dvert; + const MDeformVert *dvert = wn_data->dvert; const short mode = wn_data->mode; ModePair *mode_pair = wn_data->mode_pair; @@ -243,7 +243,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, /* In this first loop, we assign each WeightedNormalDataAggregateItem * to its smooth fan of loops (aka lnor space). */ - MPoly *mp; + const MPoly *mp; int mp_index; int item_index; for (mp = mpoly, mp_index = 0, item_index = 0; mp_index < polys_num; mp++, mp_index++) { @@ -362,7 +362,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, clnors); } else { - /* TODO: Ideally, we could add an option to BKE_mesh_normals_loop_custom_[from_vertices_]set() + /* TODO: Ideally, we could add an option to `BKE_mesh_normals_loop_custom_[from_verts_]set()` * to keep current clnors instead of resetting them to default auto-computed ones, * when given new custom normal is zero-vec. * But this is not exactly trivial change, better to keep this optimization for later... @@ -379,18 +379,18 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, copy_v3_v3(vert_normals[mv_index], items_data[mv_index].normal); } - BKE_mesh_normals_loop_custom_from_vertices_set(mvert, - wn_data->vert_normals, - vert_normals, - verts_num, - medge, - edges_num, - mloop, - loops_num, - mpoly, - polynors, - polys_num, - clnors); + BKE_mesh_normals_loop_custom_from_verts_set(mvert, + wn_data->vert_normals, + vert_normals, + verts_num, + medge, + edges_num, + mloop, + loops_num, + mpoly, + polynors, + polys_num, + clnors); MEM_freeN(vert_normals); } @@ -446,11 +446,11 @@ static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *w { const int polys_num = wn_data->polys_num; - MVert *mvert = wn_data->mvert; - MLoop *mloop = wn_data->mloop; - MPoly *mpoly = wn_data->mpoly; + const MVert *mvert = wn_data->mvert; + const MLoop *mloop = wn_data->mloop; + const MPoly *mpoly = wn_data->mpoly; - MPoly *mp; + const MPoly *mp; int mp_index; ModePair *face_area = MEM_malloc_arrayN((size_t)polys_num, sizeof(*face_area), __func__); @@ -472,11 +472,11 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData const int loops_num = wn_data->loops_num; const int polys_num = wn_data->polys_num; - MVert *mvert = wn_data->mvert; - MLoop *mloop = wn_data->mloop; - MPoly *mpoly = wn_data->mpoly; + const MVert *mvert = wn_data->mvert; + const MLoop *mloop = wn_data->mloop; + const MPoly *mpoly = wn_data->mpoly; - MPoly *mp; + const MPoly *mp; int mp_index; int *loop_to_poly = MEM_malloc_arrayN((size_t)loops_num, sizeof(*loop_to_poly), __func__); @@ -484,7 +484,7 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData ModePair *corner_angle = MEM_malloc_arrayN((size_t)loops_num, sizeof(*corner_angle), __func__); for (mp_index = 0, mp = mpoly; mp_index < polys_num; mp_index++, mp++) { - MLoop *ml_start = &mloop[mp->loopstart]; + const MLoop *ml_start = &mloop[mp->loopstart]; float *index_angle = MEM_malloc_arrayN((size_t)mp->totloop, sizeof(*index_angle), __func__); BKE_mesh_calc_poly_angles(mp, ml_start, mvert, index_angle); @@ -513,11 +513,11 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD const int loops_num = wn_data->loops_num; const int polys_num = wn_data->polys_num; - MVert *mvert = wn_data->mvert; - MLoop *mloop = wn_data->mloop; - MPoly *mpoly = wn_data->mpoly; + const MVert *mvert = wn_data->mvert; + const MLoop *mloop = wn_data->mloop; + const MPoly *mpoly = wn_data->mpoly; - MPoly *mp; + const MPoly *mp; int mp_index; int *loop_to_poly = MEM_malloc_arrayN((size_t)loops_num, sizeof(*loop_to_poly), __func__); @@ -525,7 +525,7 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD ModePair *combined = MEM_malloc_arrayN((size_t)loops_num, sizeof(*combined), __func__); for (mp_index = 0, mp = mpoly; mp_index < polys_num; mp_index++, mp++) { - MLoop *ml_start = &mloop[mp->loopstart]; + const MLoop *ml_start = &mloop[mp->loopstart]; float face_area = BKE_mesh_calc_poly_area(mp, ml_start, mvert); float *index_angle = MEM_malloc_arrayN((size_t)mp->totloop, sizeof(*index_angle), __func__); @@ -579,11 +579,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * const int edges_num = result->totedge; const int loops_num = result->totloop; const int polys_num = result->totpoly; - - MEdge *medge = result->medge; - MPoly *mpoly = result->mpoly; - MVert *mvert = result->mvert; - MLoop *mloop = result->mloop; + const MVert *mvert = BKE_mesh_verts(result); + MEdge *medge = BKE_mesh_edges_for_write(result); + const MPoly *mpoly = BKE_mesh_polys(result); + const MLoop *mloop = BKE_mesh_loops(result); /* Right now: * If weight = 50 then all faces are given equal weight. @@ -609,10 +608,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * * it helps when generating clnor spaces and default normals. */ const bool has_clnors = clnors != NULL; if (!clnors) { - clnors = CustomData_add_layer(&result->ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, loops_num); + clnors = CustomData_add_layer( + &result->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, NULL, loops_num); } - MDeformVert *dvert; + const MDeformVert *dvert; int defgrp_index; MOD_get_vgroup(ctx->object, mesh, wnmd->defgrp_name, &dvert, &defgrp_index); @@ -660,7 +660,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * MEM_SAFE_FREE(wn_data.mode_pair); MEM_SAFE_FREE(wn_data.items_data); - result->runtime.is_original = false; + result->runtime.is_original_bmesh = false; return result; } @@ -674,9 +674,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(wnmd, DNA_struct_default_get(WeightedNormalModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 8ccf140e665..fa147201dc3 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -27,6 +27,7 @@ #include "BKE_context.h" #include "BKE_deform.h" #include "BKE_lib_query.h" +#include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_screen.h" #include "BKE_texture.h" /* Texture masking. */ @@ -80,9 +81,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla twmd->cmap_curve = BKE_curvemapping_copy(wmd->cmap_curve); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; @@ -158,7 +157,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; - MDeformVert *dvert = NULL; MDeformWeight **dw = NULL; float *org_w; /* Array original weights. */ float *new_w; /* Array new weights. */ @@ -198,18 +196,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } } - if (has_mdef) { - dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, verts_num); - } - else { - /* Add a valid data layer! */ - dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, verts_num); - } + MDeformVert *dvert = BKE_mesh_deform_verts_for_write(mesh); + /* Ultimate security check. */ if (!dvert) { return mesh; } - mesh->dvert = dvert; /* Get org weights, assuming 0.0 for vertices not in given vgroup. */ org_w = MEM_malloc_arrayN(verts_num, sizeof(float), "WeightVGEdit Modifier, org_w"); @@ -287,7 +279,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * MEM_freeN(new_w); MEM_freeN(dw); - mesh->runtime.is_original = false; + mesh->runtime.is_original_bmesh = false; /* Return the vgroup-modified mesh. */ return mesh; diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 701e30fbf57..957ea3b6c8f 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -23,6 +23,7 @@ #include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_lib_query.h" +#include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_screen.h" #include "BKE_texture.h" /* Texture masking. */ @@ -128,9 +129,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeightVGMixModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md; @@ -206,7 +205,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md; - MDeformVert *dvert = NULL; MDeformWeight **dw1, **tdw1, **dw2, **tdw2; float *org_w; float *new_w; @@ -263,18 +261,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } } - if (has_mdef) { - dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, verts_num); - } - else { - /* Add a valid data layer! */ - dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, verts_num); - } + MDeformVert *dvert = BKE_mesh_deform_verts_for_write(mesh); + /* Ultimate security check. */ if (!dvert) { return mesh; } - mesh->dvert = dvert; /* Find out which vertices to work on. */ tidx = MEM_malloc_arrayN(verts_num, sizeof(int), "WeightVGMix Modifier, tidx"); @@ -444,7 +436,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * MEM_freeN(dw2); MEM_SAFE_FREE(indices); - mesh->runtime.is_original = false; + mesh->runtime.is_original_bmesh = false; /* Return the vgroup-modified mesh. */ return mesh; diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 70838bc5c4f..ead12d9f08d 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -330,9 +330,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla twmd->cmap_curve = BKE_curvemapping_copy(wmd->cmap_curve); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md; @@ -423,7 +421,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BLI_assert(mesh != NULL); WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md; - MDeformVert *dvert = NULL; MDeformWeight **dw, **tdw; float(*v_cos)[3] = NULL; /* The vertices coordinates. */ Object *ob = ctx->object; @@ -475,12 +472,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return mesh; } - dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, verts_num); + MDeformVert *dvert = BKE_mesh_deform_verts_for_write(mesh); /* Ultimate security check. */ if (!dvert) { return mesh; } - mesh->dvert = dvert; /* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight. */ tidx = MEM_malloc_arrayN(verts_num, sizeof(int), "WeightVGProximity Modifier, tidx"); @@ -640,7 +636,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * TIMEIT_END(perf); #endif - mesh->runtime.is_original = false; + mesh->runtime.is_original_bmesh = false; /* Return the vgroup-modified mesh. */ return mesh; diff --git a/source/blender/modifiers/intern/MOD_weld.cc b/source/blender/modifiers/intern/MOD_weld.cc index 19b0bf62fea..ef6d561fa00 100644 --- a/source/blender/modifiers/intern/MOD_weld.cc +++ b/source/blender/modifiers/intern/MOD_weld.cc @@ -147,9 +147,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeldModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { WeldModifierData *wmd = (WeldModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 5799da5d156..85696bed162 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -41,9 +41,7 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WireframeModifierData), modifier); } -static void requiredDataMask(Object *UNUSED(ob), - ModifierData *md, - CustomData_MeshMasks *r_cddata_masks) +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) { WireframeModifierData *wmd = (WireframeModifierData *)md; |