Add three cached topology maps to `Mesh`, to avoid computations when mesh data isn't changed. Choosing the right maps to cache is a bit arbitrary, but generally we have to start somewhere. The limiting factor is memory usage (all the new caches combined have a comparable footprint to a UV map). For now, the caches added are: - Vertex to face corner - Vertex to face - Face corner to face These caches are used in quite a few places already; - Face corner normal calculation - UV value merging - Setting sharp edges from face angles - Data transfer modifier - Voxel remesh attribute remapping - Sculpt mode painting - Sculpt mode normal calculation - Vertex paint mode - Split edges geometry node - Mesh topology geometry nodes Caching topology maps means they don't have to be rebuilt every time they're used. Meshes copied but without topology changes can share the cache, further reducing re-computations. For example, FPS with a large mesh using the "Corners of Vertex" node went from 1.8 to 2.3. Entering sculpt mode is slightly faster too. There is some obvious work for future commits: - Use caches in attribute domain interpolation - More multithreading of second phase of map building - Update/build caches eagerly in some geometry nodes Pull Request: https://projects.blender.org/blender/blender/pulls/107816
74 lines
1.9 KiB
C++
74 lines
1.9 KiB
C++
/* SPDX-FileCopyrightText: 2020 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup bke
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "BLI_sys_types.h"
|
|
|
|
struct BMesh;
|
|
struct Mesh;
|
|
struct MultiresModifierData;
|
|
|
|
struct MultiresUnsubdivideGrid {
|
|
/* For sanity checks. */
|
|
int grid_index;
|
|
int grid_size;
|
|
|
|
/** Grid coordinates in object space. */
|
|
float (*grid_co)[3];
|
|
};
|
|
|
|
struct MultiresUnsubdivideContext {
|
|
/* Input Mesh to un-subdivide. */
|
|
Mesh *original_mesh;
|
|
MDisps *original_mdisp;
|
|
|
|
/** Number of subdivision in the grids of the input mesh. */
|
|
int num_original_levels;
|
|
|
|
/** Level 0 base mesh after applying the maximum amount of unsubdivisions. */
|
|
Mesh *base_mesh;
|
|
|
|
/** Limit on how many levels down the unsubdivide operation should create, if possible. */
|
|
int max_new_levels;
|
|
|
|
/** New levels that were created after unsubdividing. */
|
|
int num_new_levels;
|
|
|
|
/**
|
|
* Number of subdivisions that should be applied to the base mesh.
|
|
* (num_new_levels + num_original_levels).
|
|
*/
|
|
int num_total_levels;
|
|
|
|
/** Data for the new grids, indexed by base mesh loop index. */
|
|
int num_grids;
|
|
MultiresUnsubdivideGrid *base_mesh_grids;
|
|
|
|
/* Private data. */
|
|
BMesh *bm_original_mesh;
|
|
blender::Span<int> loop_to_face_map;
|
|
const int *base_to_orig_vmap;
|
|
};
|
|
|
|
/* --------------------------------------------------------------------
|
|
* Construct/destruct reshape context.
|
|
*/
|
|
|
|
void multires_unsubdivide_context_init(MultiresUnsubdivideContext *context,
|
|
Mesh *original_mesh,
|
|
MultiresModifierData *mmd);
|
|
void multires_unsubdivide_context_free(MultiresUnsubdivideContext *context);
|
|
|
|
/* --------------------------------------------------------------------
|
|
* Rebuild Lower Subdivisions.
|
|
*/
|
|
|
|
/* Rebuilds all subdivision to the level 0 base mesh. */
|
|
bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context);
|