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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/modifiers')
-rw-r--r--source/blender/modifiers/CMakeLists.txt2
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c4
-rw-r--r--source/blender/modifiers/intern/MOD_array.c75
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c10
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.cc12
-rw-r--r--source/blender/modifiers/intern/MOD_build.c33
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c8
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c8
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c6
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c245
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c6
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c14
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c7
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c14
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c6
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c49
-rw-r--r--source/blender/modifiers/intern/MOD_fluid.c6
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c6
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c20
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c16
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c4
-rw-r--r--source/blender/modifiers/intern/MOD_mask.cc186
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c10
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_util.h8
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c6
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.cc17
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c4
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc467
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc1929
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.hh44
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c70
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c145
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c28
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.cc4
-rw-r--r--source/blender/modifiers/intern/MOD_remesh.c25
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c53
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c7
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c8
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c6
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c35
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c10
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c4
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_extrude.c209
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_nonmanifold.c267
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c4
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c4
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c23
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c2
-rw-r--r--source/blender/modifiers/intern/MOD_util.c12
-rw-r--r--source/blender/modifiers/intern/MOD_util.h2
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c27
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c25
-rw-r--r--source/blender/modifiers/intern/MOD_volume_to_mesh.cc2
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c6
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c10
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c94
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c18
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c18
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c10
-rw-r--r--source/blender/modifiers/intern/MOD_weld.cc4
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c4
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 &params_;
- const blender::bke::DataTypeConversions &conversions_;
-
- friend NodeParamsProvider;
-
- public:
- GeometryNodesEvaluator(GeometryNodesEvaluationParams &params)
- : 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 &params)
-{
- 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 &params);
-
-} // 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;