Skip to content

Commit

Permalink
Missing bones are now correctly added
Browse files Browse the repository at this point in the history
  • Loading branch information
munkybutt committed Oct 2, 2023
1 parent b0e86f9 commit 4c59e31
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 116 deletions.
Binary file not shown.
Binary file modified PYProjects/skin_plus_plus/py/39/skin_plus_plus_py.pyd
Binary file not shown.
38 changes: 12 additions & 26 deletions PYProjects/source/skin_plus_plus_py/headers/skin_plus_plus_py.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ typedef unsigned int UINT;


template <typename T>
UINT getItemIndex(std::vector<T> vector, T item) {
UINT getItemIndex(std::vector<T>& vector, T item) {
UINT index = std::distance(vector.begin(), find(vector.begin(), vector.end(), item));
if (index >= vector.size())
{
Expand Down Expand Up @@ -115,33 +115,13 @@ struct PySkinData final
this->boneIDs = boneIDs;
this->weights = weights;
this->positions = positions;
//for (eg::Index i = 0; i < this->boneIDs.rows(); i++)
//{
// auto message = fmt::format("Vertex: {} - ", i);
// for (UINT j = 0; j < this->boneIDs.cols(); j++)
// {
// if (j == 0)
// {
// message += "[";
// }
// auto value = this->boneIDs(i, j);
// message += fmt::format("{}", value);
// if (j < this->boneIDs.cols() - 1)
// {
// message += ", ";
// }
// }
// message += "]";
// py::print(message);
//}
}

PySkinData(py::tuple data)
{
this->setInternalState(data);
}


~PySkinData() {}

// Set the internal state of the object, replacing all data.
Expand All @@ -166,7 +146,7 @@ struct PySkinData final

// Get the bone ids in their correct order as well as any missing bones
// for the current skin modifier.
SortedBoneNameData getSortedBoneIDs(BoneNamesVector currentBoneNames)
SortedBoneNameData getSortedBoneIDs(BoneNamesVector& currentBoneNames)
{
const size_t cachedBoneCount = this->boneNames.size();
auto sortedBoneNameData = SortedBoneNameData(cachedBoneCount);
Expand All @@ -182,17 +162,23 @@ struct PySkinData final
const auto lookup = nameMap.find(nameToFind);
if (lookup != nameMap.end())
{
//py::print(lookup->first);
//py::print(lookup->second);
//py::print("-------------");
sortedBoneNameData.sortedBoneIDs[boneIndex] = lookup->second;
}
else
{
sortedBoneNameData.unfoundBoneNames.push_back(nameToFind);
py::print("Bone not found in current skin definition: ", nameToFind);
}
}
if (!sortedBoneNameData.unfoundBoneNames.empty())
{
std::string message = "The following bones are not in the skin definition:";
for (const std::string& name : sortedBoneNameData.unfoundBoneNames)
{
message += fmt::format("\n- {}", name);
}
py::print(message);

}
return sortedBoneNameData;
}
};
Expand Down
140 changes: 51 additions & 89 deletions PYProjects/source/skin_plus_plus_pymaya/skin_plus_plus_pymaya.cpp
Original file line number Diff line number Diff line change
@@ -1,33 +1,4 @@
#include <skin_plus_plus_pymaya.h>


//bool getMeshPositions(const MDagPath& dagPath, Array<Vector3>* pointArray)
//{
// nvDebugCheck(pointArray != NULL);
//
// MStatus status;
// MFnMesh fnMesh(dagPath, &status);
//
// MItMeshPolygon polyIt(dagPath, MObject::kNullObj, &status);
// if (MS::kSuccess != status) return false;
//
// // Add positions.
// MPointArray positionArray;
// status = fnMesh.getPoints(positionArray, MSpace::kObject);
// if (MS::kSuccess != status) return false;
//
// const uint positionCount = positionArray.length();
// pointArray->reserve(positionCount);
//
// for (uint i = 0; i < positionCount; i++)
// {
// MPoint point = positionArray[i];
// pointArray->append(Vector3(point.x, point.y, point.z));
// }
//
// return true;
//}

