GPv3: Add access functions for opacity and radius attributes

We need setters and getters for these two very commonly accessed attributes of grease pencil.
The code is based on the implementation of `CurvesGeometry::positions()` and `CurvesGeometry::positions_for_write()`.

Co-authored-by: Falk David <falk@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/109733
This commit is contained in:
Amelie
2023-07-11 15:11:14 +02:00
committed by Falk David
parent d31a0e8393
commit f2d3d321bb
5 changed files with 86 additions and 22 deletions

View File

@@ -14,6 +14,7 @@
#include "BLI_math_vector_types.hh"
#include "BLI_shared_cache.hh"
#include "BLI_utility_mixins.hh"
#include "BLI_virtual_array.hh"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_grease_pencil_types.h"
@@ -76,6 +77,19 @@ class Drawing : public ::GreasePencilDrawing {
*/
Span<uint3> triangles() const;
void tag_positions_changed();
/**
* Radii of the points. Values are expected to be in blender units.
*/
VArray<float> radii() const;
MutableSpan<float> radii_for_write();
/**
* Opacities for the points. Used by the render engine as an alpha value so they are expected to
* be between 0 and 1 inclusive.
*/
VArray<float> opacities() const;
MutableSpan<float> opacities_for_write();
};
class LayerGroup;

View File

