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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
//! General graphics-related utility functions. use ::{cgmath, collision, rand}; use ::{rs_utils}; /////////////////////////////////////////////////////////////////////////////// // structs // /////////////////////////////////////////////////////////////////////////////// #[derive(Clone,Debug,PartialEq)] pub struct Pose3d <S : cgmath::BaseFloat> { pub position : cgmath::Point3 <S>, pub yaw : cgmath::Rad <S>, pub pitch : cgmath::Rad <S> // TODO: roll ? } /////////////////////////////////////////////////////////////////////////////// // functions // /////////////////////////////////////////////////////////////////////////////// /// Computes an orientation basis based on given yaw and pitch. pub fn orientation_from_yaw_pitch ( yaw : cgmath::Rad <f32>, pitch : cgmath::Rad <f32> ) -> cgmath::Basis3 <f32> { use cgmath::Rotation3; let heading = cgmath::Basis3::from_angle_z (yaw); cgmath::Basis3::from_axis_angle (heading.as_ref().x, pitch) * heading } /// Clamp a 2D point to the given AABB rectangle, returns true if point was /// modified, or false otherwise if the point is already within the volume. /// /// # Examples /// /// ``` /// # extern crate gl_utils; /// # extern crate cgmath; /// # extern crate collision; /// # fn main () { /// # use gl_utils::graphics::point2d_clamp; /// let mut point = cgmath::Point2::<i32>::new (-1, -1); /// assert!{ /// point2d_clamp ( /// &collision::Aabb2::<i32>::new ((0,0).into(), (10,10).into()), /// &mut point) /// } /// assert_eq!(point, (0,0).into()); /// assert!{ /// !point2d_clamp ( /// &collision::Aabb2::<i32>::new ((-5,-5).into(), (5,5).into()), /// &mut point) /// } /// assert_eq!(point, (0,0).into()); /// let mut point = cgmath::Point2::<f64>::new (-1.0, -1.0); /// assert!{ /// point2d_clamp ( /// &collision::Aabb2::<f64>::new ((0.0,0.0).into(), (10.0,10.0).into()), /// &mut point) /// } /// assert_eq!(point, (0.0,0.0).into()); /// assert!{ /// !point2d_clamp ( /// &collision::Aabb2::<f64>::new ((-5.0,-5.0).into(), (5.0,5.0).into()), /// &mut point) /// } /// assert_eq!(point, (0.0,0.0).into()); /// # } /// ``` pub fn point2d_clamp <S : cgmath::BaseNum> ( aabb : &collision::Aabb2 <S>, point : &mut cgmath::Point2 <S> ) -> bool { use collision::Contains; if !aabb.contains (point) { point.x = rs_utils::numeric::min_partial (point.x, aabb.max.x); point.x = rs_utils::numeric::max_partial (point.x, aabb.min.x); point.y = rs_utils::numeric::min_partial (point.y, aabb.max.y); point.y = rs_utils::numeric::max_partial (point.y, aabb.min.y); true } else { false } } /// Convenience method that calls `cgmath::ortho` on the given `Ortho` struct #[inline] pub fn projection_mat_orthographic <S : cgmath::BaseFloat> ( ortho : &cgmath::Ortho <S> ) -> cgmath::Matrix4 <S> { cgmath::ortho ( ortho.left, ortho.right, ortho.bottom, ortho.top, ortho.near, ortho.far) } /// Convenience method calling `cgmath::perspective` on the given /// `PerspectiveFov` struct. /// /// This will transform points in right-handed camera (view, eye) space /// (negative Z axis into the scene, positive Y axis 'up') into left-handed 4D /// homogenous clip space where the Z axis is reversed with positive Z into the /// screen while X and Y orientations remain unchanged. #[inline] pub fn projection_mat_perspective <S : cgmath::BaseFloat> ( perspective_fov : &cgmath::PerspectiveFov <S> ) -> cgmath::Matrix4 <S> { cgmath::perspective ( perspective_fov.fovy, perspective_fov.aspect, perspective_fov.near, perspective_fov.far) } /// Generate a random point contained in the give AABB /// /// ``` /// # extern crate gl_utils; /// # extern crate cgmath; /// # extern crate collision; /// # extern crate rand; /// # fn main () { /// # use gl_utils::graphics::*; /// use collision::Contains; /// use rand::SeedableRng; /// // random sequence will be the same each time this is run /// let mut rng = rand::XorShiftRng::new_unseeded(); /// let aabb = collision::Aabb3::<f32>::new ( /// [-10.0, -10.0, -10.0].into(), /// [ 10.0, 10.0, 10.0].into()); /// let point = rand_point3d (&mut rng, &aabb); /// assert!(aabb.contains (&point)); /// let point = rand_point3d (&mut rng, &aabb); /// assert!(aabb.contains (&point)); /// let point = rand_point3d (&mut rng, &aabb); /// assert!(aabb.contains (&point)); /// let point = rand_point3d (&mut rng, &aabb); /// assert!(aabb.contains (&point)); /// let point = rand_point3d (&mut rng, &aabb); /// assert!(aabb.contains (&point)); /// # } /// ``` #[inline] pub fn rand_point3d <S, R> (rng : &mut R, aabb : &collision::Aabb3 <S>) -> cgmath::Point3 <S> where S : cgmath::BaseFloat + rand::distributions::range::SampleRange, R : rand::Rng { [ rng.gen_range (aabb.min.x, aabb.max.x), rng.gen_range (aabb.min.y, aabb.max.y), rng.gen_range (aabb.min.z, aabb.max.z) ].into() } /////////////////////////////////////////////////////////////////////////////// // impls // /////////////////////////////////////////////////////////////////////////////// impl <S : cgmath::BaseFloat> Default for Pose3d <S> { fn default() -> Self { use cgmath::{EuclideanSpace, Zero}; Pose3d { position: cgmath::Point3::origin(), yaw: cgmath::Rad::zero(), pitch: cgmath::Rad::zero() } } }