GPv3: Add DrawingTransforms

This makes sure that when the object is transformed, the painting code will take that
transformation into account.

Resolves #113424.

Pull Request: https://projects.blender.org/blender/blender/pulls/113442
This commit is contained in:
Falk David
2023-10-09 12:42:01 +02:00
committed by Falk David
parent 744bdb84f7
commit e7e1ec55d2
3 changed files with 28 additions and 8 deletions

View File

@@ -15,6 +15,7 @@
#include "BLI_color.hh"
#include "BLI_function_ref.hh"
#include "BLI_map.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_shared_cache.hh"
#include "BLI_utility_mixins.hh"
@@ -34,6 +35,14 @@ namespace blender::bke {
namespace greasepencil {
struct DrawingTransforms {
float4x4 world_space_to_layer_space;
float4x4 layer_space_to_world_space;
DrawingTransforms() = default;
DrawingTransforms(const Object &grease_pencil_ob);
};
class DrawingRuntime {
public:
/**

View File

@@ -45,6 +45,7 @@
#include "DNA_grease_pencil_types.h"
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
@@ -224,6 +225,12 @@ IDTypeInfo IDType_ID_GP = {
namespace blender::bke::greasepencil {
DrawingTransforms::DrawingTransforms(const Object &grease_pencil_ob)
{
this->layer_space_to_world_space = float4x4_view(grease_pencil_ob.object_to_world);
this->world_space_to_layer_space = math::invert(this->layer_space_to_world_space);
}
static const std::string ATTR_RADIUS = "radius";
static const std::string ATTR_OPACITY = "opacity";
static const std::string ATTR_VERTEX_COLOR = "vertex_color";

View File

@@ -119,6 +119,8 @@ struct PaintOperationExecutor {
bke::greasepencil::Drawing *drawing_;
bke::greasepencil::DrawingTransforms transforms_;
PaintOperationExecutor(const bContext &C)
{
Scene *scene = CTX_data_scene(&C);
@@ -155,16 +157,18 @@ struct PaintOperationExecutor {
BLI_assert(drawing_index >= 0);
drawing_ =
&reinterpret_cast<GreasePencilDrawing *>(grease_pencil_->drawing(drawing_index))->wrap();
transforms_ = bke::greasepencil::DrawingTransforms(*object);
}
float3 screen_space_to_object_space(const float2 co)
float3 screen_space_to_drawing_plane(const float2 co)
{
/* TODO: Use correct plane/projection. */
const float4 plane{0.0f, -1.0f, 0.0f, 0.0f};
/* TODO: Use object transform. */
float3 proj_point;
ED_view3d_win_to_3d_on_plane(region_, plane, co, false, proj_point);
return proj_point;
ED_view3d_win_to_3d_on_plane(
region_, transforms_.layer_space_to_world_space * plane, co, false, proj_point);
return math::transform_point(transforms_.world_space_to_layer_space, proj_point);
}
float radius_from_input_sample(const InputSample &sample)
@@ -204,7 +208,7 @@ struct PaintOperationExecutor {
curves.resize(curves.points_num() + 1, curves.curves_num() + 1);
curves.offsets_for_write().last(1) = num_old_points;
curves.positions_for_write().last() = screen_space_to_object_space(start_coords);
curves.positions_for_write().last() = screen_space_to_drawing_plane(start_coords);
drawing_->radii_for_write().last() = start_radius;
drawing_->opacities_for_write().last() = start_opacity;
drawing_->vertex_colors_for_write().last() = start_vertex_color;
@@ -298,7 +302,7 @@ struct PaintOperationExecutor {
/* Update the positions in the current cache. */
smoothed_coords_slice[i] = new_pos;
positions_slice[i] = screen_space_to_object_space(new_pos);
positions_slice[i] = screen_space_to_drawing_plane(new_pos);
}
/* Remove all the converged points from the active window and shrink the window accordingly. */
@@ -332,7 +336,7 @@ struct PaintOperationExecutor {
/* Overwrite last point if it's very close. */
if (math::distance(coords, prev_coords) < POINT_OVERRIDE_THRESHOLD_PX) {
curves.positions_for_write().last() = screen_space_to_object_space(coords);
curves.positions_for_write().last() = screen_space_to_drawing_plane(coords);
drawing_->radii_for_write().last() = math::max(radius, prev_radius);
drawing_->opacities_for_write().last() = math::max(opacity, prev_opacity);
return;
@@ -376,7 +380,7 @@ struct PaintOperationExecutor {
if (points.size() < min_active_smoothing_points_num) {
MutableSpan<float3> positions_slice = curves.positions_for_write().slice(new_range);
for (const int64_t i : new_screen_space_coords.index_range()) {
positions_slice[i] = screen_space_to_object_space(new_screen_space_coords[i]);
positions_slice[i] = screen_space_to_drawing_plane(new_screen_space_coords[i]);
}
return;
}