Jump to content

Creating a color vector from a UUID


Streak Wildung
 Share

You are about to reply to a thread that has been inactive for 3010 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

A long time ago, there used to be a little gadget  called the soul stealer.  Essentially it would "Steal" your soul and by using your key it would determine the "Color" of your soul.  

I've had the idea to make a new one, after nearly 10 years.  The problem is, I'm not sure how to convert a UUID to a Color Vector.  Can anyone point me to the right direction?

Link to comment
Share on other sites

Well the thing is, the soul stealer would choose a different color for a different person and the same color for the same person.  Granted, every now and again more then one person would have the same color.  So some kind of math is going on behind the scenese to extrapulate a color vector from either the Users name or the UUID.  I'm just not sure what they were doing to make it happen.

Link to comment
Share on other sites

Well my plan is to figure out what math is behind it all so you don't have to do that.  I don't want to store the information from a random number generator and have to recall that information each time.  If the script is reset or anything else I lose that and that will make the script very memory inefficent.  An external server for something like this is overkill, by a lot.  

I know the secret is going to be pretty easy and I'll feel stupid not realizing it any quicker, but for some reason I'm just not seeing how it's done and tha'ts irritating me big time.  I know it's not strored in the script, simply because I've had it for MANY years and I've reset the thing many times.  It still works and still pulls the same colors every time.

Link to comment
Share on other sites

The UUID is a random 128 bit number, represented as a hypenated 32 digit (36 characters including the hyphens). So, convert an avatar's UUID to a string, then extract only the last six characters of the string, which you can then map to a RGB color vector, like this...

default{    state_entry()    {        key UUID = llGetOwner();        integer color = (integer)( "0x"+llGetSubString((string)UUID,30,35));        float red = (color/65536)/255.0;        float green = ((color&65535)/256)/255.0;        float blue = (color&255)/255.0;        vector colorv = <red,green,blue>;        llOwnerSay((string)colorv);    }}

If you want to create color names, you'd just take as many hex digits of the UUID as you want (one would give you 16 colors, two would give you 256) and create an integer that indexes into a list of color names.

  • Like 1
Link to comment
Share on other sites

You can devise all sorts of ways to make something like this.  One of the easiest is to grab three little chunks of the user's UUID, convert them from character strings to floats, and drop them into a new vector that you can display as a color.  For example:

