542 lines
17 KiB
C++
542 lines
17 KiB
C++
// Copyright (C) 2002-2007 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
|
|
{
|
|
//! Creates a 16 bit A1R5G5B5 color
|
|
inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a)
|
|
{
|
|
return ((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,0xFF);
|
|
}
|
|
|
|
|
|
//! Creates a 16 bit A1R5G5B5 color, based on 16 bit input values
|
|
inline u16 RGB16from16(u16 r, u16 g, u16 b)
|
|
{
|
|
return (r & 0x1F) << 10 |
|
|
(g & 0x1F) << 5 |
|
|
(b & 0x1F);
|
|
}
|
|
|
|
|
|
//! Converts a 32 bit (X8R8G8B8) color to a 16 A1R5G5B5 color
|
|
inline u16 X8R8G8B8toA1R5G5B5(u32 color)
|
|
{
|
|
return ( 0x8000 |
|
|
( color & 0x00F80000) >> 9 |
|
|
( color & 0x0000F800) >> 6 |
|
|
( color & 0x000000F8) >> 3);
|
|
}
|
|
|
|
|
|
//! Converts a 32 bit (A8R8G8B8) color to a 16 A1R5G5B5 color
|
|
inline u16 A8R8G8B8toA1R5G5B5(u32 color)
|
|
{
|
|
return (( color & 0x80000000) >> 16|
|
|
( color & 0x00F80000) >> 9 |
|
|
( color & 0x0000F800) >> 6 |
|
|
( color & 0x000000F8) >> 3);
|
|
}
|
|
|
|
|
|
//! Converts a 32 bit (A8R8G8B8) color to a 16 R5G6B5 color
|
|
inline u16 A8R8G8B8toR5G6B5(u32 color)
|
|
{
|
|
return (( color & 0x00F80000) >> 8 |
|
|
( color & 0x0000FC00) >> 5 |
|
|
( color & 0x000000F8) >> 3);
|
|
}
|
|
|
|
|
|
//! Returns A8R8G8B8 Color from A1R5G5B5 color
|
|
//! build a nicer 32 Bit 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
|
|
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 red component from A1R5G5B5 color.
|
|
//! Shift left by 3 to get 8 bit value.
|
|
inline s32 getRedSigned(u16 color)
|
|
{
|
|
return ((color >> 10)&0x1F);
|
|
}
|
|
|
|
|
|
//! Returns the green component from A1R5G5B5 color
|
|
//! Shift left by 3 to get 8 bit value.
|
|
inline s32 getGreenSigned(u16 color)
|
|
{
|
|
return ((color >> 5)&0x1F);
|
|
}
|
|
|
|
|
|
//! Returns the blue component from A1R5G5B5 color
|
|
//! Shift left by 3 to get 8 bit value.
|
|
inline s32 getBlueSigned(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 s32. So all four values may be between 0 and 255.
|
|
This class is used by most parts of the Irrlicht Engine
|
|
to specify a color. Another way is using the class Colorf, which
|
|
stores the color values in 4 floats.
|
|
*/
|
|
class SColor
|
|
{
|
|
public:
|
|
|
|
//! Constructor of the Color. Does nothing. The color value
|
|
//! is not initialized to save time.
|
|
inline SColor() {}
|
|
|
|
//! Constructs the color from 4 values representing the alpha, red, green and
|
|
//! blue components of the color. Must be values between 0 and 255.
|
|
inline 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.
|
|
inline SColor(u32 clr)
|
|
: color(clr) {}
|
|
|
|
//! Returns the alpha component of the color. The alpha component
|
|
//! defines how transparent a color should be.
|
|
//! 0 means not transparent (opaque), 255 means fully transparent.
|
|
inline u32 getAlpha() const { return color>>24; }
|
|
|
|
//! Returns the red component of the color.
|
|
//! \return Returns a value between 0 and 255, specifying how red the color is.
|
|
//! 0 means no red, 255 means full red.
|
|
inline u32 getRed() const { return (color>>16) & 0xff; }
|
|
|
|
//! Returns the green component of the color.
|
|
//! \return Returns a value between 0 and 255, specifying how green the color is.
|
|
//! 0 means no green, 255 means full green.
|
|
inline u32 getGreen() const { return (color>>8) & 0xff; }
|
|
|
|
//! Returns the blue component of the color.
|
|
//! \return Returns a value between 0 and 255, specifying how blue the color is.
|
|
//! 0 means no blue, 255 means full blue.
|
|
inline u32 getBlue() const { return color & 0xff; }
|
|
|
|
//! Returns the luminance of the color.
|
|
inline f32 getLuminance() const
|
|
{
|
|
return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue();
|
|
}
|
|
|
|
//! Returns the average intensity of the color.
|
|
inline 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: Has to be a value between 0 and 255.
|
|
//! 0 means not transparent (opaque), 255 means fully transparent.
|
|
inline 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 (=black), 255 means full red.
|
|
inline 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 (=black), 255 means full green.
|
|
inline 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 (=black), 255 means full blue.
|
|
inline void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); }
|
|
|
|
//! Calculates a 16 bit A1R5G5B5 value of this color.
|
|
//! \return Returns the 16 bit A1R5G5B5 value of this color.
|
|
inline 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.
|
|
inline void toOpenGLColor(u8* dest) const
|
|
{
|
|
*dest = getRed();
|
|
*++dest = getGreen();
|
|
*++dest = getBlue();
|
|
*++dest = 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.
|
|
//! 0 means not transparent (opaque), 255 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 (=black), 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 (=black), 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 (=black), 255 means full blue.
|
|
inline void set(u32 a, u32 r, u32 g, u32 b) { color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)); }
|
|
inline void set(u32 col) { color = col; }
|
|
|
|
//! Compares the color to another color.
|
|
//! \return Returns true if the colors are the same, and false if not.
|
|
inline bool operator==(const SColor& other) const { return other.color == color; }
|
|
|
|
//! Compares the color to another color.
|
|
//! \return Returns true if the colors are different, and false if they are the same.
|
|
inline bool operator!=(const SColor& other) const { return other.color != color; }
|
|
|
|
//! Adds two colors
|
|
inline SColor operator+(const SColor& other) const
|
|
{
|
|
s32 a = getAlpha() + other.getAlpha();
|
|
if (a > 255)
|
|
a = 255;
|
|
|
|
s32 r = getRed() + other.getRed();
|
|
if (r > 255)
|
|
r = 255;
|
|
|
|
s32 g = getGreen() + other.getGreen();
|
|
if (g > 255)
|
|
g = 255;
|
|
|
|
s32 b = getBlue() + other.getBlue();
|
|
if (b > 255)
|
|
b = 255;
|
|
|
|
return SColor(a,r,g,b);
|
|
}
|
|
|
|
//! Interpolates the color with a f32 value to another color
|
|
//! \param other: Other color
|
|
//! \param d: value between 0.0f and 1.0f
|
|
//! \return Returns interpolated color.
|
|
inline SColor getInterpolated(const SColor &other, f32 d) const
|
|
{
|
|
const f32 inv = 1.0f - d;
|
|
return SColor((u32)(other.getAlpha()*inv + getAlpha()*d),
|
|
(u32)(other.getRed()*inv + getRed()*d),
|
|
(u32)(other.getGreen()*inv + getGreen()*d),
|
|
(u32)(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. */
|
|
inline SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, const f32 d) const
|
|
{
|
|
// 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 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 ));
|
|
}
|
|
|
|
//! 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.
|
|
This class is rarely used by the Irrlicht Engine
|
|
to specify a color. Another, faster way is using the class Color, which
|
|
stores the color values in a single 32 bit integer.
|
|
*/
|
|
class SColorf
|
|
{
|
|
public:
|
|
|
|
//! Constructs a color. All values are initialised with 0.0f, resulting
|
|
//! in a black color.
|
|
SColorf() : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {};
|
|
|
|
//! Constructs a color from three color values: red, green and blue.
|
|
//! \param r: Red color component. Should be a value between 0.0f meaning
|
|
//! no red (=black) and 1.0f, meaning full red.
|
|
//! \param g: Green color component. Should be a value between 0.0f meaning
|
|
//! no green (=black) and 1.0f, meaning full green.
|
|
//! \param b: Blue color component. Should be a value between 0.0f meaning
|
|
//! no blue (=black) and 1.0f, meaning full blue.
|
|
SColorf(f32 r, f32 g, f32 b) : r(r), g(g), b(b), a(1.0f) {};
|
|
|
|
//! Constructs a color from four color values: red, green, blue, and alpha.
|
|
//! \param r: Red color component. Should be a value between 0.0f meaning
|
|
//! no red (=black) and 1.0f, meaning full red.
|
|
//! \param g: Green color component. Should be a value between 0.0f meaning
|
|
//! no green (=black) and 1.0f, meaning full green.
|
|
//! \param b: Blue color component. Should be a value between 0.0f meaning
|
|
//! no blue (=black) 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,
|
|
//! 0.0f means not transparent (opaque), 1.0f means fully transparent.
|
|
SColorf(f32 r, f32 g, f32 b, f32 a) : r(r), g(g), b(b), a(a) {};
|
|
|
|
//! Constructs a color from 32 bit Color.
|
|
//! \param c: 32 bit color value from which this Colorf 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((s32)(a*255.0f), (s32)(r*255.0f), (s32)(g*255.0f), (s32)(b*255.0f));
|
|
}
|
|
|
|
//! red color component
|
|
f32 r;
|
|
|
|
//! green color component
|
|
f32 g;
|
|
|
|
//! blue component
|
|
f32 b;
|
|
|
|
//! alpha color component
|
|
f32 a;
|
|
|
|
//! 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.
|
|
//! \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 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 Returns interpolated color.
|
|
inline SColorf getInterpolated(const SColorf &other, f32 d) const
|
|
{
|
|
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, const f32 d) const
|
|
{
|
|
// 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,
|
|
g * 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
|
|
inline 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;
|
|
}
|
|
}
|
|
};
|
|
|
|
//! Class representing a color in HSV format
|
|
/** The color values for hue, saturation, value
|
|
are stored in a 32 bit floating point variable.
|
|
*/
|
|
class SColorHSL
|
|
{
|
|
public:
|
|
SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f )
|
|
: Hue ( h ), Saturation ( s ), Luminance ( l ) {}
|
|
|
|
void setfromRGB ( const SColor &color );
|
|
void settoRGB ( SColor &color ) const;
|
|
|
|
f32 Hue;
|
|
f32 Saturation;
|
|
f32 Luminance;
|
|
|
|
private:
|
|
inline u32 toRGB1(f32 rm1, f32 rm2, f32 rh) const;
|
|
|
|
};
|
|
|
|
inline void SColorHSL::settoRGB ( SColor &color ) const
|
|
{
|
|
if ( Saturation == 0.0f) // grey
|
|
{
|
|
u8 c = (u8) ( Luminance * 255.0 );
|
|
color.setRed ( c );
|
|
color.setGreen ( c );
|
|
color.setBlue ( c );
|
|
return;
|
|
}
|
|
|
|
f32 rm1, rm2;
|
|
|
|
if ( Luminance <= 0.5f )
|
|
{
|
|
rm2 = Luminance + Luminance * Saturation;
|
|
}
|
|
else
|
|
{
|
|
rm2 = Luminance + Saturation - Luminance * Saturation;
|
|
}
|
|
|
|
rm1 = 2.0f * Luminance - rm2;
|
|
|
|
color.setRed ( toRGB1(rm1, rm2, Hue + (120.0f * core::DEGTORAD )) );
|
|
color.setGreen ( toRGB1(rm1, rm2, Hue) );
|
|
color.setBlue ( toRGB1(rm1, rm2, Hue - (120.0f * core::DEGTORAD) ) );
|
|
}
|
|
|
|
|
|
inline u32 SColorHSL::toRGB1(f32 rm1, f32 rm2, f32 rh) const
|
|
{
|
|
while ( rh > 2.f * core::PI )
|
|
rh -= 2.f * core::PI;
|
|
|
|
while ( rh < 0.f )
|
|
rh += 2.f * core::PI;
|
|
|
|
if (rh < 60.0f * core::DEGTORAD ) rm1 = rm1 + (rm2 - rm1) * rh / (60.0f * core::DEGTORAD);
|
|
else if (rh < 180.0f * core::DEGTORAD ) rm1 = rm2;
|
|
else if (rh < 240.0f * core::DEGTORAD ) rm1 = rm1 + (rm2 - rm1) * ( ( 240.0f * core::DEGTORAD ) - rh) / (60.0f * core::DEGTORAD);
|
|
|
|
return (u32) (rm1 * 255.f);
|
|
}
|
|
|
|
} // end namespace video
|
|
} // end namespace irr
|
|
|
|
#endif
|
|
|