Skip to content

Commit 50e668b

Browse files
committed
Test.NativeLaunch: Implement a kinda clunky zoom/pan
- zoom middle mouse scroll - pan: left shift + middle mouse button drag (same as blender)
1 parent 4b01a09 commit 50e668b

File tree

2 files changed

+110
-8
lines changed

2 files changed

+110
-8
lines changed

Test.NativeLaunch/src/main.rs

Lines changed: 97 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ another is that its much easier to change that than a binary file.
7575
*/
7676

7777
use std::ptr::null_mut;
78+
use std::sync::Mutex;
7879
use std::{path::PathBuf, time::SystemTime};
7980

8081
use glam::Vec3;
@@ -140,20 +141,80 @@ mod render;
140141
mod d3d11_utilfn;
141142
mod util;
142143

143-
unsafe extern "system"
144-
fn wnd_proc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
144+
145+
static WINEVENTS: Mutex<Vec<WinEvent>> = Mutex::new(vec![]);
146+
fn add_winevent(evt:WinEvent) {
147+
{
148+
match WINEVENTS.lock() {
149+
Ok(mut lck) => {
150+
lck.push(evt);
151+
},
152+
Err(e) => eprintln!("failed to lock winevents: {:?}", e)
153+
}
154+
}
155+
}
156+
157+
158+
enum WinEvent {
159+
MouseWheel(i16),
160+
MousePan(i16, i16),
161+
}
162+
163+
fn get_x_lparam(lparam: LPARAM) -> i16 {
164+
(lparam & 0xFFFF) as i16
165+
}
166+
167+
fn get_y_lparam(lparam: LPARAM) -> i16 {
168+
((lparam >> 16) & 0xFFFF) as i16
169+
}
170+
171+
unsafe extern "system" fn wnd_proc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
145172
// println!("wnd proc: {:x}", msg);
146173

174+
static mut LAST_MOUSE_POS: (i16, i16) = (0, 0);
175+
static mut MOUSE_PAN_ACTIVE: bool = false;
176+
147177
match msg {
148178
WM_DESTROY => {
149179
//println!("destroy");
150180
PostQuitMessage(0);
151181
//println!("post quit message");
152182
0
153-
},
154-
_ => {
155-
DefWindowProcW(hwnd, msg, wparam, lparam)
156183
}
184+
// Handling the mouse wheel event
185+
winapi::um::winuser::WM_MOUSEWHEEL => {
186+
let delta = winapi::um::winuser::GET_WHEEL_DELTA_WPARAM(wparam) as i16;
187+
add_winevent(WinEvent::MouseWheel(delta));
188+
0
189+
}
190+
winapi::um::winuser::WM_MOUSEMOVE => {
191+
if MOUSE_PAN_ACTIVE {
192+
let x_pos = get_x_lparam(lparam);
193+
let y_pos = get_y_lparam(lparam);
194+
195+
let delta_x = x_pos.saturating_sub(LAST_MOUSE_POS.0 as i16);
196+
let delta_y = y_pos.saturating_sub(LAST_MOUSE_POS.1 as i16);
197+
198+
add_winevent(WinEvent::MousePan(delta_x as i16, delta_y as i16));
199+
LAST_MOUSE_POS = (x_pos as i16, y_pos as i16);
200+
}
201+
0
202+
}
203+
winapi::um::winuser::WM_MBUTTONDOWN => {
204+
if winapi::um::winuser::GetKeyState(winapi::um::winuser::VK_SHIFT) < 0 {
205+
MOUSE_PAN_ACTIVE = true;
206+
LAST_MOUSE_POS = (
207+
get_x_lparam(lparam),
208+
get_y_lparam(lparam),
209+
);
210+
}
211+
0
212+
}
213+
winapi::um::winuser::WM_MBUTTONUP => {
214+
MOUSE_PAN_ACTIVE = false;
215+
0
216+
}
217+
_ => DefWindowProcW(hwnd, msg, wparam, lparam),
157218
}
158219
}
159220

