Hey Ben,

I have to admit I can't follow the UV shell technique you described. I
would expect a 500 vert object with a seam up the middle to have 500 +
(number of verts in the seam) verts in the game. The technique I described
does that, by counting verts twice if they are on UV seams (or more than
twice if they are on more than one seam).

I'll try to describe that technique a little better.

Actually it might help to describe how a mesh is put together first. There
is a list of vertex positions (which are points in space), and a list of
faces (each face is just a list of IDs into the vertex list). However for
efficiency, all the faces are run together into a single list, and there's
a second list that tells how many verts are in each face so you can count
through them to get to whichever face you want. Get your head around that,
then consider UVs are exactly the same. First there's a list of UVs (points
in 2D space), then there's a list of faces where each face is a list of IDs
into the UV list, and the list of faces is all run together just like it is
for vertices.

getVertices and getAssignedUVs each return two lists. The first list for
each is the number of verts in each face (which we don't care about in this
case). For getVertices, the second list is a list of vertex IDs. For
getAssignedUVs, the second list is a list of UV IDs. Those two lists are in
the same order, so we can zip them together to see which vertex corresponds
to which UV. Remember these lists are for every vertex on every face, so
each vertex ID will come up multiple times. If a vertex is not on a seam,
every time that vertex ID comes up, the corresponding UV ID will be the
same. If a vertex is on a seam, there will be two different UV IDs
corresponding to that vertex ID. My technique just counts how many
different UV IDs each vertex has, then adds then all together.

Now, if that's not what you need, to get UV shell information, you could
use MFnMesh.getUvShellsIds. To get border edges, you will have to use an
iterator. I might be able to take a look at that tomorrow, though no
guarantees :)


On 10 Nov. 2017 8:21 pm, "Benjam901" <benandrewhe...@gmail.com> wrote:

Hey Michael,

Thank you for the tips on the API and techniques to use for speed.

I was testing out your code and it works great. I am a bit confused though
(I have not managed to wrap my head around how each return list corresponds
to each other yet).

I need border edges for the UV shells. This way I can iterate each uv set,
get the border uvs, check that this particular UVs vertex has not already
been counted and add this to the total vert count rather than each UV.

- Ben


