select randomly from 3 (or more) colors linearly (efficiently)

   1619   6   0
User Avatar
Member
1007 posts
Joined: April 2017
Offline
Hi!

I'm using a primitive wrangle to decide the brick color of each building. I already have a random value (0 to 1) for each building.

Now, I would like to have 0 to 0.33 to be color A, .33 to .66 to be color B, etc. I've done this befor using an IF satement per color but I hate the idea of needing to add if statements every time I add another color.

Is there an efficient way to simply have a bunch of colors swatches and an integer channel to tell how many colors i'm selecting from without having a bunch of IF statements?

Here's where I'm at so far:

i@buildingID;
int numCd = chi("number_of_colors");
int cdSteps = chi("color_banding");
float cdSpace = 1/numCd;
vector cda = chv("brick_color_a");
vector cdb = chv("brick_color_b");
vector cdc = chv("brick_color_c");

float rand01 = rand(@buildingID);
float randStep = rint(rand01*cdSteps)/cdSteps;

Thanks for any help!

-Olivier
User Avatar
Member
1007 posts
Joined: April 2017
Offline
…ok, it's not perfect but I think using FOR to loop over the amount of colors is gonna work. Still buggy but I'm working out the kinks.

v@Cd = 0;
i@buildingID;
float numCd = float(chi("number_of_colors")); //3.0
float cdSteps = float(chi("color_banding")); //20.0
float cdSpace = float(1/(numCd-1)); 
vector cdA = chv("brick_color_a");
vector cdB = chv("brick_color_b");
vector cdC = chv("brick_color_c");
vector cdD = chv("brick_color_d");
vector cdE = chv("brick_color_e");

float R[] = array(cdA.r, cdB.r, cdC.r, cdD.r, cdE.r);
float G[] = array(cdA.g, cdB.g, cdC.g, cdD.g, cdE.g);
float B[] = array(cdA.b, cdB.b, cdC.b, cdD.b, cdE.b);

float rand01 = rand(@buildingID); 
float rand01Step = rint(rand01*cdSteps)/cdSteps;  

float start; float end; vector cdStart; vector cdEnd;

for(int i=1; i < numCd; i++) 
    {
    start = (cdSpace*i)-cdSpace;
    end = (cdSpace*i);
    if((rand01Step > start) && (rand01Step < end))
        {
        cdStart = set(R[i-1], G[i-1], B[i-1]);
        cdEnd = set(R[i], G[i], B[i]);
        vector fit = fit01(rand01Step, cdStart, cdEnd);
        @Cd = fit;
        }
    }
Edited by olivierth - Dec. 5, 2018 20:22:01
User Avatar
Member
1737 posts
Joined: May 2006
Offline
Use a colour ramp with constant interpolation.

Attachments:
col_distro.gif (192.6 KB)
col_distribution.hipnc (80.0 KB)

http://www.tokeru.com/cgwiki [www.tokeru.com]
https://www.patreon.com/mattestela [www.patreon.com]
User Avatar
Member
7762 posts
Joined: Sept. 2011
Offline
nah dude, ramps take forever, use sample_discrete()

http://www.sidefx.com/docs/houdini/vex/functions/sample_discrete.html [www.sidefx.com]

Attribute randomize has a discrete mode too. Just put in the values, (and the weights for each if desired).
User Avatar
Member
1737 posts
Joined: May 2006
Offline
Ha, I'll argue that adding points on a colour ramp is faster and easier than sample_discrete. Tried attrib randomise in discrete mode, but there's no built-in option for discrete colours, just floats or strings.
http://www.tokeru.com/cgwiki [www.tokeru.com]
https://www.patreon.com/mattestela [www.patreon.com]
User Avatar
Member
1007 posts
Joined: April 2017
Offline
Thanks for the replies!

Wow, the ramp solution is WAY SIMPLER than my method! I like that I can add or remove colors easily at any time.

-Olivier
User Avatar
Member
1007 posts
Joined: April 2017
Offline
Yep, this works perfectly!

-Olivier

Attachments:
buildings_colors_good.JPG (170.6 KB)

  • Quick Links