This is an initial patch to avoid converting EditMesh to Mesh.
This patch makes the following changes:
- Mesh data blocks in the modifier stack can be "thin wrapped" edit-mesh data (empty mesh data, with pointers to the EditMesh and EditMeshData).
- Any users of these meshes that need the full mesh data can ensure this data exists (delaying edit-mesh conversion until it's needed).
- Currently, this means there is no EditMesh to Mesh conversion for edit-mode for many deform modifiers, giving significant performance improvements (about 2x).
- RNA Object.to_mesh initialized mesh data for Cycles & exporters.
In this patch a define is checked for, currently no functional changes unless the developer defines USE_EDITMESH_THIN_WRAP (exact details of how this is enabled can be tweaked).
Once this patch is applied, each modifier with a deformVertsEM callback which runs BKE_mesh_from_editmesh_thick_wrap_ensure needs to be updated to remove this call.
In most cases this can be removed once there is a utility to get vertex weights from both a mesh and edit-mesh vertices.
Testing playback of a mesh with ~98k tris and two deform modifiers gives a little over 2x performance improvement here.
Note that draw_cache_extract_mesh.c is accessing normals and coordinates more than I would like. In the current patch this checks for deformed coordinates on each access.
Eventually we should be able to avoid passing vertex coordinates to the GPU so many times to reduce the overhead.
Currently it's not practical to split the code into separate branches for deform/non-deform cases. With different logic for updating the coordinate buffer, we might be able to avoid checking for deformed coords on every access.
Here are some changes I'm considering.
- Instead of having thin-wrapped mesh which uses a boolean to check we could have a data-type, so mesh->runtime.data_type could be: ME_GEOMTYPE_MDATA, ME_GEOMTYPE_BMESH and later perhaps ME_GEOMTYPE_SUBSURF.
- Currently the mesh extraction code is calculating data from the edit-mesh (such as tangents and normals). This is awkward as there is logic in the modifier calculation code to calculate this for mesh data, see: editbmesh_calc_modifier_final_normals. This area could be cleaned up, making sure calculations happen in editbmesh_calc_modifier_final_normals, even with an edit-mesh.
- Ensure lazy initialization doesn't cause threading bugs. As long as the lazy initializing the mesh data happens in modifiers (for the mesh being created by the modifier stack). This isn't needed, however we will most likely want locking for the final id_eval, as well as modifiers that depend on other objects geometry.
- Checking UV tangents are being correctly calculated before & after this patch is applied.
- Check on custom normal editing.
- Remove or update BKE_mesh_foreach_mapped_loop, as it's not used. This currently uses Mesh loop layer even for edit-mesh data when MESH_FOREACH_USE_NORMAL is enabled.
- Support statvis "Distort" display option with coordinates deformed by modifiers.
- Finish this patch to a basic level:
- Resolve lazy initializing multi-threading for modifiers that depend on geometry.
- Ensure tangents work correctly (needs testing).
- Ensure normal editing works correctly (needs testing).
- Incrementally remove BKE_mesh_from_editmesh_thick_wrap_ensure for modifiers deformVertsEM callbacks.
- Ensure there are no regressions (UV-mapping, UV-tangents, auto-smooth, normal-editing, crazy-space, snapping to edit-mesh data).
- Remove pre-processor checks and enable this by default.
Note: this could go into master and be disabled at any point, initially this was my plan but as the patch gets a bit noisy. I'm not as convinced this is worth doing.
- Support modifiers passing thin-wrapped meshes between modifiers (eModifierTypeFlag_AcceptsBMesh). This shouldn't be such a big task, it's mostly a matter of making sure there are no regressions.
- Support bypassing normal calculation in wire-frame mode (for 2.7x performance in wire-frame mode - if we want to aim for this)