Quellcode durchsuchen

world <--> screen transformations

Karl Zylinski vor 6 Monaten
Ursprung
Commit
ea88256ca6
3 geänderte Dateien mit 50 neuen und 24 gelöschten Zeilen
  1. 3 1
      README.md
  2. 13 5
      karl2d.doc.odin
  3. 34 18
      karl2d.odin

+ 3 - 1
README.md

@@ -16,8 +16,9 @@ Might not be included:
 
 Here follows my near-future TODO list
 
+* get_camera_view_matrix returns Mat4... should we go hardcore 2D and return Mat3 so you can do
+    mat * Vec3{pos.x, pos.y, 1} for positions and mat * Vec3{dir.x, dir.y, 0} for dirs?
 * win32: Gamepad support
-* win32: Resizable window
 * Do proper checks of vertex count and dispatch rendering when full
 	* What happens when list is full? We can't just empty the vertex list due to being used by input assembler etc.
 * Should we sort by depth? Maybe we should use Vec3 because some 2D games rely on it?
@@ -27,6 +28,7 @@ Here follows my near-future TODO list
 * Shaders: Reflect and expose samplers
 
 ## DONE
+* win32: Resizable window
 * Flashing textures in Abyss -- Better now but still flashes when you use nose... Check the "odd_frame" stuff in d3d backend
 * Is the 1/zoom in set_camera wrong? Is the matrix multiply order wrong? Hmmmm...
 * Fix the depedency on D3D stuff so we can move load_shader etc

+ 13 - 5
karl2d.doc.odin

@@ -142,6 +142,12 @@ set_camera :: proc(camera: Maybe(Camera))
 
 screen_to_world :: proc(pos: Vec2, camera: Camera) -> Vec2
 
+world_to_screen :: proc(pos: Vec2, camera: Camera) -> Vec2
+
+get_camera_view_matrix :: proc(c: Camera) -> Mat4
+
+get_camera_world_matrix :: proc(c: Camera) -> Mat4
+
 //------//
 // MISC //
 //------//
@@ -154,14 +160,12 @@ set_internal_state :: proc(state: ^State)
 //---------------------//
 // TYPES AND CONSTANTS //
 //---------------------//
-
-// A two dimensinal vector.
 Vec2 :: [2]f32
 
-// A three dimensinal vector.
 Vec3 :: [3]f32
 
-// A 4x4 column-major matrix.
+Vec4 :: [4]f32
+
 Mat4 :: matrix[4,4]f32
 
 // A two dimensional vector of integer numeric type.
@@ -302,7 +306,7 @@ State :: struct {
 	custom_context: runtime.Context,
 	win: Window_Interface,
 	window_state: rawptr,
-	rb: Rendering_Backend_Interface,
+	rb: Render_Backend_Interface,
 	rb_state: rawptr,
 	
 	shutdown_wanted: bool,
@@ -315,6 +319,10 @@ State :: struct {
 	keys_went_up: #sparse [Keyboard_Key]bool,
 	keys_is_held: #sparse [Keyboard_Key]bool,
 
+	mouse_button_went_down: #sparse [Mouse_Button]bool,
+	mouse_button_went_up: #sparse [Mouse_Button]bool,
+	mouse_button_is_held: #sparse [Mouse_Button]bool,
+
 	window: Window_Handle,
 	width: int,
 	height: int,

+ 34 - 18
karl2d.odin

@@ -714,27 +714,44 @@ set_camera :: proc(camera: Maybe(Camera)) {
 	s.proj_matrix = make_default_projection(s.width, s.height)
 
 	if c, c_ok := camera.?; c_ok {
-		inv_target_translate := linalg.matrix4_translate(vec3_from_vec2(-c.target))
-		inv_rot := linalg.matrix4_rotate_f32(c.rotation * math.RAD_PER_DEG, {0, 0, 1})
-		inv_scale := linalg.matrix4_scale(Vec3{c.zoom, c.zoom, 1})
-		inv_offset_translate := linalg.matrix4_translate(vec3_from_vec2(c.offset))
-
-		// A view matrix is essentially the world transform matrix of the camera, but inverted. We
-		// bring everything in the world "in front of the camera".
-		//
-		// Instead of constructing the camera matrix and doing a matrix inverse, here we just do the
-		// maths in "backwards order". I.e. a camera transform matrix would be:
-		//
-		//    target_translate * rot * scale * offset_translate
-
-		s.view_matrix = inv_offset_translate * inv_scale * inv_rot * inv_target_translate 
+		s.view_matrix = get_camera_view_matrix(c)
 	} else {
 		s.view_matrix = 1
 	}
 }
 
 screen_to_world :: proc(pos: Vec2, camera: Camera) -> Vec2 {
-	panic("not implemented")
+	return (get_camera_world_matrix(camera) * Vec4 { pos.x, pos.y, 0, 1 }).xy
+}
+
+world_to_screen :: proc(pos: Vec2, camera: Camera) -> Vec2 {
+	return (get_camera_view_matrix(camera) * Vec4 { pos.x, pos.y, 0, 1 }).xy
+}
+
+get_camera_view_matrix :: proc(c: Camera) -> Mat4 {
+	inv_target_translate := linalg.matrix4_translate(vec3_from_vec2(-c.target))
+	inv_rot := linalg.matrix4_rotate_f32(c.rotation * math.RAD_PER_DEG, {0, 0, 1})
+	inv_scale := linalg.matrix4_scale(Vec3{c.zoom, c.zoom, 1})
+	inv_offset_translate := linalg.matrix4_translate(vec3_from_vec2(c.offset))
+
+	// A view matrix is essentially the world transform matrix of the camera, but inverted. We
+	// bring everything in the world "in front of the camera".
+	//
+	// Instead of constructing the camera matrix and doing a matrix inverse, here we just do the
+	// maths in "backwards order". I.e. a camera transform matrix would be:
+	//
+	//    target_translate * rot * scale * offset_translate
+
+	return inv_offset_translate * inv_scale * inv_rot * inv_target_translate
+}
+
+get_camera_world_matrix :: proc(c: Camera) -> Mat4 {
+	offset_translate := linalg.matrix4_translate(vec3_from_vec2(-c.offset))
+	rot := linalg.matrix4_rotate_f32(-c.rotation * math.RAD_PER_DEG, {0, 0, 1})
+	scale := linalg.matrix4_scale(Vec3{1/c.zoom, 1/c.zoom, 1})
+	target_translate := linalg.matrix4_translate(vec3_from_vec2(c.target))
+
+	return target_translate * rot * scale * offset_translate
 }
 
 //------//
@@ -759,13 +776,12 @@ set_internal_state :: proc(state: ^State) {
 // TYPES AND CONSTANTS //
 //---------------------//
 
-// A two dimensinal vector.
 Vec2 :: [2]f32
 
-// A three dimensinal vector.
 Vec3 :: [3]f32
 
-// A 4x4 column-major matrix.
+Vec4 :: [4]f32
+
 Mat4 :: matrix[4,4]f32
 
 // A two dimensional vector of integer numeric type.