mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Fix "feel-good" panning
This commit is contained in:
parent
1cadd50d96
commit
0cd5f8fc41
@ -1,4 +1,5 @@
|
||||
use cgmath::{EuclideanSpace, Point3, Vector2, Vector3, Zero};
|
||||
use cgmath::{EuclideanSpace, Matrix4, Point3, Vector2, Vector3, Vector4, Zero};
|
||||
use log::info;
|
||||
|
||||
use crate::render::camera;
|
||||
|
||||
@ -33,11 +34,11 @@ impl CameraController {
|
||||
};
|
||||
match key {
|
||||
winit::event::VirtualKeyCode::W | winit::event::VirtualKeyCode::Up => {
|
||||
self.camera_translate.y += amount;
|
||||
self.camera_translate.y -= amount;
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::S | winit::event::VirtualKeyCode::Down => {
|
||||
self.camera_translate.y -= amount;
|
||||
self.camera_translate.y += amount;
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::A | winit::event::VirtualKeyCode::Left => {
|
||||
@ -52,19 +53,33 @@ impl CameraController {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_mouse(
|
||||
pub fn pan_camera(
|
||||
&mut self,
|
||||
initial_camera_position: cgmath::Point3<f64>,
|
||||
delta: Vector2<f64>,
|
||||
initial_screen_position: Vector2<f64>,
|
||||
current_screen_position: Vector2<f64>,
|
||||
intial_camera: &camera::Camera,
|
||||
camera: &camera::Camera,
|
||||
perspective: &camera::Perspective,
|
||||
) {
|
||||
let view_proj = camera.calc_view_proj(perspective);
|
||||
let world = camera.project_screen_to_world(&Vector2::new(0.0, 0.0), &view_proj)
|
||||
- camera.project_screen_to_world(&delta, &view_proj);
|
||||
let initial = camera.project_screen_to_world(
|
||||
&initial_screen_position,
|
||||
&intial_camera.calc_view_proj(perspective),
|
||||
);
|
||||
let current = camera.project_screen_to_world(
|
||||
¤t_screen_position,
|
||||
&intial_camera.calc_view_proj(perspective),
|
||||
);
|
||||
let delta = initial - current;
|
||||
|
||||
info!("initial: {:?}", initial);
|
||||
info!("current: {:?}", current);
|
||||
info!("delta: {:?}", delta);
|
||||
|
||||
self.camera_position =
|
||||
Some(initial_camera_position.to_vec() + Vector3::new(-world.x, world.y, 0.0))
|
||||
Some(initial_camera_position.to_vec() + Vector3::new(delta.x, delta.y, 0.0));
|
||||
//self.camera_position = Some(Vector3::new(-delta.x, delta.y, 0.0))
|
||||
}
|
||||
|
||||
pub fn process_scroll(&mut self, delta: &winit::event::MouseScrollDelta) {
|
||||
@ -85,7 +100,9 @@ impl CameraController {
|
||||
let dt = dt.as_secs_f64() * self.speed;
|
||||
|
||||
if let Some(position) = self.camera_position {
|
||||
info!("position: {:?}", position);
|
||||
camera.position = Point3::from_vec(position);
|
||||
//camera.translation = Matrix4::from_translation(position);
|
||||
self.camera_position = None;
|
||||
}
|
||||
|
||||
@ -95,7 +112,6 @@ impl CameraController {
|
||||
// to get closer to an object you want to focus on.
|
||||
let delta = self.camera_translate * dt;
|
||||
camera.position += delta;
|
||||
|
||||
self.camera_translate -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ use winit::event::{
|
||||
};
|
||||
|
||||
use crate::input::camera_controller::CameraController;
|
||||
use crate::render::camera::Camera;
|
||||
use crate::render::render_state::RenderState;
|
||||
|
||||
mod camera_controller;
|
||||
@ -15,19 +16,21 @@ mod camera_controller;
|
||||
pub struct InputHandler {
|
||||
camera_controller: CameraController,
|
||||
|
||||
mouse_position: Option<Vector2<f64>>,
|
||||
last_mouse_position: Option<Vector2<f64>>,
|
||||
initial_camera: Option<Camera>,
|
||||
initial_camera_position: Option<cgmath::Point3<f64>>,
|
||||
mouse_pressed: bool,
|
||||
target_stroke_width: f32,
|
||||
}
|
||||
|
||||
impl InputHandler {
|
||||
pub fn new() -> Self {
|
||||
let camera_controller = CameraController::new(5.0, 100.0);
|
||||
Self {
|
||||
target_stroke_width: 1.0,
|
||||
initial_camera_position: None,
|
||||
mouse_position: None,
|
||||
last_mouse_position: None,
|
||||
initial_camera: None,
|
||||
mouse_pressed: false,
|
||||
camera_controller,
|
||||
}
|
||||
@ -39,29 +42,34 @@ impl InputHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn process_mouse_delta(&mut self, position: Vector2<f64>, state: &mut RenderState) {
|
||||
if let (Some(last_mouse_position), Some(initial_camera_position)) =
|
||||
(self.last_mouse_position, self.initial_camera_position)
|
||||
{
|
||||
let delta = last_mouse_position - position;
|
||||
self.camera_controller.process_mouse(
|
||||
fn pan_camera(&mut self, position: Vector2<f64>, render_state: &mut RenderState) {
|
||||
if let (Some(last_mouse_position), Some(initial_camera_position), Some(initial_camera)) = (
|
||||
self.last_mouse_position,
|
||||
self.initial_camera_position,
|
||||
self.initial_camera.as_ref(),
|
||||
) {
|
||||
self.camera_controller.pan_camera(
|
||||
initial_camera_position,
|
||||
delta,
|
||||
&state.camera,
|
||||
&state.perspective,
|
||||
last_mouse_position,
|
||||
position,
|
||||
initial_camera,
|
||||
&render_state.camera,
|
||||
&render_state.perspective,
|
||||
);
|
||||
} else {
|
||||
self.last_mouse_position = Some(position);
|
||||
self.initial_camera_position = Some(state.camera.position);
|
||||
self.initial_camera_position = Some(render_state.camera.position);
|
||||
self.initial_camera = Some(render_state.camera.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window_input(&mut self, event: &WindowEvent, state: &mut RenderState) -> bool {
|
||||
pub fn window_input(&mut self, event: &WindowEvent, render_state: &mut RenderState) -> bool {
|
||||
match event {
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
if self.mouse_pressed {
|
||||
let mouse_position: (f64, f64) = position.to_owned().into();
|
||||
self.process_mouse_delta(Vector2::from(mouse_position), state);
|
||||
self.pan_camera(Vector2::from(mouse_position), render_state);
|
||||
self.mouse_position = Some(Vector2::from(mouse_position));
|
||||
}
|
||||
true
|
||||
}
|
||||
@ -74,14 +82,6 @@ impl InputHandler {
|
||||
},
|
||||
..
|
||||
} => match key {
|
||||
winit::event::VirtualKeyCode::Z => {
|
||||
self.target_stroke_width *= 1.2;
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::H => {
|
||||
self.target_stroke_width *= 0.8;
|
||||
true
|
||||
}
|
||||
_ => self.camera_controller.process_keyboard(*key, *state),
|
||||
},
|
||||
WindowEvent::Touch(touch) => {
|
||||
@ -89,10 +89,10 @@ impl InputHandler {
|
||||
match touch.phase {
|
||||
TouchPhase::Started => {
|
||||
self.last_mouse_position = Some(Vector2::from(touch_position));
|
||||
self.initial_camera_position = Some(state.camera.position);
|
||||
self.initial_camera_position = Some(render_state.camera.position);
|
||||
}
|
||||
TouchPhase::Moved | TouchPhase::Ended => {
|
||||
self.process_mouse_delta(Vector2::from(touch_position), state);
|
||||
self.pan_camera(Vector2::from(touch_position), render_state);
|
||||
}
|
||||
TouchPhase::Cancelled => {}
|
||||
}
|
||||
@ -111,8 +111,30 @@ impl InputHandler {
|
||||
self.mouse_pressed = *state == ElementState::Pressed;
|
||||
|
||||
if !self.mouse_pressed {
|
||||
/*if let (
|
||||
Some(last_mouse_position),
|
||||
Some(initial_camera_position),
|
||||
Some(initial_camera),
|
||||
Some(mouse_position),
|
||||
) = (
|
||||
self.last_mouse_position,
|
||||
self.initial_camera_position,
|
||||
self.initial_camera.as_ref(),
|
||||
self.mouse_position,
|
||||
) {
|
||||
self.camera_controller.pan_camera(
|
||||
initial_camera_position,
|
||||
last_mouse_position,
|
||||
mouse_position,
|
||||
initial_camera,
|
||||
&render_state.camera,
|
||||
&render_state.perspective,
|
||||
);
|
||||
}*/
|
||||
|
||||
self.last_mouse_position = None;
|
||||
self.initial_camera_position = None;
|
||||
self.initial_camera = None;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use cgmath::prelude::*;
|
||||
use cgmath::{Matrix4, Vector2, Vector4};
|
||||
use cgmath::{Matrix4, Vector2, Vector3, Vector4};
|
||||
|
||||
use crate::render::shaders::ShaderCamera;
|
||||
|
||||
@ -19,8 +19,9 @@ pub const FLIP_Y: cgmath::Matrix4<f64> = cgmath::Matrix4::new(
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
);
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Camera {
|
||||
pub translation: cgmath::Matrix4<f64>,
|
||||
pub position: cgmath::Point3<f64>,
|
||||
pub yaw: cgmath::Rad<f64>,
|
||||
pub pitch: cgmath::Rad<f64>,
|
||||
@ -43,6 +44,7 @@ impl Camera {
|
||||
) -> Self {
|
||||
Self {
|
||||
position: position.into(),
|
||||
translation: Matrix4::identity(),
|
||||
yaw: yaw.into(),
|
||||
pitch: pitch.into(),
|
||||
width: width as f64,
|
||||
@ -61,7 +63,7 @@ impl Camera {
|
||||
cgmath::Vector3::new(self.yaw.0.cos(), self.pitch.0.sin(), self.yaw.0.sin())
|
||||
.normalize(),
|
||||
cgmath::Vector3::unit_y(),
|
||||
)
|
||||
) * self.translation
|
||||
}
|
||||
|
||||
pub fn calc_view_proj(&self, perspective: &Perspective) -> Matrix4<f64> {
|
||||
@ -76,32 +78,198 @@ impl Camera {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn project_screen_to_world(
|
||||
&self,
|
||||
screen: &Vector2<f64>,
|
||||
view_proj: &Matrix4<f64>,
|
||||
) -> Vector4<f64> {
|
||||
fn dx_matrix(width: f64, height: f64) -> Matrix4<f64> {
|
||||
// Adapted from: https://docs.microsoft.com/en-us/windows/win32/direct3d9/viewports-and-clipping#viewport-rectangle
|
||||
let min_depth = 0.0;
|
||||
let max_depth = 1.0;
|
||||
let x = 0.0;
|
||||
let y = 0.0;
|
||||
let ox = x + width / 2.0;
|
||||
let oy = y + height / 2.0;
|
||||
let oz = min_depth;
|
||||
let px = width as f64;
|
||||
let py = height as f64;
|
||||
let pz = max_depth - min_depth;
|
||||
Matrix4::from_cols(
|
||||
Vector4::new(width as f64 / 2.0, 0.0, 0.0, 0.0),
|
||||
Vector4::new(0.0, -height as f64 / 2.0, 0.0, 0.0),
|
||||
Vector4::new(0.0, 0.0, pz, 0.0),
|
||||
Vector4::new(ox, oy, oz, 1.0),
|
||||
)
|
||||
}
|
||||
|
||||
fn clip_to_window(clip: &Vector4<f64>, width: f64, height: f64) -> Vector3<f64> {
|
||||
// Adopted from: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkViewport.html
|
||||
// and https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/
|
||||
#[rustfmt::skip]
|
||||
let ndc = Vector4::new(
|
||||
clip.x / clip.w,
|
||||
clip.y / clip.w,
|
||||
clip.z / clip.w,
|
||||
clip.w / clip.w
|
||||
);
|
||||
|
||||
let min_depth = 0.0;
|
||||
let max_depth = 1.0;
|
||||
|
||||
let x = 0.0;
|
||||
let y = 0.0;
|
||||
let ox = x + self.width / 2.0;
|
||||
let oy = y + self.height / 2.0;
|
||||
let ox = x + width as f64 / 2.0;
|
||||
let oy = y + height as f64 / 2.0;
|
||||
let oz = min_depth;
|
||||
let px = width as f64;
|
||||
let py = height as f64;
|
||||
let pz = max_depth - min_depth;
|
||||
let xd = ndc.x;
|
||||
let yd = ndc.y;
|
||||
let zd = ndc.z;
|
||||
Vector3::new(px / 2.0 * xd + ox, py / 2.0 * yd + oy, pz * zd + oz)
|
||||
}
|
||||
|
||||
// Adapted from: https://docs.microsoft.com/en-us/windows/win32/direct3d9/viewports-and-clipping#viewport-rectangle
|
||||
let direct_x = Matrix4::from_cols(
|
||||
Vector4::new(self.width as f64 / 2.0, 0.0, 0.0, 0.0),
|
||||
Vector4::new(0.0, self.height as f64 / 2.0, 0.0, 0.0),
|
||||
Vector4::new(0.0, 0.0, pz, 0.0),
|
||||
Vector4::new(ox, oy, oz, 1.0),
|
||||
// https://docs.microsoft.com/en-us/windows/win32/dxtecharts/the-direct3d-transformation-pipeline
|
||||
fn clip_to_window_matrix(clip: &Vector4<f64>, width: f64, height: f64) -> Vector4<f64> {
|
||||
let w = clip.w;
|
||||
let z = clip.z;
|
||||
println!("z in clip space: {z}");
|
||||
println!("w in clip space: {w}");
|
||||
|
||||
#[rustfmt::skip]
|
||||
let ndc = Vector4::new(
|
||||
clip.x / clip.w,
|
||||
clip.y / clip.w,
|
||||
clip.z / clip.w,
|
||||
clip.w / clip.w
|
||||
);
|
||||
|
||||
let homogenous = Vector4::new(screen.x, screen.y, 1.0, 1.0) * self.position.z;
|
||||
let window = Self::dx_matrix(width, height) * ndc;
|
||||
window
|
||||
}
|
||||
|
||||
view_proj.invert().unwrap() * direct_x.invert().unwrap() * homogenous
|
||||
// https://docs.microsoft.com/en-us/windows/win32/dxtecharts/the-direct3d-transformation-pipeline
|
||||
fn window_to_clip(
|
||||
window: &Vector3<f64>,
|
||||
origin_clip_space: &Vector4<f64>,
|
||||
width: f64,
|
||||
height: f64,
|
||||
) -> Vector4<f64> {
|
||||
let z = window.z;
|
||||
println!("z in window space: {z}");
|
||||
#[rustfmt::skip]
|
||||
let fixed_window = Vector4::new(
|
||||
window.x,
|
||||
window.y,
|
||||
window.z,
|
||||
1.0
|
||||
);
|
||||
|
||||
let ndc = Self::dx_matrix(width, height).invert().unwrap() * fixed_window;
|
||||
|
||||
let w = origin_clip_space.w;
|
||||
|
||||
#[rustfmt::skip]
|
||||
let clip = Vector4::new(
|
||||
ndc.x * w,
|
||||
ndc.y * w,
|
||||
ndc.z * w,
|
||||
w,
|
||||
);
|
||||
|
||||
clip
|
||||
}
|
||||
|
||||
fn window_to_world(
|
||||
window: &Vector3<f64>,
|
||||
view_proj: &Matrix4<f64>,
|
||||
width: f64,
|
||||
height: f64,
|
||||
) -> Vector3<f64> {
|
||||
#[rustfmt::skip]
|
||||
let fixed_window = Vector4::new(
|
||||
window.x,
|
||||
window.y,
|
||||
window.z,
|
||||
1.0
|
||||
);
|
||||
|
||||
let ndc = Self::dx_matrix(width, height).invert().unwrap() * fixed_window;
|
||||
let unprojected = view_proj.invert().unwrap() * ndc;
|
||||
let world = Vector3::new(
|
||||
unprojected.x / unprojected.w,
|
||||
unprojected.y / unprojected.w,
|
||||
unprojected.z / unprojected.w,
|
||||
);
|
||||
world
|
||||
}
|
||||
|
||||
fn window_to_world_nalgebra(
|
||||
window: &Vector3<f64>,
|
||||
view_proj: &Matrix4<f64>,
|
||||
width: f64,
|
||||
height: f64,
|
||||
) -> Vector3<f64> {
|
||||
let pt = Vector4::new(
|
||||
2.0 * (window.x - 0.0) / width - 1.0,
|
||||
2.0 * (window.y - 0.0) / height - 1.0,
|
||||
window.z,
|
||||
1.0,
|
||||
);
|
||||
|
||||
/* // opengl
|
||||
let pt = Vector4::new(
|
||||
2.0 * (window.x - 0.0) / width - 1.0,
|
||||
2.0 * (window.y - 0.0) / height - 1.0,
|
||||
2.0 * window.z - 1.0,
|
||||
1.0,
|
||||
);
|
||||
*/
|
||||
let unprojected_nalgebra = view_proj.invert().unwrap() * pt;
|
||||
let world = Vector3::new(
|
||||
unprojected_nalgebra.x / unprojected_nalgebra.w,
|
||||
unprojected_nalgebra.y / unprojected_nalgebra.w,
|
||||
unprojected_nalgebra.z / unprojected_nalgebra.w,
|
||||
);
|
||||
world
|
||||
}
|
||||
|
||||
pub fn project_screen_to_world(
|
||||
&self,
|
||||
window: &Vector2<f64>,
|
||||
view_proj: &Matrix4<f64>,
|
||||
) -> Vector3<f64> {
|
||||
/* let origin_clip_space = (view_proj * Vector4::new(0.0, 0.0, 0.0, 1.0));
|
||||
|
||||
let origin_window_space =
|
||||
Self::clip_to_window_matrix(&origin_clip_space, self.width, self.height);
|
||||
let reverse_clip = Self::window_to_clip(
|
||||
&Vector3::new(window.x, window.y, origin_window_space.z),
|
||||
&origin_clip_space,
|
||||
self.width,
|
||||
self.height,
|
||||
);*/
|
||||
|
||||
let near_world = Camera::window_to_world(
|
||||
&Vector3::new(window.x, window.y, 0.0),
|
||||
&view_proj,
|
||||
self.width,
|
||||
self.height,
|
||||
);
|
||||
|
||||
let far_world = Camera::window_to_world(
|
||||
&Vector3::new(window.x, window.y, 1.0),
|
||||
&view_proj,
|
||||
self.width,
|
||||
self.height,
|
||||
);
|
||||
|
||||
// for z = 0 in world coordinates
|
||||
let u = -near_world.z / (far_world.z - near_world.z);
|
||||
println!("u: {:?}", u);
|
||||
|
||||
/*let vec = (near_world - far_world).normalize();
|
||||
let znear = 0.1;
|
||||
near_world + znear * vec*/
|
||||
|
||||
near_world + u * (far_world - near_world)
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,83 +300,129 @@ impl Perspective {
|
||||
self.aspect = width as f64 / height as f64;
|
||||
}
|
||||
|
||||
fn calc_matrix(&self) -> cgmath::Matrix4<f64> {
|
||||
pub fn calc_matrix(&self) -> cgmath::Matrix4<f64> {
|
||||
OPENGL_TO_WGPU_MATRIX * cgmath::perspective(self.fovy, self.aspect, self.znear, self.zfar)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use cgmath::{ElementWise, Matrix4, SquareMatrix, Vector3, Vector4};
|
||||
use cgmath::{AbsDiffEq, ElementWise, Matrix4, SquareMatrix, Vector2, Vector3, Vector4};
|
||||
|
||||
use super::{Camera, Perspective};
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let camera = Camera::new((0.0, 5.0, 5000.0), cgmath::Deg(-90.0), cgmath::Deg(-0.0));
|
||||
let width = 1920;
|
||||
let height = 1080;
|
||||
let perspective = Perspective::new(width, height, cgmath::Deg(45.0), 0.1, 100000.0);
|
||||
let projection = perspective;
|
||||
let width = 1920.0;
|
||||
let height = 1080.0;
|
||||
let camera = Camera::new(
|
||||
(0.0, 5.0, 5000.0),
|
||||
cgmath::Deg(-90.0),
|
||||
cgmath::Deg(45.0),
|
||||
width as u32,
|
||||
height as u32,
|
||||
);
|
||||
// 4732.561319582916
|
||||
let perspective = Perspective::new(
|
||||
width as u32,
|
||||
height as u32,
|
||||
cgmath::Deg(45.0),
|
||||
0.1,
|
||||
100000.0,
|
||||
);
|
||||
let view_proj: Matrix4<f64> = camera.calc_view_proj(&perspective);
|
||||
|
||||
let world_pos: Vector4<f64> = Vector4::new(0.0, 0.0, 0.0, 1.0);
|
||||
let clip = view_proj * world_pos;
|
||||
|
||||
let origin_clip_space = view_proj * Vector4::new(0.0, 0.0, 0.0, 1.0);
|
||||
println!("origin w in clip space: {:?}", origin_clip_space.w);
|
||||
|
||||
let world_pos: Vector4<f64> = Vector4::new(2000.0, 2000.0, 0.0, 1.0);
|
||||
println!("world_pos: {:?}", world_pos);
|
||||
let view_proj: Matrix4<f64> = (projection.calc_matrix() * camera.calc_matrix())
|
||||
.cast()
|
||||
.unwrap();
|
||||
println!("clip: {:?}", clip);
|
||||
println!("world_pos: {:?}", view_proj.invert().unwrap() * clip);
|
||||
|
||||
let result = view_proj * world_pos;
|
||||
println!("result: {:?}", result);
|
||||
println!("window: {:?}", Camera::clip_to_window(&clip, width, height));
|
||||
let window = Camera::clip_to_window_matrix(&clip, width, height);
|
||||
println!("window (matrix): {:?}", window);
|
||||
|
||||
// Adopted from: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkViewport.html
|
||||
// and https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/
|
||||
let result_ndc = Vector4::new(
|
||||
result.x / result.w,
|
||||
result.y / result.w,
|
||||
result.z / result.w,
|
||||
result.w,
|
||||
let origin_window_space = Camera::clip_to_window_matrix(&origin_clip_space, width, height);
|
||||
let reverse_clip = Camera::window_to_clip(
|
||||
&Vector3::new(window.x, window.y, origin_window_space.z),
|
||||
&origin_clip_space,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
let reverse_world = view_proj.invert().unwrap() * reverse_clip;
|
||||
|
||||
println!("r clip: {:?}", reverse_clip);
|
||||
println!("r world: {:?}", reverse_world);
|
||||
|
||||
// --------- nalgebra
|
||||
|
||||
let scale = 1.0 / origin_clip_space.w;
|
||||
|
||||
let origin_window_space_nalgebra = Vector3::new(
|
||||
0.0 + (width * (origin_clip_space.x * scale + 1.0) * 0.5),
|
||||
0.0 + (height * (origin_clip_space.y * scale + 1.0) * 0.5),
|
||||
origin_clip_space.z * scale,
|
||||
);
|
||||
println!("r origin (nalgebra): {:?}", origin_window_space_nalgebra);
|
||||
println!(
|
||||
"r world (nalgebra): {:?}",
|
||||
Camera::window_to_world_nalgebra(&window.truncate(), &view_proj, width, height)
|
||||
);
|
||||
// --------
|
||||
|
||||
// pdf trick
|
||||
let near_world = Camera::window_to_world_nalgebra(
|
||||
&Vector3::new(window.x, window.y, 0.0),
|
||||
&view_proj,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
|
||||
let min_depth = 0.0;
|
||||
let max_depth = 1.0;
|
||||
|
||||
let x = 0.0;
|
||||
let y = 0.0;
|
||||
let ox = x + width as f64 / 2.0;
|
||||
let oy = y + height as f64 / 2.0;
|
||||
let oz = min_depth;
|
||||
let px = width as f64;
|
||||
let py = height as f64;
|
||||
let pz = max_depth - min_depth;
|
||||
let xd = result_ndc.x;
|
||||
let yd = result_ndc.y;
|
||||
let zd = result_ndc.z;
|
||||
let screen = Vector3::new(px / 2.0 * xd + ox, py / 2.0 * yd + oy, pz * zd + oz);
|
||||
println!("screen: {:?}", screen);
|
||||
|
||||
// Adapted from: https://docs.microsoft.com/en-us/windows/win32/direct3d9/viewports-and-clipping#viewport-rectangle
|
||||
let direct_x = Matrix4::from_cols(
|
||||
Vector4::new(width as f64 / 2.0, 0.0, 0.0, 0.0),
|
||||
Vector4::new(0.0, height as f64 / 2.0, 0.0, 0.0),
|
||||
Vector4::new(0.0, 0.0, pz, 0.0),
|
||||
Vector4::new(ox, oy, oz, 1.0),
|
||||
let far_world = Camera::window_to_world_nalgebra(
|
||||
&Vector3::new(window.x, window.y, 1.0),
|
||||
&view_proj,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
let screen_hom = direct_x * result;
|
||||
println!("screen_hom: {:?}", screen_hom);
|
||||
let screen = Vector3::new(
|
||||
screen_hom.x / screen_hom.w,
|
||||
screen_hom.y / screen_hom.w,
|
||||
screen_hom.z / screen_hom.w,
|
||||
);
|
||||
println!("screen: {:?}", screen);
|
||||
|
||||
let screen_hom2 = Vector4::new(screen.x, screen.y, 1.0, 1.0) * 5000.0;
|
||||
println!("screen_hom2: {:?}", screen_hom2);
|
||||
let result = direct_x.invert().unwrap() * screen_hom;
|
||||
println!("result screen_hom: {:?}", result);
|
||||
let result = direct_x.invert().unwrap() * screen_hom2;
|
||||
println!("result screen_hom2: {:?}", result);
|
||||
let world_pos = view_proj.invert().unwrap() * result;
|
||||
println!("world_pos: {:?}", world_pos);
|
||||
// for z = 0 in world coordinates
|
||||
let u = -near_world.z / (far_world.z - near_world.z);
|
||||
println!("u: {:?}", u);
|
||||
let unprojected = near_world + u * (far_world - near_world);
|
||||
println!("unprojected: {:?}", unprojected);
|
||||
//assert!(Vector3::new(world_pos.x, world_pos.y, world_pos.z).abs_diff_eq(&unprojected, 0.05));
|
||||
//.------
|
||||
|
||||
// ---- test for unproject
|
||||
|
||||
let window = Vector2::new(960.0, 631.0); // 0, 4096: passt nicht
|
||||
//let window = Vector2::new(962.0, 1.0); // 0, 300: passt nicht
|
||||
//let window = Vector2::new(960.0, 540.0); // 0, 0 passt
|
||||
let near_world = Camera::window_to_world(
|
||||
&Vector3::new(window.x, window.y, 0.0),
|
||||
&view_proj,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
|
||||
let far_world = Camera::window_to_world(
|
||||
&Vector3::new(window.x, window.y, 1.0),
|
||||
&view_proj,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
|
||||
// for z = 0 in world coordinates
|
||||
let u = -near_world.z / (far_world.z - near_world.z);
|
||||
println!("u: {:?}", u);
|
||||
let unprojected = near_world + u * (far_world - near_world);
|
||||
println!("unprojected: {:?}", unprojected);
|
||||
// ----
|
||||
|
||||
//assert!(reverse_world.abs_diff_eq(&world_pos, 0.05))
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
//! the GPU.
|
||||
|
||||
mod buffer_pool;
|
||||
|
||||
mod options;
|
||||
mod piplines;
|
||||
mod shaders;
|
||||
|
||||
@ -260,7 +260,7 @@ impl RenderState {
|
||||
let camera = camera::Camera::new(
|
||||
(0.0, 5.0, 5000.0),
|
||||
cgmath::Deg(-90.0),
|
||||
cgmath::Deg(-0.0),
|
||||
cgmath::Deg(-45.0),
|
||||
size.width,
|
||||
size.height,
|
||||
);
|
||||
@ -268,7 +268,7 @@ impl RenderState {
|
||||
surface_config.width,
|
||||
surface_config.height,
|
||||
cgmath::Deg(45.0),
|
||||
0.1,
|
||||
10.0,
|
||||
100000.0,
|
||||
);
|
||||
|
||||
@ -378,7 +378,7 @@ impl RenderState {
|
||||
"transportation" => [1.0, 0.0, 0.0, 1.0],
|
||||
"building" => [0.0, 1.0, 1.0, 1.0],
|
||||
"boundary" => [0.0, 0.0, 0.0, 1.0],
|
||||
"water" => [0.0, 0.0, 1.0, 1.0],
|
||||
"water" => [0.0, 0.0, 0.7, 1.0],
|
||||
"waterway" => [0.0, 0.0, 1.0, 1.0],
|
||||
_ => [0.0, 0.0, 0.0, 0.0],
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user