Mesh: Move loose edge flag to a separate cache

As part of T95966, this patch moves loose edge information out of the
flag on each edge and into a new lazily calculated cache in mesh
runtime data. The number of loose edges is also cached, so further
processing can be skipped completely when there are no loose edges.

Previously the `ME_LOOSEEDGE` flag was updated on a "best effort"
basis. In order to be sure that it was correct, you had to be sure
to call `BKE_mesh_calc_edges_loose` first. Now the loose edge tag
is always correct. It also doesn't have to be calculated eagerly
in various places like the screw modifier where the complexity
wasn't worth the theoretical performance benefit.

The patch also adds a function to eagerly set the number of loose
edges to zero to avoid building the cache. This is used by various
primitive nodes, with the goal of improving drawing performance.
This results in a few ms shaved off extracting draw data for some
large meshes in my tests.

In the Python API, `MeshEdge.is_loose` is no longer editable.
No built-in addons set the value anyway. The upside is that
addons can be sure the data is correct based on the mesh.

**Tests**
There is one test failure in the Python OBJ exporter: `export_obj_cube`
that happens because of existing incorrect versioning. Opening the
file in master, all the edges were set to "loose", which is fixed
by this patch.

Differential Revision: https://developer.blender.org/D16504
This commit is contained in:
2022-11-18 16:05:06 -06:00
parent c0f33814c1
commit 1ea169d90e
45 changed files with 259 additions and 236 deletions

View File

@@ -200,21 +200,23 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
void GeometryExporter::createLooseEdgeList(Object *ob, Mesh *me, std::string &geom_id)
{
using namespace blender;
const Span<MEdge> edges = me->edges();
int totedges = me->totedge;
int edges_in_linelist = 0;
std::vector<uint> edge_list;
int index;
/* Find all loose edges in Mesh
* and save vertex indices in edge_list */
for (index = 0; index < totedges; index++) {
const MEdge *edge = &edges[index];
if (edge->flag & ME_LOOSEEDGE) {
edges_in_linelist += 1;
edge_list.push_back(edge->v1);
edge_list.push_back(edge->v2);
const bke::LooseEdgeCache &loose_edges = me->loose_edges();
if (loose_edges.count > 0) {
for (const int64_t i : edges.index_range()) {
if (loose_edges.is_loose_bits[i]) {
const MEdge *edge = &edges[i];
edges_in_linelist += 1;
edge_list.push_back(edge->v1);
edge_list.push_back(edge->v2);
}
}
}