Forum Groups
  All forums
    Help & Feedback
      Work in progress
      Finished Art
      Non-Max related

Featured Threads
  inspiration alert!!!
(37 replies)
  Indespensible MaxScripts, Plugins and 3rd Party Tools
(37 replies)
  The allmighty FREE Resources Thread !
(17 replies)
  spam alert!!!
(4886 replies)
  Maxforums member photo gallery index
(114 replies)
  Maxforums Member Tutorials
(89 replies)
  three cheers to maxforums...
(240 replies)
  101 Things you didnt know in Max...
(198 replies)
  A Face tutorial from MDB101 :D
(95 replies) Members Gallery
(516 replies)
(637 replies)
  Dub's Maxscript Tutorial Index
(119 replies)

Maxunderground news unavailable

Vertex Color and Texture Maps oh my!
show user profile  ccampbell
So Ive never worked with Vertex colors in max script before and I'm having a bit of trouble understanding how to to access the vertex color on my object.

Ideally i would like to bake my texture map colors to the vertex colors and then select all vets of a given color on my geometry. Or take an object with cpv already and detect and select the desired color- vertex.

Ive been doing some research today and looked at the max script help file as well as searched the forums here for some clues already. I'm just not really getting it.

Any Tips or Hints would be fantastic!

$Entrepreneur = if((Designer + Engineer)*Programmer){Problem Solver};

read 4374 times
2/11/2012 8:50:44 AM (last edit: 2/11/2012 8:50:44 AM)
show user profile  Garp
It's actually fairly simple. The vertex colors are stored (by default) in map channel #0. Only the Point3 value corresponding to each vertex holds a normalized color value, instead of UV coordinates.

Try this:
- make a plane and add a VertexPaint modifier to it;
- in the tool dialog, set the color display to vertex - unshaded (top left icon), click on the brush, then on the black colorpicker and paint it;
- right-click and convert to editable mesh.

In the Utility panel, use the More... button to launch the Channel Info utility. As you can see, the map channel labelled 0:vc has a lot more vertices than 1:map, 96 if you've left the plane to the default 4x4 segments. It's as if you had broken all the faces apart: each quad has 2 faces and each face has 3 verts. 4x4 segments x2 faces x3 verts = 96 verts.

With the plane selected, type in the listener
meshOp.getNumMapVerts $ 0
You get 96
Now type
meshOp.getMapVert $ 0 30
where $ is the mesh, 0 the map channel holding vertex colors and 30 a vertex index.
You get a value that looks like
That value has been normalized. If you want the RGB value in its 8-bit format, you need to multiply it by 255. And if you want it in the regular color format, you type
([0.298585,0.504884,0.760694] * 255) as color
You then get
(color 76.1392 128.745 193.977)

To assign a color to a vertex, you just go the other way around.
meshOp.setMapVert $ 0 30 (normalize [185,191,163])
meshOp.setMapVert $ 0 30 (normalize (color 185 191 163 as Point3))
(RGB 185 191 163 is the famous MF green)
You'll probably have to add update $ to see the change in the viewport.
If you use one of max's predefined color variables, like orange, you need to use the second version.
meshOp.setMapVert $ 0 30 (normalize (orange as Point3))

And that's about it. I hope it clarifies things a little.

read 4362 times
2/11/2012 11:41:28 AM (last edit: 2/11/2012 11:51:00 AM)
show user profile  ccampbell
Hey Garp,
Thanks alot that totally cleared a ton up, you never cease to amaze me.

Im starting to understand what the help file was talking about in the texture and vertex color definitions. One thing that still confuses me a bit is actually collecting the verts of a certain color into my selection or an array.

If i read correctly there there can be more or less color verts than actual mesh verts there for the mesh verts do not map 1to1 to the color verts. I read something about looping through the faces and referencing the texture faces or something like that but not sure how that works.

Check out the image below, It shows the end result of what I'm after in these first steps.

$Entrepreneur = if((Designer + Engineer)*Programmer){Problem Solver};

read 4332 times
2/12/2012 7:11:16 AM (last edit: 2/12/2012 7:13:40 AM)
show user profile  Garp
The correspondance between object verts and textures verts can be a little confusing. Bear with me.

Object meshes and texture meshes have the same basic definition. First an array of vertices holding point3 values, i.e. the XYZ coordinates of each vert. Second, an array of faces, also holding point3 values, but this time the 3 values are integers and correspond to vertex indices, that is, the positions in the vertex array of the vertices defining each face.
This is for trimeshes, where faces are triangular. For polymeshes, where a face (a polygon) can be defined by 3 or more vertices, the face array holds small arrays of the appropriate number of integers instead of only point3 values. But the principle is the same.

There is always a one-to-one correspondance between object faces and textures faces, so they have the same index. Now that's not true - or even possible - for the vertices. Say you have a 1x1 segments plane converted to editable mesh. That single quad is made of 2 underlying triangular faces and there is a total of 4 verts, 2 of them being used by each face definition. Nothing is preventing you from breaking these two faces apart in the UV editor and thus end up with 6 distinct vertices in the texture space. Or the other way around: you could detach the two faces of the object, map them and stitch together the texture faces. So there is no numerical way to keep track of the correspondance of the vert indices between object and texture meshes.

