diff options
Diffstat (limited to 'source/blender/blenkernel/intern/pointcloud.cc')
-rw-r--r-- | source/blender/blenkernel/intern/pointcloud.cc | 90 |
1 files changed, 76 insertions, 14 deletions
diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc index 1db14dc3dc8..b5f016e4d76 100644 --- a/source/blender/blenkernel/intern/pointcloud.cc +++ b/source/blender/blenkernel/intern/pointcloud.cc @@ -25,10 +25,13 @@ #include "DNA_object_types.h" #include "DNA_pointcloud_types.h" +#include "BLI_index_range.hh" #include "BLI_listbase.h" -#include "BLI_math.h" +#include "BLI_math_vec_types.hh" #include "BLI_rand.h" +#include "BLI_span.hh" #include "BLI_string.h" +#include "BLI_task.hh" #include "BLI_utildefines.h" #include "BKE_anim_data.h" @@ -51,6 +54,10 @@ #include "BLO_read_write.h" +using blender::float3; +using blender::IndexRange; +using blender::Span; + /* PointCloud datablock */ static void pointcloud_random(PointCloud *pointcloud); @@ -79,7 +86,7 @@ static void pointcloud_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_s { PointCloud *pointcloud_dst = (PointCloud *)id_dst; const PointCloud *pointcloud_src = (const PointCloud *)id_src; - pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_dst->mat)); + pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_src->mat)); const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE; CustomData_copy(&pointcloud_src->pdata, @@ -105,7 +112,7 @@ static void pointcloud_foreach_id(ID *id, LibraryForeachIDData *data) { PointCloud *pointcloud = (PointCloud *)id; for (int i = 0; i < pointcloud->totcol; i++) { - BKE_LIB_FOREACHID_PROCESS(data, pointcloud->mat[i], IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, pointcloud->mat[i], IDWALK_CB_USER); } } @@ -175,6 +182,7 @@ IDTypeInfo IDType_ID_PT = { /* name_plural */ "pointclouds", /* translation_context */ BLT_I18NCONTEXT_ID_POINTCLOUD, /* flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE, + /* asset_type_info */ nullptr, /* init_data */ pointcloud_init_data, /* copy_data */ pointcloud_copy_data, @@ -182,6 +190,7 @@ IDTypeInfo IDType_ID_PT = { /* make_local */ nullptr, /* foreach_id */ pointcloud_foreach_id, /* foreach_cache */ nullptr, + /* foreach_path */ nullptr, /* owner_get */ nullptr, /* blend_write */ pointcloud_blend_write, @@ -259,18 +268,70 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint) return pointcloud; } -void BKE_pointcloud_minmax(const struct PointCloud *pointcloud, float r_min[3], float r_max[3]) +struct MinMaxResult { + float3 min; + float3 max; +}; + +static MinMaxResult min_max_no_radii(Span<float3> positions) +{ + using namespace blender::math; + + return blender::threading::parallel_reduce( + positions.index_range(), + 1024, + MinMaxResult{float3(FLT_MAX), float3(-FLT_MAX)}, + [&](IndexRange range, const MinMaxResult &init) { + MinMaxResult result = init; + for (const int i : range) { + min_max(positions[i], result.min, result.max); + } + return result; + }, + [](const MinMaxResult &a, const MinMaxResult &b) { + return MinMaxResult{min(a.min, b.min), max(a.max, b.max)}; + }); +} + +static MinMaxResult min_max_with_radii(Span<float3> positions, Span<float> radii) { - float(*pointcloud_co)[3] = pointcloud->co; - float *pointcloud_radius = pointcloud->radius; - for (int a = 0; a < pointcloud->totpoint; a++) { - float *co = pointcloud_co[a]; - float radius = (pointcloud_radius) ? pointcloud_radius[a] : 0.0f; - const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius}; - const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius}; - DO_MIN(co_min, r_min); - DO_MAX(co_max, r_max); + using namespace blender::math; + + return blender::threading::parallel_reduce( + positions.index_range(), + 1024, + MinMaxResult{float3(FLT_MAX), float3(-FLT_MAX)}, + [&](IndexRange range, const MinMaxResult &init) { + MinMaxResult result = init; + for (const int i : range) { + result.min = min(positions[i] - radii[i], result.min); + result.max = max(positions[i] + radii[i], result.max); + } + return result; + }, + [](const MinMaxResult &a, const MinMaxResult &b) { + return MinMaxResult{min(a.min, b.min), max(a.max, b.max)}; + }); +} + +bool BKE_pointcloud_minmax(const PointCloud *pointcloud, float r_min[3], float r_max[3]) +{ + using namespace blender::math; + + if (!pointcloud->totpoint) { + return false; } + + Span<float3> positions{reinterpret_cast<float3 *>(pointcloud->co), pointcloud->totpoint}; + const MinMaxResult min_max = (pointcloud->radius) ? + min_max_with_radii(positions, + {pointcloud->radius, pointcloud->totpoint}) : + min_max_no_radii(positions); + + copy_v3_v3(r_min, min(min_max.min, float3(r_min))); + copy_v3_v3(r_max, max(min_max.max, float3(r_max))); + + return true; } BoundBox *BKE_pointcloud_boundbox_get(Object *ob) @@ -285,7 +346,7 @@ BoundBox *BKE_pointcloud_boundbox_get(Object *ob) ob->runtime.bb = static_cast<BoundBox *>(MEM_callocN(sizeof(BoundBox), "pointcloud boundbox")); } - blender::float3 min, max; + float3 min, max; INIT_MINMAX(min, max); if (ob->runtime.geometry_set_eval != nullptr) { ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max); @@ -417,6 +478,7 @@ void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene } /* Draw Cache */ + void (*BKE_pointcloud_batch_cache_dirty_tag_cb)(PointCloud *pointcloud, int mode) = nullptr; void (*BKE_pointcloud_batch_cache_free_cb)(PointCloud *pointcloud) = nullptr; |