Mesh: Avoid calculating normals when building BVH tree

Though they are sometimes used by users of the BVH tree, mostly
vertex normals when building the BVH tree is unnecessary. Skip it
instead and avoid storing the vertex normals in the BVH tree cache.
They are just calculated in the few places they are actually needed.
This should save at least a few percent of the runtime in some cases
where the normals weren't needed otherwise.
This commit is contained in:
Hans Goudey 2022-11-13 23:54:07 -06:00
parent cc12d2a5a0
commit 276d7f7c19
6 changed files with 27 additions and 24 deletions

View File

@ -60,7 +60,6 @@ typedef struct BVHTreeFromMesh {
/* Vertex array, so that callbacks have instant access to data. */
const struct MVert *vert;
const float (*vert_normals)[3];
const struct MEdge *edge;
const struct MFace *face;
const struct MLoop *loop;

View File

@ -74,6 +74,7 @@ typedef struct ShrinkwrapTreeData {
BVHTreeFromMesh treeData;
const struct MPoly *polys;
const float (*vert_normals)[3];
const float (*pnors)[3];
const float (*clnors)[3];
ShrinkwrapBoundaryData *boundary;

View File

@ -578,7 +578,6 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
const MFace *face,
const MLoop *loop,
const MLoopTri *looptri,
const float (*vert_normals)[3],
BVHTreeFromMesh *r_data)
{
memset(r_data, 0, sizeof(*r_data));
@ -590,7 +589,6 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
r_data->face = face;
r_data->loop = loop;
r_data->looptri = looptri;
r_data->vert_normals = vert_normals;
switch (bvh_cache_type) {
case BVHTREE_FROM_VERTS:
@ -778,7 +776,7 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_VERTS, vert, nullptr, nullptr, nullptr, nullptr, nullptr, data);
tree, BVHTREE_FROM_VERTS, vert, nullptr, nullptr, nullptr, nullptr, data);
}
return tree;
@ -913,7 +911,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_EDGES, vert, edge, nullptr, nullptr, nullptr, nullptr, data);
tree, BVHTREE_FROM_EDGES, vert, edge, nullptr, nullptr, nullptr, data);
}
return tree;
@ -1130,7 +1128,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_LOOPTRI, vert, nullptr, nullptr, mloop, looptri, nullptr, data);
tree, BVHTREE_FROM_LOOPTRI, vert, nullptr, nullptr, mloop, looptri, data);
}
return tree;
@ -1233,16 +1231,17 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
const Span<MLoop> loops = mesh->loops();
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(nullptr,
bvh_cache_type,
verts.data(),
edges.data(),
(const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
loops.data(),
looptri,
BKE_mesh_vertex_normals_ensure(mesh),
data);
{
SCOPED_TIMER_AVERAGED(__func__);
bvhtree_from_mesh_setup_data(nullptr,
bvh_cache_type,
verts.data(),
edges.data(),
(const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
loops.data(),
looptri,
data);
}
bool lock_started = false;
data->cached = bvhcache_find(
bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, &mesh->runtime->eval_mutex);

View File

@ -1377,6 +1377,7 @@ BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop
}
static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
const float (*vert_normals)[3],
uint v_idx,
RNG *rng,
float max_length,
@ -1388,7 +1389,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
float radius;
copy_v3_v3(co, treedata->vert[v_idx].co);
negate_v3_v3(no, treedata->vert_normals[v_idx]);
negate_v3_v3(no, vert_normals[v_idx]);
float vec_len = sin(max_diversion);
float offset[3];
@ -1518,9 +1519,12 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
BKE_bvhtree_from_mesh_get(&treedata, tmp_mesh ? tmp_mesh : mesh, BVHTREE_FROM_LOOPTRI, 2);
rng = BLI_rng_new_srandom(0);
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(tmp_mesh ? tmp_mesh : mesh);
for (int i = 0; i < mvert_num; i++) {
if (find_internal_spring_target_vertex(
&treedata,
vert_normals,
i,
rng,
clmd->sim_parms->internal_spring_max_length,

View File

@ -115,6 +115,7 @@ bool BKE_shrinkwrap_init_tree(
data->mesh = mesh;
data->polys = BKE_mesh_polys(mesh);
data->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
if (shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) {
data->bvh = BKE_bvhtree_from_mesh_get(&data->treeData, mesh, BVHTREE_FROM_VERTS, 2);
@ -993,8 +994,8 @@ static void target_project_edge(const ShrinkwrapTreeData *tree,
CLAMP(x, 0, 1);
float vedge_no[2][3];
copy_v3_v3(vedge_no[0], data->vert_normals[edge->v1]);
copy_v3_v3(vedge_no[1], data->vert_normals[edge->v2]);
copy_v3_v3(vedge_no[0], tree->vert_normals[edge->v1]);
copy_v3_v3(vedge_no[1], tree->vert_normals[edge->v2]);
interp_v3_v3v3(hit_co, vedge_co[0], vedge_co[1], x);
interp_v3_v3v3(hit_no, vedge_no[0], vedge_no[1], x);
@ -1040,9 +1041,9 @@ static void mesh_looptri_target_project(void *userdata,
}
/* Decode normals */
copy_v3_v3(vtri_no[0], tree->treeData.vert_normals[loop[0]->v]);
copy_v3_v3(vtri_no[1], tree->treeData.vert_normals[loop[1]->v]);
copy_v3_v3(vtri_no[2], tree->treeData.vert_normals[loop[2]->v]);
copy_v3_v3(vtri_no[0], tree->vert_normals[loop[0]->v]);
copy_v3_v3(vtri_no[1], tree->vert_normals[loop[1]->v]);
copy_v3_v3(vtri_no[2], tree->vert_normals[loop[2]->v]);
/* Solve the equations for the triangle */
if (target_project_solve_point_tri(vtri_co, vtri_no, co, raw_hit_co, dist_sq, hit_co, hit_no)) {
@ -1176,7 +1177,7 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
{
const BVHTreeFromMesh *treeData = &tree->treeData;
const MLoopTri *tri = &treeData->looptri[looptri_idx];
const float(*vert_normals)[3] = tree->treeData.vert_normals;
const float(*vert_normals)[3] = tree->vert_normals;
/* Interpolate smooth normals if enabled. */
if ((tree->polys[tri->poly].flag & ME_SMOOTH) != 0) {

View File

@ -255,7 +255,6 @@ static void snap_object_data_mesh_get(SnapObjectContext *sctx,
r_treedata, me_eval, use_hide ? BVHTREE_FROM_LOOPTRI_NO_HIDDEN : BVHTREE_FROM_LOOPTRI, 4);
BLI_assert(r_treedata->vert == verts.data());
BLI_assert(!verts.data() || r_treedata->vert_normals);
BLI_assert(r_treedata->loop == loops.data());
BLI_assert(!polys.data() || r_treedata->looptri);
BLI_assert(!r_treedata->tree || r_treedata->looptri);