Bläddra i källkod

Fix camera transformation

Karl Zylinski 6 månader sedan
förälder
incheckning
d7b978f59c
3 ändrade filer med 17 tillägg och 9 borttagningar
  1. 1 1
      README.md
  2. 1 1
      examples/raylib_ports/2d_camera/2d_camera.odin
  3. 15 7
      karl2d.odin

+ 1 - 1
README.md

@@ -16,7 +16,6 @@ Might not be included:
 
 Here follows my near-future TODO list
 
-* Is the 1/zoom in set_camera wrong? Is the matrix multiply order wrong? Hmmmm...
 * Textures: Make the sampler state configurable
 * Textures D3D11: Do we need the SRV in the texture?
 * Flashing textures in Abyss -- Better now but still flashes when you use nose... Check the "odd_frame" stuff in d3d backend
@@ -27,6 +26,7 @@ Here follows my near-future TODO list
 * Shaders: Reflect and expose samplers
 
 ## DONE
+* 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
 * Shaders: Basic loading
 * Shaders: Constants that you can set

+ 1 - 1
examples/raylib_ports/2d_camera/2d_camera.odin

@@ -44,7 +44,7 @@ main :: proc() {
 	}
 
 	camera := k2.Camera {
-		origin = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2},
+		offset = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2},
 		zoom = 1,
 	}
 

+ 15 - 7
karl2d.odin

@@ -695,12 +695,20 @@ set_camera :: proc(camera: Maybe(Camera)) {
 	s.proj_matrix = make_default_projection(s.width, s.height)
 
 	if c, c_ok := camera.?; c_ok {
-		origin_trans := linalg.matrix4_translate(vec3_from_vec2(c.origin))
-		rot := linalg.matrix4_rotate_f32(c.rotation * math.RAD_PER_DEG, {0, 0, 1})
-		translate := linalg.matrix4_translate(vec3_from_vec2(-c.target))
-		scale := linalg.matrix4_scale(Vec3{c.zoom, c.zoom, 1})
-		camera_matrix := origin_trans * scale * rot *  translate 
-		s.view_matrix = camera_matrix
+		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 
 	} else {
 		s.view_matrix = 1
 	}
@@ -794,7 +802,7 @@ Texture :: struct {
 
 Camera :: struct {
 	target: Vec2,
-	origin: Vec2,
+	offset: Vec2,
 	rotation: f32,
 	zoom: f32,
 }