Hey Michael,

Thank you for the help on this I have learned a ton of good knowledge on
how engines store and process vertices from a mesh.

It took me a while to dig through your code and understand the relationship
between vert counts, ids and uv ids and how you have assembled the data but
I think I got it :D

Thanks again!

Ben

On 15 November 2017 at 06:39, Michael Boon <[email protected]> wrote:

> Hey, in case you haven't figured this out yourself by now, here's how I'd
> do it. This is very similar to the approach from my first post, but it
> grabs UVs from the first two channels, allows for faces with no UVs, and
> also allows for easy extension to handle vertex colors or normals (as I
> expect your engine splits on normals as well as UVs).
>
> I've put a bunch of comments inline. With all the lists of vertex IDs it
> gets very hard to name variables so they make sense. I create a bunch of
> generators that compartmentalize the code more, but whether that would
> actually make it clearer is debatable.
>
> A couple of essential concepts:
>
>    - zip, (and izip, izip_longest)
>    zip takes two or more lists, and returns the first element of all of
>    them, then the second, then the third, etc. izip does the same but is more
>    memory efficient and hence faster. izip_longest is only different when the
>    lists have different lengths. zip and izip will stop when they reach the
>    end of the shortest list. izip_longest will keep returning values until it
>    reaches the end of the longest list, and you can supply a "fillvalue" that
>    it returns for the shorter lists.
>    - vertex splitting
>    I'm assuming your engine works like the others I've seen. This means
>    that each vertex has a position, one UV for each channel, and probably one
>    normal too. One way to go from Maya verts to engine verts, is to split the
>    Maya mesh along UV seams (and probably along hard edges). The way I do that
>    is by actually creating those engine-style vertices (a position and 1 or 2
>    UVs) for every corner of every face, and then counting how many unique
>    vertices I get. It's simpler to do that than to chase edges looking for UV
>    seams or UV shells.
>
> Anyhow, hopefully this code works for you, and makes sense!
>
> import maya.api.OpenMaya as om
> from itertools import izip, izip_longest
>
> # Get the currently selected mesh.
> mSelList = om.MGlobal.getActiveSelectionList()
> path = mSelList.getDagPath(0)
> fnMesh = om.MFnMesh(path)
>
> # So the engine splits vertices if their UVs are different.
> # Another way of looking at it, is that the engine stores each vertex like
> this:
> # (position, uv0, uv1)
> # So that's what we're going to do. We'll collect the position and the uvs
> of each
> # corner of each face, then put each of those corners into a set to find
> out how many
> # unique corners there are. That should tell us exactly how many vertices
> the engine
> # will count.
> # Note that we are actually storing IDs rather than real values, just
> because it's
> # easier.
> allFacesVertCounts = []
> allFacesVertIDs = []
> counter = []
>
> # The first "channel" of face-vertex properties we want is the regular
> vertex positions.
> polyVertices = fnMesh.getVertices()
> allFacesVertCounts.append(polyVertices[0])
> allFacesVertIDs.append(polyVertices[1])
> counter.append(0)
>
> # The next 2 channels are the UVs. This collects the first 2 UV channels
> but you could
> # change that to whatever you want.
> numUVChannelsUsed = 2
> uvSets = fnMesh.getUVSetNames()
> for uvSet in uvSets[:numUVChannelsUsed]:
>     f, ids = fnMesh.getAssignedUVs(uvSet)
>     allFacesVertCounts.append(f)
>     allFacesVertIDs.append(ids)
>     counter.append(0)
>
> # If you wanted to, you could also add normals, tangents, binormals and/or
> colors here.
>
> numVertProperties = len(counter)
> print 'Counting {} properties for {} vertex-faces...'.format(
>     numVertProperties, len(allFacesVertIDs[0]))
>
> uniqueVerts = set()
> assert [len(c) == len(allFacesVertCounts[0]) for c in allFacesVertCounts]
> for vertCounts in izip(*allFacesVertCounts):
>     # Inside this loop, we're looking at one face at a time.
>     # vertCounts contains the number of verts this face has in each
> channel.
>     # vertCounts[0] will be the number of actual verts.
>     # The other channels will either have the same number (if the face is
> mapped)
>     # or 0 (if the face is not mapped in this channel).
>     assert len(vertCounts) == numVertProperties, (len(vertCounts),
> numVertProperties)
>     faceVertIds = [None] * numVertProperties
>     for i in range(numVertProperties):
>         # Some faces don't have UVs in some channels, so they will have 0
> verts in
>         # that channel. We need to count through the UV id lists by the
> correct
>         # amount for each channel.
>         assert isinstance(vertCounts[i], int), type(vertCounts[i])
>         assert (vertCounts[i] == 0 or vertCounts[i] == vertCounts[0]),
> (vertCounts[i], vertCounts[0])
>         faceVertIds[i] = allFacesVertIDs[i][counter[i]:
> counter[i]+vertCounts[i]]
>         counter[i] += vertCounts[i]
>     # izip_longest lets us fill any empty faces with a default value (None
> in this case)
>     for vertParams in izip_longest(*faceVertIds, fillvalue=None):
>         # vertParams is a list of ids for this corner of the face.
>         # The first id is the vertex id. The second is the uv id in the
> first uv set.
>         # We store all these ids because if any of them are different, the
> game engine
>         # will create a new vert, so we want to count it as a new vert.
>         uniqueVerts.add(vertParams)
> for i in range(numVertProperties):
>     assert counter[i] == len(allFacesVertIDs[i]), (i, counter[i],
> len(allFacesVertIDs[i]))
> print 'Done.'
> print 'Number of Maya verts:', fnMesh.numVertices
> print 'Number of face-verts:', len(allFacesVertIDs[0])
> print 'Number of engine verts:', len(uniqueVerts)
>
>
>
> On Monday, 13 November 2017 20:20:00 UTC+11, Benjam901 wrote:
>>
>> Hello Michael,
>>
>> Thanks for the support on this it is much appreciated.
>>
>> I was not aware that I was using API 1.0, I have been reading the C++
>> docs for my reference so I assumed it was the correct API. I will make the
>> switch to 2.0.
>>
>> The selection of the UVs is just a visual test to check that I am getting
>> the correct number of borders so we can ignore that issue (I switch UV sets
>> to make sure in my tests)
>>
>> The reason I am only counting UVs on seams is those are the only ones
>> that split the vertex when we use them in the engine. We are trying to
>> "guess-timate" the total vert count before we jump into the engine so the
>> artist can be as efficient as possible with their source maya files and
>> using the UVs for the time being can get us as close as possible.
>>
>> Not all faces have UVs in uvSet that I can confirm for sure so the lists
>> are out of sync. What if I iterated the face vertices and checked each
>> vertex has UVs first and then cross referenced each list?
>>
>>
>> On 13 November 2017 at 00:46, Michael Boon <[email protected]> wrote:
>>
>>> Hi Ben,
>>>
>>> I can't see your image, but I can run your code on a mesh of my own. In
>>> really basic tests it seems to work correctly.
>>> It's a bit tricky to read through. There's a fair bit of temp code in
>>> there, and things that are assigned and not used. Also, why are you using
>>> Python API 1.0? It's more difficult to use than 2.0 (unless you're more
>>> familiar with C++, I guess).
>>>
>>> There are a few ways it could go wrong.
>>>
>>>    - The most likely problem, I think, is that the code I gave you
>>>    assumes that every face has UVs. I said "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," and that the two face lists (from
>>>    getVertices and getAssignedUVs) will be identical. That was incorrect. If
>>>    any faces have no UVs, they will get a 0 in the face list from
>>>    getAssignedUVs and your vertex ID and UV ID lists will no longer 
>>> correspond.
>>>    - There's also the problem that selecting '{0}.map[{1}]' will select
>>>    UVs in the currently active UV set, which may or may not be 'uvSet'. You
>>>    can set the currently active UV set in script, or in the UV Editor.
>>>    - The basic idea of doing "totalVertCount = sum(len(s) for s in
>>>    vertUVIDs if len(s)>1)" seems flawed to me. You're only counting
>>>    verts that are on seams. How are you going to use that number?
>>>
>>> If you can get your image attached properly (I think the problem is at
>>> your end...), and confirm that your mesh has UVs for all faces in 'uvSet',
>>> we can build up from there.
>>>
>>>
>>> On Saturday, 11 November 2017 01:10:22 UTC+11, Benjam901 wrote:
>>>>
>>>> Hey Michael,
>>>>
>>>> I copied some UVs into a new UV map and tried the same method and to
>>>> highlight what was happening I am selecting the UVs.
>>>>
>>>> For the 2nd UV set however the method looks like it fails, when I
>>>> select the UVs it selects almost all the verts in the map.
>>>>
>>>> I amended the code to give me the additional vert count i.e. verts only
>>>> on seams adn the output for the 2nd map is 166 which is not correct.
>>>>
>>>> Can you replicate this error also?
>>>>
>>>> Code and screenshot is below:
>>>>
>>>> import pymel.core as pm
>>>> import maya.OpenMaya as OM
>>>> from itertools import izip
>>>>
>>>> sel = pm.ls(sl=True)[0]
>>>> selName = str(sel.nodeName())
>>>>
>>>> mSelList = OM.MSelectionList()
>>>> OM.MGlobal.getActiveSelectionList(mSelList)
>>>> sel = OM.MItSelectionList(mSelList)
>>>> path = OM.MDagPath()
>>>> sel.getDagPath(path)
>>>> fnMesh = OM.MFnMesh(path)
>>>>
>>>> vertCount = OM.MIntArray()
>>>> vertList = OM.MIntArray()
>>>>
>>>> uvCounts = OM.MIntArray()
>>>> uvIDs = OM.MIntArray()
>>>> #uvSet='map1'
>>>>
>>>> set2 = 'uvSet'
>>>> tempSets = ['map1', 'uvSet']
>>>>
>>>> additional = 0
>>>>
>>>> #for uvSet in tempSets:
>>>> fnMesh.getVertices(vertCount, vertList)
>>>> #fnMesh.getAssignedUVs(uvCounts, uvIDs, uvSet)
>>>> fnMesh.getAssignedUVs(uvCounts, uvIDs, set2)
>>>>
>>>> vertUVIDs = [set() for _ in range(fnMesh.numVertices())]
>>>>
>>>> for vID, uvID in izip(vertList, uvIDs):
>>>>     vertUVIDs[vID].add(uvID)
>>>>
>>>> totalVertCount = sum(len(s) for s in vertUVIDs if len(s)>1)
>>>> additional += totalVertCount
>>>> print additional
>>>>
>>>> totes = [i for i in vertUVIDs if len(i) > 1]
>>>> for i in totes:
>>>>     for j in i:
>>>>         pm.select('{0}.map[{1}]'.format(selName, j), add=True)
>>>>
>>>>
>>>>
>>>> [image: Inline images 1]
>>>>
>>> --
>>> 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/to
>>> pic/python_inside_maya/5rvHKbU9ipM/unsubscribe.
>>> To unsubscribe from this group and all its topics, send an email to
>>> [email protected].
>>> To view this discussion on the web visit https://groups.google.com/d/ms
>>> gid/python_inside_maya/5c8e3e30-ad49-4d04-ae11-2a446fdf81dc%
>>> 40googlegroups.com
>>> <https://groups.google.com/d/msgid/python_inside_maya/5c8e3e30-ad49-4d04-ae11-2a446fdf81dc%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>
>>
>> --
>>
>> Tel - +46 76245 92 90 (Sweden)
>> LinkedIn: http://www.linkedin.com/pub/ben-hearn/50/a64/33b
>>
> --
> 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
> [email protected].
> To view this discussion on the web visit https://groups.google.com/d/
> msgid/python_inside_maya/23ac14f9-6484-4bbf-8e86-
> e2003d9666e1%40googlegroups.com
> <https://groups.google.com/d/msgid/python_inside_maya/23ac14f9-6484-4bbf-8e86-e2003d9666e1%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
> For more options, visit https://groups.google.com/d/optout.
>



-- 

Tel - +46 76245 92 90 (Sweden)
LinkedIn: http://www.linkedin.com/pub/ben-hearn/50/a64/33b

-- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/python_inside_maya/CAM2ybkVEH8LyKd9EDV%2BPwKDY19CgTDUjMoZs%2BSxeZEr4Cdy8sQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to