Assign random vertex color per element

Assign random vertex color per element

Anonymous
Not applicable
10,053 Views
12 Replies
Message 1 of 13

Assign random vertex color per element

Anonymous
Not applicable

Hi, im using substance painter a lot and i have to assign to my objects random vertex colors to each element to make selections. Is there any script to do this automatically? ty

ps. if there is someone using substance too and knows other way of passing selections into substance im all ears 🙂

0 Likes
Accepted solutions (1)
10,054 Views
12 Replies
Replies (12)
Message 2 of 13

Swordslayer
Advisor
Advisor
Accepted solution

If random vertex color per element is enough (which may or may not result in duplicates, changing seed might help sometimes), you can use dataChannel modifier for that:

 

dataChannelVC.gif

Message 3 of 13

Swordslayer
Advisor
Advisor

And as a script that ensures unique colors:

 

 

fn shuffle arr =
    for counter = arr.count to 1 by -1 collect
    (
        local swapIndex = random 1 counter
        swap arr[random 1 counter] arr[counter]
    )

fn incrementCounters &r &g &b step =
    if (b += step) > 256 do
    (
        b = 1
        if (g += step) > 256 do
        (
            g = 1
            if (r += step) > 256 do r = 1
        )
    )

fn getElements mesh =
(
    local vertCount = mesh.numVerts
    local faces = mesh.faces as bitArray
    local facesByVert = for v = 1 to vertCount collect #()

    for face in faces do
    (
        local faceVerts = getFace mesh face
        append facesByVert[faceVerts[1]] face
        append facesByVert[faceVerts[2]] face
        append facesByVert[faceVerts[3]] face
    )

    for face in faces collect
    (
        local i = 0, element = #(face), elementVerts = #()

        while (local f = element[i += 1]) != undefined do if faces[f] do
        (
            faces[f] = false
            local faceVerts = getFace mesh f

            for v = 1 to 3 do facesByVert[faceVerts[v]] = 
                for vertFace in facesByVert[faceVerts[v]] where faces[vertFace] collect
                (
                    append element vertFace
                    append elementVerts (int faceVerts[v])
                    dontCollect
                )
        )
        elementVerts as bitarray
    )
)

fn assignUniqueElementColor obj op shuffleElements:off =
(
    local elements = getElements (snapshotAsMesh obj)
    local stepCount = elements.count^(double 1/3) + 1
    local step = 255./stepCount
    local redArr = shuffle (#(0) + #{1..255})
    local greenArr = shuffle (#(0) + #{1..255})
    local blueArr = shuffle (#(0) + #{1..255})
    local r = 1, g = 1, b = 1
    
    if shuffleElements do
      elements = shuffle elements

    for element in elements do
    (
        op.setVertColor obj 0 element [redArr[int r], greenArr[int g], blueArr[int b]]
        incrementCounters &r &g &b step
    )
)

if isKindOf $ Editable_Mesh then assignUniqueElementColor $ meshop shuffleElements:on
else if isKindOf $ Editable_Poly do assignUniqueElementColor $ polyop shuffleElements:on

 

If you instead want to bind it to a shortcut, you can save it as a .ms file and use the macroscript creator to make a macro for it.

 

0 Likes
Message 4 of 13

Anonymous
Not applicable

Thanks again, exactly what i needed 🙂 

0 Likes
Message 5 of 13

Anonymous
Not applicable

One more q: this script is independent to data channel modifier and cant be used in previous max versions? thanks again

0 Likes
Message 6 of 13

Swordslayer
Advisor
Advisor

Yes, it works with any editable mesh / editable poly that's currently selected and should work across most of the old max version, more than a decade back at the very least.

0 Likes
Message 7 of 13

Jixal
Enthusiast
Enthusiast

Hey, this is super cool.

 

Is it possible to do the same but apply to all objects instead of just elements? 

 

For example, I have 9 objects that will be textured in Substance Painter and I want a random vertex color for each object (to use as an ID mask).

 

 

0 Likes
Message 8 of 13

Swordslayer
Advisor
Advisor

 


@Jixal wrote:

I have 9 objects that will be textured in Substance Painter and I want a random vertex color for each object (to use as an ID mask).


Something like

fn smootherStep x = 
    x * x * x * (x * (x * 6 - 15) + 10)

fn shuffle arr =
    for counter = arr.count to 1 by -1 collect
    (
        local swapIndex = random 1 counter
        swap arr[random 1 counter] arr[counter]
    )

fn assignUniqueVertexColor objs shuffleItems:off seed:0 =
(
    local maxVal = 256^3 - 1d0
    local maxCount = objs.count
    local counter = 0d0

    if shuffleItems and ::seed seed == OK do
        objs = shuffle objs

    for obj in objs do
    (
        local clr = smootherStep (counter / maxCount) * maxVal
        if isKindOf obj Editable_Poly do polyOp.setVertColor obj 0 #all [bit.shift (bit.and clr 0xff0000) -16, bit.shift (bit.and clr 0x00ff00) -8, bit.and clr 0x0000ff]
        counter += 1
    )
)

assignUniqueVertexColor (getCurrentSelection())

 

Message 9 of 13

denisT.MaxDoctor
Advisor
Advisor
 ::seed seed

 

I like it 🙂

0 Likes
Message 10 of 13

Jixal
Enthusiast
Enthusiast

Thanks 😃

0 Likes
Message 11 of 13

Anonymous
Not applicable

Hi,

I tried to use data channel for vertex color element, but it seems that it kills uv map channel...

Your script run fine. Thanks

0 Likes
Message 12 of 13

Jixal
Enthusiast
Enthusiast

Hi all, 

 

Joker Martini just released a really nice script that does everything that we want for vertex colouring objects and elements- https://jokermartini.com/product/vertex-color-editor/

 

Lightweight, simple and slick. Love it.

0 Likes
Message 13 of 13

alnoman.7cgi
Observer
Observer

Hello,
This is very useful. thanks for the effort!
could it be easy to convert wirecolor to vertex color for all objects or selected objects?

Thanks.

0 Likes