Skip to content

Commit

Permalink
Maya fixes
Browse files Browse the repository at this point in the history
Fixed issue with maya extract skin data function.
When the boneIDs array was instantiated it was instantiated with a size of 0 and then resized later. The resize call did not take into account the requirement that boneID array needs to be default values of -1.
We now instantiate the array at the maximum influence count and then resize to the maximum USED influence count which in most cases will be much lower than the max influence count. This preserves the -1 defaults and reduces the array size to only what is required.
Also fixed the mel script call to add missing bones which was non-functional previously.
  • Loading branch information
munkybutt committed Dec 16, 2024
1 parent de2ee0a commit 43c0198
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 18 deletions.
38 changes: 23 additions & 15 deletions src/cpp/skin_plus_plus_pymaya/skin_plus_plus_pymaya.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@ static void removeBonesFromBindPose(
}


std::unordered_set<std::string> getBoneNamesSet(MDagPathArray skinnedBones)
std::unordered_set<std::wstring> getBoneNamesSet(MDagPathArray skinnedBones)
{
std::vector<std::string> skinnedBoneNames(skinnedBones.length());
std::vector<std::wstring> skinnedBoneNames(skinnedBones.length());
for (UINT i = 0; i < skinnedBones.length(); i++)
{
skinnedBoneNames[i] = skinnedBones[i].partialPathName().asChar();
skinnedBoneNames[i] = skinnedBones[i].partialPathName().asWChar();
}
std::unordered_set<std::string> skinnedBoneNamesSet(skinnedBoneNames.begin(), skinnedBoneNames.end());
std::unordered_set<std::wstring> skinnedBoneNamesSet(skinnedBoneNames.begin(), skinnedBoneNames.end());
return skinnedBoneNamesSet;
}

Expand Down Expand Up @@ -154,13 +154,20 @@ static UINT getFirstFreeIndex(MPlug* arrayPlug)
}


MObject SkinManagerMaya::addMissingBones(BoneNamesVector& missingBoneNames, const UINT& skinnedBoneCount)
const bool SkinManagerMaya::addMissingBones(BoneNamesVector& missingBoneNames, const UINT& skinnedBoneCount)
{
std::wstring command = L"skinCluster -e";
for (std::wstring& name : missingBoneNames)
{
std::wstring command = fmt::format(L"skinCluster -e -ai {} {}", name, fmt::ptr(this->fnSkinCluster.name().asChar()));
MGlobal::executeCommand(MString(command.c_str()));
command = fmt::format(L"{} -ai \"{}\"", command, name);
}
command = fmt::format(L"{} {}", command, this->fnSkinCluster.name().asWChar());
auto status = MGlobal::executeCommand(MString(command.c_str()));
if (status == MS::kSuccess)
{
return true;
}
return false;
}


