PDA

View Full Version : Vertex color sanity check


JHN
09-16-2008, 10:43 PM
Hi all,

Im trying to simply retreive the vertex color per vertex (not per mapvertex!!).

In the manual there is a pseudo code example

In order to find out which texture vertex corresponds to a mesh vertex, you have to do the following:

1. Take the index of the mesh vertex.
2. Find out which faces reference the index of the face.
3. Note the number of the vertex (1st, 2nd or 3rd - .x, .y or .z) inside each face.
4. For each face referencing the vertex, get the texture face with the same index.
5. Get the index of the respective texture vertex from the face - 1st, 2nd or 3rd / .x, .y or .z
6. The vertex you got corresonds to the mesh vertex we started with.
7. Repeat steps 3 to 6 for all faces found.
Same applies to color vertices.


From that I came up with this:


o = $.mesh
vchannel = 0
vert = 145
-- Get all faces using the vert as array
fArray = (meshop.getFacesUsingVert o vert) as array
-- Get back vert order from face
vArray = (meshop.getVertsUsingFace o fArray[1]) as array
-- Find the order of the vert in the face
f = findItem vArray vert
-- Retreive verts from map face (map face corresponds with normal face
mV = (meshop.getMapVertsUsingMapFace o vchannel fArray[1]) as array
-- Vert order should be the same
v = mV[f]
--getVertColor o v
255.*(meshop.getMapVert o vchannel v)


Is this ok, it does work, but I don't do this vertex color thing alot, maybe someone can confirm...

Thanks,
-Johan

Bobo
09-17-2008, 04:52 AM
Not quite.

(
theMesh = snapshotasmesh $ --get the TriMesh into memory
vchannel = 0 --define vcolor channel index
vert = 1 --this is the vertex we are looking at
-- Get all faces using the vert as array
fArray = (meshop.getFacesUsingVert theMesh vert) as array
for f in fArray do -- for each face,
(
--Get geometry face - vertex is either its first, second or third component
gF = getFace theMesh f
-- Get map face (index corresponds with geometry face)
mF = meshop.getMapFace theMesh vchannel f
-- Find order inside the mesh face - vertex (component) order will be the same in both
mV = case of
(
(gF.x == vert): mF.x
(gF.y == vert): mF.y
(gF.z == vert): mF.z
)
--show the value
format "Face: %, MapVertex: %, Color: %\n" f mV (255.*(meshop.getMapVert theMesh vchannel mV))
)--end f loop
delete theMesh --release the mesh from memory
)--end script

For example, every mesh vertex of a geosphere with some vertex colors painted will have either 5 or 6 corresponding map vertices, each with its own value (usually the same, but sometimes not).

Here are the results from the first 4 vertices of a geosphere I painted some red on the north pole of:

Face: 1, MapVertex: 1.0, Color: [255,0,0]
Face: 2, MapVertex: 4.0, Color: [255,0,0]
Face: 3, MapVertex: 7.0, Color: [255,0,0]
Face: 4, MapVertex: 10.0, Color: [255,0,0]
Face: 5, MapVertex: 13.0, Color: [255,0,0]
0
Face: 1, MapVertex: 2.0, Color: [255,234.729,234.729]
Face: 5, MapVertex: 15.0, Color: [255,234.729,234.729]
Face: 6, MapVertex: 18.0, Color: [255,234.729,234.729]
Face: 10, MapVertex: 29.0, Color: [255,234.729,234.729]
Face: 11, MapVertex: 31.0, Color: [255,234.729,234.729]
Face: 12, MapVertex: 34.0, Color: [255,234.729,234.729]
0
Face: 1, MapVertex: 3.0, Color: [255,219.35,219.35]
Face: 2, MapVertex: 5.0, Color: [255,219.35,219.35]
Face: 6, MapVertex: 17.0, Color: [255,219.35,219.35]
Face: 7, MapVertex: 21.0, Color: [255,219.35,219.35]
Face: 13, MapVertex: 37.0, Color: [255,219.35,219.35]
Face: 14, MapVertex: 40.0, Color: [255,219.35,219.35]
0
Face: 2, MapVertex: 6.0, Color: [255,239.686,239.686]
Face: 3, MapVertex: 8.0, Color: [255,239.686,239.686]
Face: 7, MapVertex: 20.0, Color: [255,239.686,239.686]
Face: 8, MapVertex: 24.0, Color: [255,239.686,239.686]
Face: 15, MapVertex: 43.0, Color: [255,239.686,239.686]
Face: 16, MapVertex: 46.0, Color: [255,239.686,239.686]
0

If you take a box and paint a different color on each side of it, its corner vertices would need different map vertices to accomodate the color of each side. So you cannot assume there is ONE map vertex there giving the mesh vertex its color, there can be ANY number of map vertices, one per each face sharing that vertex. In some cases, these faces might reference the SAME map vertex, but in many cases they don't.
Another example, the pole of a Sphere has as many map vertices as there are segments in the sphere. Unwrap it and you will see a row of map faces at the poles, each with its own map vertex.

I see the pseudo code in the Reference is not clear, will try to add a real code example next time around.

JHN
09-17-2008, 07:29 AM
Bobo, thanks so much for your example, it does make sense... only....
I need to export a vert color per vertex, it's like exporting a weightmap, which can have only 1 value per vertex. I use vertex paint to paint the weights (since max obviously hasn't got weight maps, like maya/xsi).. So with that in mind, I only sample 1 face per vertex, since I'm assuming from the start that the painted vertex colors are going to be continous. I could also sample all the mapverts corresponding with the right faces and get back the avarage of that, but I think it's overkill.