@@ -926,6 +987,8 @@ unsafe fn runapp() -> anyhow::Result<()> {
926987
let mut total_dip_calls = 0;
927988
let mut info_start = SystemTime::now();
928989
let mut removed_once = false;
990+
let mut zoom: i16 = 0;
991+
let (mut pan_x, mut pan_y): (i16, i16) = (0,0);
929992
while !done {
930993
if SystemTime::now().duration_since(info_start).expect("whatever").as_secs() >= 1 {
931994
println!("dip calls: {}, prim/vert count: {:?}", dip_calls, (prim_count,vert_count));
@@ -965,9 +1028,35 @@ unsafe fn runapp() -> anyhow::Result<()> {
9651028
if done {
9661029
break;
9671030
}
1031+
9681032
let now = SystemTime::now();
9691033
let _elapsed = now.duration_since(start).expect("whatever").as_millis();
9701034

1035+
1036+
{
1037+
match WINEVENTS.lock() {
1038+
Ok(mut evts) => {
1039+
for e in evts.iter() {
1040+
match e {
1041+
WinEvent::MouseWheel(delta) => {
1042+
zoom = zoom.saturating_add(*delta * 10);
1043+
//println!("zoom {}", zoom);
1044+
},
1045+
WinEvent::MousePan(x, y) => {
1046+
pan_x = pan_x.saturating_add( (- *x * 50) as i16 );
1047+
pan_y = pan_y.saturating_add( (- *y * 50) as i16 );
1048+
1049+
//println!("pan: {pan_x},{pan_y}")
1050+
}
1051+
}
1052+
}
1053+
evts.clear();
1054+
},
1055+
Err(e) => eprintln!("failed to lock winevents: {:?}", e)
1056+
}
1057+
}
1058+
1059+
9711060
// if the sync interval in present below is > than zero this will slow down the dip rate to
9721061
// the something like the refresh rate of display or some safe value like 30/sec
9731062
let mut do_present = true;
@@ -1006,7 +1095,7 @@ unsafe fn runapp() -> anyhow::Result<()> {
10061095
let rotation = Vec3::new(rx, ry, rz);
10071096
(rotation,origin)
10081097
} else {
1009-
let origin = Vec3::new(0.0, 1.0, 0.0);
1098+
let origin = Vec3::new(0.0, 2.0, 0.0);
10101099
let rz = 0.0;
10111100
let rotation = Vec3::new(rx, ry, rz);
10121101
(rotation,origin)
@@ -1021,6 +1110,8 @@ unsafe fn runapp() -> anyhow::Result<()> {
10211110
prepare_shader_constants(
10221111
context,
10231112
rend_data,
1113+
zoom,
1114+
(pan_x,pan_y),
10241115
origin,
10251116
eye,
10261117
rotation,

Test.NativeLaunch/src/render.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ pub unsafe fn create_data(device:*mut ID3D11Device) -> anyhow::Result<RendData>
6262
/// - A 4x4 matrix (`Mat4`) representing the MVP transformation.
6363
6464
pub fn generate_mvp_matrix(
65+
zoom: i16,
66+
pan: (i16,i16),
6567
origin: Vec3,
6668
eye: Vec3,
6769
rotation_radians: Vec3,
@@ -79,7 +81,14 @@ pub fn generate_mvp_matrix(
7981
);
8082

8183

82-
let model = Mat4::from_rotation_translation(rotation, Vec3::ZERO);
84+
let zoom_normalized = 1.0 + zoom as f32 / i16::MAX as f32;
85+
let scale_factor = zoom_normalized * 2.0;
86+
let scale_matrix = Mat4::from_scale(Vec3::splat(scale_factor));
87+
88+
let pan_x = pan.0 as f32 / i16::MAX as f32 * 2.0; // Range from -2.0 to 2.0
89+
let pan_y = pan.1 as f32 / i16::MAX as f32 * 2.0; // Range from -2.0 to 2.0
90+
let pan_translation = Vec3::new(pan_x, pan_y, 0.0);
91+
let model = Mat4::from_rotation_translation(rotation, pan_translation) * scale_matrix;
8392

8493
let col0 = model.x_axis.truncate(); // Vec3 from first column
8594
let col1 = model.y_axis.truncate(); // Vec3 from second column
@@ -104,6 +113,8 @@ pub fn generate_mvp_matrix(
104113
pub unsafe fn prepare_shader_constants(
105114
context: *mut ID3D11DeviceContext,
106115
shape_data:&RendData,
116+
zoom: i16,
117+
pan: (i16,i16),
107118
origin: Vec3,
108119
eye: Vec3,
109120
rotation: Vec3,
@@ -115,7 +126,7 @@ pub unsafe fn prepare_shader_constants(
115126
has_tex0: bool,
116127
) -> anyhow::Result<()> {
117128
// 1. Compute the MVP matrix
118-
let (mvp, normal_mat) = generate_mvp_matrix(origin, eye, rotation, aspect_ratio, fov_y_radians, z_near, z_far);
129+
let (mvp, normal_mat) = generate_mvp_matrix(zoom, pan, origin, eye, rotation, aspect_ratio, fov_y_radians, z_near, z_far);
119130

120131
// 2. No transpose needed unless your shader uses 'row_major'
121132
// If needed, use: let mvp = mvp.transpose();

0 commit comments

Comments
 (0)