Blender V4.5
pointcloud.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <optional>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_defaults.h"
14#include "DNA_material_types.h"
15#include "DNA_object_types.h"
17
18#include "BLI_bounds.hh"
19#include "BLI_index_range.hh"
20#include "BLI_resource_scope.hh"
21#include "BLI_span.hh"
22#include "BLI_utildefines.h"
23#include "BLI_vector.hh"
24
25#include "BKE_anim_data.hh"
30#include "BKE_customdata.hh"
31#include "BKE_geometry_set.hh"
32#include "BKE_idtype.hh"
33#include "BKE_lib_id.hh"
34#include "BKE_lib_query.hh"
35#include "BKE_modifier.hh"
36#include "BKE_object.hh"
37#include "BKE_object_types.hh"
38#include "BKE_pointcloud.hh"
39
40#include "BLT_translation.hh"
41
43
44#include "BLO_read_write.hh"
45
47using blender::float3;
50using blender::Span;
52using blender::VArray;
53using blender::Vector;
54
55constexpr StringRef ATTR_POSITION = "position";
56
57static void pointcloud_init_data(ID *id)
58{
59 PointCloud *pointcloud = (PointCloud *)id;
61
63
64 new (&pointcloud->attribute_storage.wrap()) blender::bke::AttributeStorage();
65 pointcloud->runtime = new blender::bke::PointCloudRuntime();
66
67 CustomData_reset(&pointcloud->pdata);
68}
69
70static void pointcloud_copy_data(Main * /*bmain*/,
71 std::optional<Library *> /*owner_library*/,
72 ID *id_dst,
73 const ID *id_src,
74 const int /*flag*/)
75{
76 PointCloud *pointcloud_dst = (PointCloud *)id_dst;
77 const PointCloud *pointcloud_src = (const PointCloud *)id_src;
78 pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_src->mat));
79
81 &pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, pointcloud_dst->totpoint);
82 new (&pointcloud_dst->attribute_storage.wrap())
84
85 pointcloud_dst->runtime = new blender::bke::PointCloudRuntime();
86 pointcloud_dst->runtime->bounds_cache = pointcloud_src->runtime->bounds_cache;
87 pointcloud_dst->runtime->bounds_with_radius_cache =
88 pointcloud_src->runtime->bounds_with_radius_cache;
89 pointcloud_dst->runtime->bvh_cache = pointcloud_src->runtime->bvh_cache;
90 if (pointcloud_src->runtime->bake_materials) {
91 pointcloud_dst->runtime->bake_materials =
92 std::make_unique<blender::bke::bake::BakeMaterialsList>(
93 *pointcloud_src->runtime->bake_materials);
94 }
95
96 pointcloud_dst->batch_cache = nullptr;
97}
98
99static void pointcloud_free_data(ID *id)
100{
101 PointCloud *pointcloud = (PointCloud *)id;
102 BKE_animdata_free(&pointcloud->id, false);
104 CustomData_free(&pointcloud->pdata);
105 pointcloud->attribute_storage.wrap().~AttributeStorage();
106 MEM_SAFE_FREE(pointcloud->mat);
107 delete pointcloud->runtime;
108}
109
111{
112 PointCloud *pointcloud = (PointCloud *)id;
113 for (int i = 0; i < pointcloud->totcol; i++) {
115 }
116}
117
118static void pointcloud_blend_write(BlendWriter *writer, ID *id, const void *id_address)
119{
120 using namespace blender;
121 using namespace blender::bke;
122 PointCloud *pointcloud = (PointCloud *)id;
123
124 ResourceScope scope;
125 Vector<CustomDataLayer, 16> point_layers;
126 bke::AttributeStorage::BlendWriteData attribute_data{scope};
128 pointcloud->attribute_storage.wrap(), {{AttrDomain::Point, &point_layers}}, attribute_data);
130 pointcloud->pdata, AttrDomain::Point, pointcloud->totpoint, point_layers, attribute_data);
131 if (attribute_data.attributes.is_empty()) {
132 pointcloud->attribute_storage.dna_attributes = nullptr;
133 pointcloud->attribute_storage.dna_attributes_num = 0;
134 }
135 else {
136 pointcloud->attribute_storage.dna_attributes = attribute_data.attributes.data();
137 pointcloud->attribute_storage.dna_attributes_num = attribute_data.attributes.size();
138 }
139
140 /* Write LibData */
141 BLO_write_id_struct(writer, PointCloud, id_address, &pointcloud->id);
142 BKE_id_blend_write(writer, &pointcloud->id);
143
144 /* Direct data */
146 &pointcloud->pdata,
147 point_layers,
148 pointcloud->totpoint,
150 &pointcloud->id);
151 pointcloud->attribute_storage.wrap().blend_write(*writer, attribute_data);
152
153 BLO_write_pointer_array(writer, pointcloud->totcol, pointcloud->mat);
154}
155
157{
158 PointCloud *pointcloud = (PointCloud *)id;
159
160 /* Geometry */
161 CustomData_blend_read(reader, &pointcloud->pdata, pointcloud->totpoint);
162 pointcloud->attribute_storage.wrap().blend_read(*reader);
163
164 /* Forward compatibility. To be removed when runtime format changes. */
166
167 /* Materials */
168 BLO_read_pointer_array(reader, pointcloud->totcol, (void **)&pointcloud->mat);
169
170 pointcloud->runtime = new blender::bke::PointCloudRuntime();
171}
172
174 /*id_code*/ PointCloud::id_type,
175 /*id_filter*/ FILTER_ID_PT,
176 /*dependencies_id_types*/ FILTER_ID_MA,
177 /*main_listbase_index*/ INDEX_ID_PT,
178 /*struct_size*/ sizeof(PointCloud),
179 /*name*/ "PointCloud",
180 /*name_plural*/ N_("pointclouds"),
181 /*translation_context*/ BLT_I18NCONTEXT_ID_POINTCLOUD,
183 /*asset_type_info*/ nullptr,
184
185 /*init_data*/ pointcloud_init_data,
186 /*copy_data*/ pointcloud_copy_data,
187 /*free_data*/ pointcloud_free_data,
188 /*make_local*/ nullptr,
189 /*foreach_id*/ pointcloud_foreach_id,
190 /*foreach_cache*/ nullptr,
191 /*foreach_path*/ nullptr,
192 /*owner_pointer_get*/ nullptr,
193
194 /*blend_write*/ pointcloud_blend_write,
195 /*blend_read_data*/ pointcloud_blend_read_data,
196 /*blend_read_after_liblink*/ nullptr,
197
198 /*blend_read_undo_preserve*/ nullptr,
199
200 /*lib_override_apply_post*/ nullptr,
201};
202
203template<typename T>
205 const StringRef name,
206 const T default_value)
207{
209
210 const T *data = (const T *)CustomData_get_layer_named(&pointcloud.pdata, type, name);
211 if (data != nullptr) {
212 return VArray<T>::ForSpan(Span<T>(data, pointcloud.totpoint));
213 }
214 return VArray<T>::ForSingle(default_value, pointcloud.totpoint);
215}
216
217template<typename T>
218static Span<T> get_span_attribute(const PointCloud &pointcloud, const StringRef name)
219{
221
222 T *data = (T *)CustomData_get_layer_named(&pointcloud.pdata, type, name);
223 if (data == nullptr) {
224 return {};
225 }
226 return {data, pointcloud.totpoint};
227}
228
229template<typename T>
231 const StringRef name,
232 const T default_value = T())
233{
234 if (pointcloud.totpoint <= 0) {
235 return {};
236 }
238
240 &pointcloud.pdata, type, name, pointcloud.totpoint);
241 if (data != nullptr) {
242 return {data, pointcloud.totpoint};
243 }
245 &pointcloud.pdata, type, CD_SET_DEFAULT, pointcloud.totpoint, name);
246 MutableSpan<T> span = {data, pointcloud.totpoint};
247 if (pointcloud.totpoint > 0 && span.first() != default_value) {
248 span.fill(default_value);
249 }
250 return span;
251}
252
253Span<float3> PointCloud::positions() const
254{
255 return get_span_attribute<float3>(*this, "position");
256}
257MutableSpan<float3> PointCloud::positions_for_write()
258{
259 return get_mutable_attribute<float3>(*this, "position");
260}
261
262VArray<float> PointCloud::radius() const
263{
264 return get_varray_attribute<float>(*this, "radius", 0.01f);
265}
266MutableSpan<float> PointCloud::radius_for_write()
267{
268 return get_mutable_attribute<float>(*this, "radius", 0.01f);
269}
270
271PointCloud *BKE_pointcloud_add(Main *bmain, const char *name)
272{
273 PointCloud *pointcloud = BKE_id_new<PointCloud>(bmain, name);
274
275 return pointcloud;
276}
277
279{
280 PointCloud *pointcloud = static_cast<PointCloud *>(BKE_libblock_alloc(
282
283 BKE_libblock_init_empty(&pointcloud->id);
284
285 pointcloud->totpoint = totpoint;
286
287 pointcloud->attributes_for_write().add<float3>(
289
290 return pointcloud;
291}
292
293void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src, PointCloud *pointcloud_dst)
294{
295 BLI_assert(pointcloud_src->id.tag & ID_TAG_NO_MAIN);
296
297 CustomData_free(&pointcloud_dst->pdata);
298
299 const int totpoint = pointcloud_dst->totpoint = pointcloud_src->totpoint;
300 CustomData_init_from(&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, totpoint);
301
302 pointcloud_dst->runtime->bounds_cache = pointcloud_src->runtime->bounds_cache;
303 pointcloud_dst->runtime->bounds_with_radius_cache =
304 pointcloud_src->runtime->bounds_with_radius_cache;
305 pointcloud_dst->runtime->bvh_cache = pointcloud_src->runtime->bvh_cache;
306 BKE_id_free(nullptr, pointcloud_src);
307}
308
309std::optional<blender::Bounds<float3>> PointCloud::bounds_min_max(const bool use_radius) const
310{
311 using namespace blender;
312 using namespace blender::bke;
313 if (this->totpoint == 0) {
314 return std::nullopt;
315 }
316 if (use_radius) {
317 this->runtime->bounds_with_radius_cache.ensure([&](Bounds<float3> &r_bounds) {
318 const VArray<float> radius = this->radius();
319 if (const std::optional radius_single = radius.get_if_single()) {
320 r_bounds = *this->bounds_min_max(false);
321 r_bounds.pad(*radius_single);
322 return;
323 }
324 const Span radius_span = radius.get_internal_span();
325 r_bounds = *bounds::min_max_with_radii(this->positions(), radius_span);
326 });
327 }
328 else {
329 this->runtime->bounds_cache.ensure(
330 [&](Bounds<float3> &r_bounds) { r_bounds = *bounds::min_max(this->positions()); });
331 }
332 return use_radius ? this->runtime->bounds_with_radius_cache.data() :
333 this->runtime->bounds_cache.data();
334}
335
336std::optional<int> PointCloud::material_index_max() const
337{
338 if (this->totpoint == 0) {
339 return std::nullopt;
340 }
341 std::optional<int> max_material_index = blender::bounds::max<int>(
342 this->attributes()
343 .lookup_or_default<int>("material_index", blender::bke::AttrDomain::Point, 0)
344 .varray);
345 if (max_material_index.has_value()) {
346 max_material_index = std::clamp(*max_material_index, 0, MAXMAT);
347 }
348 return max_material_index;
349}
350
351void PointCloud::count_memory(blender::MemoryCounter &memory) const
352{
353 CustomData_count_memory(this->pdata, this->totpoint, memory);
354}
355
357{
358 return blender::bke::AttributeAccessor(this,
360}
361
362blender::bke::MutableAttributeAccessor PointCloud::attributes_for_write()
363{
364 return blender::bke::MutableAttributeAccessor(
366}
367
369 const blender::StringRef name)
370{
371 return name == ATTR_POSITION;
372}
373
375{
376 dst.flag = src.flag;
377 MEM_SAFE_FREE(dst.mat);
378 dst.mat = MEM_malloc_arrayN<Material *>(src.totcol, __func__);
379 dst.totcol = src.totcol;
380 MutableSpan(dst.mat, dst.totcol).copy_from(Span(src.mat, src.totcol));
381}
382
383/* Dependency Graph */
384
386{
387 return reinterpret_cast<PointCloud *>(
388 BKE_id_copy_ex(nullptr, &pointcloud_src->id, nullptr, LIB_ID_COPY_LOCALIZE));
389}
390
392 Scene *scene,
393 Object *object,
394 blender::bke::GeometrySet &geometry_set)
395{
396 /* Modifier evaluation modes. */
397 const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
398 const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
399 ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
400 const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
401
403
404 /* Get effective list of modifiers to execute. Some effects like shape keys
405 * are added as virtual modifiers before the user created modifiers. */
406 VirtualModifierData virtual_modifier_data;
407 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtual_modifier_data);
408
409 /* Evaluate modifiers. */
410 for (; md; md = md->next) {
412
413 if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
414 continue;
415 }
416
417 blender::bke::ScopedModifierTimer modifier_timer{*md};
418
419 if (mti->modify_geometry_set) {
420 mti->modify_geometry_set(md, &mectx, &geometry_set);
421 }
422 }
423}
424
426 blender::bke::GeometrySet &geometry_set)
427{
428 if (!geometry_set.has<blender::bke::PointCloudComponent>()) {
429 return nullptr;
430 }
431 blender::bke::PointCloudComponent &pointcloud_component =
433 PointCloud *pointcloud = pointcloud_component.release();
434 if (pointcloud != nullptr) {
435 /* Add back, but as read-only non-owning component. */
436 pointcloud_component.replace(pointcloud, blender::bke::GeometryOwnershipType::ReadOnly);
437 }
438 else {
439 /* The component was empty, we can also remove it. */
441 }
442 return pointcloud;
443}
444
445void BKE_pointcloud_data_update(Depsgraph *depsgraph, Scene *scene, Object *object)
446{
447 /* Free any evaluated data and restore original data. */
449
450 /* Evaluate modifiers. */
451 PointCloud *pointcloud = static_cast<PointCloud *>(object->data);
454 pointcloud_evaluate_modifiers(depsgraph, scene, object, geometry_set);
455
456 PointCloud *pointcloud_eval = take_pointcloud_ownership_from_geometry_set(geometry_set);
457
458 /* If the geometry set did not contain a point cloud, we still create an empty one. */
459 if (pointcloud_eval == nullptr) {
460 pointcloud_eval = BKE_pointcloud_new_nomain(0);
461 }
462
463 /* Assign evaluated object. */
464 const bool eval_is_owned = pointcloud_eval != pointcloud;
465 BKE_object_eval_assign_data(object, &pointcloud_eval->id, eval_is_owned);
466 object->runtime->geometry_set_eval = new blender::bke::GeometrySet(std::move(geometry_set));
467}
468
469void PointCloud::tag_positions_changed()
470{
471 this->runtime->bounds_cache.tag_dirty();
472 this->runtime->bounds_with_radius_cache.tag_dirty();
473 this->runtime->bvh_cache.tag_dirty();
474}
475
476void PointCloud::tag_radii_changed()
477{
478 this->runtime->bounds_with_radius_cache.tag_dirty();
479}
480
481/* Draw Cache */
482
483void (*BKE_pointcloud_batch_cache_dirty_tag_cb)(PointCloud *pointcloud, int mode) = nullptr;
484void (*BKE_pointcloud_batch_cache_free_cb)(PointCloud *pointcloud) = nullptr;
485
487{
488 if (pointcloud->batch_cache) {
490 }
491}
492
494{
495 if (pointcloud->batch_cache) {
497 }
498}
499
500namespace blender::bke {
501
503{
504 PointCloud *pointcloud = BKE_id_new_nomain<PointCloud>(nullptr);
505 pointcloud->totpoint = totpoint;
506 return pointcloud;
507}
508
509} // namespace blender::bke
void BKE_animdata_free(ID *id, bool do_id_user)
Definition anim_data.cc:187
CustomData interface, see also DNA_customdata_types.h.
void CustomData_blend_write_prepare(CustomData &data, blender::bke::AttrDomain domain, int domain_size, blender::Vector< CustomDataLayer, 16 > &layers_to_write, blender::bke::AttributeStorage::BlendWriteData &write_data)
void CustomData_count_memory(const CustomData &data, int totelem, blender::MemoryCounter &memory)
void * CustomData_get_layer_named_for_write(CustomData *data, eCustomDataType type, blender::StringRef name, int totelem)
@ CD_SET_DEFAULT
const void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void * CustomData_add_layer_named(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem, blender::StringRef name)
void CustomData_reset(CustomData *data)
void CustomData_blend_write(BlendWriter *writer, CustomData *data, blender::Span< CustomDataLayer > layers_to_write, int count, eCustomDataMask cddata_mask, ID *id)
void CustomData_free(CustomData *data)
void CustomData_init_from(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
void CustomData_blend_read(BlendDataReader *reader, CustomData *data, int count)
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:44
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:165
IDTypeInfo IDType_ID_PT
void * BKE_libblock_alloc(Main *bmain, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition lib_id.cc:1428
void BKE_id_free(Main *bmain, void *idv)
@ LIB_ID_CREATE_LOCALIZE
@ LIB_ID_COPY_LOCALIZE
void BKE_libblock_init_empty(ID *id) ATTR_NONNULL(1)
Definition lib_id.cc:1433
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:767
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1495
void * BKE_id_new_nomain(short type, const char *name)
Definition lib_id.cc:1500
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2611
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_USER
void BKE_modifiers_clear_errors(Object *ob)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
ModifierData * BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *data)
ModifierApplyFlag
@ MOD_APPLY_USECACHE
@ MOD_APPLY_RENDER
General operations, lookup, etc. for blender objects.
void BKE_object_eval_assign_data(Object *object, ID *data, bool is_owned)
void BKE_object_free_derived_caches(Object *ob)
General operations for point clouds.
void(* BKE_pointcloud_batch_cache_free_cb)(PointCloud *pointcloud)
void(* BKE_pointcloud_batch_cache_dirty_tag_cb)(PointCloud *pointcloud, int mode)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
void BLO_write_pointer_array(BlendWriter *writer, int64_t num, const void *data_ptr)
void BLO_read_pointer_array(BlendDataReader *reader, int64_t array_size, void **ptr_p)
Definition readfile.cc:5402
#define BLT_I18NCONTEXT_ID_POINTCLOUD
@ DAG_EVAL_RENDER
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
@ INDEX_ID_PT
Definition DNA_ID.h:1238
@ ID_TAG_NO_MAIN
Definition DNA_ID.h:886
@ ID_PT
#define DNA_struct_default_get(struct_name)
#define MAXMAT
@ eModifierMode_Render
@ eModifierMode_Realtime
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
static const char * ATTR_POSITION
BMesh const char void * data
BPy_StructRNA * depsgraph
static const CPPType & get()
AttributeSet attributes
static VArray ForSingle(T value, const int64_t size)
static VArray ForSpan(Span< T > values)
constexpr void fill(const T &value) const
Definition BLI_span.hh:517
constexpr T & first() const
Definition BLI_span.hh:679
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
std::optional< T > get_if_single() const
Span< T > get_internal_span() const
void replace(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
#define FILTER_ID_MA
#define FILTER_ID_PT
#define CD_MASK_ALL
#define MEM_SAFE_FREE(v)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
#define T
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
void pointcloud_convert_storage_to_customdata(PointCloud &pointcloud)
const AttributeAccessorFunctions & pointcloud_attribute_accessor_functions()
PointCloud * pointcloud_new_no_attributes(int totpoint)
void attribute_storage_blend_write_prepare(AttributeStorage &data, const Map< AttrDomain, Vector< CustomDataLayer, 16 > * > &layers_to_write, AttributeStorage::BlendWriteData &write_data)
std::optional< T > max(const VArray< T > &values)
VecBase< float, 3 > float3
PointCloud * BKE_pointcloud_add(Main *bmain, const char *name)
static void pointcloud_init_data(ID *id)
Definition pointcloud.cc:57
PointCloud * BKE_pointcloud_copy_for_eval(const PointCloud *pointcloud_src)
void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src, PointCloud *pointcloud_dst)
static void pointcloud_free_data(ID *id)
Definition pointcloud.cc:99
static Span< T > get_span_attribute(const PointCloud &pointcloud, const StringRef name)
static void pointcloud_foreach_id(ID *id, LibraryForeachIDData *data)
static VArray< T > get_varray_attribute(const PointCloud &pointcloud, const StringRef name, const T default_value)
PointCloud * BKE_pointcloud_new_nomain(const int totpoint)
void BKE_pointcloud_batch_cache_dirty_tag(PointCloud *pointcloud, int mode)
void BKE_pointcloud_batch_cache_free(PointCloud *pointcloud)
static PointCloud * take_pointcloud_ownership_from_geometry_set(blender::bke::GeometrySet &geometry_set)
static MutableSpan< T > get_mutable_attribute(PointCloud &pointcloud, const StringRef name, const T default_value=T())
static void pointcloud_blend_write(BlendWriter *writer, ID *id, const void *id_address)
void BKE_pointcloud_data_update(Depsgraph *depsgraph, Scene *scene, Object *object)
static void pointcloud_blend_read_data(BlendDataReader *reader, ID *id)
void pointcloud_copy_parameters(const PointCloud &src, PointCloud &dst)
static void pointcloud_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int)
Definition pointcloud.cc:70
void(* BKE_pointcloud_batch_cache_free_cb)(PointCloud *pointcloud)
static void pointcloud_evaluate_modifiers(Depsgraph *depsgraph, Scene *scene, Object *object, blender::bke::GeometrySet &geometry_set)
void(* BKE_pointcloud_batch_cache_dirty_tag_cb)(PointCloud *pointcloud, int mode)
bool BKE_pointcloud_attribute_required(const PointCloud *, const blender::StringRef name)
void pad(const PaddingT &padding)
Definition DNA_ID.h:404
int tag
Definition DNA_ID.h:424
struct ModifierData * next
void(* modify_geometry_set)(ModifierData *md, const ModifierEvalContext *ctx, blender::bke::GeometrySet *geometry_set)
struct Material ** mat
PointCloudRuntimeHandle * runtime
struct AttributeStorage attribute_storage
struct CustomData pdata
GeometryComponent & get_component_for_write(GeometryComponent::Type component_type)
bool has(const GeometryComponent::Type component_type) const
static GeometrySet from_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void remove(const GeometryComponent::Type component_type)
i
Definition text_draw.cc:230
#define N_(msgid)