camera_object.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. type camera_object_t = {
  2. base?: object_t;
  3. data?: camera_data_t;
  4. p?: mat4_t;
  5. no_jitter_p?: mat4_t;
  6. frame?: i32;
  7. v?: mat4_t;
  8. vp?: mat4_t;
  9. frustum_planes?: frustum_plane_t[];
  10. };
  11. let _camera_object_v: vec4_t = vec4_create();
  12. let _camera_object_sphere_center: vec4_t = vec4_create();
  13. let camera_object_taa_frames: i32 = 1;
  14. function camera_object_create(data: camera_data_t): camera_object_t {
  15. let raw: camera_object_t = {};
  16. raw.no_jitter_p = mat4_identity();
  17. raw.frame = 0;
  18. raw.base = object_create(false);
  19. raw.base.ext = raw;
  20. raw.base.ext_type = "camera_object_t";
  21. raw.data = data;
  22. camera_object_build_proj(raw);
  23. raw.v = mat4_identity();
  24. raw.vp = mat4_identity();
  25. if (data.frustum_culling) {
  26. raw.frustum_planes = [];
  27. for (let i: i32 = 0; i < 6; ++i) {
  28. array_push(raw.frustum_planes, frustum_plane_create());
  29. }
  30. }
  31. array_push(scene_cameras, raw);
  32. return raw;
  33. }
  34. function camera_object_build_proj(raw: camera_object_t, screen_aspect: f32 = -1.0) {
  35. if (raw.data.ortho != null) {
  36. raw.p = mat4_ortho(raw.data.ortho[0], raw.data.ortho[1], raw.data.ortho[2], raw.data.ortho[3], -raw.data.far_plane, raw.data.far_plane);
  37. }
  38. else {
  39. if (screen_aspect < 0) {
  40. screen_aspect = sys_w() / sys_h();
  41. }
  42. let aspect: f32 = raw.data.aspect ? raw.data.aspect : screen_aspect;
  43. raw.p = mat4_persp(raw.data.fov, aspect, raw.data.near_plane, raw.data.far_plane);
  44. }
  45. raw.no_jitter_p = mat4_clone(raw.p);
  46. }
  47. function camera_object_remove(raw: camera_object_t) {
  48. array_remove(scene_cameras, raw);
  49. object_remove_super(raw.base);
  50. }
  51. function camera_object_render_frame(raw: camera_object_t) {
  52. camera_object_proj_jitter(raw);
  53. camera_object_build_mat(raw);
  54. render_path_render_frame();
  55. }
  56. function camera_object_proj_jitter(raw: camera_object_t) {
  57. let w: i32 = render_path_current_w;
  58. let h: i32 = render_path_current_h;
  59. raw.p = mat4_clone(raw.no_jitter_p);
  60. let i: i32 = raw.frame % camera_object_taa_frames;
  61. let x: f32 = 0.0;
  62. let y: f32 = 0.0;
  63. if (i == 0) {
  64. x = 0.5;
  65. y = 0.333;
  66. }
  67. else if (i == 1) {
  68. x = -0.5;
  69. y = -0.333;
  70. }
  71. else if (i == 2) {
  72. x = 0.25;
  73. y = 0.111;
  74. }
  75. else if (i == 3) {
  76. x = -0.25;
  77. y = -0.111;
  78. }
  79. else if (i == 4) {
  80. x = 0.375;
  81. y = 0.444;
  82. }
  83. else {
  84. x = -0.375;
  85. y = -0.444;
  86. }
  87. x *= 2;
  88. y *= 2;
  89. raw.p.m20 += x / w;
  90. raw.p.m21 += y / h;
  91. raw.frame++;
  92. }
  93. function camera_object_build_mat(raw: camera_object_t) {
  94. transform_build_matrix(raw.base.transform);
  95. // Prevent camera matrix scaling
  96. // TODO: discards position affected by scaled camera parent
  97. let sc: vec4_t = mat4_get_scale(raw.base.transform.world);
  98. if (sc.x != 1.0 || sc.y != 1.0 || sc.z != 1.0) {
  99. _camera_object_v = vec4_create(1.0 / sc.x, 1.0 / sc.y, 1.0 / sc.z);
  100. raw.base.transform.world = mat4_scale(raw.base.transform.world, _camera_object_v);
  101. }
  102. raw.v = mat4_inv(raw.base.transform.world);
  103. raw.vp = mat4_mult_mat(raw.v, raw.p);
  104. if (raw.data.frustum_culling) {
  105. camera_object_build_view_frustum(raw.vp, raw.frustum_planes);
  106. }
  107. }
  108. function camera_object_right(raw: camera_object_t): vec4_t {
  109. return vec4_norm(vec4_create(raw.base.transform.local.m00, raw.base.transform.local.m01, raw.base.transform.local.m02));
  110. }
  111. function camera_object_up(raw: camera_object_t): vec4_t {
  112. return vec4_norm(vec4_create(raw.base.transform.local.m10, raw.base.transform.local.m11, raw.base.transform.local.m12));
  113. }
  114. function camera_object_look(raw: camera_object_t): vec4_t {
  115. return vec4_norm(vec4_create(-raw.base.transform.local.m20, -raw.base.transform.local.m21, -raw.base.transform.local.m22));
  116. }
  117. function camera_object_right_world(raw: camera_object_t): vec4_t {
  118. return vec4_norm(vec4_create(raw.base.transform.world.m00, raw.base.transform.world.m01, raw.base.transform.world.m02));
  119. }
  120. function camera_object_up_world(raw: camera_object_t): vec4_t {
  121. return vec4_norm(vec4_create(raw.base.transform.world.m10, raw.base.transform.world.m11, raw.base.transform.world.m12));
  122. }
  123. function camera_object_look_world(raw: camera_object_t): vec4_t {
  124. return vec4_norm(vec4_create(-raw.base.transform.world.m20, -raw.base.transform.world.m21, -raw.base.transform.world.m22));
  125. }
  126. function camera_object_build_view_frustum(vp: mat4_t, frustum_planes: frustum_plane_t[]) {
  127. // Left plane
  128. frustum_plane_set_components(frustum_planes[0], vp.m03 + vp.m00, vp.m13 + vp.m10, vp.m23 + vp.m20, vp.m33 + vp.m30);
  129. // Right plane
  130. frustum_plane_set_components(frustum_planes[1], vp.m03 - vp.m00, vp.m13 - vp.m10, vp.m23 - vp.m20, vp.m33 - vp.m30);
  131. // Top plane
  132. frustum_plane_set_components(frustum_planes[2], vp.m03 - vp.m01, vp.m13 - vp.m11, vp.m23 - vp.m21, vp.m33 - vp.m31);
  133. // Bottom plane
  134. frustum_plane_set_components(frustum_planes[3], vp.m03 + vp.m01, vp.m13 + vp.m11, vp.m23 + vp.m21, vp.m33 + vp.m31);
  135. // Near plane
  136. frustum_plane_set_components(frustum_planes[4], vp.m02, vp.m12, vp.m22, vp.m32);
  137. // Far plane
  138. frustum_plane_set_components(frustum_planes[5], vp.m03 - vp.m02, vp.m13 - vp.m12, vp.m23 - vp.m22, vp.m33 - vp.m32);
  139. // Normalize planes
  140. for (let i: i32 = 0; i < frustum_planes.length; ++i) {
  141. let plane: frustum_plane_t = frustum_planes[i];
  142. frustum_plane_normalize(plane);
  143. }
  144. }
  145. function camera_object_sphere_in_frustum(frustum_planes: frustum_plane_t[], t: transform_t, radius_scale: f32 = 1.0, offset_x: f32 = 0.0, offset_y: f32 = 0.0,
  146. offset_z: f32 = 0.0): bool {
  147. // Use scale when radius is changing
  148. let radius: f32 = t.radius * radius_scale;
  149. for (let i: i32 = 0; i < frustum_planes.length; ++i) {
  150. let plane: frustum_plane_t = frustum_planes[i];
  151. _camera_object_sphere_center = vec4_create(transform_world_x(t) + offset_x, transform_world_y(t) + offset_y, transform_world_z(t) + offset_z);
  152. // Outside the frustum
  153. if (frustum_plane_dist_to_sphere(plane, _camera_object_sphere_center, radius) + radius * 2 < 0) {
  154. return false;
  155. }
  156. }
  157. return true;
  158. }
  159. type frustum_plane_t = {
  160. normal?: vec4_t;
  161. constant?: f32;
  162. };
  163. function frustum_plane_create(): frustum_plane_t {
  164. let raw: frustum_plane_t = {};
  165. raw.normal = vec4_create(1.0, 0.0, 0.0);
  166. raw.constant = 0.0;
  167. return raw;
  168. }
  169. function frustum_plane_normalize(raw: frustum_plane_t) {
  170. let inv_normal_length: f32 = 1.0 / vec4_len(raw.normal);
  171. raw.normal = vec4_mult(raw.normal, inv_normal_length);
  172. raw.constant *= inv_normal_length;
  173. }
  174. function frustum_plane_dist_to_sphere(raw: frustum_plane_t, sphere_center: vec4_t, sphere_radius: f32): f32 {
  175. return (vec4_dot(raw.normal, sphere_center) + raw.constant) - sphere_radius;
  176. }
  177. function frustum_plane_set_components(raw: frustum_plane_t, x: f32, y: f32, z: f32, w: f32) {
  178. raw.normal = vec4_create(x, y, z);
  179. raw.constant = w;
  180. }