| 130 | } |
| 131 | |
| 132 | void loop() { |
| 133 | fl::clear(frameBuffer); |
| 134 | static float pos = 0; // okay static in header |
| 135 | pos += speed.value(); |
| 136 | if (pos > corkscrew.size() - 1) { |
| 137 | pos = 0; // Reset to the beginning |
| 138 | } |
| 139 | |
| 140 | // Update caching setting if it changed |
| 141 | static bool lastCachingState = cachingEnabled.value(); // okay static in header |
| 142 | if (lastCachingState != cachingEnabled.value()) { |
| 143 | corkscrew.setCachingEnabled(cachingEnabled.value()); |
| 144 | lastCachingState = cachingEnabled.value(); |
| 145 | } |
| 146 | |
| 147 | if (allWhite) { |
| 148 | for (size_t i = 0; i < frameBuffer.size(); ++i) { |
| 149 | frameBuffer.span()[i] = CRGB(8, 8, 8); |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | if (splatRendering) { |
| 154 | fl::Tile2x2_u8_wrap pos_tile = corkscrew.at_wrap(pos); |
| 155 | const fl::CRGB color = fl::CRGB::Blue; |
| 156 | // Draw each pixel in the 2x2 tile using the new wrapping API |
| 157 | for (int dx = 0; dx < 2; ++dx) { |
| 158 | for (int dy = 0; dy < 2; ++dy) { |
| 159 | auto data = pos_tile.at(dx, dy); |
| 160 | fl::vec2<fl::u16> wrapped_pos = data.first; // Already wrapped position |
| 161 | uint8_t alpha = data.second; // Alpha value |
| 162 | |
| 163 | if (alpha > 0) { // Only draw if there's some alpha |
| 164 | fl::CRGB c = color; |
| 165 | c.nscale8(alpha); // Scale the color by the alpha value |
| 166 | frameBuffer.at(wrapped_pos.x, wrapped_pos.y) = c; |
| 167 | } |
| 168 | } |
| 169 | } |
| 170 | } else { |
| 171 | // None splat rendering, looks aweful. |
| 172 | fl::vec2f pos_vec2f = corkscrew.at_no_wrap(pos); |
| 173 | fl::vec2<fl::u16> pos_i16 = fl::vec2<fl::u16>(round(pos_vec2f.x), round(pos_vec2f.y)); |
| 174 | // Now map the cork screw position to the cylindrical buffer that we |
| 175 | // will draw. |
| 176 | frameBuffer.at(pos_i16.x, pos_i16.y) = |
| 177 | fl::CRGB::Blue; // Draw a blue pixel at (w, h) |
| 178 | } |
| 179 | FastLED.show(); |
| 180 | } |