diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h index 393cc2e5fa2..e6904cc019a 100644 --- a/source/blender/blenlib/BLI_rect.h +++ b/source/blender/blenlib/BLI_rect.h @@ -63,6 +63,7 @@ void BLI_rctf_transform_pt_v(const rctf *dst, void BLI_rctf_transform_calc_m4_pivot_min_ex( const rctf *dst, const rctf *src, float matrix[4][4], uint x, uint y); void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, float matrix[4][4]); +void BLI_rctf_transform_calc_m3_pivot_min(const rctf *dst, const rctf *src, float matrix[3][3]); void BLI_rctf_translate(struct rctf *rect, float x, float y); void BLI_rcti_translate(struct rcti *rect, int x, int y); diff --git a/source/blender/blenlib/intern/rct.cc b/source/blender/blenlib/intern/rct.cc index 191a16e0cac..9551d129ad1 100644 --- a/source/blender/blenlib/intern/rct.cc +++ b/source/blender/blenlib/intern/rct.cc @@ -23,6 +23,7 @@ /* avoid including BLI_math */ static void unit_m4(float m[4][4]); +static void unit_m3(float m[3][3]); bool BLI_rcti_is_empty(const rcti *rect) { @@ -553,6 +554,16 @@ void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, floa BLI_rctf_transform_calc_m4_pivot_min_ex(dst, src, matrix, 0, 1); } +void BLI_rctf_transform_calc_m3_pivot_min(const rctf *dst, const rctf *src, float matrix[3][3]) +{ + unit_m3(matrix); + + matrix[0][0] = BLI_rctf_size_x(src) / BLI_rctf_size_x(dst); + matrix[1][1] = BLI_rctf_size_y(src) / BLI_rctf_size_y(dst); + matrix[2][0] = (src->xmin - dst->xmin) * matrix[1][1]; + matrix[2][1] = (src->ymin - dst->ymin) * matrix[0][0]; +} + void BLI_rcti_translate(rcti *rect, int x, int y) { rect->xmin += x; @@ -1128,3 +1139,11 @@ static void unit_m4(float m[4][4]) m[2][0] = m[2][1] = m[2][3] = 0.0f; m[3][0] = m[3][1] = m[3][2] = 0.0f; } + +static void unit_m3(float m[3][3]) +{ + m[0][0] = m[1][1] = m[2][2] = 1.0f; + m[0][1] = m[0][2] = 0.0f; + m[1][0] = m[1][2] = 0.0f; + m[2][0] = m[2][1] = 0.0f; +} diff --git a/source/blender/draw/engines/image/image_drawing_mode.cc b/source/blender/draw/engines/image/image_drawing_mode.cc index 26f1797d00f..053eab73b3a 100644 --- a/source/blender/draw/engines/image/image_drawing_mode.cc +++ b/source/blender/draw/engines/image/image_drawing_mode.cc @@ -291,7 +291,7 @@ void ScreenSpaceDrawingMode::do_full_update_texture_slot(const TextureInfo &text /* IMB_transform works in a non-consistent space. This should be documented or fixed!. * Construct a variant of the info_uv_to_texture that adds the texel space * transformation. */ - float4x4 uv_to_texel; + float3x3 uv_to_texel; rctf texture_area; rctf tile_area; @@ -302,7 +302,7 @@ void ScreenSpaceDrawingMode::do_full_update_texture_slot(const TextureInfo &text tile_buffer.x * (texture_info.clipping_uv_bounds.xmax - image_tile.get_tile_x_offset()), tile_buffer.y * (texture_info.clipping_uv_bounds.ymin - image_tile.get_tile_y_offset()), tile_buffer.y * (texture_info.clipping_uv_bounds.ymax - image_tile.get_tile_y_offset())); - BLI_rctf_transform_calc_m4_pivot_min(&tile_area, &texture_area, uv_to_texel.ptr()); + BLI_rctf_transform_calc_m3_pivot_min(&tile_area, &texture_area, uv_to_texel.ptr()); uv_to_texel = math::invert(uv_to_texel); rctf crop_rect; @@ -321,7 +321,7 @@ void ScreenSpaceDrawingMode::do_full_update_texture_slot(const TextureInfo &text &texture_buffer, transform_mode, IMB_FILTER_NEAREST, - uv_to_texel.ptr(), + uv_to_texel, crop_rect_ptr); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.cc b/source/blender/editors/space_sequencer/sequencer_edit.cc index 3f0df324034..701bf339c39 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.cc +++ b/source/blender/editors/space_sequencer/sequencer_edit.cc @@ -3418,7 +3418,8 @@ static int sequencer_set_2d_cursor_exec(bContext *C, wmOperator *op) float cursor_pixel[2]; RNA_float_get_array(op->ptr, "location", cursor_pixel); - SEQ_image_preview_unit_from_px(scene, cursor_pixel, sseq->cursor); + blender::float2 cursor_region = SEQ_image_preview_unit_from_px(scene, cursor_pixel); + copy_v2_v2(sseq->cursor, cursor_region); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SEQUENCER, nullptr); diff --git a/source/blender/editors/space_sequencer/sequencer_preview_draw.cc b/source/blender/editors/space_sequencer/sequencer_preview_draw.cc index 02a6f51c80d..4606da0262f 100644 --- a/source/blender/editors/space_sequencer/sequencer_preview_draw.cc +++ b/source/blender/editors/space_sequencer/sequencer_preview_draw.cc @@ -1069,8 +1069,8 @@ static void strip_draw_image_origin_and_outline(const bContext *C, return; } - float origin[2]; - SEQ_image_transform_origin_offset_pixelspace_get(CTX_data_scene(C), strip, origin); + const blender::float2 origin = SEQ_image_transform_origin_offset_pixelspace_get( + CTX_data_scene(C), strip); /* Origin. */ GPUVertFormat *format = immVertexFormat(); @@ -1146,14 +1146,14 @@ static void text_selection_draw(const bContext *C, const Strip *strip, uint pos) const float line_y = character_start.position.y + text->font_descender; - const blender::float3 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f, 0.0f}; + const blender::float2 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f}; const float view_aspect = scene->r.xasp / scene->r.yasp; - 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}, - {character_end.position.x + character_end.advance_x, line_y + text->line_height, 0.0f}, - {character_end.position.x + character_end.advance_x, line_y, 0.0f}, + blender::float3x3 transform_mat = SEQ_image_transform_matrix_get(scene, strip); + blender::float4x2 selection_quad{ + {character_start.position.x, line_y}, + {character_start.position.x, line_y + text->line_height}, + {character_end.position.x + character_end.advance_x, line_y + text->line_height}, + {character_end.position.x + character_end.advance_x, line_y}, }; immBegin(GPU_PRIM_TRIS, 6); @@ -1190,9 +1190,9 @@ static void text_edit_draw_cursor(const bContext *C, const Strip *strip, uint po const TextVarsRuntime *text = data->runtime; const Scene *scene = CTX_data_scene(C); - const blender::float3 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f, 0.0f}; + const blender::float2 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f}; const float view_aspect = scene->r.xasp / scene->r.yasp; - blender::float4x4 transform_mat = SEQ_image_transform_matrix_get(scene, strip); + blender::float3x3 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; @@ -1208,13 +1208,13 @@ static void text_edit_draw_cursor(const bContext *C, const Strip *strip, uint po cursor_coords.x, float(text_boundbox.xmin), float(text_boundbox.xmax)); cursor_coords = coords_region_view_align(UI_view2d_fromcontext(C), cursor_coords); - blender::float4x3 cursor_quad{ - {cursor_coords.x, cursor_coords.y, 0.0f}, - {cursor_coords.x, cursor_coords.y + text->line_height, 0.0f}, - {cursor_coords.x + cursor_width, cursor_coords.y + text->line_height, 0.0f}, - {cursor_coords.x + cursor_width, cursor_coords.y, 0.0f}, + blender::float4x2 cursor_quad{ + {cursor_coords.x, cursor_coords.y}, + {cursor_coords.x, cursor_coords.y + text->line_height}, + {cursor_coords.x + cursor_width, cursor_coords.y + text->line_height}, + {cursor_coords.x + cursor_width, cursor_coords.y}, }; - const blender::float3 descender_offs{0.0f, float(text->font_descender), 0.0f}; + const blender::float2 descender_offs{0.0f, float(text->font_descender)}; immBegin(GPU_PRIM_TRIS, 6); immUniformThemeColor(TH_SEQ_TEXT_CURSOR); @@ -1237,14 +1237,14 @@ static void text_edit_draw_box(const bContext *C, const Strip *strip, uint pos) const TextVarsRuntime *text = data->runtime; const Scene *scene = CTX_data_scene(C); - const blender::float3 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.0f, 0.0f}; + const blender::float2 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.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); - 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}, - {float(text->text_boundbox.xmax), float(text->text_boundbox.ymax), 0.0f}, - {float(text->text_boundbox.xmax), float(text->text_boundbox.ymin), 0.0f}, + blender::float3x3 transform_mat = SEQ_image_transform_matrix_get(CTX_data_scene(C), strip); + blender::float4x2 box_quad{ + {float(text->text_boundbox.xmin), float(text->text_boundbox.ymin)}, + {float(text->text_boundbox.xmin), float(text->text_boundbox.ymax)}, + {float(text->text_boundbox.xmax), float(text->text_boundbox.ymax)}, + {float(text->text_boundbox.xmax), float(text->text_boundbox.ymin)}, }; GPU_blend(GPU_BLEND_NONE); diff --git a/source/blender/editors/space_sequencer/sequencer_select.cc b/source/blender/editors/space_sequencer/sequencer_select.cc index 11e5423dfc2..ef39b070d44 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.cc +++ b/source/blender/editors/space_sequencer/sequencer_select.cc @@ -728,8 +728,7 @@ static Strip *strip_select_seq_from_preview( float center_dist_sq_test = 0.0f; if (center) { /* Detect overlapping center points (scaled by the zoom level). */ - float co[2]; - SEQ_image_transform_origin_offset_pixelspace_get(scene, strip, co); + blender::float2 co = SEQ_image_transform_origin_offset_pixelspace_get(scene, strip); sub_v2_v2(co, mouseco_view); mul_v2_v2(co, center_scale_px); center_dist_sq_test = len_squared_v2(co); diff --git a/source/blender/editors/space_sequencer/sequencer_text_edit.cc b/source/blender/editors/space_sequencer/sequencer_text_edit.cc index 0577dbe6e7d..299ff97c3e5 100644 --- a/source/blender/editors/space_sequencer/sequencer_text_edit.cc +++ b/source/blender/editors/space_sequencer/sequencer_text_edit.cc @@ -668,13 +668,13 @@ static void cursor_set_by_mouse_position(const bContext *C, const wmEvent *event int2 mval_region; WM_event_drag_start_mval(event, CTX_wm_region(C), mval_region); - float3 mouse_loc; + float2 mouse_loc; UI_view2d_region_to_view(v2d, mval_region.x, mval_region.y, &mouse_loc.x, &mouse_loc.y); /* 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 blender::float2 view_offs{-scene->r.xsch / 2.0f, -scene->r.ysch / 2.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); + blender::float3x3 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/space_sequencer/sequencer_view.cc b/source/blender/editors/space_sequencer/sequencer_view.cc index 35f64df0c1e..8625a34da2e 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.cc +++ b/source/blender/editors/space_sequencer/sequencer_view.cc @@ -6,6 +6,7 @@ * \ingroup spseq */ +#include "BLI_bounds_types.hh" #include "BLI_listbase.h" #include "BLI_utildefines.h" @@ -294,13 +295,13 @@ static void seq_view_collection_rect_preview(Scene *scene, blender::Span strips, rctf *rect) { - float min[2], max[2]; - SEQ_image_transform_bounding_box_from_collection(scene, strips, true, min, max); + const blender::Bounds box = SEQ_image_transform_bounding_box_from_collection( + scene, strips, true); - rect->xmin = min[0]; - rect->xmax = max[0]; - rect->ymin = min[1]; - rect->ymax = max[1]; + rect->xmin = box.min[0]; + rect->xmax = box.max[0]; + rect->ymin = box.min[1]; + rect->ymax = box.max[1]; float minsize = min_ff(BLI_rctf_size_x(rect), BLI_rctf_size_y(rect)); diff --git a/source/blender/editors/space_sequencer/space_sequencer.cc b/source/blender/editors/space_sequencer/space_sequencer.cc index 932bcd0a715..95e6951dcde 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.cc +++ b/source/blender/editors/space_sequencer/space_sequencer.cc @@ -877,9 +877,7 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region) GPU_depth_mask(false); GPU_depth_test(GPU_DEPTH_NONE); - float cursor_pixel[2]; - SEQ_image_preview_unit_to_px(scene, sseq->cursor, cursor_pixel); - + const blender::float2 cursor_pixel = SEQ_image_preview_unit_to_px(scene, sseq->cursor); DRW_draw_cursor_2d_ex(region, cursor_pixel); } diff --git a/source/blender/editors/transform/transform.cc b/source/blender/editors/transform/transform.cc index 226ffb3936c..13470881f22 100644 --- a/source/blender/editors/transform/transform.cc +++ b/source/blender/editors/transform/transform.cc @@ -125,7 +125,8 @@ void setTransformViewAspect(TransInfo *t, float r_aspect[3]) } else if (t->spacetype == SPACE_SEQ) { if (t->options & CTX_CURSOR) { - SEQ_image_preview_unit_to_px(t->scene, r_aspect, r_aspect); + const float2 aspect = SEQ_image_preview_unit_to_px(t->scene, r_aspect); + copy_v2_v2(r_aspect, aspect); } } else if (t->spacetype == SPACE_CLIP) { diff --git a/source/blender/editors/transform/transform_convert_sequencer_image.cc b/source/blender/editors/transform/transform_convert_sequencer_image.cc index 3178c5f7b55..29486524a98 100644 --- a/source/blender/editors/transform/transform_convert_sequencer_image.cc +++ b/source/blender/editors/transform/transform_convert_sequencer_image.cc @@ -46,8 +46,7 @@ static TransData *SeqToTransData(const Scene *scene, int vert_index) { const StripTransform *transform = strip->data->transform; - float origin[2]; - SEQ_image_transform_origin_offset_pixelspace_get(scene, strip, origin); + const blender::float2 origin = SEQ_image_transform_origin_offset_pixelspace_get(scene, strip); float vertex[2] = {origin[0], origin[1]}; /* Add control vertex, so rotation and scale can be calculated. @@ -220,8 +219,7 @@ static void recalcData_sequencer_image(TransInfo *t) TransDataSeq *tdseq = static_cast(td->extra); Strip *strip = tdseq->strip; StripTransform *transform = strip->data->transform; - float mirror[2]; - SEQ_image_transform_mirror_factor_get(strip, mirror); + const blender::float2 mirror = SEQ_image_transform_mirror_factor_get(strip); /* Calculate translation. */ float translation[2]; diff --git a/source/blender/editors/transform/transform_generics.cc b/source/blender/editors/transform/transform_generics.cc index fab0ad8cf49..8a9f7d81a39 100644 --- a/source/blender/editors/transform/transform_generics.cc +++ b/source/blender/editors/transform/transform_generics.cc @@ -957,7 +957,8 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2]) } if (t->spacetype == SPACE_SEQ) { SpaceSeq *sseq = (SpaceSeq *)t->area->spacedata.first; - SEQ_image_preview_unit_to_px(t->scene, sseq->cursor, cursor_local_buf); + const float2 cursor_pixel = SEQ_image_preview_unit_to_px(t->scene, sseq->cursor); + copy_v2_v2(cursor_local_buf, cursor_pixel); cursor = cursor_local_buf; } else if (t->spacetype == SPACE_CLIP) { diff --git a/source/blender/editors/transform/transform_gizmo_2d.cc b/source/blender/editors/transform/transform_gizmo_2d.cc index fa76119e105..f5c0385bf56 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.cc +++ b/source/blender/editors/transform/transform_gizmo_2d.cc @@ -255,8 +255,10 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min int selected_strips = strips.size(); if (selected_strips > 0) { has_select = true; - SEQ_image_transform_bounding_box_from_collection( - scene, strips, selected_strips != 1, r_min, r_max); + const blender::Bounds box = + SEQ_image_transform_bounding_box_from_collection(scene, strips, selected_strips != 1); + copy_v2_v2(r_min, box.min); + copy_v2_v2(r_max, box.max); } if (selected_strips > 1) { /* Don't draw the cage as transforming multiple strips isn't currently very useful as it @@ -270,7 +272,8 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min const int pivot_point = scene->toolsettings->sequencer_tool_settings->pivot_point; if (pivot_point == V3D_AROUND_CURSOR) { SpaceSeq *sseq = static_cast(area->spacedata.first); - SEQ_image_preview_unit_to_px(scene, sseq->cursor, r_center); + const blender::float2 cursor_pixel = SEQ_image_preview_unit_to_px(scene, sseq->cursor); + copy_v2_v2(r_center, cursor_pixel); } else { mid_v2_v2v2(r_center, r_min, r_max); @@ -332,8 +335,7 @@ static float gizmo2d_calc_rotation(const bContext *C) /* Only return the strip rotation if only one is selected. */ for (Strip *strip : strips) { StripTransform *transform = strip->data->transform; - float mirror[2]; - SEQ_image_transform_mirror_factor_get(strip, mirror); + const blender::float2 mirror = SEQ_image_transform_mirror_factor_get(strip); return transform->rotation * mirror[0] * mirror[1]; } } @@ -355,8 +357,8 @@ static bool seq_get_strip_pivot_median(const Scene *scene, float r_pivot[2]) if (has_select) { for (Strip *strip : strips) { - float origin[2]; - SEQ_image_transform_origin_offset_pixelspace_get(scene, strip, origin); + const blender::float2 origin = SEQ_image_transform_origin_offset_pixelspace_get(scene, + strip); add_v2_v2(r_pivot, origin); } mul_v2_fl(r_pivot, 1.0f / strips.size()); @@ -381,7 +383,8 @@ static bool gizmo2d_calc_transform_pivot(const bContext *C, float r_pivot[2]) const int pivot_point = scene->toolsettings->sequencer_tool_settings->pivot_point; if (pivot_point == V3D_AROUND_CURSOR) { - SEQ_image_preview_unit_to_px(scene, sseq->cursor, r_pivot); + const blender::float2 cursor_pixel = SEQ_image_preview_unit_to_px(scene, sseq->cursor); + copy_v2_v2(r_pivot, cursor_pixel); Editing *ed = SEQ_editing_get(scene); ListBase *seqbase = SEQ_active_seqbase_get(ed); diff --git a/source/blender/editors/transform/transform_snap_sequencer.cc b/source/blender/editors/transform/transform_snap_sequencer.cc index 802db00e184..a25e6d529ab 100644 --- a/source/blender/editors/transform/transform_snap_sequencer.cc +++ b/source/blender/editors/transform/transform_snap_sequencer.cc @@ -13,8 +13,8 @@ #include "BLI_listbase.h" #include "BLI_map.hh" #include "BLI_math_base.h" - #include "BLI_vector.hh" + #include "MEM_guardedalloc.h" #include "DNA_scene_types.h" @@ -143,8 +143,8 @@ static void points_build_sources_preview(const Scene *scene, } /* Add origins last */ - float image_origin[2]; - SEQ_image_transform_origin_offset_pixelspace_get(scene, strip, image_origin); + const blender::float2 image_origin = SEQ_image_transform_origin_offset_pixelspace_get(scene, + strip); snap_data->source_snap_points.append(image_origin); } } @@ -322,12 +322,12 @@ static void points_build_targets_preview(const Scene *scene, const Array strip_image_quad = SEQ_image_transform_final_quad_get(scene, strip); for (int j = 0; j < 4; j++) { - snap_data->target_snap_points.append(float2(strip_image_quad[j])); + snap_data->target_snap_points.append(strip_image_quad[j]); } - float image_origin[2]; - SEQ_image_transform_origin_offset_pixelspace_get(scene, strip, image_origin); - snap_data->target_snap_points.append(float2(image_origin)); + const blender::float2 image_origin = SEQ_image_transform_origin_offset_pixelspace_get(scene, + strip); + snap_data->target_snap_points.append(image_origin); } } } diff --git a/source/blender/imbuf/IMB_imbuf.hh b/source/blender/imbuf/IMB_imbuf.hh index 6d112bd7435..c1b80588cfa 100644 --- a/source/blender/imbuf/IMB_imbuf.hh +++ b/source/blender/imbuf/IMB_imbuf.hh @@ -42,6 +42,7 @@ #include "../gpu/GPU_texture.hh" +#include "BLI_math_matrix_types.hh" #include "BLI_utildefines.h" #include "IMB_imbuf_types.hh" @@ -625,7 +626,7 @@ void IMB_transform(const ImBuf *src, ImBuf *dst, eIMBTransformMode mode, eIMBInterpolationFilterMode filter, - const float transform_matrix[4][4], + const blender::float3x3 &transform_matrix, const rctf *src_crop); GPUTexture *IMB_create_gpu_texture(const char *name, diff --git a/source/blender/imbuf/intern/transform.cc b/source/blender/imbuf/intern/transform.cc index 683d9f151ef..3d44166cd34 100644 --- a/source/blender/imbuf/intern/transform.cc +++ b/source/blender/imbuf/intern/transform.cc @@ -12,6 +12,7 @@ #include "BLI_math_color.h" #include "BLI_math_interp.hh" #include "BLI_math_matrix.hh" +#include "BLI_math_matrix_types.hh" #include "BLI_math_vector.h" #include "BLI_rect.h" #include "BLI_task.hh" @@ -47,7 +48,7 @@ struct TransformContext { /* Cropping region in source image pixel space. */ rctf src_crop; - void init(const float4x4 &transform_matrix, const bool has_source_crop) + void init(const float3x3 &transform_matrix, const bool has_source_crop) { start_uv = transform_matrix.location().xy(); add_x = transform_matrix.x_axis().xy(); @@ -56,7 +57,7 @@ struct TransformContext { } private: - void init_destination_region(const float4x4 &transform_matrix, const bool has_source_crop) + void init_destination_region(const float3x3 &transform_matrix, const bool has_source_crop) { if (!has_source_crop) { dst_region_x_range = IndexRange(dst->x); @@ -68,14 +69,14 @@ struct TransformContext { const int2 margin(2); rcti rect; BLI_rcti_init_minmax(&rect); - float4x4 inverse = math::invert(transform_matrix); + float3x3 inverse = math::invert(transform_matrix); const int2 src_coords[4] = {int2(src_crop.xmin, src_crop.ymin), int2(src_crop.xmax, src_crop.ymin), int2(src_crop.xmax, src_crop.ymax), int2(src_crop.xmin, src_crop.ymax)}; for (int i = 0; i < 4; i++) { int2 src_co = src_coords[i]; - float3 dst_co = math::transform_point(inverse, float3(src_co.x, src_co.y, 0.0f)); + float2 dst_co = math::transform_point(inverse, float2(src_co)); src_corners[i] = float2(dst_co.x, dst_co.y); BLI_rcti_do_minmax_v(&rect, int2(dst_co) + margin); @@ -467,7 +468,7 @@ void IMB_transform(const ImBuf *src, ImBuf *dst, const eIMBTransformMode mode, const eIMBInterpolationFilterMode filter, - const float transform_matrix[4][4], + const float3x3 &transform_matrix, const rctf *src_crop) { BLI_assert_msg(mode != IMB_TRANSFORM_MODE_CROP_SRC || src_crop != nullptr, @@ -483,7 +484,7 @@ void IMB_transform(const ImBuf *src, if (crop) { ctx.src_crop = *src_crop; } - ctx.init(blender::float4x4(transform_matrix), crop); + ctx.init(transform_matrix, crop); threading::parallel_for(ctx.dst_region_y_range, 8, [&](IndexRange y_range) { if (filter == IMB_FILTER_NEAREST) { diff --git a/source/blender/imbuf/tests/IMB_transform_test.cc b/source/blender/imbuf/tests/IMB_transform_test.cc index dde6c939228..c84d4057aeb 100644 --- a/source/blender/imbuf/tests/IMB_transform_test.cc +++ b/source/blender/imbuf/tests/IMB_transform_test.cc @@ -41,8 +41,8 @@ static ImBuf *transform_2x_smaller(eIMBInterpolationFilterMode filter) { ImBuf *src = create_6x2_test_image(); ImBuf *dst = IMB_allocImBuf(3, 1, 32, IB_rect); - float4x4 matrix = math::from_scale(float4(2.0f)); - IMB_transform(src, dst, IMB_TRANSFORM_MODE_REGULAR, filter, matrix.ptr(), nullptr); + float3x3 matrix = math::from_scale(float3(2.0f)); + IMB_transform(src, dst, IMB_TRANSFORM_MODE_REGULAR, filter, matrix, nullptr); IMB_freeImBuf(src); return dst; } @@ -51,8 +51,8 @@ static ImBuf *transform_fractional_larger(eIMBInterpolationFilterMode filter) { ImBuf *src = create_6x2_test_image(); ImBuf *dst = IMB_allocImBuf(9, 7, 32, IB_rect); - float4x4 matrix = math::from_scale(float4(6.0f / 9.0f, 2.0f / 7.0f, 1.0f, 1.0f)); - IMB_transform(src, dst, IMB_TRANSFORM_MODE_REGULAR, filter, matrix.ptr(), nullptr); + float3x3 matrix = math::from_scale(float3(6.0f / 9.0f, 2.0f / 7.0f, 1.0f)); + IMB_transform(src, dst, IMB_TRANSFORM_MODE_REGULAR, filter, matrix, nullptr); IMB_freeImBuf(src); return dst; } @@ -137,9 +137,9 @@ TEST(imbuf_transform, nearest_very_large_scale) /* Create 3841x1 image, and scale the input image so that the three middle * pixels cover almost all of it, except the rightmost pixel. */ ImBuf *res = IMB_allocImBuf(3841, 1, 32, IB_rect); - float4x4 matrix = math::from_loc_rot_scale( - float3(254, 0, 0), math::Quaternion::identity(), float3(3.0f / 3840.0f, 1, 1)); - IMB_transform(src, res, IMB_TRANSFORM_MODE_REGULAR, IMB_FILTER_NEAREST, matrix.ptr(), nullptr); + float3x3 matrix = math::from_loc_rot_scale( + float2(254, 0), 0.0f, float2(3.0f / 3840.0f, 1)); + IMB_transform(src, res, IMB_TRANSFORM_MODE_REGULAR, IMB_FILTER_NEAREST, matrix, nullptr); /* Check result: leftmost red, middle green, two rightmost pixels blue and black. * If the transform code internally does not have enough precision while stepping diff --git a/source/blender/imbuf/tests/performance/IMB_scaling_performance_test.cc b/source/blender/imbuf/tests/performance/IMB_scaling_performance_test.cc index 850187a3451..dbecde69fb6 100644 --- a/source/blender/imbuf/tests/performance/IMB_scaling_performance_test.cc +++ b/source/blender/imbuf/tests/performance/IMB_scaling_performance_test.cc @@ -53,9 +53,9 @@ static void imb_scale_via_transform(ImBuf *&src, eIMBInterpolationFilterMode filter) { ImBuf *dst = IMB_allocImBuf(width, height, src->planes, src->flags); - float4x4 matrix = math::from_scale( - float4(float(src->x) / dst->x, float(src->y) / dst->y, 1.0f, 1.0f)); - IMB_transform(src, dst, IMB_TRANSFORM_MODE_REGULAR, filter, matrix.ptr(), nullptr); + float3x3 matrix = math::from_scale( + float3(float(src->x) / dst->x, float(src->y) / dst->y, 1.0f)); + IMB_transform(src, dst, IMB_TRANSFORM_MODE_REGULAR, filter, matrix, nullptr); IMB_freeImBuf(src); src = dst; } diff --git a/source/blender/sequencer/SEQ_transform.hh b/source/blender/sequencer/SEQ_transform.hh index 0cbd03503d3..4206ee88324 100644 --- a/source/blender/sequencer/SEQ_transform.hh +++ b/source/blender/sequencer/SEQ_transform.hh @@ -9,6 +9,7 @@ */ #include "BLI_array.hh" +#include "BLI_bounds_types.hh" #include "BLI_math_matrix_types.hh" #include "BLI_span.hh" @@ -75,18 +76,16 @@ bool SEQ_transform_is_locked(ListBase *channels, const Strip *strip); /* Image transformation. */ -void SEQ_image_transform_mirror_factor_get(const Strip *strip, float r_mirror[2]); +blender::float2 SEQ_image_transform_mirror_factor_get(const Strip *strip); /** * Get strip transform origin offset from image center * NOTE: This function does not apply axis mirror. * * \param scene: Scene in which strips are located * \param seq: Sequence to calculate image transform origin - * \param r_origin: return value */ -void SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene, - const Strip *strip, - float r_origin[2]); +blender::float2 SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene, + const Strip *strip); /** * Get 4 corner points of strip image, optionally without rotation component applied. * Corner vectors are in viewport space. @@ -109,8 +108,8 @@ blender::Array SEQ_image_transform_quad_get(const Scene *scene, 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]); +blender::float2 SEQ_image_preview_unit_to_px(const Scene *scene, blender::float2 co_src); +blender::float2 SEQ_image_preview_unit_from_px(const Scene *scene, blender::float2 co_src); /** * Get viewport axis aligned bounding box from a collection of sequences. @@ -122,11 +121,8 @@ void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], f * \param r_min: Minimum x and y values * \param r_max: Maximum x and y values */ -void SEQ_image_transform_bounding_box_from_collection(Scene *scene, - blender::Span strips, - bool apply_rotation, - float r_min[2], - float r_max[2]); +blender::Bounds SEQ_image_transform_bounding_box_from_collection( + Scene *scene, blender::Span strips, bool apply_rotation); /** * Get strip image transformation matrix. Pivot point is set to correspond with viewport coordinate @@ -135,4 +131,4 @@ 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 */ -blender::float4x4 SEQ_image_transform_matrix_get(const Scene *scene, const Strip *strip); +blender::float3x3 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 da3fa79bd6d..9a47f14efb6 100644 --- a/source/blender/sequencer/intern/render.cc +++ b/source/blender/sequencer/intern/render.cc @@ -296,14 +296,14 @@ StripScreenQuad get_strip_screen_quad(const SeqRenderData *context, const Strip Scene *scene = context->scene; const int x = context->rectx; const int y = context->recty; - float2 offset{x * 0.5f, y * 0.5f}; + const float2 offset{x * 0.5f, y * 0.5f}; Array quad = SEQ_image_transform_final_quad_get(scene, strip); const float scale = SEQ_rendersize_to_scale_factor(context->preview_render_size); - return StripScreenQuad{quad[0] * scale + offset, - quad[1] * scale + offset, - quad[2] * scale + offset, - quad[3] * scale + offset}; + return StripScreenQuad{float2(quad[0] * scale + offset), + float2(quad[1] * scale + offset), + float2(quad[2] * scale + offset), + float2(quad[3] * scale + offset)}; } /* Is quad `a` fully contained (i.e. covered by) quad `b`? For that to happen, @@ -459,7 +459,7 @@ static bool seq_need_scale_to_render_size(const Strip *strip, bool is_proxy_imag return false; } -static float4x4 sequencer_image_crop_transform_matrix(const Strip *strip, +static float3x3 sequencer_image_crop_transform_matrix(const Strip *strip, const ImBuf *in, const ImBuf *out, const float image_scale_factor, @@ -472,16 +472,16 @@ static float4x4 sequencer_image_crop_transform_matrix(const Strip *strip, * 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 translation(transform->xofs * preview_scale_factor, + transform->yofs * preview_scale_factor); + const float rotation = 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 float2 pivot(in->x * transform->origin[0], in->y * transform->origin[1]); - 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); + const float3x3 matrix = math::from_loc_rot_scale( + translation + float2(image_center_offs), rotation, scale); + const float3x3 mat_pivot = math::from_origin_transform(matrix, pivot); return math::invert(mat_pivot); } @@ -558,7 +558,7 @@ 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; - float4x4 matrix = sequencer_image_crop_transform_matrix( + float3x3 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. @@ -590,8 +590,7 @@ static void sequencer_preprocess_transform_crop( break; } - IMB_transform( - in, out, IMB_TRANSFORM_MODE_CROP_SRC, filter, (float(*)[4])matrix.base_ptr(), &source_crop); + IMB_transform(in, out, IMB_TRANSFORM_MODE_CROP_SRC, filter, matrix, &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 725851aedf3..663c1b17267 100644 --- a/source/blender/sequencer/intern/strip_transform.cc +++ b/source/blender/sequencer/intern/strip_transform.cc @@ -8,12 +8,13 @@ * \ingroup bke */ +#include "BLI_bounds.hh" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" #include "BLI_listbase.h" +#include "BLI_math_base.h" #include "BLI_math_matrix.hh" -#include "BLI_math_vector.h" #include "BLI_math_vector_types.hh" #include "SEQ_animation.hh" @@ -565,68 +566,61 @@ bool SEQ_transform_is_locked(ListBase *channels, const Strip *strip) (SEQ_channel_is_locked(channel) && ((strip->flag & SEQ_IGNORE_CHANNEL_LOCK) == 0)); } -void SEQ_image_transform_mirror_factor_get(const Strip *strip, float r_mirror[2]) +float2 SEQ_image_transform_mirror_factor_get(const Strip *strip) { - r_mirror[0] = 1.0f; - r_mirror[1] = 1.0f; + float2 mirror(1.0f, 1.0f); if ((strip->flag & SEQ_FLIPX) != 0) { - r_mirror[0] = -1.0f; + mirror.x = -1.0f; } if ((strip->flag & SEQ_FLIPY) != 0) { - r_mirror[1] = -1.0f; + mirror.y = -1.0f; } + return mirror; } -void SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene, - const Strip *strip, - float r_origin[2]) +static float2 strip_raw_image_size_get(const Scene *scene, const Strip *strip) { - float image_size[2]; - const StripElem *strip_elem = strip->data->stripdata; - if (strip_elem == nullptr) { - image_size[0] = scene->r.xsch; - image_size[1] = scene->r.ysch; - } - else { - image_size[0] = strip_elem->orig_width; - image_size[1] = strip_elem->orig_height; + if (ELEM(strip->type, STRIP_TYPE_MOVIE, STRIP_TYPE_IMAGE)) { + const StripElem *selem = strip->data->stripdata; + return {float(selem->orig_width), float(selem->orig_height)}; } - const StripTransform *transform = strip->data->transform; - r_origin[0] = (image_size[0] * transform->origin[0]) - (image_size[0] * 0.5f) + transform->xofs; - r_origin[1] = (image_size[1] * transform->origin[1]) - (image_size[1] * 0.5f) + transform->yofs; - - const float viewport_pixel_aspect[2] = {scene->r.xasp / scene->r.yasp, 1.0f}; - float mirror[2]; - SEQ_image_transform_mirror_factor_get(strip, mirror); - mul_v2_v2(r_origin, mirror); - mul_v2_v2(r_origin, viewport_pixel_aspect); + return {float(scene->r.xsch), float(scene->r.ysch)}; } -static float4x4 seq_image_transform_matrix_get_ex(const Scene *scene, +float2 SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene, const Strip *strip) +{ + const float2 image_size = strip_raw_image_size_get(scene, strip); + const StripTransform *transform = strip->data->transform; + + const float2 origin( + (image_size[0] * transform->origin[0]) - (image_size[0] * 0.5f) + transform->xofs, + (image_size[1] * transform->origin[1]) - (image_size[1] * 0.5f) + transform->yofs); + + const float2 viewport_pixel_aspect(scene->r.xasp / scene->r.yasp, 1.0f); + const float2 mirror = SEQ_image_transform_mirror_factor_get(strip); + + return origin * mirror * viewport_pixel_aspect; +} + +static float3x3 seq_image_transform_matrix_get_ex(const Scene *scene, const Strip *strip, bool apply_rotation = true) { - 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.x = strip->data->stripdata->orig_width; - image_size.y = strip->data->stripdata->orig_height; - } - 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 image_size = strip_raw_image_size_get(scene, strip); + const float2 origin(image_size.x * transform->origin[0], image_size[1] * transform->origin[1]); + const float2 translation(transform->xofs, transform->yofs); + const float rotation = apply_rotation ? transform->rotation : 0.0f; const float2 scale(transform->scale_x, transform->scale_y); - const float3 pivot = origin - (image_size / 2); + const float2 pivot = origin - (image_size / 2); - const float4x4 matrix = math::from_loc_rot_scale(translation, rotation, scale); + const float3x3 matrix = math::from_loc_rot_scale(translation, rotation, scale); return math::from_origin_transform(matrix, pivot); } -float4x4 SEQ_image_transform_matrix_get(const Scene *scene, const Strip *strip) +float3x3 SEQ_image_transform_matrix_get(const Scene *scene, const Strip *strip) { return seq_image_transform_matrix_get_ex(scene, strip); } @@ -635,34 +629,26 @@ 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.x = strip->data->stripdata->orig_width; - image_size.y = strip->data->stripdata->orig_height; - } + const float2 image_size = strip_raw_image_size_get(scene, strip); 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}, + float2 quad[4]{ + {(image_size[0] / 2) - crop->right, (image_size[1] / 2) - crop->top}, + {(image_size[0] / 2) - crop->right, (-image_size[1] / 2) + crop->bottom}, + {(-image_size[0] / 2) + crop->left, (-image_size[1] / 2) + crop->bottom}, + {(-image_size[0] / 2) + crop->left, (image_size[1] / 2) - crop->top}, }; - 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 float3x3 matrix = seq_image_transform_matrix_get_ex(scene, strip, apply_rotation); + const float2 viewport_pixel_aspect(scene->r.xasp / scene->r.yasp, 1.0f); + const float2 mirror = SEQ_image_transform_mirror_factor_get(strip); Array quad_transformed; quad_transformed.reinitialize(4); for (int i = 0; i < 4; i++) { - float3 point = math::transform_point(matrix, quad[i]); - point *= mirror; - point *= viewport_pixel_aspect; - copy_v2_v2(quad_transformed[i], point); + const float2 point = math::transform_point(matrix, quad[i]); + quad_transformed[i] = point * mirror * viewport_pixel_aspect; } return quad_transformed; } @@ -679,29 +665,32 @@ Array SEQ_image_transform_final_quad_get(const Scene *scene, const Strip 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]) +float2 SEQ_image_preview_unit_to_px(const Scene *scene, const float2 co_src) { - co_dst[0] = co_src[0] * scene->r.xsch; - co_dst[1] = co_src[1] * scene->r.ysch; + return {co_src.x * scene->r.xsch, co_src.y * scene->r.ysch}; } -void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], float co_dst[2]) +float2 SEQ_image_preview_unit_from_px(const Scene *scene, const float2 co_src) { - co_dst[0] = co_src[0] / scene->r.xsch; - co_dst[1] = co_src[1] / scene->r.ysch; + return {co_src.x / scene->r.xsch, co_src.y / scene->r.ysch}; } -void SEQ_image_transform_bounding_box_from_collection(Scene *scene, - blender::Span strips, - bool apply_rotation, - float r_min[2], - float r_max[2]) +static Bounds negative_bounds() { - INIT_MINMAX2(r_min, r_max); + return {float2(std::numeric_limits::max()), float2(std::numeric_limits::lowest())}; +} + +Bounds SEQ_image_transform_bounding_box_from_collection(Scene *scene, + blender::Span strips, + bool apply_rotation) +{ + Bounds box = negative_bounds(); + for (Strip *strip : strips) { - 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]); - } + const Array quad = SEQ_image_transform_quad_get(scene, strip, apply_rotation); + const Bounds strip_box = *blender::bounds::min_max(quad.as_span()); + box = blender::bounds::merge(box, strip_box); } + + return box; }