BMesh: simple bmesh -> mesh for evaluation
authorCampbell Barton <ideasman42@gmail.com>
Wed, 10 Oct 2018 01:51:14 +0000 (12:51 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 10 Oct 2018 02:14:15 +0000 (13:14 +1100)
Copied from CDDM_from_bmesh, the modifier stack doesn't
need to handle shape keys, vertex parents or selection history
(needed for mode switching).

source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/mesh.c
source/blender/bmesh/intern/bmesh_mesh_conv.c
source/blender/bmesh/intern/bmesh_mesh_conv.h

index 99815149ad5754844552f1b59c62e232d28298a7..9f86c16bae8172671e45ddb38d003e1a68cc45a5 100644 (file)
@@ -91,6 +91,7 @@ struct BMesh *BKE_mesh_to_bmesh(
         const bool add_key_index, const struct BMeshCreateParams *params);
 
 struct Mesh *BKE_mesh_from_bmesh_nomain(struct BMesh *bm, const struct BMeshToMeshParams *params);
+struct Mesh *BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm, int64_t cd_mask_extra);
 
 struct Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(
         struct BMEditMesh *em, CustomDataMask data_mask, float (*vertexCos)[3]);
index 9043460562deb52547018b7eb3f459411d1a9390..ef418fc68f5f3e519a495eafcd38ba2b6a09898a 100644 (file)
@@ -752,6 +752,8 @@ static void loops_to_customdata_corners(
        }
 }
 
+/* TODO(campbell): remove, use BKE_mesh_from_bmesh_for_eval_nomain instead. */
+
 /* used for both editbmesh and bmesh */
 static DerivedMesh *cddm_from_bmesh_ex(
         struct BMesh *bm, const bool use_mdisps,
index 7ba249ade18c10b77bb32d9443c59ea633adf9fd..a753a996e0a9f0c7935079117b3569c817b455dc 100644 (file)
@@ -756,6 +756,13 @@ Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm, const struct BMeshToMeshParams *para
        return mesh;
 }
 
+Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm, const int64_t cd_mask_extra)
+{
+       Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL);
+       BM_mesh_bm_to_me_for_eval(bm, mesh, cd_mask_extra);
+       return mesh;
+}
+
 /**
  * TODO(campbell): support mesh with only an edit-mesh which is lazy initialized.
  */
index 7e1e1c53a8f04b15156bdee785a0e6cc18acba6c..52d9d2cf44569e2e26438118487fa232065f1950 100644 (file)
@@ -946,3 +946,152 @@ void BM_mesh_bm_to_me(
        /* to be removed as soon as COW is enabled by default. */
        BKE_mesh_runtime_clear_geometry(me);
 }
