Set Vertex Colors per face on editable mesh


#1

I have a tri mesh / editable mesh and I would like to set a random color per face on the mesh. I’m not quite sure how to do this? The only work around i found was to make it an editable poly and then assign them by face and converting back to mesh, which is not going to work for my end goal. What am i doing wrong here?

image

delete objects
clearlistener()

b = box width:10 height:10 length:10 widthsegs:1 heightsegs:1 lengthsegs:1
obj = convertToMesh b
obj.showvertexColors = true

defaultVCFaces obj
for f = 1 to getNumfaces obj do
(
	local col = random blue red
	local faceVerts = getFace obj f
	for i = 1 to faceVerts.count do 
	(
		local v = faceVerts[i]
		setVertColor obj v col
	)
	update obj
)

#2

It would be great if someone could explain the logic behind vertex color indexing in the first example.
Second one works too, but first one allocates only 24 vc vertexes, while the second one box.numfaces * 3 which is 36

delete objects
clearlistener()

/*
-- #1
b = box showVertexColors:true
convertToMesh b
meshop.setMapSupport b 0 true
meshop.setFaceColor b 0 #{1,2} red
meshop.setFaceColor b 0 #{3,4} green
meshop.setFaceColor b 0 #{5,6} yellow
meshop.setFaceColor b 0 #{7,8} blue
meshop.setFaceColor b 0 #{9,10} orange
meshop.setFaceColor b 0 #{11,12} brown
redrawViews()
format "getNumCPVVerts: %\n" (getNumCPVVerts b)
for i=1 to b.numfaces do format "%\n" (getVCFace b i)
*/


-- #2
b = box width:10 height:10 length:10 widthsegs:1 heightsegs:1 lengthsegs:1
obj = convertToMesh b
obj.showvertexColors = true

setNumCPVVerts obj (obj.numfaces * 3)
buildVCFaces obj
for f = 1 to obj.numfaces do setVCFace obj f ([1,2,3] + [3,3,3] * (f- 1)	)


col = #(brown,red,blue,green,yellow,orange)

for f = 1 to getNumfaces obj by 2 do
(
	index = (f + 1) / 2

	local vcf1 = getVCFace obj f
	local vcf2 = getVCFace obj (f + 1)
	
	setVertColor obj vcf1[1] col[ index ]
	setVertColor obj vcf1[2] col[ index ]
	setVertColor obj vcf1[3] col[ index ]
	
	setVertColor obj vcf2[1] col[ index ]
	setVertColor obj vcf2[2] col[ index ]
	setVertColor obj vcf2[3] col[ index ]	

)
update obj


redrawViews()

#3

Can you see some relation with color?

Computers aren’t smart enough to made up - well, anything!

Computers aren’t smart enough to be or play stupid :grin:
Must be some instruction…


#4

No, no color :grin:
It’s pretty ordinary…
First detached face/s get new vertices. Faces 1,2 get vertices 9…12
It’s not vertex color thing.

If (auto) generate mapping coo. than opposite sides on (geometry) box are welded so breaking/detaching goes in pares or 4 pares (2 polys - 4 faces)

If not (like you) than “starting point” in UVW space is box with UV 0-1 and W 0,5-1,5 because it’s pivot is on “non natural” position in (center) bottom of mesh.

There… Some juicy, undocumented details from Max :grin:


#5

all is correct… 6 sides x 2 faces x 3 verts = 36
but every polygon has 2 faces but 1 invisible edge is shared. So we have 4 verts per poly (not 6).
this means 6 polys x 4 verts = 24


#6
delete objects
with redraw off 
(
	b = converttomesh (box())
	b.showvertexColors = on
		
	defaultVCFaces b  
	setNumCPVVerts b 24 off
	buildVCFaces b
	numcv = getNumCPVVerts b	

	colors = for k=1 to 6 collect (random black white)
		
	for k=0 to (getnumfaces b) / 2 - 1 do
	(
		vv = [1,2,3,4] + 4 * k
		f0 = 2 * k + 1
		f1 = f0 + 1
		setVCFace b f0 vv[1] vv[2] vv[4] 
		setVCFace b f1 vv[2] vv[3] vv[4] 
		
		for i=1 to 4 do setVertColor b vv[i] colors[k+1]  
	)

	update b
)

