User:Luisa Bourgoin/mixing color vectors

From Second Life Wiki
Jump to navigation Jump to search
Thomas Young, in the early 1800s, showed that a broad range of colors can be generated
by mixing three beams of light, provided their frequencies were widely separately.
When three such beams combine to produce white light, there are called primary colors.
There is no single unique set of these primaries, nor do they have to be monochromatic.

done some google research

Re: Luisa's script ideas / problems and other random thoughts

First published on Wednesday-05-13-2009 11:23pm inside ICE Forum webpages

I picket up this posting http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=39.msg1316#msg1316 where Fu-Kwun Hwang of www.phy.ntnu.edu.tw explained a simple approach on color mixing.

There are two color vectors dyed together. Calculation looks like that:

(100,100,55)
+(100,55,100)
+(55,100,100)
-------------
(119,119,119)

which is more easy to grasp if you look at this like that:

(0110 0100,0110 0100,0011 0111)
+(0110 0100,0011 0111,0110 0100)
+(0011 0111,0110 0100,0110 0100)
--------------------------------
=(0111 0111,0111 0111,0111 0111)

which tends to translate into LSL <lsl> // L.B. been here :-P // use it like llSetColor(tinting_two_RGBs(llGetColor(1),llGetColor(2)), 0); // to mix colors from cube side 1 and 2 onto frontside 0 vector tinting_two_RGBs(vector c1, vector c2) {

   vector re = ZERO_VECTOR;
   c1 *= 255.0;
   c2 *= 255.0;
   re.x = (integer)(c1.x) | (integer)(c2.x);
   re.y = (integer)(c1.y) | (integer)(c2.y);
   re.z = (integer)(c1.z) | (integer)(c2.z);
   return(re / 255.0);

} </lsl> ...but three postings downwards this theory has been all rumble, simple examples destroyed the plain OR aproach. None the less it's a 1st attempt. ...worked ... bad. Next try picking up code from Perl/CPAN

This is working Perl code, taken from "Color::Calc" module by Claus Färber Copyright © 2004-2008. Since he had been working on that over years and his name literally translates into "Mr. Dyer" :-D maybe we can just translate this code: <lsl> sub mix {

 my $self = __get_self(\@_);
 my @c1 = ($self->__get(\@_,1));
 my @c2 = ($self->__get(\@_));
 my $alpha = shift(@_); $alpha = 0.5 unless defined $alpha;
 return $self->__put(__normtuple(
   ($c1[0] + ($c2[0]-$c1[0])*$alpha),
   ($c1[1] + ($c2[1]-$c1[1])*$alpha),
   ($c1[2] + ($c2[2]-$c1[2])*$alpha) ));

}

sub __normtuple_in {

 return map { ($_ < 0) ? 0 : (($_ > 255) ? 255 : int($_+.5)) } @_;

}

sub __normtuple_out {

 return map { (length $_) == 3 ? '0'.$_ : $_ } __normtuple_in(@_)

}

sub __normtuple {

 return __normtuple_out(__normtuple_in(@_));

} </lsl> http://perldoc.perl.org/functions/map.html is helpfull in understanding this.

Simplified, take c1.x + (c2.x - c1.x) * a, and add some housekeeping to ensure values stay between 0 and 1.0 <lsl> // L.B. been here :-P // use it like llSetColor(tinting_two_RGBs(llGetColor(1),llGetColor(2)), 0); // to mix colors from cube side 1 and 2 onto frontside 0 vector tinting_two_RGBs(vector c1, vector c2) {

   vector re = ZERO_VECTOR;
   c1 *= 255.0;
   c2 *= 255.0;
   re.x = (integer)(c1.x + 0.5 * (c2.x - c1.x) + 0.5);
   if(re.x > 255) re.x=255;
   re.y = (integer)(c1.y + 0.5 * (c2.y - c1.y) + 0.5);
   if(re.y > 255) re.y=255;
   re.z = (integer)(c1.z + 0.5 * (c2.z - c1.z) + 0.5);
   if(re.z > 255) re.z=255;
   return(re / 255.0);

} </lsl> Mixing red with green results into yellow but ... look at this:

http://img15.myimg.de/drawing20849d.gif

<255,0,0> + <0,255,0> -> <128,128,0>

which does appear to *dark* as result. Not bright at all ... it mixes, but in a darkening way. Luminance falls of. Simple OR-ing would have given bright yellow <255,255,0>

grrrrrRRR! ...continueing further on