@@ -7,8 +7,8 @@ use crate::math::{
77 Angle , Vec3 , orient_z, rotate_x, rotate_y, spherical, translate, turns,
88} ;
99use crate :: math:: {
10- Lerp , Mat4 , Point3 , ProjMat3 , SphericalVec , Vary , mat :: RealToReal ,
11- orthographic , perspective, pt2, viewport,
10+ Lerp , Mat3 , Mat4 , Point3 , ProjMat3 , SphericalVec , Vary , orthographic ,
11+ perspective, pt2, rotate_z , viewport,
1212} ;
1313use crate :: util:: { Dims , rect:: Rect } ;
1414
@@ -67,34 +67,44 @@ pub struct Camera<Tf> {
6767///
6868/// This is the familiar "FPS" movement mode, based on camera
6969/// position and heading (look-at vector).
70- #[ derive( Copy , Clone , Debug ) ]
70+ #[ derive( Copy , Clone , Debug , Default ) ]
7171pub struct FirstPerson {
7272 /// Current position of the camera in **world** space.
7373 pub pos : Point3 < World > ,
7474 /// Current heading of the camera in **world** space.
7575 pub heading : SphericalVec < World > ,
7676}
7777
78- pub type ViewToWorld = RealToReal < 3 , View , World > ;
79-
80- /// Creates a unit `SphericalVec` from azimuth and altitude.
81- #[ cfg( feature = "fp" ) ]
82- fn az_alt < B > ( az : Angle , alt : Angle ) -> SphericalVec < B > {
83- spherical ( 1.0 , az, alt)
84- }
8578/// Orbiting camera transform.
8679///
8780/// Keeps the camera centered on a **world-space** point, and allows free
8881/// 360°/180° azimuth/altitude rotation around that point as well as setting
8982/// the distance from the point.
90- #[ derive( Copy , Clone , Debug ) ]
83+ #[ derive( Copy , Clone , Debug , Default ) ]
9184pub struct Orbit {
9285 /// The camera's target point in **world** space.
9386 pub target : Point3 < World > ,
9487 /// The camera's direction in **world** space.
9588 pub dir : SphericalVec < World > ,
9689}
9790
91+ /// Camera transform implementing airplane-like controls based on three angles.
92+ ///
93+ /// The pitch (elevation) angle controls rotation about the local lateral (x)
94+ /// axis, the yaw (bearing) angle about the local vertical (y) axis, and the
95+ /// roll (bank) angle about the local longitudinal (z) axis.
96+ #[ derive( Copy , Clone , Debug , Default ) ]
97+ pub struct PitchYawRoll {
98+ pub rot : Mat4 < View , World > ,
99+ pub trans : Vec3 < World > ,
100+ }
101+
102+ /// Creates a unit `SphericalVec` from azimuth and altitude.
103+ #[ cfg( feature = "fp" ) ]
104+ fn az_alt < B > ( az : Angle , alt : Angle ) -> SphericalVec < B > {
105+ spherical ( 1.0 , az, alt)
106+ }
107+
98108//
99109// Inherent impls
100110//
@@ -240,10 +250,7 @@ impl FirstPerson {
240250 /// Creates a first-person transform with position in the origin
241251 /// and heading in the direction of the positive x-axis.
242252 pub fn new ( ) -> Self {
243- Self {
244- pos : Point3 :: origin ( ) ,
245- heading : az_alt ( turns ( 0.0 ) , turns ( 0.0 ) ) ,
246- }
253+ Self :: default ( )
247254 }
248255
249256 /// Rotates the camera to center the view on a **world-space** point.
@@ -282,6 +289,11 @@ impl FirstPerson {
282289
283290#[ cfg( feature = "fp" ) ]
284291impl Orbit {
292+ /// TODO
293+ pub fn new ( ) -> Self {
294+ Self :: default ( )
295+ }
296+
285297 /// Adds the azimuth and altitude to the camera's current direction.
286298 ///
287299 /// Wraps the resulting azimuth to [-180°, 180°) and clamps the altitude to [-90°, 90°].
@@ -329,10 +341,59 @@ impl Orbit {
329341 }
330342}
331343
344+ #[ cfg( feature = "fp" ) ]
345+ impl PitchYawRoll {
346+ /// TODO
347+ pub fn new ( ) -> Self {
348+ Self :: default ( )
349+ }
350+
351+ /// Moves the camera position in view space.
352+ pub fn translate ( & mut self , v : Vec3 < View > ) {
353+ self . trans += self . view_to_world ( ) . apply ( & v) ;
354+ }
355+
356+ /// Moves the camera to the given position in world space.
357+ pub fn translate_to ( & mut self , pt : Point3 < World > ) {
358+ self . trans = pt. to_vec ( ) ;
359+ }
360+
361+ /// Returns the matrix from view to world space.
362+ fn view_to_world ( & self ) -> Mat4 < View , World > {
363+ let trans: Mat4 < World , World > = translate ( self . trans . to ( ) ) . to ( ) ;
364+ let rot = self . rot ;
365+ rot. then ( & trans)
366+ }
367+
368+ /// Adjusts the orientation of the camera by the given delta angles.
369+ pub fn rotate ( & mut self , pitch : Angle , yaw : Angle , roll : Angle ) {
370+ let p = rotate_x ( pitch) ;
371+ let y = rotate_y ( yaw) ;
372+ let r = rotate_z ( roll) ;
373+ let delta_rot: Mat4 < View , View > = p. then ( & y) . then ( & r) . to ( ) ;
374+
375+ self . rot = self . rot . compose ( & delta_rot) ;
376+ }
377+
378+ /// Sets the orientation of the camera to the given **world-space** angles.
379+ pub fn rotate_to ( & mut self , pitch : Angle , yaw : Angle , roll : Angle ) {
380+ let p = rotate_x ( pitch) ;
381+ let y = rotate_y ( yaw) ;
382+ let r = rotate_z ( roll) ;
383+ self . rot = p. then ( & y) . then ( & r) . to ( ) ;
384+ }
385+ }
386+
332387//
333388// Local trait impls
334389//
335390
391+ impl Transform for Mat4 < World , View > {
392+ fn world_to_view ( & self ) -> Mat4 < World , View > {
393+ * self
394+ }
395+ }
396+
336397#[ cfg( feature = "fp" ) ]
337398impl Transform for FirstPerson {
338399 fn world_to_view ( & self ) -> Mat4 < World , View > {
@@ -366,31 +427,12 @@ impl Transform for Orbit {
366427 }
367428}
368429
369- impl Transform for Mat4 < World , View > {
430+ impl Transform for PitchYawRoll {
370431 fn world_to_view ( & self ) -> Mat4 < World , View > {
371- * self
372- }
373- }
374-
375- //
376- // Foreign trait impls
377- //
432+ let trans = translate ( -self . trans . to ( ) ) . to ( ) ;
433+ let rot = self . rot . transpose ( ) ;
378434
379- #[ cfg( feature = "fp" ) ]
380- impl Default for FirstPerson {
381- /// Returns [`FirstPerson::new`].
382- fn default ( ) -> Self {
383- Self :: new ( )
384- }
385- }
386-
387- #[ cfg( feature = "fp" ) ]
388- impl Default for Orbit {
389- fn default ( ) -> Self {
390- Self {
391- target : Point3 :: default ( ) ,
392- dir : az_alt ( turns ( 0.0 ) , turns ( 0.0 ) ) ,
393- }
435+ trans. then ( & rot)
394436 }
395437}
396438
0 commit comments