#7

Indeed. I didn’t notice that at first


#8

Great work Denis and everyone sharing there knowledge. What I’m not clear on, is how do you then handle more types of scenarios, such as a Cylinder. Where the cap is made of tons of faces but appear as one. I see here with Denis and the versions above the setNumCPVVerts is hard coded which wouldn’t work for cases like a cylinder.


#9

What about using meshop methods?

b = Cylinder showVertexColors:true
convertToMesh b
meshop.setMapSupport b 0 true

faces = #{1..b.numfaces}
polys = for f in faces where faces[f] collect
(
	poly_faces = meshop.getPolysUsingFace b f
	faces -= poly_faces
	poly_faces
)

for p in polys do meshop.setFaceColor b 0 p (random black white)

redrawViews()

#10

you can do it as a general case like this

--********************************************************************

fn OnSelectionBorder item = item[1] > 0 and item[2] > 0; 

--********************************************************************

fn SetTVItem tvmap i selected =
(
	if i != 0 then
	(
		if selected then tvmap[i][1] += 1 else tvmap[i][2] += 1;
	)
)	

--********************************************************************

fn NewTVertCount tvmap =
(
	count = tvmap.count;
	for i = 1 to tvmap.count where OnSelectionBorder tvmap[i] do count += 1;
	count;	
)

--********************************************************************

fn MapTVerts tvmap mobj =
(
	newVertIndex = tvmap.count + 1;
	for i = 1 to tvmap.count where OnSelectionBorder tvmap[i] do
	(
		tvmap[i][3] = newVertIndex;
		--setTVert mobj newVertIndex (getTVert mobj i);
		setVertColor mobj newVertIndex (getVertColor  mobj i);
		newVertIndex += 1;
	)
)	

--********************************************************************

fn 	MapTVertIndex tvmap i =
(
	res = i;
	if i != 0 then
	(
		temp = tvmap[i][3];
		if temp != 0 then
			res = temp;
	)
	res;
)	

--********************************************************************
				
fn ColMapFaces mobj faces col =
(
	--tvmap = for v = 1 to mobj.numtverts collect [0,0,0];
	tvmap = for v = 1 to mobj.numcpvverts collect [0,0,0];	
	nfaces = mobj.numfaces;
	
-- initialize the selected/unselected mapping		
	
	for f = 1 to nfaces do
	(
		selected = faces[f];
		--mapverts = getTVFace mobj f;
		mapverts = getVCFace mobj f;
		for v = 1 to 3 do SetTVItem tvmap mapverts[v] selected;
	)			
	
-- create new mapping verts along edges	
	
	newVertCount = NewTVertCount tvmap;
	--setNumTVerts mobj newVertCount true;
	setNumCPVVerts mobj newVertCount true;	
	MapTVerts tvmap mobj;
	
-- match original mapping faces to these new verts	
	
	for f = 1 to nfaces where not faces[f] do
	(
		--mapverts = getTVFace mobj f;
		mapverts = getVCFace mobj f;
		for v = 1 to 3 do mapverts[v] = MapTVertIndex tvmap mapverts[v];
		--setTVFace mobj f mapverts;
		setVCFace mobj f mapverts;
	)	
	
-- now colour our selected faces	
	
	vertset = #{};
	vertset.count = newVertCount; 
	for f = 1 to nfaces where faces[f] do
	(
		--mapverts = getTVFace mobj f;
		mapverts = getVCFace mobj f;
		for v = 1 to 3 where not vertset[mapverts[v]] and tvmap[mapverts[v]][1] > 0 do
		(
			vertset[mapverts[v]] = true;
			--setTVert mobj mapverts[v] col;
			setVertColor mobj mapverts[v] col;
		)
	)		
)	

delete objects
faces = #{13..14, 19..22}
mobj = converttomesh (plane())
mobj.showvertexColors = on
defaultVCFaces mobj  
setNumCPVVerts mobj mobj.numverts off
buildVCFaces mobj	
col = [255,0,0];

ColMapFaces mobj faces col;

faces = #{1..2, 11..12, 21..22, 31..32}
col = [0,0,255];
ColMapFaces mobj faces col;

update mobj

the generic mapping case commented out


#11

This is the way I do it …