#include <maya/MGlobal.h>
#include <maya/MSelectionList.h>
#include <maya/MObject.h>
Expand Down Expand Up @@ -62,7 +33,7 @@ bool SkinManagerMaya::initialise(const wchar_t* name)
this->isValid = false;
return false;
}
py::print("success!");
py::print("Initialised successfully!");

this->isValid = true;
return true;
Expand Down Expand Up @@ -131,7 +102,7 @@ std::unordered_set<std::string> getBoneNamesSet(MDagPathArray skinnedBones)
//}


MObject SkinManagerMaya::addMissingBones(std::vector<std::string> missingBoneNames, const UINT skinnedBoneCount)
MObject SkinManagerMaya::addMissingBones(BoneNamesVector& missingBoneNames, const UINT& skinnedBoneCount)
{
MStatus status;
MSelectionList selectionList;
Expand Down Expand Up @@ -186,10 +157,14 @@ MObject SkinManagerMaya::addMissingBones(std::vector<std::string> missingBoneNam
dagModifier.connect(jointWorldMatrix, skinClusterMatrixNewElementIndex);
dagModifier.connect(jointLockInfluenceWeightsArray, skinClusterLockWeightsNewElementIndex);
dagModifier.connect(bindPoseMemberNewElementIndex, bindPoseParentNewElementIndex);

py::print("added missing bone: ", missingBoneNames[i]);
}
status = dagModifier.doIt();
std::string message = "Successfully added missing bones:";
for (const std::string& name : missingBoneNames)
{
message += fmt::format("\n- {}", name);
}
py::print(message);
if (status != MS::kSuccess)
{
throw std::exception("Failed to add missing bones!");
Expand Down Expand Up @@ -249,25 +224,6 @@ PySkinData SkinManagerMaya::getData()
}


void sortBoneIDs(BoneIDsMatrix& boneIDs, std::vector<UINT> newIDOrder, const eg::Index vertexCount, const eg::Index influenceCount)
{
BoneIDsMatrix sortedBoneIDs = BoneIDsMatrix(boneIDs);
for (eg::Index vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++)
{
for (eg::Index influenceIndex = 0; influenceIndex < influenceCount; influenceIndex++)
{
const int boneID = boneIDs(vertexIndex, influenceIndex);
if (boneID == -1)
{
continue;
}
const int newIndex = newIDOrder[boneID];
boneIDs(vertexIndex, influenceIndex) = newIndex;
}
}
}


/// <summary>
/// Convert an eigen::MatrixXd weights matrix to a MDoubleArray.
/// This array is flat, so the weights which are passed in as a vertex count x influence count matrix, need to be
Expand All @@ -283,7 +239,7 @@ void sortBoneIDs(BoneIDsMatrix& boneIDs, std::vector<UINT> newIDOrder, const eg:
/// <param name="vertexCount"></param>
/// <param name="influenceCount"></param>
/// <returns></returns>
MDoubleArray getWeightsAsMDoubleArray(BoneIDsMatrix boneIDs, WeightsMatrix weights, const eg::Index vertexCount, const eg::Index influenceCount, const eg::Index maxInfluenceCount)
MDoubleArray getWeightsAsMDoubleArray(BoneIDsMatrix& boneIDs, WeightsMatrix& weights, const eg::Index& vertexCount, const eg::Index& influenceCount, const eg::Index& maxInfluenceCount)
{
const UINT arraySize = vertexCount * maxInfluenceCount;
MDoubleArray mWeights(arraySize, 0.0);
Expand All @@ -302,30 +258,41 @@ MDoubleArray getWeightsAsMDoubleArray(BoneIDsMatrix boneIDs, WeightsMatrix weigh
mWeights[mWeightsIndex] = weight;
}
}
for (eg::Index i = 0; i < vertexCount; i++)
{
auto message = fmt::format("Vertex: {} - ", i);
for (UINT j = 0; j < influenceCount; j++)
{
if (j == 0)
{
message += "[";
}
auto mIndex = i * influenceCount + j;
message += fmt::format("{}: {}", mIndex, mWeights[mIndex]);
if (j < influenceCount - 1)
{
message += ", ";
}
}
message += "]";
py::print(message);
}
for (size_t i = 0; i < mWeights.length(); i++)
//for (eg::Index i = 0; i < vertexCount; i++)
//{
// auto message = fmt::format("Vertex: {} - ", i);
// for (UINT j = 0; j < influenceCount; j++)
// {
// if (j == 0)
// {
// message += "[";
// }
// auto mIndex = i * influenceCount + j;
// message += fmt::format("{}: {}", mIndex, mWeights[mIndex]);
// if (j < influenceCount - 1)
// {
// message += ", ";
// }
// }
// message += "]";
// py::print(message);
//}
//for (size_t i = 0; i < mWeights.length(); i++)
//{
// py::print(mWeights[i]);
//}
return mWeights;
}


void getBoneNames(std::vector<std::string>& currentBoneNames, const MDagPathArray& skinnedBones, const UINT& skinnedBoneCount)
{
currentBoneNames.clear();
currentBoneNames.resize(skinnedBoneCount);
for (UINT boneIndex = 0; boneIndex < skinnedBoneCount; boneIndex++)
{
py::print(mWeights[i]);
currentBoneNames[boneIndex] = fmt::format("{}", skinnedBones[boneIndex].partialPathName().asChar());
}
return mWeights;
}


Expand Down Expand Up @@ -357,7 +324,6 @@ bool SkinManagerMaya::setSkinWeights(PySkinData& skinData)
);
throw std::length_error(exceptionText);
}

