trig.rs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. use crate::consts::PROJECTION_PLANE_WIDTH;
  2. use crate::fp::ToFixedPoint;
  3. use core::f64::consts::PI;
  4. include!(concat!(env!("OUT_DIR"), "/lookup.rs"));
  5. pub const ANGLE_0: i32 = 0;
  6. pub const ANGLE_60: i32 = PROJECTION_PLANE_WIDTH;
  7. pub const ANGLE_30: i32 = ANGLE_60 / 2;
  8. pub const ANGLE_90: i32 = ANGLE_30 * 3;
  9. pub const ANGLE_180: i32 = ANGLE_60 * 3;
  10. pub const ANGLE_270: i32 = ANGLE_90 * 3;
  11. pub const ANGLE_360: i32 = ANGLE_60 * 6;
  12. pub const MAX_RAY_LENGTH: i32 = 2048;
  13. pub const FP_MAX_RAY_LENGTH: i32 = MAX_RAY_LENGTH << 16;
  14. fn clamp(x: i32, min: i32, max: i32) -> i32 {
  15. if x < min {
  16. min
  17. } else if x > max {
  18. max
  19. } else {
  20. x
  21. }
  22. }
  23. pub fn radian(angle: i32) -> f64 {
  24. angle as f64 * PI / ANGLE_180 as f64
  25. }
  26. pub fn cos(degrees: i32) -> i32 {
  27. COS[degrees as usize]
  28. }
  29. pub fn sin(degrees: i32) -> i32 {
  30. SIN[degrees as usize]
  31. }
  32. pub fn tan(degrees: i32) -> i32 {
  33. TAN[degrees as usize]
  34. }
  35. pub fn icos(degrees: i32) -> i32 {
  36. ICOS[degrees as usize]
  37. }
  38. pub fn isin(degrees: i32) -> i32 {
  39. ISIN[degrees as usize]
  40. }
  41. pub fn itan(degrees: i32) -> i32 {
  42. ITAN[degrees as usize]
  43. }
  44. pub fn xstep(degrees: i32) -> i32 {
  45. X_STEP[degrees as usize]
  46. }
  47. pub fn ystep(degrees: i32) -> i32 {
  48. Y_STEP[degrees as usize]
  49. }
  50. pub fn fisheye_correction(degrees: i32) -> i32 {
  51. FISHEYE[degrees as usize]
  52. }
  53. pub fn wall_height(dist: i32) -> i32 {
  54. WALL_HEIGHT[dist.min(MAX_RAY_LENGTH) as usize]
  55. }
  56. #[cfg(test)]
  57. mod tests {
  58. use float_cmp;
  59. use super::*;
  60. // #[test]
  61. // fn test_cos_values() {
  62. // let tests = [
  63. // ("ANGLE_0", ANGLE_0, 1.0),
  64. // ("ANGLE_30", ANGLE_30, 0.8660254),
  65. // ("ANGLE_60", ANGLE_60, 0.5),
  66. // ("ANGLE_90", ANGLE_90, 0.0),
  67. // ("ANGLE_180", ANGLE_180, -1.0),
  68. // ("ANGLE_270", ANGLE_270, 0.0),
  69. // ("ANGLE_360", ANGLE_360, 1.0),
  70. // ];
  71. // for (label, angle, result) in tests {
  72. // println!("cos({label})");
  73. // float_cmp::assert_approx_eq!(f64, cos(angle), result, epsilon = 0.00000003, ulps = 2);
  74. // }
  75. // }
  76. // #[test]
  77. // fn test_sin_values() {
  78. // let tests = [
  79. // ("ANGLE_0", ANGLE_0, 0.0),
  80. // ("ANGLE_30", ANGLE_30, 0.5),
  81. // ("ANGLE_60", ANGLE_60, 0.8660254),
  82. // ("ANGLE_90", ANGLE_90, 1.0),
  83. // ("ANGLE_180", ANGLE_180, 0.0),
  84. // ("ANGLE_270", ANGLE_270, -1.0),
  85. // ("ANGLE_360", ANGLE_360, 0.0),
  86. // ];
  87. // for (label, angle, result) in tests {
  88. // println!("sin({label})");
  89. // float_cmp::assert_approx_eq!(f64, sin(angle), result, epsilon = 0.00000003, ulps = 2);
  90. // }
  91. // }
  92. // #[test]
  93. // fn test_tan_values() {
  94. // let tests = [
  95. // ("ANGLE_0", ANGLE_0, 0.0),
  96. // ("ANGLE_30", ANGLE_30, 0.577350269),
  97. // ("ANGLE_60", ANGLE_60, 1.732050808),
  98. // ("ANGLE_90", ANGLE_90, f64::INFINITY),
  99. // ("ANGLE_180", ANGLE_180, 0.0),
  100. // ("ANGLE_270", ANGLE_270, f64::NEG_INFINITY),
  101. // ("ANGLE_360", ANGLE_360, 0.0),
  102. // ];
  103. // for (label, angle, result) in tests {
  104. // println!("tan({label})");
  105. // float_cmp::assert_approx_eq!(f64, tan(angle), result, epsilon = 0.00000003, ulps = 2);
  106. // }
  107. // }
  108. // #[test]
  109. // fn test_icos_values() {
  110. // let tests = [
  111. // ("ANGLE_0", ANGLE_0, 1.0),
  112. // ("ANGLE_30", ANGLE_30, 1.154700538),
  113. // ("ANGLE_60", ANGLE_60, 2.0),
  114. // ("ANGLE_90", ANGLE_90, f64::INFINITY),
  115. // ("ANGLE_180", ANGLE_180, -1.0),
  116. // ("ANGLE_270", ANGLE_270, f64::INFINITY),
  117. // ("ANGLE_360", ANGLE_360, 1.0),
  118. // ];
  119. // for (label, angle, result) in tests {
  120. // println!("icos({label})");
  121. // float_cmp::assert_approx_eq!(f64, icos(angle), result, epsilon = 0.00000003, ulps = 2);
  122. // }
  123. // }
  124. // #[test]
  125. // fn test_isin_values() {
  126. // let tests = [
  127. // ("ANGLE_0", ANGLE_0, f64::INFINITY),
  128. // ("ANGLE_30", ANGLE_30, 2.0),
  129. // ("ANGLE_60", ANGLE_60, 1.154700538),
  130. // ("ANGLE_90", ANGLE_90, 1.0),
  131. // ("ANGLE_180", ANGLE_180, f64::INFINITY),
  132. // ("ANGLE_270", ANGLE_270, -1.0),
  133. // ("ANGLE_360", ANGLE_360, f64::INFINITY),
  134. // ];
  135. // for (label, angle, result) in tests {
  136. // println!("isin({label})");
  137. // float_cmp::assert_approx_eq!(f64, isin(angle), result, epsilon = 0.00000003, ulps = 2);
  138. // }
  139. // }
  140. // #[test]
  141. // fn test_itan_values() {
  142. // let tests = [
  143. // ("ANGLE_0", ANGLE_0, f64::INFINITY),
  144. // ("ANGLE_30", ANGLE_30, 1.732050808),
  145. // ("ANGLE_60", ANGLE_60, 0.577350269),
  146. // ("ANGLE_90", ANGLE_90, 0.0),
  147. // ("ANGLE_180", ANGLE_180, f64::NEG_INFINITY),
  148. // ("ANGLE_270", ANGLE_270, 0.0),
  149. // ("ANGLE_360", ANGLE_360, f64::INFINITY),
  150. // ];
  151. // for (label, angle, result) in tests {
  152. // println!("itan({label})");
  153. // float_cmp::assert_approx_eq!(f64, itan(angle), result, epsilon = 0.00000003, ulps = 2);
  154. // }
  155. // }
  156. }