The way this is achieved is through the guarantee that for a particular face, the corresponding vertices are defined in the same order. For face x, the 1st vert in its object definition correspond to the 1st in all of its texture definitions (in the case of multiple map channels), same for the 2nd and 3rd, or more with polymeshes.
So typically, you would design a function, say tex_verts_from_obj_verts(), that takes as arguments an object, a vertex index and a map channel and then:
- find all the faces in the object mesh using that vertex in their definitions;
- for each face, find the position of the vert in the object face definition;
- for each face, use the previous position to find the corresponding vertex index in the texture face definition;
- return a bitArray with the texture vertex indices.
For a obj_verts_from_tex_vert() function, it's the same but the other way around.
It's messy and you'd need different versions for trimeshes and polymeshes. Why such functions are not already part of maxscript is beyond me (unless they've been added recently).

BUT, there is a workaround - or rather a hack - to make things much simpler (ain't life great?).
In the ChannelInfo utility, you can click-and-paste one channel to any other. So if you were to copy the channel at the top, named mesh or poly depending on your object, to any map channel, you would get the same amount of vertices in that texture mesh than in the object mesh and since the face definitions would be the same, the vertex indices would match. The utility uses a UVW Mapping Paste modifier to do that and you need to collapse it.
You can get the same result by simply applying a planar mapping to the object. For the special map channel #0 - the vertex color channel - you cannot set the map channel setting to 0 but both the UVW Map and the Unwrap UVW modifiers have a Vertex Color Channel option.

To do the same through maxscript, you have to first set the number of texture vertices to be the same as the number of object vertices, then loop through all the faces and copy the definitions from object mesh to texture mesh. Again, you would need two functions, one for trimeshes, one for polymeshes.
Once you've done that, you can happily assign vertex colors using the vert indices of the object and the color won't be assigned to some other vert at the other end of the mesh.
One thing to note though. If at some point you add a Vertex Paint modifier, it will modify map channel #0 automatically: it will keep the current vertex values (the colors) but it will reset the face definitions to be all separated and renumber all the verts.

To make testing easier, I have a short macro that displays the vert indices in the viewport, if you want it.

One last note. When comparing the color values, you need to implement some tolerance threshold as normalizing one way and multiplying by 255 the other is likely to cause rounding errors and the exact values won't always match. Annoying, I know, but there's no way around it.

edit: both the meshOp and the polyOp interfaces have a defaultMapFaces() method that automatically sets the number of texture verts and the texture face definitions to be copies of that of the object mesh.
Sorry, I just found it out.

read 4317 times
2/12/2012 2:59:57 PM (last edit: 2/12/2012 4:12:54 PM)
show user profile  Garp
And a quicky to illustrate.

Unable to display content. Adobe Flash is required.

read 4299 times
2/12/2012 6:21:24 PM (last edit: 2/12/2012 6:21:24 PM)
show user profile  ccampbell
Hey Garp, Thanks alot for the responses. I've been forced to let this one go for a few weeks as it was consuming to much of my time and i had other things to get done. I'll be working on this same issue again in the near future.

thanks alot for all the time spent to help learn me something ! :)

$Entrepreneur = if((Designer + Engineer)*Programmer){Problem Solver};

read 4239 times
2/29/2012 6:29:43 PM (last edit: 2/29/2012 6:29:43 PM)
show user profile  digital3ds
Damn garp, you seem crazy good at maxscript.. how long have you been doing it for?
- Mike Sawicki

read 4222 times
3/1/2012 6:58:51 AM (last edit: 3/1/2012 6:58:51 AM)
show user profile  ccampbell
I'm resurrecting this thread I started some months back. I finally have a bit more time and NEEEEEED to understand exactly how this texture and color per vertex stuff works. Any help would be reaaaally appreciated! I am going to have to work with it a lot soon and not understanding it is gonna drown me :/
The thing that kills me the most is for some this is CAKE but I've been struggling with it for DAAAAAYZ on multiple occasions and its not sinking in.

I have an object "theMesh" with a Texturemap on it. I need to find specific colors from the texture map and collect the Vertices under/ closest to the color I choose into my selection or an array for processing later.(i.e. generate shapes at the colored locations).

1) Learn how to search for a specific color in the texture map of my object and relate that color/pixel to a vertex on the mesh and collect for later
2)Learn how to search for a specific color when in an object with only vertex color available and collect the vertices for later.
3) create a script that will convert a texture map to Color per vertex ( and back if possible) then select all vertecies of a given color.

The biggest problem for me here is the logic. I get confused how to use the information once I have collected it . Individually i know how to collect the faces and texture faces. and i can get the cpv color of my vertices once color is available on them ( THANKS GARP!) But what I CAN NOT do is figure out how to combine all of this information together

