Notifications
Clear all

[Closed] from Map-Vertex to Mesh-Vertex

How can i get from a selected Texturevertex in the unwrap UVW to the corresponding Vertex on the mesh?

If the Texturevertex connects 3 or more faces, i can take all this face-indices and check on the mesh which vertex the faces with corresponding indices share.
But if the Texturevertex is only referenced by one or two (abutting) faces, this is not possible, since they have more than one common vertex.

So – can anyone tell me how to find the mesh Vertex that corresponds to a Texture Vertex?

Thanks!

6 Replies
1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

As you have already discovered, there is no one-to-one correspondence between texture and mesh vertices. There can be 0, 1 or more vertices corresponding to a tvertex (and vice-versa – one mesh vertex can have any number of corresponding tvertices).

So it is up to you – you could select ALL vertices corresponding to the tvertex, or display a list so the user can decide which one to select if > 1, or just select the first one found ignorring the rest…

The algorithm is simple:
*Take the tvertex.
*Find all tfaces referencing this tvertex.
*For each tface, get the mesh face with the same index
*See which position the tvertex has in the tface (.x, .y or .z) and get the same vertex from the mesh face.
*Write this vertex index to an array and repeat for all tfaces.
–At the end, the array should contain one or more mesh vertices corresponding to your tvertex.

Hey Bobo

Thank you verry much for your help.
I found this tip in the Maxscript help – but i have troubles with this point:

*See which position the tvertex has in the tface (.x, .y or .z) and get the same vertex from the mesh face.

i don’t know how to access .x .y and .z of a tface and of a mesh face

Can you help me with that?
Thanks!

1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

It is simpler than it appears.

When you use GETVERT someMesh vertIndex, the result is a Point3 value with the spatial coordinates of the vertex.
When you use GETFACE someMesh faceIndex, the result is again a Point3 value, but the 3 components are not spatial coordinates, the .x, .y and .z of the Point3 value contain the indices of the 3 vertices used by the face. Same with meshop.getMapFace() when working with texture faces.

So the idea is this: You already know the index of the tvertex you are looking for. Let’s assume it is 42 and store it in the variable theMapIndex. Now you get all tfaces using that vertex, let’s assume these are tfaces with indices 3,5 and 9. You get one of the faces using, say,
theTFaceDef = meshop.getMapFace theMesh 1 3
and the result is a Point3 value with 3 integer components, one of them will be 42 for sure, let’s say it is something like [11,42,39].
So you see whether theTFaceDef.x == theMapIndex (it is not), theTFaceDef.y == theMapIndex (BINGO!) and theTFaceDef.z == theMapIndex (nope). This means that you can now get the MeshFace with index 3 using
theFaceDef = getFace theMesh 3
and get theFaceDef.y to access the mesh vertex which corresponds to map vertex 42 (because we saw that 42 is the .y component of the tface which means it MUST be .y component of the mesh face).

Then you can repeat the above for map faces 5 and 9 and see where in their 3 components the 42 is located, then get the mesh faces 5 and 9 and get the corresponding component of their Point3 values…

Hi!

Thank you verry much! I understand now how to access the face vertex indices and try to use it in my script. But i’ve got still one problem

 My script shall do the following:

