aboutsummaryrefslogtreecommitdiff
path: root/include/SColor.h
diff options
context:
space:
mode:
authorcutealien <cutealien@dfc29bdd-3216-0410-991c-e03cc46cb475>2020-01-03 19:05:16 +0000
committercutealien <cutealien@dfc29bdd-3216-0410-991c-e03cc46cb475>2020-01-03 19:05:16 +0000
commit2ae2a551a6290f46734307bbfdafea4b1a2cf2ba (patch)
treeba2f0b468640e44899fed3df2d4cc58795f4a003 /include/SColor.h
downloadirrlicht-2ae2a551a6290f46734307bbfdafea4b1a2cf2ba.tar.xz
Merging r5975 through r6036 from trunk to ogl-es branch.
GLES drivers adapted, but only did make compile-tests. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6038 dfc29bdd-3216-0410-991c-e03cc46cb475
Diffstat (limited to 'include/SColor.h')
-rw-r--r--include/SColor.h812
1 files changed, 812 insertions, 0 deletions
diff --git a/include/SColor.h b/include/SColor.h
new file mode 100644
index 0000000..7384da9
--- /dev/null
+++ b/include/SColor.h
@@ -0,0 +1,812 @@
+// Copyright (C) 2002-2012 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#ifndef __COLOR_H_INCLUDED__
+#define __COLOR_H_INCLUDED__
+
+#include "irrTypes.h"
+#include "irrMath.h"
+
+namespace irr
+{
+namespace video
+{
+ //! An enum for the color format of textures used by the Irrlicht Engine.
+ /** A color format specifies how color information is stored.
+ NOTE: Byte order in memory is usually flipped (it's probably correct in bitmap files, but flipped on reading).
+ So for example ECF_A8R8G8B8 is BGRA in memory same as in DX9's D3DFMT_A8R8G8B8 format.
+ */
+ enum ECOLOR_FORMAT
+ {
+ //! 16 bit color format used by the software driver.
+ /** It is thus preferred by all other irrlicht engine video drivers.
+ There are 5 bits for every color component, and a single bit is left
+ for alpha information. */
+ ECF_A1R5G5B5 = 0,
+
+ //! Standard 16 bit color format.
+ ECF_R5G6B5,
+
+ //! 24 bit color, no alpha channel, but 8 bit for red, green and blue.
+ //! Warning: 24 bit formats tend to be badly supported. Depending on driver it's usually converted to another
+ // format or even not working at all. It's mostly better to use 16-bit or 32-bit formats.
+ ECF_R8G8B8,
+
+ //! Default 32 bit color format. 8 bits are used for every component: red, green, blue and alpha.
+ //! Warning: This tends to be BGRA in memory (it's ARGB on file, but with usual big-endian memory it's flipped)
+ ECF_A8R8G8B8,
+
+ /** Compressed image formats. **/
+
+ //! DXT1 color format.
+ ECF_DXT1,
+
+ //! DXT2 color format.
+ ECF_DXT2,
+
+ //! DXT3 color format.
+ ECF_DXT3,
+
+ //! DXT4 color format.
+ ECF_DXT4,
+
+ //! DXT5 color format.
+ ECF_DXT5,
+
+ //! PVRTC RGB 2bpp.
+ ECF_PVRTC_RGB2,
+
+ //! PVRTC ARGB 2bpp.
+ ECF_PVRTC_ARGB2,
+
+ //! PVRTC RGB 4bpp.
+ ECF_PVRTC_RGB4,
+
+ //! PVRTC ARGB 4bpp.
+ ECF_PVRTC_ARGB4,
+
+ //! PVRTC2 ARGB 2bpp.
+ ECF_PVRTC2_ARGB2,
+
+ //! PVRTC2 ARGB 4bpp.
+ ECF_PVRTC2_ARGB4,
+
+ //! ETC1 RGB.
+ ECF_ETC1,
+
+ //! ETC2 RGB.
+ ECF_ETC2_RGB,
+
+ //! ETC2 ARGB.
+ ECF_ETC2_ARGB,
+
+ /** The following formats may only be used for render target textures. */
+
+ /** Floating point formats. */
+
+ //! 16 bit format using 16 bits for the red channel.
+ ECF_R16F,
+
+ //! 32 bit format using 16 bits for the red and green channels.
+ ECF_G16R16F,
+
+ //! 64 bit format using 16 bits for the red, green, blue and alpha channels.
+ ECF_A16B16G16R16F,
+
+ //! 32 bit format using 32 bits for the red channel.
+ ECF_R32F,
+
+ //! 64 bit format using 32 bits for the red and green channels.
+ ECF_G32R32F,
+
+ //! 128 bit format using 32 bits for the red, green, blue and alpha channels.
+ ECF_A32B32G32R32F,
+
+ /** Unsigned normalized integer formats. */
+
+ //! 8 bit format using 8 bits for the red channel.
+ ECF_R8,
+
+ //! 16 bit format using 8 bits for the red and green channels.
+ ECF_R8G8,
+
+ //! 16 bit format using 16 bits for the red channel.
+ ECF_R16,
+
+ //! 32 bit format using 16 bits for the red and green channels.
+ ECF_R16G16,
+
+ /** Depth and stencil formats. */
+
+ //! 16 bit format using 16 bits for depth.
+ ECF_D16,
+
+ //! 32 bit format using 32 bits for depth.
+ ECF_D32,
+
+ //! 32 bit format using 24 bits for depth and 8 bits for stencil.
+ ECF_D24S8,
+
+ //! Unknown color format:
+ ECF_UNKNOWN
+ };
+
+ //! Names for ECOLOR_FORMAT types
+ const c8* const ColorFormatNames[ECF_UNKNOWN+2] =
+ {
+ "A1R5G5B5",
+ "R5G6B5",
+ "R8G8B8",
+ "A8R8G8B8",
+ "DXT1",
+ "DXT2",
+ "DXT3",
+ "DXT4",
+ "DXT5",
+ "PVRTC_RGB2",
+ "PVRTC_ARGB2",
+ "PVRTC_RGB4",
+ "PVRTC_ARGB4",
+ "PVRTC2_ARGB2",
+ "PVRTC2_ARGB4",
+ "ETC1",
+ "ETC2_RGB",
+ "ETC2_ARGB",
+ "R16F",
+ "G16R16F",
+ "A16B16G16R16F",
+ "R32F",
+ "G32R32F",
+ "A32B32G32R32F",
+ "R8",
+ "R8G8",
+ "R16",
+ "R16G16",
+ "D16",
+ "D32",
+ "D24S8",
+ "UNKNOWN",
+ 0
+ };
+
+
+ //! Creates a 16 bit A1R5G5B5 color
+ inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a=0xFF)
+ {
+ return (u16)((a & 0x80) << 8 |
+ (r & 0xF8) << 7 |
+ (g & 0xF8) << 2 |
+ (b & 0xF8) >> 3);
+ }
+
+
+ //! Creates a 16 bit A1R5G5B5 color
+ inline u16 RGB16(u32 r, u32 g, u32 b)
+ {
+ return RGBA16(r,g,b);
+ }
+
+
+ //! Creates a 16bit A1R5G5B5 color, based on 16bit input values
+ inline u16 RGB16from16(u16 r, u16 g, u16 b)
+ {
+ return (0x8000 |
+ (r & 0x1F) << 10 |
+ (g & 0x1F) << 5 |
+ (b & 0x1F));
+ }
+
+
+ //! Converts a 32bit (X8R8G8B8) color to a 16bit A1R5G5B5 color
+ inline u16 X8R8G8B8toA1R5G5B5(u32 color)
+ {
+ return (u16)(0x8000 |
+ ( color & 0x00F80000) >> 9 |
+ ( color & 0x0000F800) >> 6 |
+ ( color & 0x000000F8) >> 3);
+ }
+
+
+ //! Converts a 32bit (A8R8G8B8) color to a 16bit A1R5G5B5 color
+ inline u16 A8R8G8B8toA1R5G5B5(u32 color)
+ {
+ return (u16)(( color & 0x80000000) >> 16|
+ ( color & 0x00F80000) >> 9 |
+ ( color & 0x0000F800) >> 6 |
+ ( color & 0x000000F8) >> 3);
+ }
+
+
+ //! Converts a 32bit (A8R8G8B8) color to a 16bit R5G6B5 color
+ inline u16 A8R8G8B8toR5G6B5(u32 color)
+ {
+ return (u16)(( color & 0x00F80000) >> 8 |
+ ( color & 0x0000FC00) >> 5 |
+ ( color & 0x000000F8) >> 3);
+ }
+
+
+ //! Convert A8R8G8B8 Color from A1R5G5B5 color
+ /** build a nicer 32bit Color by extending dest lower bits with source high bits. */
+ inline u32 A1R5G5B5toA8R8G8B8(u16 color)
+ {
+ return ( (( -( (s32) color & 0x00008000 ) >> (s32) 31 ) & 0xFF000000 ) |
+ (( color & 0x00007C00 ) << 9) | (( color & 0x00007000 ) << 4) |
+ (( color & 0x000003E0 ) << 6) | (( color & 0x00000380 ) << 1) |
+ (( color & 0x0000001F ) << 3) | (( color & 0x0000001C ) >> 2)
+ );
+ }
+
+
+ //! Returns A8R8G8B8 Color from R5G6B5 color
+ inline u32 R5G6B5toA8R8G8B8(u16 color)
+ {
+ return 0xFF000000 |
+ ((color & 0xF800) << 8)|
+ ((color & 0x07E0) << 5)|
+ ((color & 0x001F) << 3);
+ }
+
+
+ //! Returns A1R5G5B5 Color from R5G6B5 color
+ inline u16 R5G6B5toA1R5G5B5(u16 color)
+ {
+ return 0x8000 | (((color & 0xFFC0) >> 1) | (color & 0x1F));
+ }
+
+
+ //! Returns R5G6B5 Color from A1R5G5B5 color
+ inline u16 A1R5G5B5toR5G6B5(u16 color)
+ {
+ return (((color & 0x7FE0) << 1) | (color & 0x1F));
+ }
+
+
+
+ //! Returns the alpha component from A1R5G5B5 color
+ /** In Irrlicht, alpha refers to opacity.
+ \return The alpha value of the color. 0 is transparent, 1 is opaque. */
+ inline u32 getAlpha(u16 color)
+ {
+ return ((color >> 15)&0x1);
+ }
+
+
+ //! Returns the red component from A1R5G5B5 color.
+ /** Shift left by 3 to get 8 bit value. */
+ inline u32 getRed(u16 color)
+ {
+ return ((color >> 10)&0x1F);
+ }
+
+
+ //! Returns the green component from A1R5G5B5 color
+ /** Shift left by 3 to get 8 bit value. */
+ inline u32 getGreen(u16 color)
+ {
+ return ((color >> 5)&0x1F);
+ }
+
+
+ //! Returns the blue component from A1R5G5B5 color
+ /** Shift left by 3 to get 8 bit value. */
+ inline u32 getBlue(u16 color)
+ {
+ return (color & 0x1F);
+ }
+
+
+ //! Returns the average from a 16 bit A1R5G5B5 color
+ inline s32 getAverage(s16 color)
+ {
+ return ((getRed(color)<<3) + (getGreen(color)<<3) + (getBlue(color)<<3)) / 3;
+ }
+
+
+ //! Class representing a 32 bit ARGB color.
+ /** The color values for alpha, red, green, and blue are
+ stored in a single u32. So all four values may be between 0 and 255.
+ Alpha in Irrlicht is opacity, so 0 is fully transparent, 255 is fully opaque (solid).
+ This class is used by most parts of the Irrlicht Engine
+ to specify a color. Another way is using the class SColorf, which
+ stores the color values in 4 floats.
+ This class must consist of only one u32 and must not use virtual functions.
+ */
+ class SColor
+ {
+ public:
+
+ //! Constructor of the Color. Does nothing.
+ /** The color value is not initialized to save time. */
+ SColor() {}
+
+ //! Constructs the color from 4 values representing the alpha, red, green and blue component.
+ /** Must be values between 0 and 255. */
+ SColor (u32 a, u32 r, u32 g, u32 b)
+ : color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {}
+
+ //! Constructs the color from a 32 bit value. Could be another color.
+ SColor(u32 clr)
+ : color(clr) {}
+
+ //! Returns the alpha component of the color.
+ /** The alpha component defines how opaque a color is.
+ \return The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */
+ u32 getAlpha() const { return color>>24; }
+
+ //! Returns the red component of the color.
+ /** \return Value between 0 and 255, specifying how red the color is.
+ 0 means no red, 255 means full red. */
+ u32 getRed() const { return (color>>16) & 0xff; }
+
+ //! Returns the green component of the color.
+ /** \return Value between 0 and 255, specifying how green the color is.
+ 0 means no green, 255 means full green. */
+ u32 getGreen() const { return (color>>8) & 0xff; }
+
+ //! Returns the blue component of the color.
+ /** \return Value between 0 and 255, specifying how blue the color is.
+ 0 means no blue, 255 means full blue. */
+ u32 getBlue() const { return color & 0xff; }
+
+ //! Get lightness of the color in the range [0,255]
+ f32 getLightness() const
+ {
+ return 0.5f*(core::max_(core::max_(getRed(),getGreen()),getBlue())+core::min_(core::min_(getRed(),getGreen()),getBlue()));
+ }
+
+ //! Get luminance of the color in the range [0,255].
+ f32 getLuminance() const
+ {
+ return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue();
+ }
+
+ //! Get average intensity of the color in the range [0,255].
+ u32 getAverage() const
+ {
+ return ( getRed() + getGreen() + getBlue() ) / 3;
+ }
+
+ //! Sets the alpha component of the Color.
+ /** The alpha component defines how transparent a color should be.
+ \param a The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */
+ void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); }
+
+ //! Sets the red component of the Color.
+ /** \param r: Has to be a value between 0 and 255.
+ 0 means no red, 255 means full red. */
+ void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); }
+
+ //! Sets the green component of the Color.
+ /** \param g: Has to be a value between 0 and 255.
+ 0 means no green, 255 means full green. */
+ void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); }
+
+ //! Sets the blue component of the Color.
+ /** \param b: Has to be a value between 0 and 255.
+ 0 means no blue, 255 means full blue. */
+ void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); }
+
+ //! Calculates a 16 bit A1R5G5B5 value of this color.
+ /** \return 16 bit A1R5G5B5 value of this color. */
+ u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); }
+
+ //! Converts color to OpenGL color format
+ /** From ARGB to RGBA in 4 byte components for endian aware
+ passing to OpenGL
+ \param dest: address where the 4x8 bit OpenGL color is stored. */
+ void toOpenGLColor(u8* dest) const
+ {
+ *dest = (u8)getRed();
+ *++dest = (u8)getGreen();
+ *++dest = (u8)getBlue();
+ *++dest = (u8)getAlpha();
+ }
+
+ //! Sets all four components of the color at once.
+ /** Constructs the color from 4 values representing the alpha,
+ red, green and blue components of the color. Must be values
+ between 0 and 255.
+ \param a: Alpha component of the color. The alpha component
+ defines how transparent a color should be. Has to be a value
+ between 0 and 255. 255 means not transparent (opaque), 0 means
+ fully transparent.
+ \param r: Sets the red component of the Color. Has to be a
+ value between 0 and 255. 0 means no red, 255 means full red.
+ \param g: Sets the green component of the Color. Has to be a
+ value between 0 and 255. 0 means no green, 255 means full
+ green.
+ \param b: Sets the blue component of the Color. Has to be a
+ value between 0 and 255. 0 means no blue, 255 means full blue. */
+ void set(u32 a, u32 r, u32 g, u32 b)
+ {
+ color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff));
+ }
+ void set(u32 col) { color = col; }
+
+ //! Compares the color to another color.
+ /** \return True if the colors are the same, and false if not. */
+ bool operator==(const SColor& other) const { return other.color == color; }
+
+ //! Compares the color to another color.
+ /** \return True if the colors are different, and false if they are the same. */
+ bool operator!=(const SColor& other) const { return other.color != color; }
+
+ //! comparison operator
+ /** \return True if this color is smaller than the other one */
+ bool operator<(const SColor& other) const { return (color < other.color); }
+
+ //! Adds two colors, result is clamped to 0..255 values
+ /** \param other Color to add to this color
+ \return Addition of the two colors, clamped to 0..255 values */
+ SColor operator+(const SColor& other) const
+ {
+ return SColor(core::min_(getAlpha() + other.getAlpha(), 255u),
+ core::min_(getRed() + other.getRed(), 255u),
+ core::min_(getGreen() + other.getGreen(), 255u),
+ core::min_(getBlue() + other.getBlue(), 255u));
+ }
+
+ //! Interpolates the color with a f32 value to another color
+ /** \param other: Other color
+ \param d: value between 0.0f and 1.0f. d=0 returns other, d=1 returns this, values between interpolate.
+ \return Interpolated color. */
+ SColor getInterpolated(const SColor &other, f32 d) const
+ {
+ d = core::clamp(d, 0.f, 1.f);
+ const f32 inv = 1.0f - d;
+ return SColor((u32)core::round32(other.getAlpha()*inv + getAlpha()*d),
+ (u32)core::round32(other.getRed()*inv + getRed()*d),
+ (u32)core::round32(other.getGreen()*inv + getGreen()*d),
+ (u32)core::round32(other.getBlue()*inv + getBlue()*d));
+ }
+
+ //! Returns interpolated color. ( quadratic )
+ /** \param c1: first color to interpolate with
+ \param c2: second color to interpolate with
+ \param d: value between 0.0f and 1.0f. */
+ SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, f32 d) const
+ {
+ // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d;
+ d = core::clamp(d, 0.f, 1.f);
+ const f32 inv = 1.f - d;
+ const f32 mul0 = inv * inv;
+ const f32 mul1 = 2.f * d * inv;
+ const f32 mul2 = d * d;
+
+ return SColor(
+ core::clamp( core::floor32(
+ getAlpha() * mul0 + c1.getAlpha() * mul1 + c2.getAlpha() * mul2 ), 0, 255 ),
+ core::clamp( core::floor32(
+ getRed() * mul0 + c1.getRed() * mul1 + c2.getRed() * mul2 ), 0, 255 ),
+ core::clamp ( core::floor32(
+ getGreen() * mul0 + c1.getGreen() * mul1 + c2.getGreen() * mul2 ), 0, 255 ),
+ core::clamp ( core::floor32(
+ getBlue() * mul0 + c1.getBlue() * mul1 + c2.getBlue() * mul2 ), 0, 255 ));
+ }
+
+ //! set the color by expecting data in the given format
+ /** \param data: must point to valid memory containing color information in the given format
+ \param format: tells the format in which data is available
+ */
+ void setData(const void *data, ECOLOR_FORMAT format)
+ {
+ switch (format)
+ {
+ case ECF_A1R5G5B5:
+ color = A1R5G5B5toA8R8G8B8(*(u16*)data);
+ break;
+ case ECF_R5G6B5:
+ color = R5G6B5toA8R8G8B8(*(u16*)data);
+ break;
+ case ECF_A8R8G8B8:
+ color = *(u32*)data;
+ break;
+ case ECF_R8G8B8:
+ {
+ const u8* p = (u8*)data;
+ set(255, p[0],p[1],p[2]);
+ }
+ break;
+ default:
+ color = 0xffffffff;
+ break;
+ }
+ }
+
+ //! Write the color to data in the defined format
+ /** \param data: target to write the color. Must contain sufficiently large memory to receive the number of bytes neede for format
+ \param format: tells the format used to write the color into data
+ */
+ void getData(void *data, ECOLOR_FORMAT format) const
+ {
+ switch(format)
+ {
+ case ECF_A1R5G5B5:
+ {
+ u16 * dest = (u16*)data;
+ *dest = video::A8R8G8B8toA1R5G5B5( color );
+ }
+ break;
+
+ case ECF_R5G6B5:
+ {
+ u16 * dest = (u16*)data;
+ *dest = video::A8R8G8B8toR5G6B5( color );
+ }
+ break;
+
+ case ECF_R8G8B8:
+ {
+ u8* dest = (u8*)data;
+ dest[0] = (u8)getRed();
+ dest[1] = (u8)getGreen();
+ dest[2] = (u8)getBlue();
+ }
+ break;
+
+ case ECF_A8R8G8B8:
+ {
+ u32 * dest = (u32*)data;
+ *dest = color;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ //! color in A8R8G8B8 Format
+ u32 color;
+ };
+
+
+ //! Class representing a color with four floats.
+ /** The color values for red, green, blue
+ and alpha are each stored in a 32 bit floating point variable.
+ So all four values may be between 0.0f and 1.0f.
+ Another, faster way to define colors is using the class SColor, which
+ stores the color values in a single 32 bit integer.
+ */
+ class SColorf
+ {
+ public:
+ //! Default constructor for SColorf.
+ /** Sets red, green and blue to 0.0f and alpha to 1.0f. */
+ SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {}
+
+ //! Constructs a color from up to four color values: red, green, blue, and alpha.
+ /** \param r: Red color component. Should be a value between
+ 0.0f meaning no red and 1.0f, meaning full red.
+ \param g: Green color component. Should be a value between 0.0f
+ meaning no green and 1.0f, meaning full green.
+ \param b: Blue color component. Should be a value between 0.0f
+ meaning no blue and 1.0f, meaning full blue.
+ \param a: Alpha color component of the color. The alpha
+ component defines how transparent a color should be. Has to be
+ a value between 0.0f and 1.0f, 1.0f means not transparent
+ (opaque), 0.0f means fully transparent. */
+ SColorf(f32 r, f32 g, f32 b, f32 a = 1.0f) : r(r), g(g), b(b), a(a) {}
+
+ //! Constructs a color from 32 bit Color.
+ /** \param c: 32 bit color from which this SColorf class is
+ constructed from. */
+ SColorf(SColor c)
+ {
+ const f32 inv = 1.0f / 255.0f;
+ r = c.getRed() * inv;
+ g = c.getGreen() * inv;
+ b = c.getBlue() * inv;
+ a = c.getAlpha() * inv;
+ }
+
+ //! Converts this color to a SColor without floats.
+ SColor toSColor() const
+ {
+ return SColor((u32)core::round32(a*255.0f), (u32)core::round32(r*255.0f), (u32)core::round32(g*255.0f), (u32)core::round32(b*255.0f));
+ }
+
+ //! Sets three color components to new values at once.
+ /** \param rr: Red color component. Should be a value between 0.0f meaning
+ no red (=black) and 1.0f, meaning full red.
+ \param gg: Green color component. Should be a value between 0.0f meaning
+ no green (=black) and 1.0f, meaning full green.
+ \param bb: Blue color component. Should be a value between 0.0f meaning
+ no blue (=black) and 1.0f, meaning full blue. */
+ void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; }
+
+ //! Sets all four color components to new values at once.
+ /** \param aa: Alpha component. Should be a value between 0.0f meaning
+ fully transparent and 1.0f, meaning opaque.
+ \param rr: Red color component. Should be a value between 0.0f meaning
+ no red and 1.0f, meaning full red.
+ \param gg: Green color component. Should be a value between 0.0f meaning
+ no green and 1.0f, meaning full green.
+ \param bb: Blue color component. Should be a value between 0.0f meaning
+ no blue and 1.0f, meaning full blue. */
+ void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; }
+
+ //! Interpolates the color with a f32 value to another color
+ /** \param other: Other color
+ \param d: value between 0.0f and 1.0f
+ \return Interpolated color. */
+ SColorf getInterpolated(const SColorf &other, f32 d) const
+ {
+ d = core::clamp(d, 0.f, 1.f);
+ const f32 inv = 1.0f - d;
+ return SColorf(other.r*inv + r*d,
+ other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d);
+ }
+
+ //! Returns interpolated color. ( quadratic )
+ /** \param c1: first color to interpolate with
+ \param c2: second color to interpolate with
+ \param d: value between 0.0f and 1.0f. */
+ inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2,
+ f32 d) const
+ {
+ d = core::clamp(d, 0.f, 1.f);
+ // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d;
+ const f32 inv = 1.f - d;
+ const f32 mul0 = inv * inv;
+ const f32 mul1 = 2.f * d * inv;
+ const f32 mul2 = d * d;
+
+ return SColorf (r * mul0 + c1.r * mul1 + c2.r * mul2,
+ g * mul0 + c1.g * mul1 + c2.g * mul2,
+ b * mul0 + c1.b * mul1 + c2.b * mul2,
+ a * mul0 + c1.a * mul1 + c2.a * mul2);
+ }
+
+
+ //! Sets a color component by index. R=0, G=1, B=2, A=3
+ void setColorComponentValue(s32 index, f32 value)
+ {
+ switch(index)
+ {
+ case 0: r = value; break;
+ case 1: g = value; break;
+ case 2: b = value; break;
+ case 3: a = value; break;
+ }
+ }
+
+ //! Returns the alpha component of the color in the range 0.0 (transparent) to 1.0 (opaque)
+ f32 getAlpha() const { return a; }
+
+ //! Returns the red component of the color in the range 0.0 to 1.0
+ f32 getRed() const { return r; }
+
+ //! Returns the green component of the color in the range 0.0 to 1.0
+ f32 getGreen() const { return g; }
+
+ //! Returns the blue component of the color in the range 0.0 to 1.0
+ f32 getBlue() const { return b; }
+
+ //! red color component
+ f32 r;
+
+ //! green color component
+ f32 g;
+
+ //! blue component
+ f32 b;
+
+ //! alpha color component
+ f32 a;
+ };
+
+
+ //! Class representing a color in HSL format
+ /** The color values for hue, saturation, luminance
+ are stored in 32bit floating point variables. Hue is in range [0,360],
+ Luminance and Saturation are in percent [0,100]
+ */
+ class SColorHSL
+ {
+ public:
+ SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f )
+ : Hue ( h ), Saturation ( s ), Luminance ( l ) {}
+
+ void fromRGB(const SColorf &color);
+ void toRGB(SColorf &color) const;
+
+ f32 Hue;
+ f32 Saturation;
+ f32 Luminance;
+
+ private:
+ inline f32 toRGB1(f32 rm1, f32 rm2, f32 rh) const;
+
+ };
+
+ inline void SColorHSL::fromRGB(const SColorf &color)
+ {
+ const f32 maxVal = core::max_(color.getRed(), color.getGreen(), color.getBlue());
+ const f32 minVal = (f32)core::min_(color.getRed(), color.getGreen(), color.getBlue());
+ Luminance = (maxVal+minVal)*50;
+ if (core::equals(maxVal, minVal))
+ {
+ Hue=0.f;
+ Saturation=0.f;
+ return;
+ }
+
+ const f32 delta = maxVal-minVal;
+ if ( Luminance <= 50 )
+ {
+ Saturation = (delta)/(maxVal+minVal);
+ }
+ else
+ {
+ Saturation = (delta)/(2-maxVal-minVal);
+ }
+ Saturation *= 100;
+
+ if (core::equals(maxVal, color.getRed()))
+ Hue = (color.getGreen()-color.getBlue())/delta;
+ else if (core::equals(maxVal, color.getGreen()))
+ Hue = 2+((color.getBlue()-color.getRed())/delta);
+ else // blue is max
+ Hue = 4+((color.getRed()-color.getGreen())/delta);
+
+ Hue *= 60.0f;
+ while ( Hue < 0.f )
+ Hue += 360;
+ }
+
+
+ inline void SColorHSL::toRGB(SColorf &color) const
+ {
+ const f32 l = Luminance/100;
+ if (core::iszero(Saturation)) // grey
+ {
+ color.set(l, l, l);
+ return;
+ }
+
+ f32 rm2;
+
+ if ( Luminance <= 50 )
+ {
+ rm2 = l + l * (Saturation/100);
+ }
+ else
+ {
+ rm2 = l + (1 - l) * (Saturation/100);
+ }
+
+ const f32 rm1 = 2.0f * l - rm2;
+
+ const f32 h = Hue / 360.0f;
+ color.set( toRGB1(rm1, rm2, h + 1.f/3.f),
+ toRGB1(rm1, rm2, h),
+ toRGB1(rm1, rm2, h - 1.f/3.f)
+ );
+ }
+
+
+ // algorithm from Foley/Van-Dam
+ inline f32 SColorHSL::toRGB1(f32 rm1, f32 rm2, f32 rh) const
+ {
+ if (rh<0)
+ rh += 1;
+ if (rh>1)
+ rh -= 1;
+
+ if (rh < 1.f/6.f)
+ rm1 = rm1 + (rm2 - rm1) * rh*6.f;
+ else if (rh < 0.5f)
+ rm1 = rm2;
+ else if (rh < 2.f/3.f)
+ rm1 = rm1 + (rm2 - rm1) * ((2.f/3.f)-rh)*6.f;
+
+ return rm1;
+ }
+
+} // end namespace video
+} // end namespace irr
+
+#endif