fixed matrix math order

This commit is contained in:
Synthasmagoria 2026-08-30 00:24:02 +02:00
commit 9b550856fb
5 changed files with 125 additions and 60 deletions

BIN
default

Binary file not shown.

View file

@ -22,12 +22,12 @@ rectangle_corners_from_rect :: proc "contextless" (rect: rect2) -> RectangleCorn
} }
} }
rectangle_corners_transform_mat3 :: proc "contextless" (corners: RectangleCorners, transform: mat3) -> RectangleCorners { rectangle_corners_transform_mat3 :: proc "contextless" (transform: mat3, corners: RectangleCorners) -> RectangleCorners {
return { return {
(v3{**corners.tl, 1.0} * transform).xy, matrix3_transform_v2(transform, corners.tl),
(v3{**corners.tr, 1.0} * transform).xy, matrix3_transform_v2(transform, corners.tr),
(v3{**corners.br, 1.0} * transform).xy, matrix3_transform_v2(transform, corners.br),
(v3{**corners.bl, 1.0} * transform).xy, matrix3_transform_v2(transform, corners.bl),
} }
} }
@ -35,8 +35,8 @@ rectangle_corners_lerp :: proc "contextless" (a, b: RectangleCorners, t: f32) ->
return { return {
linalg.lerp(a.tl, b.tl, t), linalg.lerp(a.tl, b.tl, t),
linalg.lerp(a.tr, b.tr, t), linalg.lerp(a.tr, b.tr, t),
linalg.lerp(a.bl, b.bl, t),
linalg.lerp(a.br, b.br, t), linalg.lerp(a.br, b.br, t),
linalg.lerp(a.bl, b.bl, t),
} }
} }
@ -101,9 +101,12 @@ rectangle_corners_transform_mat2 :: proc "contextless" (corners: RectangleCorner
} }
draw_animation_rectangle_corners :: proc(corners: RectangleCorners, color: rl.Color) { draw_animation_rectangle_corners :: proc(corners: RectangleCorners, color: rl.Color) {
rect := rect_from_corners(corners.tl, corners.tr, corners.br, corners.bl) rl.DrawTriangle(corners.tl, corners.bl, corners.br, {**color.rgb, color.a >> 1})
rl.DrawRectangleRec(rect, {**color.rgb, color.a >> 1}) rl.DrawTriangle(corners.br, corners.tr, corners.tl, {**color.rgb, color.a >> 1})
rl.DrawRectangleLinesEx(rect, 2, color) rl.DrawLineV(corners.tl, corners.tr, color)
rl.DrawLineV(corners.tr, corners.br, color)
rl.DrawLineV(corners.br, corners.bl, color)
rl.DrawLineV(corners.bl, corners.tl, color)
} }
/* /*
@ -160,34 +163,88 @@ animation_get_eased_progress :: proc(animation: Animation) -> f32 {
return math.floor(animation.matrix_index) + ease.ease(animation.ease, fract(animation.matrix_index)) return math.floor(animation.matrix_index) + ease.ease(animation.ease, fract(animation.matrix_index))
} }
rectangle_corners_draw :: proc(corners: RectangleCorners, color: rl.Color) {
rl.DrawLineV(corners.tl, corners.tr, rl.RED)
rl.DrawLineV(corners.tr, corners.br, rl.YELLOW)
rl.DrawLineV(corners.br, corners.bl, rl.GREEN)
rl.DrawLineV(corners.bl, corners.tl, rl.BLUE)
}
animation_draw :: proc(animation: Animation, global_transform: mat3) { animation_draw :: proc(animation: Animation, global_transform: mat3) {
switch animation.type { switch animation.type {
case .Rectangle: case .Rectangle:
shape := animation.shapes.rectangle shape := animation.shapes.rectangle
draw_animation_rectangle_corners(rectangle_corners_transform_mat3(global_transform, shape), ANIMATION_COLOR_ORIGIN)
transform := linalg.identity(mat3) transform := linalg.identity(mat3)
color_origin := cast([4]f32)(ANIMATION_COLOR_ORIGIN) matrices := slice.reinterpret([]mat3, animation.matrices[:animation.matrix_count * 9])
color_end := cast([4]f32)(ANIMATION_COLOR_END) for mat in matrices {
draw_animation_rectangle_corners(rectangle_corners_transform_mat3(shape, global_transform), ANIMATION_COLOR_ORIGIN) transform *= mat
shape_next := rectangle_corners_transform_mat3(transform, shape)
matrices := slice.reinterpret([]mat3, animation.matrices) shape_next_world := rectangle_corners_transform_mat3(global_transform, shape_next)
for i in 0..<animation.matrix_count { draw_animation_rectangle_corners(shape_next_world, ANIMATION_COLOR_ORIGIN)
animation_progress := f32(i + 1) / f32(animation.matrix_count) }
previous := rectangle_corners_transform_mat3(shape, transform)
transform *= matrices[i]
next := rectangle_corners_transform_mat3(shape, transform)
color_next := linalg.lerp(color_origin, color_end, animation_progress)
draw_animation_rectangle_corners(rectangle_corners_transform_mat3(next, global_transform), cast(rl.Color)color_next)
if f32(i) == math.floor(animation.matrix_index) {
progress := ease.ease(animation.ease, fract(animation.matrix_index))
color_previous := linalg.lerp(color_origin, color_end, animation.matrix_index / f32(animation.matrix_count))
color := linalg.lerp(color_previous, color_next, progress)
animated_corners := rectangle_corners_lerp(previous, next, progress)
animated_corners_world := rectangle_corners_transform_mat3(animated_corners, global_transform)
draw_animation_rectangle_corners(animated_corners_world, cast(rl.Color)color)
}
// shape := animation.shapes.rectangle
// transform := linalg.identity(mat3)
// color_origin := cast([4]f32)(ANIMATION_COLOR_ORIGIN)
// color_end := cast([4]f32)(ANIMATION_COLOR_END)
// draw_animation_rectangle_corners(rectangle_corners_transform_mat3(shape, global_transform), ANIMATION_COLOR_ORIGIN)
// matrices := slice.reinterpret([]mat3, animation.matrices)
// for i in 0..<animation.matrix_count {
// animation_progress := f32(i + 1) / f32(animation.matrix_count)
// previous := rectangle_corners_transform_mat3(shape, transform)
// transform *= matrices[i]
// next := rectangle_corners_transform_mat3(shape, transform)
// color_next := linalg.lerp(color_origin, color_end, animation_progress)
// draw_animation_rectangle_corners(rectangle_corners_transform_mat3(next, global_transform), cast(rl.Color)color_next)
// if f32(i) == math.floor(animation.matrix_index) {
// progress := ease.ease(animation.ease, fract(animation.matrix_index))
// color_previous := linalg.lerp(color_origin, color_end, animation.matrix_index / f32(animation.matrix_count))
// color := linalg.lerp(color_previous, color_next, progress)
// animated_corners := rectangle_corners_lerp(previous, next, progress)
// animated_corners_world := rectangle_corners_transform_mat3(animated_corners, global_transform)
// draw_animation_rectangle_corners(animated_corners_world, cast(rl.Color)color)
// }
} }
}
} }
animation_get_center :: proc(animation: Animation) -> v2 { animation_get_center :: proc(animation: Animation) -> v2 {

View file

@ -35,13 +35,7 @@ grid_get_line_separation :: proc(zoom: v2, min_line_distance: v2) -> v2 {
grid_world_to_grid_matrix :: proc(zoom, offset: v2) -> mat3 { grid_world_to_grid_matrix :: proc(zoom, offset: v2) -> mat3 {
zoom_amount := grid_get_zoom(zoom) zoom_amount := grid_get_zoom(zoom)
return ( return matrix3_translate2(offset) * linalg.matrix3_scale(v3{**zoom_amount, 1.0})
mat3 {
1, 0, 0,
0, 1, 0,
offset.x, offset.y, 1,
} *
linalg.matrix3_scale(v3{**zoom_amount, 1.0}))
} }
draw_grid :: proc(grid: Grid, area, text_draw, text_clip: rect2) { draw_grid :: proc(grid: Grid, area, text_draw, text_clip: rect2) {
@ -53,9 +47,9 @@ draw_grid :: proc(grid: Grid, area, text_draw, text_clip: rect2) {
grid_color := rl.Color{64, 64, 64, 255} grid_color := rl.Color{64, 64, 64, 255}
sep := grid_get_line_separation(grid.zoom, grid.cell_size_px) sep := grid_get_line_separation(grid.zoom, grid.cell_size_px)
tl := (v3{**position, 1.0} * world_to_grid_matrix).xy tl := matrix3_transform_v2(world_to_grid_matrix, position)
tl = linalg.floor(tl / sep) * sep tl = linalg.floor(tl / sep) * sep
br := (v3{**grid_world_br, 1.0} * world_to_grid_matrix).xy br := matrix3_transform_v2(world_to_grid_matrix, grid_world_br)
for x: f32 = tl.x; x < br.x; x += sep.x { for x: f32 = tl.x; x < br.x; x += sep.x {
world_position_x := (v3{x, 0.0, 1.0} * grid_to_world_matrix).x world_position_x := (v3{x, 0.0, 1.0} * grid_to_world_matrix).x

View file

@ -545,10 +545,10 @@ program_update :: proc() {
for draggable in program.mouse_draggables { for draggable in program.mouse_draggables {
switch draggable in draggable { switch draggable in draggable {
case MouseDraggable_Point: case MouseDraggable_Point:
position_world := (v3{**draggable.ref^, 1.0} * grid_to_world_matrix).xy position_world := matrix3_transform_v2(grid_to_world_matrix, draggable.ref^)
rl.DrawCircleV(position_world, program.mouse_draggable_radius, ANIMATION_COLOR_ORIGIN) rl.DrawCircleV(position_world, program.mouse_draggable_radius, ANIMATION_COLOR_ORIGIN)
case MouseDraggable_RectangleCornerData: case MouseDraggable_RectangleCornerData:
position_world := (v3{**draggable.corner_ref^, 1.0} * grid_to_world_matrix).xy position_world := matrix3_transform_v2(grid_to_world_matrix, draggable.corner_ref^)
rl.DrawCircleV(position_world, program.mouse_draggable_radius, ANIMATION_COLOR_ORIGIN) rl.DrawCircleV(position_world, program.mouse_draggable_radius, ANIMATION_COLOR_ORIGIN)
case MouseDraggable_RectangleData: case MouseDraggable_RectangleData:
} }
@ -608,17 +608,31 @@ program_add_rotation_matrix :: proc(angle: f32) {
case .Degrees: radians = linalg.RAD_PER_DEG * angle case .Degrees: radians = linalg.RAD_PER_DEG * angle
case .Radians: radians = angle case .Radians: radians = angle
} }
rotmat := linalg.matrix2_rotate_f32(angle)
fmt.bprint(value_strings[0][:], rotmat[0, 0]) a := linalg.cos(radians)
values[0] = rotmat[0, 0] b := linalg.sin(radians)
fmt.bprint(value_strings[1][:], rotmat[0, 1]) fmt.bprint(value_strings[0][:], a)
values[1] = rotmat[0, 1] values[0] = a
fmt.bprint(value_strings[3][:], rotmat[1, 0]) fmt.bprint(value_strings[1][:], -b)
values[3] = rotmat[1, 0] values[1] = b
fmt.bprint(value_strings[4][:], rotmat[1, 1]) fmt.bprint(value_strings[3][:], b)
values[4] = rotmat[1, 1] values[3] = a
fmt.bprint(value_strings[4][:], a)
values[4] = a
fmt.bprint(value_strings[8][:], 1) fmt.bprint(value_strings[8][:], 1)
values[8] = 1.0 values[8] = 1.0
// rotmat := linalg.matrix2_rotate_f32(angle)
// fmt.bprint(value_strings[0][:], rotmat[0, 0])
// values[0] = rotmat[0, 0]
// fmt.bprint(value_strings[1][:], rotmat[0, 1])
// values[1] = rotmat[0, 1]
// fmt.bprint(value_strings[1][:], rotmat[1, 0])
// values[3] = rotmat[1, 0]
// fmt.bprint(value_strings[4][:], rotmat[1, 1])
// values[4] = rotmat[1, 1]
// fmt.bprint(value_strings[8][:], 1)
// values[8] = 1.0
} }
program_build_dialog_ui :: proc(ctx: ^ui.Context, dialog_type: ProgramDialogType) -> []ui.Element { program_build_dialog_ui :: proc(ctx: ^ui.Context, dialog_type: ProgramDialogType) -> []ui.Element {
@ -847,21 +861,21 @@ program_handle_mouse :: proc(mouse_state: MouseState, top_bar_container, matrix_
for draggable in program.mouse_draggables { for draggable in program.mouse_draggables {
switch draggable in draggable { switch draggable in draggable {
case MouseDraggable_Point: case MouseDraggable_Point:
circle_position := (v3{**draggable.ref^, 1.0} * grid_to_world_matrix).xy circle_position := matrix3_transform_v2(grid_to_world_matrix, draggable.ref^)
if linalg.distance(mouse, circle_position) <= program.mouse_draggable_radius { if linalg.distance(mouse, circle_position) <= program.mouse_draggable_radius {
program.mouse_current_draggable = draggable program.mouse_current_draggable = draggable
mouse_state = .DraggingDraggable mouse_state = .DraggingDraggable
break state_label break state_label
} }
case MouseDraggable_RectangleCornerData: case MouseDraggable_RectangleCornerData:
circle_position := (v3{**draggable.corner_ref^, 1.0} * grid_to_world_matrix).xy circle_position := matrix3_transform_v2(grid_to_world_matrix, draggable.corner_ref^)
if linalg.distance(mouse, circle_position) <= program.mouse_draggable_radius { if linalg.distance(mouse, circle_position) <= program.mouse_draggable_radius {
program.mouse_current_draggable = draggable program.mouse_current_draggable = draggable
mouse_state = .DraggingDraggable mouse_state = .DraggingDraggable
break state_label break state_label
} }
case MouseDraggable_RectangleData: case MouseDraggable_RectangleData:
corners_world := rectangle_corners_transform_mat3(draggable.corners^, grid_to_world_matrix) corners_world := rectangle_corners_transform_mat3(grid_to_world_matrix, draggable.corners^)
rect := rect_from(corners_world.tl, corners_world.tr, corners_world.br, corners_world.bl) rect := rect_from(corners_world.tl, corners_world.tr, corners_world.br, corners_world.bl)
if rect_has_point(rect, mouse) { if rect_has_point(rect, mouse) {
program.mouse_current_draggable = draggable program.mouse_current_draggable = draggable
@ -884,9 +898,9 @@ program_handle_mouse :: proc(mouse_state: MouseState, top_bar_container, matrix_
draggable := program.mouse_current_draggable draggable := program.mouse_current_draggable
switch draggable in draggable { switch draggable in draggable {
case MouseDraggable_Point: case MouseDraggable_Point:
draggable.ref^ = (v3{**mouse, 1.0} * world_to_grid_matrix).xy draggable.ref^ = matrix3_transform_v2(world_to_grid_matrix, mouse)
case MouseDraggable_RectangleCornerData: case MouseDraggable_RectangleCornerData:
position := (v3{**mouse, 1.0} * world_to_grid_matrix).xy position := matrix3_transform_v2(world_to_grid_matrix, mouse)
corners := rectangle_corners_move_corner(draggable.corners_ref^, position, draggable.corner) corners := rectangle_corners_move_corner(draggable.corners_ref^, position, draggable.corner)
draggable.corners_ref^ = corners draggable.corners_ref^ = corners
case MouseDraggable_RectangleData: case MouseDraggable_RectangleData:

View file

@ -289,13 +289,13 @@ rect_get_size :: proc {rect2_get_size, irect2_get_size}
/// ## LINEAR ALGEBRA ## /// /// ## LINEAR ALGEBRA ## ///
matrix3_translate2 :: proc "contextless" (translation: v2) -> mat3 { matrix3_translate2 :: proc "contextless" (translation: v2) -> mat3 {
return { return {
1.0, 0.0, translation.x, 1.0, 0.0, 0.0,
0.0, 1.0, translation.y, 0.0, 1.0, 0.0,
0.0, 0.0, 1.0, translation.x, translation.y, 1.0,
} }
} }
matrix3_transform_v2 :: proc(m: mat3, v: v2) -> v2 { matrix3_transform_v2 :: proc "contextless" (m: mat3, v: v2) -> v2 {
return (m * v3{**v, 1.0}).xy return (m * v3{**v, 1.0}).xy
} }