Fixed-point render_value: same algorithm as float render_value() in engine_core.h. Returns clamped noise value in [0, 255] range. Algorithm: newx = (offset_x + center_x - cos(angle) * dist) * scale_x newy = (offset_y + center_y - sin(angle) * dist) * scale_y noise = pnoise2d(newx, newy) clamp noise to [low_limit, high_limit] map to [0, 255]
| 51 | // clamp noise to [low_limit, high_limit] |
| 52 | // map to [0, 255] |
| 53 | FASTLED_FORCE_INLINE fl::i32 render_value_fp( |
| 54 | const render_parameters_fp &p, |
| 55 | const fl::i32 *fade_lut, |
| 56 | const fl::u8 *perm) { |
| 57 | |
| 58 | using FP = fl::s16x16; |
| 59 | constexpr fl::i32 FP_ONE = static_cast<fl::i32>(1) << FP::FRAC_BITS; |
| 60 | |
| 61 | // sincos32 for angle |
| 62 | fl::u32 a24 = radiansToA24_fp(p.angle_raw); |
| 63 | SinCos32 sc = sincos32(a24); |
| 64 | |
| 65 | // sincos32 output is in [-2147418112, 2147418112] (Q0.31 range). |
| 66 | // To multiply with s16x16 dist, we use: |
| 67 | // result_s16x16 = (sc_val * dist_raw) >> 31 |
| 68 | // This gives us the product in s16x16 format. |
| 69 | fl::i32 cos_dist = static_cast<fl::i32>( |
| 70 | (static_cast<fl::i64>(sc.cos_val) * p.dist_raw) >> 31); |
| 71 | fl::i32 sin_dist = static_cast<fl::i32>( |
| 72 | (static_cast<fl::i64>(sc.sin_val) * p.dist_raw) >> 31); |
| 73 | |
| 74 | // newx = (offset_x + center_x - cos*dist) * scale_x |
| 75 | // newy = (offset_y + center_y - sin*dist) * scale_y |
| 76 | fl::i32 pre_x = p.offset_x_raw + p.center_x_raw - cos_dist; |
| 77 | fl::i32 pre_y = p.offset_y_raw + p.center_y_raw - sin_dist; |
| 78 | |
| 79 | fl::i32 nx = static_cast<fl::i32>( |
| 80 | (static_cast<fl::i64>(pre_x) * p.scale_x_raw) >> FP::FRAC_BITS); |
| 81 | fl::i32 ny = static_cast<fl::i32>( |
| 82 | (static_cast<fl::i64>(pre_y) * p.scale_y_raw) >> FP::FRAC_BITS); |
| 83 | |
| 84 | // Compute z coordinate: newz = (offset_z + z) * scale_z |
| 85 | fl::i32 nz = static_cast<fl::i32>( |
| 86 | (static_cast<fl::i64>(p.offset_z_raw + p.z_raw) * p.scale_z_raw) >> FP::FRAC_BITS); |
| 87 | |
| 88 | // Perlin noise: 2D when z==0, 3D otherwise |
| 89 | fl::i32 raw_noise; |
| 90 | if (nz == 0) { |
| 91 | raw_noise = perlin_s16x16::pnoise2d_raw(nx, ny, fade_lut, perm); |
| 92 | } else { |
| 93 | raw_noise = perlin_s16x16::pnoise3d_raw(nx, ny, nz, fade_lut, perm); |
| 94 | } |
| 95 | |
| 96 | // Clamp to [low_limit, high_limit] |
| 97 | if (raw_noise < p.low_limit_raw) raw_noise = p.low_limit_raw; |
| 98 | if (raw_noise > p.high_limit_raw) raw_noise = p.high_limit_raw; |
| 99 | |
| 100 | // Map from [low_limit, high_limit] to [0, 255] |
| 101 | // map_float(x, low, high, 0, 255) = (x - low) * 255 / (high - low) |
| 102 | fl::i32 range = p.high_limit_raw - p.low_limit_raw; |
| 103 | fl::i32 shifted = raw_noise - p.low_limit_raw; |
| 104 | |
| 105 | // shifted is in [0, range], we want (shifted * 255) / range |
| 106 | // For the common case where low=0, high=1: range = FP_ONE |
| 107 | // result = (shifted * 255) >> FRAC_BITS (since shifted is in [0, FP_ONE]) |
| 108 | // For low=-1, high=1: range = 2*FP_ONE |
| 109 | // result = (shifted * 255) / (2*FP_ONE) |
| 110 | fl::i32 result; |
no test coverage detected