parent
2c8975b1cd
commit
1543c1a6c7
|
@ -154,6 +154,8 @@ void AnimalPoser::resolveChainRotation(const std::vector<QString> &limbBoneNames
|
|||
float targetMiddleBoneLength = (middleBone.headPosition - middleBone.tailPosition).length();
|
||||
float targetLimbLength = targetBeginBoneLength + targetMiddleBoneLength;
|
||||
|
||||
//qDebug() << beginBoneName << "targetLimbLength:" << targetLimbLength << "matchLimbLength:" << matchLimbLength;
|
||||
|
||||
float targetDistanceBetweenBeginAndEndBones = matchDistanceBetweenBeginAndEndBones * (targetLimbLength / matchLimbLength);
|
||||
QVector3D targetEndBoneStartPosition = beginBone.headPosition + matchDirectionBetweenBeginAndEndPones * targetDistanceBetweenBeginAndEndBones;
|
||||
|
||||
|
@ -177,12 +179,15 @@ void AnimalPoser::resolveChainRotation(const std::vector<QString> &limbBoneNames
|
|||
|
||||
auto oldBeginBoneDirection = (beginBone.tailPosition - beginBone.headPosition).normalized();
|
||||
auto newBeginBoneDirection = (targetMiddleBoneStartPosition - beginBone.headPosition).normalized();
|
||||
//qDebug() << beginBoneName << "oldBeginBoneDirection:" << oldBeginBoneDirection << "newBeginBoneDirection:" << newBeginBoneDirection;
|
||||
auto beginBoneRotation = QQuaternion::rotationTo(oldBeginBoneDirection, newBeginBoneDirection);
|
||||
m_jointNodeTree.updateRotation(beginBoneIndex, beginBoneRotation);
|
||||
|
||||
auto oldMiddleBoneDirection = (middleBone.tailPosition - middleBone.headPosition).normalized();
|
||||
auto newMiddleBoneDirection = (targetEndBoneStartPosition - targetMiddleBoneStartPosition).normalized();
|
||||
//qDebug() << beginBoneName << "oldMiddleBoneDirection:" << oldMiddleBoneDirection << "newMiddleBoneDirection:" << newMiddleBoneDirection;
|
||||
oldMiddleBoneDirection = beginBoneRotation.rotatedVector(oldMiddleBoneDirection);
|
||||
//qDebug() << beginBoneName << "oldMiddleBoneDirection:" << oldMiddleBoneDirection << "after rotation";
|
||||
auto middleBoneRotation = QQuaternion::rotationTo(oldMiddleBoneDirection, newMiddleBoneDirection);
|
||||
m_jointNodeTree.updateRotation(middleBoneIndex, middleBoneRotation);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ bool AnimalRigger::validate()
|
|||
{
|
||||
if (m_marksMap.empty()) {
|
||||
m_messages.push_back(std::make_pair(QtCriticalMsg,
|
||||
tr("Please tell me where is the neck, limbs and joints by mark the nodes from context menu")));
|
||||
tr("Please mark the neck, limbs and joints from the context menu")));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -207,6 +207,7 @@ bool AnimalRigger::rig()
|
|||
resolveBoundingBox(bodyVerticies, xMin, xMax, yMin, yMax, zMin, zMax);
|
||||
isMainBodyVerticalAligned = fabs(yMax.y() - yMin.y()) > fabs(zMax.z() - zMin.z());
|
||||
}
|
||||
qDebug() << "isMainBodyVerticalAligned:" << isMainBodyVerticalAligned;
|
||||
|
||||
// Collect all branchs
|
||||
auto neckIndicies = m_marksMap.find(std::make_pair(BoneMark::Neck, SkeletonSide::None));
|
||||
|
@ -299,7 +300,7 @@ bool AnimalRigger::rig()
|
|||
}
|
||||
}
|
||||
if (countOfChains <= 0) {
|
||||
qDebug() << "Should not come here, there must be at least one limb";
|
||||
qDebug() << "Should not come here, there must be at least one chain";
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -311,7 +312,7 @@ bool AnimalRigger::rig()
|
|||
}
|
||||
|
||||
if (rawSpineNodes.empty()) {
|
||||
qDebug() << "Couldn't find limbs to create a spine";
|
||||
qDebug() << "Couldn't find chain to create a spine";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -355,7 +356,7 @@ bool AnimalRigger::rig()
|
|||
|
||||
auto remainingSpineVerticies = bodyVerticies;
|
||||
const std::vector<QColor> twoColorsForSpine = {BoneMarkToColor(BoneMark::Neck), BoneMarkToColor(BoneMark::Tail)};
|
||||
const std::vector<QColor> twoColorsForLimb = {BoneMarkToColor(BoneMark::Joint), BoneMarkToColor(BoneMark::Limb)};
|
||||
const std::vector<QColor> twoColorsForChain = {BoneMarkToColor(BoneMark::Joint), BoneMarkToColor(BoneMark::Limb)};
|
||||
int spineGenerateOrder = 1;
|
||||
std::map<std::pair<QString, SkeletonSide>, int> chainOrderMapBySide;
|
||||
for (int spineNodeIndex = 0; spineNodeIndex < (int)spineNodes.size(); ++spineNodeIndex) {
|
||||
|
@ -402,11 +403,7 @@ bool AnimalRigger::rig()
|
|||
tailPosition = spineNodes[spineNodeIndex + 1].position;
|
||||
} else {
|
||||
spineBoneVertices = remainingSpineVerticies;
|
||||
if (isMainBodyVerticalAligned) {
|
||||
tailPosition = findMaxY(spineBoneVertices);
|
||||
} else {
|
||||
tailPosition = findMaxZ(spineBoneVertices);
|
||||
}
|
||||
tailPosition = findExtremPointFrom(spineBoneVertices, spineNode.position);
|
||||
}
|
||||
|
||||
QVector3D spineBoneHeadPosition = averagePosition(spineBoneVertices);
|
||||
|
@ -428,7 +425,7 @@ bool AnimalRigger::rig()
|
|||
addVerticesToWeights(spineBoneVertices, spineBone.index);
|
||||
boneIndexMap[spineBone.name] = spineBone.index;
|
||||
|
||||
//qDebug() << spineBone.name << "head:" << spineBone.headPosition << "tail:" << spineBone.tailPosition;
|
||||
qDebug() << "Added spine:" << spineBone.name << "head:" << spineBone.headPosition << "tail:" << spineBone.tailPosition;
|
||||
|
||||
if (1 == spineGenerateOrder) {
|
||||
m_resultBones[boneIndexMap[Rigger::rootBoneName]].tailPosition = spineBone.headPosition;
|
||||
|
@ -450,6 +447,7 @@ bool AnimalRigger::rig()
|
|||
ribBone.index = m_resultBones.size() - 1;
|
||||
ribBone.name = namingConnector(spineName, chainName);
|
||||
ribBone.headPosition = spineBoneHeadPosition;
|
||||
qDebug() << "Added connector:" << ribBone.name;
|
||||
boneIndexMap[ribBone.name] = ribBone.index;
|
||||
if (1 == spineGenerateOrder) {
|
||||
m_resultBones[boneIndexMap[Rigger::rootBoneName]].children.push_back(ribBone.index);
|
||||
|
@ -462,12 +460,12 @@ bool AnimalRigger::rig()
|
|||
m_jointErrorItems.push_back(chainName);
|
||||
}
|
||||
|
||||
//qDebug() << "Limb markIndex:" << limbMarkIndex << " joints:" << jointMarkIndicies.size();
|
||||
qDebug() << "Adding chain:" << chainName << " joints:" << jointMarkIndicies.size();
|
||||
|
||||
int jointGenerateOrder = 1;
|
||||
|
||||
auto boneColor = [&]() {
|
||||
return twoColorsForLimb[jointGenerateOrder % 2];
|
||||
return twoColorsForChain[jointGenerateOrder % 2];
|
||||
};
|
||||
auto addToParentBone = [&](QVector3D headPosition, SkeletonSide side, int boneIndex) {
|
||||
if (1 == jointGenerateOrder) {
|
||||
|
@ -507,21 +505,8 @@ bool AnimalRigger::rig()
|
|||
lastJointBoneVerticies = remainingLimbVertices;
|
||||
}
|
||||
// Calculate the tail position from remaining verticies
|
||||
std::vector<QVector3D> extremCoords(6, jointPositions.back());
|
||||
resolveBoundingBox(lastJointBoneVerticies, extremCoords[0], extremCoords[1], extremCoords[2], extremCoords[3], extremCoords[4], extremCoords[5]);
|
||||
float maxDistance2 = std::numeric_limits<float>::min();
|
||||
QVector3D choosenExtreamCoord = jointPositions.back();
|
||||
for (size_t i = 0; i < 6; ++i) {
|
||||
const auto &position = extremCoords[i];
|
||||
auto length2 = (position - jointPositions.back()).lengthSquared();
|
||||
if (length2 >= maxDistance2) {
|
||||
maxDistance2 = length2;
|
||||
choosenExtreamCoord = position;
|
||||
}
|
||||
}
|
||||
jointPositions.push_back(choosenExtreamCoord);
|
||||
jointPositions.push_back(findExtremPointFrom(lastJointBoneVerticies, jointPositions.back()));
|
||||
|
||||
QVector3D lastPosition = spineBoneHeadPosition;
|
||||
for (jointGenerateOrder = 1; jointGenerateOrder <= (int)jointMarkIndicies.size(); ++jointGenerateOrder) {
|
||||
int jointMarkIndex = jointMarkIndicies[jointGenerateOrder - 1];
|
||||
const auto &jointMark = m_marks[jointMarkIndex];
|
||||
|
@ -567,8 +552,6 @@ bool AnimalRigger::rig()
|
|||
|
||||
boneIndexMap[jointBone.name] = jointBone.index;
|
||||
addToParentBone(jointBone.headPosition, chainMark.boneSide, jointBone.index);
|
||||
|
||||
lastPosition = jointPositions[jointGenerateOrder - 1];
|
||||
}
|
||||
|
||||
++chainGenerateOrder;
|
||||
|
@ -585,6 +568,23 @@ bool AnimalRigger::rig()
|
|||
return true;
|
||||
}
|
||||
|
||||
QVector3D AnimalRigger::findExtremPointFrom(const std::set<int> &verticies, const QVector3D &from)
|
||||
{
|
||||
std::vector<QVector3D> extremCoords(6, from);
|
||||
resolveBoundingBox(verticies, extremCoords[0], extremCoords[1], extremCoords[2], extremCoords[3], extremCoords[4], extremCoords[5]);
|
||||
float maxDistance2 = std::numeric_limits<float>::min();
|
||||
QVector3D choosenExtreamCoord = from;
|
||||
for (size_t i = 0; i < 6; ++i) {
|
||||
const auto &position = extremCoords[i];
|
||||
auto length2 = (position - from).lengthSquared();
|
||||
if (length2 >= maxDistance2) {
|
||||
maxDistance2 = length2;
|
||||
choosenExtreamCoord = position;
|
||||
}
|
||||
}
|
||||
return choosenExtreamCoord;
|
||||
}
|
||||
|
||||
QString AnimalRigger::namingChain(const QString &baseName, SkeletonSide side, int orderInSide, int totalInSide, int jointOrder)
|
||||
{
|
||||
return namingChainPrefix(baseName, side, orderInSide, totalInSide) + "_Joint" + QString::number(jointOrder);
|
||||
|
|
|
@ -23,6 +23,7 @@ private:
|
|||
QString namingConnector(const QString &spineName, const QString &chainName);
|
||||
QString namingChain(const QString &baseName, SkeletonSide side, int orderInSide, int totalInSide, int jointOrder);
|
||||
QString namingChainPrefix(const QString &baseName, SkeletonSide side, int orderInSide, int totalInSide);
|
||||
QVector3D findExtremPointFrom(const std::set<int> &verticies, const QVector3D &from);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,7 @@ QColor BoneMarkToColor(BoneMark mark) \
|
|||
{ \
|
||||
switch (mark) { \
|
||||
case BoneMark::Neck: \
|
||||
return QColor(0x51, 0xba, 0xf2); \
|
||||
return QColor(0xfd, 0x64, 0x61); \
|
||||
case BoneMark::Limb: \
|
||||
return QColor(0x29, 0xfd, 0x2f); \
|
||||
case BoneMark::Tail: \
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
const float PoseDocument::m_nodeRadius = 0.01;
|
||||
const float PoseDocument::m_groundPlaneHalfThickness = 0.01 / 4;
|
||||
const bool PoseDocument::m_hideRootAndVirtual = true;
|
||||
|
||||
bool PoseDocument::hasPastableNodesInClipboard() const
|
||||
{
|
||||
|
@ -176,10 +177,13 @@ void PoseDocument::updateRigBones(const std::vector<RiggerBone> *rigBones, const
|
|||
auto &bonesPart = partMap[m_bonesPartId];
|
||||
bonesPart.id = m_bonesPartId;
|
||||
|
||||
qDebug() << "rigBones size:" << rigBones->size();
|
||||
|
||||
std::vector<std::pair<int, int>> edgePairs;
|
||||
for (size_t i = 1; i < rigBones->size(); ++i) {
|
||||
for (size_t i = m_hideRootAndVirtual ? 1 : 0; i < rigBones->size(); ++i) {
|
||||
const auto &bone = (*rigBones)[i];
|
||||
for (const auto &child: bone.children) {
|
||||
qDebug() << "Add pair:" << bone.name << "->" << (*rigBones)[child].name;
|
||||
edgePairs.push_back({i, child});
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +193,7 @@ void PoseDocument::updateRigBones(const std::vector<RiggerBone> *rigBones, const
|
|||
auto findFirst = boneIndexToHeadNodeIdMap.find(edgePair.first);
|
||||
if (findFirst == boneIndexToHeadNodeIdMap.end()) {
|
||||
const auto &bone = (*rigBones)[edgePair.first];
|
||||
if (!bone.name.startsWith("Virtual_")) {
|
||||
if (!bone.name.startsWith("Virtual_") || !m_hideRootAndVirtual) {
|
||||
SkeletonNode node;
|
||||
node.partId = m_bonesPartId;
|
||||
node.id = QUuid::createUuid();
|
||||
|
@ -208,7 +212,7 @@ void PoseDocument::updateRigBones(const std::vector<RiggerBone> *rigBones, const
|
|||
auto findSecond = boneIndexToHeadNodeIdMap.find(edgePair.second);
|
||||
if (findSecond == boneIndexToHeadNodeIdMap.end()) {
|
||||
const auto &bone = (*rigBones)[edgePair.second];
|
||||
if (!bone.name.startsWith("Virtual_")) {
|
||||
if (!bone.name.startsWith("Virtual_") || !m_hideRootAndVirtual) {
|
||||
SkeletonNode node;
|
||||
node.partId = m_bonesPartId;
|
||||
node.id = QUuid::createUuid();
|
||||
|
@ -239,9 +243,9 @@ void PoseDocument::updateRigBones(const std::vector<RiggerBone> *rigBones, const
|
|||
nodeMap[secondNodeId].edgeIds.push_back(edge.id);
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < rigBones->size(); ++i) {
|
||||
for (size_t i = m_hideRootAndVirtual ? 1 : 0; i < rigBones->size(); ++i) {
|
||||
const auto &bone = (*rigBones)[i];
|
||||
if (bone.name.startsWith("Virtual_"))
|
||||
if (m_hideRootAndVirtual && bone.name.startsWith("Virtual_"))
|
||||
continue;
|
||||
if (bone.children.empty()) {
|
||||
const QUuid &firstNodeId = boneIndexToHeadNodeIdMap[i];
|
||||
|
@ -250,9 +254,9 @@ void PoseDocument::updateRigBones(const std::vector<RiggerBone> *rigBones, const
|
|||
node.partId = m_bonesPartId;
|
||||
node.id = QUuid::createUuid();
|
||||
node.setRadius(m_nodeRadius / 2);
|
||||
node.x = bone.tailPosition.x() + 0.5;
|
||||
node.y = -bone.tailPosition.y() + 0.5;
|
||||
node.z = -bone.tailPosition.z() + 1;
|
||||
node.x = fromOutcomeX(bone.tailPosition.x());
|
||||
node.y = fromOutcomeY(bone.tailPosition.y());
|
||||
node.z = fromOutcomeZ(bone.tailPosition.z());
|
||||
nodeMap[node.id] = node;
|
||||
newAddedNodeIds.insert(node.id);
|
||||
m_boneNameToIdsMap[bone.name] = {firstNodeId, node.id};
|
||||
|
@ -266,6 +270,8 @@ void PoseDocument::updateRigBones(const std::vector<RiggerBone> *rigBones, const
|
|||
newAddedEdgeIds.insert(edge.id);
|
||||
nodeMap[firstNodeId].edgeIds.push_back(edge.id);
|
||||
nodeMap[node.id].edgeIds.push_back(edge.id);
|
||||
|
||||
qDebug() << "Add pair:" << bone.name << "->" << "~";
|
||||
continue;
|
||||
}
|
||||
for (const auto &child: bone.children) {
|
||||
|
@ -273,6 +279,11 @@ void PoseDocument::updateRigBones(const std::vector<RiggerBone> *rigBones, const
|
|||
}
|
||||
}
|
||||
|
||||
auto findRootNodeId = boneIndexToHeadNodeIdMap.find(0);
|
||||
if (findRootNodeId != boneIndexToHeadNodeIdMap.end()) {
|
||||
nodeMap[findRootNodeId->second].setRadius(m_nodeRadius * 2);
|
||||
}
|
||||
|
||||
m_groundPartId = QUuid::createUuid();
|
||||
auto &groundPart = partMap[m_groundPartId];
|
||||
groundPart.id = m_groundPartId;
|
||||
|
@ -401,11 +412,42 @@ void PoseDocument::toParameters(std::map<QString, std::map<QString, QString>> &p
|
|||
auto findSecondNode = nodeMap.find(boneNodeIdPair.second);
|
||||
if (findSecondNode == nodeMap.end())
|
||||
continue;
|
||||
boneParameter["fromX"] = QString::number(findFirstNode->second.x - 0.5);
|
||||
boneParameter["fromY"] = QString::number(0.5 - findFirstNode->second.y);
|
||||
boneParameter["fromZ"] = QString::number(1.0 - findFirstNode->second.z);
|
||||
boneParameter["toX"] = QString::number(findSecondNode->second.x - 0.5);
|
||||
boneParameter["toY"] = QString::number(0.5 - findSecondNode->second.y);
|
||||
boneParameter["toZ"] = QString::number(1.0 - findSecondNode->second.z);
|
||||
boneParameter["fromX"] = QString::number(toOutcomeX(findFirstNode->second.x));
|
||||
boneParameter["fromY"] = QString::number(toOutcomeY(findFirstNode->second.y));
|
||||
boneParameter["fromZ"] = QString::number(toOutcomeZ(findFirstNode->second.z));
|
||||
boneParameter["toX"] = QString::number(toOutcomeX(findSecondNode->second.x));
|
||||
boneParameter["toY"] = QString::number(toOutcomeY(findSecondNode->second.y));
|
||||
boneParameter["toZ"] = QString::number(toOutcomeZ(findSecondNode->second.z));
|
||||
}
|
||||
}
|
||||
|
||||
float PoseDocument::fromOutcomeX(float x)
|
||||
{
|
||||
return x + 0.5;
|
||||
}
|
||||
|
||||
float PoseDocument::toOutcomeX(float x)
|
||||
{
|
||||
return x - 0.5;
|
||||
}
|
||||
|
||||
float PoseDocument::fromOutcomeY(float y)
|
||||
{
|
||||
return -y + 0.5;
|
||||
}
|
||||
|
||||
float PoseDocument::toOutcomeY(float y)
|
||||
{
|
||||
return 0.5 - y;
|
||||
}
|
||||
|
||||
float PoseDocument::fromOutcomeZ(float z)
|
||||
{
|
||||
return -z + 1;
|
||||
}
|
||||
|
||||
float PoseDocument::toOutcomeZ(float z)
|
||||
{
|
||||
return 1.0 - z;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ public slots:
|
|||
public:
|
||||
static const float m_nodeRadius;
|
||||
static const float m_groundPlaneHalfThickness;
|
||||
static const bool m_hideRootAndVirtual;
|
||||
|
||||
private:
|
||||
std::map<QString, std::pair<QUuid, QUuid>> m_boneNameToIdsMap;
|
||||
|
@ -61,6 +62,13 @@ private:
|
|||
std::deque<PoseHistoryItem> m_undoItems;
|
||||
std::deque<PoseHistoryItem> m_redoItems;
|
||||
std::vector<RiggerBone> m_riggerBones;
|
||||
|
||||
static float fromOutcomeX(float x);
|
||||
static float toOutcomeX(float x);
|
||||
static float fromOutcomeY(float y);
|
||||
static float toOutcomeY(float y);
|
||||
static float fromOutcomeZ(float z);
|
||||
static float toOutcomeZ(float z);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,9 +38,35 @@ bool Rigger::calculateBodyTriangles(std::set<MeshSplitterTriangle> &bodyTriangle
|
|||
}
|
||||
if (bodyTriangles.empty()) {
|
||||
m_messages.push_back(std::make_pair(QtCriticalMsg,
|
||||
tr("Calculate body from marks failed")));
|
||||
tr("Calculate body from marks failed, try to move the center anchor around")));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the calculated body is neighboring with all the cutoff makers
|
||||
std::set<int> bodyVertices;
|
||||
addTrianglesToVertices(bodyTriangles, bodyVertices);
|
||||
for (const auto &marksMapIt: m_marksMap) {
|
||||
if (isCutOffSplitter(marksMapIt.first.first)) {
|
||||
for (const auto index: marksMapIt.second) {
|
||||
auto &mark = m_marks[index];
|
||||
std::set<int> markSplitterVertices;
|
||||
addTrianglesToVertices(mark.markTriangles, markSplitterVertices);
|
||||
bool neighboring = false;
|
||||
for (const auto &index: markSplitterVertices) {
|
||||
if (bodyVertices.find(index) != bodyVertices.end()) {
|
||||
neighboring = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!neighboring) {
|
||||
m_messages.push_back(std::make_pair(QtCriticalMsg,
|
||||
tr("The center anchor is not located in the center of the model")));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -58,7 +84,7 @@ bool Rigger::addMarkGroup(BoneMark boneMark, SkeletonSide boneSide, QVector3D bo
|
|||
mark.markTriangles = markTriangles;
|
||||
|
||||
if (isCutOffSplitter(mark.boneMark)) {
|
||||
if (!mark.split(m_inputTriangles, m_maxCutOffSplitterExpandRound)) {
|
||||
if (!mark.split(m_verticesPositions, m_inputTriangles, m_maxCutOffSplitterExpandRound)) {
|
||||
m_cutoffErrorItems.push_back(SkeletonSideToDispName(mark.boneSide) + " " + BoneMarkToDispName(mark.boneMark));
|
||||
return false;
|
||||
}
|
||||
|
|
34
src/rigger.h
34
src/rigger.h
|
@ -22,31 +22,49 @@ public:
|
|||
std::set<MeshSplitterTriangle> markTriangles;
|
||||
const std::set<MeshSplitterTriangle> &bigGroup() const
|
||||
{
|
||||
return m_firstGroup.size() > m_secondGroup.size() ?
|
||||
m_firstGroup :
|
||||
m_secondGroup;
|
||||
return m_isFirstBiggerThenSecond ? m_firstGroup : m_secondGroup;
|
||||
}
|
||||
const std::set<MeshSplitterTriangle> &smallGroup() const
|
||||
{
|
||||
return m_firstGroup.size() > m_secondGroup.size() ?
|
||||
m_secondGroup :
|
||||
m_firstGroup;
|
||||
return m_isFirstBiggerThenSecond ? m_secondGroup : m_firstGroup;
|
||||
}
|
||||
bool split(const std::set<MeshSplitterTriangle> &input, int expandRound=0)
|
||||
bool split(const std::vector<QVector3D> &verticesPositions, const std::set<MeshSplitterTriangle> &input, int expandRound=0)
|
||||
{
|
||||
int totalRound = 1 + expandRound;
|
||||
for (int round = 0; round < totalRound; ++round) {
|
||||
m_firstGroup.clear();
|
||||
m_secondGroup.clear();
|
||||
bool splitResult = MeshSplitter::split(input, markTriangles, m_firstGroup, m_secondGroup, round > 0);
|
||||
if (splitResult)
|
||||
if (splitResult) {
|
||||
sortByDistanceFromOrigin(verticesPositions);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
std::set<MeshSplitterTriangle> m_firstGroup;
|
||||
std::set<MeshSplitterTriangle> m_secondGroup;
|
||||
bool m_isFirstBiggerThenSecond = false;
|
||||
|
||||
float minDistance2FromOrigin(const std::vector<QVector3D> &verticesPositions, const std::set<MeshSplitterTriangle> &triangles)
|
||||
{
|
||||
float minDistance2 = std::numeric_limits<float>::max();
|
||||
for (const auto &triangle: triangles) {
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
float distance2 = verticesPositions[triangle.indicies[i]].lengthSquared();
|
||||
if (distance2 < minDistance2)
|
||||
minDistance2 = distance2;
|
||||
}
|
||||
}
|
||||
return minDistance2;
|
||||
}
|
||||
|
||||
void sortByDistanceFromOrigin(const std::vector<QVector3D> &verticesPositions)
|
||||
{
|
||||
m_isFirstBiggerThenSecond = minDistance2FromOrigin(verticesPositions, m_firstGroup) <
|
||||
minDistance2FromOrigin(verticesPositions, m_secondGroup);
|
||||
}
|
||||
};
|
||||
|
||||
class RiggerBone
|
||||
|
|
Loading…
Reference in New Issue