|
Blender V4.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 "BLI_string_ref.hh"#include "BLI_task.hh"#include "BLI_timeit.hh"#include "BLI_vector.hh"#include "BKE_attribute.hh"#include "BKE_customdata.hh"#include "BKE_mesh.hh"#include "BKE_mesh_runtime.hh"#include "BKE_multires.hh"#include "BKE_key.hh"#include "BKE_main.hh"#include "DEG_depsgraph_query.hh"#include "bmesh.hh"#include "intern/bmesh_private.hh"#include "CLG_log.h"Go to the source code of this file.
Classes | |
| struct | MeshToBMeshLayerInfo |
| struct | BMeshToMeshLayerInfo |
Namespaces | |
| namespace | blender |
Functions | |
| bool | BM_attribute_stored_in_bmesh_builtin (const StringRef name) |
| static BMFace * | bm_face_create_from_mpoly (BMesh &bm, Span< int > face_verts, Span< int > face_edges, Span< BMVert * > vtable, Span< BMEdge * > etable) |
| static Vector< MeshToBMeshLayerInfo > | mesh_to_bm_copy_info_calc (const CustomData &mesh_data, CustomData &bm_data) |
| static void | mesh_attributes_copy_to_bmesh_block (CustomData &data, const Span< MeshToBMeshLayerInfo > copy_info, const int mesh_index, BMHeader &header) |
| void | BM_mesh_bm_from_me (BMesh *bm, const Mesh *mesh, const BMeshFromMeshParams *params) |
| static BMVert ** | bm_to_mesh_vertex_map (BMesh *bm, const int old_verts_num) |
| BMesh -> Mesh. | |
| static void | assert_bmesh_has_no_mesh_only_attributes (const BMesh &bm) |
| static void | bmesh_to_mesh_calc_object_remap (Main &bmain, Mesh &mesh, BMesh &bm, const int old_totvert) |
| static Vector< BMeshToMeshLayerInfo > | bm_to_mesh_copy_info_calc (const CustomData &bm_data, CustomData &mesh_data) |
| static void | blender::bm_vert_table_build (BMesh &bm, MutableSpan< const BMVert * > table, bool &need_select_vert, bool &need_hide_vert) |
| static void | blender::bm_edge_table_build (BMesh &bm, MutableSpan< const BMEdge * > table, bool &need_select_edge, bool &need_hide_edge, bool &need_sharp_edge, bool &need_uv_seams) |
| static void | blender::bm_face_loop_table_build (BMesh &bm, MutableSpan< const BMFace * > face_table, MutableSpan< const BMLoop * > loop_table, bool &need_select_poly, bool &need_hide_poly, bool &need_sharp_face, bool &need_material_index, Vector< int > &loop_layers_not_to_copy) |
| static void | blender::bmesh_block_copy_to_mesh_attributes (const Span< BMeshToMeshLayerInfo > copy_info, const int mesh_index, const void *block) |
| static void | blender::bm_to_mesh_verts (const BMesh &bm, const Span< const BMVert * > bm_verts, Mesh &mesh, MutableSpan< bool > select_vert, MutableSpan< bool > hide_vert) |
| static void | blender::bm_to_mesh_edges (const BMesh &bm, const Span< const BMEdge * > bm_edges, Mesh &mesh, MutableSpan< bool > select_edge, MutableSpan< bool > hide_edge, MutableSpan< bool > sharp_edge, MutableSpan< bool > uv_seams) |
| static void | blender::bm_to_mesh_faces (const BMesh &bm, const Span< const BMFace * > bm_faces, Mesh &mesh, MutableSpan< bool > select_poly, MutableSpan< bool > hide_poly, MutableSpan< bool > sharp_faces, MutableSpan< int > material_indices) |
| static void | blender::bm_to_mesh_loops (const BMesh &bm, const Span< const BMLoop * > bm_loops, Mesh &mesh) |
| void | BM_mesh_bm_to_me (Main *bmain, BMesh *bm, Mesh *mesh, const BMeshToMeshParams *params) |
| void | BM_mesh_bm_to_me_compact (BMesh &bm, Mesh &mesh, const CustomData_MeshMasks *mask, const bool add_mesh_attributes) |
| void | BM_mesh_bm_to_me_for_eval (BMesh &bm, Mesh &mesh, 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 #35170 & #44415. 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, MutableSpan< float3 > positions, 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 'mesh->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 963 of file bmesh_mesh_convert.cc.
References BLI_assert, bm, CD_PROP_BOOL, CD_PROP_FLOAT3, CustomData_has_layer_named(), BMesh::edata, BMesh::ldata, BMesh::pdata, and BMesh::vdata.
Referenced by BM_mesh_bm_to_me_compact().
| bool BM_attribute_stored_in_bmesh_builtin | ( | const blender::StringRef | name | ) |
Definition at line 120 of file bmesh_mesh_convert.cc.
References ELEM.
Referenced by CustomData_shallow_copy_remove_non_bmesh_attributes(), and blender::ed::sculpt_paint::dyntopo::dyntopo_supports_layer().
|
static |
Definition at line 139 of file bmesh_mesh_convert.cc.
References bm, BM_CREATE_SKIP_CD, BM_face_create(), blender::Span< T >::size(), and verts.
Referenced by BM_mesh_bm_from_me().
| void BM_mesh_bm_from_me | ( | BMesh * | bm, |
| const Mesh * | mesh, | ||
| const BMeshFromMeshParams * | params ) |
Definition at line 214 of file bmesh_mesh_convert.cc.
References BMesh::act_face, blender::Vector< T, InlineBufferCapacity, Allocator >::append(), BKE_uv_map_edge_select_name_get(), BKE_uv_map_pin_name_get(), BKE_uv_map_vert_select_name_get(), BLI_array_alloca, BLI_assert, BLI_findlink(), BLI_listbase_count(), BLI_SCOPED_DEFER, bm, BM_CREATE_SKIP_CD, BM_EDGE, BM_edge_create(), BM_edge_select_set(), BM_ELEM_CD_GET_VOID_P, BM_ELEM_CD_SET_INT, BM_elem_flag_enable, BM_ELEM_HIDDEN, BM_elem_index_set, BM_ELEM_SEAM, BM_ELEM_SMOOTH, BM_FACE, bm_face_create_from_mpoly(), BM_FACE_FIRST_LOOP, BM_face_normal_update(), BM_face_select_set(), BM_LOOP, BM_select_history_clear(), BM_select_history_store_notest, BM_VERT, BM_vert_create(), BM_vert_select_set(), CD_CONSTRUCT, CD_MASK_BMESH, CD_PROP_BOOL, CD_PROP_FLOAT2, CD_SET_DEFAULT, CD_SHAPE_KEYINDEX, CD_SHAPEKEY, copy_v3_v3(), CustomData_add_layer(), CustomData_add_layer_named(), CustomData_bmesh_init_pool(), CustomData_bmesh_merge_layout(), CustomData_free_layer_named(), CustomData_get_layer_index_n(), CustomData_get_layer_name(), CustomData_get_named_layer_index(), CustomData_get_offset(), CustomData_has_layer(), CustomData_init_layout_from(), CustomData_MeshMasks_update(), CustomData_number_of_layers(), CustomData_shallow_copy_remove_non_bmesh_attributes(), KeyBlock::data, DEG_is_original_id(), e, BMesh::edata, BMesh::elem_index_dirty, float, BMFace::head, BMLoop::head, BMVert::head, BMHeader::hflag, MSelect::index, blender::Array< T, InlineBufferCapacity, Allocator >::is_empty(), blender::Span< T >::is_empty(), CustomData::layers, BMesh::ldata, LISTBASE_FOREACH, BMFace::mat_nr, MAX_CUSTOMDATA_LAYER_NAME, ME_ESEL, ME_FSEL, ME_VSEL, MEM_SAFE_FREE, mesh_attributes_copy_to_bmesh_block(), mesh_to_bm_copy_info_calc(), min_ii(), KeyBlock::name, BMLoop::next, KeyBlock::next, BMVert::no, params, BMesh::pdata, printf, blender::Array< T, InlineBufferCapacity, Allocator >::reinitialize(), BMesh::shapenr, blender::Span< T >::slice(), KeyBlock::totelem, BMesh::totface, CustomData::totlayer, BMesh::totvert, MSelect::type, CustomDataLayer::uid, KeyBlock::uid, UNLIKELY, v, and BMesh::vdata.
Referenced by blender::ed::sculpt_paint::trim::apply_trim(), 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(), blender::ed::sculpt_paint::face_set::delete_geometry(), ED_uvedit_add_simple_uvs(), edbm_separate_exec(), blender::ed::sculpt_paint::dyntopo::enable_ex(), geometry_extract_apply(), get_bmesh_from_mesh(), blender::geometry::boolean::mesh_bm_concat(), paint_mask_slice_exec(), undomesh_to_editmesh(), and blender::ed::sculpt_paint::trim::update_normals().
| void BM_mesh_bm_to_me | ( | Main * | bmain, |
| BMesh * | bm, | ||
| Mesh * | mesh, | ||
| const BMeshToMeshParams * | params ) |
Definition at line 1409 of file bmesh_mesh_convert.cc.
References BKE_mesh_clear_geometry(), bm, BMesh::totedge, BMesh::totface, BMesh::totloop, and BMesh::totvert.
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(), blender::ed::sculpt_paint::face_set::delete_geometry(), ED_uvedit_add_simple_uvs(), EDBM_mesh_load_ex(), edbm_separate_exec(), mesh_separate_arrays(), mesh_separate_loose(), mesh_separate_tagged(), modify_mesh(), multires_unsubdivide_to_basemesh(), prepare_mesh_for_viewport_render(), sculptsession_bm_to_me_update_data_only(), and undomesh_from_editmesh().
| void BM_mesh_bm_to_me_compact | ( | BMesh & | bm, |
| Mesh & | mesh, | ||
| const CustomData_MeshMasks * | mask, | ||
| bool | add_mesh_attributes ) |
A version of BM_mesh_bm_to_me_for_eval but copying data layers and Mesh attributes is optional. It also allows shape-keys but don't re-assigns shape-key indices.
| mask | Custom data masks to control which layers are copied. If nullptr, no layer data is copied. |
| add_mesh_attributes | If true, adds mesh attributes during the conversion. |
Definition at line 1623 of file bmesh_mesh_convert.cc.
References BMesh::act_face, assert_bmesh_has_no_mesh_only_attributes(), BKE_mesh_runtime_clear_geometry(), BLI_assert, bm, BM_EDGE, BM_elem_index_get, BM_FACE, BM_LOOP, BM_VERT, CD_CONSTRUCT, CD_FLAG_NOCOPY, CustomData_merge_layout(), BMesh::edata, BMesh::elem_index_dirty, blender::bke::SpanAttributeWriter< T >::finish(), CustomDataLayer::flag, CustomData::layers, BMesh::ldata, blender::bke::MutableAttributeAccessor::lookup_or_add_for_write_only_span(), BMesh::pdata, blender::Array< T, InlineBufferCapacity, Allocator >::reinitialize(), blender::bke::SpanAttributeWriter< T >::span, BMesh::totedge, BMesh::totface, BMesh::totloop, BMesh::totvert, and BMesh::vdata.
Referenced by BM_mesh_bm_to_me_for_eval(), and create_mesh().
| void BM_mesh_bm_to_me_for_eval | ( | BMesh & | bm, |
| Mesh & | mesh, | ||
| const CustomData_MeshMasks * | cd_mask_extra ) |
A version of BM_mesh_bm_to_me intended for getting the mesh to pass to the modifier stack for evaluation, instead of mode switching (where we make sure all data is kept and do expensive lookups to maintain shape keys).
Key differences:
cddm_from_bmesh_ex in 2.7x, removed MFace support. Definition at line 1799 of file bmesh_mesh_convert.cc.
References bm, BM_mesh_bm_to_me_compact(), CD_MASK_DERIVEDMESH, and CustomData_MeshMasks_update().
Referenced by BKE_mesh_from_bmesh_for_eval_nomain(), BKE_mesh_wrapper_ensure_mdata(), and blender::ed::spreadsheet::spreadsheet_get_display_geometry_set().
|
static |
Calculate the necessary information to copy every data layer from the BMesh to the Mesh.
Definition at line 1060 of file bmesh_mesh_convert.cc.
References blender::Vector< T, InlineBufferCapacity, Allocator >::append(), CD_FLAG_NOCOPY, CustomData_get_elem_size(), CustomData_get_layer_index_n(), CustomData_get_named_layer_index(), CustomDataLayer::data, blender::Vector< T, InlineBufferCapacity, Allocator >::fill(), CustomDataLayer::flag, CustomData::layers, CustomDataLayer::name, CustomDataLayer::offset, CustomData::totlayer, BMeshToMeshLayerInfo::type, and CustomDataLayer::type.
Referenced by blender::bm_to_mesh_edges(), blender::bm_to_mesh_faces(), blender::bm_to_mesh_loops(), and blender::bm_to_mesh_verts().
|
static |
Update key with shape key data stored in bm.
| bm | The source BMesh. |
| key | The destination key. |
| positions | The destination vertex array (in some situations its coordinates are updated). |
| active_shapekey_to_mvert | When editing a non-basis shape key, the coordinates for the basis are typically copied into the positions 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 the mesh position. See BMeshToMeshParams.active_shapekey_to_mvert doc-string. |
Definition at line 756 of file bmesh_mesh_convert.cc.
References add_v3_v3(), BKE_keyblock_add(), BKE_keyblock_get_dependent_keys(), 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_INDEX, LOG, MEM_freeN(), MEM_mallocN, MEM_reallocN, MEM_SAFE_FREE, 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.
Returns custom-data shape-key index from a key-block or -1
Definition at line 728 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 604 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 bmesh_to_mesh_calc_object_remap().
|
static |
Definition at line 980 of file bmesh_mesh_convert.cc.
References bm, BM_elem_index_get, bm_to_mesh_vertex_map(), ELEM, eModifierType_Hook, HookModifierData::indexar, HookModifierData::indexar_num, LISTBASE_FOREACH, MEM_freeN(), Main::objects, PARVERT1, and PARVERT3.
|
static |
Definition at line 196 of file bmesh_mesh_convert.cc.
References CustomData_bmesh_alloc_block(), CustomData_data_copy_value(), CustomData_data_set_default_value(), BMHeader::data, and POINTER_OFFSET.
Referenced by BM_mesh_bm_from_me().
|
static |
Calculate the necessary information to copy every data layer from the Mesh to the BMesh.
Definition at line 170 of file bmesh_mesh_convert.cc.
References blender::Vector< T, InlineBufferCapacity, Allocator >::append(), CustomData_get_elem_size(), CustomData_get_layer_index_n(), CustomData_get_named_layer_index(), CustomDataLayer::data, blender::Vector< T, InlineBufferCapacity, Allocator >::fill(), CustomData::layers, CustomDataLayer::name, CustomDataLayer::offset, CustomData::totlayer, CustomDataLayer::type, and MeshToBMeshLayerInfo::type.
Referenced by BM_mesh_bm_from_me().
|
static |
Definition at line 109 of file bmesh_mesh_convert.cc.
Referenced by bm_to_mesh_shape().