With that in mind (which I should have stated in my first post offcourse) is my method still sound, cause I only need 1 color per vertex back..

Thanks,
-Johan

*prepares for some more testing*

Bobo
09-17-2008, 03:03 PM
With that in mind (which I should have stated in my first post offcourse) is my method still sound, cause I only need 1 color per vertex back..


Nope, your method is not sound. It uses findItem to find something that has no relevance to what you are trying to do, and would work just by accident but not because it is correct.

To get just one value, remove my FOR loop and just set F=1 instead. The rest can remain the same as you need to check the .x, .y and .z components of the Face and MapFace definitions to see which vertex corresponds to which mapVertex.

CastorBlast
10-26-2008, 12:34 AM
Hello,

Thank you very much for this post. This code really helps me.

However, I'd like to ask about the vchannel variable. I saw in the manual, and it's an Integer which stands for the mapChannel of the face, but I really don't understand this. Could someone explain me or tell me where to get this information?

I tried writing this same function, but I got an error:
-- Runtime error: Map support not enabled for specified map channel: 0

As I said, I don't understand this. I then set vchannel to 1 and it worked, but I'd like to understand a bit more about what I'm writing.

Thank you again.

JHN
10-26-2008, 12:18 PM
By default an object has no vertex colors and so no information in map channel 0. So if you haven't assigned them explicitly this failure will occur. Collapse the object to mesh/poly and assign vtx colors by hand. Do you still have the problem then?

-Johan

CastorBlast
10-26-2008, 03:11 PM
I can't find out how to assign by hand.

I tried using setNumCPVVerts $ (getNumVerts $) true and I still get the same error after I execute the function I want.

Then I tried meshop.setNumCPVVerts (getNumVerts $) 162, and it doesn't work, I get the same error after executing this one.

How then can I "assign vtx colors by hand". (I have already converted it to Mesh).

Thank you.

NOTE: if a leave vchannel = 1, the function does work. However, if after that I assign a material, I still get the same values. So it is like the material assignment is not being registered, or the function is not working...