+
+/**
+ * A version of #BM_mesh_bm_to_me intended for getting the mesh to pass to the modifier stack for evaluation,
+ * instad of mode switching (where we make sure all data is kept and do expensive lookups to maintain shape keys).
+ *
+ * Key differences:
+ *
+ * - Don't support merging with existing mesh.
+ * - Ignore shape-keys.
+ * - Ignore vertex-parents.
+ * - Ignore selection history.
+ * - Uses simpler method to calculate #ME_EDGEDRAW
+ * - Uses #CD_MASK_DERIVEDMESH instead of #CD_MASK_MESH.
+ *
+ * \note Was `cddm_from_bmesh_ex` in 2.7x, removed `MFace` support.
+ */
+void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *dm, const int64_t cd_mask_extra)
+{
+       /* must be an empty mesh. */
+       BLI_assert(dm->totvert == 0);
+       BLI_assert((cd_mask_extra & CD_MASK_SHAPEKEY) == 0);
+
+       dm->totvert = bm->totvert;
+       dm->totedge = bm->totedge;
+       dm->totface = 0;
+       dm->totloop = bm->totloop;
+       dm->totpoly = bm->totface;
+
+       CustomData_add_layer(&dm->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totvert);
+       CustomData_add_layer(&dm->edata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totedge);
+       CustomData_add_layer(&dm->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totface);
+
+       CustomData_add_layer(&dm->vdata, CD_MVERT, CD_CALLOC, NULL, bm->totvert);
+       CustomData_add_layer(&dm->edata, CD_MEDGE, CD_CALLOC, NULL, bm->totedge);
+       CustomData_add_layer(&dm->ldata, CD_MLOOP, CD_CALLOC, NULL, bm->totloop);
+       CustomData_add_layer(&dm->pdata, CD_MPOLY, CD_CALLOC, NULL, bm->totface);
+
+       BKE_mesh_update_customdata_pointers(dm, false);
+
+       BMIter iter;
+       BMVert *eve;
+       BMEdge *eed;
+       BMFace *efa;
+       MVert *mvert = dm->mvert;
+       MEdge *medge = dm->medge;
+       MLoop *mloop = dm->mloop;
+       MPoly *mpoly = dm->mpoly;
+       int *index, add_orig;
+       unsigned int i, j;
+
+       const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+       const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+       const int cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);
+
+       dm->runtime.deformed_only = true;
+
+       /* don't add origindex layer if one already exists */
+       add_orig = !CustomData_has_layer(&bm->pdata, CD_ORIGINDEX);
+
+       /* don't process shapekeys, we only feed them through the modifier stack as needed,
+        * e.g. for applying modifiers or the like*/
+       const CustomDataMask mask = (CD_MASK_DERIVEDMESH | cd_mask_extra) & ~CD_MASK_SHAPEKEY;
+       CustomData_merge(&bm->vdata, &dm->vdata, mask, CD_CALLOC, dm->totvert);
+       CustomData_merge(&bm->edata, &dm->edata, mask, CD_CALLOC, dm->totedge);
+       CustomData_merge(&bm->ldata, &dm->ldata, mask, CD_CALLOC, dm->totloop);
+       CustomData_merge(&bm->pdata, &dm->pdata, mask, CD_CALLOC, dm->totpoly);
+
+       index = CustomData_get_layer(&dm->vdata, CD_ORIGINDEX);
+
+       BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+               MVert *mv = &mvert[i];
+
+               copy_v3_v3(mv->co, eve->co);
+
+               BM_elem_index_set(eve, i); /* set_inline */
+
+               normal_float_to_short_v3(mv->no, eve->no);
+
+               mv->flag = BM_vert_flag_to_mflag(eve);
+
+               if (cd_vert_bweight_offset != -1) mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset);
+
+               if (add_orig) *index++ = i;
+
+               CustomData_from_bmesh_block(&bm->vdata, &dm->vdata, eve->head.data, i);
+       }
+       bm->elem_index_dirty &= ~BM_VERT;
+
+       index = CustomData_get_layer(&dm->edata, CD_ORIGINDEX);
+       BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
+               MEdge *med = &medge[i];
+
+               BM_elem_index_set(eed, i); /* set_inline */
+
+               med->v1 = BM_elem_index_get(eed->v1);
+               med->v2 = BM_elem_index_get(eed->v2);
+
+               med->flag = BM_edge_flag_to_mflag(eed);
+
+               /* handle this differently to editmode switching,
+                * only enable draw for single user edges rather then calculating angle */
+               if ((med->flag & ME_EDGEDRAW) == 0) {
+                       if (eed->l && eed->l == eed->l->radial_next) {
+                               med->flag |= ME_EDGEDRAW;
+                       }
+               }
+
+               if (cd_edge_crease_offset  != -1) med->crease  = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset);
+               if (cd_edge_bweight_offset != -1) med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset);
+
+               CustomData_from_bmesh_block(&bm->edata, &dm->edata, eed->head.data, i);
+               if (add_orig) *index++ = i;
+       }
+       bm->elem_index_dirty &= ~BM_EDGE;
+
+       index = CustomData_get_layer(&dm->pdata, CD_ORIGINDEX);
+       j = 0;
+       BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
+               BMLoop *l_iter;
+               BMLoop *l_first;
+               MPoly *mp = &mpoly[i];
+
+               BM_elem_index_set(efa, i); /* set_inline */
+
+               mp->totloop = efa->len;
+               mp->flag = BM_face_flag_to_mflag(efa);
+               mp->loopstart = j;
+               mp->mat_nr = efa->mat_nr;
+
+               l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+               do {
+                       mloop->v = BM_elem_index_get(l_iter->v);
+                       mloop->e = BM_elem_index_get(l_iter->e);
+                       CustomData_from_bmesh_block(&bm->ldata, &dm->ldata, l_iter->head.data, j);
+
+                       BM_elem_index_set(l_iter, j); /* set_inline */
+
+                       j++;
+                       mloop++;
+               } while ((l_iter = l_iter->next) != l_first);
+
+               CustomData_from_bmesh_block(&bm->pdata, &dm->pdata, efa->head.data, i);
+
+               if (add_orig) *index++ = i;
+       }
+       bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
+
+       dm->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
+}
index 008960e7f6edfe76ed0f771a114cbf9c205ee7aa..a8bef1ee2a2d212169cf92012f8247055e78aa5d 100644 (file)
@@ -65,4 +65,9 @@ void BM_mesh_bm_to_me(
         const struct BMeshToMeshParams *params)
 ATTR_NONNULL(2, 3, 4);
 
+void BM_mesh_bm_to_me_for_eval(
+        BMesh *bm, struct Mesh *me, const int64_t cd_mask_extra)
+ATTR_NONNULL(1, 2);
+
+
 #endif /* __BMESH_MESH_CONV_H__ */