For what its worth I found that using MFnSkinCluster to set weights was 
slower than setting the value on the plug its self. However I never tested 
this on meshes above 100k so your mileage might vary.

On Friday, October 18, 2019 at 10:46:57 AM UTC-4, Jesse K. wrote:
>
> Hi Michael,
>
> Thanks a lot for the extra suggestions. I had some time to take a look at 
> this and followed your advice.
> I ended up using the hitBary1 and hitBary2 to get the closest component by 
> using the face_itr.getTriangle for the returned relative triangle index of 
> the closestIntersection.
> That actually made things a lot faster already (about 2.5x)
>
> I moved cv_uv and cv_component out of the loop too.
> Disabling normalize made it slightly faster too, but the largest 
> performance gain by fair was actually moving the setWeights out of the loop.
> I kept it inside of the while loop because the setWeights won't take an 
> MObjectArray. But I gained a lot of performance by putting the weights and 
> indexes of the influence objects in arrays and applying those later.
>
> I used the cProfile module too and as you already suggested the setWeights 
> and setBlendWeights were the 3 and second slowest calls respectively with 
> closestIntersection being the slowest call out of everything.
>
> On Monday, September 23, 2019 at 6:35:47 AM UTC+2, Michael Boon wrote:
>>
>> I'm glad that helped. 
>>
>> You're still doing a lot of work for every vertex of every polygon 
>> (meaning most verts are hit many times), and also for every influence 
>> object for each of those verts.
>> I'm not completely clear on what you're doing there, but I think you can 
>> still make it significantly faster if you want to.
>>
>> I think you could use hitTriangle, hitBary1 and hitBary2 (returned from 
>> mesh.closestIntersection) to get 3 vertices and their relative distances to 
>> your hit location, rather than getting all the verts for each polygon. Then 
>> you could choose the closest vert and avoid a bunch of work.
>>
>> If you do want to average the skinning from multiple verts, you could 
>> look up all your verts' skinning influences and weights first, so you don't 
>> have to look each vert up once for every polygon it is part of. That might 
>> make it 2x faster or more if you're lucky.
>>
>> You can move indexForInfluenceObject out of the loops and save a lot of 
>> calls to that. I assume (but I'm not sure) that a dict lookup would be 
>> faster than that call. You can move cv_uv and cv_component out of that loop 
>> too since they will return the same thing every time.
>>
>> When you call surf_sc.setWeights you have normalize=True. It would be 
>> faster to leave that false and then normalize all weights after you're 
>> done. It's also possible this is the slowest call in your whole algorithm 
>> and it might be worth trying to build your own lists and do a single call 
>> to setWeights right at the end. You could use the cprofile module to 
>> measure your algorithm and find out which function calls are taking the 
>> most time.
>>
>> You can get away without composing strings for your faces or verts. That 
>> should be faster too. Here's an example for a face. There's an equivalent 
>> for vertices and for face-vertices too.
>> face_itr = om.MItMeshPolygon(mesh_dag_path) # Do this only once per mesh
>> face_itr.setIndex(facenr) # Do this in your "while not 
>> surf_itr.isRowDone()" loop
>>
>>
>>
>> On Friday, 13 September 2019 19:05:02 UTC+10, Jesse K. wrote:
>>>
>>> Hi Michael!
>>>
>>> Thanks so much for the tip. I had a look at the function you mentioned 
>>> and wrote this as improvement using that. From what I've tested it performs 
>>> on meshes up to 900k faces in roughly 0.7 seconds compared to roughly 8 
>>> seconds for the old version.
>>> I'm pretty sure this is still not the fastest way to do this, but it's 
>>> already way faster than it was before. So if you have any other improvement 
>>> points I'd like to hear it!
>>>
>>> def geo_weights_to_surface(source, target, tol=0.005, 
>>> space=om.MSpace.kWorld):
>>>
>>>     start = time.time()
>>>     # Mesh
>>>     mesh_sel = om.MSelectionList().add(source)
>>>     mesh_dag_path = mesh_sel.getDagPath(0)
>>>     mesh_dag_path.extendToShape()
>>>     mesh = om.MFnMesh(mesh_dag_path)
>>>     mesh_node = om.MFnDependencyNode(mesh_dag_path.node())
>>>     mesh_attr = mesh_node.attribute('inMesh')
>>>     mesh_plug = mesh_node.findPlug(mesh_attr, 0)
>>>     mesh_sc_array = mesh_plug.connectedTo(True, False)
>>>     mesh_sc_node = mesh_sc_array[0].node()
>>>
>>>     mesh_sc = oma.MFnSkinCluster(mesh_sc_node)
>>>     mesh_influences = mesh_sc.influenceObjects()
>>>     # Surface
>>>     surf_sel = om.MSelectionList().add(target)
>>>     surf_dag_path = surf_sel.getDagPath(0)
>>>     shape_nr = surf_dag_path.numberOfShapesDirectlyBelow()
>>>
>>>     # Append shapes to array
>>>     shapes = om.MDagPathArray()
>>>     for idx in range(shape_nr):
>>>         dag_path = surf_sel.getDagPath(0)
>>>         dag_path.extendToShape(idx)
>>>         shapes.append(dag_path)
>>>
>>>     for item in range(len(shapes)):
>>>         surf_dag_path = surf_sel.getDagPath(0)
>>>         surf_dag_path.extendToShape(item)
>>>         shape_node = om.MFnDependencyNode(surf_dag_path.node())
>>>         surf_attr = shape_node.attribute('create')
>>>         surf_plug = shape_node.findPlug(surf_attr, 0)
>>>         surf_sc_array = surf_plug.connectedTo(True, False)
>>>         surf_sc_node = surf_sc_array[0].node()
>>>         surf_sc = oma.MFnSkinCluster(surf_sc_node)
>>>         surf = om.MFnNurbsSurface(shapes[item])
>>>
>>>         surf_itr = om.MItSurfaceCV(shapes[item])
>>>
>>>         while not surf_itr.isDone():
>>>             while not surf_itr.isRowDone():
>>>                 pos = surf_itr.position()
>>>                 float_pos = om.MFloatPoint(pos.x, pos.y, pos.z)
>>>                 uvs = surf_itr.uvIndices()
>>>                 cv_normal = surf.normal(uvs[0], uvs[1], space=space)
>>>                 dir_vector = om.MFloatVector(cv_normal.x, cv_normal.y, 
>>> cv_normal.z)
>>>                 facenr = mesh.closestIntersection(float_pos, dir_vector, 
>>> space, 0.05, True)[2]
>>>                 face_sel = om.MSelectionList().add(source + '.f[' + 
>>> str(facenr) + ']')
>>>                 face_component = face_sel.getComponent(0)[1]
>>>
>>>                 face_itr = om.MItMeshFaceVertex(mesh_dag_path, 
>>> face_component)
>>>                 while not face_itr.isDone():
>>>                     if face_itr.position().isEquivalent(pos, tol):
>>>                         vtx_idx = face_itr.vertexId()
>>>                         idx_sel = om.MSelectionList().add(source + '.f[' + 
>>> str(vtx_idx) + ']')
>>>                         vtx = idx_sel.getComponent(0)[1]
>>>                         for mesh_inf in range(len(mesh_influences)):
>>>                             mesh_inf_idx = mesh_sc.indexForInfluenceObject(
>>>                                 mesh_influences[mesh_inf])
>>>                             vtx_weight = mesh_sc.getWeights(mesh_dag_path, 
>>> vtx, mesh_inf_idx)
>>>                             vtx_blend_weight = 
>>> mesh_sc.getBlendWeights(mesh_dag_path, vtx)
>>>                             cv_uv = surf_itr.uvIndices()
>>>                             cv_component = 
>>> om.MFnNurbsSurface(surf_dag_path).cv(cv_uv[0], cv_uv[1])
>>>                             surf_inf_idx = surf_sc.indexForInfluenceObject(
>>>                                 mesh_influences[mesh_inf])
>>>                             surf_sc.setWeights(surf_dag_path, cv_component, 
>>> surf_inf_idx,
>>>                                                vtx_weight[0], 
>>> normalize=True)
>>>                             surf_sc.setBlendWeights(surf_dag_path, 
>>> cv_component, vtx_blend_weight)
>>>                     face_itr.next()
>>>                 surf_itr.next()
>>>             surf_itr.nextRow()
>>>
>>>     print 'Copying weights took', time.time() - start, 'seconds.'
>>>
>>>
>>>

-- 
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/de3c6b65-ca97-4992-82a7-16970836c58e%40googlegroups.com.

Reply via email to