break up the mesh along the uv-seams so that there can be created a one-to-one correlation between mesh vertices and map vertices. Actually the same happens if you export to .3DS and use “preserve Max’s Texture coordinates”.

 My script looks like this so far:
 
 part one:

     macros.run "Modifier Stack" "Convert_to_Mesh"
     subobjectLevel = 4
     actionMan.executeAction 0 "40021" --select All
     modPanel.addModToSelection (Unwrap_UVW ()) ui:on
     $.modifiers[#unwrap_uvw].unwrap.edit ()
     allVertices = $.modifiers[#unwrap_uvw].unwrap.getSelectedVertices()
     $.modifiers[#unwrap_uvw].unwrap2.VertToEdgeSelect()
     allEdges = $.modifiers[#unwrap_uvw].unwrap2.getSelectedEdges()
     
     openUVEdges = #{}
     
     for i=1 to allEdges.numberSet do (
     	$.modifiers[#unwrap_uvw].unwrap2.selectEdges #{i}
     	$.modifiers[#unwrap_uvw].unwrap2.openEdgeSelect()
     	local myselection = $.modifiers[#unwrap_uvw].unwrap2.getSelectedEdges()
     	myselection[i]=false
     	$.modifiers[#unwrap_uvw].unwrap2.selectEdges myselection
     	$.modifiers[#unwrap_uvw].unwrap2.openEdgeSelect()
 	openUVEdges = openUVEdges + $.modifiers[#unwrap_uvw].unwrap2.getSelectedEdges()	
     )
     $.modifiers[#unwrap_uvw].unwrap2.selectEdges openUVEdges
     
 This part of the script selects all open edges in the uv editor and stores them in "openUVEdges". So far it works fine.

in the secound part, i try to select each tEdge in “openUVEdges” one by one, take the two tVertices which are connected by the tEdge, then take the corresponding mesh vertices and finally get the corresponding mesh edge and append it to “openEdges”.


     openEdges = #{}
     
     for j in openUVEdges do (
     	$.modifiers[#unwrap_uvw].unwrap2.selectEdges #{j}
     	$.modifiers[#unwrap_uvw].unwrap2.EdgeToVertSelect()
     	local tVertices = $.modifiers[#unwrap_uvw].unwrap.getSelectedVertices()
     	
     	local polyVertices = #()
     	for v in tVertices do (
     		macros.run "Modifier Stack" "Convert_to_Mesh"
     		local tvertexFaces = meshOp.getMapFacesUsingMapVert $ 1 #{v}
     		macros.run "Modifier Stack" "Convert_to_Poly"
     		for f in tvertexFaces do(
     			 mapFace = polyOp.getMapFace $ 1 f
     			 polyFace = polyOp.getFaceVerts $ f
 			 --here i loop just through all faces and take the last one, because I don't have
  			 -- multiple mesh vertices sharing the same map vertex
     		)
     		append polyVertices polyFace[findItem mapFace v]
     	)
 	openEdges = openEdges + (polyOp.getEdgesUsingVert $ polyVertices[1] * polyOp.getEdgesUsingVert $ polyVertices[2])		
     	
     )
     
     macros.run "Modifier Stack" "Convert_to_Poly"
     subobjectLevel = 2
     $.EditablePoly.SetSelection #Edge openEdges
     
 My Problem is the following line:

     append polyVertices polyFace[findItem mapFace v]
     
 i get the following error:

     -- Error occurred in V loop
     --  Frame:
     --   V: 2
     --   polyFace: undefined
     --   tvertexFaces: #{1, 8}
     --   called in j loop
     --  Frame:
     --   tVertices: #{2..3}
     --   polyVertices: #()
     --   j: 9
     -- No ""get"" function for undefined
     
 i just don't understand what "get" it means - because there's nowhere a "get"
 
 Do you see what i'm doing wrong?
 
 
 Thanks a lot!

polyFace is undefined in the scope of your code. It only exists inside the FOR loop scope and is destroyed the moment the FOR loop finishes.
“get” means that you are trying to get a value from a variable that is undefined.

You would have to pre-declare the variable polyFace before the loop in the higher scope to make it visible after the loop finishes.

Here is some code that tries to perform the same as the 3DS export:


fn SplitVertsByMapVerts theMesh =
(

--first collect two arrays of bitarrays - one containing the map vertices for each mesh vertex,
--the other containing the faces using each mesh vertex:
convertToMesh theMesh 
lastVert = theMesh.numverts
lastFace = theMesh.numfaces
VertsUsage = for v = 1 to lastVert collect #{}
FaceUsage = for v = 1 to lastVert collect #{}
for f = 1 to lastFace do
(
	theFace = getFace theMesh f
	theMapFace = meshop.getMapFace theMesh 1 f
	append VertsUsage[theFace.x] theMapFace.x
	append VertsUsage[theFace.y] theMapFace.y
	append VertsUsage[theFace.z] theMapFace.z
	append FaceUsage [theFace.x] f
	append FaceUsage [theFace.y] f
	append FaceUsage [theFace.z] f
)
--Now we can go though the mesh vertex array and see if we have 2 or more map vertices.
--If yes, we count from 2 to the number of map verts and create new mesh vertices with the
--same position as the current mesh vertex. Then we go through the list of collected faces
--using that vertex and see which of the 3 components matches the current vertex and its
--corresponding map vertex matches the current map vertex. We repoint that component of the face
--to the new mesh vertex. Thus, for each previously existing map vertex, we get a new mesh vertex
--at the end of the vertex list. 

for v = 1 to VertsUsage.count do
(
	theMapVertsArray = VertsUsage[v] as array
	if theMapVertsArray.count > 1 do
	(
		theFacesArray = FaceUsage[v] as array
		theVertPos = getVert theMesh v
		for mapv = 2 to theMapVertsArray.count do
		(
			theMapVert = theMapVertsArray[mapv]
			newIndex = theMesh.numverts+1
			setNumVerts theMesh newIndex true
			setVert theMesh newIndex theVertPos 
			for f in theFacesArray do
			(
				theFaceDef = getFace theMesh f
				theMapFaceDef = meshOp.getMapFace theMesh 1 f
				if theMapFaceDef.x == theMapVert and theFaceDef.x == v do 
				(
					theFaceDef.x = newIndex 
					setFace theMesh f theFaceDef
				)				
				if theMapFaceDef.y == theMapVert and theFaceDef.y == v do 
				(
					theFaceDef.y = newIndex 
					setFace theMesh f theFaceDef
				)				
				if theMapFaceDef.z == theMapVert and theFaceDef.z == v do 
				(
					theFaceDef.z = newIndex 
					setFace theMesh f theFaceDef
				)				
			)--end f loop
		)--end v loop
	)
)
update theMesh

)

SplitVertsByMapVerts $Sphere01