On Friday, 10 November 2017 02:57:06 UTC+1, Michael Boon wrote:
>
> For speed, you definitely want to use OpenMaya, but more importantly,
> avoid creating new Python objects every time you loop over a vert. Try to
> create some lists of regular Python ints upfront, then just count them.
>
> Once you have a MFnMesh, you can get a list of the UV IDs used at each
> corner of each face using MFnMesh.getVertices() and MFnMesh.
> getAssignedUVs().
> polyVertices = fnMesh.getVertices()
> polyUVIDs = fnMesh.getAssignedUVs() # with optional UV set name
> Both those functions return two lists. The first list in each is the list
> of vertex counts in each polygon, which we don't care about. The second
> lists are the vert IDs, and the corresponding UV IDs. It's significant that
> these are corresponding lists, since we're going to zip them together.
>
> Create a list with an entry for each vert in the mesh, then you can put
> the UV IDs each vert uses into its entry in the list. You know the number
> of verts, so you can create the main list in one hit, for speed. By using
> sets, you only record the unique IDs used at each vert.
>
> vertUVIDs = [set() for _ in range(fnMesh.numVertices)]
>
>
> Then go through the getAssignedUVs result in a loop and record which UV
> IDs are used at each vert:
> (Note: itertools.izip will be much faster than regular zip here because it
> doesn't create a new list)
> for vID, uvID in izip(polyVertices[1], polyUVIDs[1]):
>     vertUVIDs[vID].add(uvID)
>
> Once you have the UV IDs at each vert, you just sum the lengths of the
> sets:
> totalVertCount = sum(len(s) for s in vertUVIDs)
>
> Note that verts with no UVs will not be counted at all this way. You might
> want to add a check that every set has at least one element in it.
>
> I can count ~20k verts in ~30ms that way, which is certainly good enough
> for games work :)
>
>
> On Friday, 10 November 2017 03:03:12 UTC+11, Benjam901 wrote:
>>
>> Hello all,
>>
>> So here is my struggle at the moment.
>>
>> I am trying to guesstimate the "actual" in-engine vert count for a given
>> object in Maya so we can validate the LOD steps per object before we export.
>>
>> *Proposed solution:*
>> The way I am trying to do this is by checking that a vertex is on a UV
>> border edge and adding this to the total vert count.
>>
>> So for example an object with 500 verts which has a UV border straight
>> through the middle will end up with 1000 verts in-engine because of the UV
>> split.
>>
>> The problem I am having is wrapping my head around the underlying data
>> models for verts, faces, edges and uvs.
>>
>> *Solution 1:*
>> I have a sort of working solution that does not use the API but instead
>> relies on the mel command: *polySelectBorderShell 1*
>>
>> import pymel.core as pm
>> import maya.mel as mel
>>
>> sel = pm.ls(sl=True)[0] # Get object selection
>>
>> # Edges must be selected here
>> mel.eval("polySelectBorderShell 1")
>> uvs = pm.polyListComponentConversion(fe=True, tuv=True)
>> uvList = pm.ls(uvs, flatten=True)
>> uvDict = {}
>> for i in uvList:
>>    print i
>>    uvNum = int(i.split('[')[-1].split(']')[0])
>>    uvDict.update({uvNum:i})
>>
>> vertBorders = {} # e.g. {'map1':[1, 2, 3, 5, 71]}
>> uvSets = pm.polyUVSet(sel, query=True, allUVSets=True)
>> for uvSet in uvSets:
>>    vertBorders.update({uvSet:[]})
>>    uvs = pm.polyEvaluate(sel, uvs=uvSet, uv=True)
>>    for uvNum in range(uvs):
>>        if uvNum in uvDict:
>>            vert = pm.polyListComponentConversion(uvDict[uvNum],
>> fuv=True, tv=True)[0]
>>            vertBorders[uvSet].append(vert)
>>
>> count = 0
>> multiList = vertBorders.values()
>> result = set(multiList[0]).intersection(*multiList[:1])
>> count += len(result)
>> newMultiList = []
>> for L in multiList:
>>    newList = [i for i in L if i not in result]
>>    count += len(newList)
>> print count
>>
>>
>> The above solution kinda gets me there and I need to make sure its legit
>> and patch it up but for the most part it works.
>> Problem is that it is *SLOW *hence trying to use the API.
>>
>> *Solution 2:*
>> For the API I am following along with this mode of thinking here: 
>> *http://forums.cgsociety.org/archive/index.php?t-729364.html
>> <http://forums.cgsociety.org/archive/index.php?t-729364.html>*
>>
>> Mu current solution and where I am stuck is here. I know I need to run
>> some comparisons but how and on what I am deadlocked at.
>>
>> def getVertFromId(dagPath, vertID):
>>     vertIt = OM.MItMeshVertex(dagPath)
>>     vtxIdUtil = OM.MScriptUtil()
>>     vtxIdUtil.createFromInt(0)
>>     vtxIdPtr = vtxIdUtil.asIntPtr()
>>     vertIt.setIndex(vertID, vtxIdPtr)
>>     return vertIt
>>
>> def getFaceFromId(dagPath, faceId):
>>     faceIt = OM.MItMeshPolygon(dagPath)
>>     faceIdUtil = OM.MScriptUtil()
>>     faceIdUtil.createFromInt(0)
>>     faceIdPtr = faceIdUtil.asIntPtr()
>>     faceIt.setIndex(faceId, faceIdPtr)
>>     return faceIt
>>
>> def getVertUVInfo(vertIn):
>>     uArr = OM.MFloatArray()
>>     vArr = OM.MFloatArray()
>>     fIDs = OM.MIntArray()
>>     uvIndices = OM.MIntArray()
>>     uvSet = 'map1'
>>     vertIn.getUVs(uArr, vArr, fIDs, uvSet)
>>     vertIn.getUVIndices(uvIndices, uvSet)
>>
>>     print uArr, vArr, fIDs, uvIndices
>>     return fIDs, uvIndices
>>
>> def stripUnecessaryFaces(currentEdgeFaces, faceIDs1, faceIDs2):
>>     fID1 = []
>>     fID2 = []
>>     for fID in faceIDs1:
>>         if fID in currentEdgeFaces:
>>             fID1.append(fID)
>>
>>     for fID in faceIDs2:
>>         if fID in currentEdgeFaces:
>>             fID2.append(fID)
>>
>>     return fID1, fID2
>>
>> def main():
>>     mSelList = OM.MSelectionList()
>>     OM.MGlobal.getActiveSelectionList(mSelList)
>>     sel = OM.MItSelectionList(mSelList)
>>
>>     dagPath = OM.MDagPath()
>>     sel.getDagPath(dagPath)
>>     dagPath.extendToShape()
>>     connFaces = OM.MIntArray()
>>
>>     edgeIter = OM.MItMeshEdge(dagPath)
>>     while not edgeIter.isDone():
>>         f1 = None
>>         f2 = None
>>         edgeIter.getConnectedFaces(connFaces)
>>         if len(connFaces) == 1:
>>             # open edge
>>             print 'Open edge'
>>
>>         f1 = connFaces[0] # face 1
>>         try:
>>             f2 = connFaces[1] # face 2
>>         except:
>>             pass
>>
>>         vert1Index = edgeIter.index(0)
>>         vert2Index = edgeIter.index(1)
>>
>>         MfVert1 = getVertFromId(dagPath, vert1Index)
>>         MfVert2 = getVertFromId(dagPath, vert2Index)
>>
>>         fIdsvert1, uvIndicesVert1 = getVertUVInfo(MfVert1)
>>         fIdsvert2, uvIndicesVert2 = getVertUVInfo(MfVert2)
>>
>>         edgeIter.next()
>>
>>
>> Any suggestions on where to go from here or how to solve this is very
>> much appreciated!
>>
>> // Ben
>>
>> --
You received this message because you are subscribed to a topic in the
Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/
topic/python_inside_maya/5rvHKbU9ipM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
python_inside_maya+unsubscr...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/
msgid/python_inside_maya/2d436e81-b03e-405e-b87b-
63f49173a9e7%40googlegroups.com
<https://groups.google.com/d/msgid/python_inside_maya/2d436e81-b03e-405e-b87b-63f49173a9e7%40googlegroups.com?utm_medium=email&utm_source=footer>
.

For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to python_inside_maya+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/python_inside_maya/CAA27_yJ3-FnWM_AwkjcNV37d2a524NbCnHQb3yxKq7D%2B4CpQwA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to