gs_camera.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include "graphics/gs_camera.h"
  2. #include "platform/gs_platform.h"
  3. #include "base/gs_engine.h"
  4. gs_camera_t gs_camera_default()
  5. {
  6. // Construct default camera parameters
  7. gs_camera_t cam = gs_default_val();
  8. cam.transform = gs_vqs_default();
  9. cam.transform.position = (gs_vec3){0.f, 0.f, -1.f};
  10. cam.fov = 60.f;
  11. cam.near_plane = 0.1f;
  12. cam.far_plane = 1000.f;
  13. cam.ortho_scale = 1.f;
  14. cam.proj_type = gs_projection_type_orthographic;
  15. return cam;
  16. }
  17. gs_camera_t gs_camera_perspective()
  18. {
  19. gs_camera_t cam = gs_camera_default();
  20. cam.proj_type = gs_projection_type_perspective;
  21. return cam;
  22. }
  23. gs_vec3 gs_camera_forward(gs_camera_t* cam)
  24. {
  25. return (gs_quat_rotate(cam->transform.rotation, (gs_vec3){0.0f, 0.0f, -1.0f}));
  26. }
  27. gs_vec3 gs_camera_backward(gs_camera_t* cam)
  28. {
  29. return (gs_quat_rotate(cam->transform.rotation, (gs_vec3){0.0f, 0.0f, 1.0f}));
  30. }
  31. gs_vec3 gs_camera_up(gs_camera_t* cam)
  32. {
  33. return (gs_quat_rotate(cam->transform.rotation, (gs_vec3){0.0f, 1.0f, 0.0f}));
  34. }
  35. gs_vec3 gs_camera_down(gs_camera_t* cam)
  36. {
  37. return (gs_quat_rotate(cam->transform.rotation, (gs_vec3){0.0f, -1.0f, 0.0f}));
  38. }
  39. gs_vec3 gs_camera_right(gs_camera_t* cam)
  40. {
  41. return (gs_quat_rotate(cam->transform.rotation, (gs_vec3){1.0f, 0.0f, 0.0f}));
  42. }
  43. gs_vec3 gs_camera_left(gs_camera_t* cam)
  44. {
  45. return (gs_quat_rotate(cam->transform.rotation, (gs_vec3){-1.0f, 0.0f, 0.0f}));
  46. }
  47. gs_vec3 gs_camera_unproject(gs_camera_t* cam, gs_vec3 coords, s32 view_width, s32 view_height)
  48. {
  49. gs_vec3 wc = gs_default_val();
  50. // Get inverse of view projection from camera
  51. gs_mat4 inverse_vp = gs_mat4_inverse(gs_camera_get_view_projection(cam, view_width, view_height));
  52. f32 w_x = (f32)coords.x;
  53. f32 w_y = (f32)coords.y;
  54. f32 w_z = (f32)coords.z;
  55. // Transform from ndc
  56. gs_vec4 in;
  57. in.x = (w_x / (f32)view_width) * 2.f - 1.f;
  58. in.y = 1.f - (w_y / (f32)view_height) * 2.f;
  59. in.z = 2.f * w_z - 1.f;
  60. in.w = 1.f;
  61. // To world coords
  62. gs_vec4 out = gs_mat4_mul_vec4(inverse_vp, in);
  63. if (out.w == 0.f)
  64. {
  65. // Avoid div by zero
  66. return wc;
  67. }
  68. out.w = 1.f / out.w;
  69. wc = (gs_vec3) {
  70. out.x * out.w,
  71. out.y * out.w,
  72. out.z * out.w
  73. };
  74. return wc;
  75. }
  76. gs_mat4 gs_camera_get_view_projection(gs_camera_t* cam, s32 view_width, s32 view_height)
  77. {
  78. gs_mat4 view = gs_camera_get_view(cam);
  79. gs_mat4 proj = gs_camera_get_projection(cam, view_width, view_height);
  80. return gs_mat4_mul(proj, view);
  81. }
  82. gs_mat4 gs_camera_get_view(gs_camera_t* cam)
  83. {
  84. gs_vec3 up = gs_camera_up(cam);
  85. gs_vec3 forward = gs_camera_forward(cam);
  86. gs_vec3 target = gs_vec3_add(forward, cam->transform.position);
  87. return gs_mat4_look_at(cam->transform.position, target, up);
  88. }
  89. gs_mat4 gs_camera_get_projection(gs_camera_t* cam, s32 view_width, s32 view_height)
  90. {
  91. gs_mat4 proj_mat = gs_mat4_identity();
  92. switch(cam->proj_type)
  93. {
  94. case gs_projection_type_perspective:
  95. {
  96. proj_mat = gs_mat4_perspective(cam->fov, (f32)view_width / (f32)view_height, cam->near_plane, cam->far_plane);
  97. } break;
  98. // Don't like this...
  99. case gs_projection_type_orthographic:
  100. {
  101. f32 _ar = (f32)view_width / (f32)view_height;
  102. f32 distance = 0.5f * (cam->far_plane - cam->near_plane);
  103. const f32 ortho_scale = cam->ortho_scale;
  104. const f32 aspect_ratio = _ar;
  105. proj_mat = gs_mat4_ortho
  106. (
  107. -ortho_scale * aspect_ratio,
  108. ortho_scale * aspect_ratio,
  109. -ortho_scale,
  110. ortho_scale,
  111. -distance,
  112. distance
  113. );
  114. // (
  115. // 0.f,
  116. // view_width,
  117. // view_height,
  118. // 0.f,
  119. // cam->near_plane,
  120. // cam->far_plane
  121. //);
  122. } break;
  123. }
  124. return proj_mat;
  125. }
  126. void gs_camera_offset_orientation(gs_camera_t* cam, f32 yaw, f32 pitch)
  127. {
  128. gs_quat x = gs_quat_angle_axis(gs_deg_to_rad(yaw), (gs_vec3){0.f, 1.f, 0.f}); // Absolute up
  129. gs_quat y = gs_quat_angle_axis(gs_deg_to_rad(pitch), gs_camera_right(cam)); // Relative right
  130. cam->transform.rotation = gs_quat_mul(gs_quat_mul(x, y), cam->transform.rotation);
  131. }