@@ -29,6 +29,7 @@
#include "BLI_string_ref.hh"
#include "BLI_string_utils.h"
#include "BLI_vector_set.hh"
#include "BLI_virtual_array.hh"
#include "BLO_read_write.h"
@@ -250,6 +251,40 @@ IDTypeInfo IDType_ID_GP = {
namespace blender::bke::greasepencil {
static const std::string ATTR_OPACITY = "opacity";
static const std::string ATTR_RADIUS = "radius";
/* Curves attributes getters */
static int domain_num(const CurvesGeometry &curves, const eAttrDomain domain)
{
return domain == ATTR_DOMAIN_POINT ? curves.points_num() : curves.curves_num();
}
static CustomData &domain_custom_data(CurvesGeometry &curves, const eAttrDomain domain)
{
return domain == ATTR_DOMAIN_POINT ? curves.point_data : curves.curve_data;
}
template<typename T>
static MutableSpan<T> get_mutable_attribute(CurvesGeometry &curves,
const eAttrDomain domain,
const StringRefNull name,
const T default_value = T())
{
const int num = domain_num(curves, domain);
const eCustomDataType type = cpp_type_to_custom_data_type(CPPType::get<T>());
CustomData &custom_data = domain_custom_data(curves, domain);
T *data = (T *)CustomData_get_layer_named_for_write(&custom_data, type, name.c_str(), num);
if (data != nullptr) {
return {data, num};
}
data = (T *)CustomData_add_layer_named(&custom_data, type, CD_SET_DEFAULT, num, name.c_str());
MutableSpan<T> span = {data, num};
if (num > 0 && span.first() != default_value) {
span.fill(default_value);
}
return span;
}
Drawing::Drawing()
{
this->base.type = GP_DRAWING;
@@ -344,6 +379,30 @@ bke::CurvesGeometry &Drawing::strokes_for_write()
return this->geometry.wrap();
}
VArray<float> Drawing::radii() const
{
return *this->strokes().attributes().lookup_or_default<float>(
ATTR_RADIUS, ATTR_DOMAIN_POINT, 0.01f);
}
MutableSpan<float> Drawing::radii_for_write()
{
return get_mutable_attribute<float>(
this->geometry.wrap(), ATTR_DOMAIN_POINT, ATTR_RADIUS, 0.01f);
}
VArray<float> Drawing::opacities() const
{
return *this->strokes().attributes().lookup_or_default<float>(
ATTR_OPACITY, ATTR_DOMAIN_POINT, 1.0f);
}
MutableSpan<float> Drawing::opacities_for_write()
{
return get_mutable_attribute<float>(
this->geometry.wrap(), ATTR_DOMAIN_POINT, ATTR_OPACITY, 1.0f);
}
void Drawing::tag_positions_changed()
{
this->geometry.wrap().tag_positions_changed();

View File

@@ -40,7 +40,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
}
/* Resize the CurvesGeometry. */
CurvesGeometry &curves = r_drawing.geometry.wrap();
Drawing &drawing = r_drawing.wrap();
CurvesGeometry &curves = drawing.strokes_for_write();
curves.resize(num_points, num_strokes);
if (num_strokes > 0) {
curves.offsets_for_write().copy_from(offsets);
@@ -53,10 +54,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
/* Point Attributes. */
MutableSpan<float3> positions = curves.positions_for_write();
SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_span<float>(
"radius", ATTR_DOMAIN_POINT);
SpanAttributeWriter<float> opacities = attributes.lookup_or_add_for_write_span<float>(
"opacity", ATTR_DOMAIN_POINT);
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>(
"delta_time", ATTR_DOMAIN_POINT);
SpanAttributeWriter<float> rotations = attributes.lookup_or_add_for_write_span<float>(
@@ -118,8 +117,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
Span<bGPDspoint> stroke_points{gps->points, gps->totpoints};
MutableSpan<float3> stroke_positions = positions.slice(stroke_points_range);
MutableSpan<float> stroke_radii = radii.span.slice(stroke_points_range);
MutableSpan<float> stroke_opacities = opacities.span.slice(stroke_points_range);
MutableSpan<float> stroke_radii = radii.slice(stroke_points_range);
MutableSpan<float> stroke_opacities = opacities.slice(stroke_points_range);
MutableSpan<float> stroke_deltatimes = delta_times.span.slice(stroke_points_range);
MutableSpan<float> stroke_rotations = rotations.span.slice(stroke_points_range);
MutableSpan<ColorGeometry4f> stroke_vertex_colors = vertex_colors.span.slice(
@@ -153,8 +152,6 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
}
}
radii.finish();
opacities.finish();
delta_times.finish();
rotations.finish();
vertex_colors.finish();

View File

@@ -315,10 +315,8 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const Span<float3> positions = curves.positions();
const VArray<bool> cyclic = curves.cyclic();
const VArray<float> radii = *attributes.lookup_or_default<float>(
"radius", ATTR_DOMAIN_POINT, 1.0f);
const VArray<float> opacities = *attributes.lookup_or_default<float>(
"opacity", ATTR_DOMAIN_POINT, 1.0f);
const VArray<float> radii = drawing.radii();
const VArray<float> opacities = drawing.opacities();
/* Assumes that if the ".selection" attribute does not exist, all points are selected. */
const VArray<float> selection_float = *attributes.lookup_or_default<float>(
".selection", ATTR_DOMAIN_POINT, true);

View File

@@ -91,7 +91,7 @@ void PaintOperation::on_stroke_done(const bContext &C)
const Span<bke::greasepencil::StrokePoint> stroke_points =
grease_pencil_eval.runtime->stroke_buffer();
CurvesGeometry &curves = drawing_orig.geometry.wrap();
CurvesGeometry &curves = drawing_orig.strokes_for_write();
int num_old_curves = curves.curves_num();
int num_old_points = curves.points_num();
@@ -107,16 +107,14 @@ void PaintOperation::on_stroke_done(const bContext &C)
/* Set position, radius and opacity attribute. */
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
MutableSpan<float3> positions = curves.positions_for_write();
SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_span<float>(
"radius", ATTR_DOMAIN_POINT);
SpanAttributeWriter<float> opacities = attributes.lookup_or_add_for_write_span<float>(
"opacity", ATTR_DOMAIN_POINT);
MutableSpan<float> radii = drawing_orig.radii_for_write();
MutableSpan<float> opacities = drawing_orig.opacities_for_write();
for (const int i : IndexRange(stroke_points.size())) {
const bke::greasepencil::StrokePoint &point = stroke_points[i];
const int point_i = new_points_range[i];
positions[point_i] = point.position;
radii.span[point_i] = point.radius;
opacities.span[point_i] = point.opacity;
radii[point_i] = point.radius;
opacities[point_i] = point.opacity;
}
/* Set material index attribute. */
@@ -149,8 +147,6 @@ void PaintOperation::on_stroke_done(const bContext &C)
grease_pencil_eval.runtime->stroke_cache.clear();
drawing_orig.tag_positions_changed();
radii.finish();
opacities.finish();
materials.finish();
DEG_id_tag_update(&grease_pencil_orig.id, ID_RECALC_GEOMETRY);