| 316 | } |
| 317 | |
| 318 | void Corkscrew::draw(bool use_multi_sampling) { |
| 319 | // The draw method should map from the rectangular surface to the LED pixel data |
| 320 | // This is the reverse of readFrom - we read from our surface and populate LED data |
| 321 | auto source_surface = getOrCreateInputSurface(); |
| 322 | |
| 323 | // Make sure we have pixel storage |
| 324 | if (mPixelStorage.empty()) { |
| 325 | // If no pixel storage is configured, there's nothing to draw to |
| 326 | return; |
| 327 | } |
| 328 | |
| 329 | CRGB* led_data = rawData(); |
| 330 | if (!led_data) return; |
| 331 | |
| 332 | if (use_multi_sampling) { |
| 333 | // Use multi-sampling to get better accuracy |
| 334 | for (fl::size led_idx = 0; led_idx < mNumLeds; ++led_idx) { |
| 335 | // Get the wrapped tile for this LED position |
| 336 | Tile2x2_u8_wrap tile = at_wrap(static_cast<float>(led_idx)); |
| 337 | |
| 338 | // Accumulate color from the 4 sample points with their weights |
| 339 | fl::u32 r_accum = 0, g_accum = 0, b_accum = 0; |
| 340 | fl::u32 total_weight = 0; |
| 341 | |
| 342 | // Sample from each of the 4 corners of the tile |
| 343 | for (fl::u8 x = 0; x < 2; x++) { |
| 344 | for (fl::u8 y = 0; y < 2; y++) { |
| 345 | const auto& entry = tile.at(x, y); |
| 346 | vec2<u16> pos = entry.first; |
| 347 | fl::u8 weight = entry.second; |
| 348 | |
| 349 | // Bounds check for the source surface |
| 350 | if (pos.x < source_surface->width() && pos.y < source_surface->height()) { |
| 351 | // Sample from the source surface |
| 352 | CRGB sample_color = source_surface->at(pos.x, pos.y); |
| 353 | |
| 354 | // Accumulate weighted color components |
| 355 | r_accum += static_cast<fl::u32>(sample_color.r) * weight; |
| 356 | g_accum += static_cast<fl::u32>(sample_color.g) * weight; |
| 357 | b_accum += static_cast<fl::u32>(sample_color.b) * weight; |
| 358 | total_weight += weight; |
| 359 | } |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | // Calculate final color by dividing by total weight |
| 364 | CRGB final_color = CRGB::Black; |
| 365 | if (total_weight > 0) { |
| 366 | final_color.r = static_cast<fl::u8>(r_accum / total_weight); |
| 367 | final_color.g = static_cast<fl::u8>(g_accum / total_weight); |
| 368 | final_color.b = static_cast<fl::u8>(b_accum / total_weight); |
| 369 | } |
| 370 | |
| 371 | // Store the result in the LED data |
| 372 | led_data[led_idx] = final_color; |
| 373 | } |
| 374 | } else { |
| 375 | // Simple non-multi-sampling version |