#ifndef DUST3D_RIG_GENERATOR_H #define DUST3D_RIG_GENERATOR_H #include #include #include #include #include "outcome.h" #include "model.h" #include "rigger.h" #include "rigtype.h" class RigGenerator : public QObject { Q_OBJECT public: RigGenerator(RigType rigType, const Outcome &outcome); ~RigGenerator(); Model *takeResultMesh(); std::vector *takeResultBones(); std::map *takeResultWeights(); const std::vector> &messages(); Outcome *takeOutcome(); bool isSuccessful(); void generate(); signals: void finished(); public slots: void process(); private: struct BoneNodeChain { size_t fromNodeIndex; std::vector> nodeIndices; bool isSpine; size_t attachNodeIndex; }; RigType m_rigType = RigType::None; Outcome *m_outcome = nullptr; Model *m_resultMesh = nullptr; std::vector *m_resultBones = nullptr; std::map *m_resultWeights = nullptr; std::vector> m_messages; std::map> m_neighborMap; std::vector m_boneNodeChain; std::vector m_neckChains; std::vector m_leftLimbChains; std::vector m_rightLimbChains; std::vector m_tailChains; std::vector m_spineChains; std::unordered_set m_virtualJoints; std::vector m_attachLimbsToSpineNodeIndices; std::vector m_attachLimbsToSpineJointIndices; std::map> m_branchNodesMapByMark; std::vector m_neckJoints; std::vector> m_leftLimbJoints; std::vector> m_rightLimbJoints; std::vector m_tailJoints; std::vector m_spineJoints; std::map m_boneNameToIndexMap; ShaderVertex *m_debugEdgeVertices = nullptr; int m_debugEdgeVerticesNum = 0; bool m_isSpineVertical = false; bool m_isSuccessful = false; void buildNeighborMap(); void buildBoneNodeChain(); void buildSkeleton(); void computeSkinWeights(); void buildDemoMesh(); void calculateSpineDirection(bool *isVertical); void attachLimbsToSpine(); void extractSpineJoints(); void extractBranchJoints(); void extractJointsFromBoneNodeChain(const BoneNodeChain &boneNodeChain, std::vector *joints); void extractJoints(const size_t &fromNodeIndex, const std::vector> &nodeIndices, std::vector *joints, bool checkLastNoneMarkedNode=true); void groupNodeIndices(const std::map> &neighborMap, std::vector> *groups); void computeBranchSkinWeights(size_t fromBoneIndex, const QString &boneNamePrefix, const std::vector &vertexIndices, std::vector *discardedVertexIndices=nullptr); void splitByNodeIndex(size_t nodeIndex, std::unordered_set *left, std::unordered_set *right); void collectNodes(size_t fromNodeIndex, std::unordered_set *container, std::unordered_set *visited); void collectNodesForBoneRecursively(size_t fromNodeIndex, const std::unordered_set *limitedNodeIndices, std::vector> *boneNodeIndices, size_t depth, std::unordered_set *visited); void removeBranchsFromNodes(const std::vector> *boneNodeIndices, std::vector *resultNodes); }; #endif