Mesh: Parallelize bounding box calculation (WIP)

This replaces the single-threaded calculation of mesh min and max
positions with a `parallel_reduce` loop. Since the bounding box
of a mesh is retrieved quite often (at the end of each evaluation,
currently 2(?!) times when leaving edit mode, etc.), this makes for a
quite noticeable speedup actually.

On my Ryzen 3700x and a 4.2 million vertex mesh, I observed
a 4.4x performance increase, from 14 ms to 4.4 ms.

I added some methods to `float3` so they would be inlined, but
they're also a nice addition, since they're used often anyway.

Differential Revision: https://developer.blender.org/D13572
This commit is contained in:
Hans Goudey 2021-12-22 11:04:03 -06:00
parent 3579a9e0fc
commit 6a71b2af66
Notes: blender-bot 2023-02-14 09:48:23 +01:00
Referenced by commit 6d7dbdbb44, Point Cloud: Optimize bounding box calculation
2 changed files with 46 additions and 5 deletions

View File

@ -36,13 +36,16 @@
#include "BLI_bitmap.h"
#include "BLI_edgehash.h"
#include "BLI_endian_switch.h"
#include "BLI_float3.hh"
#include "BLI_ghash.h"
#include "BLI_hash.h"
#include "BLI_index_range.hh"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_string.h"
#include "BLI_task.hh"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@ -1577,13 +1580,35 @@ void BKE_mesh_looptri_get_real_edges(const Mesh *mesh, const MLoopTri *looptri,
bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3])
{
int i = me->totvert;
MVert *mvert;
for (mvert = me->mvert; i--; mvert++) {
minmax_v3v3_v3(r_min, r_max, mvert->co);
using namespace blender;
if (me->totvert == 0) {
return false;
}
return (me->totvert != 0);
struct Result {
float3 min;
float3 max;
};
const Result minmax = threading::parallel_reduce(
IndexRange(me->totvert),
1024,
Result{float3(FLT_MAX), float3(-FLT_MAX)},
[&](IndexRange range, const Result &init) {
Result result = init;
for (const int i : range) {
float3::min_max(me->mvert[i].co, result.min, result.max);
}
return result;
},
[](const Result &a, const Result &b) {
return Result{float3::min(a.min, b.min), float3::max(a.max, b.max)};
});
copy_v3_v3(r_min, float3::min(minmax.min, r_min));
copy_v3_v3(r_max, float3::max(minmax.max, r_max));
return true;
}
void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys)

View File

@ -228,6 +228,22 @@ struct float3 {
return result;
}
static float3 min(const float3 &a, const float3 &b)
{
return {a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y, a.z < b.z ? a.z : b.z};
}
static float3 max(const float3 &a, const float3 &b)
{
return {a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y, a.z > b.z ? a.z : b.z};
}
static void min_max(const float3 &vector, float3 &min, float3 &max)
{
min = float3::min(vector, min);
max = float3::max(vector, max);
}
static float3 safe_divide(const float3 &a, const float b)
{
return (b != 0.0f) ? a / b : float3(0.0f);