ulfben

ArduboyLUTs (float)

Mar 8th, 2020
170
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //CONSTANTS are from: https://github.com/ulfben/ArduboyRayCaster/blob/master/Config.h
  2.  
  3. // tangent tables equivalent to slopes, used to compute initial intersections with ray
  4. std::array<float, ANGLE_360> tan_table;
  5. std::array<float, ANGLE_360> inv_tan_table;
  6.  
  7. // step tables used to find next intersection, equivalent to slopes times width and height of cell    
  8. std::array<float, ANGLE_360> y_step;
  9. std::array<float, ANGLE_360> x_step;
  10.  
  11. // 1/cos and 1/sin tables used to compute distance of intersection very quickly  
  12. // Optimization: cos(X) == sin(X+90), so for cos lookups we can simply re-use the sin-table with an offset of ANGLE_90.    
  13. std::array<float, ANGLE_360 + ANGLE_90> inv_sin_table; //+90 degrees to make room for the tail-end of the offset cos values.    
  14. float* inv_cos_table = &inv_sin_table[ANGLE_90]; //cos(X) == sin(X+90).    
  15.  
  16. // cos table used to fix view distortion caused by radial projection (eg: cancel out fishbowl effect)
  17. std::array<float, HALF_FOV_ANGLE * 2> cos_table;
  18.    
  19. constexpr inline bool isFacingLeft(const int view_angle) const noexcept {
  20.     return (view_angle >= ANGLE_90 && view_angle < ANGLE_270);
  21. }
  22. constexpr inline bool isFacingRight(const int view_angle) const noexcept {
  23.     return (view_angle < ANGLE_90 || view_angle >= ANGLE_270);
  24. }
  25. constexpr inline bool isFacingDown(const int view_angle) const noexcept {
  26.     return (view_angle >= ANGLE_0 && view_angle < ANGLE_180);
  27. }
  28. constexpr inline bool isFacingUp(const int view_angle) const noexcept {
  29.     return (view_angle >= ANGLE_180 && view_angle < ANGLE_360);
  30. }
  31.  
  32. void buildLookupTables() noexcept {
  33.     constexpr auto TENTH_OF_A_RADIAN = ANGLE_TO_RADIANS * 0.1f;      
  34.     for (int ang = ANGLE_0; ang < ANGLE_360; ang++) {
  35.         const auto rad_angle = TENTH_OF_A_RADIAN + (ang * ANGLE_TO_RADIANS); //adding a small offset to avoid edge cases with 0.
  36.         tan_table[ang] = std::tan(rad_angle);
  37.         inv_tan_table[ang] = 1.0f / tan_table[ang];
  38.         inv_sin_table[ang] = 1.0f / std::sin(rad_angle);
  39.  
  40.         // tangent has the incorrect signs in all quadrants except 1, so manually fix the signs of each quadrant.
  41.         if (isFacingDown(ang)) {
  42.             y_step[ang] = std::abs(tan_table[ang] * CELL_SIZE);
  43.         } else {
  44.             assert(isFacingUp(ang) && "isFacingUp() should be the exact inverse of isFacingDown(). Have you changed the coordinate system?");
  45.             y_step[ang] = -std::abs(tan_table[ang] * CELL_SIZE);
  46.         }
  47.         if (isFacingLeft(ang)) {
  48.             x_step[ang] = -std::abs(inv_tan_table[ang] * CELL_SIZE);
  49.         } else {
  50.             assert(isFacingRight(ang) && "isFacingRight() should be the exact inverse of isFacingDown(). Have you changed the coordinate system?");
  51.             x_step[ang] = std::abs(inv_tan_table[ang] * CELL_SIZE);
  52.         }
  53.         assert(std::fabs(y_step[ang]) != 0.0f && "Potential asymtotic ray on the y-axis produced while building lookup tables.");
  54.         assert(std::fabs(x_step[ang]) != 0.0f && "Potential asymtotic ray on the x-axis produced while building lookup tables.");            
  55.     }
  56.  
  57.     //duplicate the first 90 sin values at the end of the array, to complete the joint sin & cos lookup table.
  58.     auto end = std::end(inv_sin_table) - ANGLE_90;
  59.     std::copy_n(std::begin(inv_sin_table), ANGLE_90, end);
  60.  
  61.     // create view filter table. Without this we would see a fishbowl effect. There is a cosine wave modulated on top of the view distance as a side effect of casting from a fixed point.
  62.     // to cancel this effect out, we multiple by the inverse of the cosine and the result is the proper scale.
  63.     // inverse cosine would be 1/cos(rad_angle), but 1 is too small to give us good sized slivers, hence the constant K which is arbitrarily chosen for what looks good.
  64.     for (int ang = -HALF_FOV_ANGLE; ang < HALF_FOV_ANGLE; ang++) {
  65.         const auto rad_angle = TENTH_OF_A_RADIAN + (ang * ANGLE_TO_RADIANS);
  66.         const auto index = ang + HALF_FOV_ANGLE;
  67.         cos_table[index] = (K / std::cos(rad_angle));
  68.     }
  69. }
  70.  
  71. template <class Container>
  72. [[nodiscard]] std::string join(const Container values, std::string delimiter = ","s){
  73.     using T = typename Container::value_type;    
  74.     return std::accumulate(
  75.         std::begin(values),  
  76.         std::end(values),
  77.         std::string(),
  78.         [delimiter](std::string a, T b) -> std::string {
  79.             std::string delim(a.length() > 0 ? delimiter : ""s);
  80.             return a + delim + std::to_string(b);
  81.     });
  82. }
  83.  
  84. template<typename T>
  85. void printTableDefinition(const char* name, const T table, const size_t size) const noexcept {        
  86.     //std::cout << "std::array<float, " << size << "> " << name << "{\n"; //PC
  87.     std::cout << "constexpr float " << name << "[" << size << "] PROGMEM {\n"; //ArduBoy
  88.     std::cout << "\t" << join(table, size, "f,");
  89.     std::cout << "f};\n";
  90. }
  91.  
  92. void prettyPrintLUTs() noexcept {
  93.     printTableDefinition("tan_table", tan_table, tan_table.size());
  94.     printTableDefinition("y_step", y_step, y_step.size());
  95.     printTableDefinition("x_step", x_step, x_step.size());
  96.     printTableDefinition("inv_sin_table", inv_sin_table, inv_sin_table.size());
  97.     printTableDefinition("inv_tan_table", inv_tan_table, inv_tan_table.size());
  98.     printTableDefinition("cos_table", cos_table, cos_table.size());
  99.     std::cout << "const float* inv_cos_table = &inv_sin_table[" << ANGLE_90 << "];\n";      
  100. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×