diff --git a/source/blender/editors/space_sequencer/sequencer_preview_draw.cc b/source/blender/editors/space_sequencer/sequencer_preview_draw.cc index 617056ab56f..fd76a44315f 100644 --- a/source/blender/editors/space_sequencer/sequencer_preview_draw.cc +++ b/source/blender/editors/space_sequencer/sequencer_preview_draw.cc @@ -1062,8 +1062,8 @@ static void strip_draw_image_origin_and_outline(const bContext *C, immUnbindProgram(); /* Outline. */ - float strip_image_quad[4][2]; - SEQ_image_transform_final_quad_get(CTX_data_scene(C), strip, strip_image_quad); + const blender::Array strip_image_quad = SEQ_image_transform_final_quad_get( + CTX_data_scene(C), strip); GPU_line_smooth(true); GPU_blend(GPU_BLEND_ALPHA); @@ -1080,10 +1080,10 @@ static void strip_draw_image_origin_and_outline(const bContext *C, immUniformColor3fv(col); immUniform1f("lineWidth", U.pixelsize); immBegin(GPU_PRIM_LINE_LOOP, 4); - immVertex2f(pos, strip_image_quad[0][0], strip_image_quad[0][1]); - immVertex2f(pos, strip_image_quad[1][0], strip_image_quad[1][1]); - immVertex2f(pos, strip_image_quad[2][0], strip_image_quad[2][1]); - immVertex2f(pos, strip_image_quad[3][0], strip_image_quad[3][1]); + immVertex2f(pos, strip_image_quad[0].x, strip_image_quad[0].y); + immVertex2f(pos, strip_image_quad[1].x, strip_image_quad[1].y); + immVertex2f(pos, strip_image_quad[2].x, strip_image_quad[2].y); + immVertex2f(pos, strip_image_quad[3].x, strip_image_quad[3].y); immEnd(); immUnbindProgram(); GPU_line_width(1); @@ -1124,8 +1124,7 @@ static void text_selection_draw(const bContext *C, const Strip *strip, uint pos) const blender::float3 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f, 0.0f}; const float view_aspect = scene->r.xasp / scene->r.yasp; - blender::float4x4 transform_mat; - SEQ_image_transform_matrix_get(scene, strip, transform_mat.ptr()); + blender::float4x4 transform_mat = SEQ_image_transform_matrix_get(scene, strip); blender::float4x3 selection_quad{ {character_start.position.x, line_y, 0.0f}, {character_start.position.x, line_y + text->line_height, 0.0f}, @@ -1169,8 +1168,7 @@ static void text_edit_draw_cursor(const bContext *C, const Strip *strip, uint po const blender::float3 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f, 0.0f}; const float view_aspect = scene->r.xasp / scene->r.yasp; - blender::float4x4 transform_mat; - SEQ_image_transform_matrix_get(scene, strip, transform_mat.ptr()); + blender::float4x4 transform_mat = SEQ_image_transform_matrix_get(scene, strip); const blender::int2 cursor_position = strip_text_cursor_offset_to_position(text, data->cursor_offset); const float cursor_width = 10; @@ -1217,8 +1215,7 @@ static void text_edit_draw_box(const bContext *C, const Strip *strip, uint pos) const blender::float3 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f, 0.0f}; const float view_aspect = scene->r.xasp / scene->r.yasp; - blender::float4x4 transform_mat; - SEQ_image_transform_matrix_get(CTX_data_scene(C), strip, transform_mat.ptr()); + blender::float4x4 transform_mat = SEQ_image_transform_matrix_get(CTX_data_scene(C), strip); blender::float4x3 box_quad{ {float(text->text_boundbox.xmin), float(text->text_boundbox.ymin), 0.0f}, {float(text->text_boundbox.xmin), float(text->text_boundbox.ymax), 0.0f}, diff --git a/source/blender/editors/space_sequencer/sequencer_select.cc b/source/blender/editors/space_sequencer/sequencer_select.cc index 79b95012efc..9af957933ba 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.cc +++ b/source/blender/editors/space_sequencer/sequencer_select.cc @@ -442,8 +442,8 @@ void recurs_sel_seq(Strip *strip_meta) bool strip_point_image_isect(const Scene *scene, const Strip *strip, float point_view[2]) { - float strip_image_quad[4][2]; - SEQ_image_transform_final_quad_get(scene, strip, strip_image_quad); + const blender::Array strip_image_quad = SEQ_image_transform_final_quad_get( + scene, strip); return isect_point_quad_v2(point_view, strip_image_quad[0], strip_image_quad[1], @@ -2025,8 +2025,8 @@ static bool strip_box_select_rect_image_isect(const Scene *scene, const Strip *strip, const rctf *rect) { - float strip_image_quad[4][2]; - SEQ_image_transform_final_quad_get(scene, strip, strip_image_quad); + const blender::Array strip_image_quad = SEQ_image_transform_final_quad_get( + scene, strip); float rect_quad[4][2] = {{rect->xmax, rect->ymax}, {rect->xmax, rect->ymin}, {rect->xmin, rect->ymin}, diff --git a/source/blender/editors/space_sequencer/sequencer_text_edit.cc b/source/blender/editors/space_sequencer/sequencer_text_edit.cc index 741046c43cb..0577dbe6e7d 100644 --- a/source/blender/editors/space_sequencer/sequencer_text_edit.cc +++ b/source/blender/editors/space_sequencer/sequencer_text_edit.cc @@ -674,8 +674,7 @@ static void cursor_set_by_mouse_position(const bContext *C, const wmEvent *event /* Convert cursor coordinates to domain of CharInfo::position. */ const blender::float3 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f, 0.0f}; const float view_aspect = scene->r.xasp / scene->r.yasp; - blender::float4x4 transform_mat; - SEQ_image_transform_matrix_get(CTX_data_scene(C), strip, transform_mat.ptr()); + blender::float4x4 transform_mat = SEQ_image_transform_matrix_get(CTX_data_scene(C), strip); transform_mat = blender::math::invert(transform_mat); mouse_loc.x /= view_aspect; diff --git a/source/blender/editors/transform/transform_snap_sequencer.cc b/source/blender/editors/transform/transform_snap_sequencer.cc index 99d50d92cbd..c381084ddfe 100644 --- a/source/blender/editors/transform/transform_snap_sequencer.cc +++ b/source/blender/editors/transform/transform_snap_sequencer.cc @@ -170,8 +170,8 @@ static bool seq_snap_source_points_build_preview(const Scene *scene, snap_data->source_snap_points.reinitialize(point_count_source); int i = 0; for (Strip *strip : snap_sources) { - float seq_image_quad[4][2]; - SEQ_image_transform_final_quad_get(scene, strip, seq_image_quad); + const blender::Array seq_image_quad = SEQ_image_transform_final_quad_get( + scene, strip); for (int j = 0; j < 4; j++) { snap_data->source_snap_points[i][0] = seq_image_quad[j][0]; @@ -449,8 +449,8 @@ static bool seq_snap_target_points_build_preview(const Scene *scene, if (snap_mode & SEQ_SNAP_TO_STRIPS_PREVIEW) { for (Strip *strip : snap_targets) { - float strip_image_quad[4][2]; - SEQ_image_transform_final_quad_get(scene, strip, strip_image_quad); + const blender::Array strip_image_quad = SEQ_image_transform_final_quad_get( + scene, strip); for (int j = 0; j < 4; j++) { snap_data->target_snap_points[i][0] = strip_image_quad[j][0]; diff --git a/source/blender/sequencer/SEQ_transform.hh b/source/blender/sequencer/SEQ_transform.hh index a872e985ed0..0cbd03503d3 100644 --- a/source/blender/sequencer/SEQ_transform.hh +++ b/source/blender/sequencer/SEQ_transform.hh @@ -8,6 +8,8 @@ * \ingroup sequencer */ +#include "BLI_array.hh" +#include "BLI_math_matrix_types.hh" #include "BLI_span.hh" struct ListBase; @@ -92,22 +94,20 @@ void SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene, * \param scene: Scene in which strips are located * \param seq: Sequence to calculate transformed image quad * \param apply_rotation: Apply sequence rotation transform to the quad - * \param r_quad: array of 4 2D vectors + * \return array of 4 2D vectors */ -void SEQ_image_transform_quad_get(const Scene *scene, - const Strip *strip, - bool apply_rotation, - float r_quad[4][2]); +blender::Array SEQ_image_transform_quad_get(const Scene *scene, + const Strip *strip, + bool apply_rotation); /** * Get 4 corner points of strip image. Corner vectors are in viewport space. * * \param scene: Scene in which strips are located * \param seq: Sequence to calculate transformed image quad - * \param r_quad: array of 4 2D vectors + * \return array of 4 2D vectors */ -void SEQ_image_transform_final_quad_get(const Scene *scene, - const Strip *strip, - float r_quad[4][2]); +blender::Array SEQ_image_transform_final_quad_get(const Scene *scene, + const Strip *strip); void SEQ_image_preview_unit_to_px(const Scene *scene, const float co_src[2], float co_dst[2]); void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], float co_dst[2]); @@ -134,8 +134,5 @@ void SEQ_image_transform_bounding_box_from_collection(Scene *scene, * * \param scene: Scene in which strips are located * \param seq: Strip that is used to construct the matrix - * \param r_transform_matrix: Return value */ -void SEQ_image_transform_matrix_get(const Scene *scene, - const Strip *strip, - float r_transform_matrix[4][4]); +blender::float4x4 SEQ_image_transform_matrix_get(const Scene *scene, const Strip *strip); diff --git a/source/blender/sequencer/intern/render.cc b/source/blender/sequencer/intern/render.cc index 01893d148b7..264425a39a1 100644 --- a/source/blender/sequencer/intern/render.cc +++ b/source/blender/sequencer/intern/render.cc @@ -21,7 +21,7 @@ #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math_geom.h" -#include "BLI_math_rotation.h" +#include "BLI_math_matrix.hh" #include "BLI_path_utils.hh" #include "BLI_rect.h" #include "BLI_task.hh" @@ -297,13 +297,12 @@ StripScreenQuad get_strip_screen_quad(const SeqRenderData *context, const Strip const int y = context->recty; float2 offset{x * 0.5f, y * 0.5f}; - float quad[4][2]; - SEQ_image_transform_final_quad_get(scene, strip, quad); + Array quad = SEQ_image_transform_final_quad_get(scene, strip); const float scale = SEQ_rendersize_to_scale_factor(context->preview_render_size); - return StripScreenQuad{float2(quad[0]) * scale + offset, - float2(quad[1]) * scale + offset, - float2(quad[2]) * scale + offset, - float2(quad[3]) * scale + offset}; + return StripScreenQuad{quad[0] * scale + offset, + quad[1] * scale + offset, + quad[2] * scale + offset, + quad[3] * scale + offset}; } /* Is quad `a` fully contained (i.e. covered by) quad `b`? For that to happen, @@ -459,30 +458,30 @@ static bool seq_need_scale_to_render_size(const Strip *strip, bool is_proxy_imag return false; } -static void sequencer_image_crop_transform_matrix(const Strip *strip, - const ImBuf *in, - const ImBuf *out, - const float image_scale_factor, - const float preview_scale_factor, - float r_transform_matrix[4][4]) +static float4x4 sequencer_image_crop_transform_matrix(const Strip *strip, + const ImBuf *in, + const ImBuf *out, + const float image_scale_factor, + const float preview_scale_factor) { const StripTransform *transform = strip->data->transform; - const float scale_x = transform->scale_x * image_scale_factor; - const float scale_y = transform->scale_y * image_scale_factor; - const float image_center_offs_x = (out->x - in->x) / 2; - const float image_center_offs_y = (out->y - in->y) / 2; - const float translate_x = transform->xofs * preview_scale_factor + image_center_offs_x; - const float translate_y = transform->yofs * preview_scale_factor + image_center_offs_y; - const float pivot[3] = {in->x * transform->origin[0], in->y * transform->origin[1], 0.0f}; - float rotation_matrix[3][3]; - axis_angle_to_mat3_single(rotation_matrix, 'Z', transform->rotation); - loc_rot_size_to_mat4(r_transform_matrix, - float3{translate_x, translate_y, 0.0f}, - rotation_matrix, - float3{scale_x, scale_y, 1.0f}); - transform_pivot_set_m4(r_transform_matrix, pivot); - invert_m4(r_transform_matrix); + /* This value is intentionally kept as integer. Otherwise images with odd dimensions would + * be translated to center of canvas by non-integer value, which would cause it to be + * interpolated. Interpolation with 0 user defined translation is unwanted behavior. */ + const int3 image_center_offs((out->x - in->x) / 2, (out->y - in->y) / 2, 0); + + const float3 translation( + transform->xofs * preview_scale_factor, transform->yofs * preview_scale_factor, 0.0f); + const float3 rotation(0.0f, 0.0f, transform->rotation); + const float2 scale(transform->scale_x * image_scale_factor, + transform->scale_y * image_scale_factor); + const float3 pivot(in->x * transform->origin[0], in->y * transform->origin[1], 0.0f); + + const float4x4 matrix = math::from_loc_rot_scale( + translation + float3(image_center_offs), rotation, scale); + const float4x4 mat_pivot = math::from_origin_transform(matrix, pivot); + return math::invert(mat_pivot); } static void sequencer_image_crop_init(const Strip *strip, @@ -558,9 +557,8 @@ static void sequencer_preprocess_transform_crop( const bool do_scale_to_render_size = seq_need_scale_to_render_size(strip, is_proxy_image); const float image_scale_factor = do_scale_to_render_size ? 1.0f : preview_scale_factor; - float transform_matrix[4][4]; - sequencer_image_crop_transform_matrix( - strip, in, out, image_scale_factor, preview_scale_factor, transform_matrix); + float4x4 matrix = sequencer_image_crop_transform_matrix( + strip, in, out, image_scale_factor, preview_scale_factor); /* Proxy image is smaller, so crop values must be corrected by proxy scale factor. * Proxy scale factor always matches preview_scale_factor. */ @@ -591,7 +589,12 @@ static void sequencer_preprocess_transform_crop( break; } - IMB_transform(in, out, IMB_TRANSFORM_MODE_CROP_SRC, filter, transform_matrix, &source_crop); + IMB_transform(in, + out, + IMB_TRANSFORM_MODE_CROP_SRC, + filter, + (float(*)[4])(matrix.base_ptr()), + &source_crop); if (is_strip_covering_screen(context, strip)) { out->planes = in->planes; diff --git a/source/blender/sequencer/intern/strip_transform.cc b/source/blender/sequencer/intern/strip_transform.cc index 1c153cd9fe2..725851aedf3 100644 --- a/source/blender/sequencer/intern/strip_transform.cc +++ b/source/blender/sequencer/intern/strip_transform.cc @@ -12,8 +12,7 @@ #include "DNA_sequence_types.h" #include "BLI_listbase.h" -#include "BLI_math_matrix.h" -#include "BLI_math_rotation.h" +#include "BLI_math_matrix.hh" #include "BLI_math_vector.h" #include "BLI_math_vector_types.hh" @@ -30,6 +29,8 @@ #include "sequencer.hh" #include "strip_time.hh" +using namespace blender; + bool SEQ_transform_single_image_check(const Strip *strip) { return (strip->flag & SEQ_SINGLE_FRAME_CONTENT) != 0; @@ -603,93 +604,79 @@ void SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene, mul_v2_v2(r_origin, viewport_pixel_aspect); } -void SEQ_image_transform_matrix_get(const Scene *scene, - const Strip *strip, - float r_transform_matrix[4][4]) +static float4x4 seq_image_transform_matrix_get_ex(const Scene *scene, + const Strip *strip, + bool apply_rotation = true) { - float image_size[2] = {float(scene->r.xsch), float(scene->r.ysch)}; + float3 image_size(float(scene->r.xsch), float(scene->r.ysch), 0.0f); if (ELEM(strip->type, STRIP_TYPE_MOVIE, STRIP_TYPE_IMAGE)) { - image_size[0] = strip->data->stripdata->orig_width; - image_size[1] = strip->data->stripdata->orig_height; + image_size.x = strip->data->stripdata->orig_width; + image_size.y = strip->data->stripdata->orig_height; } - StripTransform *transform = strip->data->transform; - float rotation_matrix[3][3]; - axis_angle_to_mat3_single(rotation_matrix, 'Z', transform->rotation); - loc_rot_size_to_mat4(r_transform_matrix, - blender::float3{transform->xofs, transform->yofs, 0.0f}, - rotation_matrix, - blender::float3{transform->scale_x, transform->scale_y, 1.0f}); - const float origin[2] = {image_size[0] * transform->origin[0], - image_size[1] * transform->origin[1]}; - const float pivot[3] = {origin[0] - (image_size[0] / 2), origin[1] - (image_size[1] / 2), 0.0f}; - transform_pivot_set_m4(r_transform_matrix, pivot); + const StripTransform *transform = strip->data->transform; + const float3 origin( + image_size.x * transform->origin[0], image_size[1] * transform->origin[1], 0.0f); + const float3 translation(transform->xofs, transform->yofs, 0.0f); + const float3 rotation(0.0f, 0.0f, apply_rotation ? transform->rotation : 0.0f); + const float2 scale(transform->scale_x, transform->scale_y); + const float3 pivot = origin - (image_size / 2); + + const float4x4 matrix = math::from_loc_rot_scale(translation, rotation, scale); + return math::from_origin_transform(matrix, pivot); } -static void strip_image_transform_quad_get_ex(const Scene *scene, - const Strip *strip, - bool apply_rotation, - float r_quad[4][2]) +float4x4 SEQ_image_transform_matrix_get(const Scene *scene, const Strip *strip) { - StripTransform *transform = strip->data->transform; - const StripCrop *crop = strip->data->crop; + return seq_image_transform_matrix_get_ex(scene, strip); +} - float image_size[2] = {float(scene->r.xsch), float(scene->r.ysch)}; +static Array strip_image_transform_quad_get_ex(const Scene *scene, + const Strip *strip, + bool apply_rotation) +{ + + float3 image_size(float(scene->r.xsch), float(scene->r.ysch), 0.0f); if (ELEM(strip->type, STRIP_TYPE_MOVIE, STRIP_TYPE_IMAGE)) { - image_size[0] = strip->data->stripdata->orig_width; - image_size[1] = strip->data->stripdata->orig_height; + image_size.x = strip->data->stripdata->orig_width; + image_size.y = strip->data->stripdata->orig_height; } - float transform_matrix[4][4]; - float rotation_matrix[3][3]; - axis_angle_to_mat3_single(rotation_matrix, 'Z', apply_rotation ? transform->rotation : 0.0f); - loc_rot_size_to_mat4(transform_matrix, - blender::float3{transform->xofs, transform->yofs, 0.0f}, - rotation_matrix, - blender::float3{transform->scale_x, transform->scale_y, 1.0f}); - const float origin[2] = {image_size[0] * transform->origin[0], - image_size[1] * transform->origin[1]}; - const float pivot[3] = {origin[0] - (image_size[0] / 2), origin[1] - (image_size[1] / 2), 0.0f}; - transform_pivot_set_m4(transform_matrix, pivot); + const StripCrop *crop = strip->data->crop; + float3 quad[4]{ + {(image_size[0] / 2) - crop->right, (image_size[1] / 2) - crop->top, 0.0f}, + {(image_size[0] / 2) - crop->right, (-image_size[1] / 2) + crop->bottom, 0.0f}, + {(-image_size[0] / 2) + crop->left, (-image_size[1] / 2) + crop->bottom, 0.0f}, + {(-image_size[0] / 2) + crop->left, (image_size[1] / 2) - crop->top, 0.0f}, + }; - float quad_temp[4][3]; - for (int i = 0; i < 4; i++) { - zero_v3(quad_temp[i]); - } - - quad_temp[0][0] = (image_size[0] / 2) - crop->right; - quad_temp[0][1] = (image_size[1] / 2) - crop->top; - quad_temp[1][0] = (image_size[0] / 2) - crop->right; - quad_temp[1][1] = (-image_size[1] / 2) + crop->bottom; - quad_temp[2][0] = (-image_size[0] / 2) + crop->left; - quad_temp[2][1] = (-image_size[1] / 2) + crop->bottom; - quad_temp[3][0] = (-image_size[0] / 2) + crop->left; - quad_temp[3][1] = (image_size[1] / 2) - crop->top; - - float mirror[2]; + const float3 viewport_pixel_aspect(scene->r.xasp / scene->r.yasp, 1.0f, 1.0f); + const float4x4 matrix = seq_image_transform_matrix_get_ex(scene, strip, apply_rotation); + float3 mirror; SEQ_image_transform_mirror_factor_get(strip, mirror); - const float viewport_pixel_aspect[2] = {scene->r.xasp / scene->r.yasp, 1.0f}; + Array quad_transformed; + quad_transformed.reinitialize(4); for (int i = 0; i < 4; i++) { - mul_m4_v3(transform_matrix, quad_temp[i]); - mul_v2_v2(quad_temp[i], mirror); - mul_v2_v2(quad_temp[i], viewport_pixel_aspect); - copy_v2_v2(r_quad[i], quad_temp[i]); + float3 point = math::transform_point(matrix, quad[i]); + point *= mirror; + point *= viewport_pixel_aspect; + copy_v2_v2(quad_transformed[i], point); } + return quad_transformed; } -void SEQ_image_transform_quad_get(const Scene *scene, - const Strip *strip, - bool apply_rotation, - float r_quad[4][2]) +Array SEQ_image_transform_quad_get(const Scene *scene, + const Strip *strip, + bool apply_rotation) { - strip_image_transform_quad_get_ex(scene, strip, apply_rotation, r_quad); + return strip_image_transform_quad_get_ex(scene, strip, apply_rotation); } -void SEQ_image_transform_final_quad_get(const Scene *scene, const Strip *strip, float r_quad[4][2]) +Array SEQ_image_transform_final_quad_get(const Scene *scene, const Strip *strip) { - strip_image_transform_quad_get_ex(scene, strip, true, r_quad); + return strip_image_transform_quad_get_ex(scene, strip, true); } void SEQ_image_preview_unit_to_px(const Scene *scene, const float co_src[2], float co_dst[2]) @@ -712,8 +699,7 @@ void SEQ_image_transform_bounding_box_from_collection(Scene *scene, { INIT_MINMAX2(r_min, r_max); for (Strip *strip : strips) { - float quad[4][2]; - SEQ_image_transform_quad_get(scene, strip, apply_rotation, quad); + Array quad = SEQ_image_transform_quad_get(scene, strip, apply_rotation); for (int i = 0; i < 4; i++) { minmax_v2v2_v2(r_min, r_max, quad[i]); }