Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

HSV —> RGB Color Fader problems

Brasou Kwasman
Registered User
Join date: 12 May 2008
Posts: 15
06-07-2008 13:48
Hello! im trying to create an object that well(Slowly) fade betweeen colors, To do this im trying to create a way to convert the HSV (Hue, Saturation and Value I think) to RGB formats, the expected inputs are H=0-360 S=0-1 V=0-1

then I just slowly changed H adding 1-2 on every X amount of time, it should slowly cycle though the rainbow of colors, but my code iv got isnt working :(

I found the formula here http://www.easyrgb.com/index.php?X=MATH&H=21#text21

and tried to convert it, but it doesn't want to work :( (Note, the S and V seem to work fine, just not the H aspect)

timer()
{
llSetTimerEvent( colorwheeltime );
a+=10;
if(a>=360) a==0;

float H=a;
float S=1;
float V=1;
llSetText((string)a,<1.0, 0.0, 0.0>,1);
if ( S == 0 ) //HSV from 0 to 1
{
color.x = V;
color.y = V;
color.z = V;
}
else
{
float var_h = H * 6;
if ( var_h == 6 ) var_h = 0;
float var_i = llFloor( var_h );
float var_1 = V * ( 1 - S );
float var_2 = V * ( 1 - S * ( var_h - var_i ) );
float var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) );
float var_r;float var_g;float var_b;
if ( var_i == 0 ) { var_r = V ; var_g = var_3 ; var_b = var_1 ;}
else if ( var_i == 1 ) { var_r = var_2 ; var_g = V ; var_b = var_1 ;}
else if ( var_i == 2 ) { var_r = var_1 ; var_g = V ; var_b = var_3; }
else if ( var_i == 3 ) { var_r = var_1 ; var_g = var_2 ; var_b = V ; }
else if ( var_i == 4 ) { var_r = var_3 ; var_g = var_1 ; var_b = V ; }
else { var_r = V ; var_g = var_1 ; var_b = var_2; }

color.x = var_r;
color.y = var_g;
color.z = var_b;
}
llSetColor(color,ALL_SIDES);
}


It just stays a solid purple color :(
Viktoria Dovgal
Join date: 29 Jul 2007
Posts: 3,593
06-07-2008 18:34
I went through similar aggravation some months ago, and learned that there are lots and lots of broken HSV conversion functions out on the web, even in their original languages :D

Here is one attempt that worked well enough for me. I since saw that there is another translation of this one on the wiki, but for some reason that one has the GPL slapped on (not sure it's really kosher to add that to a transliteration of random stuff found on the web). Test thingies are tacked on so you can have some vague queasy feeling that it might work.

[ETA: contrary to a later remark in the thread, this is tested and works. ]

CODE

// rgb2hsv and hsv2rgb functions are simple transliterations
// from http://www.cs.rit.edu/~ncs/color/t_convert.html

vector rgb2hsv (vector rgb) {
vector hsv;

float min = llListStatistics(LIST_STAT_MIN, [rgb.x,rgb.y,rgb.z]);
float max = llListStatistics(LIST_STAT_MAX, [rgb.x,rgb.y,rgb.z]);
hsv.z = max;

float delta = max - min;
if (delta == 0.) {
delta = .00000001; // division by 0 kludge
}

if (max != 0.) {
hsv.y = delta / max;
}
else {
hsv.y = 0.;
hsv.x = -1.;
return hsv;
}

if (rgb.x == max) {
hsv.x = (rgb.y - rgb.z) / delta;
}
else if (rgb.y == max) {
hsv.x = 2 + (rgb.z - rgb.x) / delta;
}
else {
hsv.x = 4 + (rgb.x - rgb.y) / delta;
}

hsv.x *= 60.;
if (hsv.x < 0.) {
hsv.x += 360.;
}

return hsv;
}

vector hsv2rgb (vector hsv) {
vector rgb;

if (hsv.y == 0.) {
rgb.x = hsv.z;
rgb.y = hsv.z;
rgb.z = hsv.z;
return rgb;
}

hsv.x /= 60.;
integer i = llFloor(hsv.x);
float f = hsv.x - i;
float p = hsv.z * (1 - hsv.y);
float q = hsv.z * (1 - hsv.y * f);
float t = hsv.z * (1 - hsv.y * (1 - f));

if (i == 0) {
rgb.x = hsv.z;
rgb.y = t;
rgb.z = p;
}
else if (i == 1) {
rgb.x = q;
rgb.y = hsv.z;
rgb.z = p;
}
else if (i == 2) {
rgb.x = p;
rgb.y = hsv.z;
rgb.z = t;
}
else if (i == 3) {
rgb.x = p;
rgb.y = q;
rgb.z = hsv.z;
}
else if (i == 4) {
rgb.x = t;
rgb.y = p;
rgb.z = hsv.z;
}
else {
rgb.x = hsv.z;
rgb.y = p;
rgb.z = q;
}

return rgb;
}

default
{

// Some simple tests
touch_start (integer foo)
{
// Step through some RGB values and see if an RGB->HSV->RGB
// round trip gives us the same numbers.
llOwnerSay("testing");
vector rgb;
for (rgb.x = 0.; rgb.x <=1.; rgb.x += 0.1) {
for (rgb.y = 0.; rgb.y <=1.; rgb.y += 0.1) {
for (rgb.z = 0.; rgb.z <=1.; rgb.z += 0.1) {
vector hsv = rgb2hsv(rgb); // turn our RGB to HSV …
vector rgb2 = hsv2rgb(hsv); // … and back again.

// compare the strings as a sleazy way to
// ignore float silliness
if ((string) rgb != (string)rgb2) {
llOwnerSay(
"oops! rgb: " + (string) rgb
+ " rgb2: " + (string) rgb2
+ " hsv: " + (string) hsv
);
}

} // rgb.z
} // rgb.y
} // rgb.x

llOwnerSay("two way conversion check done");

// Oo a rainbow!
llOwnerSay("5 rainbow cycles, whee!");
integer i;
vector hsvstart = <0., 1., 1.>;

for (i = 0; i < 5; i++) {
for (hsvstart.x = 0.; hsvstart.x < 360.; hsvstart.x++) {
llSetColor(hsv2rgb(hsvstart), ALL_SIDES);
}
}

llOwnerSay("done");
}
}

_____________________
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
06-08-2008 09:49
Dunno if this will give you what you want, but a REAL simple way to do a color fader works like this:

CODE

float gfSteps = 10.0;
float gfStepDelay = 0.1;

Fade(vector pvStartColor, vector pvEndColor) {
vector lvStepDelta;
float lfStep;

lvStepDelta = (pvEndColor - pvStartColor) / gfSteps;
for (lfStep=0.0; lfStep <= gfSteps; lfStep += 1.0) {
llSetColor(pvStartColor+lvStepDelta*lfStep, ALL_SIDES);
llSleep(gfStepDelay);
}
}

vector RandomColor() {
return <llFrand(1.0),llFrand(1.0),llFrand(1.0)>;
}

default {
state_entry() {
llSetColor(RandomColor(),ALL_SIDES);
}
touch_start(integer piCount) {
Fade(llGetColor(0),RandomColor());
}
}
Squirrel Wood
Nuteater. Beware!
Join date: 14 Jun 2006
Posts: 471
06-08-2008 23:49
If you IM me in SL I can pass you a RGB => HSL and HSL => RGB converter once I get on.

A working one at that.


And here's a simple explanation of how HSL works:
http://www.codeproject.com/KB/recipes/colorspace1/hsl.png