Blender
V3.3
|
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_alloca.h"
#include "BLI_array.hh"
#include "BLI_index_range.hh"
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
#include "BLI_span.hh"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_multires.h"
#include "BKE_key.h"
#include "BKE_main.h"
#include "DEG_depsgraph_query.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
#include "CLG_log.h"
Go to the source code of this file.
Functions | |
void | BM_mesh_cd_flag_ensure (BMesh *bm, Mesh *mesh, const char cd_flag) |
void | BM_mesh_cd_flag_apply (BMesh *bm, const char cd_flag) |
char | BM_mesh_cd_flag_from_bmesh (BMesh *bm) |
static BMFace * | bm_face_create_from_mpoly (BMesh &bm, Span< MLoop > loops, Span< BMVert * > vtable, Span< BMEdge * > etable) |
void | BM_mesh_bm_from_me (BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params) |
static BMVert ** | bm_to_mesh_vertex_map (BMesh *bm, int ototvert) |
BMesh -> Mesh. More... | |
BLI_INLINE void | bmesh_quick_edgedraw_flag (MEdge *med, BMEdge *e) |
void | BM_mesh_bm_to_me (Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) |
void | BM_mesh_bm_to_me_for_eval (BMesh *bm, Mesh *me, const CustomData_MeshMasks *cd_mask_extra) |
Edit-Mesh to Shape Key Conversion | |
There are some details relating to using data from shape keys that need to be considered carefully for shape key synchronization logic. Key Block Usage Key blocks (data in Mesh.key must be used carefully). They can be used to query which key blocks are relative to the basis since it's not possible to add/remove/reorder key blocks while in edit-mode. Key Block CoordinatesKey blocks locations must not be used. This was done from v2.67 to 3.0, causing bugs T35170 & T44415. Shape key synchronizing could work under the assumption that the key-block is fixed-in-place when entering edit-mode allowing them to be used as a reference when exiting. It often does work but isn't reliable since for e.g. rendering may flush changes from the edit-mesh to the key-block (there are a handful of other situations where changes may be flushed, see ED_editors_flush_edits and related functions). When using undo, it's not known if the data in key-block is from the past or future, so just don't use this data as it causes pain and suffering for users and developers alike. Instead, use the shape-key values stored in CD_SHAPEKEY since they are reliably based on the original locations, unless explicitly manipulated. It's important to write the final shape-key values back to the CD_SHAPEKEY so applying the difference between the original-basis and the new coordinates isn't done multiple times. Therefore ED_editors_flush_edits and other flushing calls will update both the Mesh.key and the edit-mode CD_SHAPEKEY custom-data layers. WARNING: There is an exception to the rule of ignoring coordinates in the destination: that is when shape-key data in Flushing Coordinates Back to the BMeshThe edit-mesh may be flushed back to the Mesh and Key used to generate it. When this is done, the new values are written back to the BMesh's CD_SHAPEKEY as well. This is necessary when editing basis-shapes so the difference in shape keys is not applied multiple times. If it were important to avoid it could be skipped while exiting edit-mode (as the entire BMesh is freed in that case), however it's just copying back a In general updating the BMesh's CD_SHAPEKEY makes shake-key logic easier to reason about since it means flushing data back to the mesh has the same behavior as exiting and entering edit-mode (a more common operation). Meaning there is one less corner-case to have to consider. Exceptional Cases There are some situations that should not happen in typical usage but are still handled in this code, since failure to handle them could loose user-data. These could be investigated further since if they never happen in practice, we might consider removing them. However, the possibility of an mesh directly being modified by Python or some other low level logic that changes key-blocks means there is a potential this to happen so keeping code to these cases remain supported.
| |
static int | bm_to_mesh_shape_layer_index_from_kb (BMesh *bm, KeyBlock *currkey) |
static void | bm_to_mesh_shape (BMesh *bm, Key *key, MVert *mvert, const bool active_shapekey_to_mvert) |
Variables | |
static CLG_LogRef | LOG = {"bmesh.mesh.convert"} |
BM mesh conversion functions.
When converting to/from a Mesh/BMesh you can optionally pass a shape key to edit. This has the effect of editing the shape key-block rather than the original mesh vertex coords (although additional geometry is still allowed and uses fallback locations on converting).
While this works for any mesh/bmesh this is made use of by entering and exiting edit-mode.
There are comments in code but this should help explain the general intention as to how this works converting from/to bmesh.
This is where the most confusing code is! Won't attempt to document the details here, for that read the code. But basics are as follows.
Copying the locations back to the shape keys is quite confusing... One main area of confusion is that when editing a 'Basis' key-block 'me->key->refkey' The coords are written into the mesh, from the users perspective the Basis coords are written into the mesh when exiting edit-mode.
When not editing the 'Basis', the original vertex locations (stored in the mesh and unchanged during edit-mode), are copied back into the mesh.
This has the effect from the users POV of leaving the mesh un-touched, and only editing the active shape key-block.
Other details noted here which might not be so obvious:
Definition in file bmesh_mesh_convert.cc.
|
static |
Definition at line 188 of file bmesh_mesh_convert.cc.
References bm, BM_CREATE_SKIP_CD, BM_face_create(), blender::Array< T, InlineBufferCapacity, Allocator >::data(), blender::Span< T >::index_range(), blender::Span< T >::size(), and verts.
Referenced by BM_mesh_bm_from_me().
void BM_mesh_bm_from_me | ( | BMesh * | bm, |
const Mesh * | me, | ||
const struct BMeshFromMeshParams * | params | ||
) |
Definition at line 204 of file bmesh_mesh_convert.cc.
References BMesh::act_face, Mesh::act_face, BKE_mesh_vertex_normals_ensure(), BLI_array_alloca, BLI_assert, BLI_findlink(), BLI_listbase_count(), Key::block, bm, BM_CREATE_SKIP_CD, BM_EDGE, BM_edge_create(), BM_edge_flag_from_mflag(), BM_edge_select_set(), BM_ELEM_CD_GET_VOID_P, BM_ELEM_CD_SET_FLOAT, BM_ELEM_CD_SET_INT, BM_elem_index_set, BM_FACE, bm_face_create_from_mpoly(), BM_FACE_FIRST_LOOP, BM_face_flag_from_mflag(), BM_face_normal_update(), BM_face_select_set(), BM_LOOP, BM_mesh_cd_flag_apply(), BM_mesh_cd_flag_from_bmesh(), BM_select_history_clear(), BM_select_history_store_notest, BM_VERT, BM_vert_create(), BM_vert_flag_from_mflag(), BM_vert_select_set(), CD_ASSIGN, CD_BWEIGHT, CD_CALLOC, CD_CREASE, CD_DEFAULT, Mesh::cd_flag, CD_MASK_BMESH, CD_SHAPE_KEYINDEX, CD_SHAPEKEY, copy_v3_v3(), CustomData_add_layer(), CustomData_add_layer_named(), CustomData_bmesh_init_pool(), CustomData_bmesh_merge(), CustomData_copy(), CustomData_get_layer_index_n(), CustomData_get_offset(), CustomData_has_layer(), CustomData_MeshMasks_update(), CustomData_number_of_layers(), CustomData_to_bmesh_block(), BMHeader::data, KeyBlock::data, DEG_is_original_id(), e, BMesh::edata, Mesh::edata, BMesh::elem_index_dirty, ListBase::first, float(), BMVert::head, BMLoop::head, BMFace::head, BMHeader::hflag, Mesh::id, MSelect::index, blender::Array< T, InlineBufferCapacity, Allocator >::is_empty(), Mesh::key, CustomData::layers, BMesh::ldata, Mesh::ldata, LISTBASE_FOREACH, mask(), BMFace::mat_nr, ME_CDFLAG_EDGE_BWEIGHT, ME_CDFLAG_EDGE_CREASE, ME_CDFLAG_VERT_BWEIGHT, ME_ESEL, ME_FACE_SEL, ME_FSEL, ME_VSEL, Mesh::medge, min_ii(), Mesh::mloop, Mesh::mpoly, Mesh::mselect, Mesh::mvert, KeyBlock::name, ID::name, BMLoop::next, KeyBlock::next, BMVert::no, params, BMesh::pdata, Mesh::pdata, blender::Array< T, InlineBufferCapacity, Allocator >::reinitialize(), SELECT, BMesh::shapenr, Mesh::totedge, KeyBlock::totelem, BMesh::totface, CustomData::totlayer, Mesh::totloop, Mesh::totpoly, Mesh::totselect, BMesh::totvert, Mesh::totvert, MSelect::type, CustomDataLayer::uid, KeyBlock::uid, Key::uidgen, UNLIKELY, v, v1, v2, BMesh::vdata, and Mesh::vdata.
Referenced by bc_triangulate_mesh(), BKE_mesh_remesh_voxel_fix_poles(), BKE_mesh_to_bmesh_ex(), BMD_mesh_bm_create(), bmo_mesh_to_bmesh_exec(), bpy_bmesh_from_mesh(), bpy_bmesh_from_object(), ED_uvedit_add_simple_uvs(), edbm_separate_exec(), geometry_extract_apply(), get_bmesh_from_mesh(), blender::nodes::node_geo_edge_split_cc::mesh_edge_split(), paint_mask_slice_exec(), SCULPT_dynamic_topology_enable_ex(), sculpt_face_set_create_exec(), sculpt_face_set_delete_geometry(), sculpt_face_sets_init_flood_fill(), sculpt_face_sets_init_loop(), sculpt_gesture_apply_trim(), sculpt_gesture_trim_normals_update(), and undomesh_to_editmesh().
void BM_mesh_bm_to_me | ( | Main * | bmain, |
BMesh * | bm, | ||
Mesh * | me, | ||
const struct BMeshToMeshParams * | params | ||
) |
Definition at line 905 of file bmesh_mesh_convert.cc.
References BMesh::act_face, Mesh::act_face, BKE_mesh_clear_derived_normals(), BKE_mesh_runtime_clear_geometry(), BKE_mesh_update_customdata_pointers(), BLI_assert, BLI_listbase_count(), bm, BM_CHECK_ELEMENT, BM_EDGE, BM_edge_flag_to_mflag(), BM_EDGES_OF_MESH, BM_ELEM_CD_GET_FLOAT_AS_UCHAR, BM_ELEM_CD_SET_INT, BM_elem_index_get, BM_elem_index_set, BM_FACE, BM_FACE_FIRST_LOOP, BM_face_flag_to_mflag(), BM_FACES_OF_MESH, BM_ITER_MESH, BM_ITER_MESH_INDEX, BM_mesh_cd_flag_from_bmesh(), bm_to_mesh_shape(), bm_to_mesh_vertex_map(), BM_VERT, BM_vert_flag_to_mflag(), BM_VERTS_OF_MESH, bmesh_quick_edgedraw_flag(), MVert::bweight, MEdge::bweight, CD_ASSIGN, CD_BWEIGHT, CD_CALLOC, CD_CREASE, Mesh::cd_flag, CD_MASK_MESH, CD_MEDGE, CD_MLOOP, CD_MPOLY, CD_MVERT, CD_SHAPE_KEYINDEX, BMVert::co, MVert::co, copy_v3_v3(), MEdge::crease, CustomData_add_layer(), CustomData_copy(), CustomData_free(), CustomData_from_bmesh_block(), CustomData_get_offset(), CustomData_MeshMasks_update(), BMHeader::data, BMLoop::e, e, MLoop::e, BMesh::edata, Mesh::edata, ELEM, BMesh::elem_index_dirty, eModifierType_Hook, Mesh::fdata, MVert::flag, MEdge::flag, MPoly::flag, BMVert::head, BMLoop::head, BMFace::head, MSelect::index, HookModifierData::indexar, HookModifierData::indexar_num, Mesh::key, BMesh::ldata, Mesh::ldata, BMFace::len, LISTBASE_FOREACH, LISTBASE_FOREACH_INDEX, MPoly::loopstart, mask(), BMFace::mat_nr, MPoly::mat_nr, ME_ESEL, ME_FSEL, ME_VSEL, MEM_callocN, MEM_freeN, MEM_mallocN, MEM_SAFE_FREE, Mesh::mselect, multires_topology_changed(), Mesh::mvert, BMLoop::next, Main::objects, params, PARVERT1, PARVERT3, BMesh::pdata, Mesh::pdata, BMesh::selected, BMesh::totedge, Mesh::totedge, BMesh::totface, Mesh::totface, BMesh::totloop, Mesh::totloop, MPoly::totloop, Mesh::totpoly, Mesh::totselect, BMesh::totvert, Mesh::totvert, MSelect::type, BMLoop::v, v, MLoop::v, MEdge::v1, MEdge::v2, BMesh::vdata, and Mesh::vdata.
Referenced by bc_triangulate_mesh(), BKE_mesh_from_bmesh_nomain(), BKE_mesh_mirror_apply_mirror_on_axis(), bmo_bmesh_to_mesh_exec(), bpy_bmesh_to_mesh(), blender::nodes::node_geo_mesh_primitive_ico_sphere_cc::create_ico_sphere_mesh(), ED_uvedit_add_simple_uvs(), EDBM_mesh_load_ex(), edbm_separate_exec(), mesh_separate_arrays(), mesh_separate_loose(), mesh_separate_tagged(), modifyMesh(), multires_unsubdivide_to_basemesh(), prepare_mesh_for_viewport_render(), sculpt_face_set_delete_geometry(), sculptsession_bm_to_me_update_data_only(), and undomesh_from_editmesh().
void BM_mesh_bm_to_me_for_eval | ( | BMesh * | bm, |
Mesh * | me, | ||
const CustomData_MeshMasks * | cd_mask_extra | ||
) |
Definition at line 1168 of file bmesh_mesh_convert.cc.
References BKE_mesh_clear_derived_normals(), BKE_mesh_update_customdata_pointers(), BLI_assert, bm, BM_EDGE, BM_edge_flag_to_mflag(), BM_EDGES_OF_MESH, BM_ELEM_CD_GET_FLOAT_AS_UCHAR, BM_elem_index_get, BM_elem_index_set, BM_FACE, BM_FACE_FIRST_LOOP, BM_face_flag_to_mflag(), BM_FACES_OF_MESH, BM_ITER_MESH_INDEX, BM_LOOP, BM_mesh_cd_flag_from_bmesh(), BM_VERT, BM_vert_flag_to_mflag(), BM_VERTS_OF_MESH, MEdge::bweight, CD_BWEIGHT, CD_CALLOC, CD_CREASE, Mesh::cd_flag, CD_MASK_DERIVEDMESH, CD_MASK_SHAPEKEY, CD_MEDGE, CD_MLOOP, CD_MPOLY, CD_MVERT, BMVert::co, copy_v3_v3(), MEdge::crease, CustomData_add_layer(), CustomData_from_bmesh_block(), CustomData_get_offset(), CustomData_merge(), CustomData_MeshMasks_update(), BMHeader::data, Mesh_Runtime::deformed_only, BMLoop::e, MLoop::e, BMesh::edata, Mesh::edata, BMesh::elem_index_dirty, MEdge::flag, MPoly::flag, BMVert::head, BMEdge::head, BMLoop::head, BMFace::head, BMEdge::l, BMesh::ldata, Mesh::ldata, BMFace::len, MPoly::loopstart, mask(), BMFace::mat_nr, MPoly::mat_nr, ME_EDGEDRAW, Mesh::medge, Mesh::mloop, Mesh::mpoly, Mesh::mvert, BMLoop::next, BMesh::pdata, Mesh::pdata, BMLoop::radial_next, Mesh::runtime, BMesh::totedge, Mesh::totedge, BMesh::totface, Mesh::totface, BMesh::totloop, Mesh::totloop, MPoly::totloop, Mesh::totpoly, BMesh::totvert, Mesh::totvert, BMLoop::v, MLoop::v, BMEdge::v1, MEdge::v1, BMEdge::v2, MEdge::v2, BMesh::vdata, Mesh::vdata, and CustomData_MeshMasks::vmask.
Referenced by BKE_mesh_from_bmesh_for_eval_nomain(), and blender::ed::spreadsheet::spreadsheet_get_display_geometry_set().
Definition at line 117 of file bmesh_mesh_convert.cc.
References BLI_assert, bm, BM_data_layer_add(), BM_data_layer_free(), CD_BWEIGHT, CD_CREASE, CustomData_has_layer(), BMesh::edata, ME_CDFLAG_EDGE_BWEIGHT, ME_CDFLAG_EDGE_CREASE, ME_CDFLAG_VERT_BWEIGHT, ME_CDFLAG_VERT_CREASE, BMesh::pdata, CustomData::pool, CustomData::totlayer, and BMesh::vdata.
Referenced by BM_mesh_bm_from_me(), BM_mesh_cd_flag_ensure(), and BM_mesh_copy_init_customdata_from_mesh_array().
Definition at line 108 of file bmesh_mesh_convert.cc.
References bm, BM_mesh_cd_flag_apply(), BM_mesh_cd_flag_from_bmesh(), Mesh::cd_flag, and mesh.
Referenced by createTransEdge(), createTransMeshVertCData(), edgetag_ensure_cd_flag(), and v3d_editvertex_buts().
char BM_mesh_cd_flag_from_bmesh | ( | BMesh * | bm | ) |
Definition at line 169 of file bmesh_mesh_convert.cc.
References bm, CD_BWEIGHT, CD_CREASE, CustomData_has_layer(), BMesh::edata, ME_CDFLAG_EDGE_BWEIGHT, ME_CDFLAG_EDGE_CREASE, ME_CDFLAG_VERT_BWEIGHT, ME_CDFLAG_VERT_CREASE, and BMesh::vdata.
Referenced by BM_mesh_bm_from_me(), BM_mesh_bm_to_me(), BM_mesh_bm_to_me_for_eval(), BM_mesh_cd_flag_ensure(), and BM_mesh_copy_init_customdata_from_mesh_array().
|
static |
Update key
with shape key data stored in bm
.
bm | The source BMesh. |
key | The destination key. |
mvert | The destination vertex array (in some situations it's coordinates are updated). |
active_shapekey_to_mvert | When editing a non-basis shape key, the coordinates for the basis are typically copied into the mvert array since it makes sense for the meshes vertex coordinates to match the "Basis" key. When enabled, skip this step and copy BMVert.co directly to MVert.co, See BMeshToMeshParams.active_shapekey_to_mvert doc-string. |
Definition at line 683 of file bmesh_mesh_convert.cc.
References add_v3_v3(), BKE_keyblock_add(), BKE_keyblock_is_basis(), BLI_assert, BLI_findlink(), Key::block, bm, BM_ELEM_CD_GET_INT, BM_ELEM_CD_GET_VOID_P, BM_ITER_MESH_INDEX, bm_to_mesh_shape_layer_index_from_kb(), BM_VERTS_OF_MESH, CD_SHAPE_KEYINDEX, CD_SHAPEKEY, CLOG_WARN, BMVert::co, copy_v3_v3(), CustomData_get_n_offset(), CustomData_get_offset(), Key::elemsize, ListBase::first, float(), KEY_RELATIVE, CustomData::layers, LISTBASE_FOREACH, LOG, MEM_freeN, MEM_mallocN, MEM_reallocN, CustomDataLayer::name, KeyBlock::next, ORIGINDEX_NONE, Key::refkey, BMesh::shapenr, sub_v3_v3v3(), CustomData::totlayer, BMesh::totvert, CustomDataLayer::type, Key::type, CustomDataLayer::uid, KeyBlock::uid, and BMesh::vdata.
Referenced by BM_mesh_bm_to_me().
Returns custom-data shape-key index from a key-block or -1
Definition at line 655 of file bmesh_mesh_convert.cc.
References bm, CD_SHAPEKEY, CustomData::layers, CustomData::totlayer, CustomDataLayer::type, CustomDataLayer::uid, KeyBlock::uid, and BMesh::vdata.
Referenced by bm_to_mesh_shape().
Definition at line 532 of file bmesh_mesh_convert.cc.
References BLI_assert, bm, BM_ELEM_CD_GET_INT, BM_ITER_MESH_INDEX, BM_VERTS_OF_MESH, CD_SHAPE_KEYINDEX, CustomData_get_offset(), MEM_callocN, ORIGINDEX_NONE, and BMesh::vdata.
Referenced by BM_mesh_bm_to_me().
BLI_INLINE void bmesh_quick_edgedraw_flag | ( | MEdge * | med, |
BMEdge * | e | ||
) |
Definition at line 888 of file bmesh_mesh_convert.cc.
References dot_v3v3(), e, MEdge::flag, ME_EDGEDRAW, and BMVert::no.
Referenced by BM_mesh_bm_to_me().
|
static |
Definition at line 102 of file bmesh_mesh_convert.cc.
Referenced by bm_to_mesh_shape().