gs_camera.c 3.4 KB

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