Skip to content

Commit

Permalink
Skin IO: review logic to increase performance closes #456
Browse files Browse the repository at this point in the history
  • Loading branch information
miquelcampos committed Feb 15, 2025
1 parent 7c8230c commit 8a2a67b
Showing 1 changed file with 45 additions and 26 deletions.
71 changes: 45 additions & 26 deletions release/scripts/mgear/core/skin.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from mgear.vendor.Qt import QtCore
from mgear.vendor.Qt import QtGui
from mgear.core import pyqt
from mgear.core import utils
from maya.app.general.mayaMixin import MayaQWidgetDockableMixin

FILE_EXT = ".gSkin"
Expand Down Expand Up @@ -137,6 +138,7 @@ def get_mesh_components_from_tag_expression(skinCls, tag="*"):
return dagPath, components


# @utils.timeFunc
def getGeometryComponents(skinCls):
"""Get the geometry components from skincluster
Expand Down Expand Up @@ -330,6 +332,7 @@ def exportSkin(filePath=None, objs=None, *args):
return True


@utils.timeFunc
def exportSkinPack(packPath=None, objs=None, use_json=False, *args):
if use_json:
file_ext = FILE_JSON_EXT
Expand Down Expand Up @@ -393,45 +396,57 @@ def exportJsonSkinPack(packPath=None, objs=None, *args):
######################################


# @utils.timeFunc
def setInfluenceWeights(skinCls, dagPath, components, dataDic, compressed):
"""Sets influence weights for a given skin cluster.
Args:
skinCls (PyNode): The skin cluster node.
dagPath (MDagPath): The DAG path of the mesh.
components (MObject): The component selection (e.g., vertices).
dataDic (dict): A dictionary containing influence weights.
compressed (bool): Whether to use compressed weight format.
"""
unusedImports = []
weights = getCurrentWeights(skinCls, dagPath, components)

influencePaths = OpenMaya.MDagPathArray()
numInfluences = get_skin_cluster_fn(skinCls.name()).influenceObjects(
influencePaths
)
skinFn = get_skin_cluster_fn(skinCls.name()) # Cache function call
numInfluences = skinFn.influenceObjects(influencePaths)

numComponentsPerInfluence = int(weights.length() / numInfluences)

# Precompute influence names (Avoiding PyMEL)
influenceMap = {
OpenMaya.MFnDependencyNode(influencePaths[ii].node()).name(): ii
for ii in range(influencePaths.length())
}

for importedInfluence, wtValues in dataDic["weights"].items():
for ii in range(influencePaths.length()):
influenceName = influencePaths[ii].partialPathName()
nnspace = pm.PyNode(influenceName).stripNamespace()
influenceWithoutNamespace = nnspace
if influenceWithoutNamespace == importedInfluence:
if compressed:
for jj in range(numComponentsPerInfluence):
# json keys can't be integers. The vtx number key
# is unicode. example: vtx[35] would be: u"35": 0.6974,
# But the binary format is still an int, so check both.
# if the key doesn't exist, set it to 0.0
wt = wtValues.get(jj) or wtValues.get(str(jj)) or 0.0
weights.set(wt, jj * numInfluences + ii)
else:
for jj in range(numComponentsPerInfluence):
wt = wtValues[jj]
weights.set(wt, jj * numInfluences + ii)
break
influenceIndex = influenceMap.get(importedInfluence)
if influenceIndex is not None:
if compressed:
for jj in range(numComponentsPerInfluence):
wt = wtValues.get(jj, wtValues.get(str(jj), 0.0))

weights.set(wt, jj * numInfluences + influenceIndex)
else:
for jj, wt in enumerate(wtValues):
weights.set(wt, jj * numInfluences + influenceIndex)
else:
unusedImports.append(importedInfluence)

influenceIndices = OpenMaya.MIntArray(numInfluences)
# influenceIndices assignment
influenceIndices = OpenMaya.MIntArray()
influenceIndices.setLength(numInfluences)
for ii in range(numInfluences):
influenceIndices.set(ii, ii)
get_skin_cluster_fn(skinCls.name()).setWeights(
dagPath, components, influenceIndices, weights, False
)
influenceIndices[ii] = ii # Direct assignment is faster

# Apply the weights
skinFn.setWeights(dagPath, components, influenceIndices, weights, False)


# @utils.timeFunc
def setBlendWeights(skinCls, dagPath, components, dataDic, compressed):
if compressed:
# The compressed format skips 0.0 weights. If the key is empty,
Expand All @@ -453,6 +468,7 @@ def setBlendWeights(skinCls, dagPath, components, dataDic, compressed):
)


# @utils.timeFunc
def setData(skinCls, dataDic, compressed):
dagPath, components = getGeometryComponents(skinCls)
setInfluenceWeights(skinCls, dagPath, components, dataDic, compressed)
Expand Down Expand Up @@ -498,6 +514,7 @@ def getObjsFromSkinFile(filePath=None, *args):
print(x)


# @utils.timeFunc
def importSkin(filePath=None, *args):

if not filePath:
Expand Down Expand Up @@ -605,6 +622,7 @@ def importSkin(filePath=None, *args):
pm.displayWarning(warningMsg.format(objName))


@utils.timeFunc
def importSkinPack(filePath=None, *args):
if not filePath:
filePath = pm.fileDialog2(
Expand All @@ -627,6 +645,7 @@ def importSkinPack(filePath=None, *args):
######################################


@utils.timeFunc
def skinCopy(sourceMesh=None, targetMesh=None, *args, **kwargs):
if not sourceMesh or not targetMesh:
if len(pm.selected()) >= 2:
Expand Down

0 comments on commit 8a2a67b

Please sign in to comment.