30 bool gapActive = (gapParams.
num_leds > 0 && gapParams.
gap > 0.0f && numLeds >
static_cast<fl::u16
>(gapParams.
num_leds));
34 const float ledProgress =
static_cast<float>(ledIndex) /
static_cast<float>(numLeds - 1);
35 const fl::u16 row = ledIndex / width;
36 const fl::u16 remainder = ledIndex % width;
37 const float alpha =
static_cast<float>(remainder) /
static_cast<float>(width);
38 const float width_pos = ledProgress * numLeds;
39 const float height_pos =
static_cast<float>(row) + alpha;
40 return vec2f(width_pos, height_pos);
48 float width_pos =
static_cast<float>(ledIndex) *
static_cast<float>(width);
51 float height_pos = width_pos /
static_cast<float>(width);
53 return vec2f(width_pos, height_pos);
60 float ledsPerTurn =
static_cast<float>(numLeds) / totalTurns;
61 fl::u16 calc_width =
static_cast<fl::u16
>(
fl::ceil(ledsPerTurn));
63 fl::u16 height_from_turns =
static_cast<fl::u16
>(
fl::ceil(totalTurns));
67 if (calc_width * height_from_turns > numLeds) {
69 calc_height =
static_cast<fl::u16
>(
fl::ceil(
static_cast<float>(numLeds) /
static_cast<float>(calc_width)));
71 calc_height = height_from_turns;
75 *height = calc_height;
126 position.
x = fmodf(position.
x,
static_cast<float>(
mWidth));
136 FASTLED_ASSERT(
false,
"Out of bounds access in Corkscrew at_splat: "
142 float i_floor = floorf(i);
143 float i_ceil = ceilf(i);
147 return splat(position);
152 float t = i - i_floor;
153 vec2f interpolated_pos = map_range(
t, 0.0f, 1.0f, pos1, pos2);
154 return splat(interpolated_pos);
167 fl::size cache_index =
static_cast<fl::size
>(i);
211 for (fl::size i = 0; i <
mNumLeds; ++i) {
253 if (use_multi_sampling) {
262 target_surface->clear();
265 for (fl::size led_idx = 0; led_idx <
mNumLeds; ++led_idx) {
270 vec2i16 coord(
static_cast<fl::i16
>(rect_pos.
x + 0.5f),
271 static_cast<fl::i16
>(rect_pos.
y + 0.5f));
274 coord.
x =
MAX(0,
MIN(coord.
x,
static_cast<fl::i16
>(source_grid.
width()) - 1));
275 coord.
y =
MAX(0,
MIN(coord.
y,
static_cast<fl::i16
>(source_grid.
height()) - 1));
278 CRGB sampled_color = source_grid.
at(coord.
x, coord.
y);
281 if (led_idx < target_surface->
size()) {
282 target_surface->data()[led_idx] = sampled_color;
312 for (fl::size i = 0; i < target_surface->size(); ++i) {
313 target_surface->data()[i] = color;
329 if (!led_data)
return;
331 if (use_multi_sampling) {
333 for (fl::size led_idx = 0; led_idx <
mNumLeds; ++led_idx) {
338 fl::u32 r_accum = 0, g_accum = 0, b_accum = 0;
339 fl::u32 total_weight = 0;
344 const auto& entry = tile.
at(
x,
y);
346 fl::u8 weight = entry.second;
349 if (
pos.x < source_surface->width() &&
pos.y < source_surface->height()) {
351 CRGB sample_color = source_surface->at(
pos.x,
pos.y);
354 r_accum +=
static_cast<fl::u32
>(sample_color.r) * weight;
355 g_accum +=
static_cast<fl::u32
>(sample_color.g) * weight;
356 b_accum +=
static_cast<fl::u32
>(sample_color.b) * weight;
357 total_weight += weight;
364 if (total_weight > 0) {
365 final_color.r =
static_cast<fl::u8>(r_accum / total_weight);
366 final_color.g =
static_cast<fl::u8>(g_accum / total_weight);
367 final_color.b =
static_cast<fl::u8>(b_accum / total_weight);
371 led_data[led_idx] = final_color;
375 for (fl::size led_idx = 0; led_idx <
mNumLeds; ++led_idx) {
380 vec2i16 coord(
static_cast<fl::i16
>(rect_pos.
x + 0.5f),
381 static_cast<fl::i16
>(rect_pos.
y + 0.5f));
384 coord.
x =
MAX(0,
MIN(coord.
x,
static_cast<fl::i16
>(source_surface->width()) - 1));
385 coord.
y =
MAX(0,
MIN(coord.
y,
static_cast<fl::i16
>(source_surface->height()) - 1));
388 CRGB sampled_color = source_surface->at(coord.
x, coord.
y);
391 led_data[led_idx] = sampled_color;
399 target_surface->
clear();
400 const u16 width =
static_cast<u16
>(source_grid.
width());
401 const u16 height =
static_cast<u16
>(source_grid.
height());
404 for (fl::size led_idx = 0; led_idx <
mNumLeds; ++led_idx) {
409 fl::u32 r_accum = 0, g_accum = 0, b_accum = 0;
410 fl::u32 total_weight = 0;
415 const auto& entry = tile.
at(
x,
y);
417 fl::u8 weight = entry.second;
420 if (
pos.x >= 0 &&
pos.x < width &&
421 pos.y >= 0 &&
pos.y < height) {
427 r_accum +=
static_cast<fl::u32
>(sample_color.r) * weight;
428 g_accum +=
static_cast<fl::u32
>(sample_color.g) * weight;
429 b_accum +=
static_cast<fl::u32
>(sample_color.b) * weight;
430 total_weight += weight;
437 if (total_weight > 0) {
438 final_color.r =
static_cast<fl::u8>(r_accum / total_weight);
439 final_color.g =
static_cast<fl::u8>(g_accum / total_weight);
440 final_color.b =
static_cast<fl::u8>(b_accum / total_weight);
445 if (led_idx < target_surface->
size()) {
446 target_surface->data()[led_idx] = final_color;
461 for (fl::u16 i = 0; i <
mNumLeds; ++i) {
const Corkscrew * corkscrew_
fl::shared_ptr< fl::Grid< CRGB > > & getOrCreateInputSurface()
Tile2x2_u8 at_splat_extrapolate(float i) const
Tile2x2_u8_wrap calculateTileAtWrap(float i) const
void setCachingEnabled(bool enabled)
fl::ScreenMap toScreenMap(float diameter=0.5f) const
Corkscrew(float totalTurns, fl::u16 numLeds, bool invert=false, const Gap &gapParams=Gap())
fl::Grid< CRGB > & surface()
void readFromMulti(const fl::Grid< CRGB > &target_grid) const
void fillInputSurface(const CRGB &color)
PixelStorage mPixelStorage
vec2f at_exact(fl::u16 i) const
fl::shared_ptr< fl::Grid< CRGB > > mInputSurface
fl::vector< Tile2x2_u8_wrap > mTileCache
void initializeCache() const
Tile2x2_u8_wrap at_wrap(float i) const
void draw(bool use_multi_sampling=true)
vec2f at_no_wrap(fl::u16 i) const
void readFrom(const fl::Grid< CRGB > &source_grid, bool use_multi_sampling=true)
fl::size pixelCount() const
fl::pair< vec2< u16 >, u8 > Entry
vec2< u16 > origin() const
#define ALMOST_EQUAL_FLOAT(a, b)
void calculateDimensions(float totalTurns, fl::u16 numLeds, const Gap &gapParams, fl::u16 *width, fl::u16 *height)
vec2f calculateLedPositionExtended(fl::u16 ledIndex, fl::u16 numLeds, float totalTurns, const Gap &gapParams, fl::u16 width, fl::u16 height)
Tile2x2_u8 splat(vec2f xy)
"Splat" as in "splat pixel rendering" takes a pixel value in float x,y coordinates and "splats" it in...
shared_ptr< T > make_shared(Args &&... args)
pair_element< I, T1, T2 >::type & get(pair< T1, T2 > &p) noexcept
HeapVector< T, Allocator > vector
Corkscrew LED strip projection and rendering.
@ Black
<div style='background:#000000;width:4em;height:4em;'></div>
Representation of an RGB pixel (Red, Green, Blue)
Struct representing gap parameters for corkscrew mapping.