Grid matrix math fix
This commit is contained in:
parent
9b550856fb
commit
c0d84bae43
4 changed files with 80 additions and 34 deletions
|
|
@ -24,10 +24,10 @@ rectangle_corners_from_rect :: proc "contextless" (rect: rect2) -> RectangleCorn
|
|||
|
||||
rectangle_corners_transform_mat3 :: proc "contextless" (transform: mat3, corners: RectangleCorners) -> RectangleCorners {
|
||||
return {
|
||||
matrix3_transform_v2(transform, corners.tl),
|
||||
matrix3_transform_v2(transform, corners.tr),
|
||||
matrix3_transform_v2(transform, corners.br),
|
||||
matrix3_transform_v2(transform, corners.bl),
|
||||
matrix3_transform_xy(transform, corners.tl),
|
||||
matrix3_transform_xy(transform, corners.tr),
|
||||
matrix3_transform_xy(transform, corners.br),
|
||||
matrix3_transform_xy(transform, corners.bl),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,37 +35,36 @@ grid_get_line_separation :: proc(zoom: v2, min_line_distance: v2) -> v2 {
|
|||
|
||||
grid_world_to_grid_matrix :: proc(zoom, offset: v2) -> mat3 {
|
||||
zoom_amount := grid_get_zoom(zoom)
|
||||
return matrix3_translate2(offset) * linalg.matrix3_scale(v3{**zoom_amount, 1.0})
|
||||
return matrix3_translate2(offset) * matrix3_scale2(zoom_amount)
|
||||
}
|
||||
|
||||
draw_grid :: proc(grid: Grid, area, text_draw, text_clip: rect2) {
|
||||
draw_grid :: proc(grid: Grid, area, text_draw, text_clip: rect2, color: rl.Color) {
|
||||
world_to_grid_matrix := grid_world_to_grid_matrix(grid.zoom, grid.offset)
|
||||
grid_to_world_matrix := linalg.inverse(world_to_grid_matrix)
|
||||
position := rect_get_tl(area)
|
||||
size := rect_get_size(area)
|
||||
grid_world_br := position + size
|
||||
grid_color := rl.Color{64, 64, 64, 255}
|
||||
|
||||
sep := grid_get_line_separation(grid.zoom, grid.cell_size_px)
|
||||
tl := matrix3_transform_v2(world_to_grid_matrix, position)
|
||||
tl := matrix3_transform_xy(world_to_grid_matrix, position)
|
||||
tl = linalg.floor(tl / sep) * sep
|
||||
br := matrix3_transform_v2(world_to_grid_matrix, grid_world_br)
|
||||
br := matrix3_transform_xy(world_to_grid_matrix, grid_world_br)
|
||||
|
||||
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 := (grid_to_world_matrix * v3{x, 0.0, 1.0}).x
|
||||
p1 := v2{world_position_x, position.y}
|
||||
p2 := v2{world_position_x, grid_world_br.y}
|
||||
rl.DrawLineV(p1, p2, grid_color)
|
||||
rl.DrawLineV(p1, p2, color)
|
||||
if p1.x >= text_clip.x && p1.x < text_clip.x + text_clip.width {
|
||||
draw_float_aligned(x, {world_position_x, text_draw.y}, program.font_style, .Middle, .Top, rl.GRAY)
|
||||
}
|
||||
}
|
||||
|
||||
for y: f32 = tl.y; y < br.y; y += sep.y {
|
||||
world_position_y := (v3{0.0, y, 1.0} * grid_to_world_matrix).y
|
||||
world_position_y := (grid_to_world_matrix * v3{0.0, y, 1.0}).y
|
||||
p1 := v2{position.x, world_position_y}
|
||||
p2 := v2{grid_world_br.x, world_position_y}
|
||||
rl.DrawLineV(p1, p2, grid_color)
|
||||
rl.DrawLineV(p1, p2, color)
|
||||
if p1.y >= text_clip.y && p1.y < text_clip.y + text_clip.height {
|
||||
draw_float_aligned(y, {text_draw.x, world_position_y}, program.font_style, .Left, .Center, rl.GRAY)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,32 @@
|
|||
package main
|
||||
|
||||
/*
|
||||
Rules of matrices:
|
||||
1) Order matters when multiplying with vectors
|
||||
- m * v = Column vector x matrix
|
||||
- v * m = Row vector x matrix
|
||||
|
||||
2) Odin matrices are column-major for math efficiency
|
||||
fmt.println(matrix[3, 3]f32 {
|
||||
a, -b, 0,
|
||||
b, a, 0,
|
||||
0, 0, 1,
|
||||
})
|
||||
>> [0.8660254, 0.5, 0, -0.5, 0.8660254, 0, 0, 0, 1]
|
||||
|
||||
Additionally this means that the first index of a matrix is the column.
|
||||
mat[<column>, <row>].
|
||||
If you had an array of 9 floats ([9]f32) and you accessed the first one
|
||||
It'd be the same as accessing the first colmun of a matrix.
|
||||
array[1] = mat[1, 0]
|
||||
|
||||
3) Matrix multiplication order matters
|
||||
// scale first then translate
|
||||
transformation_a := translation * scale
|
||||
// translate first then scale
|
||||
transformation_b := scale * translation
|
||||
*/
|
||||
|
||||
import rl "libraries/raylib"
|
||||
import ui "libraries/snths_ui"
|
||||
import "core:mem"
|
||||
|
|
@ -275,8 +302,10 @@ matrix_pool_get_mat3 :: proc() -> (value_strings: []InputFloatField, values: []f
|
|||
assert(program.matrix_count + 1 < matrix_pool_max(), "Max matrix count exceeded")
|
||||
value_strings = program.matrix_value_string_pool[program.matrix_count * 9 : program.matrix_count * 9 + 9]
|
||||
values = program.matrix_float_pool[program.matrix_count * 9 : program.matrix_count * 9 + 9]
|
||||
for &str in value_strings {
|
||||
str[0] = '0'
|
||||
for i in 0..<len(value_strings) {
|
||||
mem.set(raw_data(&value_strings[i]), 0, len(InputFloatField))
|
||||
value_strings[i][0] = '0'
|
||||
values[i] = 0.0
|
||||
}
|
||||
program.matrix_count += 1
|
||||
return value_strings, values
|
||||
|
|
@ -508,7 +537,7 @@ program_update :: proc() {
|
|||
matrix_container_br := rect_get_br(rect2(matrix_container.area))
|
||||
grid_text_clip := rect_from_area(v2{matrix_container_br.x, top_bar_container_br.y}, program_screen_size())
|
||||
grid_area := rect2{0.0, 0.0, **program_screen_size()}
|
||||
draw_grid(program.grid, grid_area, rect_grow(grid_text_clip, -4.0), rect_grow(grid_text_clip, -32.0))
|
||||
draw_grid(program.grid, grid_area, rect_grow(grid_text_clip, -4.0), rect_grow(grid_text_clip, -32.0), {255, 255, 255, 64})
|
||||
|
||||
{
|
||||
animation := &program.animation
|
||||
|
|
@ -545,10 +574,10 @@ program_update :: proc() {
|
|||
for draggable in program.mouse_draggables {
|
||||
switch draggable in draggable {
|
||||
case MouseDraggable_Point:
|
||||
position_world := matrix3_transform_v2(grid_to_world_matrix, draggable.ref^)
|
||||
position_world := matrix3_transform_xy(grid_to_world_matrix, draggable.ref^)
|
||||
rl.DrawCircleV(position_world, program.mouse_draggable_radius, ANIMATION_COLOR_ORIGIN)
|
||||
case MouseDraggable_RectangleCornerData:
|
||||
position_world := matrix3_transform_v2(grid_to_world_matrix, draggable.corner_ref^)
|
||||
position_world := matrix3_transform_xy(grid_to_world_matrix, draggable.corner_ref^)
|
||||
rl.DrawCircleV(position_world, program.mouse_draggable_radius, ANIMATION_COLOR_ORIGIN)
|
||||
case MouseDraggable_RectangleData:
|
||||
}
|
||||
|
|
@ -611,15 +640,15 @@ program_add_rotation_matrix :: proc(angle: f32) {
|
|||
|
||||
a := linalg.cos(radians)
|
||||
b := linalg.sin(radians)
|
||||
fmt.bprint(value_strings[0][:], a)
|
||||
fmt.bprintf(value_strings[0][:], "%.3f", a)
|
||||
values[0] = a
|
||||
fmt.bprint(value_strings[1][:], -b)
|
||||
values[1] = b
|
||||
fmt.bprint(value_strings[3][:], b)
|
||||
values[3] = a
|
||||
fmt.bprint(value_strings[4][:], a)
|
||||
fmt.bprintf(value_strings[1][:], "%.3f", -b)
|
||||
values[1] = -b
|
||||
fmt.bprintf(value_strings[3][:], "%.3f", b)
|
||||
values[3] = b
|
||||
fmt.bprintf(value_strings[4][:], "%.3f", a)
|
||||
values[4] = a
|
||||
fmt.bprint(value_strings[8][:], 1)
|
||||
fmt.bprint(value_strings[8][:], f32(1.0))
|
||||
values[8] = 1.0
|
||||
|
||||
// rotmat := linalg.matrix2_rotate_f32(angle)
|
||||
|
|
@ -861,14 +890,14 @@ program_handle_mouse :: proc(mouse_state: MouseState, top_bar_container, matrix_
|
|||
for draggable in program.mouse_draggables {
|
||||
switch draggable in draggable {
|
||||
case MouseDraggable_Point:
|
||||
circle_position := matrix3_transform_v2(grid_to_world_matrix, draggable.ref^)
|
||||
circle_position := matrix3_transform_xy(grid_to_world_matrix, draggable.ref^)
|
||||
if linalg.distance(mouse, circle_position) <= program.mouse_draggable_radius {
|
||||
program.mouse_current_draggable = draggable
|
||||
mouse_state = .DraggingDraggable
|
||||
break state_label
|
||||
}
|
||||
case MouseDraggable_RectangleCornerData:
|
||||
circle_position := matrix3_transform_v2(grid_to_world_matrix, draggable.corner_ref^)
|
||||
circle_position := matrix3_transform_xy(grid_to_world_matrix, draggable.corner_ref^)
|
||||
if linalg.distance(mouse, circle_position) <= program.mouse_draggable_radius {
|
||||
program.mouse_current_draggable = draggable
|
||||
mouse_state = .DraggingDraggable
|
||||
|
|
@ -898,9 +927,9 @@ program_handle_mouse :: proc(mouse_state: MouseState, top_bar_container, matrix_
|
|||
draggable := program.mouse_current_draggable
|
||||
switch draggable in draggable {
|
||||
case MouseDraggable_Point:
|
||||
draggable.ref^ = matrix3_transform_v2(world_to_grid_matrix, mouse)
|
||||
draggable.ref^ = matrix3_transform_xy(world_to_grid_matrix, mouse)
|
||||
case MouseDraggable_RectangleCornerData:
|
||||
position := matrix3_transform_v2(world_to_grid_matrix, mouse)
|
||||
position := matrix3_transform_xy(world_to_grid_matrix, mouse)
|
||||
corners := rectangle_corners_move_corner(draggable.corners_ref^, position, draggable.corner)
|
||||
draggable.corners_ref^ = corners
|
||||
case MouseDraggable_RectangleData:
|
||||
|
|
@ -908,7 +937,7 @@ program_handle_mouse :: proc(mouse_state: MouseState, top_bar_container, matrix_
|
|||
draggable.corners^ = rectangle_corners_add(draggable.corners^, mouse_delta_grid)
|
||||
}
|
||||
case .DraggingGrid:
|
||||
program.grid.offset -= rl.GetMouseDelta()
|
||||
program.grid.offset -= rl.GetMouseDelta() * grid_get_zoom(program.grid.zoom)
|
||||
if !rl.IsMouseButtonDown(.LEFT) {
|
||||
mouse_state = .Hover
|
||||
break state_label
|
||||
|
|
|
|||
|
|
@ -289,13 +289,31 @@ rect_get_size :: proc {rect2_get_size, irect2_get_size}
|
|||
/// ## LINEAR ALGEBRA ## ///
|
||||
matrix3_translate2 :: proc "contextless" (translation: v2) -> mat3 {
|
||||
return {
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
translation.x, translation.y, 1.0,
|
||||
1.0, 0.0, translation.x,
|
||||
0.0, 1.0, translation.y,
|
||||
0.0, 0.0, 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
matrix3_transform_v2 :: proc "contextless" (m: mat3, v: v2) -> v2 {
|
||||
matrix3_scale2 :: proc "contextless" (scale: v2) -> mat3 {
|
||||
return {
|
||||
scale.x, 0.0, 0.0,
|
||||
0.0, scale.y, 0.0,
|
||||
0.0, 0.0, 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
matrix3_rotate2 :: proc "contextless" (ang: f32) -> mat3 {
|
||||
a := linalg.cos(ang)
|
||||
b := linalg.sin(ang)
|
||||
return {
|
||||
a, b, 0,
|
||||
-b, a, 0,
|
||||
0, 0, 1,
|
||||
}
|
||||
}
|
||||
|
||||
matrix3_transform_xy :: proc "contextless" (m: mat3, v: v2) -> v2 {
|
||||
return (m * v3{**v, 1.0}).xy
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue