twn_draw: draw_camera_unproject()

This commit is contained in:
veclavtalica
2025-03-07 19:31:31 +03:00
parent 733a1786ab
commit 923cd81571
3 changed files with 176 additions and 0 deletions

View File

@ -5,6 +5,7 @@
#include "twn_types.h"
#include "twn_util.h"
#include "twn_vec.h"
#include "twn_vec_c.h"
#include "twn_deferred_commands.h"
#include <SDL2/SDL.h>
@ -497,6 +498,69 @@ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position,
}
DrawCameraUnprojectResult draw_camera_unproject(Vec2 point,
Vec3 position,
Vec3 direction,
Vec3 up,
float fov,
float zoom,
float draw_distance)
{
bool const orthographic = fabsf(0.0f - fov) < 0.00001f;
if (!orthographic && fov >= (float)(M_PI))
log_warn("Invalid fov given (%f)", (double)fov);
/* inital zoom = 1.0 correlates to perspective from this */
zoom *= 0.1f;
float const aspect = (float)ctx.base_render_width / (float)ctx.base_render_height;
Camera const camera = {
.fov = fov,
.pos = position,
.target = vec3_norm(direction),
.up = up,
.viewbox = {
aspect/-zoom, aspect/zoom,
1/zoom, 1/-zoom
},
.far_z = draw_distance
};
Matrix4 const projection_matrix = orthographic ? camera_orthographic(&camera) : camera_perspective(&camera);
Matrix4 const look_at_matrix = camera_look_at(&camera);
/* TODO: cache matrices for repeated camera inputs, those are expensive */
Matrix4 const inverse_view_proj = matrix_inverse(matrix_multiply(projection_matrix, look_at_matrix));
point.y = (float)ctx.base_render_height - point.y;
if (!orthographic) {
point = (Vec2) {
point.x,
point.y,
};
}
Vec4 v;
v.x = 2.0f * point.x / (float)ctx.base_render_width - 1.0f;
v.y = 2.0f * point.y / (float)ctx.base_render_height - 1.0f;
v.z = 2.0f * 1.0f - 1.0f;
v.w = 1.0f;
log_vec2(point, "point");
v = matrix_vector_multiply(inverse_view_proj, v);
/* TODO: is it even ever not equal to 1 in our case ? */
v = vec4_scale(v, 1.0f / v.w);
return (DrawCameraUnprojectResult){
.position = (Vec3){ v.x, v.y, v.z },
.direction = vec3_norm(vec3_sub(position, (Vec3){ v.x, v.y, v.z })),
};
}
void set_depth_range(double low, double high) {
depth_range_low = low;
depth_range_high = high;