CastorBlast
10-26-2008, 04:19 PM
Okay, I think that assigning vertex colors by hand means to apply the VertexPaint modifier, am I right? By doing this, I can execute the Bobo-function with vchannel = 0 and get no errors.

The question that still remains is the color itself. The first time I execute the function I get that every vertex is white, and after I assign more materials, I still get the same answer.

How can I fix this?

JHN
10-26-2008, 07:39 PM
Hi,

Try this code


b = box heightSegs:10 widthSegs:10 lengthSegs:10
convertToPoly b

-- enable viewport shading
b.showVertexColors = true
b.vertexColorsShaded = false
b.VertexColorType = #color

-- Only works in 2008 and higher
polyOp.setMapSupport b 0 true

-- Get vertColor vert count
vc = polyOp.getNumMapVerts b 0

-- Create color as point3 value
c = (orange as point3) / 255

-- Loop over all verts and assign a vertex color
for i in 1 to vc do
polyOp.setMapVert b 0 i c

-- redraw views
completeRedraw()


Goodluck,
-Johan

CastorBlast
10-27-2008, 09:43 AM
Thank you for your answer, JHN.

I didn't try the code because I don't have 3DS 2008. But I found out how to fix what I was trying to do.

I have another question, though. I modified a bit the Bob-function so instead of telling me the colour of a given vertex, it applies another colour. I just used meshop.setMapVert, and it works. But only for the viewport. There I can see the changes the functions applies, but then it doesn't render. The object rendered appears with the initial colour it had when it was first created; as ignoring the changes applied by the function.

What do I need to add after I set the vertex colout in order to get the object propperly rendered?

Thank you again

JHN
10-27-2008, 10:55 AM
So have you an vertex color map applied to your material... vertex colors don't render without the special vertex color map applied to the diffuse slot of a material. You have to tell the renderer which color to render, just like max when an material is applied to a object it doesn't render the object(wireframe) color anymore.

-Johan

CastorBlast
10-27-2008, 03:19 PM
Okay. I am very confused. Honestly I have been working with MAXScript for a couple of weeks, and I have never worked with a similar tool ever before. I have some knowledge of 3DStudio, but none of computer graphics programming.

Now let me try to explain what I'm trying to do, because I'm affraid I'm heading the worng direction:

I have a huge function that calculates the colour for a given vertex (or face). I give this function the vertex's (or face's) normal as the input, and I get the colour to apply to that vertex (face) as the output of the function.

So, assuming this function works perfectly, is this the propper way to do this?

What I'm thinking is to apply this output colour to meshop.setMapVert, is that right? But only during this early stage. Later it would not be with simple colours but with any material so, is this Bobo-function working with the #alpha channel what I need?

