randomize vertex color


#1

Is it possible to randomize only the blue channel on a set of objects?
I want all the vertices of each cube to have the same blue color value, but I want each cube to have a different value of this blue. Is that possible in mel?


#2

sure, its possible.

http://help.autodesk.com/cloudhelp/2016/ENU/Maya-Tech-Docs/Commands/rand.html


#3

well this is the command so set a vertex color:
polyColorPerVertex -rgb 0.8 0.0 0.4;

and when I introduce the random function, I get an error message:

polyColorPerVertex -rgb rand <<0,0>> <<0,0>> <<0.2,0.8>>;


#4

You might have to generate and capture the random number, then feed it into the polyColorPerVertex command.

For example:

$randBlue = `rand  0.2 0.8`;

polyColorPerVertex -rgb 0.0 0.0 $randBlue;

If you want the verts to be different to each other you need to get their names into a list and loop over it generating a new random number each time.


#5

actually its not working:

Error: line 1: invalid syntax


#6

actually its not working:

Error: line 1: invalid syntax

It sounds like you ran his MEL code in a Python tab (given the error message). The code works fine on my end.


#7

Sorry, you were right. But actually all the objects have the same color.
I want to have a different blue value for each object.


#8

Right, I think Faux’s intention was to show how to apply a random color to the blue channel of a vertex color.

So if you want a different color per object, you could create a loop and on each iteration of the loop, you generate a new random value for the blue color. Your list of objects could be one color per object, or you could make it one color per vertex. It’s up to you how you want to structure your loop.

For example:

// Create a test poly plane.
polyPlane;

// Specify the set of vertices I want to color. You'll want to edit this according to what you want to color
string $listOfObjects[] = { "pPlaneShape1.vtx[12]", "pPlaneShape1.vtx[24]" };

// Give each object in the list a random blue color.
int $i;
for( $i = 0; $i < size($listOfObjects); $i++ )
{
	float $randBlue = `rand 0.2 0.8`;
	polyColorPerVertex -rgb 0.0 0.0 $randBlue $listOfObjects[$i];
}


#9

Here’s a modified version of that script that I think does what you want:


// Populate $listOfObjects yourself to be the actual shape names.
string $listOfObjects[] = { "pPlaneShape1" };

int $i;
for( $i = 0; $i < size($listOfObjects); $i++ )
{
	// Generate random blue color per object.
	float $randBlue = `rand 0.2 0.8`;

	// Iterate over the set of vertices on each object and apply the same blue.
	int $eval[] = `polyEvaluate -v`;
	int $numVertices = $eval[0];
	int $v;
	for( $v = 0; $v < $numVertices; $v++ )
	{
		polyColorPerVertex -rgb 0.0 0.0 $randBlue ($listOfObjects[$i] + ".vtx[" + $v + "]");
	}
}

#10

when I select the objects and run the script, nothing happens.


#11

Change this line:

// Populate $listOfObjects yourself to be the actual shape names.
 string $listOfObjects[] = { "pPlaneShape1" };

to this:

string $listOfObjects[] = `ls -sl`;

It’s worth taking the time to read and understand the code.


#12

works like a charm!
thanks guys :slight_smile:


#13

could be a bit slow on 4000 objects and sometimes the end results are unpredictable (1 color of green)


#14

Not sure how a green object gets in there. It’s pretty explicit in that it sets the RG channels to 0.0. In my testing I never get a green object.

   As far as performance goes, this is going to be slow because it runs a command on each vertex of each object. It won't scale well. Using the API would make this a lot faster since it can batch the changes in a single call per object.
   
   Below is a Python API version of the same script. Make sure you run this in a Python tab:
import maya.api.OpenMaya as om
import random
import time

def maya_useNewAPI():
	pass

def getSelectedMeshes():
	"""
	Returns a list of DAG paths pointing to the shape node.
	"""
	selList = om.MGlobal.getActiveSelectionList()
	paths = []
	for i in range(selList.length()):
		try:
			path = selList.getDagPath(i)
			path.extendToShape()
			if path.apiType() == om.MFn.kMesh:
				paths.append(path)
		except:
			continue
	return paths

start = time.time()
meshes = getSelectedMeshes()
numMeshes = len(meshes)
for mesh in meshes:
	meshFn = om.MFnMesh( mesh )
	faces = range(meshFn.numPolygons)
	colors = om.MColorArray()
	colors.setLength(meshFn.numPolygons)
	randBlue = om.MColor()
	randBlue.b = random.uniform( 0.2, 0.8 )
	for i in xrange(meshFn.numPolygons):
		colors[i] = randBlue
	meshFn.setFaceColors(colors, faces)
elapsed = time.time() - start
print "Processed %d meshes in %fs" % (numMeshes, elapsed)

[Edit]
I modified the above script to use setFaceColors() instead which is a bit faster than using setVertexColors(). In this particular case, we don’t care about individual components since the whole object gets the same color, so we can minimize the number of calls by setting the color per face rather than per vertex.

[setVertexColors]
Using Maya 2016, on my machine it processed 1210 meshes in 1.61s.

[setFaceColors]
Using Maya 2016, on my machine it processed 1210 meshes in 1.38s.


#15

Thanks alot, way faster!


#16

This is great!
So what would you need to change in this script to create a random vertex colour per object?