Merge branch 'blender-v3.0-release'

This commit is contained in:
Hans Goudey 2021-11-02 15:23:59 -05:00
commit 8c58838f6a
5 changed files with 97 additions and 15 deletions

View File

@ -372,6 +372,11 @@ class CustomDataAttributes {
void *buffer);
bool remove(const AttributeIDRef &attribute_id);
/**
* Change the order of the attributes to match the order of IDs in the argument.
*/
void reorder(Span<AttributeIDRef> new_order);
bool foreach_attribute(const AttributeForeachCallback callback,
const AttributeDomain domain) const;
};

View File

@ -835,6 +835,26 @@ bool CustomDataAttributes::foreach_attribute(const AttributeForeachCallback call
return true;
}
void CustomDataAttributes::reorder(Span<AttributeIDRef> new_order)
{
BLI_assert(new_order.size() == data.totlayer);
Map<AttributeIDRef, int> old_order;
old_order.reserve(data.totlayer);
Array<CustomDataLayer> old_layers(Span(data.layers, data.totlayer));
for (const int i : old_layers.index_range()) {
old_order.add_new(attribute_id_from_custom_data_layer(old_layers[i]), i);
}
MutableSpan layers(data.layers, data.totlayer);
for (const int i : layers.index_range()) {
const int old_index = old_order.lookup(new_order[i]);
layers[i] = old_layers[old_index];
}
CustomData_update_typemap(&data);
}
} // namespace blender::bke
/* -------------------------------------------------------------------- */

View File

@ -348,6 +348,7 @@ std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve)
* because attributes are stored on splines rather than in a flat array on the curve:
* - The same set of attributes exists on every spline.
* - Attributes with the same name have the same type on every spline.
* - Attributes are in the same order on every spline.
*/
void CurveEval::assert_valid_point_attributes() const
{
@ -356,25 +357,40 @@ void CurveEval::assert_valid_point_attributes() const
return;
}
const int layer_len = splines_.first()->attributes.data.totlayer;
Map<AttributeIDRef, AttributeMetaData> map;
for (const SplinePtr &spline : splines_) {
BLI_assert(spline->attributes.data.totlayer == layer_len);
spline->attributes.foreach_attribute(
Array<AttributeIDRef> ids_in_order(layer_len);
Array<AttributeMetaData> meta_data_in_order(layer_len);
{
int i = 0;
splines_.first()->attributes.foreach_attribute(
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
map.add_or_modify(
attribute_id,
[&](AttributeMetaData *map_data) {
/* All unique attribute names should be added on the first spline. */
BLI_assert(spline == splines_.first());
*map_data = meta_data;
},
[&](AttributeMetaData *map_data) {
/* Attributes on different splines should all have the same type. */
BLI_assert(meta_data == *map_data);
});
ids_in_order[i] = attribute_id;
meta_data_in_order[i] = meta_data;
i++;
return true;
},
ATTR_DOMAIN_POINT);
}
for (const SplinePtr &spline : splines_) {
/* All splines should have the same number of attributes. */
BLI_assert(spline->attributes.data.totlayer == layer_len);
int i = 0;
spline->attributes.foreach_attribute(
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
/* Attribute names and IDs should have the same order and exist on all splines. */
BLI_assert(attribute_id == ids_in_order[i]);
/* Attributes with the same ID different splines should all have the same type. */
BLI_assert(meta_data == meta_data_in_order[i]);
i++;
return true;
},
ATTR_DOMAIN_POINT);
}
#endif
}

View File

@ -530,6 +530,24 @@ static void join_instance_groups_volume(Span<GeometryInstanceGroup> set_groups,
}
}
/**
* Curve point domain attributes must be in the same order on every spline. The order might have
* been different on separate instances, so ensure that all splines have the same order. Note that
* because #Map is used, the order is not necessarily consistent every time, but it is the same for
* every spline, and that's what matters.
*/
static void sort_curve_point_attributes(const Map<AttributeIDRef, AttributeKind> &info,
MutableSpan<SplinePtr> splines)
{
Vector<AttributeIDRef> new_order;
for (const AttributeIDRef attribute_id : info.keys()) {
new_order.append(attribute_id);
}
for (SplinePtr &spline : splines) {
spline->attributes.reorder(new_order);
}
}
static void join_instance_groups_curve(Span<GeometryInstanceGroup> set_groups, GeometrySet &result)
{
CurveEval *curve = join_curve_splines_and_builtin_attributes(set_groups);
@ -550,6 +568,8 @@ static void join_instance_groups_curve(Span<GeometryInstanceGroup> set_groups, G
{GEO_COMPONENT_TYPE_CURVE},
attributes,
static_cast<GeometryComponent &>(dst_component));
sort_curve_point_attributes(attributes, curve->splines());
curve->assert_valid_point_attributes();
}
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)

View File

@ -356,6 +356,24 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id,
}
}
/**
* Curve point domain attributes must be in the same order on every spline. The order might have
* been different on separate instances, so ensure that all splines have the same order. Note that
* because #Map is used, the order is not necessarily consistent every time, but it is the same for
* every spline, and that's what matters.
*/
static void sort_curve_point_attributes(const Map<AttributeIDRef, AttributeMetaData> &info,
MutableSpan<SplinePtr> splines)
{
Vector<AttributeIDRef> new_order;
for (const AttributeIDRef attribute_id : info.keys()) {
new_order.append(attribute_id);
}
for (SplinePtr &spline : splines) {
spline->attributes.reorder(new_order);
}
}
/**
* Fill data for an attribute on the new curve based on all source curves.
*/
@ -409,6 +427,8 @@ static void join_curve_attributes(const Map<AttributeIDRef, AttributeMetaData> &
ensure_control_point_attribute(attribute_id, meta_data.data_type, src_components, result);
}
}
sort_curve_point_attributes(info, result.splines());
}
static void join_curve_components(MutableSpan<GeometrySet> src_geometry_sets, GeometrySet &result)
@ -449,6 +469,7 @@ static void join_curve_components(MutableSpan<GeometrySet> src_geometry_sets, Ge
dst_curve->attributes.reallocate(dst_curve->splines().size());
join_curve_attributes(info, src_components, *dst_curve);
dst_curve->assert_valid_point_attributes();
dst_component.replace(dst_curve);
}