76 Image *ima_ =
nullptr;
77 ImBuf *ibuf_ =
nullptr;
78 void *lock_ =
nullptr;
85 return ibuf_ !=
nullptr;
98 size_ = {ibuf_->x, ibuf_->y};
100 reinterpret_cast<ColorGeometry4b *
>(ibuf_->byte_buffer.data), ibuf_->x * ibuf_->y);
121 return this->size_.x;
126 return this->size_.y;
131 return c.x >= 0 && c.x < this->size_.x && c.y >= 0 && c.y < this->size_.y;
136 const div_t d = div(index, this->size_.x);
137 return int2{d.rem, d.quot};
142 return c.x + c.y * this->size_.x;
181 const bool is_stroke =
color.r > 0.0f;
182 const bool is_seed =
color.g > 0.0f;
193 constexpr const ColorGeometry4b output_stroke_color = {255, 0, 0, 255};
194 constexpr const ColorGeometry4b output_seed_color = {127, 127, 0, 255};
195 constexpr const ColorGeometry4b output_border_color = {0, 0, 255, 255};
196 constexpr const ColorGeometry4b output_fill_color = {127, 255, 0, 255};
199 constexpr const ColorGeometry4b output_debug_color = {255, 127, 0, 255};
203 std::min(
int(a.
g) +
int(
b.g), 255),
204 std::min(
int(a.
b) +
int(
b.b), 255),
205 std::min(
int(a.
a) +
int(
b.a), 255));
211 output_color = add_colors(output_color, output_debug_color);
214 output_color = add_colors(output_color, output_fill_color);
217 output_color = add_colors(output_color, output_stroke_color);
220 output_color = add_colors(output_color, output_border_color);
223 output_color = add_colors(output_color, output_seed_color);
225 color = std::move(output_color);
237 row_start += buffer.
width();
242 row_start += buffer.
width();
262template<FillBorderMode border_mode>
266 const int width = buffer.
width();
267 const int height = buffer.
height();
273 active_pixels.
push(
i);
277 enum FilterDirection {
282 bool border_contact =
false;
284 const int index = active_pixels.
pop();
290 border_contact =
true;
296 border_contact =
true;
316 std::min(width - 1 - coord.x, leak_filter_width));
319 std::min(height - 1 - coord.y, leak_filter_width));
320 bool is_boundary_horizontal =
false;
321 bool is_boundary_vertical =
false;
322 for (
const int filter_i : filter_y_neg) {
326 for (
const int filter_i : filter_y_pos) {
330 for (
const int filter_i : filter_x_neg) {
334 for (
const int filter_i : filter_x_pos) {
340 if (coord.x > 0 && !is_boundary_horizontal) {
343 if (coord.x < width - 1 && !is_boundary_horizontal) {
346 if (coord.y > 0 && !is_boundary_vertical) {
349 if (coord.y < height - 1 && !is_boundary_vertical) {
383 for ([[maybe_unused]]
const int iter :
IndexRange(iterations)) {
396 active_pixels.
push(
i);
402 const int index = active_pixels.
pop();
413 for ([[maybe_unused]]
const int iter :
IndexRange(iterations)) {
426 active_pixels.
push(
i);
432 const int index = active_pixels.
pop();
458 using BoundarySection = std::list<int>;
462 const int width = buffer.
width();
463 const int height = buffer.
height();
467 constexpr const uint8_t start_direction = 3;
468 auto find_start_coordinates = [&]() -> BoundaryStartMap {
469 BoundaryStartMap starts;
472 for (
const int x :
IndexRange(width).drop_back(1)) {
478 if (!filled_left && filled_right && !border_right) {
480 starts.add(index_right, {});
483 if (!include_holes) {
492 struct NeighborIterator {
498 auto find_next_neighbor = [&](NeighborIterator &iter) ->
bool {
503 const int neighbor_dir =
wrap_dir_3n(iter.direction + 5 +
i);
514 iter.index = neighbor_index;
515 iter.direction = neighbor_dir;
522 BoundaryStartMap boundary_starts = find_start_coordinates();
525 for (
const int start_index : boundary_starts.keys()) {
527 if (!boundary_starts.contains(start_index)) {
530 BoundarySection §ion = boundary_starts.lookup(start_index);
531 section.push_back(start_index);
532 NeighborIterator iter = {start_index, start_direction};
533 while (find_next_neighbor(iter)) {
535 if (iter.index == start_index) {
540 if (boundary_starts.contains(iter.index)) {
541 BoundarySection &next_section = boundary_starts.lookup(iter.index);
542 if (next_section.empty()) {
544 boundary_starts.remove(iter.index);
548 section.splice(section.end(), next_section);
549 boundary_starts.remove(iter.index);
554 section.push_back(iter.index);
557 if (iter.index != start_index) {
558 boundary_starts.remove(start_index);
564 for (
const BoundarySection §ion : boundary_starts.values()) {
566 for (
const int index : section) {
572 return final_boundary;
583 const int material_index,
584 const float hardness)
598 "curve_type",
"material_index",
"cyclic",
"hardness",
"fill_opacity"};
602 curves.update_curve_types();
626 cyclic.
span.fill(
true);
627 materials.
span.fill(material_index);
628 hardnesses.span.fill(hardness);
635 fill_opacities.finish();
637 for (
const int point_i :
curves.points_range()) {
638 const int pixel_index = boundary.
pixels[point_i];
640 const float2 region_coord =
643 positions[point_i] = position;
647 constexpr const float pressure = 1.0f;
661 if (use_vertex_color) {
667 skip_curve_attributes.
add(
"fill_color");
671 fill_colors.
span.fill(vertex_color);
675 skip_point_attributes.
add(
"vertex_color");
679 vertex_colors.
span.fill(vertex_color);
706 const int stroke_material_index,
707 const float stroke_hardness,
709 const bool output_as_colors)
711 constexpr const int leak_filter_width = 3;
716 if (output_as_colors) {
747 if (dilate_pixels > 0) {
748 dilate(buffer, dilate_pixels);
750 else if (dilate_pixels < 0) {
751 erode(buffer, -dilate_pixels);
756 const bool fill_holes =
invert;
766 stroke_material_index,
777 const bool is_boundary_layer,
785 auto is_visible_curve = [&](
const int curve_i) {
788 if (points.
size() < 2) {
794 materials[curve_i] + 1);
797 if (gp_style ==
nullptr || is_hidden_material) {
805 if (is_boundary_layer) {
811 if (!is_visible_curve(curve_i)) {
814 const bool is_boundary_stroke = fill_guides[curve_i];
815 return is_boundary_stroke;
828 const std::optional<float> alpha_threshold)
830 if (!alpha_threshold) {
836 for (const int curve_i : range) {
837 const Material *material = BKE_object_material_get(const_cast<Object *>(&object),
838 materials[curve_i] + 1);
839 const float material_alpha = material && material->gp_style ?
840 material->gp_style->stroke_rgba[3] :
842 const IndexRange points = curves.points_by_curve()[curve_i];
843 for (const int point_i : points) {
844 const float alpha = (material_alpha * opacities[point_i] > *alpha_threshold ? 1.0f : 0.0f);
845 colors[point_i] = ColorGeometry4f(tint_color.r, tint_color.g, tint_color.b, alpha);
864 const Object &object_eval,
871 std::optional<Bounds<float2>> boundary_bounds;
879 const Layer &layer = *grease_pencil.layers()[info.layer_index];
883 &object_eval,
object, info.drawing);
884 const bool only_boundary_strokes = boundary_layers[info.layer_index];
895 object, info, only_boundary_strokes, curve_mask_memory);
900 if (points.
size() < 2) {
904 const int material_index = materials[curve_i];
911 if (only_boundary_strokes && !is_boundary_stroke[curve_i]) {
915 for (
const int point_i : points) {
924 boundary_bounds =
bounds::merge(boundary_bounds, {point_bounds});
930 return boundary_bounds;
938 const bool uniform_zoom,
939 const float max_zoom_factor,
941 const float pixel_scale)
946 const int2 min_image_size =
int2(128, 128);
948 switch (fit_method) {
962 if (!boundary_bounds) {
984 fill_bounds.
center() - 0.5f * region_bounds.
size() * zoom.x,
985 fill_bounds.
center() + 0.5f * region_bounds.
size() * zoom.y};
989 region_bounds.
size());
994 return std::make_tuple(zoom, offset, image_size, image_to_region);
1007 const int2 &image_size,
1008 const std::optional<float> alpha_threshold,
1009 const float2 &fill_point,
1030 const float3 fill_point_layer = placement.
project(fill_point);
1038 if (offscreen_buffer ==
nullptr) {
1042 const bool use_xray =
false;
1046 const float4x4 layer_to_view = world_to_view * layer_to_world;
1054 const float mouse_dot_size = 4.0f;
1058 const Layer &layer = *grease_pencil.layers()[info.layer_index];
1059 if (!layer.is_visible()) {
1063 const bool is_boundary_layer = boundary_layers[info.layer_index];
1072 object, info, is_boundary_layer, curve_mask_memory);
1075 info.drawing.strokes(),
1097 const float line_width = 1.0f;
1122 const std::optional<float> alpha_threshold,
1123 const float2 &fill_point,
1126 const int stroke_material_index,
1127 const bool keep_images)
1138 const bool uniform_zoom =
true;
1139 const float max_zoom_factor = 5.0f;
1143 const auto [zoom, offset, image_size, image_to_region] =
fit_strokes_to_view(view_context,
1176 const float stroke_hardness = 1.0f;
1184 stroke_material_index,
Camera data-block and utility functions.
Low-level operations for curves.
Low-level operations for grease pencil.
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_id_free(Main *bmain, void *idv)
General operations, lookup, etc. for materials.
Material * BKE_object_material_get(Object *ob, short act)
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define BLI_SCOPED_DEFER(function_to_defer)
#define ENUM_OPERATORS(_type, _max)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
Object is a sort of wrapper for general info.
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
void GPU_depth_mask(bool depth)
void GPU_blend(GPUBlend blend)
BPy_StructRNA * depsgraph
static VArray from_single(T value, const int64_t size)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr IndexRange drop_front(int64_t n) const
constexpr IndexRange index_range() const
void push(const T &value)
static VArray from_single(T value, const int64_t size)
static VArray from_container(ContainerT container)
void append(const T &value)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
AttributeAccessor attributes() const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
const bke::CurvesGeometry & strokes() const
float4x4 to_world_space(const Object &object) const
bool use_project_to_surface() const
void cache_viewport_depths(Depsgraph *depsgraph, ARegion *region, View3D *view3d)
bool use_project_to_stroke() const
float4x4 to_world_space() const
float3 project_with_shift(float2 co) const
float3 project(float2 co, bool &clipped) const
MutableSpan< ColorGeometry4b > pixels()
Span< ColorGeometry4b > pixels() const
ColorGeometry4b & pixel_from_coord(const int2 &c)
int2 coord_from_index(const int index) const
int index_from_coord(const int2 &c) const
bool is_valid_coord(const int2 &c) const
const ColorGeometry4b & pixel_from_coord(const int2 &c) const
void foreach_index(Fn &&fn) const
VecBase< float, 2 > float2
CCL_NAMESPACE_BEGIN ccl_device float invert(const float color, const float factor)
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval, const Object &ob_orig, const bke::greasepencil::Drawing &drawing_orig)
auto attribute_filter_from_skip_ref(const Span< StringRef > skip)
void fill_attribute_range_default(MutableAttributeAccessor dst_attributes, AttrDomain domain, const AttributeFilter &attribute_filter, IndexRange range)
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
void compute_view_matrices(const ViewContext &view_context, const Scene &scene, const int2 &win_size, const float2 &zoom, const float2 &offset)
void region_reset(ARegion ®ion, const RegionViewData &data)
void draw_lines(const float4x4 &transform, IndexRange indices, Span< float3 > start_positions, Span< float3 > end_positions, const VArray< ColorGeometry4f > &colors, float line_width)
Image * image_render_end(Main &bmain, GPUOffScreen *buffer)
void draw_grease_pencil_strokes(const RegionView3D &rv3d, const int2 &win_size, const Object &object, const bke::greasepencil::Drawing &drawing, const float4x4 &transform, const IndexMask &strokes_mask, const VArray< ColorGeometry4f > &colors, const bool use_xray, const float radius_scale)
RegionViewData region_init(ARegion ®ion, const int2 &win_size)
void draw_dot(const float4x4 &transform, const float3 &position, const float point_size, const ColorGeometry4f &color)
GPUOffScreen * image_render_begin(const int2 &win_size)
void clear_projection_matrix()
void set_projection_matrix(const RegionView3D &rv3d)
static FillBoundary build_fill_boundary(const ImageBufferAccessor &buffer, bool include_holes)
static IndexMask get_visible_boundary_strokes(const Object &object, const DrawingInfo &info, const bool is_boundary_layer, IndexMaskMemory &memory)
static const int2 offset_by_direction[num_directions]
constexpr const char * attr_is_fill_guide
constexpr const char * attr_material_index
static Bounds< float2 > get_region_bounds(const ARegion ®ion)
static void dilate(ImageBufferAccessor &buffer, int iterations=1)
float opacity_from_input_sample(const float pressure, const Brush *brush, const BrushGpencilSettings *settings)
FillResult flood_fill(ImageBufferAccessor &buffer, const int leak_filter_width=0)
static void erode(ImageBufferAccessor &buffer, int iterations=1)
const ColorGeometry4f draw_boundary_color
static int wrap_dir_3n(const int dir)
bke::CurvesGeometry fill_strokes(const ViewContext &view_context, const Brush &brush, const Scene &scene, const bke::greasepencil::Layer &layer, const VArray< bool > &boundary_layers, Span< DrawingInfo > src_drawings, bool invert, const std::optional< float > alpha_threshold, const float2 &fill_point, const ExtensionData &extensions, FillToolFitMethod fit_method, int stroke_material_index, bool keep_images)
constexpr const int num_directions
static VArray< ColorGeometry4f > get_stroke_colors(const Object &object, const bke::CurvesGeometry &curves, const VArray< float > &opacities, const VArray< int > materials, const ColorGeometry4f &tint_color, const std::optional< float > alpha_threshold)
static void mark_borders(ImageBufferAccessor &buffer)
static std::optional< Bounds< float2 > > get_boundary_bounds(const ARegion ®ion, const RegionView3D &rv3d, const Object &object, const Object &object_eval, const VArray< bool > &boundary_layers, const Span< DrawingInfo > src_drawings)
static void convert_colors_to_flags(ImageBufferAccessor &buffer)
static bke::CurvesGeometry boundary_to_curves(const Scene &scene, const ViewContext &view_context, const Brush &brush, const FillBoundary &boundary, const ImageBufferAccessor &buffer, const ed::greasepencil::DrawingPlacement &placement, const float3x3 &image_to_region, const int material_index, const float hardness)
static auto fit_strokes_to_view(const ViewContext &view_context, const VArray< bool > &boundary_layers, const Span< DrawingInfo > src_drawings, const FillToolFitMethod fit_method, const float2 fill_point, const bool uniform_zoom, const float max_zoom_factor, const float2 margin, const float pixel_scale)
static bke::CurvesGeometry process_image(Image &ima, const Scene &scene, const ViewContext &view_context, const Brush &brush, const ed::greasepencil::DrawingPlacement &placement, const float3x3 &image_to_region, const int stroke_material_index, const float stroke_hardness, const bool invert, const bool output_as_colors)
static Image * render_strokes(const ViewContext &view_context, const Brush &brush, const Scene &scene, const bke::greasepencil::Layer &layer, const VArray< bool > &boundary_layers, const Span< DrawingInfo > src_drawings, const int2 &image_size, const std::optional< float > alpha_threshold, const float2 &fill_point, const ExtensionData &extensions, const ed::greasepencil::DrawingPlacement &placement, const float2 &zoom, const float2 &offset)
float radius_from_input_sample(const RegionView3D *rv3d, const ARegion *region, const Brush *brush, const float pressure, const float3 &location, const float4x4 &to_world, const BrushGpencilSettings *settings)
static void convert_flags_to_colors(ImageBufferAccessor &buffer)
static void set_flag(ColorGeometry4b &color, const ColorFlag flag, bool value)
const ColorGeometry4f draw_seed_color
static bool get_flag(const ColorGeometry4b &color, const ColorFlag flag)
static void invert_fill(ImageBufferAccessor &buffer)
bool brush_using_vertex_color(const GpPaint *gp_paint, const Brush *brush)
T clamp(const T &a, const T &min, const T &max)
T safe_divide(const T &a, const T &b)
T reduce_max(const VecBase< T, Size > &a)
MatT from_loc_scale(const typename MatT::loc_type &location, const VecBase< typename MatT::base_type, ScaleDim > &scale)
T max(const T &a, const T &b)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
MatBase< float, 3, 3 > float3x3
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
struct BrushGpencilSettings * gpencil_settings
struct MaterialGPencilStyle * gp_style
struct ToolSettings * toolsettings
static MatBase identity()
VecBase< T, 2 > xy() const
MutableVArraySpan< T > span
const bke::greasepencil::Drawing & drawing
struct blender::ed::greasepencil::ExtensionData::@020012301277233322117257155067364007210377153176 lines
Vector< int > offset_indices