JHN
10-27-2008, 03:52 PM
Vertex colors are very confusing! So with acknowledging that lets have a look and see if I can help with this (because I'm also still learning all about vertex colors!).

Some pointers... vertex color vertices are not the same as mesh vertices. Vertexcolor vertices are the same as UVW vertices. The vertexcolors are stored in mapchannel 0 and behave the same as a normal UVW map (try to apply a UVWunwrap to an vertexedcolored object, select vertexcolors on the Unwrap and press reset, now check out the UVeditor, colors are represented as UVW (or point3) values). So that means there's no direct relation between a mesh vertex and a vertex color vertex. That's the real confusing part.
Only a face has a relation to a VC vertex each (tri)face has 3 UVW verts... with these you can do the manipulations.

First
You are applying the normal direction of a given face as vertex color to the vertexcolor vertices? Am I right?

in very short pseudocode

normal = getNormalFace object face1
mapVerts = getMapVertsFromFace object face1
for i in mapVerts do setMapVert object i normal

This will apply the face normal as color to the faces' mapVerts.

Is that what you mean? And what do you want to do with this information, you want to apply the normals as vertex color? there should be easier ways... maybe..

-Johan

CastorBlast
10-27-2008, 04:54 PM
Hello again,



First
You are applying the normal direction of a given face as vertex color to the vertexcolor vertices? Am I right?

in very short pseudocode

normal = getNormalFace object face1
mapVerts = getMapVertsFromFace object face1
for i in mapVerts do setMapVert object i normal



Well, actually no.

Suppose we have a function myFunction that gets one input parameter Nn, and returns a point3 color. The calculations of the function are irrelevant right now. Nn is the normal of a given vertex (or face). The output is the colour I want to apply to that vertex (or face).

So my code goes inside the Bob-function like:

(
theMesh = snapshotasmesh $ --get the TriMesh into memory
vchannel = 0 --define vcolor channel index
vert = 1 --this is the vertex to which I want to calculate a new colour
--Nn contains the normal of this vector
-- Get all faces using the vert as array
-- Actually I don't need to go through the whole of this loop,
-- to get on correct mV is enough.
fArray = (meshop.getFacesUsingVert theMesh vert) as array
for f in fArray do -- for each face,
(
--Get geometry face - vertex is either its first, second or third
component
gF = getFace theMesh f
-- Get map face (index corresponds with geometry face)
mF = meshop.getMapFace theMesh vchannel f
-- Find order inside the mesh face - vertex (component) order will be the
same in both
mV = case of
(
(gF.x == vert): mF.x
(gF.y == vert): mF.y
(gF.z == vert): mF.z
)
--apply the calculated colour to the vertex
meshop.setMapVert theMesh vchannel mV (myFunction Nn)
)--end f loop
delete theMesh --release the mesh from memory
)--end script



So, at this point, this function is enough for me! I'm at a point in which working with plain colours is all I need (I will post here my results as soon as I have them).

But later, I need to use textures, so myFunction won't be working with regular colours, and therefore it won't be returning regular colours. So my question is, would this procedure still work for me then? Is there a way to get the RGB component of any material to apply it to a given vertex (or face)?

Once again, thank you.

JHN
10-27-2008, 07:08 PM
Ah ok, I see what you mean now. The same function could be a starting point to retreive colors from a texture. There's no quickmethod to retreive information from a texture. If you want to get it from bitmaps, the thing you have to do is to figure out where the UVWmap (channel 1, 2 till n..) vertex is and where on the bitmap that is, then you have to get the pixel which corresponds to the UV coordinate with the bitmap functions.

It's not a trivial thing, and I don't really know how to get the values from procedural textures such as noise. I'd reckon you'd need to render the map to a bitmap and sample that. But that's as far as I can take from the top of my head.

In the MXS manual there's a tutorial about a object map painter which uses lot of these idea's in a somewhat similar fashion. It has been written by Bobo and if you really want some expert advice, you should try to contact him also check out a tutorial he made: http://www.scriptspot.com/bobo/mxs5/pflow/pflow__inherit_UV.htm

Cheers,
-Johan

CastorBlast
10-28-2008, 10:16 PM
Hello to everyone who's been following my posts here, specially JHN and Bobo.

After all my questions, I have finally completed the first stage of what I need to do.

Please watch it here:

http://forums.cgsociety.org/attachment.php?attachmentid=134449&stc=1

So how does this work? I'm really not sure at all. The function which performs the main blending and masking was not written by me or for MAXScript and I don't understand it. All I did was to translate it to MAXScript to achieve what I need to do.

Basically the idea is to make some sort of extension to the Top/Bottom material and make it a Top/Bottom/Left/Right/Front/Back material. Aditionally, the original function was very, very precise because it worked by pixel, I had to work by vertex so I lost a lot of precission.

Well, I don't want to discuss this here anymore, I'll open a new thread for this because my new questions go away from the main subject of this one, and I also want to get more attention.

Thank you again for all your help.



http://forums.cgsociety.org/attachment.php?attachmentid=134450&stc=1

CGTalk Moderation
10-28-2008, 10:16 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.