1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
use na::{self, Real, U3}; use aliases::{TVec2, TVec3, TVec4, TMat4}; /// Define a picking region. /// /// # Parameters /// * `center` - Specify the center of a picking region in window coordinates. /// * `delta` - Specify the width and height, respectively, of the picking region in window coordinates. /// * `viewport` - Rendering viewport pub fn pick_matrix<N: Real>(center: &TVec2<N>, delta: &TVec2<N>, viewport: &TVec4<N>) -> TMat4<N> { let shift = TVec3::new( (viewport.z - (center.x - viewport.x) * na::convert(2.0)) / delta.x, (viewport.w - (center.y - viewport.y) * na::convert(2.0)) / delta.y, N::zero() ); let result = TMat4::new_translation(&shift); result.prepend_nonuniform_scaling(&TVec3::new(viewport.z / delta.x, viewport.w / delta.y, N::one())) } /// Map the specified object coordinates `(obj.x, obj.y, obj.z)` into window coordinates using OpenGL near and far clip planes definition. /// /// # Parameters /// * `obj` - Specify the object coordinates. /// * `model` - Specifies the current modelview matrix. /// * `proj` - Specifies the current projection matrix. /// * `viewport` - Specifies the current viewport. pub fn project<N: Real>(obj: &TVec3<N>, model: &TMat4<N>, proj: &TMat4<N>, viewport: TVec4<N>) -> TVec3<N> { project_no(obj, model, proj, viewport) } /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates. /// /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) /// /// # Parameters /// * `obj` - Specify the object coordinates. /// * `model` - Specifies the current modelview matrix. /// * `proj` - Specifies the current projection matrix. /// * `viewport` - Specifies the current viewport. pub fn project_no<N: Real>(obj: &TVec3<N>, model: &TMat4<N>, proj: &TMat4<N>, viewport: TVec4<N>) -> TVec3<N> { let proj = project_zo(obj, model, proj, viewport); TVec3::new(proj.x, proj.y, proj.z * na::convert(0.5) + na::convert(0.5)) } /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates. /// /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) /// /// # Parameters /// * `obj` - Specify the object coordinates. /// * `model` - Specifies the current modelview matrix. /// * `proj` - Specifies the current projection matrix. /// * `viewport` - Specifies the current viewport. pub fn project_zo<N: Real>(obj: &TVec3<N>, model: &TMat4<N>, proj: &TMat4<N>, viewport: TVec4<N>) -> TVec3<N> { let normalized = proj * model * TVec4::new(obj.x, obj.y, obj.z, N::one()); let scale = N::one() / normalized.w; TVec3::new( viewport.x + (viewport.z * (normalized.x * scale + N::one()) * na::convert(0.5)), viewport.y + (viewport.w * (normalized.y * scale + N::one()) * na::convert(0.5)), normalized.z * scale, ) } /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates using OpenGL near and far clip planes definition. /// /// # Parameters /// * `obj` - Specify the window coordinates to be mapped. /// * `model` - Specifies the current modelview matrix. /// * `proj` - Specifies the current projection matrix. /// * `viewport` - Specifies the current viewport. pub fn unproject<N: Real>(win: &TVec3<N>, model: &TMat4<N>, proj: &TMat4<N>, viewport: TVec4<N>) -> TVec3<N> { unproject_no(win, model, proj, viewport) } /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates. /// /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) /// /// # Parameters /// * `obj` - Specify the window coordinates to be mapped. /// * `model` - Specifies the current modelview matrix. /// * `proj` - Specifies the current projection matrix. /// * `viewport` - Specifies the current viewport. pub fn unproject_no<N: Real>(win: &TVec3<N>, model: &TMat4<N>, proj: &TMat4<N>, viewport: TVec4<N>) -> TVec3<N> { let _2: N = na::convert(2.0); let transform = (proj * model).try_inverse().unwrap_or_else(TMat4::zeros); let pt = TVec4::new( _2 * (win.x - viewport.x) / viewport.z - N::one(), _2 * (win.y - viewport.y) / viewport.w - N::one(), _2 * win.z - N::one(), N::one(), ); let result = transform * pt; result.fixed_rows::<U3>(0) / result.w } /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates. /// /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) /// /// # Parameters /// * `obj` - Specify the window coordinates to be mapped. /// * `model` - Specifies the current modelview matrix. /// * `proj` - Specifies the current projection matrix. /// * `viewport` - Specifies the current viewport. pub fn unproject_zo<N: Real>(win: &TVec3<N>, model: &TMat4<N>, proj: &TMat4<N>, viewport: TVec4<N>) -> TVec3<N> { let _2: N = na::convert(2.0); let transform = (proj * model).try_inverse().unwrap_or_else(TMat4::zeros); let pt = TVec4::new( _2 * (win.x - viewport.x) / viewport.z - N::one(), _2 * (win.y - viewport.y) / viewport.w - N::one(), win.z, N::one(), ); let result = transform * pt; result.fixed_rows::<U3>(0) / result.w }