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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_editmesh_cache.h5
-rw-r--r--source/blender/blenkernel/BKE_mesh.h23
-rw-r--r--source/blender/blenkernel/BKE_modifier.h3
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c52
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c2
-rw-r--r--source/blender/blenkernel/intern/editmesh.c3
-rw-r--r--source/blender/blenkernel/intern/editmesh_cache.c44
-rw-r--r--source/blender/blenkernel/intern/mesh.c24
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c16
-rw-r--r--source/blender/blenkernel/intern/mesh_iterators.c272
-rw-r--r--source/blender/blenkernel/intern/mesh_wrapper.c165
-rw-r--r--source/blender/blenkernel/intern/modifier.c35
-rw-r--r--source/blender/blenkernel/intern/object.c3
-rw-r--r--source/blender/bmesh/intern/bmesh_query.c44
-rw-r--r--source/blender/bmesh/intern/bmesh_query.h10
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.c185
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c26
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c23
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h24
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c5
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c7
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c5
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c5
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c5
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c6
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c5
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c5
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c5
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c5
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c5
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c3
-rw-r--r--source/blender/modifiers/intern/MOD_util.c11
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c5
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c5
36 files changed, 861 insertions, 185 deletions
diff --git a/source/blender/blenkernel/BKE_editmesh_cache.h b/source/blender/blenkernel/BKE_editmesh_cache.h
index c6a2541e0a7..6c812098b2e 100644
--- a/source/blender/blenkernel/BKE_editmesh_cache.h
+++ b/source/blender/blenkernel/BKE_editmesh_cache.h
@@ -33,6 +33,11 @@ void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, struct EditMe
void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, struct EditMeshData *emd);
+bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em,
+ struct EditMeshData *emd,
+ float min[3],
+ float max[3]);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index f14b9a30d99..52d458c108d 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -85,12 +85,6 @@ struct Mesh *BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm,
const struct CustomData_MeshMasks *cd_mask_extra,
const struct Mesh *me_settings);
-struct Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(
- struct BMEditMesh *em,
- const struct CustomData_MeshMasks *cd_mask_extra,
- float (*vertexCos)[3],
- const struct Mesh *me_settings);
-
int poly_find_loop_from_vert(const struct MPoly *poly, const struct MLoop *loopstart, uint vert);
int poly_get_adj_loops_from_vert(const struct MPoly *poly,
const struct MLoop *mloop,
@@ -673,6 +667,23 @@ void BKE_mesh_calc_edges_loose(struct Mesh *mesh);
void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select);
void BKE_mesh_calc_edges_tessface(struct Mesh *mesh);
+/* *** mesh_geomtype.c *** */
+struct Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(
+ struct BMEditMesh *em,
+ const struct CustomData_MeshMasks *cd_mask_extra,
+ float (*vertexCos)[3],
+ const struct Mesh *me_settings);
+struct Mesh *BKE_mesh_wrapper_from_editmesh(struct BMEditMesh *em,
+ const struct CustomData_MeshMasks *cd_mask_extra,
+ const struct Mesh *me_settings);
+void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me);
+bool BKE_mesh_wrapper_minmax(const struct Mesh *me, float min[3], float max[3]);
+void BKE_mesh_wrapper_normals_update(struct Mesh *me);
+
+/* In DerivedMesh.c */
+void BKE_mesh_wrapper_deferred_finalize(struct Mesh *me_eval,
+ const CustomData_MeshMasks *final_datamask);
+
/* **** Depsgraph evaluation **** */
void BKE_mesh_eval_geometry(struct Depsgraph *depsgraph, struct Mesh *mesh);
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 58c0b6b71e0..a7bf345567f 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -101,6 +101,9 @@ typedef enum {
/* For modifiers that use CD_PREVIEW_MCOL for preview. */
eModifierTypeFlag_UsesPreview = (1 << 9),
eModifierTypeFlag_AcceptsVertexCosOnly = (1 << 10),
+
+ /** Accepts #BMesh input (without conversion). */
+ eModifierTypeFlag_AcceptsBMesh = (1 << 11),
} ModifierTypeFlag;
/* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 220bafa2187..817fe849eab 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -168,6 +168,7 @@ set(SRC
intern/mesh_runtime.c
intern/mesh_tangent.c
intern/mesh_validate.c
+ intern/mesh_wrapper.c
intern/modifier.c
intern/movieclip.c
intern/multires.c
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 52fe51afcb2..8f820a873fe 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -90,6 +90,8 @@
static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER;
static void mesh_init_origspace(Mesh *mesh);
+static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
+ const CustomData_MeshMasks *final_datamask);
/* -------------------------------------------------------------------- */
@@ -861,6 +863,16 @@ static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval)
mesh_eval->edit_mesh = mesh_input->edit_mesh;
}
+void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval,
+ const CustomData_MeshMasks *cd_mask_finalize)
+{
+ if (me_eval->runtime.wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) {
+ editbmesh_calc_modifier_final_normals(me_eval, cd_mask_finalize);
+ me_eval->runtime.wrapper_type_finalize &= ~(1 << ME_WRAPPER_TYPE_BMESH);
+ }
+ BLI_assert(me_eval->runtime.wrapper_type_finalize == 0);
+}
+
static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -1391,11 +1403,16 @@ 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 *final_datamask,
- Mesh *mesh_final)
+static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
+ const CustomData_MeshMasks *final_datamask)
{
- const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
+ if (mesh_final->runtime.wrapper_type != ME_WRAPPER_TYPE_MDATA) {
+ /* Generated at draw time. */
+ mesh_final->runtime.wrapper_type_finalize = (1 << mesh_final->runtime.wrapper_type);
+ return;
+ }
+
+ const bool do_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 ||
(final_datamask->lmask & CD_MASK_NORMAL) != 0);
/* Some modifiers may need this info from their target (other) object,
* simpler to generate it here as well. */
@@ -1501,7 +1518,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* Evaluate modifiers up to certain index to get the mesh cage. */
int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1);
if (r_cage && cageIndex == -1) {
- mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(
+ mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input, &final_datamask, NULL, mesh_input);
}
@@ -1574,12 +1591,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
}
}
else {
- mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL, mesh_input);
- ASSERT_IS_VALID_MESH(mesh_final);
-
- if (deformed_verts) {
- BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
- }
+ mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords(
+ em_input, NULL, deformed_verts, mesh_input);
+ deformed_verts = NULL;
}
/* create an orco derivedmesh in parallel */
@@ -1657,7 +1671,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
BKE_mesh_runtime_ensure_edit_data(me_orig);
me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformed_verts);
}
- mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap(
+ mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input,
&final_datamask,
deformed_verts ? MEM_dupallocN(deformed_verts) : NULL,
@@ -1689,7 +1703,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
}
else {
/* this is just a copy of the editmesh, no need to calc normals */
- mesh_final = BKE_mesh_from_editmesh_with_coords_thin_wrap(
+ mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input, &final_datamask, deformed_verts, mesh_input);
deformed_verts = NULL;
}
@@ -1700,6 +1714,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* Add orco coordinates to final and deformed mesh if requested. */
if (final_datamask.vmask & CD_MASK_ORCO) {
+ /* FIXME(Campbell): avoid the need to convert to mesh data just to add an orco layer. */
+ BKE_mesh_wrapper_ensure_mdata(mesh_final);
+
add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);
}
@@ -1707,10 +1724,15 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
BKE_id_free(NULL, mesh_orco);
}
+ /* Ensure normals calculation below is correct. */
+ BLI_assert((mesh_input->flag & ME_AUTOSMOOTH) == (mesh_final->flag & ME_AUTOSMOOTH));
+ BLI_assert(mesh_input->smoothresh == mesh_final->smoothresh);
+ BLI_assert(mesh_input->smoothresh == mesh_cage->smoothresh);
+
/* Compute normals. */
- editbmesh_calc_modifier_final_normals(mesh_input, &final_datamask, mesh_final);
+ editbmesh_calc_modifier_final_normals(mesh_final, &final_datamask);
if (mesh_cage && (mesh_cage != mesh_final)) {
- editbmesh_calc_modifier_final_normals(mesh_input, &final_datamask, mesh_cage);
+ editbmesh_calc_modifier_final_normals(mesh_cage, &final_datamask);
}
/* Return final mesh. */
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index f4acbdca772..6c8438e478e 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -293,7 +293,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
cd_mask_extra = datamasks->mask;
BLI_linklist_free((LinkNode *)datamasks, NULL);
- me = BKE_mesh_from_editmesh_with_coords_thin_wrap(em, &cd_mask_extra, NULL, me_input);
+ me = BKE_mesh_wrapper_from_editmesh_with_coords(em, &cd_mask_extra, NULL, me_input);
deformedVerts = editbmesh_vert_coords_alloc(em, &numVerts);
defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats");
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 5aaae74e670..c4160d6d253 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -32,6 +32,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_iterators.h"
@@ -266,7 +267,7 @@ BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em)
float min[3], max[3];
INIT_MINMAX(min, max);
if (em->mesh_eval_cage) {
- BKE_mesh_minmax(em->mesh_eval_cage, min, max);
+ BKE_mesh_wrapper_minmax(em->mesh_eval_cage, min, max);
}
em->bb_cage = MEM_callocN(sizeof(BoundBox), "BMEditMesh.bb_cage");
diff --git a/source/blender/blenkernel/intern/editmesh_cache.c b/source/blender/blenkernel/intern/editmesh_cache.c
index 8d3f1e84bcd..5017a48d14e 100644
--- a/source/blender/blenkernel/intern/editmesh_cache.c
+++ b/source/blender/blenkernel/intern/editmesh_cache.c
@@ -22,11 +22,17 @@
#include "MEM_guardedalloc.h"
+#include "BLI_math_vector.h"
+
#include "DNA_mesh_types.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h" /* own include */
+/* -------------------------------------------------------------------- */
+/** \name Ensure Data (derived from coords)
+ * \{ */
+
void BKE_editmesh_cache_ensure_poly_normals(BMEditMesh *em, EditMeshData *emd)
{
if (!(emd->vertexCos && (emd->polyNos == NULL))) {
@@ -112,3 +118,41 @@ void BKE_editmesh_cache_ensure_poly_centers(BMEditMesh *em, EditMeshData *emd)
emd->polyCos = (const float(*)[3])polyCos;
}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Calculate Min/Max
+ * \{ */
+
+bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em,
+ struct EditMeshData *emd,
+ float min[3],
+ float max[3])
+{
+ BMesh *bm = em->bm;
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ if (bm->totvert) {
+ if (emd->vertexCos) {
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ minmax_v3v3_v3(min, max, emd->vertexCos[i]);
+ }
+ }
+ else {
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(min, max, eve->co);
+ }
+ }
+ return true;
+ }
+ else {
+ zero_v3(min);
+ zero_v3(max);
+ return false;
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index aeef287bb87..0d20d25f84c 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -866,26 +866,6 @@ Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm,
return mesh;
}
-/**
- * TODO(campbell): support mesh with only an edit-mesh which is lazy initialized.
- */
-Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(BMEditMesh *em,
- const CustomData_MeshMasks *cd_mask_extra,
- float (*vertexCos)[3],
- const Mesh *me_settings)
-{
- Mesh *me = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, cd_mask_extra, me_settings);
- /* Use editmesh directly where possible. */
- me->runtime.is_original = true;
- if (vertexCos) {
- /* We will own this array in the future. */
- BKE_mesh_vert_coords_apply(me, vertexCos);
- MEM_freeN(vertexCos);
- me->runtime.is_original = false;
- }
- return me;
-}
-
BoundBox *BKE_mesh_boundbox_get(Object *ob)
{
/* This is Object-level data access,
@@ -895,7 +875,7 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob)
float min[3], max[3];
INIT_MINMAX(min, max);
- if (!BKE_mesh_minmax(me, min, max)) {
+ if (!BKE_mesh_wrapper_minmax(me, min, max)) {
min[0] = min[1] = min[2] = -1.0f;
max[0] = max[1] = max[2] = 1.0f;
}
@@ -916,7 +896,7 @@ void BKE_mesh_texspace_calc(Mesh *me)
float min[3], max[3];
INIT_MINMAX(min, max);
- if (!BKE_mesh_minmax(me, min, max)) {
+ if (!BKE_mesh_wrapper_minmax(me, min, max)) {
min[0] = min[1] = min[2] = -1.0f;
max[0] = max[1] = max[2] = 1.0f;
}
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 655c70bcf61..f2c84028570 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -1076,6 +1076,10 @@ static Mesh *mesh_new_from_mball_object(Object *object)
static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
{
+ /* While we could copy this into the new mesh,
+ * add the data to 'mesh' so future calls to this function don't need to re-convert the data. */
+ BKE_mesh_wrapper_ensure_mdata(mesh);
+
Mesh *mesh_result = NULL;
BKE_id_copy_ex(NULL,
&mesh->id,
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index f0d19f01aab..433db26ded8 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -46,6 +46,7 @@
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_multires.h"
@@ -396,6 +397,21 @@ void BKE_mesh_ensure_normals(Mesh *mesh)
*/
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
{
+ switch ((eMeshWrapperType)mesh->runtime.wrapper_type) {
+ case ME_WRAPPER_TYPE_MDATA:
+ /* Run code below. */
+ break;
+ case ME_WRAPPER_TYPE_BMESH: {
+ struct BMEditMesh *em = mesh->edit_mesh;
+ EditMeshData *emd = mesh->runtime.edit_data;
+ if (emd->vertexCos) {
+ BKE_editmesh_cache_ensure_vert_normals(em, emd);
+ BKE_editmesh_cache_ensure_poly_normals(em, emd);
+ }
+ return;
+ }
+ }
+
float(*poly_nors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
const bool do_vert_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) != 0;
const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL || poly_nors == NULL);
diff --git a/source/blender/blenkernel/intern/mesh_iterators.c b/source/blender/blenkernel/intern/mesh_iterators.c
index f2ed9456b11..5ecf5ae316d 100644
--- a/source/blender/blenkernel/intern/mesh_iterators.c
+++ b/source/blender/blenkernel/intern/mesh_iterators.c
@@ -24,6 +24,8 @@
#include "DNA_meshdata_types.h"
#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_mesh.h"
#include "BKE_mesh_iterators.h"
@@ -42,23 +44,53 @@ void BKE_mesh_foreach_mapped_vert(Mesh *mesh,
void *userData,
MeshForeachFlag flag)
{
- const MVert *mv = mesh->mvert;
- const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
-
- if (index) {
- for (int i = 0; i < mesh->totvert; i++, mv++) {
- const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
- const int orig = *index++;
- if (orig == ORIGINDEX_NONE) {
- continue;
+ if (mesh->edit_mesh != NULL) {
+ BMEditMesh *em = mesh->edit_mesh;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMVert *eve;
+ int i;
+ if (mesh->runtime.edit_data->vertexCos != NULL) {
+ const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
+ const float(*vertexNos)[3];
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ BKE_editmesh_cache_ensure_vert_normals(em, mesh->runtime.edit_data);
+ vertexNos = mesh->runtime.edit_data->vertexNos;
+ }
+ else {
+ vertexNos = NULL;
+ }
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL;
+ func(userData, i, vertexCos[i], no, NULL);
+ }
+ }
+ else {
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? eve->no : NULL;
+ func(userData, i, eve->co, no, NULL);
}
- func(userData, orig, mv->co, NULL, no);
}
}
else {
- for (int i = 0; i < mesh->totvert; i++, mv++) {
- const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
- func(userData, i, mv->co, NULL, no);
+ const MVert *mv = mesh->mvert;
+ const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
+
+ if (index) {
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
+ const int orig = *index++;
+ if (orig == ORIGINDEX_NONE) {
+ continue;
+ }
+ func(userData, orig, mv->co, NULL, no);
+ }
+ }
+ else {
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
+ func(userData, i, mv->co, NULL, no);
+ }
}
}
}
@@ -69,22 +101,47 @@ void BKE_mesh_foreach_mapped_edge(
void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
void *userData)
{
- const MVert *mv = mesh->mvert;
- const MEdge *med = mesh->medge;
- const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX);
+ if (mesh->edit_mesh != NULL) {
+ BMEditMesh *em = mesh->edit_mesh;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMEdge *eed;
+ int i;
+ if (mesh->runtime.edit_data->vertexCos != NULL) {
+ const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
- if (index) {
- for (int i = 0; i < mesh->totedge; i++, med++) {
- const int orig = *index++;
- if (orig == ORIGINDEX_NONE) {
- continue;
+ BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
+ func(userData,
+ i,
+ vertexCos[BM_elem_index_get(eed->v1)],
+ vertexCos[BM_elem_index_get(eed->v2)]);
+ }
+ }
+ else {
+ BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
+ func(userData, i, eed->v1->co, eed->v2->co);
}
- func(userData, orig, mv[med->v1].co, mv[med->v2].co);
}
}
else {
- for (int i = 0; i < mesh->totedge; i++, med++) {
- func(userData, i, mv[med->v1].co, mv[med->v2].co);
+ const MVert *mv = mesh->mvert;
+ const MEdge *med = mesh->medge;
+ const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX);
+
+ if (index) {
+ for (int i = 0; i < mesh->totedge; i++, med++) {
+ const int orig = *index++;
+ if (orig == ORIGINDEX_NONE) {
+ continue;
+ }
+ func(userData, orig, mv[med->v1].co, mv[med->v2].co);
+ }
+ }
+ else {
+ for (int i = 0; i < mesh->totedge; i++, med++) {
+ func(userData, i, mv[med->v1].co, mv[med->v2].co);
+ }
}
}
}
@@ -99,40 +156,72 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
void *userData,
MeshForeachFlag flag)
{
+
/* We can't use dm->getLoopDataLayout(dm) here,
* we want to always access dm->loopData, EditDerivedBMesh would
* return loop data from bmesh itself. */
- const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
- CustomData_get_layer(&mesh->ldata, CD_NORMAL) :
- NULL;
+ if (mesh->edit_mesh != NULL) {
+ BMEditMesh *em = mesh->edit_mesh;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMFace *efa;
- const MVert *mv = mesh->mvert;
- const MLoop *ml = mesh->mloop;
- const MPoly *mp = mesh->mpoly;
- const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
- const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
- int p_idx, i;
-
- if (v_index || f_index) {
- for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
- for (i = 0; i < mp->totloop; i++, ml++) {
- const int v_idx = v_index ? v_index[ml->v] : ml->v;
- const int f_idx = f_index ? f_index[p_idx] : p_idx;
+ const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
+
+ /* XXX: investigate using EditMesh data. */
+ const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
+ CustomData_get_layer(&mesh->ldata, CD_NORMAL) :
+ NULL;
+
+ int f_idx;
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, f_idx) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ const BMVert *eve = l_iter->v;
+ const int v_idx = BM_elem_index_get(eve);
const float *no = lnors ? *lnors++ : NULL;
- if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
- continue;
- }
- func(userData, v_idx, f_idx, mv[ml->v].co, no);
- }
+ func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no);
+ } while ((l_iter = l_iter->next) != l_first);
}
}
else {
- for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
- for (i = 0; i < mp->totloop; i++, ml++) {
- const int v_idx = ml->v;
- const int f_idx = p_idx;
- const float *no = lnors ? *lnors++ : NULL;
- func(userData, v_idx, f_idx, mv[ml->v].co, no);
+ const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
+ CustomData_get_layer(&mesh->ldata, CD_NORMAL) :
+ NULL;
+
+ const MVert *mv = mesh->mvert;
+ const MLoop *ml = mesh->mloop;
+ const MPoly *mp = mesh->mpoly;
+ const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
+ const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
+ int p_idx, i;
+
+ if (v_index || f_index) {
+ for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
+ for (i = 0; i < mp->totloop; i++, ml++) {
+ const int v_idx = v_index ? v_index[ml->v] : ml->v;
+ const int f_idx = f_index ? f_index[p_idx] : p_idx;
+ const float *no = lnors ? *lnors++ : NULL;
+ if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
+ continue;
+ }
+ func(userData, v_idx, f_idx, mv[ml->v].co, no);
+ }
+ }
+ }
+ else {
+ for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
+ for (i = 0; i < mp->totloop; i++, ml++) {
+ const int v_idx = ml->v;
+ const int f_idx = p_idx;
+ const float *no = lnors ? *lnors++ : NULL;
+ func(userData, v_idx, f_idx, mv[ml->v].co, no);
+ }
}
}
}
@@ -145,37 +234,72 @@ void BKE_mesh_foreach_mapped_face_center(
void *userData,
MeshForeachFlag flag)
{
- const MVert *mvert = mesh->mvert;
- const MPoly *mp = mesh->mpoly;
- const MLoop *ml;
- float _no_buf[3];
- float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
- const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
+ if (mesh->edit_mesh != NULL) {
+ BMEditMesh *em = mesh->edit_mesh;
+ BMesh *bm = em->bm;
+ const float(*polyCos)[3];
+ const float(*polyNos)[3];
+ BMFace *efa;
+ BMIter iter;
+ int i;
- if (index) {
- for (int i = 0; i < mesh->totpoly; i++, mp++) {
- const int orig = *index++;
- if (orig == ORIGINDEX_NONE) {
- continue;
+ BKE_editmesh_cache_ensure_poly_centers(em, mesh->runtime.edit_data);
+ polyCos = mesh->runtime.edit_data->polyCos; /* always set */
+
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ BKE_editmesh_cache_ensure_poly_normals(em, mesh->runtime.edit_data);
+ polyNos = mesh->runtime.edit_data->polyNos; /* maybe NULL */
+ }
+ else {
+ polyNos = NULL;
+ }
+
+ if (polyNos) {
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
+ const float *no = polyNos[i];
+ func(userData, i, polyCos[i], no);
}
- float cent[3];
- ml = &mesh->mloop[mp->loopstart];
- BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
- if (flag & MESH_FOREACH_USE_NORMAL) {
- BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
+ }
+ else {
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
+ const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? efa->no : NULL;
+ func(userData, i, polyCos[i], no);
}
- func(userData, orig, cent, no);
}
}
else {
- for (int i = 0; i < mesh->totpoly; i++, mp++) {
- float cent[3];
- ml = &mesh->mloop[mp->loopstart];
- BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
- if (flag & MESH_FOREACH_USE_NORMAL) {
- BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
+ const MVert *mvert = mesh->mvert;
+ const MPoly *mp = mesh->mpoly;
+ const MLoop *ml;
+ float _no_buf[3];
+ float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
+ const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
+
+ if (index) {
+ for (int i = 0; i < mesh->totpoly; i++, mp++) {
+ const int orig = *index++;
+ if (orig == ORIGINDEX_NONE) {
+ continue;
+ }
+ float cent[3];
+ ml = &mesh->mloop[mp->loopstart];
+ BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
+ }
+ func(userData, orig, cent, no);
+ }
+ }
+ else {
+ for (int i = 0; i < mesh->totpoly; i++, mp++) {
+ float cent[3];
+ ml = &mesh->mloop[mp->loopstart];
+ BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
+ }
+ func(userData, i, cent, no);
}
- func(userData, i, cent, no);
}
}
}
diff --git a/source/blender/blenkernel/intern/mesh_wrapper.c b/source/blender/blenkernel/intern/mesh_wrapper.c
new file mode 100644
index 00000000000..fc65be1dd56
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_wrapper.c
@@ -0,0 +1,165 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * The primary purpose of this API is to avoid unnecessary mesh conversion for the final
+ * output of a modified mesh.
+ *
+ * This API handles the case when the modifier stack outputs a mesh which does not have
+ * #Mesh data (#MPoly, #MLoop, #MEdge, #MVert).
+ * Currently this is used so the resulting mesh can have #BMEditMesh data,
+ * postponing the converting until it's needed or avoiding conversion entirely
+ * which can be an expensive operation.
+ * Once converted, the meshes type changes to #ME_WRAPPER_TYPE_MDATA,
+ * although the edit mesh is not cleared.
+ *
+ * This API exposes functions that abstract over the different kinds of internal data,
+ * as well as supporting converting the mesh into regular mesh.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_defaults.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_edgehash.h"
+#include "BLI_ghash.h"
+#include "BLI_hash.h"
+#include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_animsys.h"
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
+#include "BKE_global.h"
+#include "BKE_idtype.h"
+#include "BKE_key.h"
+#include "BKE_lib_id.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_modifier.h"
+#include "BKE_multires.h"
+#include "BKE_object.h"
+
+#include "PIL_time.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
+ const CustomData_MeshMasks *cd_mask_extra,
+ float (*vertexCos)[3],
+ const Mesh *me_settings)
+{
+ Mesh *me = BKE_id_new_nomain(ID_ME, NULL);
+ BKE_mesh_copy_settings(me, me_settings);
+ BKE_mesh_runtime_ensure_edit_data(me);
+
+ me->runtime.wrapper_type = ME_WRAPPER_TYPE_BMESH;
+ if (cd_mask_extra) {
+ me->runtime.cd_mask_extra = *cd_mask_extra;
+ }
+
+ /* Use edit-mesh directly where possible. */
+ me->runtime.is_original = true;
+ me->edit_mesh = MEM_dupallocN(em);
+
+/* Make sure, we crash if these are ever used. */
+#ifdef DEBUG
+ me->totvert = INT_MAX;
+ me->totedge = INT_MAX;
+ me->totpoly = INT_MAX;
+ me->totloop = INT_MAX;
+#else
+ me->totvert = 0;
+ me->totedge = 0;
+ me->totpoly = 0;
+ me->totloop = 0;
+#endif
+
+ EditMeshData *edit_data = me->runtime.edit_data;
+ edit_data->vertexCos = vertexCos;
+ return me;
+}
+
+Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
+ const CustomData_MeshMasks *cd_mask_extra,
+ const Mesh *me_settings)
+{
+ return BKE_mesh_wrapper_from_editmesh_with_coords(em, cd_mask_extra, NULL, me_settings);
+}
+
+void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
+{
+ if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
+ return;
+ }
+ const eMeshWrapperType geom_type_orig = me->runtime.wrapper_type;
+ me->runtime.wrapper_type = ME_WRAPPER_TYPE_MDATA;
+
+ switch (geom_type_orig) {
+ case ME_WRAPPER_TYPE_MDATA: {
+ break; /* Quiet warning. */
+ }
+ case ME_WRAPPER_TYPE_BMESH: {
+ me->totvert = 0;
+ me->totedge = 0;
+ me->totpoly = 0;
+ me->totloop = 0;
+
+ BLI_assert(me->edit_mesh != NULL);
+ BLI_assert(me->runtime.edit_data != NULL);
+
+ BMEditMesh *em = me->edit_mesh;
+ BM_mesh_bm_to_me_for_eval(em->bm, me, &me->runtime.cd_mask_extra);
+
+ EditMeshData *edit_data = me->runtime.edit_data;
+ if (edit_data->vertexCos) {
+ BKE_mesh_vert_coords_apply(me, edit_data->vertexCos);
+ me->runtime.is_original = false;
+ }
+ break;
+ }
+ }
+
+ if (me->runtime.wrapper_type_finalize) {
+ BKE_mesh_wrapper_deferred_finalize(me, &me->runtime.cd_mask_extra);
+ }
+}
+
+bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3])
+{
+ switch ((eMeshWrapperType)me->runtime.wrapper_type) {
+ case ME_WRAPPER_TYPE_BMESH:
+ return BKE_editmesh_cache_calc_minmax(me->edit_mesh, me->runtime.edit_data, min, max);
+ case ME_WRAPPER_TYPE_MDATA:
+ return BKE_mesh_minmax(me, min, max);
+ }
+ BLI_assert(0);
+}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 305acf3a377..6b54a530034 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -50,6 +50,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_appdir.h"
#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_global.h"
#include "BKE_idtype.h"
#include "BKE_key.h"
@@ -934,6 +935,30 @@ void BKE_modifier_path_init(char *path, int path_maxlen, const char *name)
BLI_join_dirfile(path, path_maxlen, G.relbase_valid ? "//" : BKE_tempdir_session(), name);
}
+/**
+ * Call when #ModifierTypeInfo.dependsOnNormals callback requests normals.
+ */
+static void modwrap_dependsOnNormals(Mesh *me)
+{
+ switch ((eMeshWrapperType)me->runtime.wrapper_type) {
+ case ME_WRAPPER_TYPE_BMESH: {
+ EditMeshData *edit_data = me->runtime.edit_data;
+ if (edit_data->vertexCos) {
+ /* Note that 'ensure' is acceptable here since these values aren't modified in-place.
+ * If that changes we'll need to recalculate. */
+ BKE_editmesh_cache_ensure_vert_normals(me->edit_mesh, edit_data);
+ }
+ else {
+ BM_mesh_normals_update(me->edit_mesh->bm);
+ }
+ break;
+ }
+ case ME_WRAPPER_TYPE_MDATA:
+ BKE_mesh_calc_normals(me);
+ break;
+ }
+}
+
/* wrapper around ModifierTypeInfo.modifyMesh that ensures valid normals */
struct Mesh *BKE_modifier_modify_mesh(ModifierData *md,
@@ -943,8 +968,14 @@ struct Mesh *BKE_modifier_modify_mesh(ModifierData *md,
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
BLI_assert(CustomData_has_layer(&me->pdata, CD_NORMAL) == false);
+ if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
+ if ((mti->flags & eModifierTypeFlag_AcceptsBMesh) == 0) {
+ BKE_mesh_wrapper_ensure_mdata(me);
+ }
+ }
+
if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
- BKE_mesh_calc_normals(me);
+ modwrap_dependsOnNormals(me);
}
return mti->modifyMesh(md, ctx, me);
}
@@ -959,7 +990,7 @@ void BKE_modifier_deform_verts(ModifierData *md,
BLI_assert(!me || CustomData_has_layer(&me->pdata, CD_NORMAL) == false);
if (me && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
- BKE_mesh_calc_normals(me);
+ modwrap_dependsOnNormals(me);
}
mti->deformVerts(md, ctx, me, vertexCos, numVerts);
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index d17575195e3..3e2629f8272 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -81,6 +81,7 @@
#include "BKE_displist.h"
#include "BKE_duplilist.h"
#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_fcurve_driver.h"
@@ -3089,7 +3090,7 @@ void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval)
INIT_MINMAX(min, max);
- if (!BKE_mesh_minmax(me_eval, min, max)) {
+ if (!BKE_mesh_wrapper_minmax(me_eval, min, max)) {
zero_v3(min);
zero_v3(max);
}
diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c
index 64950411fed..e000b253000 100644
--- a/source/blender/bmesh/intern/bmesh_query.c
+++ b/source/blender/bmesh/intern/bmesh_query.c
@@ -1568,6 +1568,41 @@ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq,
}
/**
+ * A version of BM_loop_calc_face_normal_safe_ex which takes vertex coordinates.
+ */
+float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l,
+ const float normal_fallback[3],
+ float const (*vertexCos)[3],
+ const float epsilon_sq,
+ float r_normal[3])
+{
+ const int i_prev = BM_elem_index_get(l->prev->v);
+ const int i_next = BM_elem_index_get(l->next->v);
+ const int i = BM_elem_index_get(l->v);
+
+ float v1[3], v2[3], v_tmp[3];
+ sub_v3_v3v3(v1, vertexCos[i_prev], vertexCos[i]);
+ sub_v3_v3v3(v2, vertexCos[i_next], vertexCos[i]);
+
+ const float fac = ((v2[0] == 0.0f) ?
+ ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) :
+ v1[1] / v2[1]) :
+ v1[0] / v2[0]);
+
+ mul_v3_v3fl(v_tmp, v2, fac);
+ sub_v3_v3(v_tmp, v1);
+ if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) {
+ /* Not co-linear, we can compute cross-product and normalize it into normal. */
+ cross_v3_v3v3(r_normal, v1, v2);
+ return normalize_v3(r_normal);
+ }
+ else {
+ copy_v3_v3(r_normal, normal_fallback);
+ return 0.0f;
+ }
+}
+
+/**
* #BM_loop_calc_face_normal_safe_ex with pre-defined sane epsilon.
*
* Since this doesn't scale based on triangle size, fixed value works well.
@@ -1577,6 +1612,15 @@ float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal);
}
+float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l,
+ const float normal_fallback[3],
+ float const (*vertexCos)[3],
+ float r_normal[3])
+
+{
+ return BM_loop_calc_face_normal_safe_vcos_ex(l, normal_fallback, vertexCos, 1e-5f, r_normal);
+}
+
/**
* \brief BM_loop_calc_face_normal
*
diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h
index aaf8191c5db..7e07059d4d8 100644
--- a/source/blender/bmesh/intern/bmesh_query.h
+++ b/source/blender/bmesh/intern/bmesh_query.h
@@ -142,6 +142,16 @@ float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(
float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3])
ATTR_NONNULL();
+float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l,
+ const float normal_fallback[3],
+ float const (*vertexCos)[3],
+ const float epsilon_sq,
+ float r_normal[3]) ATTR_NONNULL();
+float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l,
+ const float normal_fallback[3],
+ float const (*vertexCos)[3],
+ float r_normal[3]) ATTR_NONNULL();
+
void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]);
void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index 401f5c76a02..cbb5f5f06ff 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -105,6 +105,14 @@ typedef struct MeshRenderData {
BMEditMesh *edit_bmesh;
BMesh *bm;
EditMeshData *edit_data;
+
+ /* For deformed edit-mesh data. */
+ /* Use for #ME_WRAPPER_TYPE_BMESH. */
+ const float (*bm_vert_coords)[3];
+ const float (*bm_vert_normals)[3];
+ const float (*bm_poly_normals)[3];
+ const float (*bm_poly_centers)[3];
+
int *v_origindex, *e_origindex, *p_origindex;
int crease_ofs;
int bweight_ofs;
@@ -151,9 +159,24 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final);
mr->bm = me->edit_mesh->bm;
mr->edit_bmesh = me->edit_mesh;
- mr->edit_data = me->runtime.edit_data;
mr->me = (do_final) ? me->edit_mesh->mesh_eval_final : me->edit_mesh->mesh_eval_cage;
- bool use_mapped = !do_uvedit && mr->me && !mr->me->runtime.is_original;
+ mr->edit_data = mr->me->runtime.edit_data;
+
+ if (mr->edit_data) {
+ EditMeshData *emd = mr->edit_data;
+ if (emd->vertexCos) {
+ BKE_editmesh_cache_ensure_vert_normals(mr->edit_bmesh, emd);
+ BKE_editmesh_cache_ensure_poly_normals(mr->edit_bmesh, emd);
+ }
+
+ mr->bm_vert_coords = mr->edit_data->vertexCos;
+ mr->bm_vert_normals = mr->edit_data->vertexNos;
+ mr->bm_poly_normals = mr->edit_data->polyNos;
+ mr->bm_poly_centers = mr->edit_data->polyCos;
+ }
+
+ bool has_mdata = (mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA);
+ bool use_mapped = has_mdata && !do_uvedit && mr->me && !mr->me->runtime.is_original;
int bm_ensure_types = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE;
@@ -184,7 +207,7 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
/* Seems like the mesh_eval_final do not have the right origin indices.
* Force not mapped in this case. */
- if (do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) {
+ if (has_mdata && do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) {
// mr->edit_bmesh = NULL;
mr->extract_type = MR_EXTRACT_MESH;
}
@@ -311,12 +334,23 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
/* Use bmface->no instead. */
}
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
+
+ const float(*vert_coords)[3] = NULL;
+ const float(*vert_normals)[3] = NULL;
+ const float(*poly_normals)[3] = NULL;
+
+ if (mr->edit_data && mr->edit_data->vertexCos) {
+ vert_coords = mr->bm_vert_coords;
+ vert_normals = mr->bm_vert_normals;
+ poly_normals = mr->bm_poly_normals;
+ }
+
mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(mr->bm,
- NULL,
- NULL,
- NULL,
+ vert_coords,
+ vert_normals,
+ poly_normals,
is_auto_smooth,
split_angle,
mr->loop_normals,
@@ -396,6 +430,42 @@ BLI_INLINE BMVert *bm_original_vert_get(const MeshRenderData *mr, int idx)
NULL;
}
+BLI_INLINE const float *bm_vert_co_get(const MeshRenderData *mr, const BMVert *eve)
+{
+ const float(*vert_coords)[3] = mr->bm_vert_coords;
+ if (vert_coords != NULL) {
+ return vert_coords[BM_elem_index_get(eve)];
+ }
+ else {
+ UNUSED_VARS(mr);
+ return eve->co;
+ }
+}
+
+BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *eve)
+{
+ const float(*vert_normals)[3] = mr->bm_vert_normals;
+ if (vert_normals != NULL) {
+ return vert_normals[BM_elem_index_get(eve)];
+ }
+ else {
+ UNUSED_VARS(mr);
+ return eve->co;
+ }
+}
+
+BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *efa)
+{
+ const float(*poly_normals)[3] = mr->bm_poly_normals;
+ if (poly_normals != NULL) {
+ return poly_normals[BM_elem_index_get(efa)];
+ }
+ else {
+ UNUSED_VARS(mr);
+ return efa->no;
+ }
+}
+
/** \} */
/* ---------------------------------------------------------------------- */
@@ -1480,7 +1550,7 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf)
BMVert *eve;
int v;
BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) {
- data->packed_nor[v] = GPU_normal_convert_i10_v3(eve->no);
+ data->packed_nor[v] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve));
}
}
else {
@@ -1492,14 +1562,11 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_pos_nor_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *_data)
+static void extract_pos_nor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
{
MeshExtract_PosNor_Data *data = _data;
PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert->pos, loop->v->co);
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, loop->v));
vert->nor = data->packed_nor[BM_elem_index_get(loop->v)];
BMFace *efa = loop->f;
vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
@@ -1536,8 +1603,8 @@ static void extract_pos_nor_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge
int l = mr->loop_len + e * 2;
MeshExtract_PosNor_Data *data = _data;
PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert[0].pos, eed->v1->co);
- copy_v3_v3(vert[1].pos, eed->v2->co);
+ copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
+ copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)];
vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)];
}
@@ -1561,7 +1628,7 @@ static void extract_pos_nor_lvert_bmesh(const MeshRenderData *mr, int v, BMVert
int l = mr->loop_len + mr->edge_loose_len * 2 + v;
MeshExtract_PosNor_Data *data = _data;
PosNorLoop *vert = data->vbo_data + l;
- copy_v3_v3(vert->pos, eve->co);
+ copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
vert->nor = data->packed_nor[BM_elem_index_get(eve)];
}
@@ -1627,10 +1694,10 @@ static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *
normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]);
}
else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, loop->v->no);
+ normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_vert_no_get(mr, loop->v));
}
else {
- normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, loop->f->no);
+ normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_face_no_get(mr, loop->f));
}
}
@@ -1704,10 +1771,10 @@ static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loo
((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
}
else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(loop->v->no);
+ ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, loop->v));
}
else {
- ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(loop->f->no);
+ ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, loop->f));
}
BMFace *efa = loop->f;
((GPUPackedNormal *)data)[l].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
@@ -1915,7 +1982,10 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool
if (mr->extract_type == MR_EXTRACT_BMESH) {
BMesh *bm = mr->bm;
for (int v = 0; v < mr->vert_len; v++) {
- copy_v3_v3(orco[v], BM_vert_at_index(bm, v)->co);
+ const BMVert *eve = BM_vert_at_index(bm, v);
+ /* Exceptional case where #bm_vert_co_get can be avoided, as we want the original coords.
+ * not the distorted ones. */
+ copy_v3_v3(orco[v], eve->co);
}
}
else {
@@ -2301,14 +2371,14 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_edge_fac_loop_bmesh(const MeshRenderData *UNUSED(mr),
- int l,
- BMLoop *loop,
- void *_data)
+static void extract_edge_fac_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
{
MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
if (BM_edge_is_manifold(loop->e)) {
- float ratio = loop_edge_factor_get(loop->f->no, loop->v->co, loop->v->no, loop->next->v->co);
+ float ratio = loop_edge_factor_get(bm_face_no_get(mr, loop->f),
+ bm_vert_co_get(mr, loop->v),
+ bm_vert_no_get(mr, loop->v),
+ bm_vert_co_get(mr, loop->next->v));
data->vbo_data[l] = ratio * 253 + 1;
}
else {
@@ -3133,7 +3203,7 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf)
return data;
}
-static void extract_stretch_angle_loop_bmesh(const MeshRenderData *UNUSED(mr),
+static void extract_stretch_angle_loop_bmesh(const MeshRenderData *mr,
int l,
BMLoop *loop,
void *_data)
@@ -3150,8 +3220,12 @@ static void extract_stretch_angle_loop_bmesh(const MeshRenderData *UNUSED(mr),
BMLoop *l_next_tmp = loop;
luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
- compute_normalize_edge_vectors(
- auv, av, luv->uv, luv_next->uv, l_tmp->v->co, l_next_tmp->v->co);
+ compute_normalize_edge_vectors(auv,
+ av,
+ luv->uv,
+ luv_next->uv,
+ bm_vert_co_get(mr, l_tmp->v),
+ bm_vert_co_get(mr, l_next_tmp->v));
/* Save last edge. */
copy_v2_v2(last_auv, auv[1]);
copy_v3_v3(last_av, av[1]);
@@ -3167,7 +3241,12 @@ static void extract_stretch_angle_loop_bmesh(const MeshRenderData *UNUSED(mr),
else {
luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs);
luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
- compute_normalize_edge_vectors(auv, av, luv->uv, luv_next->uv, loop->v->co, l_next->v->co);
+ compute_normalize_edge_vectors(auv,
+ av,
+ luv->uv,
+ luv_next->uv,
+ bm_vert_co_get(mr, loop->v),
+ bm_vert_co_get(mr, l_next->v));
}
edituv_get_stretch_angle(auv, av, data->vbo_data + l);
}
@@ -3307,7 +3386,7 @@ static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang)
if (mr->extract_type == MR_EXTRACT_BMESH) {
int l = 0;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- float fac = angle_normalized_v3v3(f->no, dir) / (float)M_PI;
+ float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI;
fac = overhang_remap(fac, min, max, minmax_irange);
for (int i = 0; i < f->len; i++, l++) {
r_overhang[l] = fac;
@@ -3385,7 +3464,11 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
for (int i = 0; i < mr->tri_len; i++) {
BMLoop **ltri = looptris[i];
const int index = BM_elem_index_get(ltri[0]->f);
- const float *cos[3] = {ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co};
+ const float *cos[3] = {
+ bm_vert_co_get(mr, ltri[0]->v),
+ bm_vert_co_get(mr, ltri[1]->v),
+ bm_vert_co_get(mr, ltri[2]->v),
+ };
float ray_co[3];
float ray_no[3];
@@ -3398,7 +3481,8 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
BMFace *f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, NULL, NULL);
if (f_hit && dist < face_dists[index]) {
- float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no));
+ float angle_fac = fabsf(
+ dot_v3v3(bm_face_no_get(mr, ltri[0]->f), bm_face_no_get(mr, f_hit)));
angle_fac = 1.0f - angle_fac;
angle_fac = angle_fac * angle_fac * angle_fac;
angle_fac = 1.0f - angle_fac;
@@ -3603,8 +3687,17 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
BMesh *bm = em->bm;
BMFace *f;
+ if (mr->bm_vert_coords != NULL) {
+ BKE_editmesh_cache_ensure_poly_normals(em, mr->edit_data);
+
+ /* Most likely this is already valid, ensure just in case.
+ * Needed for #BM_loop_calc_face_normal_safe_vcos. */
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ }
+
int l = 0;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ int p = 0;
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, p) {
float fac = -1.0f;
if (f->len > 3) {
@@ -3613,13 +3706,23 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
fac = 0.0f;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
+ const float *no_face;
float no_corner[3];
- BM_loop_calc_face_normal_safe(l_iter, no_corner);
+ if (mr->bm_vert_coords != NULL) {
+ no_face = mr->bm_poly_normals[p];
+ BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner);
+ }
+ else {
+ no_face = f->no;
+ BM_loop_calc_face_normal_safe(l_iter, no_corner);
+ }
+
/* simple way to detect (what is most likely) concave */
- if (dot_v3v3(f->no, no_corner) < 0.0f) {
+ if (dot_v3v3(no_face, no_corner) < 0.0f) {
negate_v3(no_corner);
}
- fac = max_ff(fac, angle_normalized_v3v3(f->no, no_corner));
+ fac = max_ff(fac, angle_normalized_v3v3(no_face, no_corner));
+
} while ((l_iter = l_iter->next) != l_first);
fac *= 2.0f;
}
@@ -3842,14 +3945,14 @@ static void *extract_fdots_pos_init(const MeshRenderData *mr, void *buf)
return vbo->data;
}
-static void extract_fdots_pos_loop_bmesh(const MeshRenderData *UNUSED(mr),
+static void extract_fdots_pos_loop_bmesh(const MeshRenderData *mr,
int UNUSED(l),
BMLoop *loop,
void *data)
{
float(*center)[3] = (float(*)[3])data;
float w = 1.0f / (float)loop->f->len;
- madd_v3_v3fl(center[BM_elem_index_get(loop->f)], loop->v->co, w);
+ madd_v3_v3fl(center[BM_elem_index_get(loop->f)], bm_vert_co_get(mr, loop->v), w);
}
static void extract_fdots_pos_loop_mesh(const MeshRenderData *mr,
@@ -3928,7 +4031,7 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *
nor[f].w = NOR_AND_FLAG_HIDDEN;
}
else {
- nor[f] = GPU_normal_convert_i10_v3(efa->no);
+ nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa));
/* Select / Active Flag. */
nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
@@ -3946,7 +4049,7 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *
nor[f].w = NOR_AND_FLAG_HIDDEN;
}
else {
- nor[f] = GPU_normal_convert_i10_v3(efa->no);
+ nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa));
/* Select / Active Flag. */
nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
@@ -4171,7 +4274,7 @@ static void *extract_skin_roots_init(const MeshRenderData *mr, void *buf)
const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_ofs);
if (vs->flag & MVERT_SKIN_ROOT) {
vbo_data->size = (vs->radius[0] + vs->radius[1]) * 0.5f;
- copy_v3_v3(vbo_data->local_pos, eve->co);
+ copy_v3_v3(vbo_data->local_pos, bm_vert_co_get(mr, eve));
vbo_data++;
root_len++;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 649bcd7bbaa..4488a044187 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -96,11 +96,25 @@ static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *c
cd_used->edit_uv = 1;
}
+BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me)
+{
+ switch ((eMeshWrapperType)me->runtime.wrapper_type) {
+ case ME_WRAPPER_TYPE_MDATA:
+ return &me->ldata;
+ break;
+ case ME_WRAPPER_TYPE_BMESH:
+ return &me->edit_mesh->bm->ldata;
+ break;
+ }
+
+ BLI_assert(0);
+ return &me->ldata;
+}
+
static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
- const CustomData *cd_ldata = &me_final->ldata;
-
+ const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
if (layer != -1) {
cd_used->uv |= (1 << layer);
@@ -110,8 +124,7 @@ static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used
static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
- const CustomData *cd_ldata = &me_final->ldata;
-
+ const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV);
if (layer != -1) {
cd_used->uv |= (1 << layer);
@@ -121,8 +134,7 @@ static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd
static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
- const CustomData *cd_ldata = &me_final->ldata;
-
+ const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
if (layer != -1) {
cd_used->vcol |= (1 << layer);
@@ -134,7 +146,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
int gpumat_array_len)
{
const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me;
- const CustomData *cd_ldata = &me_final->ldata;
+ const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
/* See: DM_vertex_attributes_from_gpu for similar logic */
DRW_MeshCDMask cd_used;
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 8ee52756f27..9d6f95552b9 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -374,16 +374,19 @@ static bool walk_floor_distance_get(RegionView3D *rv3d,
mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
add_v3_v3(ray_start, dvec_tmp);
- ret = ED_transform_snap_object_project_ray(walk->snap_context,
- walk->depsgraph,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- },
- ray_start,
- ray_normal,
- r_distance,
- r_location,
- r_normal_dummy);
+ ret = ED_transform_snap_object_project_ray(
+ walk->snap_context,
+ walk->depsgraph,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ /* Avoid having to convert the edit-mesh to a regular mesh. */
+ .use_object_edit_cage = true,
+ },
+ ray_start,
+ ray_normal,
+ r_distance,
+ r_location,
+ r_normal_dummy);
/* artificially scale the distance to the scene size */
*r_distance /= walk->grid;
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index dc1a2b5ff1d..029352f3d85 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -112,7 +112,20 @@ typedef struct Mesh_Runtime {
* In the future we may leave the mesh-data empty
* since its not needed if we can use edit-mesh data. */
char is_original;
- char _pad[6];
+
+ /** #eMeshWrapperType and others. */
+ char wrapper_type;
+ /**
+ * A type mask from wrapper_type,
+ * in case there are differences in finalizing logic between types.
+ */
+ char wrapper_type_finalize;
+
+ char _pad[4];
+
+ /** Needed in case we need to lazily initialize the mesh. */
+ CustomData_MeshMasks cd_mask_extra;
+
} Mesh_Runtime;
typedef struct Mesh {
@@ -228,6 +241,15 @@ typedef struct TFace {
/* **************** MESH ********************* */
+/** #Mesh_Runtime.wrapper_type */
+typedef enum eMeshWrapperType {
+ /** Use mesh data (#Mesh.mvert,#Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */
+ ME_WRAPPER_TYPE_MDATA = 0,
+ /** Use edit-mesh data (#Mesh.#edit_mesh, #Mesh_Runtime.edit_data). */
+ ME_WRAPPER_TYPE_BMESH = 1,
+ /* ME_WRAPPER_TYPE_SUBD = 2, */ /* TODO */
+} eMeshWrapperType;
+
/* texflag */
enum {
ME_AUTOSPACE = 1,
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 29d456e5126..99ce447236b 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -162,6 +162,11 @@ static void deformVertsEM(ModifierData *md,
ArmatureModifierData *amd = (ArmatureModifierData *)md;
Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
armature_deform_verts(amd->object,
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index 5f2043d8c09..ef8530557d7 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -502,10 +502,15 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
}
- if (mesh_src) {
+ if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
BLI_assert(mesh_src->totvert == numVerts);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
if (cmd->type == MOD_CAST_TYPE_CUBOID) {
cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
}
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
index 6224cf6b1fc..3b2268ea14d 100644
--- a/source/blender/modifiers/intern/MOD_correctivesmooth.c
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -756,6 +756,11 @@ static void deformVertsEM(ModifierData *md,
Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
correctivesmooth_modifier_do(
md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)numVerts, editData);
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 238c8223799..eec87a918ec 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -142,6 +142,11 @@ static void deformVertsEM(ModifierData *md,
{
Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
deformVerts(md, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 514ea185ede..0cb882d0532 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -407,6 +407,11 @@ static void deformVertsEM(ModifierData *md,
Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index 095ca95594b..0ca8bc55fb8 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -35,6 +35,7 @@
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_lib_id.h"
+#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
#include "BKE_particle.h"
@@ -783,6 +784,11 @@ static void deformVertsEM(ModifierData *md,
Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
LaplacianDeformModifier_do(
(LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index 2fefca68bad..643afc5b5fc 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -559,6 +559,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
laplaciansmoothModifier_do(
(LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 8dd507d51a4..0a7aa006fcc 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -125,6 +125,11 @@ static void deformVertsEM(ModifierData *md,
struct Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, em, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
deformVerts(md, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index c5ed6363415..57b5f3891b2 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -479,6 +479,11 @@ static void deformVertsEM(ModifierData *md,
Mesh *mesh_src = MOD_deform_mesh_eval_get(
ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
meshdeformModifier_do(md, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index bb8519b01ea..11dc0a92769 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -142,6 +142,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
struct MDeformVert *dvert = NULL;
int defgrp_index = -1;
if (swmd->vgroup_name[0] != '\0') {
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 0bd16a318ae..a81b42905e3 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -440,6 +440,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index 5b13bee7dac..7ac6690e3a7 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -216,6 +216,9 @@ static void deformVertsEM(ModifierData *md,
/* mesh_src is needed for vgroups, and taking edges into account. */
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ /* TODO(campbell): use edit-mode data only (remove this line). */
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+
smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index bd453c24a31..4999c77c355 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -196,7 +196,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
}
else if (ob->type == OB_MESH) {
if (em) {
- mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL, ob->data);
+ mesh = BKE_mesh_wrapper_from_editmesh_with_coords(em, NULL, vertexCos, ob->data);
}
else {
/* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether
@@ -209,9 +209,12 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
mesh->runtime.deformed_only = 1;
}
+ if (em != NULL) {
+ /* pass */
+ }
/* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether
* we really need vertexCos here. */
- if (vertexCos) {
+ else if (vertexCos) {
BKE_mesh_vert_coords_apply(mesh, vertexCos);
mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
}
@@ -241,7 +244,9 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
}
}
- BLI_assert(mesh == NULL || mesh->totvert == num_verts);
+ if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
+ BLI_assert(mesh->totvert == num_verts);
+ }
return mesh;
}
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index 458e2d0caea..692f0ca18f0 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -381,6 +381,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
warpModifier_do(wmd, ctx, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index fc4b65a7e5c..90d9f451f75 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -353,6 +353,11 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
}
+ /* TODO(Campbell): use edit-mode data only (remove this line). */
+ if (mesh_src != NULL) {
+ BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ }
+
waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
if (!ELEM(mesh_src, NULL, mesh)) {