def copyVertex(driverMesh, drivenMesh, minDeltaLength, vertexIds, vertexWeights, multiplier=None, space=om.MSpace.kObject): """ copy vertex position from driver to driven :param driverMesh: 'driverMeshName' :param drivenMesh: 'drivenMeshName' :param minDeltaLength: float :param vertexIds: [0, 1, ...] :param vertexWeights: [1.0, 0.5, ...] :param multiplier: float or detect if None :param space: om.MSpace.k___ :return: """ multiplier = getEditBlendshapeMultiplier(drivenMesh, multiplier) deltas = [] for vertexId, weight, driverPosition, drivenPosition in izip( vertexIds, vertexWeights, getVertexPositions(driverMesh, vertexIds, space), getVertexPositions(drivenMesh, vertexIds, space)): deltas.append((driverPosition - drivenPosition) * weight * multiplier) mc.prMovePointsCmd(drivenMesh, space, minDeltaLength, vertexIds, *deltas)
def smoothDelta(driverMesh, drivenMesh, minDeltaLength, vertexIds, vertexWeights, multiplier=None, space=om.MSpace.kObject): """ average the difference vector (=delta) between the driverMesh and drivenMesh vertices with their neighbors deltas :param driverMesh: 'driverMeshName' :param drivenMesh: 'drivenMeshName' :param minDeltaLength: float :param vertexIds: [0, 1, ...] :param vertexWeights: [1.0, 0.5, ...] :param multiplier: float or detect if None :param space: om.MSpace.k___ :return: """ multiplier = getEditBlendshapeMultiplier(drivenMesh, multiplier) # get all relevant vertex ids (add neighbors) neighborIds = {} drivenIter = getMItMeshVertex(drivenMesh) allVertexIds = list(vertexIds) for vertexId in vertexIds: drivenIter.setIndex(vertexId) neighborIds[vertexId] = drivenIter.getConnectedVertices() for neighbor in neighborIds[vertexId]: if neighbor not in allVertexIds: allVertexIds.append(neighbor) # get all positions and deltas of interest driverPositions = om.MPointArray() driverIter = getMItMeshVertex(driverMesh) drivenPositions = om.MPointArray() drivenIter = getMItMeshVertex(drivenMesh) allDeltas = {} for vertexId in allVertexIds: driverIter.setIndex(vertexId) drivenIter.setIndex(vertexId) driverPosition = driverIter.position(space) drivenPosition = drivenIter.position(space) driverPositions.append(driverPosition) drivenPositions.append(drivenPosition) allDeltas[vertexId] = drivenPosition - driverPosition # calculate deformation deltas deltas = [] for x, [vertexId, weight] in enumerate(izip(vertexIds, vertexWeights)): averageDelta = om.MVector() for neighborId in neighborIds[vertexId]: averageDelta += allDeltas[neighborId] averageDelta /= len(neighborIds[vertexId]) deltas.append( ((driverPositions[x] + averageDelta) - drivenPositions[x]) * weight * multiplier) # do the deformation mc.prMovePointsCmd(drivenMesh, space, minDeltaLength, vertexIds, *deltas)
def averageVertex(drivenMesh, minDeltaLength, vertexIds, vertexWeights, multiplier=None, space=om.MSpace.kObject): """ average ("relax") a vertex, relative to its neighbors. this operation is not using the "target" / driver mesh. :param drivenMesh: 'drivenMeshName' :param minDeltaLength: float :param vertexIds: [0, 1, ...] :param vertexWeights: [1.0, 0.5, ...] :param multiplier: float or detect if None :param space: om.MSpace.k___ :return: """ multiplier = getEditBlendshapeMultiplier(drivenMesh, multiplier) drivenIter = getMItMeshVertex(drivenMesh) # get all relevant vertex ids and neighbor vertex ids allVertexIds = list(vertexIds) allNeighborIds = [] for vertexId in vertexIds: drivenIter.setIndex(vertexId) neighborIds = drivenIter.getConnectedVertices() allNeighborIds.append(neighborIds) for neighbor in neighborIds: if neighbor not in allVertexIds: allVertexIds.append(neighbor) # get all relevant positions (as vector for calculations) allPositions = om.MVectorArray() for vertexId in allVertexIds: drivenIter.setIndex(vertexId) allPositions.append(drivenIter.position(space)) # calculate deltas deltas = [] for vertexId, vertexWeight in izip(vertexIds, vertexWeights): drivenIter.setIndex(vertexId) averagePosition = om.MVector() neighborsIds = allNeighborIds[allVertexIds.index(vertexId)] for neighborId in neighborsIds: averagePosition += allPositions[allVertexIds.index(neighborId)] averagePosition /= len(neighborsIds) deltas.append( (averagePosition - allPositions[allVertexIds.index(vertexId)]) * vertexWeight * multiplier) # do the deformation mc.prMovePointsCmd(drivenMesh, space, minDeltaLength, vertexIds, *deltas)
def closestPoint(driverMesh, drivenMesh, minDeltaLength, vertexIds, vertexWeights, multiplier=None, space=om.MSpace.kObject, closestVertex=False): """ move the drivenMesh vertex to the closestPoint or closestVertex on the driverMesh :param driverMesh: 'driverMeshName' :param drivenMesh: 'drivenMeshName' :param minDeltaLength: float :param vertexIds: [0, 1, ...] :param vertexWeights: [1.0, 0.5, ...] :param multiplier: float or detect if None :param space: om.MSpace.k___ :param closestVertex: bool :return: """ multiplier = getEditBlendshapeMultiplier(drivenMesh, multiplier) drivenIter = getMItMeshVertex(drivenMesh) selection = om.MSelectionList() selection.add(driverMesh) meshFn = om.MFnMesh(selection.getDagPath(0)) deltas = [] for vertexId, vertexWeight in izip(vertexIds, vertexWeights): drivenIter.setIndex(vertexId) startPosition = drivenIter.position(space) targetPosition, polygonId = meshFn.getClosestPoint( startPosition, space) if closestVertex: shortestDistance = None for polyVtxId in meshFn.getPolygonVertices(polygonId): polyVtxPosition = meshFn.getPoint(polyVtxId, space) distance = (polyVtxPosition - startPosition).length() if shortestDistance is None or distance < shortestDistance: shortestDistance = distance targetPosition = polyVtxPosition deltas.append( (targetPosition - startPosition) * vertexWeight * multiplier) # do the deformation mc.prMovePointsCmd(drivenMesh, space, minDeltaLength, vertexIds, *deltas)
import maya.api.OpenMaya as om import maya.cmds as mc mc.file(newFile=True, force=True) mc.unloadPlugin('prMovePointsCmd') mc.loadPlugin(r'C:\Users\paz\Documents\git\prmaya\prmaya\plugins\prMovePointsCmd.py') #mc.loadPlugin(r'C:\Users\paz\documents\visual studio 2015\Projects\prMovePointsCmd\prMovePointsCmd\Release\prMovePointsCmd.mll') mesh = mc.polySphere(radius=10, ch=False, subdivisionsAxis=130, subdivisionsHeight=80)[0] target = mc.polySphere(radius=12, ch=False, subdivisionsAxis=130, subdivisionsHeight=80)[0] blendshape = mc.blendShape([target, mesh])[0] mc.delete(target) mc.setAttr(blendshape+'.'+target, 0.5) joint = mc.createNode('joint') mc.skinCluster(mesh, joint) mc.setAttr(joint+'.rx', 90) mc.sculptTarget(blendshape, e=True, target=0) vectorIds = range(0, mc.polyEvaluate(mesh, vertex=True), 2) vectors = [om.MVector(0, 0.5, 0) for x in vectorIds] times = [] for x in range(5): start = time.time() mc.prMovePointsCmd(mesh, om.MSpace.kLast, 0.00001, vectorIds, *vectors) end = time.time() times.append(end-start) print('time average: {}'.format(round(sum(times)/len(times), 2)))