GPv3: Convert editcurve to bézier curves
In GPv2, strokes could be edited using bézier curve handles. This was implemented by creating an `editcurve` for a stroke that would store the handles and other attributes. In GPv3, we can directly make use of the `CURVE_TYPE_BEZIER` and store the curve as a bézier curve. Note: This PR only handles conversion. Not rendering or anything else. Pull Request: https://projects.blender.org/blender/blender/pulls/118386
This commit is contained in:
@@ -77,13 +77,23 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
|
||||
|
||||
/* Get the number of points, number of strokes and the offsets for each stroke. */
|
||||
Vector<int> offsets;
|
||||
Vector<int8_t> curve_types;
|
||||
offsets.append(0);
|
||||
int num_strokes = 0;
|
||||
int num_points = 0;
|
||||
bool has_bezier_stroke = false;
|
||||
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf.strokes) {
|
||||
num_points += gps->totpoints;
|
||||
offsets.append(num_points);
|
||||
if (gps->editcurve != nullptr) {
|
||||
has_bezier_stroke = true;
|
||||
num_points += gps->editcurve->tot_curve_points;
|
||||
curve_types.append(CURVE_TYPE_BEZIER);
|
||||
}
|
||||
else {
|
||||
num_points += gps->totpoints;
|
||||
curve_types.append(CURVE_TYPE_POLY);
|
||||
}
|
||||
num_strokes++;
|
||||
offsets.append(num_points);
|
||||
}
|
||||
|
||||
/* Resize the CurvesGeometry. */
|
||||
@@ -96,8 +106,14 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
|
||||
OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||
|
||||
/* All strokes are poly curves. */
|
||||
curves.fill_curve_types(CURVE_TYPE_POLY);
|
||||
if (!has_bezier_stroke) {
|
||||
/* All strokes are poly curves. */
|
||||
curves.fill_curve_types(CURVE_TYPE_POLY);
|
||||
}
|
||||
else {
|
||||
curves.curve_types_for_write().copy_from(curve_types);
|
||||
curves.update_curve_types();
|
||||
}
|
||||
|
||||
/* Find used vertex groups in this drawing. */
|
||||
ListBase stroke_vertex_group_names;
|
||||
@@ -120,6 +136,12 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
|
||||
|
||||
/* Point Attributes. */
|
||||
MutableSpan<float3> positions = curves.positions_for_write();
|
||||
MutableSpan<float3> handle_positions_left = has_bezier_stroke ?
|
||||
curves.handle_positions_left_for_write() :
|
||||
MutableSpan<float3>();
|
||||
MutableSpan<float3> handle_positions_right = has_bezier_stroke ?
|
||||
curves.handle_positions_right_for_write() :
|
||||
MutableSpan<float3>();
|
||||
MutableSpan<float> radii = drawing.radii_for_write();
|
||||
MutableSpan<float> opacities = drawing.opacities_for_write();
|
||||
SpanAttributeWriter<float> delta_times = attributes.lookup_or_add_for_write_span<float>(
|
||||
@@ -160,8 +182,6 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
|
||||
|
||||
int stroke_i = 0;
|
||||
LISTBASE_FOREACH_INDEX (bGPDstroke *, gps, &gpf.strokes, stroke_i) {
|
||||
/* TODO: check if `gps->editcurve` is not nullptr and parse bezier curve instead. */
|
||||
|
||||
stroke_cyclic.span[stroke_i] = (gps->flag & GP_STROKE_CYCLIC) != 0;
|
||||
/* TODO: This should be a `double` attribute. */
|
||||
stroke_init_times.span[stroke_i] = float(gps->inittime);
|
||||
@@ -181,6 +201,7 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
|
||||
continue;
|
||||
}
|
||||
|
||||
const Span<bGPDspoint> src_points{gps->points, gps->totpoints};
|
||||
/* Previously, Grease Pencil used a radius convention where 1 `px` = 0.001 units. This `px`
|
||||
* was the brush size which would be stored in the stroke thickness and then scaled by the
|
||||
* point pressure factor. Finally, the render engine would divide this thickness value by
|
||||
@@ -188,8 +209,13 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
|
||||
* into blender units. Store the radius now directly in blender units. This makes it
|
||||
* consistent with how hair curves handle the radius. */
|
||||
const float stroke_thickness = float(gps->thickness) / 2000.0f;
|
||||
Span<bGPDspoint> src_points{gps->points, gps->totpoints};
|
||||
MutableSpan<float3> dst_positions = positions.slice(points);
|
||||
MutableSpan<float3> dst_handle_positions_left = has_bezier_stroke ?
|
||||
handle_positions_left.slice(points) :
|
||||
MutableSpan<float3>();
|
||||
MutableSpan<float3> dst_handle_positions_right = has_bezier_stroke ?
|
||||
handle_positions_right.slice(points) :
|
||||
MutableSpan<float3>();
|
||||
MutableSpan<float> dst_radii = radii.slice(points);
|
||||
MutableSpan<float> dst_opacities = opacities.slice(points);
|
||||
MutableSpan<float> dst_deltatimes = delta_times.span.slice(points);
|
||||
@@ -199,30 +225,58 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
|
||||
MutableSpan<MDeformVert> dst_dverts = use_dverts ? dverts.slice(points) :
|
||||
MutableSpan<MDeformVert>();
|
||||
|
||||
threading::parallel_for(src_points.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int point_i : range) {
|
||||
const bGPDspoint &pt = src_points[point_i];
|
||||
dst_positions[point_i] = float3(pt.x, pt.y, pt.z);
|
||||
dst_radii[point_i] = stroke_thickness * pt.pressure;
|
||||
dst_opacities[point_i] = pt.strength;
|
||||
dst_rotations[point_i] = pt.uv_rot;
|
||||
dst_vertex_colors[point_i] = ColorGeometry4f(pt.vert_color);
|
||||
dst_selection[point_i] = (pt.flag & GP_SPOINT_SELECT) != 0;
|
||||
if (use_dverts && gps->dvert) {
|
||||
copy_dvert(gps->dvert[point_i], dst_dverts[point_i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dst_deltatimes.first() = 0;
|
||||
threading::parallel_for(
|
||||
src_points.index_range().drop_front(1), 4096, [&](const IndexRange range) {
|
||||
for (const int point_i : range) {
|
||||
const bGPDspoint &pt = src_points[point_i];
|
||||
const bGPDspoint &pt_prev = src_points[point_i - 1];
|
||||
dst_deltatimes[point_i] = pt.time - pt_prev.time;
|
||||
if (curve_types[stroke_i] == CURVE_TYPE_POLY) {
|
||||
threading::parallel_for(src_points.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int point_i : range) {
|
||||
const bGPDspoint &pt = src_points[point_i];
|
||||
dst_positions[point_i] = float3(pt.x, pt.y, pt.z);
|
||||
dst_radii[point_i] = stroke_thickness * pt.pressure;
|
||||
dst_opacities[point_i] = pt.strength;
|
||||
dst_rotations[point_i] = pt.uv_rot;
|
||||
dst_vertex_colors[point_i] = ColorGeometry4f(pt.vert_color);
|
||||
dst_selection[point_i] = (pt.flag & GP_SPOINT_SELECT) != 0;
|
||||
if (use_dverts && gps->dvert) {
|
||||
copy_dvert(gps->dvert[point_i], dst_dverts[point_i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dst_deltatimes.first() = 0;
|
||||
threading::parallel_for(
|
||||
src_points.index_range().drop_front(1), 4096, [&](const IndexRange range) {
|
||||
for (const int point_i : range) {
|
||||
const bGPDspoint &pt = src_points[point_i];
|
||||
const bGPDspoint &pt_prev = src_points[point_i - 1];
|
||||
dst_deltatimes[point_i] = pt.time - pt_prev.time;
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (curve_types[stroke_i] == CURVE_TYPE_BEZIER) {
|
||||
BLI_assert(gps->editcurve != nullptr);
|
||||
Span<bGPDcurve_point> src_curve_points{gps->editcurve->curve_points,
|
||||
gps->editcurve->tot_curve_points};
|
||||
|
||||
threading::parallel_for(src_curve_points.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int point_i : range) {
|
||||
const bGPDcurve_point &cpt = src_curve_points[point_i];
|
||||
dst_positions[point_i] = float3(cpt.bezt.vec[1]);
|
||||
dst_handle_positions_left[point_i] = float3(cpt.bezt.vec[0]);
|
||||
dst_handle_positions_right[point_i] = float3(cpt.bezt.vec[2]);
|
||||
dst_radii[point_i] = stroke_thickness * cpt.pressure;
|
||||
dst_opacities[point_i] = cpt.strength;
|
||||
dst_rotations[point_i] = cpt.uv_rot;
|
||||
dst_vertex_colors[point_i] = ColorGeometry4f(cpt.vert_color);
|
||||
dst_selection[point_i] = (cpt.flag & GP_CURVE_POINT_SELECT) != 0;
|
||||
if (use_dverts && gps->dvert) {
|
||||
copy_dvert(gps->dvert[point_i], dst_dverts[point_i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
/* Unknown curve type. */
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
delta_times.finish();
|
||||
|
||||
Reference in New Issue
Block a user