MDagPathArray skinnedBones;
MStatus status;
this->fnSkinCluster.influenceObjects(skinnedBones, &status);
Expand All @@ -366,41 +332,37 @@ bool SkinManagerMaya::setSkinWeights(PySkinData& skinData)
throw std::exception("Error querying bones!");
}
auto skinnedBoneCount = skinnedBones.length();
py::print("skinnedBoneCount: ", skinnedBoneCount);
auto currentBoneNames = std::vector<std::string>(skinnedBoneCount);
for (UINT boneIndex = 0; boneIndex < skinnedBoneCount; boneIndex++)
{
currentBoneNames[boneIndex] = fmt::format("{}", skinnedBones[boneIndex].partialPathName().asChar());
}
getBoneNames(currentBoneNames, skinnedBones, skinnedBoneCount);
bool bonesAdded = false;
if (skinnedBoneCount == 0)
{
this->addMissingBones(skinData.boneNames, skinnedBoneCount);
bonesAdded = true;
}
auto sortedBoneIDs = skinData.getSortedBoneIDs(currentBoneNames);
if (sortedBoneIDs.unfoundBoneNames.size() != 0)
if (!sortedBoneIDs.unfoundBoneNames.empty())
{
skinnedBones.clear();
this->addMissingBones(sortedBoneIDs.unfoundBoneNames, skinnedBoneCount);
bonesAdded = true;
}
if (bonesAdded)
{
this->initialise(this->name.asWChar());
//getMeshAndSkinFns(this->fnMesh, this->fnSkinCluster, this->name);
skinnedBones.clear();
this->fnSkinCluster.influenceObjects(skinnedBones, &status);
skinnedBoneCount = skinnedBones.length();
getBoneNames(currentBoneNames, skinnedBones, skinnedBoneCount);
if (status != MS::kSuccess)
{
throw std::exception("Error querying bones!");
}
sortedBoneIDs = skinData.getSortedBoneIDs(currentBoneNames);
skinnedBoneCount = skinnedBones.length();
if (sortedBoneIDs.unfoundBoneNames.size() != 0)
{
throw std::exception("Could not find all bones required!");
}
}

py::print("updated skinnedBoneCount: ", skinnedBoneCount);
const auto sortedBoneSize = sortedBoneIDs.sortedBoneIDs.size();
py::print("sortedBoneSize: ", sortedBoneSize);
MIntArray mBoneIDs(sortedBoneSize);
for (size_t index = 0; index < sortedBoneSize; index++)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,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::string> missingBoneNames, const UINT skinnedBoneCount);
MObject addMissingBones(std::vector<std::string>& missingBoneNames, const UINT& skinnedBoneCount);

// Get the vertex weights, bone ids and positions from the given node
PySkinData getData();
Expand Down

0 comments on commit 4c59e31

Please sign in to comment.