Notifications
Clear all

[Closed] group faces by SetFaceColor

What is a good way to filter through an entire objects polygons sorting out the polygons with matching face colors? From there I just want to put the information into a struct or array which contains the face index with the color.

The desired results would return something like this.

#(Faces:#(1,5,8,30,60,30,20) Color:[10,50,150])
#(Faces:#(7,5,9,27,54,32,22) Color:[30,80,70])

The script below creates a test file for what I’m talking about.
Thank you guys. It’s a new year, look out for new stuff.


delete objects
obj = convertToPoly (sphere segments:12)
obj.displayByLayer = false 
obj.vertexColorType = 5
obj.vertexColorMapChannel = 99
obj.showVertexColors = on

numFacesBitArr =  polyOp.getNumFaces obj
grp = 18

fn shuffleIndexes count = --unique Random order
(
	list = #() 	
	list.count = count
	for k = 1 to count do 
	(
		i = random 1 k
		list[k] = list[i]
		list[i] = k
	)
	return list
)

faceIdxArr = shuffleIndexes numFacesBitArr

clearlistener()
for g = 1 to faceIdxArr.count by grp do
(
	faces = (for i = g to (g + grp-1) collect faceIdxArr[i]) as bitArray
	COL = [(random 10 245), (random 10 245), (random 10 245)]
	polyOp.SetFaceColor obj 99 faces COL -- and set a color as user feedback
)
completeRedraw()

-- polyData = faces:? col:?

60 Replies

Alright I’m getting somewhere.

Now I need to figure out a good way to make my data array Unique based on colors.

So there is only one color item in the array which then has the complete list of faces that are associated with it.


(
	struct myPolys
	(
		Faces,
		Color
	)
	
	obj = selection[1]
	clearlistener()
	
	if classof obj == Editable_Poly do (
		myData = #()
		storedSelection = polyOp.getFaceSelection obj
		
		numFaces = polyOp.getNumFaces obj
		for i = 1 to numFaces do
		(
			polyOp.setFaceSelection obj i
			col = obj.GetFaceColor 99
			append myData (myPolys Faces:i Color:col)
		)
		polyOp.setFaceSelection obj storedSelection --restore users selection
		print myData
	)
)


   random [10,10,10] [245,245,245]
  

is better than


   [(random 10 245), (random 10 245), (random 10 245)]
   

Also:
the GetFaceColor is ridiculously slow!

How else would you get the face color then? What would be faster?

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

polyop.getmapvert for all map face vertices. it makes the getting color about 50 times faster

How does using polyop.getmapvert allow me to get the same result which is struct with the sorted data of face color and face indices. I seem to be missing something as polyop.getmapvert returns a point 3…not an rgb value?

1 Reply
(@wallworm)
Joined: 11 months ago

Posts: 0

From my understanding (which might be wrong), I think that a vertex color is equivalent to a tvert internally… and the rgb colors are actually just stored in point3. Again, I might be wrong… it’s too late for me to be even sure that (am I right) it answers your question in any useful way. It seems like I came to that conclusion a few months back while making something.

EDIT… so if I am not blowing smoke, it means that doing getmapverts using the vert color channel will result in the colors of the verts for that face… and perhaps that is some speed bonus over getFaceColor()

But how does one get around the fact that one vert can store many colors consider it 1 vert can be a part of multiple faces.

I guess we will wait to see what Denis has to say about the topic.

2 Replies
(@wallworm)
Joined: 11 months ago

Posts: 0

Well a Vert can have multiple Texture Verts… but if you know the face you can get only the texture vertices for that face. See polyop.getMapFace().

(@denist)
Joined: 11 months ago

Posts: 0

thanks.
well. first is there is no ‘color’ channels in poly structure. all channels are point3. if the poly returns the color it’s only an extra service that poly interface provides.
the returned ‘color’ is not more than point3 -> point4 -> color.
ok. let’s talk about ‘face’ color. there is NO such thing in poly structure. there is ‘face’ mapping where every map face has a list of isolated (not shared) map verts. using setfsacecolor you:

apply face mapping

set the same color (actually point3) to all face map verts

because there is no such thing as ‘face’ color we can define it as:

average color of all face vertices

or

the color of the first (or any) face vertex

and… how to convert point3 to color? easy… i’ve showed it on this forum:
#1 … (color point3.x point3.y point3.z)*255
#2 … (point3 as point4) as color

That is very cool. I was unaware that was a place of information.
Check out the script below. So far it creates the scene for test, then assigns random colors to polygons, choosing colors from a limited selection.
I then get all the vert color data.

Now how do I then create an array similar to that mentioned before where I can return a struct with this data.

The color of the face, the faces of the same color, and the verts used on those faces.

