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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2019-03-28 13:42:53 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-03-28 22:02:59 +0300
commit7b95d64d2f521cafe6a521af5b082c0a13cf8460 (patch)
tree6e49f06362ab6562ac0a78fca24a3d23c9d716d3 /source/blender/blenkernel
parentc39d82daf4ac79d87a10283eff2694d1744ed183 (diff)
Cleanup: better naming, comments, variable scoping in mesh_calc_modifiers.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c825
1 files changed, 416 insertions, 409 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 886545ff4b1..ac2ae8a1e35 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -879,18 +879,18 @@ static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer)
static void add_orco_mesh(
Object *ob, BMEditMesh *em, Mesh *mesh,
- Mesh *me_orco, int layer)
+ Mesh *mesh_orco, int layer)
{
float (*orco)[3], (*layerorco)[3];
int totvert, free;
totvert = mesh->totvert;
- if (me_orco) {
+ if (mesh_orco) {
free = 1;
- if (me_orco->totvert == totvert) {
- orco = BKE_mesh_vertexCos_get(me_orco, NULL);
+ if (mesh_orco->totvert == totvert) {
+ orco = BKE_mesh_vertexCos_get(mesh_orco, NULL);
}
else {
orco = BKE_mesh_vertexCos_get(mesh, NULL);
@@ -991,6 +991,59 @@ static void mesh_copy_autosmooth(Mesh *me, Mesh *me_orig)
}
}
+static void mesh_calc_modifier_final_normals(
+ const Mesh *mesh_input,
+ const CustomData_MeshMasks *dataMask,
+ const bool sculpt_dyntopo,
+ Mesh *mesh_final)
+{
+ /* Compute normals. */
+ const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
+ (dataMask->lmask & CD_MASK_NORMAL) != 0);
+ /* Some modifiers may need this info from their target (other) object, simpler to generate it here as well.
+ * Note that they will always be generated when no loop normals are comptuted,
+ * since they are needed by drawing code. */
+ const bool do_poly_normals = ((dataMask->pmask & CD_MASK_NORMAL) != 0);
+
+ if (do_loop_normals) {
+ /* In case we also need poly normals, add the layer here, then BKE_mesh_calc_normals_split() will fill it. */
+ if (do_poly_normals) {
+ if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
+ CustomData_add_layer(&mesh_final->pdata, CD_NORMAL, CD_CALLOC, NULL, mesh_final->totpoly);
+ }
+ }
+ /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */
+ BKE_mesh_calc_normals_split(mesh_final);
+ BKE_mesh_tessface_clear(mesh_final);
+ }
+
+ if (sculpt_dyntopo == false) {
+ /* watch this! after 2.75a we move to from tessface to looptri (by default) */
+ if (dataMask->fmask & CD_MASK_MFACE) {
+ BKE_mesh_tessface_ensure(mesh_final);
+ }
+
+ /* without this, drawing ngon tri's faces will show ugly tessellated face
+ * normals and will also have to calculate normals on the fly, try avoid
+ * this where possible since calculating polygon normals isn't fast,
+ * note that this isn't a problem for subsurf (only quads) or editmode
+ * which deals with drawing differently.
+ *
+ * Only calc vertex normals if they are flagged as dirty.
+ * If using loop normals, poly nors have already been computed.
+ */
+ if (!do_loop_normals) {
+ BKE_mesh_ensure_normals_for_display(mesh_final);
+ }
+ }
+
+ /* Some modifiers, like datatransfer, may generate those data as temp layer, we do not want to keep them,
+ * as they are used by display code when available (i.e. even if autosmooth is disabled). */
+ if (!do_loop_normals && CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
+ CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
+ }
+}
+
static void mesh_calc_modifiers(
struct Depsgraph *depsgraph,
Scene *scene, Object *ob,
@@ -998,58 +1051,62 @@ static void mesh_calc_modifiers(
const bool need_mapping,
const CustomData_MeshMasks *dataMask,
const int index,
- const bool useCache,
+ const bool use_cache,
/* return args */
Mesh **r_deform,
Mesh **r_final)
{
- ModifierData *firstmd, *md, *previewmd = NULL;
- CDMaskLink *datamasks, *curr;
- /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */
- CustomData_MeshMasks mask, nextmask, previewmask = {0}, append_mask = CD_MASK_BAREMESH_ORIGINDEX;
-
- float (*deformedVerts)[3] = NULL;
- int numVerts = ((Mesh *)ob->data)->totvert;
- const bool useRenderParams = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
- const int required_mode = useRenderParams ? eModifierMode_Render : eModifierMode_Realtime;
+ /* Input and final mesh. Final mesh is only created the moment the first
+ * constructive modifier is executed, or a deform modifier needs normals
+ * or certain data layers. */
+ Mesh *mesh_input = ob->data;
+ Mesh *mesh_final = NULL;
+ Mesh *mesh_deform = NULL;
+ BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
+
+ /* Deformed vertex locations array. Deform only modifier need this type of
+ * float array rather than MVert*. Tracked along with mesh_final as an
+ * optimization to avoid copying coordinates back and forth if there are
+ * multiple sequential deform only modifiers. */
+ float (*deformed_verts)[3] = NULL;
+ int num_deformed_verts = mesh_input->totvert;
bool isPrevDeform = false;
+
+ /* Mesh with constructive modifiers but no deformation applied. Tracked
+ * along with final mesh if undeformed / orco coordinates are requested
+ * for texturing. */
+ Mesh *mesh_orco = NULL;
+ Mesh *mesh_orco_cloth = NULL;
+
+ /* Modifier evaluation modes. */
+ const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+ const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
+
+ /* Sculpt can skip certain modifiers. */
MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
const bool has_multires = (mmd && mmd->sculptlvl != 0);
bool multires_applied = false;
- const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !useRenderParams;
- const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !useRenderParams;
+ const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !use_render;
+ const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !use_render;
- /* Generic preview only in object mode! */
- const bool do_mod_mcol = (ob->mode == OB_MODE_OBJECT);
- const bool do_loop_normals = ((((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) != 0 ||
- (dataMask->lmask & CD_MASK_NORMAL) != 0);
- /* Some modifiers may need this info from their target (other) object, simpler to generate it here as well.
- * Note that they will always be generated when no loop normals are comptuted,
- * since they are needed by drawing code. */
- const bool do_poly_normals = ((dataMask->pmask & CD_MASK_NORMAL) != 0);
+ /* Modifier evaluation contexts for different types of modifiers. */
+ ModifierApplyFlag app_render = use_render ? MOD_APPLY_RENDER : 0;
+ ModifierApplyFlag app_cache = use_cache ? MOD_APPLY_USECACHE : 0;
+ const ModifierEvalContext mectx = {depsgraph, ob, app_render | app_cache};
+ const ModifierEvalContext mectx_orco = {depsgraph, ob, app_render | MOD_APPLY_ORCO};
+ /* Get effective list of modifiers to execute. Some effects like shape keys
+ * are added as virtual modifiers before the user created modifiers. */
VirtualModifierData virtualModifierData;
+ ModifierData *firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ ModifierData *md = firstmd;
- ModifierApplyFlag app_flags = useRenderParams ? MOD_APPLY_RENDER : 0;
- ModifierApplyFlag deform_app_flags = app_flags;
-
- BLI_assert((((Mesh *)ob->data)->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
-
- if (useCache)
- app_flags |= MOD_APPLY_USECACHE;
- if (useDeform)
- deform_app_flags |= MOD_APPLY_USECACHE;
-
- /* TODO(sybren): do we really need three context objects? Or do we modify
- * them on the fly to change the flags where needed? */
- const ModifierEvalContext mectx_deform = {depsgraph, ob, deform_app_flags};
- const ModifierEvalContext mectx_apply = {depsgraph, ob, app_flags};
- const ModifierEvalContext mectx_orco = {depsgraph, ob, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO};
-
- md = firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
-
- modifiers_clearErrors(ob);
-
+ /* Preview colors by modifiers such as dynamic paint, to show the results
+ * even if the resulting data is not used in a material. Only in object mode.
+ * TODO: this is broken, not drawn by the drawn manager. */
+ const bool do_mod_mcol = (ob->mode == OB_MODE_OBJECT);
+ ModifierData *previewmd = NULL;
+ CustomData_MeshMasks previewmask = {0};
if (do_mod_mcol) {
/* Find the last active modifier generating a preview, or NULL if none. */
/* XXX Currently, DPaint modifier just ignores this.
@@ -1058,21 +1115,21 @@ static void mesh_calc_modifiers(
previewmd = modifiers_getLastPreview(scene, md, required_mode);
}
- datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, previewmd, &previewmask);
- curr = datamasks;
-
- if (r_deform) {
- *r_deform = NULL;
- }
- *r_final = NULL;
+ /* Compute accumulated datamasks needed by each modifier. It helps to do
+ * this fine grained so that for example vertex groups are preserved up to
+ * an armature modifier, but not through a following subsurf modifier where
+ * subdividing them is expensive. */
+ CDMaskLink *datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, previewmd, &previewmask);
+ CDMaskLink *md_datamask = datamasks;
+ /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */
+ CustomData_MeshMasks append_mask = CD_MASK_BAREMESH_ORIGINDEX;
- /* We need mesh even for deform-only part of the stack, in cases where some modifier needs
- * e.g. access to updated normals. See T62633 for an example. */
- Mesh *me = NULL;
+ /* Clear errors before evaluation. */
+ modifiers_clearErrors(ob);
+ /* Apply all leading deform modifiers. */
if (useDeform) {
- /* Apply all leading deforming modifiers */
- for (; md; md = md->next, curr = curr->next) {
+ for (; md; md = md->next, md_datamask = md_datamask->next) {
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!modifier_isEnabled(scene, md, required_mode)) {
@@ -1084,19 +1141,18 @@ static void mesh_calc_modifiers(
}
if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
- if (!deformedVerts) {
- deformedVerts = BKE_mesh_vertexCos_get(ob->data, &numVerts);
+ if (!deformed_verts) {
+ deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts);
}
-
- if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
- if (me == NULL) {
- me = BKE_mesh_copy_for_eval(ob->data, true);
- ASSERT_IS_VALID_MESH(me);
+ else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+ if (mesh_final == NULL) {
+ mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
+ ASSERT_IS_VALID_MESH(mesh_final);
}
- BKE_mesh_apply_vert_coords(me, deformedVerts);
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
}
- modwrap_deformVerts(md, &mectx_deform, me, deformedVerts, numVerts);
+ modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
isPrevDeform = true;
}
@@ -1111,29 +1167,18 @@ static void mesh_calc_modifiers(
/* Result of all leading deforming modifiers is cached for
* places that wish to use the original mesh but with deformed
- * coordinates (vpaint, etc.)
- */
+ * coordinates (like vertex paint). */
if (r_deform) {
- *r_deform = BKE_mesh_copy_for_eval(ob->data, true);
+ mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true);
- if (deformedVerts) {
- BKE_mesh_apply_vert_coords(*r_deform, deformedVerts);
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_deform, deformed_verts);
}
}
}
- else {
- /* default behavior for meshes */
- deformedVerts = BKE_mesh_vertexCos_get(ob->data, &numVerts);
- }
-
-
- /* Now apply all remaining modifiers. If useDeform is off then skip
- * OnlyDeform ones.
- */
- Mesh *me_orco = NULL;
- Mesh *me_orco_cloth = NULL;
- for (; md; md = md->next, curr = curr->next) {
+ /* Apply all remaining constructive and deforming modifiers. */
+ for (; md; md = md->next, md_datamask = md_datamask->next) {
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!modifier_isEnabled(scene, md, required_mode)) {
@@ -1144,7 +1189,7 @@ static void mesh_calc_modifiers(
continue;
}
- if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && me) {
+ if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && mesh_final) {
modifier_setError(md, "Modifier requires original data, bad stack position");
continue;
}
@@ -1161,7 +1206,7 @@ static void mesh_calc_modifiers(
}
}
- if (sculpt_dyntopo && !useRenderParams)
+ if (sculpt_dyntopo)
unsupported = true;
if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM)
@@ -1189,91 +1234,87 @@ static void mesh_calc_modifiers(
continue;
}
- /* add an orco layer if needed by this modifier */
- memset(&mask, 0, sizeof(mask));
- if (mti->requiredDataMask) {
+ /* Add an orco layer if needed by this modifier. */
+ if (mesh_final && mti->requiredDataMask) {
+ CustomData_MeshMasks mask = {0};
mti->requiredDataMask(ob, md, &mask);
- }
-
- if (me && (mask.vmask & CD_MASK_ORCO)) {
- add_orco_mesh(ob, NULL, me, me_orco, CD_ORCO);
+ if (mask.vmask & CD_MASK_ORCO) {
+ add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_ORCO);
+ }
}
/* How to apply modifier depends on (a) what we already have as
* a result of previous modifiers (could be a Mesh or just
- * deformed vertices) and (b) what type the modifier is.
- */
-
+ * deformed vertices) and (b) what type the modifier is. */
if (mti->type == eModifierTypeType_OnlyDeform) {
/* No existing verts to deform, need to build them. */
- if (!deformedVerts) {
- if (me) {
+ if (!deformed_verts) {
+ if (mesh_final) {
/* Deforming a mesh, read the vertex locations
* out of the mesh and deform them. Once done with this
- * run of deformers verts will be written back.
- */
- deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts);
+ * run of deformers verts will be written back. */
+ deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts);
}
else {
- deformedVerts = BKE_mesh_vertexCos_get(ob->data, &numVerts);
+ deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts);
}
}
-
/* if this is not the last modifier in the stack then recalculate the normals
* to avoid giving bogus normals to the next modifier see: [#23673] */
- if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+ else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
/* XXX, this covers bug #23673, but we may need normal calc for other types */
- if (me) {
- BKE_mesh_apply_vert_coords(me, deformedVerts);
+ if (mesh_final) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
}
}
- modwrap_deformVerts(md, &mectx_deform, me, deformedVerts, numVerts);
+ modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
}
else {
/* determine which data layers are needed by following modifiers */
- if (curr->next)
- nextmask = curr->next->mask;
+ CustomData_MeshMasks nextmask;
+ if (md_datamask->next)
+ nextmask = md_datamask->next->mask;
else
nextmask = *dataMask;
/* apply vertex coordinates or build a Mesh as necessary */
- if (me) {
- if (deformedVerts) {
- BKE_mesh_apply_vert_coords(me, deformedVerts);
+ if (mesh_final) {
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
}
}
else {
- me = BKE_mesh_copy_for_eval(ob->data, true);
- ASSERT_IS_VALID_MESH(me);
+ mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
+ ASSERT_IS_VALID_MESH(mesh_final);
- if (deformedVerts) {
- BKE_mesh_apply_vert_coords(me, deformedVerts);
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
}
- /* Constructive modifiers need to have an origindex
- * otherwise they wont have anywhere to copy the data from.
+ /* Initialize original indices the first time we evaluate a
+ * constructive modifier. Modifiers will then do mapping mostly
+ * automatic by copying them through CustomData_copy_data along
+ * with other data.
*
- * Also create ORIGINDEX data if any of the following modifiers
- * requests it, this way Mirror, Solidify etc will keep ORIGINDEX
- * data by using generic DM_copy_vert_data() functions.
- */
+ * These are created when either requested by evaluation, or if
+ * following modifiers requested them. */
if (need_mapping || ((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX)) {
/* calc */
- CustomData_add_layer(&me->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, me->totvert);
- CustomData_add_layer(&me->edata, CD_ORIGINDEX, CD_CALLOC, NULL, me->totedge);
- CustomData_add_layer(&me->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, me->totpoly);
+ CustomData_add_layer(&mesh_final->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totvert);
+ CustomData_add_layer(&mesh_final->edata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totedge);
+ CustomData_add_layer(&mesh_final->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, mesh_final->totpoly);
/* Not worth parallelizing this, gives less than 0.1% overall speedup in best of best cases... */
- range_vn_i(CustomData_get_layer(&me->vdata, CD_ORIGINDEX), me->totvert, 0);
- range_vn_i(CustomData_get_layer(&me->edata, CD_ORIGINDEX), me->totedge, 0);
- range_vn_i(CustomData_get_layer(&me->pdata, CD_ORIGINDEX), me->totpoly, 0);
+ range_vn_i(CustomData_get_layer(&mesh_final->vdata, CD_ORIGINDEX), mesh_final->totvert, 0);
+ range_vn_i(CustomData_get_layer(&mesh_final->edata, CD_ORIGINDEX), mesh_final->totedge, 0);
+ range_vn_i(CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX), mesh_final->totpoly, 0);
}
}
/* set the Mesh to only copy needed data */
- mask = curr->mask;
+ CustomData_MeshMasks mask = md_datamask->mask;
/* needMapping check here fixes bug [#28112], otherwise it's
* possible that it won't be copied */
CustomData_MeshMasks_update(&mask, &append_mask);
@@ -1282,44 +1323,44 @@ static void mesh_calc_modifiers(
mask.emask |= CD_MASK_ORIGINDEX;
mask.pmask |= CD_MASK_ORIGINDEX;
}
- mesh_set_only_copy(me, &mask);
+ mesh_set_only_copy(mesh_final, &mask);
/* add cloth rest shape key if needed */
if (mask.vmask & CD_MASK_CLOTH_ORCO) {
- add_orco_mesh(ob, NULL, me, me_orco, CD_CLOTH_ORCO);
+ add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_CLOTH_ORCO);
}
/* add an origspace layer if needed */
- if ((curr->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) {
- if (!CustomData_has_layer(&me->ldata, CD_ORIGSPACE_MLOOP)) {
- CustomData_add_layer(&me->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, me->totloop);
- mesh_init_origspace(me);
+ if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) {
+ if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
+ CustomData_add_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, mesh_final->totloop);
+ mesh_init_origspace(mesh_final);
}
}
- Mesh *me_next = modwrap_applyModifier(md, &mectx_apply, me);
- ASSERT_IS_VALID_MESH(me_next);
+ Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final);
+ ASSERT_IS_VALID_MESH(mesh_next);
- if (me_next) {
+ if (mesh_next) {
/* if the modifier returned a new mesh, release the old one */
- if (me && me != me_next) {
- BLI_assert(me != ob->data);
- BKE_id_free(NULL, me);
+ if (mesh_final != mesh_next) {
+ BLI_assert(mesh_final != mesh_input);
+ BKE_id_free(NULL, mesh_final);
}
- me = me_next;
+ mesh_final = mesh_next;
- if (deformedVerts) {
- MEM_freeN(deformedVerts);
- deformedVerts = NULL;
+ if (deformed_verts) {
+ MEM_freeN(deformed_verts);
+ deformed_verts = NULL;
}
- mesh_copy_autosmooth(me, ob->data);
+ mesh_copy_autosmooth(mesh_final, mesh_input);
}
/* create an orco mesh in parallel */
if (nextmask.vmask & CD_MASK_ORCO) {
- if (!me_orco) {
- me_orco = create_orco_mesh(ob, ob->data, NULL, CD_ORCO);
+ if (!mesh_orco) {
+ mesh_orco = create_orco_mesh(ob, mesh_input, NULL, CD_ORCO);
}
nextmask.vmask &= ~CD_MASK_ORCO;
@@ -1333,45 +1374,45 @@ static void mesh_calc_modifiers(
mti->requiredDataMask(ob, md, &temp_cddata_masks);
}
CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask);
- mesh_set_only_copy(me_orco, &temp_cddata_masks);
+ mesh_set_only_copy(mesh_orco, &temp_cddata_masks);
- me_next = modwrap_applyModifier(md, &mectx_orco, me_orco);
- ASSERT_IS_VALID_MESH(me_next);
+ mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco);
+ ASSERT_IS_VALID_MESH(mesh_next);
- if (me_next) {
+ if (mesh_next) {
/* if the modifier returned a new mesh, release the old one */
- if (me_orco && me_orco != me_next) {
- BLI_assert(me_orco != ob->data);
- BKE_id_free(NULL, me_orco);
+ if (mesh_orco != mesh_next) {
+ BLI_assert(mesh_orco != mesh_input);
+ BKE_id_free(NULL, mesh_orco);
}
- me_orco = me_next;
+ mesh_orco = mesh_next;
}
}
/* create cloth orco mesh in parallel */
if (nextmask.vmask & CD_MASK_CLOTH_ORCO) {
- if (!me_orco_cloth) {
- me_orco_cloth = create_orco_mesh(ob, ob->data, NULL, CD_CLOTH_ORCO);
+ if (!mesh_orco_cloth) {
+ mesh_orco_cloth = create_orco_mesh(ob, mesh_input, NULL, CD_CLOTH_ORCO);
}
nextmask.vmask &= ~CD_MASK_CLOTH_ORCO;
nextmask.vmask |= CD_MASK_ORIGINDEX;
nextmask.emask |= CD_MASK_ORIGINDEX;
nextmask.pmask |= CD_MASK_ORIGINDEX;
- mesh_set_only_copy(me_orco_cloth, &nextmask);
+ mesh_set_only_copy(mesh_orco_cloth, &nextmask);
- me_next = modwrap_applyModifier(md, &mectx_orco, me_orco_cloth);
- ASSERT_IS_VALID_MESH(me_next);
+ mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco_cloth);
+ ASSERT_IS_VALID_MESH(mesh_next);
- if (me_next) {
+ if (mesh_next) {
/* if the modifier returned a new mesh, release the old one */
- if (me_orco_cloth && me_orco_cloth != me_next) {
- BLI_assert(me_orco != ob->data);
- BKE_id_free(NULL, me_orco_cloth);
+ if (mesh_orco_cloth != mesh_next) {
+ BLI_assert(mesh_orco != mesh_input);
+ BKE_id_free(NULL, mesh_orco_cloth);
}
- me_orco_cloth = me_next;
+ mesh_orco_cloth = mesh_next;
}
}
@@ -1381,7 +1422,7 @@ static void mesh_calc_modifiers(
append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL;
}
- me->runtime.deformed_only = false;
+ mesh_final->runtime.deformed_only = false;
}
isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
@@ -1395,85 +1436,46 @@ static void mesh_calc_modifiers(
}
}
+ BLI_linklist_free((LinkNode *)datamasks, NULL);
+
for (md = firstmd; md; md = md->next)
modifier_freeTemporaryData(md);
/* Yay, we are done. If we have a Mesh and deformed vertices
* need to apply these back onto the Mesh. If we have no
- * Mesh then we need to build one.
- */
- if (me) {
- *r_final = me;
-
- if (deformedVerts) {
- BKE_mesh_apply_vert_coords(*r_final, deformedVerts);
- }
+ * Mesh then we need to build one. */
+ if (mesh_final == NULL) {
+ mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
}
- else {
- *r_final = BKE_mesh_copy_for_eval(ob->data, true);
-
- if (deformedVerts) {
- BKE_mesh_apply_vert_coords(*r_final, deformedVerts);
- }
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ MEM_freeN(deformed_verts);
+ deformed_verts = NULL;
}
- /* add an orco layer if needed */
+ /* Add orco coordinates to final and deformed mesh if requested. */
if (dataMask->vmask & CD_MASK_ORCO) {
- add_orco_mesh(ob, NULL, *r_final, me_orco, CD_ORCO);
+ add_orco_mesh(ob, NULL, mesh_final, mesh_orco, CD_ORCO);
- if (r_deform && *r_deform)
- add_orco_mesh(ob, NULL, *r_deform, NULL, CD_ORCO);
+ if (mesh_deform)
+ add_orco_mesh(ob, NULL, mesh_deform, NULL, CD_ORCO);
}
- if (do_loop_normals) {
- /* In case we also need poly normals, add the layer here, then BKE_mesh_calc_normals_split() will fill it. */
- if (do_poly_normals) {
- if (!CustomData_has_layer(&(*r_final)->pdata, CD_NORMAL)) {
- CustomData_add_layer(&(*r_final)->pdata, CD_NORMAL, CD_CALLOC, NULL, (*r_final)->totpoly);
- }
- }
- /* Compute loop normals (note: will compute poly and vert normals as well, if needed!) */
- BKE_mesh_calc_normals_split(*r_final);
- BKE_mesh_tessface_clear(*r_final);
+ if (mesh_orco) {
+ BKE_id_free(NULL, mesh_orco);
}
-
- if (sculpt_dyntopo == false) {
- /* watch this! after 2.75a we move to from tessface to looptri (by default) */
- if (dataMask->fmask & CD_MASK_MFACE) {
- BKE_mesh_tessface_ensure(*r_final);
- }
-
- /* without this, drawing ngon tri's faces will show ugly tessellated face
- * normals and will also have to calculate normals on the fly, try avoid
- * this where possible since calculating polygon normals isn't fast,
- * note that this isn't a problem for subsurf (only quads) or editmode
- * which deals with drawing differently.
- *
- * Only calc vertex normals if they are flagged as dirty.
- * If using loop normals, poly nors have already been computed.
- */
- if (!do_loop_normals) {
- BKE_mesh_ensure_normals_for_display(*r_final);
- }
+ if (mesh_orco_cloth) {
+ BKE_id_free(NULL, mesh_orco_cloth);
}
- /* Some modifiers, like datatransfer, may generate those data as temp layer, we do not want to keep them,
- * as they are used by display code when available (i.e. even if autosmooth is disabled). */
- if (!do_loop_normals && CustomData_has_layer(&(*r_final)->ldata, CD_NORMAL)) {
- CustomData_free_layers(&(*r_final)->ldata, CD_NORMAL, (*r_final)->totloop);
- }
+ /* Compute normals. */
+ mesh_calc_modifier_final_normals(mesh_input, dataMask, sculpt_dyntopo, mesh_final);
- if (me_orco) {
- BKE_id_free(NULL, me_orco);
- }
- if (me_orco_cloth) {
- BKE_id_free(NULL, me_orco_cloth);
+ /* Return final mesh */
+ *r_final = mesh_final;
+ if (r_deform) {
+ *r_deform = mesh_deform;
}
-
- if (deformedVerts)
- MEM_freeN(deformedVerts);
-
- BLI_linklist_free((LinkNode *)datamasks, NULL);
}
@@ -1512,213 +1514,264 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev
return true;
}
+static void editbmesh_calc_modifier_final_normals(
+ const Mesh *mesh_input,
+ const CustomData_MeshMasks *dataMask,
+ Mesh *mesh_final)
+{
+ const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
+ (dataMask->lmask & CD_MASK_NORMAL) != 0);
+ /* Some modifiers may need this info from their target (other) object, simpler to generate it here as well. */
+ const bool do_poly_normals = ((dataMask->pmask & CD_MASK_NORMAL) != 0);
+
+ if (do_loop_normals) {
+ /* In case we also need poly normals, add the layer here, then BKE_mesh_calc_normals_split() will fill it. */
+ if (do_poly_normals) {
+ if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
+ CustomData_add_layer(&mesh_final->pdata, CD_NORMAL, CD_CALLOC, NULL, mesh_final->totpoly);
+ }
+ }
+ /* Compute loop normals */
+ BKE_mesh_calc_normals_split(mesh_final);
+ BKE_mesh_tessface_clear(mesh_final);
+ }
+
+ /* BMESH_ONLY, ensure tessface's used for drawing,
+ * but don't recalculate if the last modifier in the stack gives us tessfaces
+ * check if the derived meshes are DM_TYPE_EDITBMESH before calling, this isn't essential
+ * but quiets annoying error messages since tessfaces wont be created. */
+ if (dataMask->fmask & CD_MASK_MFACE) {
+ if (mesh_final->edit_mesh == NULL) {
+ BKE_mesh_tessface_ensure(mesh_final);
+ }
+ }
+
+ /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
+ if (!do_loop_normals) {
+ BKE_mesh_ensure_normals_for_display(mesh_final);
+
+ /* Some modifiers, like datatransfer, may generate those data, we do not want to keep them,
+ * as they are used by display code when available (i.e. even if autosmooth is disabled). */
+ if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) {
+ CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop);
+ }
+ }
+}
+
static void editbmesh_calc_modifiers(
struct Depsgraph *depsgraph,
Scene *scene,
Object *ob,
- BMEditMesh *em,
+ BMEditMesh *em_input,
const CustomData_MeshMasks *dataMask,
/* return args */
Mesh **r_cage,
Mesh **r_final)
{
- ModifierData *md;
- float (*deformedVerts)[3] = NULL;
- CustomData_MeshMasks mask = {0}, append_mask = CD_MASK_BAREMESH;
- int i, numVerts = 0, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
- CDMaskLink *datamasks, *curr;
- const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
- const bool do_init_statvis = false; /* FIXME: use V3D_OVERLAY_EDIT_STATVIS. */
- VirtualModifierData virtualModifierData;
+ /* Input and final mesh. Final mesh is only created the moment the first
+ * constructive modifier is executed, or a deform modifier needs normals
+ * or certain data layers. */
+ Mesh *mesh_input = ob->data;
+ Mesh *mesh_final = NULL;
+ Mesh *mesh_cage = NULL;
+
+ /* Deformed vertex locations array. Deform only modifier need this type of
+ * float array rather than MVert*. Tracked along with mesh_final as an
+ * optimization to avoid copying coordinates back and forth if there are
+ * multiple sequential deform only modifiers. */
+ float (*deformed_verts)[3] = NULL;
+ int num_deformed_verts = 0;
bool isPrevDeform = false;
- /* TODO(sybren): do we really need multiple objects, or shall we change the flags where needed? */
- const ModifierEvalContext mectx = {depsgraph, ob, 0};
- const ModifierEvalContext mectx_orco = {depsgraph, ob, MOD_APPLY_ORCO};
- const ModifierEvalContext mectx_cache = {depsgraph, ob, MOD_APPLY_USECACHE};
+ /* Mesh with constructive modifiers but no deformation applied. Tracked
+ * along with final mesh if undeformed / orco coordinates are requested
+ * for texturing. */
+ Mesh *mesh_orco = NULL;
- const bool do_loop_normals = ((((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH) != 0 ||
- (dataMask->lmask & CD_MASK_NORMAL) != 0);
- /* Some modifiers may need this info from their target (other) object, simpler to generate it here as well. */
- const bool do_poly_normals = ((dataMask->pmask & CD_MASK_NORMAL) != 0);
+ /* Modifier evaluation modes. */
+ const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
+ const bool do_init_statvis = false; /* FIXME: use V3D_OVERLAY_EDIT_STATVIS. */
- modifiers_clearErrors(ob);
+ /* Modifier evaluation contexts for different types of modifiers. */
+ const ModifierEvalContext mectx = {depsgraph, ob, MOD_APPLY_USECACHE};
+ const ModifierEvalContext mectx_orco = {depsgraph, ob, MOD_APPLY_ORCO};
+ /* Evaluate modifiers up to certain index to get the mesh cage. */
+ int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
if (r_cage && cageIndex == -1) {
- *r_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(em, dataMask, NULL);
- mesh_copy_autosmooth(*r_cage, ob->data);
+ mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(em_input, dataMask, NULL);
+ mesh_copy_autosmooth(mesh_cage, mesh_input);
}
- md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
-
- /* copied from mesh_calc_modifiers */
- datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, NULL, NULL);
+ /* Get effective list of modifiers to execute. Some effects like shape keys
+ * are added as virtual modifiers before the user created modifiers. */
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
- curr = datamasks;
+ /* Compute accumulated datamasks needed by each modifier. It helps to do
+ * this fine grained so that for example vertex groups are preserved up to
+ * an armature modifier, but not through a following subsurf modifier where
+ * subdividing them is expensive. */
+ CDMaskLink *datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode, NULL, NULL);
+ CDMaskLink *md_datamask = datamasks;
+ CustomData_MeshMasks append_mask = CD_MASK_BAREMESH;
- Mesh *me = NULL;
- Mesh *me_orco = NULL;
+ /* Clear errors before evaluation. */
+ modifiers_clearErrors(ob);
- for (i = 0; md; i++, md = md->next, curr = curr->next) {
+ for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) {
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- memset(&mask, 0, sizeof(mask));
- if (!editbmesh_modifier_is_enabled(scene, md, me != NULL)) {
+ if (!editbmesh_modifier_is_enabled(scene, md, mesh_final != NULL)) {
continue;
}
- /* add an orco layer if needed by this modifier */
- if (me && mti->requiredDataMask) {
+ /* Add an orco layer if needed by this modifier. */
+ if (mesh_final && mti->requiredDataMask) {
+ CustomData_MeshMasks mask = {0};
mti->requiredDataMask(ob, md, &mask);
if (mask.vmask & CD_MASK_ORCO) {
- add_orco_mesh(ob, em, me, me_orco, CD_ORCO);
+ add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
}
}
/* How to apply modifier depends on (a) what we already have as
- * a result of previous modifiers (could be a DerivedMesh or just
- * deformed vertices) and (b) what type the modifier is.
- */
-
+ * a result of previous modifiers (could be a mesh or just
+ * deformed vertices) and (b) what type the modifier is. */
if (mti->type == eModifierTypeType_OnlyDeform) {
/* No existing verts to deform, need to build them. */
- if (!deformedVerts) {
- if (me) {
+ if (!deformed_verts) {
+ if (mesh_final) {
/* Deforming a derived mesh, read the vertex locations
* out of the mesh and deform them. Once done with this
- * run of deformers verts will be written back.
- */
- deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts);
+ * run of deformers verts will be written back. */
+ deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts);
}
else {
- deformedVerts = editbmesh_get_vertex_cos(em, &numVerts);
+ deformed_verts = editbmesh_get_vertex_cos(em_input, &num_deformed_verts);
}
}
-
- if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
- if (me == NULL) {
- me = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL);
- ASSERT_IS_VALID_MESH(me);
- mesh_copy_autosmooth(me, ob->data);
+ else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+ if (mesh_final == NULL) {
+ mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL);
+ ASSERT_IS_VALID_MESH(mesh_final);
+ mesh_copy_autosmooth(mesh_final, mesh_input);
}
- BLI_assert(deformedVerts != NULL);
- BKE_mesh_apply_vert_coords(me, deformedVerts);
+ BLI_assert(deformed_verts != NULL);
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
}
if (mti->deformVertsEM)
- modwrap_deformVertsEM(md, &mectx, em, me, deformedVerts, numVerts);
+ modwrap_deformVertsEM(md, &mectx, em_input, mesh_final, deformed_verts, num_deformed_verts);
else
- modwrap_deformVerts(md, &mectx, me, deformedVerts, numVerts);
+ modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
}
else {
- Mesh *me_next;
-
/* apply vertex coordinates or build a DerivedMesh as necessary */
- if (me) {
- if (deformedVerts) {
- Mesh *me_temp = BKE_mesh_copy_for_eval(me, false);
-
- if (!(r_cage && me == *r_cage)) {
- BKE_id_free(NULL, me);
+ if (mesh_final) {
+ if (deformed_verts) {
+ Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false);
+ if (mesh_final != mesh_cage) {
+ BKE_id_free(NULL, mesh_final);
}
- me = me_temp;
- BKE_mesh_apply_vert_coords(me, deformedVerts);
+ mesh_final = mesh_tmp;
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
}
- else if (r_cage && me == *r_cage) {
+ else if (mesh_final == mesh_cage) {
/* 'me' may be changed by this modifier, so we need to copy it. */
- me = BKE_mesh_copy_for_eval(me, false);
+ mesh_final = BKE_mesh_copy_for_eval(mesh_final, false);
}
}
else {
- me = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL);
- ASSERT_IS_VALID_MESH(me);
+ mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL);
+ ASSERT_IS_VALID_MESH(mesh_final);
- mesh_copy_autosmooth(me, ob->data);
+ mesh_copy_autosmooth(mesh_final, mesh_input);
- if (deformedVerts) {
- BKE_mesh_apply_vert_coords(me, deformedVerts);
+ if (deformed_verts) {
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
}
}
/* create an orco derivedmesh in parallel */
- mask = curr->mask;
+ CustomData_MeshMasks mask = md_datamask->mask;
if (mask.vmask & CD_MASK_ORCO) {
- if (!me_orco) {
- me_orco = create_orco_mesh(ob, ob->data, em, CD_ORCO);
+ if (!mesh_orco) {
+ mesh_orco = create_orco_mesh(ob, mesh_input, em_input, CD_ORCO);
}
mask.vmask &= ~CD_MASK_ORCO;
mask.vmask |= CD_MASK_ORIGINDEX;
mask.emask |= CD_MASK_ORIGINDEX;
mask.pmask |= CD_MASK_ORIGINDEX;
- mesh_set_only_copy(me_orco, &mask);
+ mesh_set_only_copy(mesh_orco, &mask);
- me_next = modwrap_applyModifier(md, &mectx_orco, me_orco);
- ASSERT_IS_VALID_MESH(me_next);
+ Mesh *mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco);
+ ASSERT_IS_VALID_MESH(mesh_next);
- if (me_next) {
+ if (mesh_next) {
/* if the modifier returned a new dm, release the old one */
- if (me_orco && me_orco != me_next) {
- BKE_id_free(NULL, me_orco);
+ if (mesh_orco && mesh_orco != mesh_next) {
+ BKE_id_free(NULL, mesh_orco);
}
- me_orco = me_next;
+ mesh_orco = mesh_next;
}
}
/* set the DerivedMesh to only copy needed data */
CustomData_MeshMasks_update(&mask, &append_mask);
- mask = curr->mask; /* CD_MASK_ORCO may have been cleared above */ /* XXX WHAT? ovewrites mask ??? */
+ mask = md_datamask->mask; /* CD_MASK_ORCO may have been cleared above */ /* XXX WHAT? ovewrites mask ??? */
mask.vmask |= CD_MASK_ORIGINDEX;
mask.emask |= CD_MASK_ORIGINDEX;
mask.pmask |= CD_MASK_ORIGINDEX;
- mesh_set_only_copy(me, &mask);
+ mesh_set_only_copy(mesh_final, &mask);
if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) {
- if (!CustomData_has_layer(&me->ldata, CD_ORIGSPACE_MLOOP)) {
- CustomData_add_layer(&me->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, me->totloop);
- mesh_init_origspace(me);
+ if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
+ CustomData_add_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_CALLOC, NULL, mesh_final->totloop);
+ mesh_init_origspace(mesh_final);
}
}
- me_next = modwrap_applyModifier(md, &mectx_cache, me);
- ASSERT_IS_VALID_MESH(me_next);
+ Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final);
+ ASSERT_IS_VALID_MESH(mesh_next);
- if (me_next) {
- if (me && me != me_next) {
- BKE_id_free(NULL, me);
+ if (mesh_next) {
+ if (mesh_final && mesh_final != mesh_next) {
+ BKE_id_free(NULL, mesh_final);
}
- me = me_next;
+ mesh_final = mesh_next;
- if (deformedVerts) {
- MEM_freeN(deformedVerts);
- deformedVerts = NULL;
+ if (deformed_verts) {
+ MEM_freeN(deformed_verts);
+ deformed_verts = NULL;
}
- mesh_copy_autosmooth(me, ob->data);
+ mesh_copy_autosmooth(mesh_final, mesh_input);
}
- me->runtime.deformed_only = false;
+ mesh_final->runtime.deformed_only = false;
}
if (r_cage && i == cageIndex) {
- if (me && deformedVerts) {
- *r_cage = BKE_mesh_copy_for_eval(me, false);
- BKE_mesh_apply_vert_coords(*r_cage, deformedVerts);
+ if (mesh_final && deformed_verts) {
+ mesh_cage = BKE_mesh_copy_for_eval(mesh_final, false);
+ BKE_mesh_apply_vert_coords(mesh_cage, deformed_verts);
}
- else if (me) {
- *r_cage = me;
+ else if (mesh_final) {
+ mesh_cage = mesh_final;
}
else {
- Mesh *me_orig = ob->data;
+ Mesh *me_orig = mesh_input;
if (me_orig->id.tag & LIB_TAG_COPIED_ON_WRITE) {
BKE_mesh_runtime_ensure_edit_data(me_orig);
- me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformedVerts);
+ me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformed_verts);
}
- *r_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(
- em, &mask,
- deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
- mesh_copy_autosmooth(*r_cage, ob->data);
+ mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(
+ em_input, dataMask,
+ deformed_verts ? MEM_dupallocN(deformed_verts) : NULL);
+ mesh_copy_autosmooth(mesh_cage, mesh_input);
}
}
@@ -1729,22 +1782,20 @@ static void editbmesh_calc_modifiers(
/* Yay, we are done. If we have a DerivedMesh and deformed vertices need
* to apply these back onto the DerivedMesh. If we have no DerivedMesh
- * then we need to build one.
- */
- if (me && deformedVerts) {
- *r_final = BKE_mesh_copy_for_eval(me, false);
-
- if (!(r_cage && me == *r_cage)) {
- BKE_id_free(NULL, me);
+ * then we need to build one. */
+ if (mesh_final) {
+ if (deformed_verts) {
+ Mesh *mesh_tmp = BKE_mesh_copy_for_eval(mesh_final, false);
+ if (mesh_final != mesh_cage) {
+ BKE_id_free(NULL, mesh_final);
+ }
+ BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ mesh_final = mesh_tmp;
}
- BKE_mesh_apply_vert_coords(*r_final, deformedVerts);
}
- else if (me) {
- *r_final = me;
- }
- else if (!deformedVerts && r_cage && *r_cage) {
+ else if (!deformed_verts && mesh_cage) {
/* cage should already have up to date normals */
- *r_final = *r_cage;
+ mesh_final = mesh_cage;
/* In this case, we should never have weight-modifying modifiers in stack... */
if (do_init_statvis) {
@@ -1753,10 +1804,10 @@ static void editbmesh_calc_modifiers(
}
else {
/* this is just a copy of the editmesh, no need to calc normals */
- *r_final = BKE_mesh_from_editmesh_with_coords_thin_wrap(em, dataMask, deformedVerts);
- deformedVerts = NULL;
+ mesh_final = BKE_mesh_from_editmesh_with_coords_thin_wrap(em_input, dataMask, deformed_verts);
+ deformed_verts = NULL;
- mesh_copy_autosmooth(*r_final, ob->data);
+ mesh_copy_autosmooth(mesh_final, mesh_input);
/* In this case, we should never have weight-modifying modifiers in stack... */
if (do_init_statvis) {
@@ -1764,73 +1815,29 @@ static void editbmesh_calc_modifiers(
}
}
- if (do_loop_normals) {
- /* In case we also need poly normals, add the layer here, then BKE_mesh_calc_normals_split() will fill it. */
- if (do_poly_normals) {
- if (!CustomData_has_layer(&(*r_final)->pdata, CD_NORMAL)) {
- CustomData_add_layer(&(*r_final)->pdata, CD_NORMAL, CD_CALLOC, NULL, (*r_final)->totpoly);
- }
- if (r_cage && *r_cage && (*r_cage != *r_final)) {
- if (!CustomData_has_layer(&(*r_cage)->pdata, CD_NORMAL)) {
- CustomData_add_layer(&(*r_cage)->pdata, CD_NORMAL, CD_CALLOC, NULL, (*r_cage)->totpoly);
- }
- }
- }
- /* Compute loop normals */
- BKE_mesh_calc_normals_split(*r_final);
- BKE_mesh_tessface_clear(*r_final);
- if (r_cage && *r_cage && (*r_cage != *r_final)) {
- BKE_mesh_calc_normals_split(*r_cage);
- BKE_mesh_tessface_clear(*r_cage);
- }
+ if (deformed_verts) {
+ MEM_freeN(deformed_verts);
}
- /* BMESH_ONLY, ensure tessface's used for drawing,
- * but don't recalculate if the last modifier in the stack gives us tessfaces
- * check if the derived meshes are DM_TYPE_EDITBMESH before calling, this isn't essential
- * but quiets annoying error messages since tessfaces wont be created. */
- if (dataMask->fmask & CD_MASK_MFACE) {
- if ((*r_final)->edit_mesh == NULL) {
- BKE_mesh_tessface_ensure(*r_final);
- }
- if (r_cage && *r_cage) {
- if ((*r_cage)->edit_mesh == NULL) {
- if (*r_cage != *r_final) {
- BKE_mesh_tessface_ensure(*r_cage);
- }
- }
- }
+ /* Add orco coordinates to final and deformed mesh if requested. */
+ if (dataMask->vmask & CD_MASK_ORCO) {
+ add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
}
- /* --- */
-
- /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
- if (!do_loop_normals) {
- BKE_mesh_ensure_normals_for_display(*r_final);
-
- if (r_cage && *r_cage && (*r_cage != *r_final)) {
- BKE_mesh_ensure_normals_for_display(*r_cage);
- }
- /* Some modifiers, like datatransfer, may generate those data, we do not want to keep them,
- * as they are used by display code when available (i.e. even if autosmooth is disabled). */
- if (CustomData_has_layer(&(*r_final)->ldata, CD_NORMAL)) {
- CustomData_free_layers(&(*r_final)->ldata, CD_NORMAL, (*r_final)->totloop);
- }
- if (r_cage && CustomData_has_layer(&(*r_cage)->ldata, CD_NORMAL)) {
- CustomData_free_layers(&(*r_cage)->ldata, CD_NORMAL, (*r_cage)->totloop);
- }
+ if (mesh_orco) {
+ BKE_id_free(NULL, mesh_orco);
}
- /* add an orco layer if needed */
- if (dataMask->vmask & CD_MASK_ORCO)
- add_orco_mesh(ob, em, *r_final, me_orco, CD_ORCO);
-
- if (me_orco) {
- BKE_id_free(NULL, me_orco);
+ /* Compute normals. */
+ editbmesh_calc_modifier_final_normals(mesh_input, dataMask, mesh_final);
+ if (mesh_cage && (mesh_cage != mesh_final)) {
+ editbmesh_calc_modifier_final_normals(mesh_input, dataMask, mesh_cage);
}
- if (deformedVerts) {
- MEM_freeN(deformedVerts);
+ /* Return final mesh. */
+ *r_final = mesh_final;
+ if (r_cage) {
+ *r_cage = mesh_cage;
}
}