Topology, Curves, Gamma, and Samples

Topology, Tiles, and Mosaic layout
Animation Curves
Color Gamma correct
change timescale dynamically on NeoPixelAnimator
bilinear color blend methods
new samples to support new features
This commit is contained in:
Makuna
2016-03-20 10:06:58 -07:00
parent 22f5e71a0b
commit 3dbfae7fc4
30 changed files with 1917 additions and 110 deletions
+6 -1
View File
@@ -125,11 +125,16 @@ public:
_animationLastTick = millis();
}
uint16_t TimeScale()
uint16_t getTimeScale()
{
return _timeScale;
}
void setTimeScale(uint16_t timeScale)
{
_timeScale = (timeScale < 1) ? (1) : (timeScale > 32768) ? 32768 : timeScale;
}
private:
struct AnimationContext
{
+10 -1
View File
@@ -32,6 +32,15 @@ License along with NeoPixel. If not, see
#include "internal/HsbColor.h"
#include "internal/HtmlColor.h"
#include "internal/RgbwColor.h"
#include "internal/Layouts.h"
#include "internal/NeoTopology.h"
#include "internal/NeoTiles.h"
#include "internal/NeoMosaic.h"
#include "internal/NeoEase.h"
#include "internal/NeoGamma.h"
#include "internal/NeoColorFeatures.h"
#if defined(ARDUINO_ARCH_ESP8266)
@@ -124,7 +133,7 @@ public:
return _countPixels;
};
void SetPixelColor(uint16_t indexPixel, typename T_COLOR_FEATURE::ColorObject color)
void SetPixelColor(uint16_t indexPixel, const typename T_COLOR_FEATURE::ColorObject& color)
{
if (indexPixel < _countPixels)
{
+1 -1
View File
@@ -67,7 +67,7 @@ HsbColor::HsbColor(const RgbColor& color)
B = v;
}
HsbColor HsbColor::LinearBlend(HsbColor left, HsbColor right, float progress)
HsbColor HsbColor::LinearBlend(const HsbColor& left, const HsbColor& right, float progress)
{
return HsbColor(left.H + ((right.H - left.H) * progress),
left.S + ((right.S - left.S) * progress),
+2 -1
View File
@@ -1,3 +1,4 @@
/*-------------------------------------------------------------------------
HsbColor provides a color object that can be directly consumed by NeoPixelBus
@@ -62,7 +63,7 @@ struct HsbColor
// progress - (0.0 - 1.0) value where 0.0 will return left and 1.0 will return right
// and a value between will blend the color weighted linearly between them
// ------------------------------------------------------------------------
static HsbColor LinearBlend(HsbColor left, HsbColor right, float progress);
static HsbColor LinearBlend(const HsbColor& left, const HsbColor& right, float progress);
// ------------------------------------------------------------------------
// Hue, Saturation, Brightness color members
+2 -1
View File
@@ -1,6 +1,7 @@
/*-------------------------------------------------------------------------
HslColor provides a color object that can be directly consumed by NeoPixelBus
Written by Michael C. Miller.
I invest time and resources providing this open source code,
@@ -70,7 +71,7 @@ HslColor::HslColor(const RgbColor& color)
L = l;
}
HslColor HslColor::LinearBlend(HslColor left, HslColor right, float progress)
HslColor HslColor::LinearBlend(const HslColor& left, const HslColor& right, float progress)
{
return HslColor(left.H + ((right.H - left.H) * progress),
left.S + ((right.S - left.S) * progress),
+1 -1
View File
@@ -64,7 +64,7 @@ struct HslColor
// progress - (0.0 - 1.0) value where 0.0 will return left and 1.0 will return right
// and a value between will blend the color weighted linearly between them
// ------------------------------------------------------------------------
static HslColor LinearBlend(HslColor left, HslColor right, float progress);
static HslColor LinearBlend(const HslColor& left, const HslColor& right, float progress);
// ------------------------------------------------------------------------
// Hue, Saturation, Lightness color members
+19 -1
View File
@@ -62,7 +62,25 @@ struct HtmlColor
{
};
// ------------------------------------------------------------------------
// BilinearBlend between four colors by the amount defined by 2d variable
// c00 - upper left quadrant color
// c01 - upper right quadrant color
// c10 - lower left quadrant color
// c11 - lower right quadrant color
// x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space
// y - unit value (0.0 - 1.0) that defines the blend progress in vertical space
// ------------------------------------------------------------------------
static HtmlColor BilinearBlend(const HtmlColor& c00,
const HtmlColor& c01,
const HtmlColor& c10,
const HtmlColor& c11,
float x,
float y)
{
return RgbColor::BilinearBlend(c00, c01, c10, c11, x, y);
}
// ------------------------------------------------------------------------
// Color member (0-0xffffff) where
// 0xff0000 is red
+425
View File
@@ -0,0 +1,425 @@
#pragma once
/*-------------------------------------------------------------------------
Layout provides a collection of class objects that are used with NeoTopology
object.
They define the specific layout of pixels and do the math to change the 2d
cordinate space to 1d cordinate space
Written by Michael C. Miller.
I invest time and resources providing this open source code,
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
-------------------------------------------------------------------------
This file is part of the Makuna/NeoPixelBus library.
NeoPixelBus is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
NeoPixelBus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with NeoPixel. If not, see
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
//-----------------------------------------------------------------------------
// RowMajor
//-----------------------------------------------------------------------------
class RowMajorLayout;
class RowMajor90Layout;
class RowMajor180Layout;
class RowMajor270Layout;
class RowMajorTilePreference
{
public:
typedef RowMajorLayout EvenRowEvenColumnLayout;
typedef RowMajor270Layout EvenRowOddColumnLayout;
typedef RowMajor90Layout OddRowEvenColumnLayout;
typedef RowMajor180Layout OddRowOddColumnLayout;
};
// layout example of 4x4
// 00 01 02 03
// 04 05 06 07
// 08 09 10 11
// 12 13 14 15
//
class RowMajorLayout : public RowMajorTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
return x + y * width;
}
};
// layout example of 4x4
// 12 08 04 00
// 13 09 05 01
// 14 10 06 02
// 15 11 07 03
//
class RowMajor90Layout : public RowMajorTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
return (width - 1 - x) * height + y;
}
};
// layout example of 4x4
// 15 14 13 12
// 11 10 09 08
// 07 06 05 04
// 03 02 01 00
//
class RowMajor180Layout : public RowMajorTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
return (width - 1 - x) + (height - 1 - y) * width;
}
};
// layout example of 4x4
// 03 07 11 15
// 02 06 10 14
// 01 05 09 13
// 00 04 08 12
//
class RowMajor270Layout : public RowMajorTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
return x * height + (height - 1 - y);
}
};
//-----------------------------------------------------------------------------
// ColumnMajor
//-----------------------------------------------------------------------------
class ColumnMajorLayout;
class ColumnMajor90Layout;
class ColumnMajor180Layout;
class ColumnMajor270Layout;
class ColumnMajorTilePreference
{
public:
typedef ColumnMajorLayout EvenRowEvenColumnLayout;
typedef ColumnMajor270Layout EvenRowOddColumnLayout;
typedef ColumnMajor90Layout OddRowEvenColumnLayout;
typedef ColumnMajor180Layout OddRowOddColumnLayout;
};
// layout example of 4x4
// 00 04 08 12
// 01 05 09 13
// 02 06 10 14
// 03 07 11 15
//
class ColumnMajorLayout : public ColumnMajorTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
return x * height + y;
}
};
// layout example of 4x4
// 03 02 01 00
// 07 06 05 04
// 11 10 09 08
// 15 14 13 12
//
class ColumnMajor90Layout : public ColumnMajorTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
return (width - 1 - x) + y * width;
}
};
// layout example of 4x4
// 15 11 07 03
// 14 10 06 02
// 13 09 05 01
// 12 08 04 00
//
class ColumnMajor180Layout : public ColumnMajorTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
return (width - 1 - x) * height + (height - 1 - y);
}
};
// layout example of 4x4
// 12 13 14 15
// 08 09 10 11
// 04 05 06 07
// 00 01 02 03
//
class ColumnMajor270Layout : public ColumnMajorTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
return x + (height - 1 - y) * width;
}
};
//-----------------------------------------------------------------------------
// RowMajorAlternating
//-----------------------------------------------------------------------------
class RowMajorAlternating270Layout;
class RowMajorAlternating90Layout;
class RowMajorAlternatingTilePreference
{
public:
typedef RowMajorAlternating270Layout EvenRowEvenColumnLayout;
typedef RowMajorAlternating270Layout EvenRowOddColumnLayout;
typedef RowMajorAlternating90Layout OddRowEvenColumnLayout;
typedef RowMajorAlternating90Layout OddRowOddColumnLayout;
};
// layout example of 4x4
// 00 01 02 03
// 07 06 05 04
// 08 09 10 11
// 15 14 13 12
//
class RowMajorAlternatingLayout : public RowMajorAlternatingTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
uint16_t index = y * width;
if (y & 0x0001)
{
index += ((width - 1) - x);
}
else
{
index += x;
}
return index;
}
};
// layout example of 4x4
// 15 08 07 00
// 14 09 06 01
// 13 10 05 02
// 12 11 04 03
//
class RowMajorAlternating90Layout : public RowMajorAlternatingTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
uint16_t mx = ((width - 1) - x);
uint16_t index = mx * height;
if (mx & 0x0001)
{
index += ((height - 1) - y);
}
else
{
index += y;
}
return index;
}
};
// layout example of 4x4
// 12 13 14 15
// 11 10 09 08
// 04 05 06 07
// 03 02 01 00
//
class RowMajorAlternating180Layout : public RowMajorAlternatingTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
uint16_t my = ((height - 1) - y);
uint16_t index = my * width;
if (my & 0x0001)
{
index += x;
}
else
{
index += ((width - 1) - x);
}
return index;
}
};
// layout example of 4x4
// 03 04 11 12
// 02 05 10 13
// 01 06 09 14
// 00 07 08 15
//
class RowMajorAlternating270Layout : public RowMajorAlternatingTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
uint16_t index = x * height;
if (x & 0x0001)
{
index += y;
}
else
{
index += ((height - 1) - y);
}
return index;
}
};
//-----------------------------------------------------------------------------
// ColumnMajorAlternating
//-----------------------------------------------------------------------------
class ColumnMajorAlternatingLayout;
class ColumnMajorAlternating180Layout;
class ColumnMajorAlternatingTilePreference
{
public:
typedef ColumnMajorAlternatingLayout EvenRowEvenColumnLayout;
typedef ColumnMajorAlternatingLayout EvenRowOddColumnLayout;
typedef ColumnMajorAlternating180Layout OddRowEvenColumnLayout;
typedef ColumnMajorAlternating180Layout OddRowOddColumnLayout;
};
// layout example of 4x4
// 00 07 08 15
// 01 06 09 14
// 02 05 10 13
// 03 04 11 12
//
class ColumnMajorAlternatingLayout : public ColumnMajorAlternatingTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
uint16_t index = x * height;
if (x & 0x0001)
{
index += ((height - 1) - y);
}
else
{
index += y;
}
return index;
}
};
// layout example of 4x4
// 03 02 01 00
// 04 05 06 07
// 11 10 09 08
// 12 13 14 15
//
class ColumnMajorAlternating90Layout : public ColumnMajorAlternatingTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
uint16_t index = y * width;
if (y & 0x0001)
{
index += x;
}
else
{
index += ((width - 1) - x);
}
return index;
}
};
// layout example of 4x4
// 12 11 04 03
// 13 10 05 02
// 14 09 06 01
// 15 08 07 00
//
class ColumnMajorAlternating180Layout : public ColumnMajorAlternatingTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
uint16_t mx = ((width - 1) - x);
uint16_t index = mx * height;
if (mx & 0x0001)
{
index += y;
}
else
{
index += ((height - 1) - y);
}
return index;
}
};
// layout example of 4x4
// 15 14 13 12
// 08 09 10 11
// 07 06 05 04
// 00 01 02 03
//
class ColumnMajorAlternating270Layout : public ColumnMajorAlternatingTilePreference
{
public:
static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y)
{
uint16_t my = ((height - 1) - y);
uint16_t index = my * width;
if (my & 0x0001)
{
index += ((width - 1) - x);
}
else
{
index += x;
}
return index;
}
};
+2 -5
View File
@@ -30,26 +30,23 @@ class Neo3Elements
{
public:
static const size_t PixelSize = 3;
static const RgbColor Empty();
static uint8_t* getPixelAddress(uint8_t* pPixels, uint16_t indexPixel)
{
return &pPixels[indexPixel * PixelSize];
return pPixels + indexPixel * PixelSize;
}
typedef RgbColor ColorObject;
};
class Neo4Elements
{
public:
static const size_t PixelSize = 4;
static const RgbColor Empty();
static uint8_t* getPixelAddress(uint8_t* pPixels, uint16_t indexPixel)
{
return &pPixels[indexPixel * PixelSize];
return pPixels + indexPixel * PixelSize;
}
typedef RgbwColor ColorObject;
+83 -73
View File
@@ -28,187 +28,197 @@ License along with NeoPixel. If not, see
#ifdef ARDUINO_ARCH_AVR
typedef float(*AnimEaseFunction)(float linear);
typedef float(*AnimEaseFunction)(float unitValue);
#else
#undef max
#undef min
#include <functional>
typedef std::function<float(float linear)> AnimEaseFunction;
typedef std::function<float(float unitValue)> AnimEaseFunction;
#endif
class NeoEase
{
public:
static float QuadraticIn(float linear)
static float Linear(float unitValue)
{
return linear * linear;
return unitValue;
}
static float QuadraticOut(float linear)
static float QuadraticIn(float unitValue)
{
return (-linear * (linear - 2.0f));
return unitValue * unitValue;
}
static float QuadraticInOut(float linear)
static float QuadraticOut(float unitValue)
{
linear *= 2.0f;
if (linear < 1.0f)
return (-unitValue * (unitValue - 2.0f));
}
static float QuadraticInOut(float unitValue)
{
unitValue *= 2.0f;
if (unitValue < 1.0f)
{
return (0.5f * linear * linear);
return (0.5f * unitValue * unitValue);
}
else
{
linear -= 1.0f;
return (-0.5f * (linear * (linear - 2.0f) - 1.0f));
unitValue -= 1.0f;
return (-0.5f * (unitValue * (unitValue - 2.0f) - 1.0f));
}
}
static float CubicIn(float linear)
static float CubicIn(float unitValue)
{
return (linear * linear * linear);
return (unitValue * unitValue * unitValue);
}
static float CubicOut(float linear)
static float CubicOut(float unitValue)
{
linear -= 1.0f;
return (linear * linear * linear + 1);
unitValue -= 1.0f;
return (unitValue * unitValue * unitValue + 1);
}
static float CubicInOut(float linear)
static float CubicInOut(float unitValue)
{
linear *= 2.0f;
if (linear < 1.0f)
unitValue *= 2.0f;
if (unitValue < 1.0f)
{
return (0.5f * linear * linear * linear);
return (0.5f * unitValue * unitValue * unitValue);
}
else
{
linear -= 2.0f;
return (0.5f * (linear * linear * linear + 2.0f));
unitValue -= 2.0f;
return (0.5f * (unitValue * unitValue * unitValue + 2.0f));
}
}
static float QuarticIn(float linear)
static float QuarticIn(float unitValue)
{
return (linear * linear * linear * linear);
return (unitValue * unitValue * unitValue * unitValue);
}
static float QuarticOut(float linear)
static float QuarticOut(float unitValue)
{
linear -= 1.0f;
return -(linear * linear * linear * linear - 1);
unitValue -= 1.0f;
return -(unitValue * unitValue * unitValue * unitValue - 1);
}
static float QuarticInOut(float linear)
static float QuarticInOut(float unitValue)
{
linear *= 2.0f;
if (linear < 1.0f)
unitValue *= 2.0f;
if (unitValue < 1.0f)
{
return (0.5f * linear * linear * linear * linear);
return (0.5f * unitValue * unitValue * unitValue * unitValue);
}
else
{
linear -= 2.0f;
return (-0.5f * (linear * linear * linear * linear - 2.0f));
unitValue -= 2.0f;
return (-0.5f * (unitValue * unitValue * unitValue * unitValue - 2.0f));
}
}
static float QuinticIn(float linear)
static float QuinticIn(float unitValue)
{
return (linear * linear * linear * linear * linear);
return (unitValue * unitValue * unitValue * unitValue * unitValue);
}
static float QuinticOut(float linear)
static float QuinticOut(float unitValue)
{
linear -= 1.0f;
return (linear * linear * linear * linear * linear + 1.0f);
unitValue -= 1.0f;
return (unitValue * unitValue * unitValue * unitValue * unitValue + 1.0f);
}
static float QuinticInOut(float linear)
static float QuinticInOut(float unitValue)
{
linear *= 2.0f;
if (linear < 1.0f)
unitValue *= 2.0f;
if (unitValue < 1.0f)
{
return (0.5f * linear * linear * linear * linear * linear);
return (0.5f * unitValue * unitValue * unitValue * unitValue * unitValue);
}
else
{
linear -= 2.0f;
return (0.5f * (linear * linear * linear * linear * linear + 2.0f));
unitValue -= 2.0f;
return (0.5f * (unitValue * unitValue * unitValue * unitValue * unitValue + 2.0f));
}
}
static float SinusoidalIn(float linear)
static float SinusoidalIn(float unitValue)
{
return (-cos(linear * HALF_PI) + 1.0f);
return (-cos(unitValue * HALF_PI) + 1.0f);
}
static float SinusoidalOut(float linear)
static float SinusoidalOut(float unitValue)
{
return (sin(linear * HALF_PI));
return (sin(unitValue * HALF_PI));
}
static float SinusoidalInOut(float linear)
static float SinusoidalInOut(float unitValue)
{
return -0.5 * (cos(PI * linear) - 1.0f);
return -0.5 * (cos(PI * unitValue) - 1.0f);
}
static float ExponentialIn(float linear)
static float ExponentialIn(float unitValue)
{
return (pow(2, 10.0f * (linear - 1.0f)));
return (pow(2, 10.0f * (unitValue - 1.0f)));
}
static float ExponentialOut(float linear)
static float ExponentialOut(float unitValue)
{
return (-pow(2, -10.0f * linear) + 1.0f);
return (-pow(2, -10.0f * unitValue) + 1.0f);
}
static float ExponentialInOut(float linear)
static float ExponentialInOut(float unitValue)
{
linear *= 2.0f;
if (linear < 1.0f)
unitValue *= 2.0f;
if (unitValue < 1.0f)
{
return (0.5f * pow(2, 10.0f * (linear - 1.0f)));
return (0.5f * pow(2, 10.0f * (unitValue - 1.0f)));
}
else
{
linear -= 1.0f;
return (0.5f * (-pow(2, -10.0f * linear) + 2.0f));
unitValue -= 1.0f;
return (0.5f * (-pow(2, -10.0f * unitValue) + 2.0f));
}
}
static float CircularIn(float linear)
static float CircularIn(float unitValue)
{
if (linear == 1.0f)
if (unitValue == 1.0f)
{
return 1.0f;
}
else
{
return (-(sqrt(1.0f - linear * linear) - 1.0f));
return (-(sqrt(1.0f - unitValue * unitValue) - 1.0f));
}
}
static float CircularOut(float linear)
static float CircularOut(float unitValue)
{
linear -= 1.0f;
return (sqrt(1.0f - linear * linear));
unitValue -= 1.0f;
return (sqrt(1.0f - unitValue * unitValue));
}
static float CircularInOut(float linear)
static float CircularInOut(float unitValue)
{
linear *= 2.0f;
if (linear < 1.0f)
unitValue *= 2.0f;
if (unitValue < 1.0f)
{
return (-0.5f * (sqrt(1.0f - linear * linear) - 1));
return (-0.5f * (sqrt(1.0f - unitValue * unitValue) - 1));
}
else
{
linear -= 2.0f;
return (0.5f * (sqrt(1.0f - linear * linear) + 1.0f));
unitValue -= 2.0f;
return (0.5f * (sqrt(1.0f - unitValue * unitValue) + 1.0f));
}
}
static float Gamma(float unitValue)
{
return pow(unitValue, 1.0f / 0.45f);
}
};
+90
View File
@@ -0,0 +1,90 @@
/*-------------------------------------------------------------------------
NeoPixelGamma class is used to correct RGB colors for human eye gamma levels
Written by Michael C. Miller.
I invest time and resources providing this open source code,
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
-------------------------------------------------------------------------
This file is part of the Makuna/NeoPixelBus library.
NeoPixelBus is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
NeoPixelBus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with NeoPixel. If not, see
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
#pragma once
// NeoGammaEquationMethod uses no memory but is slower than NeoGammaTableMethod
class NeoGammaEquationMethod
{
public:
static uint8_t Correct(uint8_t value)
{
return static_cast<uint8_t>(255.0f * NeoEase::Gamma(value / 255.0f) + 0.5f);
}
};
// NeoGammaTableMethod uses 256 bytes of memory, but is significantly faster
class NeoGammaTableMethod
{
public:
static uint8_t Correct(uint8_t value)
{
return _table[value];
}
private:
static const uint8_t _table[256];
};
// use one of the method classes above as a converter for this template class
template<typename T_METHOD> class NeoGamma
{
public:
RgbColor Correct(const RgbColor& original)
{
return RgbColor(T_METHOD::Correct(original.R),
T_METHOD::Correct(original.G),
T_METHOD::Correct(original.B));
}
RgbwColor Correct(const RgbwColor& original)
{
return RgbwColor(T_METHOD::Correct(original.R),
T_METHOD::Correct(original.G),
T_METHOD::Correct(original.B),
T_METHOD::Correct(original.W) );
}
};
const uint8_t NeoGammaTableMethod::_table[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6,
6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11,
12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19,
19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28,
29, 30, 30, 31, 32, 33, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40,
41, 42, 43, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71,
72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 86, 87, 88, 89,
91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 105, 106, 108, 109, 110,
112, 113, 115, 116, 118, 119, 121, 122, 123, 125, 126, 128, 130, 131, 133, 134,
136, 137, 139, 140, 142, 144, 145, 147, 149, 150, 152, 154, 155, 157, 159, 160,
162, 164, 166, 167, 169, 171, 173, 175, 176, 178, 180, 182, 184, 186, 187, 189,
191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221,
223, 225, 227, 229, 231, 233, 235, 238, 240, 242, 244, 246, 248, 251, 253, 255
};
+157
View File
@@ -0,0 +1,157 @@
#pragma once
/*-------------------------------------------------------------------------
Mosiac provides a mapping feature of a 2d cordinate to linear 1d cordinate
It is used to map tiles of matricies of NeoPixels to a index on the NeoPixelBus
where the the matricies use a set of prefered topology and the tiles of
those matricies use the RowMajorAlternating layout
Written by Michael C. Miller.
I invest time and resources providing this open source code,
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
-------------------------------------------------------------------------
This file is part of the Makuna/NeoPixelBus library.
NeoPixelBus is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
NeoPixelBus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with NeoPixel. If not, see
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
//-----------------------------------------------------------------------------
// class NeoMosaic
// Complex Tile layout class that reduces distance of the interconnects between
// the tiles by using different rotations of the layout at specific locations
//
// T_LAYOUT = the layout used for matrix panel (rotation is ignored)
//
// NOTE: The tiles in the mosaic are always laid out using RowMajorAlternating
//
//-----------------------------------------------------------------------------
template <typename T_LAYOUT> class NeoMosaic
{
public:
NeoMosaic(uint16_t topoWidth, uint16_t topoHeight,
uint16_t mosaicWidth, uint16_t mosaicHeight) :
_topoWidth(topoWidth),
_topoHeight(topoHeight),
_mosaicWidth(mosaicWidth),
_mosaicHeight(mosaicHeight)
{
}
uint16_t Map(uint16_t x, uint16_t y) const
{
uint16_t localIndex;
uint16_t tileOffset;
calculate(x, y, &localIndex, &tileOffset);
return localIndex + tileOffset;
}
NeoTopologyHint TopologyHint(uint16_t x, uint16_t y) const
{
uint16_t localIndex;
uint16_t tileOffset;
NeoTopologyHint result;
calculate(x, y, &localIndex, &tileOffset);
if (localIndex == 0)
{
result = NeoTopologyHint_FirstOnPanel;
}
else if (localIndex == (_topoWidth * _topoHeight - 1))
{
result = NeoTopologyHint_LastOnPanel;
}
else
{
result = NeoTopologyHint_InPanel;
}
return result;
}
uint16_t getWidth() const
{
return _topoWidth * _mosaicWidth;
}
uint16_t getHeight() const
{
return _topoHeight * _mosaicHeight;
}
private:
const uint16_t _topoWidth;
const uint16_t _topoHeight;
const uint16_t _mosaicWidth;
const uint16_t _mosaicHeight;
void calculate(uint16_t x, uint16_t y, uint16_t* pLocalIndex, uint16_t* pTileOffset) const
{
uint16_t totalWidth = getWidth();
uint16_t totalHeight = getHeight();
if (x >= totalWidth)
{
x = totalWidth - 1;
}
if (y >= totalHeight)
{
y = totalHeight - 1;
}
uint16_t tileX = x / _topoWidth;
uint16_t topoX = x % _topoWidth;
uint16_t tileY = y / _topoHeight;
uint16_t topoY = y % _topoHeight;
*pTileOffset = RowMajorAlternatingLayout::Map(_mosaicWidth,
_mosaicHeight,
tileX,
tileY) * _topoWidth * _topoHeight;
if (tileX & 0x0001)
{
// odd columns
if (tileY & 0x0001)
{
*pLocalIndex = T_LAYOUT::OddRowOddColumnLayout::Map(_topoWidth, _topoHeight, topoX, topoY);
}
else
{
*pLocalIndex = T_LAYOUT::EvenRowOddColumnLayout::Map(_topoWidth, _topoHeight, topoX, topoY);
}
}
else
{
// even columns
if (tileY & 0x0001)
{
*pLocalIndex = T_LAYOUT::OddRowEvenColumnLayout::Map(_topoWidth, _topoHeight, topoX, topoY);
}
else
{
*pLocalIndex = T_LAYOUT::EvenRowEvenColumnLayout::Map(_topoWidth, _topoHeight, topoX, topoY);
}
}
}
};
+1 -4
View File
@@ -32,10 +32,7 @@ NeoPixelAnimator::NeoPixelAnimator(uint16_t countAnimations, uint16_t timeScale)
_activeAnimations(0),
_isRunning(true)
{
// due to strange esp include header issues, min and max aren't usable
_timeScale = (timeScale < 1) ? (1) : (timeScale > 32768) ? 32768 : timeScale;
//_timeScale = max(1, min(32768, timeScale));
setTimeScale(timeScale);
_animations = new AnimationContext[_countAnimations];
}
+124
View File
@@ -0,0 +1,124 @@
#pragma once
/*-------------------------------------------------------------------------
NeoTiles provides a mapping feature of a 2d cordinate to linear 1d cordinate
It is used to map tiles of matricies of NeoPixels to a index on the NeoPixelBus
where the the matricies use one topology and the tiles of those matricies can
use another
Written by Michael C. Miller.
I invest time and resources providing this open source code,
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
-------------------------------------------------------------------------
This file is part of the Makuna/NeoPixelBus library.
NeoPixelBus is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
NeoPixelBus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with NeoPixel. If not, see
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
//-----------------------------------------------------------------------------
// class NeoTiles
// Simple template Tile layout class
// T_MATRIX_LAYOUT = the layout used on the pixel matrix panel (a tile)
// T_TILE_LAYOUT = the layout used for the tiles.
//
//-----------------------------------------------------------------------------
template <typename T_MATRIX_LAYOUT, typename T_TILE_LAYOUT> class NeoTiles
{
public:
NeoTiles(uint16_t topoWidth, uint16_t topoHeight,
uint16_t tilesWidth, uint16_t tilesHeight) :
_topo(topoWidth, topoHeight),
_width(tilesWidth),
_height(tilesHeight)
{
}
uint16_t Map(uint16_t x, uint16_t y) const
{
uint16_t localIndex;
uint16_t tileOffset;
calculate(x, y, &localIndex, &tileOffset);
return localIndex + tileOffset;
}
NeoTopologyHint TopologyHint(uint16_t x, uint16_t y) const
{
uint16_t localIndex;
uint16_t tileOffset;
NeoTopologyHint result;
calculate(x, y, &localIndex, &tileOffset);
if (localIndex == 0)
{
result = NeoTopologyHint_FirstOnPanel;
}
else if (localIndex == (_topo.getWidth() * _topo.getHeight() - 1))
{
result = NeoTopologyHint_LastOnPanel;
}
else
{
result = NeoTopologyHint_InPanel;
}
return result;
}
uint16_t getWidth() const
{
return _width * _topo.getWidth();
}
uint16_t getHeight() const
{
return _height * _topo.getHeight();
}
private:
const NeoTopology<T_MATRIX_LAYOUT> _topo;
const uint16_t _width;
const uint16_t _height;
void calculate(uint16_t x, uint16_t y, uint16_t* pLocalIndex, uint16_t* pTileOffset) const
{
uint16_t totalWidth = getWidth();
uint16_t totalHeight = getHeight();
if (x >= totalWidth)
{
x = totalWidth - 1;
}
if (y >= totalHeight)
{
y = totalHeight - 1;
}
uint16_t tileX = x / _topo.getWidth();
uint16_t topoX = x % _topo.getWidth();
uint16_t tileY = y / _topo.getHeight();
uint16_t topoY = y % _topo.getHeight();
*pTileOffset = T_TILE_LAYOUT::Map(_width, _height, tileX, tileY) * _topo.getWidth() * _topo.getHeight();
*pLocalIndex = _topo.Map(topoX, topoY);
}
};
+73
View File
@@ -0,0 +1,73 @@
#pragma once
/*-------------------------------------------------------------------------
NeoTopology provides a mapping feature of a 2d cordinate to linear 1d cordinate
It is used to map a matrix of NeoPixels to a index on the NeoPixelBus
Written by Michael C. Miller.
I invest time and resources providing this open source code,
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
-------------------------------------------------------------------------
This file is part of the Makuna/NeoPixelBus library.
NeoPixelBus is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
NeoPixelBus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with NeoPixel. If not, see
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
enum NeoTopologyHint
{
NeoTopologyHint_FirstOnPanel,
NeoTopologyHint_InPanel,
NeoTopologyHint_LastOnPanel,
};
template <typename T_LAYOUT> class NeoTopology
{
public:
NeoTopology(uint16_t width, uint16_t height) :
_width(width),
_height(height)
{
}
uint16_t Map(uint16_t x, uint16_t y) const
{
if (x >= _width)
{
x = _width - 1;
}
if (y >= _height)
{
y = _height - 1;
}
return T_LAYOUT::Map(_width, _height, x, y);
}
uint16_t getWidth() const
{
return _width;
}
uint16_t getHeight() const
{
return _height;
}
private:
const uint16_t _width;
const uint16_t _height;
};
+19 -1
View File
@@ -217,9 +217,27 @@ void RgbColor::Lighten(uint8_t delta)
}
}
RgbColor RgbColor::LinearBlend(RgbColor left, RgbColor right, float progress)
RgbColor RgbColor::LinearBlend(const RgbColor& left, const RgbColor& right, float progress)
{
return RgbColor( left.R + ((right.R - left.R) * progress),
left.G + ((right.G - left.G) * progress),
left.B + ((right.B - left.B) * progress));
}
RgbColor RgbColor::BilinearBlend(const RgbColor& c00,
const RgbColor& c01,
const RgbColor& c10,
const RgbColor& c11,
float x,
float y)
{
float v00 = (1.0f - x) * (1.0f - y);
float v10 = x * (1.0f - y);
float v01 = (1.0f - x) * y;
float v11 = x * y;
return RgbColor(
c00.R * v00 + c10.R * v10 + c01.R * v01 + c11.R * v11,
c00.G * v00 + c10.G * v10 + c01.G * v01 + c11.G * v11,
c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11);
}
+28 -2
View File
@@ -79,6 +79,16 @@ struct RgbColor
{
};
bool operator==(const RgbColor& other) const
{
return (R == other.R && G == other.G && B == other.B);
};
bool operator!=(const RgbColor& other) const
{
return !(*this == other);
};
// ------------------------------------------------------------------------
// CalculateBrightness will calculate the overall brightness
// NOTE: This is a simple linear brightness
@@ -93,7 +103,7 @@ struct RgbColor
void Darken(uint8_t delta);
// ------------------------------------------------------------------------
// Lighten will adjust the color by the given delta toward white
// Lighten will adjust the color by the given delta toward ite
// NOTE: This is a simple linear change
// delta - (0-255) the amount to lighten the color
// ------------------------------------------------------------------------
@@ -106,8 +116,24 @@ struct RgbColor
// progress - (0.0 - 1.0) value where 0 will return left and 1.0 will return right
// and a value between will blend the color weighted linearly between them
// ------------------------------------------------------------------------
static RgbColor LinearBlend(RgbColor left, RgbColor right, float progress);
static RgbColor LinearBlend(const RgbColor& left, const RgbColor& right, float progress);
// ------------------------------------------------------------------------
// BilinearBlend between four colors by the amount defined by 2d variable
// c00 - upper left quadrant color
// c01 - upper right quadrant color
// c10 - lower left quadrant color
// c11 - lower right quadrant color
// x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space
// y - unit value (0.0 - 1.0) that defines the blend progress in vertical space
// ------------------------------------------------------------------------
static RgbColor BilinearBlend(const RgbColor& c00,
const RgbColor& c01,
const RgbColor& c10,
const RgbColor& c11,
float x,
float y);
// ------------------------------------------------------------------------
// Red, Green, Blue color members (0-255) where
// (0,0,0) is black and (255,255,255) is white
+22 -3
View File
@@ -29,13 +29,13 @@ License along with NeoPixel. If not, see
#include "HsbColor.h"
#include "RgbwColor.h"
RgbwColor::RgbwColor(HslColor color)
RgbwColor::RgbwColor(const HslColor& color)
{
RgbColor rgbColor(color);
*this = rgbColor;
}
RgbwColor::RgbwColor(HsbColor color)
RgbwColor::RgbwColor(const HsbColor& color)
{
RgbColor rgbColor(color);
*this = rgbColor;
@@ -137,10 +137,29 @@ void RgbwColor::Lighten(uint8_t delta)
}
}
RgbwColor RgbwColor::LinearBlend(RgbwColor left, RgbwColor right, float progress)
RgbwColor RgbwColor::LinearBlend(const RgbwColor& left, const RgbwColor& right, float progress)
{
return RgbwColor( left.R + ((right.R - left.R) * progress),
left.G + ((right.G - left.G) * progress),
left.B + ((right.B - left.B) * progress),
left.W + ((right.W - left.W) * progress) );
}
RgbwColor RgbwColor::BilinearBlend(const RgbwColor& c00,
const RgbwColor& c01,
const RgbwColor& c10,
const RgbwColor& c11,
float x,
float y)
{
float v00 = (1.0f - x) * (1.0f - y);
float v10 = x * (1.0f - y);
float v01 = (1.0f - x) * y;
float v11 = x * y;
return RgbwColor(
c00.R * v00 + c10.R * v10 + c01.R * v01 + c11.R * v11,
c00.G * v00 + c10.G * v10 + c01.G * v01 + c11.G * v11,
c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11,
c00.W * v00 + c10.W * v10 + c01.W * v01 + c11.W * v11 );
}
+30 -4
View File
@@ -59,7 +59,7 @@ struct RgbwColor
// ------------------------------------------------------------------------
// Construct a RgbwColor using RgbColor
// ------------------------------------------------------------------------
RgbwColor(RgbColor color) :
RgbwColor(const RgbColor& color) :
R(color.R),
G(color.G),
B(color.B),
@@ -71,12 +71,12 @@ struct RgbwColor
// ------------------------------------------------------------------------
// Construct a RgbwColor using HslColor
// ------------------------------------------------------------------------
RgbwColor(HslColor color);
RgbwColor(const HslColor& color);
// ------------------------------------------------------------------------
// Construct a RgbwColor using HsbColor
// ------------------------------------------------------------------------
RgbwColor(HsbColor color);
RgbwColor(const HsbColor& color);
// ------------------------------------------------------------------------
// Construct a RgbwColor that will have its values set in latter operations
@@ -86,6 +86,16 @@ struct RgbwColor
{
};
bool operator==(const RgbwColor& other) const
{
return (R == other.R && G == other.G && B == other.B && W == other.W);
};
bool operator!=(const RgbwColor& other) const
{
return !(*this == other);
};
// ------------------------------------------------------------------------
// Returns if the color is grey, all values are equal other than white
// ------------------------------------------------------------------------
@@ -130,8 +140,24 @@ struct RgbwColor
// progress - (0.0 - 1.0) value where 0 will return left and 1.0 will return right
// and a value between will blend the color weighted linearly between them
// ------------------------------------------------------------------------
static RgbwColor LinearBlend(RgbwColor left, RgbwColor right, float progress);
static RgbwColor LinearBlend(const RgbwColor& left, const RgbwColor& right, float progress);
// ------------------------------------------------------------------------
// BilinearBlend between four colors by the amount defined by 2d variable
// c00 - upper left quadrant color
// c01 - upper right quadrant color
// c10 - lower left quadrant color
// c11 - lower right quadrant color
// x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space
// y - unit value (0.0 - 1.0) that defines the blend progress in vertical space
// ------------------------------------------------------------------------
static RgbwColor BilinearBlend(const RgbwColor& c00,
const RgbwColor& c01,
const RgbwColor& c10,
const RgbwColor& c11,
float x,
float y);
// ------------------------------------------------------------------------
// Red, Green, Blue, White color members (0-255) where
// (0,0,0,0) is black and (255,255,255, 0) and (0,0,0,255) is white