HSVというのは、いわゆるHSV色空間のことです。
これは、Hue(色相)、Saturation(彩度)、Value(明度)を表しておりましています。
ご存知?の通りRGBの色空間から、HSVの色空間へ変換が可能でして、
これを利用すれば、今のRGBの色から、少し濃い色にしたり、逆に薄い色にしたり、
明るい色にしたり、暗い色にしたり、色相を反転させたり、いろいろできるわけです。
そしてこちらが、関数と逆関数です。スキニツカテイイヨー(あんまりテストしてないので・・・)
float fractF(float x) { if(x >= 0) { return(x - (integer)x); } else { return(1.0 + (x - (integer)x));}} vector getRgbFromHsv(vector hsv) { vector rgb = <hsv.z, hsv.z, hsv.z>; if(hsv.y > 0.0) { hsv.x *= 6.0; integer i = (integer)hsv.x; float f = fractF(hsv.x); if(i == 0) { rgb.y *= 1.0 - hsv.y * (1.0 - f); rgb.z *= 1.0 - hsv.y; } else if(i == 1) { rgb.x *= 1.0 - hsv.y * f; rgb.z *= 1.0 - hsv.y; } else if(i == 2) { rgb.x *= 1.0 - hsv.y; rgb.z *= 1.0 - hsv.y * (1.0 - f); } else if(i == 3) { rgb.x *= 1.0 - hsv.y; rgb.y *= 1.0 - hsv.y * f; } else if(i == 4) { rgb.x *= 1.0 - hsv.y * (1.0 - f); rgb.y *= 1.0 - hsv.y; } else if(i == 5) { rgb.y *= 1.0 - hsv.y; rgb.z *= 1.0 - hsv.y * f; } } return(rgb); } vector getHsvFromRgb(vector rgb) { float min = llListStatistics(LIST_STAT_MIN, [rgb.x, rgb.y, rgb.z]); float max = llListStatistics(LIST_STAT_MAX, [rgb.x, rgb.y, rgb.z]); vector hsv = <max - min, max - min, max>; if(hsv.x > 0.0) { if(max == rgb.x) { hsv.x = (rgb.y - rgb.z) / hsv.x; if (hsv.x < 0.0) { hsv.x += 6.0; } } else if(max == rgb.y) { hsv.x = 2.0 + (rgb.z - rgb.x) / hsv.x; } else { hsv.x = 4.0 + (rgb.x - rgb.y) / hsv.x; } } hsv.x /= 6.0; if(max != 0.0) { hsv.y /= max; } return(hsv); } default { state_entry() { } touch_start(integer total_number) { vector color = <0.5, 0.7, 0.2>; vector hsv = getHsvFromRgb(color); vector rgb = getRgbFromHsv(hsv); llOwnerSay((string) hsv); llOwnerSay((string) rgb); } }
色相は0→1が360度に対応していますので、
1を超えたら、また0→1へを繰り返します。
余談ですが、HLS色空間というものもあります。
こちらは少し、また計算式が変わってきています。詳しいことはこちらに。
以上
そしていつものおまけ
GLSL でおなじみの lerp や fract はよく使用するので、準備しておくと便利です。
float fractF(float x) { if(x >= 0) { return(x - (integer)x); } else { return(1.0 + (x - (integer)x));}} float minF(float x, float xmin) { if(x > xmin) { return xmin; } else {return x;}} float maxF(float x, float xmax) { if(x < xmax) { return xmax; } else {return x;}} vector lerpV(vector A, vector B, float r) { return(A * (1.0 - r) + B * r); } float lerpF(float a, float b, float r) { return(a * (1.0 - r) + b * r); } integer lerpI(float a, float b, float r) { return((integer)(a * (1.0 - r) + b * r)); } float limitF(float x, float xmin, float xmax) { if(x > xmax) { return xmax; } else if(x < xmin) { return xmin; } else {return x;}} integer limitI(float x, float xmin, float xmax) { if(x > xmax) { return (integer)xmax; } else if(x < xmin) { return (integer)xmin; } else {return (integer)x;}} float normalizeF(float x, float xmin, float xmax) { return (x - xmin) / (xmax - xmin); }
コメント