Notifications
Clear all

[Closed] how to get the mapVertex coresponding to a vertex?

Since Max has a very strange arhitecture, meaning mapVertex at position i not always coresponds to the vertex at position i. Is there a way to get the mapVertex coresponding to a vertex at position i? Or is there a way to make shure that mapVertex at position i always coresponds to vertex at position i?

21 Replies

That’s not strange architecture at all…it makes perfect sense when you consider the fact that a face on your mesh topology will not necessarily have all the same adjacent faces in your map topology…and if the adjacency structures are different, the corresponding verts will necessarily be different. In other words, if 2 adjacent faces in your mesh are not adjacent in your map, they can’t share the same verts…so the vertex count in your map will be different than in your mesh and thus there can’t be a 1:1 correspondence between verts in either.

One way to find the “similar” vert in your map, to one in your mesh, is to figure out the internal index of your vertex on a face that shares it…then lookup that face in your map and get whichever of its vertices that has the same internal index. Mesh faces and map faces will always have a 1:1 correspondence (unlike verts), so you can do those types of cross-lookups without an issue.

So imagine I want to find the UV value of vertex 123 on my mesh. First, I find the face that has that vertex in its vertex list…so imagine a face whose vertex list is [122,123,124]…then I calculate the internal index of that vertex in that face. In this case, vertex 123 has an internal index of 2 on that face, since it’s the 2nd vert in its vertex list. Finally, I grab the same face index from my map, and get the UV value of its 2nd vertex.

The caveat to that (or any similar) approach, would be the fact that a vertex on the mesh can potentially correspond to multiple UV values on the mesh, since its adjacent faces on the mesh may not be the same as those in the map.

as above in it’s simplest form every thing goes by the face index


for f = 1 to msh.numfaces do
(
    geoverts = getface msh f;
    mapverts = getTVFace msh f;
    
    for v = 1 to 3 do
    (
        geovert = getvert msh geoverts[v];
        mapvert = getTVert msh     mapverts[v];
--.....        
    )
)

it’s also worth noting that a geo vert can have many associated map verts and visa versa (though less common it is possible)

1 Reply
(@gtafan)
Joined: 2 years ago

Posts: 0

Thanks, I gues to make it worck for all map chanels, not only chanel 1, I have to use the coresponding meshop functions.
I have read in max documentation that the relation between vertex and mapVertex is not always 1:1, but I have seen no gameengines that use meshes with other vertex to mapVertex relation then 1:1. In my case the relation is always 1:1, but sometimes max f*cks up the index, so for example vertex 1 is related to Mapvertex 20 and I would better like to have all vertex and mapVertex the same way, if that´s not already the case. Is there a way to do something like that? What I mean is, that mapVertex coresponding to vertex 1 should also have index 1 and so on.

it’s not pretty or particularly fast…


fn GeoVertToMapVert obj v mapCh =
    (
        faces = (polyop.getFacesUsingVert obj v) as array 
        faceIndices = for i in faces collect finditem (polyop.getFaceVerts obj i) v;
        makeUniqueArray (for i = 1 to faces.count collect (polyop.getMapFace obj mapCh faces[i])[faceIndices[i]]);
    )

I have read in max documentation that the relation between vertex and mapVertex is not always 1:1, but I have seen no gameengines that use
meshes with other vertex to mapVertex relation then 1:1.

game engines use “vertex” based geometry every thing stored on a per vertex basis so “1:1” relationship between position, vertex color, uv , normals etc but if you need a break in the mapping or vertex color or normals you need a “new” vertex with the same position value but with the new uv value etc.

you could model in the above manner in max, so every time you need a mapping seam you could detach the geometry so it becomes a new mesh element or if you need a new smoothing group detach to a new element and if you’re really lucky you’ll keep the 1:1 relationship between geo verts, map verts channel 1, map verts channel 2, normal verts, vertex color verts but be warned never under any circumstances use weld selected

another solution could be to export to a game engine then import the result back into max… then there will be a 1:1 relationship between verts and uvs etc but again no welding!

another solution could be to do script that mimics the exporter (I think I’ve posted one with tangent space handling on here using mxs bsearch) and create a new game styie mesh then everything
is 1:1

Thanks, the only problem with the code is that makeUniqueArray, if I remember right it´s only avaibler with newer max versions, so I can´t use it.

1 Reply
(@gtafan)
Joined: 2 years ago

Posts: 0

Yes, I understood that, but it not so much only about 1:1, more important is index matching between vertex and coresponding mapVertex.
Also like I said makeUniqueArray not worcking for me, as it´s available in 3ds Max 2008 and higher.
Also, since I have meshes and not polies, shouldn´t I use meshop insted of polyop?

yes that what I mean by 1:1 if you follow the link the code half way down will create a mesh where vert index will be the same as the mapvert index, you’ll just have a mesh with more verts than are really needed.

1 Reply
(@gtafan)
Joined: 2 years ago

Posts: 0

OK thanks, but what about my problem with makeUniqueArray and my question about polyop?

try this…


fn GeoVertToMapVert2 obj v mapCh =
    (
        local verts = #{}
        local faces = (meshop.getFacesUsingVert obj v) as array;
        
        for i = 1 to faces.count do
        (
            local geoface = meshop.getfaceverts obj i;
            local mapface = meshop.getmapface obj mapCh i;
            
            local vertnotfound = true;
            for j = 1 to 3 while vertnotfound do
            (
                if geoface[j] == v then
                (
                    vertnotfound = false;
                    verts[mapface[j]] = true;
                )        
            )
        )
        verts as array;
    )

1 Reply
(@gtafan)
Joined: 2 years ago

Posts: 0

Thanks, will try it. Just for better Understanding, obj is the mesh, mapCh is the chanel (-2 to max 99), but what´s v? Also verts is a 2 dimensional array containing mapVerts for every vertex, right? I am really new to maxscript and my english is really bad, so sorry if some questions could sound strange.

v is the vert index you want to find the mapping verts for which are returned by the function in 1D array

i was a bit hurried in my coding this should work for you


fn GeoVertToMapVert2 obj v mapCh =
(
    local mapverts = #{}
    local faces = meshop.getFacesUsingVert obj v;

    for f  in faces do
    (
        local geoface = getface obj f;
        local mapface = meshop.getmapface obj mapCh f;

        local foundvert = false;
        for j = 1 to 3 while not foundvert do
        (
            if geoface[j] == v then
            (
                foundvert = true;
                mapverts[mapface[j]] = true;
            )
        )
    )
    mapverts as array;
)

So it returns just the mapVert for a single vert and map chanel? But why array? There is always exactly 1 mapVertex coresponding to vertex and map chanel.
Have writen some code myself, but not 100% shure if it worcks.

fn fixMapVertTable msh mapUsed=(
table=#()
for i = 1 to mapUsed.count do append table #()
for i = 1 to msh.numverts do (
face=getFace msh i
for j = 1 to mapUsed.count do(
if mapUsed[j] then (
mapFace=meshop.getMapFace msh (j-3) i
if mapFace!=face then (
for k = 1 to 3 do table[j][face[k]]=mapFace[k]
)
)
)
)
return table
)

msh is my mesh and mapUsed is a bool array which tells if the map chanel is used. Map chanels are starting with -2.

Page 1 / 2