# Generate list of k distant unique colors

## weblog/

As far as I know, the best way to do picking in OpenGL is still to render each pickable object (pickle?) using a unique color. Here's what I use to get k distant and unique RGB colors. The idea is very straightforward. Sample the RGB color cube at points on the k lattice. Here's what that looks like for k = 103

This is easy to generate in matlab with:

``````k = 10*10*10;
s = ceil(k^(1/3));
[R,G,B] = ind2sub([s s s],1:k);
rgb = uint8([R;G;B]'-1)/(s-1)*255);
``````

Here's a plot of the colors in one image:

If you're object ids have spacial coherency then this will still place similar colors near each other (shouldn't really be a problem if you use a decent precision for your picking buffer). But you can always randomize the order with:

I = randperm(k); rgb = uint8([R(I);G(I);B(I)]'-1)/(s-1)*255);

to give you something like

Here's a C++ version using Eigen and libigl:

``````  size_t k = 1024;
size_t s = ceil(cbrt(k));
Matrix<unsigned char,Dynamic,3> rgb(k,3);
ArrayXi I,re;
igl::randperm(k,I);
igl::mod(I,s*s,re);
rgb.col(2) = (((I-re)/(s*s)*255)/(s-1)).cast<unsigned char>();
I = re;
igl::mod(I,s,re);
rgb.col(1) = (((I-re)/(s)*255)/(s-1)).cast<unsigned char>();
rgb.col(0) = ((re*255)/(s-1)).cast<unsigned char>();
``````

Or for the faint of heart:

``````  igl::randperm(k,I);
{
size_t i = 0;
for(size_t b = 0;b<s&&i<k;b++)
{
for(size_t g = 0;g<s&&i<k;g++)
{
for(size_t r = 0;r<s&&i<k;r++)
{
rgb(I(i),0) = r*255/(s-1);
rgb(I(i),1) = g*255/(s-1);
rgb(I(i),2) = b*255/(s-1);
i++;
}
}
}
}
``````

Update: Here's another way which requires less computation and doesn't require knowing how many unique colors you want ahead of time (though it sort of assumes a smallish number). This won't promise distant colors like above, but will still work for picking if you use unsigned byte precision:

``````[R,G,B] = ind2sub([256 256 256],mod((0:k-1)*(103811),256^3)+1);
rgb = uint8(permute(([R;G;B]'-1),[1 3 2]));
``````

The idea is to sample the 2563 cube with a large prime stride. I choose 103811 because it produced a nice balance of colors for k==100.

;