Attributes: Integrate implicit sharing with the attribute API #107059

Merged
Jacques Lucke merged 8 commits from HooglyBoogly/blender:implicit-sharing-attribute-api into main 2023-04-19 11:21:21 +02:00
83 changed files with 488 additions and 366 deletions

View File

@ -86,6 +86,8 @@ struct AttributeInit {
VArray,
/** #AttributeInitMoveArray. */
MoveArray,
/** #AttributeInitShared. */
Shared,
};
Type type;
AttributeInit(const Type type) : type(type) {}
@ -121,9 +123,6 @@ struct AttributeInitVArray : public AttributeInit {
* Sometimes data is created before a geometry component is available. In that case, it's
* preferable to move data directly to the created attribute to avoid a new allocation and a copy.
*
* Note that this will only have a benefit for attributes that are stored directly as contiguous
* arrays, so not for some built-in attributes.
*
* The array must be allocated with MEM_*, since `attribute_try_create` will free the array if it
* can't be used directly, and that is generally how Blender expects custom data to be allocated.
*/
@ -133,6 +132,20 @@ struct AttributeInitMoveArray : public AttributeInit {
AttributeInitMoveArray(void *data) : AttributeInit(Type::MoveArray), data(data) {}
};
/**
* Create a shared attribute by adding a user to a shared data array.
* The sharing info has ownership of the provided contiguous array.
*/
struct AttributeInitShared : public AttributeInit {
const void *data = nullptr;
const ImplicitSharingInfo *sharing_info = nullptr;
AttributeInitShared(const void *data, const ImplicitSharingInfo &sharing_info)
: AttributeInit(Type::Shared), data(data), sharing_info(&sharing_info)
{
}
};
/* Returns false when the iteration should be stopped. */
using AttributeForeachCallback =
FunctionRef<bool(const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data)>;
@ -151,6 +164,21 @@ template<typename T> struct AttributeReader {
*/
eAttrDomain domain;
/**
* Information about shared ownership of the attribute array. This will only be provided
* if the virtual array directly references the contiguous original attribute array.
*/
const ImplicitSharingInfo *sharing_info;
const VArray<T> &operator*() const
{
return this->varray;
}
VArray<T> &operator*()
{
return this->varray;
}
operator bool() const
{
return this->varray;
@ -270,15 +298,25 @@ template<typename T> struct SpanAttributeWriter {
struct GAttributeReader {
GVArray varray;
eAttrDomain domain;
const ImplicitSharingInfo *sharing_info;
operator bool() const
{
return this->varray;
}
const GVArray &operator*() const
{
return this->varray;
}
GVArray &operator*()
{
return this->varray;
}
template<typename T> AttributeReader<T> typed() const
{
return {varray.typed<T>(), domain};
return {varray.typed<T>(), domain, sharing_info};
}
};
@ -457,15 +495,15 @@ class AttributeAccessor {
* Get read-only access to the attribute. If necessary, the attribute is interpolated to the
* given domain, and converted to the given type, in that order. The result may be empty.
*/
GVArray lookup(const AttributeIDRef &attribute_id,
const std::optional<eAttrDomain> domain,
const std::optional<eCustomDataType> data_type) const;
GAttributeReader lookup(const AttributeIDRef &attribute_id,
const std::optional<eAttrDomain> domain,
const std::optional<eCustomDataType> data_type) const;
/**
* Get read-only access to the attribute whereby the attribute is interpolated to the given
* domain. The result may be empty.
*/
GVArray lookup(const AttributeIDRef &attribute_id, const eAttrDomain domain) const
GAttributeReader lookup(const AttributeIDRef &attribute_id, const eAttrDomain domain) const
{
return this->lookup(attribute_id, domain, std::nullopt);
}
@ -474,7 +512,8 @@ class AttributeAccessor {
* Get read-only access to the attribute whereby the attribute is converted to the given type.
* The result may be empty.
*/
GVArray lookup(const AttributeIDRef &attribute_id, const eCustomDataType data_type) const
GAttributeReader lookup(const AttributeIDRef &attribute_id,
const eCustomDataType data_type) const
{
return this->lookup(attribute_id, std::nullopt, data_type);
}
@ -484,8 +523,8 @@ class AttributeAccessor {
* given domain and then converted to the given type, in that order. The result may be empty.
*/
template<typename T>
VArray<T> lookup(const AttributeIDRef &attribute_id,
const std::optional<eAttrDomain> domain = std::nullopt) const
AttributeReader<T> lookup(const AttributeIDRef &attribute_id,
const std::optional<eAttrDomain> domain = std::nullopt) const
{
const CPPType &cpp_type = CPPType::get<T>();
const eCustomDataType data_type = cpp_type_to_custom_data_type(cpp_type);
@ -498,23 +537,23 @@ class AttributeAccessor {
* If the attribute does not exist, a virtual array with the given default value is returned.
* If the passed in default value is null, the default value of the type is used (generally 0).
*/
GVArray lookup_or_default(const AttributeIDRef &attribute_id,
const eAttrDomain domain,
const eCustomDataType data_type,
const void *default_value = nullptr) const;
GAttributeReader lookup_or_default(const AttributeIDRef &attribute_id,
const eAttrDomain domain,
const eCustomDataType data_type,
const void *default_value = nullptr) const;
/**
* Same as the generic version above, but should be used when the type is known at compile time.
*/
template<typename T>
VArray<T> lookup_or_default(const AttributeIDRef &attribute_id,
const eAttrDomain domain,
const T &default_value) const
AttributeReader<T> lookup_or_default(const AttributeIDRef &attribute_id,
const eAttrDomain domain,
const T &default_value) const
{
if (VArray<T> varray = this->lookup<T>(attribute_id, domain)) {
if (AttributeReader<T> varray = this->lookup<T>(attribute_id, domain)) {
return varray;
}
return VArray<T>::ForSingle(default_value, this->domain_size(domain));
return {VArray<T>::ForSingle(default_value, this->domain_size(domain)), domain};
}
/**
@ -626,6 +665,15 @@ class MutableAttributeAccessor : public AttributeAccessor {
{
return fn_->add(owner_, attribute_id, domain, data_type, initializer);
}
template<typename T>
bool add(const AttributeIDRef &attribute_id,
const eAttrDomain domain,
const AttributeInit &initializer)
{
const CPPType &cpp_type = CPPType::get<T>();
const eCustomDataType data_type = cpp_type_to_custom_data_type(cpp_type);
return this->add(attribute_id, domain, data_type, initializer);
}
/**
* Find an attribute with the given id, domain and data type. If it does not exist, create a new

View File

@ -658,11 +658,18 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
ASSERT_IS_VALID_MESH(mesh_final);
}
MutableAttributeAccessor attributes = mesh_final->attributes_for_write();
SpanAttributeWriter<float3> rest_positions =
attributes.lookup_or_add_for_write_only_span<float3>("rest_position", ATTR_DOMAIN_POINT);
if (rest_positions && attributes.domain_size(ATTR_DOMAIN_POINT) > 0) {
attributes.lookup<float3>("position").materialize(rest_positions.span);
rest_positions.finish();
const AttributeReader positions = attributes.lookup<float3>("position");
if (positions) {
if (positions.sharing_info && positions.varray.is_span()) {
attributes.add<float3>("rest_position",
ATTR_DOMAIN_POINT,
AttributeInitShared(positions.varray.get_internal_span().data(),

I think you make too many implicit assumptions here:

  • The attribute is definitely shared.
  • The attribute is definitely stored as continuous array.

Both assumptions generally have to be checked for.

I think you make too many implicit assumptions here: * The attribute is definitely shared. * The attribute is definitely stored as continuous array. Both assumptions generally have to be checked for.

I thought it was reasonable to assume that sharing_info != nullptr implies varray.is_span(), but I can also check the latter explicitly too. I guess this will get nicer when attributes don't always have to be stored as contiguous arrays.

I should definitely check for sharing_info here though. I did it elsewhere and forgot here.

I thought it was reasonable to assume that `sharing_info != nullptr` implies `varray.is_span()`, but I can also check the latter explicitly too. I guess this will get nicer when attributes don't always have to be stored as contiguous arrays. I should definitely check for `sharing_info` here though. I did it elsewhere and forgot here.
*positions.sharing_info));
}
else {
attributes.add<float3>(
"rest_position", ATTR_DOMAIN_POINT, AttributeInitVArray(positions.varray));
}
}
}

View File

@ -218,6 +218,12 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
}
return true;
}
case AttributeInit::Type::Shared: {
const AttributeInitShared &init = static_cast<const AttributeInitShared &>(initializer);
const void *stored_data = CustomData_add_layer_with_data(
&custom_data, data_type, const_cast<void *>(init.data), domain_num, init.sharing_info);
return stored_data != nullptr;
}
}
BLI_assert_unreachable();
@ -293,6 +299,16 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
custom_data, data_type, attribute_id, domain_num, data, nullptr);
break;
}
case AttributeInit::Type::Shared: {
const AttributeInitShared &init = static_cast<const AttributeInitShared &>(initializer);
add_generic_custom_data_layer_with_existing_data(custom_data,
data_type,
attribute_id,
domain_num,
const_cast<void *>(init.data),
init.sharing_info);
break;
}
}
return old_layer_num < custom_data.totlayer;
}
@ -314,7 +330,7 @@ bool BuiltinCustomDataLayerProvider::layer_exists(const CustomData &custom_data)
return CustomData_has_layer(&custom_data, stored_type_);
}
GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) const
GAttributeReader BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
@ -326,22 +342,23 @@ GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) cons
const int element_num = custom_data_access_.get_element_num(owner);
if (element_num == 0) {
if (this->layer_exists(*custom_data)) {
return GVArray::ForSpan({type, nullptr, 0});
return {GVArray::ForSpan({type, nullptr, 0}), domain_, nullptr};
}
return {};
}
const void *data = nullptr;
int index;
if (stored_as_named_attribute_) {
data = CustomData_get_layer_named(custom_data, stored_type_, name_.c_str());
index = CustomData_get_named_layer_index(custom_data, stored_type_, name_.c_str());
}
else {
data = CustomData_get_layer(custom_data, stored_type_);
index = CustomData_get_layer_index(custom_data, stored_type_);
}
if (data == nullptr) {
if (index == -1) {
return {};
}
return GVArray::ForSpan({type, data, element_num});
const CustomDataLayer &layer = custom_data->layers[index];
return {GVArray::ForSpan({type, layer.data, element_num}), domain_, layer.sharing_info};
}
GAttributeWriter BuiltinCustomDataLayerProvider::try_get_for_write(void *owner) const
@ -472,7 +489,7 @@ GAttributeReader CustomDataAttributeProvider::try_get_for_read(
continue;
}
GSpan data{*type, layer.data, element_num};
return {GVArray::ForSpan(data), domain_};
return {GVArray::ForSpan(data), domain_, layer.sharing_info};
}
return {};
}
@ -729,50 +746,52 @@ static blender::GVArray try_adapt_data_type(blender::GVArray varray,
return conversions.try_convert(std::move(varray), to_type);
}
GVArray AttributeAccessor::lookup(const AttributeIDRef &attribute_id,
const std::optional<eAttrDomain> domain,
const std::optional<eCustomDataType> data_type) const
GAttributeReader AttributeAccessor::lookup(const AttributeIDRef &attribute_id,
const std::optional<eAttrDomain> domain,
const std::optional<eCustomDataType> data_type) const
{
GAttributeReader attribute = this->lookup(attribute_id);
if (!attribute) {
return {};
}
GVArray varray = std::move(attribute.varray);
if (domain.has_value()) {
if (attribute.domain != domain) {
varray = this->adapt_domain(varray, attribute.domain, *domain);
if (!varray) {
attribute.varray = this->adapt_domain(attribute.varray, attribute.domain, *domain);
attribute.domain = *domain;
attribute.sharing_info = nullptr;
if (!attribute.varray) {
return {};
}
}
}
if (data_type.has_value()) {
const CPPType &type = *custom_data_type_to_cpp_type(*data_type);
if (varray.type() != type) {
varray = try_adapt_data_type(std::move(varray), type);
if (!varray) {
if (attribute.varray.type() != type) {
attribute.varray = try_adapt_data_type(std::move(attribute.varray), type);
attribute.sharing_info = nullptr;
if (!attribute.varray) {
return {};
}
}
}
return varray;
return attribute;
}
GVArray AttributeAccessor::lookup_or_default(const AttributeIDRef &attribute_id,
const eAttrDomain domain,
const eCustomDataType data_type,
const void *default_value) const
GAttributeReader AttributeAccessor::lookup_or_default(const AttributeIDRef &attribute_id,
const eAttrDomain domain,
const eCustomDataType data_type,
const void *default_value) const
{
GVArray varray = this->lookup(attribute_id, domain, data_type);
if (varray) {
return varray;
GAttributeReader attribute = this->lookup(attribute_id, domain, data_type);
if (attribute) {
return attribute;
}
const CPPType &type = *custom_data_type_to_cpp_type(data_type);
const int64_t domain_size = this->domain_size(domain);
if (default_value == nullptr) {
return GVArray::ForSingleRef(type, domain_size, type.default_value());
return {GVArray::ForSingleRef(type, domain_size, type.default_value()), domain, nullptr};
}
return GVArray::ForSingle(type, domain_size, default_value);
return {GVArray::ForSingle(type, domain_size, default_value), domain, nullptr};
}
Set<AttributeIDRef> AttributeAccessor::all_ids() const
@ -921,7 +940,7 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer(
return true;
}
GVArray src = src_attributes.lookup(id, meta_data.domain);
GVArray src = *src_attributes.lookup(id, meta_data.domain);
BLI_assert(src);
bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, meta_data.domain, meta_data.data_type);

View File

@ -66,7 +66,7 @@ class BuiltinAttributeProvider {
{
}
virtual GVArray try_get_for_read(const void *owner) const = 0;
virtual GAttributeReader try_get_for_read(const void *owner) const = 0;
virtual GAttributeWriter try_get_for_write(void *owner) const = 0;
virtual bool try_delete(void *owner) const = 0;
virtual bool try_create(void *onwer, const AttributeInit &initializer) const = 0;
@ -196,7 +196,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
{
}
GVArray try_get_for_read(const void *owner) const final;
GAttributeReader try_get_for_read(const void *owner) const final;
GAttributeWriter try_get_for_write(void *owner) const final;
bool try_delete(void *owner) const final;
bool try_create(void *owner, const AttributeInit &initializer) const final;
@ -279,7 +279,7 @@ inline GAttributeReader lookup(const void *owner, const AttributeIDRef &attribut
const StringRef name = attribute_id.name();
if (const BuiltinAttributeProvider *provider =
providers.builtin_attribute_providers().lookup_default_as(name, nullptr)) {
return {provider->try_get_for_read(owner), provider->domain()};
return provider->try_get_for_read(owner);
}
}
for (const DynamicAttributesProvider *provider : providers.dynamic_attribute_providers()) {

View File

@ -1280,7 +1280,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
blender::bke::AttributeAccessor attributes = mesh->attributes();
mask = looptri_no_hidden_map_get(
mesh->polys(),
attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false),
*attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false),
looptris.size(),
&mask_bits_act_len);
ATTR_FALLTHROUGH;

View File

@ -747,7 +747,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
Span<float> radii = {};
if (main_attributes.contains("radius")) {
radii = evaluated_attribute_if_necessary(
main_attributes.lookup_or_default<float>("radius", ATTR_DOMAIN_POINT, 1.0f),
*main_attributes.lookup_or_default<float>("radius", ATTR_DOMAIN_POINT, 1.0f),
main,
main.curve_type_counts(),
eval_buffer)
@ -805,7 +805,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
const eAttrDomain src_domain = meta_data.domain;
const eCustomDataType type = meta_data.data_type;
GVArray src = main_attributes.lookup(id, src_domain, type);
const GVArray src = *main_attributes.lookup(id, src_domain, type);
const eAttrDomain dst_domain = get_attribute_domain_for_mesh(mesh_attributes, id);
GSpanAttributeWriter dst = mesh_attributes.lookup_or_add_for_write_only_span(
@ -841,7 +841,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
}
const eAttrDomain src_domain = meta_data.domain;
const eCustomDataType type = meta_data.data_type;
GVArray src = profile_attributes.lookup(id, src_domain, type);
const GVArray src = *profile_attributes.lookup(id, src_domain, type);
const eAttrDomain dst_domain = get_attribute_domain_for_mesh(mesh_attributes, id);
GSpanAttributeWriter dst = mesh_attributes.lookup_or_add_for_write_only_span(

View File

@ -3237,8 +3237,9 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
blender::MutableSpan<int> poly_offsets = me->poly_offsets_for_write();
blender::MutableSpan<int> corner_verts = me->corner_verts_for_write();
const bool is_sharp = orgmesh->attributes().lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false)[0];
const bool is_sharp = orgmesh->attributes()
.lookup_or_default<bool>("sharp_face", ATTR_DOMAIN_FACE, false)
.varray[0];
BKE_mesh_smooth_flag_set(me, !is_sharp);
/* Get size (dimension) but considering scaling. */

View File

@ -131,14 +131,16 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
{
}
GVArray try_get_for_read(const void *owner) const final
GAttributeReader try_get_for_read(const void *owner) const final
{
const Instances *instances = static_cast<const Instances *>(owner);
if (instances == nullptr) {
return {};
}
Span<float4x4> transforms = instances->transforms();
return VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms);
return {VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms),
domain_,
nullptr};
}
GAttributeWriter try_get_for_write(void *owner) const final

View File

@ -1114,7 +1114,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
CD_PROP_FLOAT3,
BuiltinAttributeProvider::NonCreatable,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
point_access,
tag_component_positions_changed);

View File

@ -139,7 +139,7 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud()
ATTR_DOMAIN_POINT,
CD_PROP_FLOAT3,
CD_PROP_FLOAT3,
BuiltinAttributeProvider::NonCreatable,
BuiltinAttributeProvider::Creatable,
BuiltinAttributeProvider::NonDeletable,
point_access,
tag_component_positions_changed);

View File

@ -248,7 +248,7 @@ GVArray AttributeFieldInput::get_varray_for_context(const GeometryFieldContext &
{
const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_);
if (auto attributes = context.attributes()) {
return attributes->lookup(name_, context.domain(), data_type);
return *attributes->lookup(name_, context.domain(), data_type);
}
return {};
}
@ -304,7 +304,7 @@ GVArray IDAttributeFieldInput::get_varray_for_context(const GeometryFieldContext
const StringRef name = get_random_id_attribute_name(context.domain());
if (auto attributes = context.attributes()) {
if (GVArray attribute = attributes->lookup(name, context.domain(), CD_PROP_INT32)) {
if (GVArray attribute = *attributes->lookup(name, context.domain(), CD_PROP_INT32)) {
return attribute;
}
}
@ -334,7 +334,7 @@ GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryField
const IndexMask /*mask*/) const
{
const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_);
return context.attributes()->lookup(*anonymous_id_, context.domain(), data_type);
return *context.attributes()->lookup(*anonymous_id_, context.domain(), data_type);
}
std::string AnonymousAttributeFieldInput::socket_inspection_name() const
@ -474,7 +474,7 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
}
attributes.remove(attribute_id);
if (attributes.add(attribute_id, domain, data_type, bke::AttributeInitMoveArray{buffer})) {
if (attributes.add(attribute_id, domain, data_type, bke::AttributeInitMoveArray(buffer))) {
return true;
}

View File

@ -2507,7 +2507,7 @@ static void gpencil_generate_edgeloops(Object *ob,
const Span<MDeformVert> dverts = me->deform_verts();
const blender::Span<blender::float3> vert_normals = me->vert_normals();
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> uv_seams = attributes.lookup_or_default<bool>(
const VArray<bool> uv_seams = *attributes.lookup_or_default<bool>(
".uv_seam", ATTR_DOMAIN_EDGE, false);
/* Arrays for all edge vertices (forward and backward) that form a edge loop.
@ -2753,7 +2753,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
gpl_fill, scene->r.cfra + frame_offset, GP_GETFRAME_ADD_NEW);
int i;
const VArray<int> mesh_material_indices = me_eval->attributes().lookup_or_default<int>(
const VArray<int> mesh_material_indices = *me_eval->attributes().lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
for (i = 0; i < polys_len; i++) {
const IndexRange poly = polys[i];

View File

@ -1486,7 +1486,7 @@ bool BKE_mesh_material_index_used(Mesh *me, short index)
using namespace blender;
using namespace blender::bke;
const AttributeAccessor attributes = me->attributes();
const VArray<int> material_indices = attributes.lookup_or_default<int>(
const VArray<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
if (material_indices.is_single()) {
return material_indices.get_internal_single() == index;
@ -1718,11 +1718,11 @@ void BKE_mesh_mselect_validate(Mesh *me)
(me->totselect), sizeof(MSelect), "Mesh selection history");
const AttributeAccessor attributes = me->attributes();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
const VArray<bool> select_edge = attributes.lookup_or_default<bool>(
const VArray<bool> select_edge = *attributes.lookup_or_default<bool>(
".select_edge", ATTR_DOMAIN_EDGE, false);
const VArray<bool> select_poly = attributes.lookup_or_default<bool>(
const VArray<bool> select_poly = *attributes.lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
for (i_src = 0, i_dst = 0; i_src < me->totselect; i_src++) {
@ -1830,7 +1830,7 @@ void BKE_mesh_count_selected_items(const Mesh *mesh, int r_count[3])
void BKE_mesh_vert_coords_get(const Mesh *mesh, float (*vert_coords)[3])
{
blender::bke::AttributeAccessor attributes = mesh->attributes();
VArray<float3> positions = attributes.lookup_or_default(
VArray<float3> positions = *attributes.lookup_or_default(
"position", ATTR_DOMAIN_POINT, float3(0));
positions.materialize({(float3 *)vert_coords, mesh->totvert});
}

View File

@ -411,7 +411,7 @@ static void copy_poly_attributes(Mesh *dest_mesh,
}
/* Fix material indices after they have been transferred as a generic attribute. */
const VArray<int> src_material_indices = orig_me->attributes().lookup_or_default<int>(
const VArray<int> src_material_indices = *orig_me->attributes().lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
const int src_index = src_material_indices[index_in_orig_me];
if (material_remap.index_range().contains(src_index)) {

View File

@ -1087,7 +1087,7 @@ static void move_shapekey_layers_to_keyblocks(const Mesh &mesh,
if (kb->uid == actshape_uid) {
kb->data = MEM_malloc_arrayN(kb->totelem, sizeof(float3), __func__);
MutableSpan<float3> kb_coords(static_cast<float3 *>(kb->data), kb->totelem);
mesh.attributes().lookup<float3>("position").materialize(kb_coords);
mesh.attributes().lookup<float3>("position").varray.materialize(kb_coords);
}
else {
kb->data = layer.data;

View File

@ -623,7 +623,7 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me)
using namespace blender::bke;
MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
if (hide_vert.is_single() && !hide_vert.get_internal_single()) {
attributes.remove(".hide_edge");
@ -662,7 +662,7 @@ void BKE_mesh_flush_hidden_from_polys(Mesh *me)
using namespace blender::bke;
MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
attributes.remove(".hide_vert");
@ -705,7 +705,7 @@ void BKE_mesh_flush_select_from_polys(Mesh *me)
{
using namespace blender::bke;
MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> select_poly = attributes.lookup_or_default<bool>(
const VArray<bool> select_poly = *attributes.lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
if (select_poly.is_single() && !select_poly.get_internal_single()) {
attributes.remove(".select_vert");
@ -720,9 +720,9 @@ void BKE_mesh_flush_select_from_polys(Mesh *me)
/* Use generic domain interpolation to read the polygon attribute on the other domains.
* Assume selected faces are not hidden and none of their vertices/edges are hidden. */
attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_POINT, false)
.materialize(select_vert.span);
.varray.materialize(select_vert.span);
attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_EDGE, false)
.materialize(select_edge.span);
.varray.materialize(select_edge.span);
select_vert.finish();
select_edge.finish();
@ -759,7 +759,7 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
{
using namespace blender::bke;
MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
if (select_vert.is_single() && !select_vert.get_internal_single()) {
attributes.remove(".select_edge");
@ -774,8 +774,8 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
me->edges(),
me->polys(),
me->corner_verts(),
attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false),
attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false),
*attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false),
*attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false),
select_vert,
select_edge.span,
select_poly.span);

View File

@ -1550,7 +1550,7 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh,
const AttributeAccessor attributes = mesh->attributes();
MutableSpan<MVert> verts(mesh->mvert, mesh->totvert);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
@ -1559,7 +1559,7 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh,
});
MutableSpan<MEdge> edges(mesh->medge, mesh->totedge);
const VArray<bool> hide_edge = attributes.lookup_or_default<bool>(
const VArray<bool> hide_edge = *attributes.lookup_or_default<bool>(
".hide_edge", ATTR_DOMAIN_EDGE, false);
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
@ -1567,7 +1567,7 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh,
}
});
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
threading::parallel_for(legacy_polys.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
@ -1643,7 +1643,7 @@ void BKE_mesh_legacy_convert_material_indices_to_mpoly(Mesh *mesh,
using namespace blender;
using namespace blender::bke;
const AttributeAccessor attributes = mesh->attributes();
const VArray<int> material_indices = attributes.lookup_or_default<int>(
const VArray<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
threading::parallel_for(legacy_polys.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
@ -1897,7 +1897,7 @@ void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh,
const AttributeAccessor attributes = mesh->attributes();
MutableSpan<MVert> verts(mesh->mvert, mesh->totvert);
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
@ -1906,7 +1906,7 @@ void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh,
});
MutableSpan<MEdge> edges(mesh->medge, mesh->totedge);
const VArray<bool> select_edge = attributes.lookup_or_default<bool>(
const VArray<bool> select_edge = *attributes.lookup_or_default<bool>(
".select_edge", ATTR_DOMAIN_EDGE, false);
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
@ -1914,7 +1914,7 @@ void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh,
}
});
const VArray<bool> select_poly = attributes.lookup_or_default<bool>(
const VArray<bool> select_poly = *attributes.lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
threading::parallel_for(legacy_polys.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {

View File

@ -317,8 +317,8 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
const OffsetIndices target_polys = target->polys();
const Span<int> target_corner_verts = target->corner_verts();
const VArray<int> src_face_sets = src_attributes.lookup<int>(".sculpt_face_set",
ATTR_DOMAIN_FACE);
const VArray src_face_sets =
* src_attributes.lookup<int>(".sculpt_face_set", ATTR_DOMAIN_FACE);
if (!src_face_sets) {
return;
}

View File

@ -126,7 +126,7 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
}
const AttributeAccessor attributes = mesh->attributes();
const VArraySpan<float2> uv_map = attributes.lookup<float2>(uvmap, ATTR_DOMAIN_CORNER);
const VArraySpan uv_map = *attributes.lookup<float2>(uvmap, ATTR_DOMAIN_CORNER);
if (uv_map.is_empty()) {
BKE_reportf(reports,
RPT_ERROR,

View File

@ -1833,7 +1833,7 @@ static bool find_geonode_attribute_rgba(const DupliObject *dupli,
/* Attempt to look up the attribute. */
std::optional<bke::AttributeAccessor> attributes = component->attributes();
const VArray data = attributes->lookup<ColorGeometry4f>(name);
const VArray data = *attributes->lookup<ColorGeometry4f>(name);
/* If the attribute was found and converted to float RGBA successfully, output it. */
if (data) {

View File

@ -2127,7 +2127,7 @@ void BKE_sculpt_sync_face_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)
}
const AttributeAccessor attributes = mesh->attributes();
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
/* Nothing is hidden, so we can just remove all visibility bitmaps. */

View File

@ -668,7 +668,7 @@ static bool update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
}
const AttributeAccessor attributes = mesh->attributes();
const VArraySpan<float2> uv_map = attributes.lookup<float2>(active_uv_name, ATTR_DOMAIN_CORNER);
const VArraySpan uv_map = *attributes.lookup<float2>(active_uv_name, ATTR_DOMAIN_CORNER);
uv_islands::MeshData mesh_data(
{pbvh->looptri, pbvh->totprim},

View File

@ -274,9 +274,9 @@ bool PointCloud::bounds_min_max(blender::float3 &min, blender::float3 &max) cons
}
this->runtime->bounds_cache.ensure([&](Bounds<float3> &r_bounds) {
const AttributeAccessor attributes = this->attributes();
const VArraySpan<float3> positions = attributes.lookup<float3>(POINTCLOUD_ATTR_POSITION);
const Span<float3> positions = this->positions();
if (attributes.contains(POINTCLOUD_ATTR_RADIUS)) {
const VArraySpan<float> radii = attributes.lookup<float>(POINTCLOUD_ATTR_RADIUS);
const VArraySpan radii = *attributes.lookup<float>(POINTCLOUD_ATTR_RADIUS);
r_bounds = *bounds::min_max_with_radii(positions, radii);
}
else {

View File

@ -52,7 +52,7 @@ static bool everything_selected(const Curves &curves_id)
{
using namespace blender;
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const VArray<bool> selection = curves.attributes().lookup_or_default<bool>(
const VArray<bool> selection = *curves.attributes().lookup_or_default<bool>(
".selection", ATTR_DOMAIN_POINT, true);
return selection.is_single() && selection.get_internal_single();
}

View File

@ -59,7 +59,7 @@ static void populate_cache_for_instance(Object &object,
const InstancesComponent &instances =
*base_geometry.get_component_for_read<InstancesComponent>();
const AttributeAccessor instance_attributes = *instances.attributes();
const VArray attribute = instance_attributes.lookup<ColorGeometry4f>(".viewer");
const VArray attribute = *instance_attributes.lookup<ColorGeometry4f>(".viewer");
if (!attribute) {
return;
}

View File

@ -495,8 +495,8 @@ static void curve_create_attribute(CurveRenderData *rdata, GPUVertBuf *vbo_attr)
const bke::CurvesGeometry &curves = rdata->curve_eval->geometry.wrap();
curves.ensure_can_interpolate_to_evaluated();
const VArraySpan<ColorGeometry4f> colors = curves.attributes().lookup<ColorGeometry4f>(
".viewer", ATTR_DOMAIN_POINT);
const VArraySpan colors = *curves.attributes().lookup<ColorGeometry4f>(".viewer",
ATTR_DOMAIN_POINT);
ColorGeometry4f *vbo_data = static_cast<ColorGeometry4f *>(GPU_vertbuf_get_data(vbo_attr));
curves.interpolate_to_evaluated(colors, MutableSpan<ColorGeometry4f>{vbo_data, vert_len});
}

View File

@ -268,7 +268,7 @@ static void curves_batch_cache_ensure_edit_points_selection(const bke::CurvesGeo
MutableSpan<float> data(static_cast<float *>(GPU_vertbuf_get_data(cache.edit_points_selection)),
curves.points_num());
const VArray<float> attribute = curves.attributes().lookup_or_default<float>(
const VArray<float> attribute = *curves.attributes().lookup_or_default<float>(
".selection", ATTR_DOMAIN_POINT, true);
attribute.materialize(data);
}
@ -343,14 +343,14 @@ static void curves_batch_ensure_attribute(const Curves &curves,
* the Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a
* similar texture state swizzle to map the attribute correctly as for volume attributes, so we
* can control the conversion ourselves. */
VArray<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>(
bke::AttributeReader<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>(
request.attribute_name, request.domain, {0.0f, 0.0f, 0.0f, 1.0f});
MutableSpan<ColorGeometry4f> vbo_span{
static_cast<ColorGeometry4f *>(GPU_vertbuf_get_data(attr_vbo)),
attributes.domain_size(request.domain)};
attribute.materialize(vbo_span);
attribute.varray.materialize(vbo_span);
/* Existing final data may have been for a different attribute (with a different name or domain),
* free the data. */

View File

@ -251,7 +251,7 @@ static void pointcloud_extract_position_and_radius(const PointCloud &pointcloud,
const bke::AttributeAccessor attributes = pointcloud.attributes();
const Span<float3> positions = pointcloud.positions();
const VArray<float> radii = attributes.lookup<float>("radius", ATTR_DOMAIN_POINT);
const VArray<float> radii = *attributes.lookup<float>("radius");
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
@ -303,7 +303,7 @@ static void pointcloud_extract_attribute(const PointCloud &pointcloud,
* the Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a
* similar texture state swizzle to map the attribute correctly as for volume attributes, so we
* can control the conversion ourselves. */
VArray<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>(
bke::AttributeReader<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>(
request.attribute_name, request.domain, {0.0f, 0.0f, 0.0f, 1.0f});
static GPUVertFormat format = {0};
@ -316,7 +316,7 @@ static void pointcloud_extract_attribute(const PointCloud &pointcloud,
MutableSpan<ColorGeometry4f> vbo_data{
static_cast<ColorGeometry4f *>(GPU_vertbuf_get_data(attr_buf)), pointcloud.totpoint};
attribute.materialize(vbo_data);
attribute.varray.materialize(vbo_data);
}
/** \} */

View File

@ -2040,7 +2040,8 @@ static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache *cache,
return;
}
const blender::VArraySpan<int> material_indices = mesh_eval->attributes().lookup_or_default<int>(
const blender::bke::AttributeAccessor attributes = mesh_eval->attributes();
const blender::VArraySpan<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
/* Count number of subdivided polygons for each material. */

View File

@ -329,7 +329,7 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
* use for now because we can't use a per-point radius yet. */
const blender::bke::CurvesGeometry &curves = curves_id.geometry.wrap();
if (curves.curves_num() >= 1) {
blender::VArray<float> radii = curves.attributes().lookup_or_default(
blender::VArray<float> radii = *curves.attributes().lookup_or_default(
"radius", ATTR_DOMAIN_POINT, 0.005f);
const blender::IndexRange first_curve_points = curves.points_by_curve()[0];
const float first_radius = radii[first_curve_points.first()];

View File

@ -438,9 +438,9 @@ static void extract_mesh_attr_viewer_init(const MeshRenderData *mr,
const StringRefNull attr_name = ".viewer";
const bke::AttributeAccessor attributes = mr->me->attributes();
attributes
.lookup_or_default<ColorGeometry4f>(attr_name, ATTR_DOMAIN_CORNER, {1.0f, 0.0f, 1.0f, 1.0f})
.materialize(attr);
const bke::AttributeReader attribute = attributes.lookup_or_default<ColorGeometry4f>(
attr_name, ATTR_DOMAIN_CORNER, {1.0f, 0.0f, 1.0f, 1.0f});
attribute.varray.materialize(attr);
}
constexpr MeshExtract create_extractor_attr_viewer()

View File

@ -15,7 +15,7 @@ namespace blender::ed::curves {
bool remove_selection(bke::CurvesGeometry &curves, const eAttrDomain selection_domain)
{
const bke::AttributeAccessor attributes = curves.attributes();
const VArray<bool> selection = attributes.lookup_or_default<bool>(
const VArray<bool> selection = *attributes.lookup_or_default<bool>(
".selection", selection_domain, true);
const int domain_size_orig = attributes.domain_size(selection_domain);
Vector<int64_t> indices;

View File

@ -585,9 +585,8 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob,
VArraySpan<float2> surface_uv_map;
if (curves_id.surface_uv_map != nullptr) {
const bke::AttributeAccessor surface_attributes = surface_mesh.attributes();
surface_uv_map = surface_attributes
.lookup(curves_id.surface_uv_map, ATTR_DOMAIN_CORNER, CD_PROP_FLOAT2)
.typed<float2>();
surface_uv_map = *surface_attributes.lookup<float2>(curves_id.surface_uv_map,
ATTR_DOMAIN_CORNER);
}
const OffsetIndices points_by_curve = curves.points_by_curve();
@ -795,7 +794,7 @@ static int curves_set_selection_domain_exec(bContext *C, wmOperator *op)
continue;
}
if (const GVArray src = attributes.lookup(".selection", domain)) {
if (const GVArray src = *attributes.lookup(".selection", domain)) {
const CPPType &type = src.type();
void *dst = MEM_malloc_arrayN(attributes.domain_size(domain), type.size(), __func__);
src.materialize(dst);

View File

@ -34,7 +34,7 @@ static IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves,
if (meta_data && meta_data->domain == ATTR_DOMAIN_POINT) {
/* Avoid the interpolation from interpolating the attribute to the
* curve domain by retrieving the point domain values directly. */
const VArray<bool> selection = attributes.lookup_or_default<bool>(
const VArray<bool> selection = *attributes.lookup_or_default<bool>(
".selection", ATTR_DOMAIN_POINT, true);
if (selection.is_single()) {
return selection.get_internal_single() ? IndexMask(curves_range) : IndexMask();
@ -49,7 +49,7 @@ static IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves,
return point_selection.as_span().contains(true);
});
}
const VArray<bool> selection = attributes.lookup_or_default<bool>(
const VArray<bool> selection = *attributes.lookup_or_default<bool>(
".selection", ATTR_DOMAIN_CURVE, true);
return index_mask_ops::find_indices_from_virtual_array(curves_range, selection, 2048, r_indices);
}
@ -64,7 +64,7 @@ IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, Vector<int
{
return index_mask_ops::find_indices_from_virtual_array(
curves.points_range(),
curves.attributes().lookup_or_default<bool>(".selection", ATTR_DOMAIN_POINT, true),
*curves.attributes().lookup_or_default<bool>(".selection", ATTR_DOMAIN_POINT, true),
2048,
r_indices);
}
@ -166,7 +166,7 @@ bool has_anything_selected(const VArray<bool> &varray, const IndexRange range_to
bool has_anything_selected(const bke::CurvesGeometry &curves)
{
const VArray<bool> selection = curves.attributes().lookup<bool>(".selection");
const VArray<bool> selection = *curves.attributes().lookup<bool>(".selection");
return !selection || contains(selection, selection.index_range(), true);
}

View File

@ -270,7 +270,7 @@ static int geometry_attribute_convert_exec(bContext *C, wmOperator *op)
}
case ConvertAttributeMode::VertexGroup: {
Array<float> src_weights(mesh->totvert);
VArray<float> src_varray = attributes.lookup_or_default<float>(
VArray<float> src_varray = *attributes.lookup_or_default<float>(
name, ATTR_DOMAIN_POINT, 0.0f);
src_varray.materialize(src_weights);
attributes.remove(name);
@ -703,13 +703,15 @@ bool ED_geometry_attribute_convert(Mesh *mesh,
}
const std::string name_copy = name;
const GVArray varray = attributes.lookup_or_default(name_copy, dst_domain, dst_type);
const GVArray varray = *attributes.lookup_or_default(name_copy, dst_domain, dst_type);
const CPPType &cpp_type = varray.type();
void *new_data = MEM_malloc_arrayN(varray.size(), cpp_type.size(), __func__);
varray.materialize_to_uninitialized(new_data);
attributes.remove(name_copy);
attributes.add(name_copy, dst_domain, dst_type, bke::AttributeInitMoveArray(new_data));
if (!attributes.add(name_copy, dst_domain, dst_type, bke::AttributeInitMoveArray(new_data))) {
MEM_freeN(new_data);
}
return true;
}

View File

@ -80,7 +80,7 @@ void paintface_flush_flags(bContext *C,
if (me_orig != nullptr && me_eval != nullptr && me_orig->totpoly == me->totpoly) {
/* Update the COW copy of the mesh. */
if (flush_hidden) {
const VArray<bool> hide_poly_me = attributes_me.lookup_or_default<bool>(
const VArray<bool> hide_poly_me = *attributes_me.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> hide_poly_orig =
attributes_orig.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE);
@ -88,7 +88,7 @@ void paintface_flush_flags(bContext *C,
hide_poly_orig.finish();
}
if (flush_selection) {
const VArray<bool> select_poly_me = attributes_me.lookup_or_default<bool>(
const VArray<bool> select_poly_me = *attributes_me.lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> select_poly_orig =
attributes_orig.lookup_or_add_for_write_only_span<bool>(".select_poly",
@ -100,7 +100,7 @@ void paintface_flush_flags(bContext *C,
/* Mesh polys => Final derived polys */
if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
if (flush_hidden) {
const VArray<bool> hide_poly_orig = attributes_orig.lookup_or_default<bool>(
const VArray<bool> hide_poly_orig = *attributes_orig.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> hide_poly_eval =
attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_poly",
@ -114,7 +114,7 @@ void paintface_flush_flags(bContext *C,
hide_poly_eval.finish();
}
if (flush_selection) {
const VArray<bool> select_poly_orig = attributes_orig.lookup_or_default<bool>(
const VArray<bool> select_poly_orig = *attributes_orig.lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> select_poly_eval =
attributes_eval.lookup_or_add_for_write_only_span<bool>(".select_poly",
@ -194,7 +194,7 @@ void paintface_reveal(bContext *C, Object *ob, const bool select)
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
if (select) {
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>(
".select_poly", ATTR_DOMAIN_FACE);
@ -228,9 +228,9 @@ static void build_poly_connections(blender::AtomicDisjointSet &islands,
const Span<int> corner_edges = mesh.corner_edges();
const bke::AttributeAccessor attributes = mesh.attributes();
const VArray<bool> uv_seams = attributes.lookup_or_default<bool>(
const VArray<bool> uv_seams = *attributes.lookup_or_default<bool>(
".uv_seam", ATTR_DOMAIN_EDGE, false);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
/* Polys are connected if they share edges. By connecting all edges of a loop (as long as they
@ -277,7 +277,7 @@ static void paintface_select_linked_faces(Mesh &mesh,
const Span<int> corner_edges = mesh.corner_edges();
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
const VArray<bool> uv_seams = attributes.lookup_or_default<bool>(
const VArray<bool> uv_seams = *attributes.lookup_or_default<bool>(
".uv_seam", ATTR_DOMAIN_EDGE, false);
bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>(
".select_poly", ATTR_DOMAIN_FACE);
@ -380,7 +380,7 @@ void paintface_select_more(Mesh *mesh, const bool face_step)
".select_poly", ATTR_DOMAIN_FACE);
bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
".select_vert", ATTR_DOMAIN_POINT);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
const OffsetIndices polys = mesh->polys();
@ -432,7 +432,7 @@ void paintface_select_less(Mesh *mesh, const bool face_step)
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>(
".select_poly", ATTR_DOMAIN_FACE);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
const OffsetIndices polys = mesh->polys();
@ -478,7 +478,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
}
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>(
".select_poly", ATTR_DOMAIN_FACE);
@ -545,9 +545,9 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
const OffsetIndices polys = me->polys();
const Span<int> corner_verts = me->corner_verts();
bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
const VArray<bool> select_poly = attributes.lookup_or_default<bool>(
const VArray<bool> select_poly = *attributes.lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
for (int i = 0; i < me->totpoly; i++) {
@ -581,7 +581,7 @@ bool paintface_mouse_select(bContext *C,
Mesh *me = BKE_mesh_from_object(ob);
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
bke::AttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write<bool>(
".select_poly", ATTR_DOMAIN_FACE);
@ -656,7 +656,7 @@ void paintvert_flush_flags(Object *ob)
const int *orig_indices = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
const VArray<bool> hide_vert_orig = attributes_orig.lookup_or_default<bool>(
const VArray<bool> hide_vert_orig = *attributes_orig.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
bke::SpanAttributeWriter<bool> hide_vert_eval =
attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_vert", ATTR_DOMAIN_POINT);
@ -672,7 +672,7 @@ void paintvert_flush_flags(Object *ob)
}
hide_vert_eval.finish();
const VArray<bool> select_vert_orig = attributes_orig.lookup_or_default<bool>(
const VArray<bool> select_vert_orig = *attributes_orig.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
bke::SpanAttributeWriter<bool> select_vert_eval =
attributes_eval.lookup_or_add_for_write_only_span<bool>(".select_vert", ATTR_DOMAIN_POINT);
@ -784,9 +784,9 @@ void paintvert_select_more(Mesh *mesh, const bool face_step)
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
".select_vert", ATTR_DOMAIN_POINT);
const VArray<bool> hide_edge = attributes.lookup_or_default<bool>(
const VArray<bool> hide_edge = *attributes.lookup_or_default<bool>(
".hide_edge", ATTR_DOMAIN_EDGE, false);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
const OffsetIndices polys = mesh->polys();
@ -840,9 +840,9 @@ void paintvert_select_less(Mesh *mesh, const bool face_step)
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
".select_vert", ATTR_DOMAIN_POINT);
const VArray<bool> hide_edge = attributes.lookup_or_default<bool>(
const VArray<bool> hide_edge = *attributes.lookup_or_default<bool>(
".hide_edge", ATTR_DOMAIN_EDGE, false);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
const OffsetIndices polys = mesh->polys();
@ -911,7 +911,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
}
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
".select_vert", ATTR_DOMAIN_POINT);
@ -987,7 +987,7 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
}
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
".select_vert", ATTR_DOMAIN_POINT);
@ -1051,7 +1051,7 @@ void paintvert_reveal(bContext *C, Object *ob, const bool select)
}
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
".select_vert", ATTR_DOMAIN_POINT);

View File

@ -1481,7 +1481,7 @@ void ED_mesh_split_faces(Mesh *mesh)
const Span<int> corner_edges = mesh->corner_edges();
const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI);
const bke::AttributeAccessor attributes = mesh->attributes();
const VArray<bool> mesh_sharp_edges = attributes.lookup_or_default<bool>(
const VArray<bool> mesh_sharp_edges = *attributes.lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face"));

View File

@ -135,7 +135,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
/* Output mesh will be all smooth or all flat shading. */
const bke::AttributeAccessor attributes = mesh->attributes();
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
const bool smooth_normals = !sharp_faces[0];

View File

@ -211,7 +211,7 @@ bool ED_vgroup_parray_alloc(ID *id,
if (use_vert_sel) {
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
for (int i = 0; i < me->totvert; i++) {
@ -671,7 +671,7 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
}
else {
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
int v_act;
@ -1063,7 +1063,7 @@ static void vgroup_select_verts(Object *ob, int select)
const Span<MDeformVert> dverts = me->deform_verts();
if (!dverts.is_empty()) {
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
bke::SpanAttributeWriter<bool> select_vert =
attributes.lookup_or_add_for_write_only_span<bool>(".select_vert", ATTR_DOMAIN_POINT);
@ -1628,7 +1628,7 @@ static void vgroup_smooth_subset(Object *ob,
}
else {
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
const blender::Span<int2> edges = me->edges();
@ -1704,7 +1704,7 @@ static void vgroup_smooth_subset(Object *ob,
}
else {
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
int j;
@ -2118,7 +2118,7 @@ void ED_vgroup_mirror(Object *ob,
BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__);
MutableSpan<MDeformVert> dverts = me->deform_verts_for_write();
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
for (int vidx = 0; vidx < me->totvert; vidx++) {
@ -2278,7 +2278,7 @@ static void vgroup_assign_verts(Object *ob, const float weight)
}
else {
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
MutableSpan<MDeformVert> dverts = me->deform_verts_for_write();
@ -3907,7 +3907,7 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
MutableSpan<MDeformVert> dverts = me->deform_verts_for_write();
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
for (i = 0; i < me->totvert; i++) {

View File

@ -164,9 +164,9 @@ struct AddOperationExecutor {
/* Find UV map. */
VArraySpan<float2> surface_uv_map;
if (curves_id_orig_->surface_uv_map != nullptr) {
surface_uv_map = surface_orig.attributes().lookup<float2>(curves_id_orig_->surface_uv_map,
ATTR_DOMAIN_CORNER);
surface_uv_map_eval_ = surface_eval_->attributes().lookup<float2>(
surface_uv_map = *surface_orig.attributes().lookup<float2>(curves_id_orig_->surface_uv_map,
ATTR_DOMAIN_CORNER);
surface_uv_map_eval_ = *surface_eval_->attributes().lookup<float2>(
curves_id_orig_->surface_uv_map, ATTR_DOMAIN_CORNER);
}

View File

@ -133,7 +133,7 @@ struct CombOperationExecutor {
transforms_ = CurvesSurfaceTransforms(*curves_ob_orig_, curves_id_orig_->surface);
point_factors_ = curves_orig_->attributes().lookup_or_default<float>(
point_factors_ = *curves_orig_->attributes().lookup_or_default<float>(
".selection", ATTR_DOMAIN_POINT, 1.0f);
curve_selection_ = curves::retrieve_selected_curves(*curves_id_orig_, selected_curve_indices_);

View File

@ -134,9 +134,9 @@ struct DensityAddOperationExecutor {
/* Find UV map. */
VArraySpan<float2> surface_uv_map;
if (curves_id_orig_->surface_uv_map != nullptr) {
surface_uv_map = surface_orig_->attributes().lookup<float2>(curves_id_orig_->surface_uv_map,
ATTR_DOMAIN_CORNER);
surface_uv_map_eval_ = surface_eval_->attributes().lookup<float2>(
surface_uv_map = *surface_orig_->attributes().lookup<float2>(curves_id_orig_->surface_uv_map,
ATTR_DOMAIN_CORNER);
surface_uv_map_eval_ = *surface_eval_->attributes().lookup<float2>(
curves_id_orig_->surface_uv_map, ATTR_DOMAIN_CORNER);
}
if (surface_uv_map.is_empty()) {

View File

@ -277,7 +277,7 @@ struct CurvesEffectOperationExecutor {
return;
}
curve_selection_factors_ = curves_->attributes().lookup_or_default(
curve_selection_factors_ = *curves_->attributes().lookup_or_default(
".selection", ATTR_DOMAIN_CURVE, 1.0f);
curve_selection_ = curves::retrieve_selected_curves(*curves_id_, selected_curve_indices_);

View File

@ -105,7 +105,7 @@ struct PinchOperationExecutor {
transforms_ = CurvesSurfaceTransforms(*object_, curves_id_->surface);
point_factors_ = curves_->attributes().lookup_or_default<float>(
point_factors_ = *curves_->attributes().lookup_or_default<float>(
".selection", ATTR_DOMAIN_POINT, 1.0f);
curve_selection_ = curves::retrieve_selected_curves(*curves_id_, selected_curve_indices_);

View File

@ -104,7 +104,7 @@ struct PuffOperationExecutor {
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
brush_pos_re_ = stroke_extension.mouse_position;
point_factors_ = curves_->attributes().lookup_or_default<float>(
point_factors_ = *curves_->attributes().lookup_or_default<float>(
".selection", ATTR_DOMAIN_POINT, 1.0f);
curve_selection_ = curves::retrieve_selected_curves(*curves_id_, selected_curve_indices_);

View File

@ -18,7 +18,7 @@ bke::SpanAttributeWriter<float> float_selection_ensure(Curves &curves_id)
if (const auto meta_data = attributes.lookup_meta_data(".selection")) {
if (meta_data->data_type == CD_PROP_BOOL) {
const VArray<float> selection = attributes.lookup<float>(".selection");
const VArray<float> selection = *attributes.lookup<float>(".selection");
float *dst = static_cast<float *>(
MEM_malloc_arrayN(selection.size(), sizeof(float), __func__));
selection.materialize({dst, selection.size()});

View File

@ -155,7 +155,7 @@ struct SlideOperationExecutor {
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
curve_factors_ = curves_orig_->attributes().lookup_or_default(
curve_factors_ = *curves_orig_->attributes().lookup_or_default(
".selection", ATTR_DOMAIN_CURVE, 1.0f);
curve_selection_ = curves::retrieve_selected_curves(*curves_id_orig_, selected_curve_indices_);
@ -170,8 +170,8 @@ struct SlideOperationExecutor {
return;
}
surface_looptris_orig_ = surface_orig_->looptris();
surface_uv_map_orig_ = surface_orig_->attributes().lookup<float2>(uv_map_name,
ATTR_DOMAIN_CORNER);
surface_uv_map_orig_ = *surface_orig_->attributes().lookup<float2>(uv_map_name,
ATTR_DOMAIN_CORNER);
if (surface_uv_map_orig_.is_empty()) {
report_missing_uv_map_on_original_surface(stroke_extension.reports);
return;
@ -198,8 +198,8 @@ struct SlideOperationExecutor {
surface_looptris_eval_ = surface_eval_->looptris();
surface_positions_eval_ = surface_eval_->vert_positions();
surface_corner_verts_eval_ = surface_eval_->corner_verts();
surface_uv_map_eval_ = surface_eval_->attributes().lookup<float2>(uv_map_name,
ATTR_DOMAIN_CORNER);
surface_uv_map_eval_ = *surface_eval_->attributes().lookup<float2>(uv_map_name,
ATTR_DOMAIN_CORNER);
if (surface_uv_map_eval_.is_empty()) {
report_missing_uv_map_on_evaluated_surface(stroke_extension.reports);
return;

View File

@ -77,7 +77,7 @@ struct SmoothOperationExecutor {
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
brush_pos_re_ = stroke_extension.mouse_position;
point_factors_ = curves_->attributes().lookup_or_default<float>(
point_factors_ = *curves_->attributes().lookup_or_default<float>(
".selection", ATTR_DOMAIN_POINT, 1.0f);
curve_selection_ = curves::retrieve_selected_curves(*curves_id_, selected_curve_indices_);
transforms_ = CurvesSurfaceTransforms(*object_, curves_id_->surface);

View File

@ -123,7 +123,7 @@ struct SnakeHookOperatorExecutor {
transforms_ = CurvesSurfaceTransforms(*object_, curves_id_->surface);
curve_factors_ = curves_->attributes().lookup_or_default(
curve_factors_ = *curves_->attributes().lookup_or_default(
".selection", ATTR_DOMAIN_CURVE, 1.0f);
curve_selection_ = curves::retrieve_selected_curves(*curves_id_, selected_curve_indices_);

View File

@ -137,7 +137,7 @@ struct NormalAnglePrecalc {
/* Returns number of elements. */
static int get_vcol_elements(Mesh *me, size_t *r_elem_size)
{
const std::optional<bke::AttributeMetaData> meta_data = me->attributes().lookup_meta_data(
const std::optional<bke::AttributeMetaData> meta_data = *me->attributes().lookup_meta_data(
me->active_color_attribute);
if (r_elem_size) {
@ -1953,7 +1953,7 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
ss, data->brush->falloff_shape);
const blender::bke::AttributeAccessor attributes = data->me->attributes();
const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const blender::VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
/* For each vertex */
@ -2042,7 +2042,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
const blender::bke::AttributeAccessor attributes = data->me->attributes();
const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const blender::VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) {
@ -2157,7 +2157,7 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
ss, data->brush->falloff_shape);
const blender::bke::AttributeAccessor attributes = data->me->attributes();
const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const blender::VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
/* For each vertex */
@ -2228,7 +2228,7 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(void *__restrict userdata,
ss, data->brush->falloff_shape);
const blender::bke::AttributeAccessor attributes = data->me->attributes();
const blender::VArray<bool> select_vert = attributes.lookup_or_default<bool>(
const blender::VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
/* For each vertex */
@ -2859,7 +2859,7 @@ static void *vpaint_init_vpaint(bContext *C,
vpd->is_texbrush = !(brush->vertexpaint_tool == VPAINT_TOOL_BLUR) && brush->mtex.tex;
if (brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) {
const GVArray attribute = me->attributes().lookup(me->active_color_attribute, domain);
const GVArray attribute = *me->attributes().lookup(me->active_color_attribute, domain);
vpd->smear.color_prev = MEM_malloc_arrayN(attribute.size(), attribute.type().size(), __func__);
attribute.materialize(vpd->smear.color_prev);
@ -2896,7 +2896,7 @@ static bool vpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
ED_mesh_color_ensure(me, nullptr);
const std::optional<bke::AttributeMetaData> meta_data = me->attributes().lookup_meta_data(
const std::optional<bke::AttributeMetaData> meta_data = *me->attributes().lookup_meta_data(
me->active_color_attribute);
if (!meta_data) {
@ -2957,9 +2957,9 @@ static void do_vpaint_brush_blur_loops(bContext *C,
Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint);
const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
const blender::VArray<bool> select_vert = *me->attributes().lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
const blender::VArray<bool> select_poly = *me->attributes().lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
@ -3100,9 +3100,9 @@ static void do_vpaint_brush_blur_verts(bContext *C,
Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint);
const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
const blender::VArray<bool> select_vert = *me->attributes().lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
const blender::VArray<bool> select_poly = *me->attributes().lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
@ -3248,9 +3248,9 @@ static void do_vpaint_brush_smear(bContext *C,
Color *color_prev_smear = static_cast<Color *>(vpd->smear.color_prev);
Color *color_prev = reinterpret_cast<Color *>(ss->cache->prev_colors_vpaint);
const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
const blender::VArray<bool> select_vert = *me->attributes().lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
const blender::VArray<bool> select_poly = *me->attributes().lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
@ -3415,7 +3415,7 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd,
{
using Blend = typename Traits::BlendType;
const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
const blender::VArray<bool> select_vert = *me->attributes().lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
VPaintAverageAccum<Blend> *accum = (VPaintAverageAccum<Blend> *)MEM_mallocN(
@ -3532,9 +3532,9 @@ static void vpaint_do_draw(bContext *C,
Color *previous_color = static_cast<Color *>(ss->cache->prev_colors_vpaint);
const blender::VArray<bool> select_vert = me->attributes().lookup_or_default<bool>(
const blender::VArray<bool> select_vert = *me->attributes().lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
const blender::VArray<bool> select_poly = me->attributes().lookup_or_default<bool>(
const blender::VArray<bool> select_poly = *me->attributes().lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) {
@ -4083,9 +4083,9 @@ static void fill_mesh_face_or_corner_attribute(Mesh &mesh,
const bool use_vert_sel,
const bool use_face_sel)
{
const VArray<bool> select_vert = mesh.attributes().lookup_or_default<bool>(
const VArray<bool> select_vert = *mesh.attributes().lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
const VArray<bool> select_poly = mesh.attributes().lookup_or_default<bool>(
const VArray<bool> select_poly = *mesh.attributes().lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
const OffsetIndices polys = mesh.polys();

View File

@ -102,7 +102,7 @@ static bool vertex_paint_from_weight(Object *ob)
/* Retrieve the vertex group with the domain and type of the existing color
* attribute, in order to let the attribute API handle both conversions. */
const GVArray vertex_group = attributes.lookup(
const GVArray vertex_group = *attributes.lookup(
deform_group->name,
ATTR_DOMAIN_POINT,
bke::cpp_type_to_custom_data_type(color_attribute.varray.type()));
@ -162,13 +162,13 @@ static IndexMask get_selected_indices(const Mesh &mesh,
const bke::AttributeAccessor attributes = mesh.attributes();
if (mesh.editflag & ME_EDIT_PAINT_FACE_SEL) {
const VArray<bool> selection = attributes.lookup_or_default<bool>(
const VArray<bool> selection = *attributes.lookup_or_default<bool>(
".select_poly", domain, false);
return index_mask_ops::find_indices_from_virtual_array(
selection.index_range(), selection, 4096, indices);
}
if (mesh.editflag & ME_EDIT_PAINT_VERT_SEL) {
const VArray<bool> selection = attributes.lookup_or_default<bool>(
const VArray<bool> selection = *attributes.lookup_or_default<bool>(
".select_vert", domain, false);
return index_mask_ops::find_indices_from_virtual_array(
selection.index_range(), selection, 4096, indices);
@ -190,7 +190,7 @@ static void face_corner_color_equalize_verts(Mesh &mesh, const IndexMask selecti
return;
}
GVArray color_attribute_point = attributes.lookup(name, ATTR_DOMAIN_POINT);
GVArray color_attribute_point = *attributes.lookup(name, ATTR_DOMAIN_POINT);
GVArray color_attribute_corner = attributes.adapt_domain(
color_attribute_point, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER);
color_attribute_corner.materialize(selection, attribute.span.data());

View File

@ -417,7 +417,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
if (mode == SCULPT_FACE_SET_SELECTION) {
const bke::AttributeAccessor attributes = mesh->attributes();
const VArraySpan<bool> select_poly = attributes.lookup_or_default<bool>(
const VArraySpan<bool> select_poly = *attributes.lookup_or_default<bool>(
".select_poly", ATTR_DOMAIN_FACE, false);
threading::parallel_for(select_poly.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
@ -605,7 +605,7 @@ static void sculpt_face_sets_init_loop(Object *ob, const int mode)
if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) {
const bke::AttributeAccessor attributes = mesh->attributes();
const VArraySpan<int> material_indices = attributes.lookup_or_default<int>(
const VArraySpan<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
for (const int i : IndexRange(mesh->totpoly)) {
ss->face_sets[i] = material_indices[i] + 1;
@ -656,7 +656,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
switch (mode) {
case SCULPT_FACE_SETS_FROM_LOOSE_PARTS: {
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
sculpt_face_sets_init_flood_fill(
ob, [&](const int from_face, const int /*edge*/, const int to_face) {
@ -677,7 +677,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
break;
}
case SCULPT_FACE_SETS_FROM_UV_SEAMS: {
const VArraySpan<bool> uv_seams = mesh->attributes().lookup_or_default<bool>(
const VArraySpan<bool> uv_seams = *mesh->attributes().lookup_or_default<bool>(
".uv_seam", ATTR_DOMAIN_EDGE, false);
sculpt_face_sets_init_flood_fill(
ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {
@ -695,7 +695,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
break;
}
case SCULPT_FACE_SETS_FROM_SHARP_EDGES: {
const VArraySpan<bool> sharp_edges = mesh->attributes().lookup_or_default<bool>(
const VArraySpan<bool> sharp_edges = *mesh->attributes().lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
sculpt_face_sets_init_flood_fill(
ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {

View File

@ -349,7 +349,7 @@ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me,
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
".select_vert", ATTR_DOMAIN_POINT);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
const VArray<bool> hide_vert = *attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
for (int index = 0; index < me->totvert; index++) {
@ -380,7 +380,7 @@ static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me,
bke::MutableAttributeAccessor attributes = me->attributes_for_write();
bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>(
".select_poly", ATTR_DOMAIN_FACE);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
for (int index = 0; index < me->totpoly; index++) {

View File

@ -101,7 +101,7 @@ static void createTransCurvesVerts(bContext * /*C*/, TransInfo *t)
MutableSpan<float3> positions = curves.positions_for_write();
if (use_proportional_edit) {
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const VArray<bool> selection = curves.attributes().lookup_or_default<bool>(
const VArray<bool> selection = *curves.attributes().lookup_or_default<bool>(
".selection", ATTR_DOMAIN_POINT, true);
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange range) {
Vector<float> closest_distances;

View File

@ -513,9 +513,9 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id)
FrsMaterial tmpMat;
const bke::AttributeAccessor attributes = me->attributes();
const VArray<int> material_indices = attributes.lookup_or_default<int>(
const VArray<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
// We parse the vlak nodes again and import meshes while applying the clipping

View File

@ -52,7 +52,7 @@ bke::CurvesGeometry create_curve_from_vert_indices(
continue;
}
const GVArray mesh_attribute = mesh_attributes.lookup(attribute_id, ATTR_DOMAIN_POINT);
const GVArray mesh_attribute = *mesh_attributes.lookup(attribute_id, ATTR_DOMAIN_POINT);
/* Some attributes might not exist if they were builtin attribute on domains that don't
* have any elements, i.e. a face attribute on the output of the line primitive node. */
if (!mesh_attribute) {

View File

@ -108,7 +108,7 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points,
/* Transfer the ID attribute if it exists, using the ID of the first merged point. */
if (attribute_ids.contains("id")) {
VArraySpan<int> src = src_attributes.lookup_or_default<int>("id", ATTR_DOMAIN_POINT, 0);
VArraySpan<int> src = *src_attributes.lookup_or_default<int>("id", ATTR_DOMAIN_POINT, 0);
bke::SpanAttributeWriter<int> dst = dst_attributes.lookup_or_add_for_write_only_span<int>(
"id", ATTR_DOMAIN_POINT);

View File

@ -699,7 +699,7 @@ static AllPointCloudsInfo preprocess_pointclouds(const GeometrySet &geometry_set
const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
const eAttrDomain domain = info.attributes.kinds[attribute_index].domain;
if (attributes.contains(attribute_id)) {
GVArray attribute = attributes.lookup_or_default(attribute_id, domain, data_type);
GVArray attribute = *attributes.lookup_or_default(attribute_id, domain, data_type);
pointcloud_info.attributes[attribute_index].emplace(std::move(attribute));
}
}
@ -710,9 +710,9 @@ static AllPointCloudsInfo preprocess_pointclouds(const GeometrySet &geometry_set
}
}
if (info.create_radius_attribute) {
pointcloud_info.radii = attributes.lookup_or_default("radius", ATTR_DOMAIN_POINT, 0.01f);
pointcloud_info.radii = *attributes.lookup_or_default("radius", ATTR_DOMAIN_POINT, 0.01f);
}
const VArray<float3> position_attribute = attributes.lookup_or_default<float3>(
const VArray<float3> position_attribute = *attributes.lookup_or_default<float3>(
"position", ATTR_DOMAIN_POINT, float3(0));
pointcloud_info.positions = position_attribute.get_internal_span();
}
@ -929,7 +929,7 @@ static AllMeshesInfo preprocess_meshes(const GeometrySet &geometry_set,
const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
const eAttrDomain domain = info.attributes.kinds[attribute_index].domain;
if (attributes.contains(attribute_id)) {
GVArray attribute = attributes.lookup_or_default(attribute_id, domain, data_type);
GVArray attribute = *attributes.lookup_or_default(attribute_id, domain, data_type);
mesh_info.attributes[attribute_index].emplace(std::move(attribute));
}
}
@ -939,8 +939,8 @@ static AllMeshesInfo preprocess_meshes(const GeometrySet &geometry_set,
mesh_info.stored_vertex_ids = ids_attribute.varray.get_internal_span().typed<int>();
}
}
mesh_info.material_indices = attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
mesh_info.material_indices =*
attributes.lookup_or_default<int>("material_index", ATTR_DOMAIN_FACE, 0);
}
info.no_loose_edges_hint = std::all_of(
@ -1231,7 +1231,7 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
const AttributeIDRef &attribute_id = info.attributes.ids[attribute_index];
const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
if (attributes.contains(attribute_id)) {
GVArray attribute = attributes.lookup_or_default(attribute_id, domain, data_type);
GVArray attribute = *attributes.lookup_or_default(attribute_id, domain, data_type);
curve_info.attributes[attribute_index].emplace(std::move(attribute));
}
}
@ -1244,12 +1244,12 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
if (attributes.contains("radius")) {
curve_info.radius =
attributes.lookup<float>("radius", ATTR_DOMAIN_POINT).get_internal_span();
attributes.lookup<float>("radius", ATTR_DOMAIN_POINT).varray.get_internal_span();
info.create_radius_attribute = true;
}
if (attributes.contains("nurbs_weight")) {
curve_info.nurbs_weight =
attributes.lookup<float>("nurbs_weight", ATTR_DOMAIN_POINT).get_internal_span();
attributes.lookup<float>("nurbs_weight", ATTR_DOMAIN_POINT).varray.get_internal_span();
info.create_nurbs_weight_attribute = true;
}
curve_info.resolution = curves.resolution();
@ -1258,9 +1258,9 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
}
if (attributes.contains("handle_right")) {
curve_info.handle_left =
attributes.lookup<float3>("handle_left", ATTR_DOMAIN_POINT).get_internal_span();
attributes.lookup<float3>("handle_left", ATTR_DOMAIN_POINT).varray.get_internal_span();
curve_info.handle_right =
attributes.lookup<float3>("handle_right", ATTR_DOMAIN_POINT).get_internal_span();
attributes.lookup<float3>("handle_right", ATTR_DOMAIN_POINT).varray.get_internal_span();
info.create_handle_postion_attributes = true;
}
}

View File

@ -94,9 +94,9 @@ static void retrieve_attribute_spans(const Span<bke::AttributeIDRef> ids,
Vector<GMutableSpan> &dst,
Vector<bke::GSpanAttributeWriter> &dst_attributes)
{
const bke::AttributeAccessor src_attributes = src_curves.attributes();
for (const int i : ids.index_range()) {
GVArray src_attribute = src_curves.attributes().lookup(ids[i], ATTR_DOMAIN_POINT);
BLI_assert(src_attribute);
const GVArray src_attribute = *src_attributes.lookup(ids[i], ATTR_DOMAIN_POINT);
src.append(src_attribute.get_internal_span());
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(src_attribute.type());

View File

@ -2077,9 +2077,9 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info,
edge_feat_settings.func_reduce = feat_data_sum_reduce;
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> sharp_edges = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_edges = *attributes.lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
EdgeFeatData edge_feat_data = {nullptr};

View File

@ -394,7 +394,7 @@ void ABCGenericMeshWriter::get_geo_groups(Object *object,
std::map<std::string, std::vector<int32_t>> &geo_groups)
{
const bke::AttributeAccessor attributes = mesh->attributes();
const VArraySpan<int> material_indices = attributes.lookup_or_default<int>(
const VArraySpan<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
for (const int i : material_indices.index_range()) {
@ -452,7 +452,7 @@ static void get_topology(struct Mesh *mesh,
const OffsetIndices polys = mesh->polys();
const Span<int> corner_verts = mesh->corner_verts();
const bke::AttributeAccessor attributes = mesh->attributes();
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
for (const int i : sharp_faces.index_range()) {
if (sharp_faces[i]) {

View File

@ -294,7 +294,7 @@ static bool collect_vertex_counts_per_poly(Mesh *me,
{
const blender::OffsetIndices polys = me->polys();
const blender::bke::AttributeAccessor attributes = me->attributes();
const blender::VArray<int> material_indices = attributes.lookup_or_default<int>(
const blender::VArray<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
bool is_triangulated = true;
@ -404,7 +404,7 @@ void GeometryExporter::create_mesh_primitive_list(short material_index,
prepareToAppendValues(is_triangulated, *primitive_list, vcount_list);
const blender::bke::AttributeAccessor attributes = me->attributes();
const blender::VArray<int> material_indices = attributes.lookup_or_default<int>(
const blender::VArray<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
/* <p> */
@ -623,7 +623,7 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals,
bool use_custom_normals = false;
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
BKE_mesh_calc_normals_split(me);

View File

@ -89,7 +89,7 @@ static void generate_vertex_map(const Mesh *mesh,
const StringRef uv_name = CustomData_get_active_layer_name(&mesh->ldata, CD_PROP_FLOAT2);
if (!uv_name.is_empty()) {
const bke::AttributeAccessor attributes = mesh->attributes();
uv_map = attributes.lookup<float2>(uv_name, ATTR_DOMAIN_CORNER);
uv_map = *attributes.lookup<float2>(uv_name, ATTR_DOMAIN_CORNER);
export_uv = !uv_map.is_empty();
}
}
@ -245,7 +245,7 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams
if (!name.is_empty()) {
const bke::AttributeAccessor attributes = mesh->attributes();
const VArray<ColorGeometry4f> color_attribute =
attributes.lookup_or_default<ColorGeometry4f>(
*attributes.lookup_or_default<ColorGeometry4f>(
name, ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f, 0.0f});
if (!color_attribute.is_empty()) {
plyData.vertex_colors.reserve(ply_to_vertex.size());

View File

@ -108,7 +108,7 @@ void USDGenericMeshWriter::write_color_data(const Mesh *mesh,
pxr::UsdGeomPrimvar colors_pv = pvApi.CreatePrimvar(
primvar_name, pxr::SdfValueTypeNames->Color3fArray, prim_varying);
const VArray<ColorGeometry4f> attribute = mesh->attributes().lookup_or_default<ColorGeometry4f>(
const VArray<ColorGeometry4f> attribute = *mesh->attributes().lookup_or_default<ColorGeometry4f>(
attribute_id, meta_data.domain, {0.0f, 0.0f, 0.0f, 1.0f});
pxr::VtArray<pxr::GfVec3f> colors_data;
@ -345,7 +345,7 @@ static void get_loops_polys(const Mesh *mesh, USDMeshData &usd_mesh_data)
/* Only construct face groups (a.k.a. geometry subsets) when we need them for material
* assignments. */
const bke::AttributeAccessor attributes = mesh->attributes();
const VArray<int> material_indices = attributes.lookup_or_default<int>(
const VArray<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
if (!material_indices.is_single() && mesh->totcol > 1) {
const VArraySpan<int> indices_span(material_indices);
@ -513,7 +513,7 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_
bke::AttributeAccessor attributes = mesh->attributes();
const Span<float3> vert_normals = mesh->vert_normals();
const Span<float3> poly_normals = mesh->poly_normals();
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
for (const int i : polys.index_range()) {
const IndexRange poly = polys[i];

View File

@ -254,7 +254,7 @@ void OBJWriter::write_vertex_coords(FormatHandler &fh,
const StringRef name = mesh->active_color_attribute;
if (write_colors && !name.is_empty()) {
const bke::AttributeAccessor attributes = mesh->attributes();
const VArray<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>(
const VArray<ColorGeometry4f> attribute = *attributes.lookup_or_default<ColorGeometry4f>(
name, ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f, 0.0f});
BLI_assert(tot_count == attribute.size());
@ -338,7 +338,7 @@ void OBJWriter::write_poly_elements(FormatHandler &fh,
const int tot_deform_groups = obj_mesh_data.tot_deform_groups();
threading::EnumerableThreadSpecific<Vector<float>> group_weights;
const bke::AttributeAccessor attributes = obj_mesh_data.get_mesh()->attributes();
const VArray<int> material_indices = attributes.lookup_or_default<int>(
const VArray<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
obj_parallel_chunked_output(fh, tot_polygons, [&](FormatHandler &buf, int idx) {

View File

@ -44,7 +44,7 @@ OBJMesh::OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Obj
mesh_edges_ = export_mesh_->edges();
mesh_polys_ = export_mesh_->polys();
mesh_corner_verts_ = export_mesh_->corner_verts();
sharp_faces_ = export_mesh_->attributes().lookup_or_default<bool>(
sharp_faces_ = *export_mesh_->attributes().lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
}
else {
@ -78,7 +78,7 @@ void OBJMesh::set_mesh(Mesh *mesh)
mesh_edges_ = mesh->edges();
mesh_polys_ = mesh->polys();
mesh_corner_verts_ = mesh->corner_verts();
sharp_faces_ = export_mesh_->attributes().lookup_or_default<bool>(
sharp_faces_ = *export_mesh_->attributes().lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
}
@ -214,7 +214,7 @@ void OBJMesh::calc_smooth_groups(const bool use_bitflags)
void OBJMesh::calc_poly_order()
{
const bke::AttributeAccessor attributes = export_mesh_->attributes();
const VArray<int> material_indices = attributes.lookup_or_default<int>(
const VArray<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
if (material_indices.is_single() && material_indices.get_internal_single() == 0) {
return;
@ -296,7 +296,7 @@ void OBJMesh::store_uv_coords_and_indices()
return;
}
const bke::AttributeAccessor attributes = export_mesh_->attributes();
const VArraySpan<float2> uv_map = attributes.lookup<float2>(active_uv_name, ATTR_DOMAIN_CORNER);
const VArraySpan uv_map = *attributes.lookup<float2>(active_uv_name, ATTR_DOMAIN_CORNER);
if (uv_map.is_empty()) {
uv_coords_.clear();
return;

View File

@ -333,8 +333,8 @@ static void mesh_merge_transform(Mesh *result,
}
const bke::AttributeAccessor cap_attributes = cap_mesh->attributes();
if (const VArray<int> cap_material_indices = cap_attributes.lookup<int>("material_index",
ATTR_DOMAIN_FACE)) {
if (const VArray cap_material_indices = *cap_attributes.lookup<int>("material_index",
ATTR_DOMAIN_FACE)) {
bke::MutableAttributeAccessor result_attributes = result->attributes_for_write();
bke::SpanAttributeWriter<int> result_material_indices =
result_attributes.lookup_or_add_for_write_span<int>("material_index", ATTR_DOMAIN_FACE);

View File

@ -1086,10 +1086,8 @@ static void store_computed_output_attributes(
/* Try to create the attribute reusing the stored buffer. This will only succeed if the
* attribute didn't exist before, or if it existed but was removed above. */
if (attributes.add(store.name,
store.domain,
bke::cpp_type_to_custom_data_type(store.data.type()),
bke::AttributeInitMoveArray(store.data.data()))) {
if (attributes.add(
store.name, store.domain, data_type, bke::AttributeInitMoveArray(store.data.data()))) {
continue;
}

View File

@ -138,8 +138,7 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
if (const Mesh *mesh = geometry_set.get_mesh_for_read()) {
count++;
if (const VArray<float3> positions = mesh->attributes().lookup<float3>("position",
ATTR_DOMAIN_POINT)) {
if (const VArray positions = *mesh->attributes().lookup<float3>("position")) {
if (positions.is_span()) {
span_count++;
positions_span = positions.get_internal_span();
@ -150,8 +149,7 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
if (const PointCloud *points = geometry_set.get_pointcloud_for_read()) {
count++;
if (const VArray<float3> positions = points->attributes().lookup<float3>("position",
ATTR_DOMAIN_POINT)) {
if (const VArray positions = *points->attributes().lookup<float3>("position")) {
if (positions.is_span()) {
span_count++;
positions_span = positions.get_internal_span();
@ -182,16 +180,14 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
int offset = 0;
if (const Mesh *mesh = geometry_set.get_mesh_for_read()) {
if (const VArray<float3> varray = mesh->attributes().lookup<float3>("position",
ATTR_DOMAIN_POINT)) {
if (const VArray varray = *mesh->attributes().lookup<float3>("position")) {
varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
offset += varray.size();
}
}
if (const PointCloud *points = geometry_set.get_pointcloud_for_read()) {
if (const VArray<float3> varray = points->attributes().lookup<float3>("position",
ATTR_DOMAIN_POINT)) {
if (const VArray varray = *points->attributes().lookup<float3>("position")) {
varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
offset += varray.size();
}

View File

@ -82,20 +82,21 @@ static void fill_rotation_attribute(const Span<float3> tangents,
static void copy_curve_domain_attributes(const AttributeAccessor curve_attributes,
MutableAttributeAccessor point_attributes)
{
curve_attributes.for_all([&](const bke::AttributeIDRef &id,
const bke::AttributeMetaData &meta_data) {
if (curve_attributes.is_builtin(id)) {
return true;
}
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
return true;
}
point_attributes.add(id,
ATTR_DOMAIN_POINT,
meta_data.data_type,
bke::AttributeInitVArray(curve_attributes.lookup(id, ATTR_DOMAIN_POINT)));
return true;
});
curve_attributes.for_all(
[&](const bke::AttributeIDRef &id, const bke::AttributeMetaData &meta_data) {
if (curve_attributes.is_builtin(id)) {
return true;
}
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
return true;
}
point_attributes.add(
id,
ATTR_DOMAIN_POINT,
meta_data.data_type,
bke::AttributeInitVArray(*curve_attributes.lookup(id, ATTR_DOMAIN_POINT)));
return true;
});
}
static PointCloud *pointcloud_from_curves(bke::CurvesGeometry curves,
@ -108,8 +109,8 @@ static PointCloud *pointcloud_from_curves(bke::CurvesGeometry curves,
if (rotation_id) {
MutableAttributeAccessor attributes = curves.attributes_for_write();
const VArraySpan<float3> tangents = attributes.lookup<float3>(tangent_id, ATTR_DOMAIN_POINT);
const VArraySpan<float3> normals = attributes.lookup<float3>(normal_id, ATTR_DOMAIN_POINT);
const VArraySpan tangents = *attributes.lookup<float3>(tangent_id, ATTR_DOMAIN_POINT);
const VArraySpan normals = *attributes.lookup<float3>(normal_id, ATTR_DOMAIN_POINT);
SpanAttributeWriter<float3> rotations = attributes.lookup_or_add_for_write_only_span<float3>(
rotation_id, ATTR_DOMAIN_POINT);
fill_rotation_attribute(tangents, normals, rotations.span);

View File

@ -298,13 +298,13 @@ static void node_geo_exec(GeoNodeExecParams params)
TIP_("Curves are not attached to any UV map"));
return;
}
const VArraySpan<float2> uv_map_orig = mesh_attributes_orig.lookup<float2>(uv_map_name,
ATTR_DOMAIN_CORNER);
const VArraySpan<float2> uv_map_eval = mesh_attributes_eval.lookup<float2>(uv_map_name,
ATTR_DOMAIN_CORNER);
const VArraySpan<float3> rest_positions = mesh_attributes_eval.lookup<float3>(rest_position_name,
ATTR_DOMAIN_POINT);
const VArraySpan<float2> surface_uv_coords = curves.attributes().lookup_or_default(
const VArraySpan uv_map_orig = *mesh_attributes_orig.lookup<float2>(uv_map_name,
ATTR_DOMAIN_CORNER);
const VArraySpan uv_map_eval = *mesh_attributes_eval.lookup<float2>(uv_map_name,
ATTR_DOMAIN_CORNER);
const VArraySpan rest_positions = *mesh_attributes_eval.lookup<float3>(rest_position_name,
ATTR_DOMAIN_POINT);
const VArraySpan surface_uv_coords = *curves.attributes().lookup_or_default<float2>(
"surface_uv_coordinate", ATTR_DOMAIN_CURVE, float2(0));
const Span<MLoopTri> looptris_orig = surface_mesh_orig->looptris();
@ -374,7 +374,7 @@ static void node_geo_exec(GeoNodeExecParams params)
invalid_uv_count);
/* Then also deform edit curve information for use in sculpt mode. */
const CurvesGeometry &curves_orig = edit_hints->curves_id_orig.geometry.wrap();
const VArraySpan<float2> surface_uv_coords_orig = curves_orig.attributes().lookup_or_default(
const VArraySpan<float2> surface_uv_coords_orig = *curves_orig.attributes().lookup_or_default(
"surface_uv_coordinate", ATTR_DOMAIN_CURVE, float2(0));
if (!surface_uv_coords_orig.is_empty()) {
deform_curves(curves_orig,

View File

@ -41,7 +41,7 @@ class HandlePositionFieldInput final : public bke::CurvesFieldInput {
const AttributeAccessor attributes = curves.attributes();
StringRef side = left_ ? "handle_left" : "handle_right";
VArray<float3> handles = attributes.lookup_or_default<float3>(
VArray<float3> handles = *attributes.lookup_or_default<float3>(
side, ATTR_DOMAIN_POINT, {0, 0, 0});
if (relative.is_single()) {

View File

@ -76,6 +76,7 @@ static void add_instances_from_component(
if (selection.is_empty()) {
return;
}
const AttributeAccessor src_attributes = *src_component.attributes();
/* The initial size of the component might be non-zero when this function is called for multiple
* component types. */
@ -86,8 +87,7 @@ static void add_instances_from_component(
MutableSpan<int> dst_handles = dst_component.reference_handles().slice(start_len, select_len);
MutableSpan<float4x4> dst_transforms = dst_component.transforms().slice(start_len, select_len);
VArray<float3> positions = src_component.attributes()->lookup_or_default<float3>(
"position", domain, {0, 0, 0});
const VArraySpan positions = *src_attributes.lookup<float3>("position");
const bke::Instances *src_instances = instance.get_instances_for_read();
@ -158,24 +158,28 @@ static void add_instances_from_component(
}
}
bke::CustomDataAttributes &instance_attributes = dst_component.custom_data_attributes();
bke::MutableAttributeAccessor dst_attributes = dst_component.attributes_for_write();
for (const auto item : attributes_to_propagate.items()) {
const AttributeIDRef &attribute_id = item.key;
const AttributeKind attribute_kind = item.value;
const GVArray src_attribute = src_component.attributes()->lookup_or_default(
attribute_id, ATTR_DOMAIN_POINT, attribute_kind.data_type);
BLI_assert(src_attribute);
std::optional<GMutableSpan> dst_attribute_opt = instance_attributes.get_for_write(
attribute_id);
if (!dst_attribute_opt) {
if (!instance_attributes.create(attribute_id, attribute_kind.data_type)) {
continue;
}
dst_attribute_opt = instance_attributes.get_for_write(attribute_id);
const AttributeIDRef &id = item.key;
const bke::GAttributeReader src = src_attributes.lookup(id, ATTR_DOMAIN_POINT);
if (!src) {
/* Domain interpolation can fail if the source domain is empty. */
continue;
}
const eCustomDataType type = bke::cpp_type_to_custom_data_type(src.varray.type());
if (src.varray.size() == dst_component.instances_num() && src.sharing_info &&
src.varray.is_span()) {
const bke::AttributeInitShared init(src.varray.get_internal_span().data(),
*src.sharing_info);
dst_attributes.add(id, ATTR_DOMAIN_INSTANCE, type, init);
}
else {
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, ATTR_DOMAIN_INSTANCE, type);
array_utils::gather(src.varray, selection, dst.span.slice(start_len, select_len));
dst.finish();
}
BLI_assert(dst_attribute_opt);
array_utils::gather(src_attribute, selection, dst_attribute_opt->slice(start_len, select_len));
}
}

View File

@ -50,12 +50,13 @@ static void convert_instances_to_points(GeometrySet &geometry_set,
geometry_set.replace_pointcloud(pointcloud);
array_utils::gather(positions, selection, pointcloud->positions_for_write());
bke::MutableAttributeAccessor point_attributes = pointcloud->attributes_for_write();
bke::MutableAttributeAccessor dst_attributes = pointcloud->attributes_for_write();
bke::SpanAttributeWriter<float> point_radii =
point_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
dst_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
array_utils::gather(radii, selection, point_radii.span);
point_radii.finish();
const bke::AttributeAccessor src_attributes = instances.attributes();
Map<AttributeIDRef, AttributeKind> attributes_to_propagate;
geometry_set.gather_attributes_for_propagation({GEO_COMPONENT_TYPE_INSTANCES},
GEO_COMPONENT_TYPE_POINT_CLOUD,
@ -67,18 +68,22 @@ static void convert_instances_to_points(GeometrySet &geometry_set,
attributes_to_propagate.remove("radius");
for (const auto item : attributes_to_propagate.items()) {
const AttributeIDRef &attribute_id = item.key;
const AttributeKind attribute_kind = item.value;
const AttributeIDRef &id = item.key;
const eCustomDataType type = item.value.data_type;
const GVArray src = instances.attributes().lookup_or_default(
attribute_id, ATTR_DOMAIN_INSTANCE, attribute_kind.data_type);
BLI_assert(src);
GSpanAttributeWriter dst = point_attributes.lookup_or_add_for_write_only_span(
attribute_id, ATTR_DOMAIN_POINT, attribute_kind.data_type);
BLI_assert(dst);
src.materialize_compressed_to_uninitialized(selection, dst.span.data());
dst.finish();
const GAttributeReader src = src_attributes.lookup(id);
if (selection.size() == instances.instances_num() && src.sharing_info &&
src.varray.is_span()) {
const bke::AttributeInitShared init(src.varray.get_internal_span().data(),
*src.sharing_info);
dst_attributes.add(id, ATTR_DOMAIN_POINT, type, init);
}
else {
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, ATTR_DOMAIN_POINT, type);
array_utils::gather(src.varray, selection, dst.span);
dst.finish();
}
}
}

View File

@ -446,7 +446,8 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves,
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
return true;
}
if (meta_data.data_type == CD_PROP_STRING) {
const eCustomDataType type = meta_data.data_type;
if (type == CD_PROP_STRING) {
return true;
}
if (guide_curve_attributes.is_builtin(id) &&
@ -455,15 +456,14 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves,
}
if (meta_data.domain == ATTR_DOMAIN_CURVE) {
const GVArraySpan src_generic = guide_curve_attributes.lookup(
id, ATTR_DOMAIN_CURVE, meta_data.data_type);
const GVArraySpan src_generic = *guide_curve_attributes.lookup(id, ATTR_DOMAIN_CURVE, type);
GSpanAttributeWriter dst_generic = children_attributes.lookup_or_add_for_write_only_span(
id, ATTR_DOMAIN_CURVE, meta_data.data_type);
id, ATTR_DOMAIN_CURVE, type);
if (!dst_generic) {
return true;
}
attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
attribute_math::convert_to_static_type(type, [&](auto dummy) {
using T = decltype(dummy);
const Span<T> src = src_generic.typed<T>();
MutableSpan<T> dst = dst_generic.span.typed<T>();
@ -490,15 +490,14 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves,
}
else {
BLI_assert(meta_data.domain == ATTR_DOMAIN_POINT);
const GVArraySpan src_generic = guide_curve_attributes.lookup(
id, ATTR_DOMAIN_POINT, meta_data.data_type);
const GVArraySpan src_generic = *guide_curve_attributes.lookup(id, ATTR_DOMAIN_POINT, type);
GSpanAttributeWriter dst_generic = children_attributes.lookup_or_add_for_write_only_span(
id, ATTR_DOMAIN_POINT, meta_data.data_type);
id, ATTR_DOMAIN_POINT, type);
if (!dst_generic) {
return true;
}
attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
attribute_math::convert_to_static_type(type, [&](auto dummy) {
using T = decltype(dummy);
const Span<T> src = src_generic.typed<T>();
MutableSpan<T> dst = dst_generic.span.typed<T>();
@ -579,14 +578,16 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves,
return true;
}
const GVArray src = point_attributes.lookup(id, ATTR_DOMAIN_POINT, meta_data.data_type);
GSpanAttributeWriter dst = children_attributes.lookup_or_add_for_write_only_span(
id, ATTR_DOMAIN_CURVE, meta_data.data_type);
if (!dst) {
return true;
const GAttributeReader src = point_attributes.lookup(id);
if (src.sharing_info && src.varray.is_span()) {
const bke::AttributeInitShared init(src.varray.get_internal_span().data(),
*src.sharing_info);
children_attributes.add(id, ATTR_DOMAIN_CURVE, meta_data.data_type, init);
}
else {
children_attributes.add(
id, ATTR_DOMAIN_CURVE, meta_data.data_type, bke::AttributeInitVArray(src.varray));
}
src.materialize(dst.span.data());
dst.finish();
return true;
});
}
@ -673,7 +674,7 @@ static GeometrySet generate_interpolated_curves(
}
});
const VArraySpan point_positions = point_attributes.lookup<float3>("position");
const VArraySpan point_positions = *point_attributes.lookup<float3>("position");
const int num_child_curves = point_attributes.domain_size(ATTR_DOMAIN_POINT);
/* The set of guides per child are stored in a flattened array to allow fast access, reduce

View File

@ -65,7 +65,7 @@ static void fill_new_attribute(Span<const GeometryComponent *> src_components,
if (domain_num == 0) {
continue;
}
GVArray read_attribute = component->attributes()->lookup_or_default(
GVArray read_attribute = *component->attributes()->lookup_or_default(
attribute_id, domain, data_type, nullptr);
GVArraySpan src_span{read_attribute};

View File

@ -35,7 +35,7 @@ static VArray<bool> select_mesh_faces_by_material(const Mesh &mesh,
}
const AttributeAccessor attributes = mesh.attributes();
const VArray<int> material_indices = attributes.lookup_or_default<int>(
const VArray<int> material_indices = *attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
if (material_indices.is_single()) {
const int slot_i = material_indices.get_internal_single();

View File

@ -93,7 +93,7 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions,
* have a simple utility for that yet though so there is some overhead right now. */
MutableAttributeAccessor attributes = mesh->attributes_for_write();
if (create_uv_map) {
const VArraySpan<float2> orig_uv_map = attributes.lookup<float2>("UVMap");
const VArraySpan orig_uv_map = *attributes.lookup<float2>("UVMap");
SpanAttributeWriter<float2> uv_map = attributes.lookup_or_add_for_write_only_span<float2>(
uv_map_id, ATTR_DOMAIN_CORNER);
uv_map.span.copy_from(orig_uv_map);

View File

@ -62,6 +62,7 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
geometry_set.remove_geometry_during_modify();
return;
}
const AttributeAccessor src_attributes = mesh->attributes();
bke::MeshFieldContext field_context{*mesh, domain};
fn::FieldEvaluator evaluator{field_context, domain_size};
evaluator.set_selection(selection_field);
@ -72,16 +73,30 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
evaluator.add(radius_field);
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
const VArray<float3> positions_eval = evaluator.get_evaluated<float3>(0);
const VArray<float> radii_eval = evaluator.get_evaluated<float>(1);
const bool share_arrays = selection.size() == domain_size;
const bool share_position = share_arrays && positions_eval.is_span() &&
positions_eval.get_internal_span().data() ==
mesh->vert_positions().data();
PointCloud *pointcloud;
if (share_position) {
/* Create an empty point cloud so the positions can be shared. */
pointcloud = BKE_pointcloud_new_nomain(0);
CustomData_free_layer_named(&pointcloud->pdata, "position", pointcloud->totpoint);
pointcloud->totpoint = mesh->totvert;
const bke::AttributeReader src = src_attributes.lookup<float3>("position");
const bke::AttributeInitShared init(src.varray.get_internal_span().data(), *src.sharing_info);
pointcloud->attributes_for_write().add<float3>("position", ATTR_DOMAIN_POINT, init);
}
else {
pointcloud = BKE_pointcloud_new_nomain(selection.size());
array_utils::gather(positions_eval, selection, pointcloud->positions_for_write());
}
PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size());
geometry_set.replace_pointcloud(pointcloud);
MutableAttributeAccessor dst_attributes = pointcloud->attributes_for_write();
GSpanAttributeWriter position = dst_attributes.lookup_or_add_for_write_only_span(
"position", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
array_utils::gather(evaluator.get_evaluated(0), selection, position.span);
position.finish();
GSpanAttributeWriter radius = dst_attributes.lookup_or_add_for_write_only_span(
"radius", ATTR_DOMAIN_POINT, CD_PROP_FLOAT);
array_utils::gather(evaluator.get_evaluated(1), selection, radius.span);
@ -93,22 +108,32 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
false,
propagation_info,
attributes);
attributes.remove("radius");
attributes.remove("position");
const AttributeAccessor src_attributes = mesh->attributes();
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
const eCustomDataType data_type = entry.value.data_type;
GVArray src = src_attributes.lookup_or_default(attribute_id, domain, data_type);
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, ATTR_DOMAIN_POINT, data_type);
if (dst && src) {
array_utils::gather(src, selection, dst.span);
const bke::GAttributeReader src = src_attributes.lookup(attribute_id, domain, data_type);
if (!src) {
/* Domain interpolation can fail if the source domain is empty. */
continue;
}
if (share_arrays && src.domain == domain && src.sharing_info && src.varray.is_span()) {
const bke::AttributeInitShared init(src.varray.get_internal_span().data(),
*src.sharing_info);
dst_attributes.add(attribute_id, ATTR_DOMAIN_POINT, data_type, init);
}
else {
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, ATTR_DOMAIN_POINT, data_type);
array_utils::gather(src.varray, selection, dst.span);
dst.finish();
}
}
geometry_set.replace_pointcloud(pointcloud);
geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_POINT_CLOUD});
}

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_task.hh"
#include "BLI_array_utils.hh"
#include "DNA_pointcloud_types.h"
@ -49,26 +49,40 @@ static void geometry_set_points_to_vertices(
propagation_info,
attributes);
Mesh *mesh = BKE_mesh_new_nomain(selection.size(), 0, 0, 0);
geometry_set.replace_mesh(mesh);
Mesh *mesh;
if (selection.size() == points->totpoint) {
/* Create a mesh without positions so the attribute can be shared. */
mesh = BKE_mesh_new_nomain(0, 0, 0, 0);
CustomData_free_layer_named(&mesh->vdata, "position", mesh->totvert);
mesh->totvert = selection.size();
}
else {
mesh = BKE_mesh_new_nomain(selection.size(), 0, 0, 0);
}
const AttributeAccessor src_attributes = points->attributes();
MutableAttributeAccessor dst_attributes = mesh->attributes_for_write();
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
const AttributeIDRef id = entry.key;
const eCustomDataType data_type = entry.value.data_type;
GVArray src = src_attributes.lookup_or_default(attribute_id, ATTR_DOMAIN_POINT, data_type);
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, ATTR_DOMAIN_POINT, data_type);
if (dst && src) {
src.materialize_compressed_to_uninitialized(selection, dst.span.data());
const GAttributeReader src = src_attributes.lookup(id);
if (selection.size() == points->totpoint && src.sharing_info && src.varray.is_span()) {
const bke::AttributeInitShared init(src.varray.get_internal_span().data(),
*src.sharing_info);
dst_attributes.add(id, ATTR_DOMAIN_POINT, data_type, init);
}
else {
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, ATTR_DOMAIN_POINT, data_type);
array_utils::gather(src.varray, selection, dst.span);
dst.finish();
}
}
mesh->loose_edges_tag_none();
geometry_set.replace_mesh(mesh);
geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_MESH});
}

View File

@ -28,8 +28,7 @@ static void gather_point_data_from_component(Field<float> radius_field,
if (component.is_empty()) {
return;
}
VArray<float3> positions = component.attributes()->lookup_or_default<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
const VArray<float3> positions = *component.attributes()->lookup<float3>("position");
bke::GeometryFieldContext field_context{component, ATTR_DOMAIN_POINT};
const int domain_num = component.attribute_domain_size(ATTR_DOMAIN_POINT);

View File

@ -31,10 +31,10 @@ static void set_computed_position_and_offset(GeometryComponent &component,
MutableAttributeAccessor attributes = *component.attributes_for_write();
/* Optimize the case when `in_positions` references the original positions array. */
const VArray<float3> positions_read_only = attributes.lookup<float3>("position");
const bke::AttributeReader positions_read_only = attributes.lookup<float3>("position");
bool positions_are_original = false;
if (positions_read_only.is_span() && in_positions.is_span()) {
positions_are_original = positions_read_only.get_internal_span().data() ==
if (positions_read_only.varray.is_span() && in_positions.is_span()) {
positions_are_original = positions_read_only.varray.get_internal_span().data() ==
in_positions.get_internal_span().data();
}

View File

@ -466,8 +466,8 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval
const blender::OffsetIndices polys = me->polys();
const blender::Span<int> corner_verts = me->corner_verts();
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> sharp_faces = attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
const VArray<bool> sharp_faces =
attributes.lookup_or_default<bool>("sharp_face", ATTR_DOMAIN_FACE, false).varray;
looptri = static_cast<MLoopTri *>(MEM_mallocN(sizeof(*looptri) * tottri, __func__));
triangles = static_cast<TriTessFace *>(MEM_callocN(sizeof(TriTessFace) * tottri, __func__));