Expand Down Expand Up @@ -270,21 +277,15 @@ PySkinData SkinManagerMaya::extractSkinData(const bool safeMode)
MDoubleArray weights;
UINT boneCount;
this->fnSkinCluster.getWeights(this->dagPath, this->component, weights, boneCount);
PySkinData pySkinData = PySkinData(vertexCount, this->maximumVertexWeightCount);
MDagPathArray skinnedBones;
MStatus status;
this->fnSkinCluster.influenceObjects(skinnedBones, &status);
if (status != MS::kSuccess)
{
throw std::runtime_error("Failed to find influence objects!");
}
pySkinData.boneNames = std::vector<std::wstring>(skinnedBones.length());
for (UINT boneIndex = 0; boneIndex < skinnedBones.length(); boneIndex++)
{
pySkinData.boneNames[boneIndex] = fmt::format(L"{}", fmt::ptr(skinnedBones[boneIndex].partialPathName().asChar()));
}
MPoint mPoint;
pySkinData.setMaximumVertexWeightCount(boneCount);
PySkinData pySkinData = PySkinData(vertexCount, boneCount);
for (UINT vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++)
{
UINT influenceIndex = 0;
Expand All @@ -301,11 +302,18 @@ PySkinData SkinManagerMaya::extractSkinData(const bool safeMode)
pySkinData.boneIDs(vertexIndex, influenceIndex) = boneIndex;
influenceIndex += 1;
}
this->maximumVertexWeightCount = influenceIndex > this->maximumVertexWeightCount ? influenceIndex : this->maximumVertexWeightCount;
fnMesh.getPoint(vertexIndex, mPoint, MSpace::kObject);
pySkinData.positions(vertexIndex, 0) = mPoint.x;
pySkinData.positions(vertexIndex, 1) = mPoint.y;
pySkinData.positions(vertexIndex, 2) = mPoint.z;
}
pySkinData.setMaximumVertexWeightCount(this->maximumVertexWeightCount);
pySkinData.boneNames = std::vector<std::wstring>(skinnedBones.length());
for (UINT boneIndex = 0; boneIndex < skinnedBones.length(); boneIndex++)
{
pySkinData.boneNames[boneIndex] = fmt::format(L"{}", MNamespace::stripNamespaceFromName(skinnedBones[boneIndex].partialPathName()).asWChar());
}
if (safeMode)
{
if (pySkinData.weights.hasNaN())
Expand Down Expand Up @@ -415,7 +423,7 @@ static void getBoneNames(std::vector<std::wstring>& currentBoneNames, const MDag
currentBoneNames.resize(skinnedBoneCount);
for (UINT boneIndex = 0; boneIndex < skinnedBoneCount; boneIndex++)
{
currentBoneNames[boneIndex] = fmt::format(L"{}", fmt::ptr(skinnedBones[boneIndex].partialPathName().asChar()));
currentBoneNames[boneIndex] = fmt::format(L"{}", skinnedBones[boneIndex].partialPathName().asWChar());
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/cpp/skin_plus_plus_pymaya/skin_plus_plus_pymaya.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <maya/MFnSkinCluster.h>
#include <maya/MItDependencyGraph.h>
#include <maya/MMatrixArray.h>
#include <maya/MNamespace.h>
#include <maya/MPlug.h>
#include <maya/MQuaternion.h>
#include <maya/MSelectionList.h>
Expand Down Expand Up @@ -235,7 +236,7 @@ class SkinManagerMaya

// Get the skin weights from the given node's skin modifier
//std::vector<std::vector<std::vector <float>>> getSkinWeights();
MObject addMissingBones(std::vector<std::wstring>& missingBoneNames, const UINT& skinnedBoneCount);
const bool addMissingBones(std::vector<std::wstring>& missingBoneNames, const UINT& skinnedBoneCount);

// Get the vertex weights, bone ids and positions from the given node
PySkinData extractSkinData(const bool safeMode = true);
Expand Down
5 changes: 3 additions & 2 deletions src/cpp/skin_plus_plus_pymxs/source/skin_plus_plus_pymxs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,9 @@ bool SkinManager::applySkinData(PySkinData& skinData)
"skin bone ids count does not match skin weights count: " + convertWCharToChar(this->node->GetName())
);
const int vertexCount = getVertexCount(node);
if (boneIDsRows != vertexCount && !skinData.vertexIDs.has_value()) throw std::length_error(
fmt::format("skin vertex count does not match provided data count: {}", convertWCharToChar(this->node->GetName()))

if (boneIDsRows != vertexCount && !skinData.vertexIDs.has_value()) throw py::value_error(
"skin vertex count does not match provided data count: " + convertWCharToChar(this->node->GetName())
);
auto skinBoneCount = this->iSkin->GetNumBones();
if (skinBoneCount == 0)
Expand Down
Binary file modified src/skin_plus_plus/dccs/max/2024/skin_plus_plus_pymxs.pyd
Binary file not shown.
Binary file modified src/skin_plus_plus/py/310/skin_plus_plus_py.pyd
Binary file not shown.

0 comments on commit 43c0198

Please sign in to comment.