diff --git a/source/blender/editors/sculpt_paint/grease_pencil_erase.cc b/source/blender/editors/sculpt_paint/grease_pencil_erase.cc index 63b8038f1a4..32bed696bb6 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_erase.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_erase.cc @@ -867,52 +867,58 @@ struct EraseOperationExecutor { GreasePencil &grease_pencil = *static_cast(obact->data); bool changed = false; - const auto execute_eraser_on_drawing = [&](const int layer_index, - const int frame_number, - Drawing &drawing) { - const Layer &layer = grease_pencil.layer(layer_index); - const bke::CurvesGeometry &src = drawing.strokes(); + const auto execute_eraser_on_drawing = + [&](const int layer_index, const int frame_number, Drawing &drawing) { + const Layer &layer = grease_pencil.layer(layer_index); + const bke::CurvesGeometry &src = drawing.strokes(); - /* Evaluated geometry. */ - bke::crazyspace::GeometryDeformation deformation = - bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation( - ob_eval, *obact, layer_index, frame_number); + /* Evaluated geometry. */ + bke::crazyspace::GeometryDeformation deformation = + bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation( + ob_eval, *obact, layer_index, frame_number); - /* Compute screen space positions. */ - Array screen_space_positions(src.points_num()); - threading::parallel_for(src.points_range(), 4096, [&](const IndexRange src_points) { - for (const int src_point : src_points) { - ED_view3d_project_float_global(region, - math::transform_point(layer.to_world_space(*ob_eval), - deformation.positions[src_point]), - screen_space_positions[src_point], - V3D_PROJ_TEST_NOP); - } - }); + /* Compute screen space positions. */ + Array screen_space_positions(src.points_num()); + threading::parallel_for(src.points_range(), 4096, [&](const IndexRange src_points) { + for (const int src_point : src_points) { + const int result = ED_view3d_project_float_global( + region, + math::transform_point(layer.to_world_space(*ob_eval), + deformation.positions[src_point]), + screen_space_positions[src_point], + V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_FAR); + if (result != V3D_PROJ_RET_OK) { + /* Set the screen space position to a impossibly far coordinate for all the points + * that are outside near/far clipping planes, this is to prevent accidental + * intersections with strokes not visibly present in the camera. */ + screen_space_positions[src_point] = float2(1e20); + } + } + }); - /* Erasing operator. */ - bke::CurvesGeometry dst; - bool erased = false; - switch (self.eraser_mode_) { - case GP_BRUSH_ERASER_STROKE: - erased = stroke_eraser(src, screen_space_positions, dst); - break; - case GP_BRUSH_ERASER_HARD: - erased = hard_eraser(src, screen_space_positions, dst, self.keep_caps_); - break; - case GP_BRUSH_ERASER_SOFT: - erased = soft_eraser(src, screen_space_positions, dst, self.keep_caps_); - break; - } + /* Erasing operator. */ + bke::CurvesGeometry dst; + bool erased = false; + switch (self.eraser_mode_) { + case GP_BRUSH_ERASER_STROKE: + erased = stroke_eraser(src, screen_space_positions, dst); + break; + case GP_BRUSH_ERASER_HARD: + erased = hard_eraser(src, screen_space_positions, dst, self.keep_caps_); + break; + case GP_BRUSH_ERASER_SOFT: + erased = soft_eraser(src, screen_space_positions, dst, self.keep_caps_); + break; + } - if (erased) { - /* Set the new geometry. */ - drawing.geometry.wrap() = std::move(dst); - drawing.tag_topology_changed(); - changed = true; - self.affected_drawings_.add(&drawing); - } - }; + if (erased) { + /* Set the new geometry. */ + drawing.geometry.wrap() = std::move(dst); + drawing.tag_topology_changed(); + changed = true; + self.affected_drawings_.add(&drawing); + } + }; if (self.active_layer_only_) { /* Erase only on the drawing at the current frame of the active layer. */