polyGroups =
#(
(polyData color:[156,43,12] faces:#{1,5,10,8} verts:#(1,2,3,4)),
(myPolys color:[222,134,196] faces:#{2,7,9} verts:#(3,4,5,6)),
(myPolys color:[156,43,12] faces:#{3,6,12,14} verts:#(5,6,7,8)),
(myPolys color:[175,187,81] faces:#{4,11,13,15} verts:#(7,8,1,2))
)

TESTING SCRIPT


(
	-- SCENE SETUP
	delete objects
	obj = convertToPoly (sphere segments:8)
	obj.displayByLayer = false 
	obj.vertexColorType = 5
	obj.vertexColorMapChannel = 99
	obj.showVertexColors = on

	facesCollection =  #{1..polyOp.getNumFaces obj}

	fn fnSetColor node faces = 
	(
		col = #(red,yellow,orange,green,blue)
		c = random 1 col.count
		polyOp.SetFaceColor node 99 faces col[c] -- set a color of poly face
	)
	
 	clearlistener()
	for f in facesCollection do
	(
		fnSetColor obj f
	)
	update obj
	
	--DATA COLLECTING
	numVerts = polyop.GetNumVerts obj
	for i = 1 to numVerts do
	(
		vertPt = (polyop.getMapVert obj 99 i) as point4
		vertCol = vertPt as color
		print vertCol
		
	)
)



So in this script using the one I posted above this, I added to it.

I added going through each set of verts face by face and getting the average RGB value for each face and then storing it all in a struct.

Sadly the store struct and face/vert/color data does NOT properly match that of the object.
I’m not sure what to do next.

Feel free to test it out. Just run the script and youll see in the returned data that the Faces & Colors do not turn out right.


(
	-- SCENE SETUP
	delete objects
	obj = convertToPoly (sphere segments:8)
	polyop.deleteFaces obj #{1..8,25..32}
	obj.displayByLayer = false 
	obj.vertexColorType = 5
	obj.vertexColorMapChannel = 99
	obj.showVertexColors = on

	facesCollection =  #{1..polyOp.getNumFaces obj}

	fn fnSetColor node faces = 
	(
		col = #(red,green,blue)
		c = random 1 col.count
		polyOp.SetFaceColor node 99 faces col[c] -- set a color of poly face
	)
	
 	clearlistener()
	for f in facesCollection do
	(
		fnSetColor obj f
	)
	update obj
	
	--DATA COLLECTING
	struct Data (face,verts,color)
	
	Polygroups = #()
	
	--store each set of verts along with the face ID number they create'
	numFaces = polyop.GetNumFaces obj
	for i = 1 to numFaces do
	(
		pts = polyop.getFaceVerts obj i
		append Polygroups (Data face:i verts:pts)
	)
	
	--find each faces average color
	for itm in Polygroups do
	(
		pts = itm.verts
		avgRGB = [0,0,0]
		
		for i in pts do
		(
			vertPt = (polyop.getMapVert obj 99 i) as point4
			vertCol = vertPt as color
			avgRGB += vertCol
		)
 		avgRGB /= pts.count
		
		itm.color = avgRGB --pump back into the data the color associated with that set of verts/face
	)
	print Polygroups
)

do you not listen me? i told that SetFaceColor is very slow. Do you not trust me?
check yourself:


 (
 	-- SCENE SETUP
 	delete objects
 	obj = convertToPoly (sphere segments:64)
 	--polyop.deleteFaces obj #{1..8,25..32}
 	obj.displayByLayer = false 
 	obj.vertexColorType = 5
 	obj.vertexColorMapChannel = 99
 	obj.showVertexColors = on
 		
 	polyop.setmapsupport obj 99 on
 	polyop.applyuvwmap obj #face channel:99
 --	polyop.getmapsupport obj 99
 
 	facesCollection =  #{1..polyOp.getNumFaces obj}
 	seed 0
 	fn fnSetColor node face = 
 	(
 		col = #(red,green,blue)
 		c = random 1 col.count
 		polyOp.SetFaceColor node 99 face col[c] -- SLOW!!!
 		--for v in (polyop.getmapface obj 99 face) do polyop.setmapvert obj 99 v (col[c] as point4) -- FASTER!!!
 	)
 	
 	t1 = timestamp()
 	for f in facesCollection do
 	(
 		fnSetColor obj f
 	)
 	update obj
 	format "time:%
" (timestamp() - t1)
 )
 
1 Reply
(@jokermartini)
Joined: 11 months ago

Posts: 0

You said GetFaceColor was slow…there was no mention of SetFaceColor as well. I was unaware that was the same case. That is crazy how much faster it is.

Using this new method how does one return an array contain the information desired…

The faces of the same color, the color of those faces and the verts used on those faces.

polyGroups =
#(
(polyData color:[156,43,12] faces:#{1,5,10,8} verts:#(1,2,3,4)),
(myPolys color:[222,134,196] faces:#{2,7,9} verts:#(3,4,5,6)),
(myPolys color:[156,43,12] faces:#{3,6,12,14} verts:#(5,6,7,8)),
(myPolys color:[175,187,81] faces:#{4,11,13,15} verts:#(7,8,1,2))
)

Page 1 / 5