diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 05aa9111fa3..a65817474b4 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -71,6 +71,11 @@ #include "DEG_depsgraph_query.h" #include "BLO_read_write.h" +#include "BLI_float3.hh" + +#include "BLI_index_range.hh" +#include "BLI_task.hh" + static void mesh_clear_geometry(Mesh *mesh); static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata); @@ -1575,17 +1580,71 @@ 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]) +MINLINE void zminmax_v3v3_v3(float min[3], float max[3], const float vec[3]) +{ + min[0] = min[0] > vec[0] ? vec[0] : min[0]; + min[1] = min[1] > vec[1] ? vec[1] : min[1]; + min[2] = min[2] > vec[2] ? vec[2] : min[2]; + max[0] = max[0] < vec[0] ? vec[0] : max[0]; + max[1] = max[1] < vec[1] ? vec[1] : max[1]; + max[2] = max[2] < vec[2] ? vec[2] : max[2]; +} +bool BKE_mesh_minmax_st(const Mesh *me, float r_min[3], float r_max[3]) { + double s = PIL_check_seconds_timer(); int i = me->totvert; MVert *mvert; for (mvert = me->mvert; i--; mvert++) { minmax_v3v3_v3(r_min, r_max, mvert->co); } - + double e = PIL_check_seconds_timer(); + printf("BKE_mesh_minmax %d verts in %.6f ms\n", me->totvert, (e - s) * 1000); return (me->totvert != 0); } +struct MinMaxResult { + blender::float3 min; + blender::float3 max; + inline void add_coordinate(const blender::float3 &co) + { + minmax_v3v3_v3(min, max, co); + } +}; + +bool BKE_mesh_minmax(const Mesh *mesh, float r_min[3], float r_max[3]) +{ + using namespace blender; + if (mesh->totvert == 0) { + return false; + } + double s = PIL_check_seconds_timer(); + const MinMaxResult minmax = threading::parallel_reduce( + IndexRange(mesh->totvert), + 1024, + {float3(FLT_MAX), float3(-FLT_MAX)}, + [mesh](IndexRange range, const MinMaxResult &init) { + MinMaxResult result = init; + for (const int i : range) { + result.add_coordinate(mesh->mvert[i].co); + //zminmax_v3v3_v3(result.min, result.max, mesh->mvert[i].co); + } + return result; + }, + [](const MinMaxResult &a, const MinMaxResult &b) { + MinMaxResult result = a; + result.add_coordinate(b.min); + result.add_coordinate(b.max); + return result; + }); + + copy_v3_v3(r_min, minmax.min); + copy_v3_v3(r_max, minmax.max); + double e = PIL_check_seconds_timer(); + printf("BKE_mesh_minmax %d verts in %.6f ms\n", mesh->totvert, (e - s) * 1000); + + return true; +} + void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys) { int i; diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index d32470c0dcc..3875036aedc 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -40,7 +40,7 @@ extern "C" { * Typically accessed from #Mesh.mvert */ typedef struct MVert { - float co[3]; + float co[4]; /** * Cache the normal, can always be recalculated from surrounding faces. * See #CD_CUSTOMLOOPNORMAL for custom normals.