default{    touch_start(integer total_number)    {        string UUID = (string)llDetectedKey(0);        string U1 = llGetSubString(UUID, 0,3);        string U2 = llGetSubString(UUID,-4,-1);        string U3 = llGetSubString(UUID,-9,-6);        float V1 = (float)("0x" + U1)*0.00001;        float V2 = (float)("0x" + U2)*0.00001;        float V3 = (float)("0x" + U3)*0.00001;        vector Color = <V1, V2, V3>;//        llSay(0, (string) Color);        llSetColor(Color,ALL_SIDES);            }}

I picked three substrings carefully to avoid the hyphens, but didn't have any other logic in mind. When I touch the scripted object, I get a color of <0.62056, 0.34423, 0.30027>, which is a warm brown, like a latte.  My alt gets <0.37806, 0.47235, 0.40152>, which is a sort of sage green color.

It's a silly sort of toy, not too hard to script.

EDIT:  Hehe... Maddy beat me to it.   :smileyvery-happy:

  • Like 1
Link to comment
Share on other sites

You mean this?

float V1 = (float)("0x" + U1)*0.00001;

U1 is a text string, four characters long.  You want it to be interpreted as a float, so you need to typecast it.  Hence the (float).  You know that the character string is actually representing a hexadecimal number, so you have to be sure that you identify it as hex before you typecast it.  Hence the reason for adding "0x" first.  Finally, you want to use the resulting number in a color vector, which means that it has to be in the range [0.0,1.0].  Hence the reason for multiplying by 0.00001.

Maddy did the same thing in hers with

integer color = (integer)( "0x"+llGetSubString((string)UUID,30,35));

The big difference is that she grabbed a 6-character string to begin with and then sliced it up and normalized the chunks after that initial step. As I said, you can approach the problem in many different ways.

Link to comment
Share on other sites

There's actually a lot going on in our code that we didn't explain, but that's how it always goes. Whether you grab three two-digit chunks of the UUID as Rolig did, or one six digit chunk as I did makes no functional difference. And the reason it makes no difference is that UUIDs are assigned randomly (though not completely so, as there are subsets of UUID that fix one or more of the digits to make certain distinctions between types of UUID). You can read more about that here...

https://en.wikipedia.org/wiki/Universally_unique_identifier

Note that most (not all) SL UUIDs are RFC-4122 version 4, and are of the form "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx". As you can see, the version digit "4" and the "y" digit, which can only be "8, 9, A or B" aren't random. So you'd want to steer clear of those two digits when mapping SL UUID to color.

Now, because UUIDs are generated randomly, any digit or digit sequence within the UUID is also random (except as noted above). For that reason, it doesn't make any difference which digits you pick to map into SL's color space. And you needn't pick a total of six digits, as Rolig and I did. You could select only three and map only one digit (16 levels) to each color R/G/B. That would give you a total palette of 4096 colors, rather than the 16.8 million you get by using 2 digits (256 levels) per R/G/B.

Rolig parses three pairs of two digits from the UUID, and performs the same math conversion on each. I perform a single string extraction of 6 digits, and therefore must parse the result mathematically. The result is the same. And as Rolig explains, because SL requires floating point color values between 0(black) and 1.0 (white), you must convert the integer values extracted from the UUID (0-255 for two digits, 0-15 for one) to floating point.

Here's what's happening, line by line...

integer color = (integer)( "0x"+llGetSubString((string)UUID,30,35));

Characters 30-35 are the last six characters of the 36 character UUID string, which avoids the "4" and "y" digits. I extract those digits, then prepend "0x" so the resulting string will be understood by the script interpreter as a hexadecimal number. That number is then typecast to a single integer, which will range in value from 0 though 16,777,215. But I really want to understand those 6 hex digits as three pairs of two digits. Rolig makes that much more apparent in her code, which converts two digit pairs into three distinct integers ranging from 0 through 255. So, Rolig extracts three numbers of the hexadecimal form 0xXX, and I extract one of the form 0xXXXXXX.

Because I've extracted a single six digit hex number, and converted that to decimal (the integer "color"), I have to use math to extract the three two digit hex numbers I really want (red, green, blue). By understanding that each two digit pair represents 256 different values, I can parse them out by thinking of 16,777,216 as 256*256*256. I'll explain each line of code below the line.

float red = (color/65536)/255.0;

If I divide color by 65536 (which is 256*256), I'll have a result that ranges from 0-255. All I must do to convert that to a floating point number in the range of 0 to 1.0 is... divide by 255.0 (the .0 is important here, forcing the result to be floating point, not integer). I use the result to represent red.

float green = ((color&65535)/256)/255.0;

Now this gets a little tricky. To get at the middle two hex digits of color, I have to divide by 256. But that will give me a number that can be as large as 65535 because the leftmost two digits of color are still there. I've got to get rid of them, and that's what "color&65535" does. That effectively zeros out the top two hex digits of color before I do the divide. The "&" operator performs the "bitwise and" of 65535 with color. My original hex number is of the form 0xXXXXXX, and 65535 is 0x00FFFF. The "and" of the hex digit zero with any other digit results in zero. So now I have a hex number of the form 0x00XXXX, which ranges (in integer decimal) from 0 through 65535. The result of the division by 256 is therefore limited to 0-255, just as I want. Again, I then divide by 255.0 to convert to the floating point range of 0-1.0.

float blue = (color&255)/255.0;

Here, the "&255" retains only the lower two digits of color, discarding the rest. The result of that bitwise and can range from 0-255, so all I must do is then divide by 255.0.

I suspect Rolig's approach stems from her vastly greater experience with LSL scripting, and probably her lifelong exposure to computer systems with fairly ample resources. My background is in real-time systems with very limited resources. It was actually fairly rare for me to work on systems that had any text processing facilities. For that reason, I'm more comfortable turning everything into a math problem as quickly as possible.

I vote for Rolig's solution as being the more elegant, as it's simply easier to comprehend. My method is more opaque because I'm nefarious, and opacity is a valuable skill. So is invisibility, which is not the same as transparency.

;-).

Link to comment
Share on other sites


Madelaine McMasters wrote:

[ ... ]

I suspect Rolig's approach stems from her vastly greater experience with LSL scripting, and probably her lifelong exposure to computer systems with fairly ample resources. My background is in real-time systems with very limited resources. It was actually fairly rare for me to work on systems that had any text processing facilities. For that reason, I'm more comfortable turning everything into a math problem as quickly as possible.

I vote for Rolig's solution as being the more elegant, as it's simply easier to comprehend. My method is more opaque because I'm nefarious, and opacity is a valuable skill. So is invisibility, which is not the same as transparency.

;-).

Actually, the explanation is simpler than that. I am a very brute force mathematician and I'm lazy. There's little finesee in my approach.  I know that I want three numbers in the end, so I do my chopping early, get three pieces of the UUID to play with, and THEN do the fancy math.  Maddy has more math elegance, so she does the fancy math at the start and produces a compact, opaque result. Fortunately, we both end up at the same place in the end.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3010 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...