ue_types/
vector.rs

1//! Vector types and utilities
2
3use crate::BinarySerializable;
4use glam::{Vec2, Vec3, Vec4};
5
6/// 3D Vector representing position, velocity, direction, etc.
7/// This is the most commonly used vector type in UE.
8pub type Vector = Vec3;
9
10/// 2D Vector for UI coordinates, texture coordinates, etc.
11pub type Vector2D = Vec2;
12
13/// 4D Vector for homogeneous coordinates, RGBA colors, etc.
14pub type Vector4 = Vec4;
15
16/// Quaternion for rotations (preferred over Rotator for math operations)
17pub type Quaternion = glam::Quat;
18
19/// 3x3 Matrix
20pub type Matrix3 = glam::Mat3;
21
22/// 4x4 Matrix for transformations
23pub type Matrix4 = glam::Mat4;
24
25// Implement BinarySerializable for glam types
26impl BinarySerializable for Vector {}
27impl BinarySerializable for Vector2D {}
28impl BinarySerializable for Vector4 {}
29impl BinarySerializable for Quaternion {}
30impl BinarySerializable for Matrix3 {}
31impl BinarySerializable for Matrix4 {}
32
33/// UE-style vector constants and utility functions
34pub struct VectorConstants;
35
36impl VectorConstants {
37    /// Forward vector (positive X)
38    pub const FORWARD: Vector = Vec3::X;
39    
40    /// Right vector (positive Y)  
41    pub const RIGHT: Vector = Vec3::Y;
42    
43    /// Up vector (positive Z)
44    pub const UP: Vector = Vec3::Z;
45    
46    /// Zero vector
47    pub const ZERO: Vector = Vec3::ZERO;
48    
49    /// One vector (1, 1, 1)
50    pub const ONE: Vector = Vec3::ONE;
51}
52
53/// Extension trait for Vector operations common in UE
54pub trait VectorExt {
55    /// Get the size (magnitude) of the vector
56    fn size(self) -> f32;
57    
58    /// Get the squared size (magnitude squared) - faster than size()
59    fn size_squared(self) -> f32;
60    
61    /// Check if the vector is nearly zero
62    fn is_nearly_zero(self, tolerance: f32) -> bool;
63    
64    /// Check if the vector is normalized (unit length)
65    fn is_normalized(self) -> bool;
66    
67    /// Get a normalized copy of the vector
68    fn get_safe_normal(self, tolerance: f32) -> Vector;
69}
70
71impl VectorExt for Vector {
72    fn size(self) -> f32 {
73        self.length()
74    }
75    
76    fn size_squared(self) -> f32 {
77        self.length_squared()
78    }
79    
80    fn is_nearly_zero(self, tolerance: f32) -> bool {
81        self.length_squared() <= tolerance * tolerance
82    }
83    
84    fn is_normalized(self) -> bool {
85        (self.length_squared() - 1.0).abs() < 0.01
86    }
87    
88    fn get_safe_normal(self, tolerance: f32) -> Vector {
89        let square_sum = self.length_squared();
90        if square_sum == 1.0 {
91            return self;
92        } else if square_sum < tolerance * tolerance {
93            return Vector::ZERO;
94        }
95        self.normalize()
96    }
97}
98
99/// Extension trait for Vector2D operations
100pub trait Vector2DExt {
101    /// Get the size (magnitude) of the 2D vector
102    fn size(self) -> f32;
103    
104    /// Get the squared size (magnitude squared)
105    fn size_squared(self) -> f32;
106    
107    /// Check if the vector is nearly zero
108    fn is_nearly_zero(self, tolerance: f32) -> bool;
109}
110
111impl Vector2DExt for Vector2D {
112    fn size(self) -> f32 {
113        self.length()
114    }
115    
116    fn size_squared(self) -> f32 {
117        self.length_squared()
118    }
119    
120    fn is_nearly_zero(self, tolerance: f32) -> bool {
121        self.length_squared() <= tolerance * tolerance
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use super::*;
128
129    #[test]
130    fn test_vector_constants() {
131        assert_eq!(VectorConstants::FORWARD, Vec3::new(1.0, 0.0, 0.0));
132        assert_eq!(VectorConstants::RIGHT, Vec3::new(0.0, 1.0, 0.0));
133        assert_eq!(VectorConstants::UP, Vec3::new(0.0, 0.0, 1.0));
134    }
135
136    #[test]
137    fn test_vector_ext() {
138        let v = Vector::new(3.0, 4.0, 0.0);
139        assert_eq!(v.size(), 5.0);
140        assert_eq!(v.size_squared(), 25.0);
141        assert!(!v.is_nearly_zero(0.1));
142        
143        let normalized = v.get_safe_normal(0.001);
144        assert!(normalized.is_normalized());
145    }
146}