Fix #117997: Crash trying to copy vertex group attributes as spans #119212
|
@ -376,12 +376,27 @@ static GSpan evaluate_attribute(const GVArray &src,
|
|||
const CurvesGeometry &curves,
|
||||
Vector<std::byte> &buffer)
|
||||
{
|
||||
if (curves.is_single_type(CURVE_TYPE_POLY) && src.is_span()) {
|
||||
return src.get_internal_span();
|
||||
/* Poly curves evaluated points match the curve points, no need to interpolate. */
|
||||
if (curves.is_single_type(CURVE_TYPE_POLY)) {
|
||||
if (src.is_span()) {
|
||||
return src.get_internal_span();
|
||||
}
|
||||
buffer.reinitialize(curves.points_num() * src.type().size());
|
||||
src.materialize(buffer.data());
|
||||
GMutableSpan eval{src.type(), buffer.data(), curves.points_num()};
|
||||
LukasTonne marked this conversation as resolved
Outdated
|
||||
return eval;
|
||||
}
|
||||
|
||||
if (src.is_span()) {
|
||||
buffer.reinitialize(curves.evaluated_points_num() * src.type().size());
|
||||
LukasTonne marked this conversation as resolved
Hans Goudey
commented
`GVArraySpan` is a utility to do this
Lukas Tönne
commented
I don't see how this would work: I don't see how this would work: `GVArraySpan` can wrap the input `src` array but is not mutable (can't materialize into it). `GVMutableArraySpan` is mutable but can't be simply constructed from the immutable `src` buffer.
Iliya Katushenock
commented
But this is src buffer and should not be mutable, no? But this is *src* buffer and should not be mutable, no?
Lukas Tönne
commented
Ok, looked into the constructor and it actually does a Ok, looked into the constructor and it actually does a `materialize` internally. That wasn't clear to me.
|
||||
GMutableSpan eval{src.type(), buffer.data(), curves.evaluated_points_num()};
|
||||
LukasTonne marked this conversation as resolved
Hans Goudey
commented
Seems worth also having a fast path for Seems worth also having a fast path for `curves.is_single_type(CURVE_TYPE_POLY)` here. The `materialize` can happen directly into the `buffer`.
Lukas Tönne
commented
I don't think we can directly materialize into the output buffer because of the I don't think we can directly materialize into the output buffer because of the `interpolate_to_evaluated` call. The input array is per control point, the output is per evaluated point.
Hans Goudey
commented
When When `curves.is_single_type(CURVE_TYPE_POLY)` is true, there is the same number of control point and evaluated points. That optimization is done just above, except that it requires `is_span()` there.
Lukas Tönne
commented
Ok, makes sense. I'll add a comment though, because i don't think it's obvious why this works for poly curves. Ok, makes sense. I'll add a comment though, because i don't think it's obvious why this works for poly curves.
|
||||
curves.interpolate_to_evaluated(src.get_internal_span(), eval);
|
||||
return eval;
|
||||
}
|
||||
GVArraySpan src_buffer(src);
|
||||
buffer.reinitialize(curves.evaluated_points_num() * src.type().size());
|
||||
GMutableSpan eval{src.type(), buffer.data(), curves.evaluated_points_num()};
|
||||
curves.interpolate_to_evaluated(src.get_internal_span(), eval);
|
||||
curves.interpolate_to_evaluated(src_buffer, eval);
|
||||
return eval;
|
||||
}
|
||||
|
||||
|
@ -843,6 +858,9 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
|||
|
||||
Vector<std::byte> eval_buffer;
|
||||
|
||||
/* Make sure curve attributes can be interpolated. */
|
||||
main.ensure_can_interpolate_to_evaluated();
|
||||
|
||||
build_mesh_positions(curves_info, offsets, eval_buffer, *mesh);
|
||||
|
||||
mesh->tag_overlapping_none();
|
||||
|
@ -909,6 +927,9 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
|||
return true;
|
||||
});
|
||||
|
||||
/* Make sure profile attributes can be interpolated. */
|
||||
profile.ensure_can_interpolate_to_evaluated();
|
||||
|
||||
const AttributeAccessor profile_attributes = profile.attributes();
|
||||
profile_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
|
||||
if (main_attributes.contains(id)) {
|
||||
|
|
ensure_can_interpolate_to_evaluated
should be called at some higher level before all this interpolation needs to happen