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/ecaec038-6ae3-4c46-bb11-07fdb6590813%40googlegroups.com.

Reply via email to