GPv3: Fix initialization of the DrawingPlacement struct from tool settings

The `DrawingPlacement` utility struct is initialized based on various
tool settings, including the `gpencil_v3d_align` flag. This flag was
used in a switch statement, but didn't handle all the potential flag
combinations, leaving placement variables like the origin vector
uninitialized and causing nan values when projecting.

Pull Request: https://projects.blender.org/blender/blender/pulls/121246
This commit is contained in:
Lukas Tönne
2024-05-01 09:03:10 +02:00
parent f595345f52
commit 6c1bf7fc94
4 changed files with 65 additions and 29 deletions

View File

@@ -68,26 +68,35 @@ DrawingPlacement::DrawingPlacement(const Scene &scene,
}
}
/* Initialize DrawingPlacementDepth from toolsettings. */
switch (scene.toolsettings->gpencil_v3d_align) {
case GP_PROJECT_VIEWSPACE:
depth_ = DrawingPlacementDepth::ObjectOrigin;
placement_loc_ = layer_space_to_world_space_.location();
break;
case (GP_PROJECT_VIEWSPACE | GP_PROJECT_CURSOR):
const char align_flag = scene.toolsettings->gpencil_v3d_align;
if (align_flag & GP_PROJECT_VIEWSPACE) {
if (align_flag & GP_PROJECT_CURSOR) {
depth_ = DrawingPlacementDepth::Cursor;
surface_offset_ = 0.0f;
placement_loc_ = float3(scene.cursor.location);
break;
case (GP_PROJECT_VIEWSPACE | GP_PROJECT_DEPTH_VIEW):
}
if (align_flag & GP_PROJECT_DEPTH_VIEW) {
depth_ = DrawingPlacementDepth::Surface;
surface_offset_ = scene.toolsettings->gpencil_surface_offset;
/* Default to view placement with the object origin if we don't hit a surface. */
placement_loc_ = layer_space_to_world_space_.location();
break;
case (GP_PROJECT_VIEWSPACE | GP_PROJECT_DEPTH_STROKE):
}
if (align_flag & GP_PROJECT_DEPTH_STROKE) {
depth_ = DrawingPlacementDepth::NearestStroke;
surface_offset_ = 0.0f;
/* Default to view placement with the object origin if we don't hit a stroke. */
placement_loc_ = layer_space_to_world_space_.location();
break;
}
else {
depth_ = DrawingPlacementDepth::ObjectOrigin;
surface_offset_ = 0.0f;
placement_loc_ = layer_space_to_world_space_.location();
}
}
else {
depth_ = DrawingPlacementDepth::ObjectOrigin;
surface_offset_ = 0.0f;
placement_loc_ = float3(0.0f);
}
if (ELEM(plane_,

View File

@@ -71,19 +71,19 @@ struct GreasePencilStrokeParams {
int layer_index;
int frame_number;
float multi_frame_falloff;
ed::greasepencil::DrawingPlacement placement;
const ed::greasepencil::DrawingPlacement &placement;
bke::greasepencil::Drawing &drawing;
/* Note: accessing region in worker threads will return null,
* this has to be done on the main thread and passed explicitly. */
static GreasePencilStrokeParams from_context(const Scene &scene,
const Depsgraph &depsgraph,
const ARegion &region,
const View3D &view3d,
Depsgraph &depsgraph,
ARegion &region,
Object &object,
int layer_index,
int frame_number,
float multi_frame_falloff,
const ed::greasepencil::DrawingPlacement &placement,
bke::greasepencil::Drawing &drawing);
};
@@ -105,6 +105,8 @@ class GreasePencilStrokeOperationCommon : public GreasePencilStrokeOperation {
BrushStrokeMode stroke_mode;
/* Initiali mouse sample position, used for placement origin. */
float2 start_mouse_position;
/* Previous mouse position for computing the direction. */
float2 prev_mouse_position;

View File

@@ -153,20 +153,19 @@ bool is_brush_inverted(const Brush &brush, const BrushStrokeMode stroke_mode)
GreasePencilStrokeParams GreasePencilStrokeParams::from_context(
const Scene &scene,
const Depsgraph &depsgraph,
const ARegion &region,
const View3D &view3d,
Depsgraph &depsgraph,
ARegion &region,
Object &object,
const int layer_index,
const int frame_number,
const float multi_frame_falloff,
const ed::greasepencil::DrawingPlacement &placement,
bke::greasepencil::Drawing &drawing)
{
Object &ob_eval = *DEG_get_evaluated_object(&depsgraph, &object);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
const bke::greasepencil::Layer &layer = *grease_pencil.layers()[layer_index];
ed::greasepencil::DrawingPlacement placement(scene, region, view3d, ob_eval, layer);
return {*scene.toolsettings,
region,
@@ -176,7 +175,7 @@ GreasePencilStrokeParams GreasePencilStrokeParams::from_context(
layer_index,
frame_number,
multi_frame_falloff,
std::move(placement),
placement,
drawing};
}
@@ -235,24 +234,36 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing(
using namespace blender::bke::greasepencil;
const Scene &scene = *CTX_data_scene(&C);
const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C);
const View3D &view3d = *CTX_wm_view3d(&C);
const ARegion &region = *CTX_wm_region(&C);
Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C);
View3D &view3d = *CTX_wm_view3d(&C);
ARegion &region = *CTX_wm_region(&C);
Object &object = *CTX_data_active_object(&C);
Object &object_eval = *DEG_get_evaluated_object(&depsgraph, &object);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
std::atomic<bool> changed = false;
const Vector<MutableDrawingInfo> drawings = get_drawings_for_sculpt(C);
threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) {
const Layer &layer = *grease_pencil.layers()[info.layer_index];
ed::greasepencil::DrawingPlacement placement(scene, region, view3d, object_eval, layer);
if (placement.use_project_to_surface()) {
placement.cache_viewport_depths(&depsgraph, &region, &view3d);
}
else if (placement.use_project_to_nearest_stroke()) {
placement.cache_viewport_depths(&depsgraph, &region, &view3d);
placement.set_origin_to_nearest_stroke(this->start_mouse_position);
}
GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context(
scene,
depsgraph,
region,
view3d,
object,
info.layer_index,
info.frame_number,
info.multi_frame_falloff,
placement,
info.drawing);
if (fn(params)) {
changed = true;
@@ -273,6 +284,7 @@ void GreasePencilStrokeOperationCommon::init_stroke(const bContext &C,
init_brush(brush);
this->start_mouse_position = start_sample.mouse_position;
this->prev_mouse_position = start_sample.mouse_position;
}

View File

@@ -67,11 +67,15 @@ void GrabOperation::foreach_grabbed_drawing(
const GreasePencilStrokeParams &params, const IndexMask &mask, Span<float> weights)> fn)
const
{
using bke::greasepencil::Drawing;
using bke::greasepencil::Layer;
const Scene &scene = *CTX_data_scene(&C);
const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C);
const ARegion &region = *CTX_wm_region(&C);
const View3D &view3d = *CTX_wm_view3d(&C);
Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C);
ARegion &region = *CTX_wm_region(&C);
View3D &view3d = *CTX_wm_view3d(&C);
Object &object = *CTX_data_active_object(&C);
Object &object_eval = *DEG_get_evaluated_object(&depsgraph, &object);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
bool changed = false;
@@ -80,7 +84,7 @@ void GrabOperation::foreach_grabbed_drawing(
if (data.point_mask.is_empty()) {
return;
}
const bke::greasepencil::Layer &layer = *grease_pencil.layers()[data.layer_index];
const Layer &layer = *grease_pencil.layers()[data.layer_index];
/* If a new frame is created, could be impossible find the stroke. */
const int drawing_index = layer.drawing_index_at(data.frame_number);
if (drawing_index < 0) {
@@ -93,15 +97,24 @@ void GrabOperation::foreach_grabbed_drawing(
bke::greasepencil::Drawing &drawing =
reinterpret_cast<GreasePencilDrawing &>(drawing_base).wrap();
ed::greasepencil::DrawingPlacement placement(scene, region, view3d, object_eval, layer);
if (placement.use_project_to_surface()) {
placement.cache_viewport_depths(&depsgraph, &region, &view3d);
}
else if (placement.use_project_to_nearest_stroke()) {
placement.cache_viewport_depths(&depsgraph, &region, &view3d);
placement.set_origin_to_nearest_stroke(this->start_mouse_position);
}
GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context(
scene,
depsgraph,
region,
view3d,
object,
data.layer_index,
data.frame_number,
data.multi_frame_falloff,
std::move(placement),
drawing);
if (fn(params, data.point_mask, data.weights)) {
changed = true;