[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:?
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!
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?
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.
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().
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)
)
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))
)