rendering, physics, player and camera WIP
This commit is contained in:
87
src/picking.rs
Normal file
87
src/picking.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use crate::camera::Camera;
|
||||
use crate::mesh::Mesh;
|
||||
use glam::{Mat4, Vec3, Vec4};
|
||||
|
||||
pub struct Ray
|
||||
{
|
||||
pub origin: Vec3,
|
||||
pub direction: Vec3,
|
||||
}
|
||||
|
||||
impl Ray
|
||||
{
|
||||
pub fn from_screen_position(
|
||||
screen_x: f32,
|
||||
screen_y: f32,
|
||||
screen_width: u32,
|
||||
screen_height: u32,
|
||||
camera: &Camera,
|
||||
) -> Self
|
||||
{
|
||||
let ndc_x = (2.0 * screen_x) / screen_width as f32 - 1.0;
|
||||
let ndc_y = 1.0 - (2.0 * screen_y) / screen_height as f32;
|
||||
|
||||
let clip_coords = Vec4::new(ndc_x, ndc_y, -1.0, 1.0);
|
||||
|
||||
let view_matrix = camera.view_matrix();
|
||||
let projection_matrix = camera.projection_matrix();
|
||||
let inv_projection = projection_matrix.inverse();
|
||||
let inv_view = view_matrix.inverse();
|
||||
|
||||
let eye_coords = inv_projection * clip_coords;
|
||||
let eye_coords = Vec4::new(eye_coords.x, eye_coords.y, -1.0, 0.0);
|
||||
|
||||
let world_coords = inv_view * eye_coords;
|
||||
let direction = Vec3::new(world_coords.x, world_coords.y, world_coords.z).normalize();
|
||||
|
||||
Ray {
|
||||
origin: camera.position,
|
||||
direction,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intersects_mesh(&self, mesh: &Mesh, transform: &Mat4) -> Option<f32>
|
||||
{
|
||||
let inv_transform = transform.inverse();
|
||||
let local_origin = inv_transform.transform_point3(self.origin);
|
||||
let local_direction = inv_transform.transform_vector3(self.direction).normalize();
|
||||
|
||||
let mut closest_distance = f32::MAX;
|
||||
let mut hit = false;
|
||||
|
||||
for triangle_idx in (0..mesh.num_indices).step_by(3)
|
||||
{
|
||||
let distance =
|
||||
self.intersects_triangle_local(local_origin, local_direction, mesh, triangle_idx);
|
||||
|
||||
if let Some(d) = distance
|
||||
{
|
||||
if d < closest_distance
|
||||
{
|
||||
closest_distance = d;
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hit
|
||||
{
|
||||
Some(closest_distance)
|
||||
}
|
||||
else
|
||||
{
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn intersects_triangle_local(
|
||||
&self,
|
||||
local_origin: Vec3,
|
||||
local_direction: Vec3,
|
||||
_mesh: &Mesh,
|
||||
_triangle_idx: u32,
|
||||
) -> Option<f32>
|
||||
{
|
||||
None
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user