diff options
Diffstat (limited to 'libraries/irrlicht-1.8.1/include/SColor.h')
-rw-r--r-- | libraries/irrlicht-1.8.1/include/SColor.h | 697 |
1 files changed, 697 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/include/SColor.h b/libraries/irrlicht-1.8.1/include/SColor.h new file mode 100644 index 0000000..b61bbef --- /dev/null +++ b/libraries/irrlicht-1.8.1/include/SColor.h | |||
@@ -0,0 +1,697 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #ifndef __COLOR_H_INCLUDED__ | ||
6 | #define __COLOR_H_INCLUDED__ | ||
7 | |||
8 | #include "irrTypes.h" | ||
9 | #include "irrMath.h" | ||
10 | |||
11 | namespace irr | ||
12 | { | ||
13 | namespace video | ||
14 | { | ||
15 | //! An enum for the color format of textures used by the Irrlicht Engine. | ||
16 | /** A color format specifies how color information is stored. */ | ||
17 | enum ECOLOR_FORMAT | ||
18 | { | ||
19 | //! 16 bit color format used by the software driver. | ||
20 | /** It is thus preferred by all other irrlicht engine video drivers. | ||
21 | There are 5 bits for every color component, and a single bit is left | ||
22 | for alpha information. */ | ||
23 | ECF_A1R5G5B5 = 0, | ||
24 | |||
25 | //! Standard 16 bit color format. | ||
26 | ECF_R5G6B5, | ||
27 | |||
28 | //! 24 bit color, no alpha channel, but 8 bit for red, green and blue. | ||
29 | ECF_R8G8B8, | ||
30 | |||
31 | //! Default 32 bit color format. 8 bits are used for every component: red, green, blue and alpha. | ||
32 | ECF_A8R8G8B8, | ||
33 | |||
34 | /** Floating Point formats. The following formats may only be used for render target textures. */ | ||
35 | |||
36 | //! 16 bit floating point format using 16 bits for the red channel. | ||
37 | ECF_R16F, | ||
38 | |||
39 | //! 32 bit floating point format using 16 bits for the red channel and 16 bits for the green channel. | ||
40 | ECF_G16R16F, | ||
41 | |||
42 | //! 64 bit floating point format 16 bits are used for the red, green, blue and alpha channels. | ||
43 | ECF_A16B16G16R16F, | ||
44 | |||
45 | //! 32 bit floating point format using 32 bits for the red channel. | ||
46 | ECF_R32F, | ||
47 | |||
48 | //! 64 bit floating point format using 32 bits for the red channel and 32 bits for the green channel. | ||
49 | ECF_G32R32F, | ||
50 | |||
51 | //! 128 bit floating point format. 32 bits are used for the red, green, blue and alpha channels. | ||
52 | ECF_A32B32G32R32F, | ||
53 | |||
54 | //! Unknown color format: | ||
55 | ECF_UNKNOWN | ||
56 | }; | ||
57 | |||
58 | |||
59 | //! Creates a 16 bit A1R5G5B5 color | ||
60 | inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a=0xFF) | ||
61 | { | ||
62 | return (u16)((a & 0x80) << 8 | | ||
63 | (r & 0xF8) << 7 | | ||
64 | (g & 0xF8) << 2 | | ||
65 | (b & 0xF8) >> 3); | ||
66 | } | ||
67 | |||
68 | |||
69 | //! Creates a 16 bit A1R5G5B5 color | ||
70 | inline u16 RGB16(u32 r, u32 g, u32 b) | ||
71 | { | ||
72 | return RGBA16(r,g,b); | ||
73 | } | ||
74 | |||
75 | |||
76 | //! Creates a 16bit A1R5G5B5 color, based on 16bit input values | ||
77 | inline u16 RGB16from16(u16 r, u16 g, u16 b) | ||
78 | { | ||
79 | return (0x8000 | | ||
80 | (r & 0x1F) << 10 | | ||
81 | (g & 0x1F) << 5 | | ||
82 | (b & 0x1F)); | ||
83 | } | ||
84 | |||
85 | |||
86 | //! Converts a 32bit (X8R8G8B8) color to a 16bit A1R5G5B5 color | ||
87 | inline u16 X8R8G8B8toA1R5G5B5(u32 color) | ||
88 | { | ||
89 | return (u16)(0x8000 | | ||
90 | ( color & 0x00F80000) >> 9 | | ||
91 | ( color & 0x0000F800) >> 6 | | ||
92 | ( color & 0x000000F8) >> 3); | ||
93 | } | ||
94 | |||
95 | |||
96 | //! Converts a 32bit (A8R8G8B8) color to a 16bit A1R5G5B5 color | ||
97 | inline u16 A8R8G8B8toA1R5G5B5(u32 color) | ||
98 | { | ||
99 | return (u16)(( color & 0x80000000) >> 16| | ||
100 | ( color & 0x00F80000) >> 9 | | ||
101 | ( color & 0x0000F800) >> 6 | | ||
102 | ( color & 0x000000F8) >> 3); | ||
103 | } | ||
104 | |||
105 | |||
106 | //! Converts a 32bit (A8R8G8B8) color to a 16bit R5G6B5 color | ||
107 | inline u16 A8R8G8B8toR5G6B5(u32 color) | ||
108 | { | ||
109 | return (u16)(( color & 0x00F80000) >> 8 | | ||
110 | ( color & 0x0000FC00) >> 5 | | ||
111 | ( color & 0x000000F8) >> 3); | ||
112 | } | ||
113 | |||
114 | |||
115 | //! Convert A8R8G8B8 Color from A1R5G5B5 color | ||
116 | /** build a nicer 32bit Color by extending dest lower bits with source high bits. */ | ||
117 | inline u32 A1R5G5B5toA8R8G8B8(u16 color) | ||
118 | { | ||
119 | return ( (( -( (s32) color & 0x00008000 ) >> (s32) 31 ) & 0xFF000000 ) | | ||
120 | (( color & 0x00007C00 ) << 9) | (( color & 0x00007000 ) << 4) | | ||
121 | (( color & 0x000003E0 ) << 6) | (( color & 0x00000380 ) << 1) | | ||
122 | (( color & 0x0000001F ) << 3) | (( color & 0x0000001C ) >> 2) | ||
123 | ); | ||
124 | } | ||
125 | |||
126 | |||
127 | //! Returns A8R8G8B8 Color from R5G6B5 color | ||
128 | inline u32 R5G6B5toA8R8G8B8(u16 color) | ||
129 | { | ||
130 | return 0xFF000000 | | ||
131 | ((color & 0xF800) << 8)| | ||
132 | ((color & 0x07E0) << 5)| | ||
133 | ((color & 0x001F) << 3); | ||
134 | } | ||
135 | |||
136 | |||
137 | //! Returns A1R5G5B5 Color from R5G6B5 color | ||
138 | inline u16 R5G6B5toA1R5G5B5(u16 color) | ||
139 | { | ||
140 | return 0x8000 | (((color & 0xFFC0) >> 1) | (color & 0x1F)); | ||
141 | } | ||
142 | |||
143 | |||
144 | //! Returns R5G6B5 Color from A1R5G5B5 color | ||
145 | inline u16 A1R5G5B5toR5G6B5(u16 color) | ||
146 | { | ||
147 | return (((color & 0x7FE0) << 1) | (color & 0x1F)); | ||
148 | } | ||
149 | |||
150 | |||
151 | |||
152 | //! Returns the alpha component from A1R5G5B5 color | ||
153 | /** In Irrlicht, alpha refers to opacity. | ||
154 | \return The alpha value of the color. 0 is transparent, 1 is opaque. */ | ||
155 | inline u32 getAlpha(u16 color) | ||
156 | { | ||
157 | return ((color >> 15)&0x1); | ||
158 | } | ||
159 | |||
160 | |||
161 | //! Returns the red component from A1R5G5B5 color. | ||
162 | /** Shift left by 3 to get 8 bit value. */ | ||
163 | inline u32 getRed(u16 color) | ||
164 | { | ||
165 | return ((color >> 10)&0x1F); | ||
166 | } | ||
167 | |||
168 | |||
169 | //! Returns the green component from A1R5G5B5 color | ||
170 | /** Shift left by 3 to get 8 bit value. */ | ||
171 | inline u32 getGreen(u16 color) | ||
172 | { | ||
173 | return ((color >> 5)&0x1F); | ||
174 | } | ||
175 | |||
176 | |||
177 | //! Returns the blue component from A1R5G5B5 color | ||
178 | /** Shift left by 3 to get 8 bit value. */ | ||
179 | inline u32 getBlue(u16 color) | ||
180 | { | ||
181 | return (color & 0x1F); | ||
182 | } | ||
183 | |||
184 | |||
185 | //! Returns the average from a 16 bit A1R5G5B5 color | ||
186 | inline s32 getAverage(s16 color) | ||
187 | { | ||
188 | return ((getRed(color)<<3) + (getGreen(color)<<3) + (getBlue(color)<<3)) / 3; | ||
189 | } | ||
190 | |||
191 | |||
192 | //! Class representing a 32 bit ARGB color. | ||
193 | /** The color values for alpha, red, green, and blue are | ||
194 | stored in a single u32. So all four values may be between 0 and 255. | ||
195 | Alpha in Irrlicht is opacity, so 0 is fully transparent, 255 is fully opaque (solid). | ||
196 | This class is used by most parts of the Irrlicht Engine | ||
197 | to specify a color. Another way is using the class SColorf, which | ||
198 | stores the color values in 4 floats. | ||
199 | This class must consist of only one u32 and must not use virtual functions. | ||
200 | */ | ||
201 | class SColor | ||
202 | { | ||
203 | public: | ||
204 | |||
205 | //! Constructor of the Color. Does nothing. | ||
206 | /** The color value is not initialized to save time. */ | ||
207 | SColor() {} | ||
208 | |||
209 | //! Constructs the color from 4 values representing the alpha, red, green and blue component. | ||
210 | /** Must be values between 0 and 255. */ | ||
211 | SColor (u32 a, u32 r, u32 g, u32 b) | ||
212 | : color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {} | ||
213 | |||
214 | //! Constructs the color from a 32 bit value. Could be another color. | ||
215 | SColor(u32 clr) | ||
216 | : color(clr) {} | ||
217 | |||
218 | //! Returns the alpha component of the color. | ||
219 | /** The alpha component defines how opaque a color is. | ||
220 | \return The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */ | ||
221 | u32 getAlpha() const { return color>>24; } | ||
222 | |||
223 | //! Returns the red component of the color. | ||
224 | /** \return Value between 0 and 255, specifying how red the color is. | ||
225 | 0 means no red, 255 means full red. */ | ||
226 | u32 getRed() const { return (color>>16) & 0xff; } | ||
227 | |||
228 | //! Returns the green component of the color. | ||
229 | /** \return Value between 0 and 255, specifying how green the color is. | ||
230 | 0 means no green, 255 means full green. */ | ||
231 | u32 getGreen() const { return (color>>8) & 0xff; } | ||
232 | |||
233 | //! Returns the blue component of the color. | ||
234 | /** \return Value between 0 and 255, specifying how blue the color is. | ||
235 | 0 means no blue, 255 means full blue. */ | ||
236 | u32 getBlue() const { return color & 0xff; } | ||
237 | |||
238 | //! Get lightness of the color in the range [0,255] | ||
239 | f32 getLightness() const | ||
240 | { | ||
241 | return 0.5f*(core::max_(core::max_(getRed(),getGreen()),getBlue())+core::min_(core::min_(getRed(),getGreen()),getBlue())); | ||
242 | } | ||
243 | |||
244 | //! Get luminance of the color in the range [0,255]. | ||
245 | f32 getLuminance() const | ||
246 | { | ||
247 | return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue(); | ||
248 | } | ||
249 | |||
250 | //! Get average intensity of the color in the range [0,255]. | ||
251 | u32 getAverage() const | ||
252 | { | ||
253 | return ( getRed() + getGreen() + getBlue() ) / 3; | ||
254 | } | ||
255 | |||
256 | //! Sets the alpha component of the Color. | ||
257 | /** The alpha component defines how transparent a color should be. | ||
258 | \param a The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */ | ||
259 | void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); } | ||
260 | |||
261 | //! Sets the red component of the Color. | ||
262 | /** \param r: Has to be a value between 0 and 255. | ||
263 | 0 means no red, 255 means full red. */ | ||
264 | void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); } | ||
265 | |||
266 | //! Sets the green component of the Color. | ||
267 | /** \param g: Has to be a value between 0 and 255. | ||
268 | 0 means no green, 255 means full green. */ | ||
269 | void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); } | ||
270 | |||
271 | //! Sets the blue component of the Color. | ||
272 | /** \param b: Has to be a value between 0 and 255. | ||
273 | 0 means no blue, 255 means full blue. */ | ||
274 | void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); } | ||
275 | |||
276 | //! Calculates a 16 bit A1R5G5B5 value of this color. | ||
277 | /** \return 16 bit A1R5G5B5 value of this color. */ | ||
278 | u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); } | ||
279 | |||
280 | //! Converts color to OpenGL color format | ||
281 | /** From ARGB to RGBA in 4 byte components for endian aware | ||
282 | passing to OpenGL | ||
283 | \param dest: address where the 4x8 bit OpenGL color is stored. */ | ||
284 | void toOpenGLColor(u8* dest) const | ||
285 | { | ||
286 | *dest = (u8)getRed(); | ||
287 | *++dest = (u8)getGreen(); | ||
288 | *++dest = (u8)getBlue(); | ||
289 | *++dest = (u8)getAlpha(); | ||
290 | } | ||
291 | |||
292 | //! Sets all four components of the color at once. | ||
293 | /** Constructs the color from 4 values representing the alpha, | ||
294 | red, green and blue components of the color. Must be values | ||
295 | between 0 and 255. | ||
296 | \param a: Alpha component of the color. The alpha component | ||
297 | defines how transparent a color should be. Has to be a value | ||
298 | between 0 and 255. 255 means not transparent (opaque), 0 means | ||
299 | fully transparent. | ||
300 | \param r: Sets the red component of the Color. Has to be a | ||
301 | value between 0 and 255. 0 means no red, 255 means full red. | ||
302 | \param g: Sets the green component of the Color. Has to be a | ||
303 | value between 0 and 255. 0 means no green, 255 means full | ||
304 | green. | ||
305 | \param b: Sets the blue component of the Color. Has to be a | ||
306 | value between 0 and 255. 0 means no blue, 255 means full blue. */ | ||
307 | void set(u32 a, u32 r, u32 g, u32 b) | ||
308 | { | ||
309 | color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)); | ||
310 | } | ||
311 | void set(u32 col) { color = col; } | ||
312 | |||
313 | //! Compares the color to another color. | ||
314 | /** \return True if the colors are the same, and false if not. */ | ||
315 | bool operator==(const SColor& other) const { return other.color == color; } | ||
316 | |||
317 | //! Compares the color to another color. | ||
318 | /** \return True if the colors are different, and false if they are the same. */ | ||
319 | bool operator!=(const SColor& other) const { return other.color != color; } | ||
320 | |||
321 | //! comparison operator | ||
322 | /** \return True if this color is smaller than the other one */ | ||
323 | bool operator<(const SColor& other) const { return (color < other.color); } | ||
324 | |||
325 | //! Adds two colors, result is clamped to 0..255 values | ||
326 | /** \param other Color to add to this color | ||
327 | \return Addition of the two colors, clamped to 0..255 values */ | ||
328 | SColor operator+(const SColor& other) const | ||
329 | { | ||
330 | return SColor(core::min_(getAlpha() + other.getAlpha(), 255u), | ||
331 | core::min_(getRed() + other.getRed(), 255u), | ||
332 | core::min_(getGreen() + other.getGreen(), 255u), | ||
333 | core::min_(getBlue() + other.getBlue(), 255u)); | ||
334 | } | ||
335 | |||
336 | //! Interpolates the color with a f32 value to another color | ||
337 | /** \param other: Other color | ||
338 | \param d: value between 0.0f and 1.0f | ||
339 | \return Interpolated color. */ | ||
340 | SColor getInterpolated(const SColor &other, f32 d) const | ||
341 | { | ||
342 | d = core::clamp(d, 0.f, 1.f); | ||
343 | const f32 inv = 1.0f - d; | ||
344 | return SColor((u32)core::round32(other.getAlpha()*inv + getAlpha()*d), | ||
345 | (u32)core::round32(other.getRed()*inv + getRed()*d), | ||
346 | (u32)core::round32(other.getGreen()*inv + getGreen()*d), | ||
347 | (u32)core::round32(other.getBlue()*inv + getBlue()*d)); | ||
348 | } | ||
349 | |||
350 | //! Returns interpolated color. ( quadratic ) | ||
351 | /** \param c1: first color to interpolate with | ||
352 | \param c2: second color to interpolate with | ||
353 | \param d: value between 0.0f and 1.0f. */ | ||
354 | SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, f32 d) const | ||
355 | { | ||
356 | // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d; | ||
357 | d = core::clamp(d, 0.f, 1.f); | ||
358 | const f32 inv = 1.f - d; | ||
359 | const f32 mul0 = inv * inv; | ||
360 | const f32 mul1 = 2.f * d * inv; | ||
361 | const f32 mul2 = d * d; | ||
362 | |||
363 | return SColor( | ||
364 | core::clamp( core::floor32( | ||
365 | getAlpha() * mul0 + c1.getAlpha() * mul1 + c2.getAlpha() * mul2 ), 0, 255 ), | ||
366 | core::clamp( core::floor32( | ||
367 | getRed() * mul0 + c1.getRed() * mul1 + c2.getRed() * mul2 ), 0, 255 ), | ||
368 | core::clamp ( core::floor32( | ||
369 | getGreen() * mul0 + c1.getGreen() * mul1 + c2.getGreen() * mul2 ), 0, 255 ), | ||
370 | core::clamp ( core::floor32( | ||
371 | getBlue() * mul0 + c1.getBlue() * mul1 + c2.getBlue() * mul2 ), 0, 255 )); | ||
372 | } | ||
373 | |||
374 | //! set the color by expecting data in the given format | ||
375 | /** \param data: must point to valid memory containing color information in the given format | ||
376 | \param format: tells the format in which data is available | ||
377 | */ | ||
378 | void setData(const void *data, ECOLOR_FORMAT format) | ||
379 | { | ||
380 | switch (format) | ||
381 | { | ||
382 | case ECF_A1R5G5B5: | ||
383 | color = A1R5G5B5toA8R8G8B8(*(u16*)data); | ||
384 | break; | ||
385 | case ECF_R5G6B5: | ||
386 | color = R5G6B5toA8R8G8B8(*(u16*)data); | ||
387 | break; | ||
388 | case ECF_A8R8G8B8: | ||
389 | color = *(u32*)data; | ||
390 | break; | ||
391 | case ECF_R8G8B8: | ||
392 | { | ||
393 | u8* p = (u8*)data; | ||
394 | set(255, p[0],p[1],p[2]); | ||
395 | } | ||
396 | break; | ||
397 | default: | ||
398 | color = 0xffffffff; | ||
399 | break; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | //! Write the color to data in the defined format | ||
404 | /** \param data: target to write the color. Must contain sufficiently large memory to receive the number of bytes neede for format | ||
405 | \param format: tells the format used to write the color into data | ||
406 | */ | ||
407 | void getData(void *data, ECOLOR_FORMAT format) | ||
408 | { | ||
409 | switch(format) | ||
410 | { | ||
411 | case ECF_A1R5G5B5: | ||
412 | { | ||
413 | u16 * dest = (u16*)data; | ||
414 | *dest = video::A8R8G8B8toA1R5G5B5( color ); | ||
415 | } | ||
416 | break; | ||
417 | |||
418 | case ECF_R5G6B5: | ||
419 | { | ||
420 | u16 * dest = (u16*)data; | ||
421 | *dest = video::A8R8G8B8toR5G6B5( color ); | ||
422 | } | ||
423 | break; | ||
424 | |||
425 | case ECF_R8G8B8: | ||
426 | { | ||
427 | u8* dest = (u8*)data; | ||
428 | dest[0] = (u8)getRed(); | ||
429 | dest[1] = (u8)getGreen(); | ||
430 | dest[2] = (u8)getBlue(); | ||
431 | } | ||
432 | break; | ||
433 | |||
434 | case ECF_A8R8G8B8: | ||
435 | { | ||
436 | u32 * dest = (u32*)data; | ||
437 | *dest = color; | ||
438 | } | ||
439 | break; | ||
440 | |||
441 | default: | ||
442 | break; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | //! color in A8R8G8B8 Format | ||
447 | u32 color; | ||
448 | }; | ||
449 | |||
450 | |||
451 | //! Class representing a color with four floats. | ||
452 | /** The color values for red, green, blue | ||
453 | and alpha are each stored in a 32 bit floating point variable. | ||
454 | So all four values may be between 0.0f and 1.0f. | ||
455 | Another, faster way to define colors is using the class SColor, which | ||
456 | stores the color values in a single 32 bit integer. | ||
457 | */ | ||
458 | class SColorf | ||
459 | { | ||
460 | public: | ||
461 | //! Default constructor for SColorf. | ||
462 | /** Sets red, green and blue to 0.0f and alpha to 1.0f. */ | ||
463 | SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {} | ||
464 | |||
465 | //! Constructs a color from up to four color values: red, green, blue, and alpha. | ||
466 | /** \param r: Red color component. Should be a value between | ||
467 | 0.0f meaning no red and 1.0f, meaning full red. | ||
468 | \param g: Green color component. Should be a value between 0.0f | ||
469 | meaning no green and 1.0f, meaning full green. | ||
470 | \param b: Blue color component. Should be a value between 0.0f | ||
471 | meaning no blue and 1.0f, meaning full blue. | ||
472 | \param a: Alpha color component of the color. The alpha | ||
473 | component defines how transparent a color should be. Has to be | ||
474 | a value between 0.0f and 1.0f, 1.0f means not transparent | ||
475 | (opaque), 0.0f means fully transparent. */ | ||
476 | SColorf(f32 r, f32 g, f32 b, f32 a = 1.0f) : r(r), g(g), b(b), a(a) {} | ||
477 | |||
478 | //! Constructs a color from 32 bit Color. | ||
479 | /** \param c: 32 bit color from which this SColorf class is | ||
480 | constructed from. */ | ||
481 | SColorf(SColor c) | ||
482 | { | ||
483 | const f32 inv = 1.0f / 255.0f; | ||
484 | r = c.getRed() * inv; | ||
485 | g = c.getGreen() * inv; | ||
486 | b = c.getBlue() * inv; | ||
487 | a = c.getAlpha() * inv; | ||
488 | } | ||
489 | |||
490 | //! Converts this color to a SColor without floats. | ||
491 | SColor toSColor() const | ||
492 | { | ||
493 | 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)); | ||
494 | } | ||
495 | |||
496 | //! Sets three color components to new values at once. | ||
497 | /** \param rr: Red color component. Should be a value between 0.0f meaning | ||
498 | no red (=black) and 1.0f, meaning full red. | ||
499 | \param gg: Green color component. Should be a value between 0.0f meaning | ||
500 | no green (=black) and 1.0f, meaning full green. | ||
501 | \param bb: Blue color component. Should be a value between 0.0f meaning | ||
502 | no blue (=black) and 1.0f, meaning full blue. */ | ||
503 | void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; } | ||
504 | |||
505 | //! Sets all four color components to new values at once. | ||
506 | /** \param aa: Alpha component. Should be a value between 0.0f meaning | ||
507 | fully transparent and 1.0f, meaning opaque. | ||
508 | \param rr: Red color component. Should be a value between 0.0f meaning | ||
509 | no red and 1.0f, meaning full red. | ||
510 | \param gg: Green color component. Should be a value between 0.0f meaning | ||
511 | no green and 1.0f, meaning full green. | ||
512 | \param bb: Blue color component. Should be a value between 0.0f meaning | ||
513 | no blue and 1.0f, meaning full blue. */ | ||
514 | void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; } | ||
515 | |||
516 | //! Interpolates the color with a f32 value to another color | ||
517 | /** \param other: Other color | ||
518 | \param d: value between 0.0f and 1.0f | ||
519 | \return Interpolated color. */ | ||
520 | SColorf getInterpolated(const SColorf &other, f32 d) const | ||
521 | { | ||
522 | d = core::clamp(d, 0.f, 1.f); | ||
523 | const f32 inv = 1.0f - d; | ||
524 | return SColorf(other.r*inv + r*d, | ||
525 | other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d); | ||
526 | } | ||
527 | |||
528 | //! Returns interpolated color. ( quadratic ) | ||
529 | /** \param c1: first color to interpolate with | ||
530 | \param c2: second color to interpolate with | ||
531 | \param d: value between 0.0f and 1.0f. */ | ||
532 | inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2, | ||
533 | f32 d) const | ||
534 | { | ||
535 | d = core::clamp(d, 0.f, 1.f); | ||
536 | // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d; | ||
537 | const f32 inv = 1.f - d; | ||
538 | const f32 mul0 = inv * inv; | ||
539 | const f32 mul1 = 2.f * d * inv; | ||
540 | const f32 mul2 = d * d; | ||
541 | |||
542 | return SColorf (r * mul0 + c1.r * mul1 + c2.r * mul2, | ||
543 | g * mul0 + c1.g * mul1 + c2.g * mul2, | ||
544 | b * mul0 + c1.b * mul1 + c2.b * mul2, | ||
545 | a * mul0 + c1.a * mul1 + c2.a * mul2); | ||
546 | } | ||
547 | |||
548 | |||
549 | //! Sets a color component by index. R=0, G=1, B=2, A=3 | ||
550 | void setColorComponentValue(s32 index, f32 value) | ||
551 | { | ||
552 | switch(index) | ||
553 | { | ||
554 | case 0: r = value; break; | ||
555 | case 1: g = value; break; | ||
556 | case 2: b = value; break; | ||
557 | case 3: a = value; break; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | //! Returns the alpha component of the color in the range 0.0 (transparent) to 1.0 (opaque) | ||
562 | f32 getAlpha() const { return a; } | ||
563 | |||
564 | //! Returns the red component of the color in the range 0.0 to 1.0 | ||
565 | f32 getRed() const { return r; } | ||
566 | |||
567 | //! Returns the green component of the color in the range 0.0 to 1.0 | ||
568 | f32 getGreen() const { return g; } | ||
569 | |||
570 | //! Returns the blue component of the color in the range 0.0 to 1.0 | ||
571 | f32 getBlue() const { return b; } | ||
572 | |||
573 | //! red color component | ||
574 | f32 r; | ||
575 | |||
576 | //! green color component | ||
577 | f32 g; | ||
578 | |||
579 | //! blue component | ||
580 | f32 b; | ||
581 | |||
582 | //! alpha color component | ||
583 | f32 a; | ||
584 | }; | ||
585 | |||
586 | |||
587 | //! Class representing a color in HSL format | ||
588 | /** The color values for hue, saturation, luminance | ||
589 | are stored in 32bit floating point variables. Hue is in range [0,360], | ||
590 | Luminance and Saturation are in percent [0,100] | ||
591 | */ | ||
592 | class SColorHSL | ||
593 | { | ||
594 | public: | ||
595 | SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f ) | ||
596 | : Hue ( h ), Saturation ( s ), Luminance ( l ) {} | ||
597 | |||
598 | void fromRGB(const SColorf &color); | ||
599 | void toRGB(SColorf &color) const; | ||
600 | |||
601 | f32 Hue; | ||
602 | f32 Saturation; | ||
603 | f32 Luminance; | ||
604 | |||
605 | private: | ||
606 | inline f32 toRGB1(f32 rm1, f32 rm2, f32 rh) const; | ||
607 | |||
608 | }; | ||
609 | |||
610 | inline void SColorHSL::fromRGB(const SColorf &color) | ||
611 | { | ||
612 | const f32 maxVal = core::max_(color.getRed(), color.getGreen(), color.getBlue()); | ||
613 | const f32 minVal = (f32)core::min_(color.getRed(), color.getGreen(), color.getBlue()); | ||
614 | Luminance = (maxVal+minVal)*50; | ||
615 | if (core::equals(maxVal, minVal)) | ||
616 | { | ||
617 | Hue=0.f; | ||
618 | Saturation=0.f; | ||
619 | return; | ||
620 | } | ||
621 | |||
622 | const f32 delta = maxVal-minVal; | ||
623 | if ( Luminance <= 50 ) | ||
624 | { | ||
625 | Saturation = (delta)/(maxVal+minVal); | ||
626 | } | ||
627 | else | ||
628 | { | ||
629 | Saturation = (delta)/(2-maxVal-minVal); | ||
630 | } | ||
631 | Saturation *= 100; | ||
632 | |||
633 | if (core::equals(maxVal, color.getRed())) | ||
634 | Hue = (color.getGreen()-color.getBlue())/delta; | ||
635 | else if (core::equals(maxVal, color.getGreen())) | ||
636 | Hue = 2+((color.getBlue()-color.getRed())/delta); | ||
637 | else // blue is max | ||
638 | Hue = 4+((color.getRed()-color.getGreen())/delta); | ||
639 | |||
640 | Hue *= 60.0f; | ||
641 | while ( Hue < 0.f ) | ||
642 | Hue += 360; | ||
643 | } | ||
644 | |||
645 | |||
646 | inline void SColorHSL::toRGB(SColorf &color) const | ||
647 | { | ||
648 | const f32 l = Luminance/100; | ||
649 | if (core::iszero(Saturation)) // grey | ||
650 | { | ||
651 | color.set(l, l, l); | ||
652 | return; | ||
653 | } | ||
654 | |||
655 | f32 rm2; | ||
656 | |||
657 | if ( Luminance <= 50 ) | ||
658 | { | ||
659 | rm2 = l + l * (Saturation/100); | ||
660 | } | ||
661 | else | ||
662 | { | ||
663 | rm2 = l + (1 - l) * (Saturation/100); | ||
664 | } | ||
665 | |||
666 | const f32 rm1 = 2.0f * l - rm2; | ||
667 | |||
668 | const f32 h = Hue / 360.0f; | ||
669 | color.set( toRGB1(rm1, rm2, h + 1.f/3.f), | ||
670 | toRGB1(rm1, rm2, h), | ||
671 | toRGB1(rm1, rm2, h - 1.f/3.f) | ||
672 | ); | ||
673 | } | ||
674 | |||
675 | |||
676 | // algorithm from Foley/Van-Dam | ||
677 | inline f32 SColorHSL::toRGB1(f32 rm1, f32 rm2, f32 rh) const | ||
678 | { | ||
679 | if (rh<0) | ||
680 | rh += 1; | ||
681 | if (rh>1) | ||
682 | rh -= 1; | ||
683 | |||
684 | if (rh < 1.f/6.f) | ||
685 | rm1 = rm1 + (rm2 - rm1) * rh*6.f; | ||
686 | else if (rh < 0.5f) | ||
687 | rm1 = rm2; | ||
688 | else if (rh < 2.f/3.f) | ||
689 | rm1 = rm1 + (rm2 - rm1) * ((2.f/3.f)-rh)*6.f; | ||
690 | |||
691 | return rm1; | ||
692 | } | ||
693 | |||
694 | } // end namespace video | ||
695 | } // end namespace irr | ||
696 | |||
697 | #endif | ||