-How to I get a bitmap available for sampling ( open in variable some how? ).
-How do I get vertex(point3) coords into bitmap (point2) coords and back?
-How do I relate a uv/uvw coordinate and/or color to my mesh vertex/face once I have found the color I am looking for?
-Not exactly sure what the difference is between uv and uvw coordinates in relation to a texture map are. I know W is the 3rd dimension and not usually used on a bitmap unless procedural but are they the same othewise?
-Less relevant but would be great to know! - Can I get the texture color information using BaryCoords? i.e. IntersectRayEX

I know some of those questions probably over lap but thats my problem! i just dont know how to put it all together

I'm stuck here guys, any code or tutorials you can provide would be really helpful.

$Entrepreneur = if((Designer + Engineer)*Programmer){Problem Solver};

read 4074 times
6/15/2012 12:45:50 AM (last edit: 6/15/2012 12:50:26 AM)
show user profile  ccampbell
So I think I'm nearly there but I'm having a problem still... For some reason I'm only getting Red Pixel colors back even though i have Red, Green, and blue available in my bitmap. I think I'm collecting the texture vert color's wrong or converting the uvw coords to bitmap coords wrong but not sure what the problem is!

Can anybody help with the code?

-- loop through all mesh vertx
-- get connected faces
-- loop through all connected faces and get coresponding texture faces
-- get mapverts from texture faces
-- find vert indicies in map verts that coresponds to current master loop vertex
--get coords of of texture verts by using collected indicies from above
--convert coords of vertex into bitmap coords
--get pixel color at that coordinate
--if blue collect master loop vertex integer into array

--Variable Declerations
theMesh = $
MapChannel = 1
theTextureMap = renderMap theMesh.material.diffuseMap size:[subdivs,subdivs] filter:on display:false

TargetFacesTexVerts= #()
TargetFacesTexVertCoords = #()
VertIndicies = #()
TexVertColors = #()
BlueVerts = #()
GreenVerts = #()
RedVerts = #()

-- Loop through all mesh verts
for v = 1 to theMesh.numverts do
--Get corresponding shared faces
TargetFaces = polyop.getFacesUsingVert theMesh v as array --get faces that reference the current vertex

-- get corresponding face verts then get corresponding texture vert indecies
for f = 1 to TargetFaces.count do
FaceVerts = polyop.getFaceVerts theMesh TargetFaces[f] -- get mesh face verts
append VertIndicies (finditem FaceVerts v) -- get face index corresponding to primary vert index.

FaceTexVerts = polyOp.getMapface theMesh MapChannel f -- get single texture face verts
append TargetFacesTexVerts FaceTexVerts
-- Get coordinates of each respective vertex
for c = 1 to TargetFacesTexVerts.count do
append TargetFacesTexVertCoords (polyop.getmapvert theMesh MapChannel TargetFacesTexVerts[C][VertIndicies[C]])

for b = 1 to TargetFacesTexVertCoords.count do
--convert vertex coords to bitmap coords
--textureCoords = [ (uvCoords.x)*(thisTexture.width-1) , thisTexture.height-(uvCoords.y)*(thisTexture.height-1) ]
BitmapCoords = [ (TargetFacesTexVertCoords[b][1])*(theTextureMap.width-1) , theTextureMap.height-(TargetFacesTexVertCoords[b][2])*(theTextureMap.height-1) ]
--print Bitmapcoords
append TexVertColors (getPixels theTextureMap BitmapCoords 1)--[1]
--print TexVertColors
--Average Vertex Color
Avg = TexVertColors[1][1]
for A = 2 to TexVertColors.count do
Avg = Avg + TexVertColors[A][1] as point3
--Get average vert color from all texture vert colors collected
AverageColor = (avg / TexVertColors.count) as point3

--Look for Primarily blue texture verts
if AverageColor[3] > AverageColor[1] and AverageColor[3] > AverageColor[2]
append BlueVerts v
Print ("BlueVerts: " + BlueVerts[v] as string)
if AverageColor[2] > AverageColor[1] and AverageColor[2] > AverageColor[3]
append GreenVerts v
Print ( "Green: " + GreenVerts[v] as string)
if AverageColor[1] > AverageColor[2] and AverageColor[1] > AverageColor[3]
append RedVerts v
Print ("Red: " + RedVerts[v] as string)

-- reset array's for next loop
TargetFacesTexVerts= #()
TargetFacesTexVertCoords = #()
VertIndicies = #()
TexVertColors = #()


$Entrepreneur = if((Designer + Engineer)*Programmer){Problem Solver};

read 4027 times
6/15/2012 8:52:54 PM (last edit: 6/15/2012 10:12:32 PM)
show user profile  ccampbell
Bump** Gotta get this resolved ive officially started working on a project that requires extracting colors from a texture map and getting there position on the 3d object.

Does anybody know how to convert uvw coordinates to bitmap coordinates (and back if possible)?

$Entrepreneur = if((Designer + Engineer)*Programmer){Problem Solver};

read 3996 times
6/18/2012 5:02:27 PM (last edit: 6/18/2012 5:02:27 PM)
#Maxforums IRC
Open chat window