Generate bone previews

master
Jeremy HU 2022-12-03 15:54:12 +11:00
parent 995230db59
commit 374f16038d
2 changed files with 100 additions and 22 deletions

View File

@ -21,6 +21,7 @@
*/ */
#include <dust3d/rig/skeleton_generator.h> #include <dust3d/rig/skeleton_generator.h>
#include <unordered_map>
namespace dust3d { namespace dust3d {
@ -33,9 +34,9 @@ void SkeletonGenerator::setVertices(const std::vector<Vector3>& vertices)
m_vertices = vertices; m_vertices = vertices;
} }
void SkeletonGenerator::setFaces(const std::vector<std::vector<size_t>>& faces) void SkeletonGenerator::setTriangles(const std::vector<std::vector<size_t>>& triangles)
{ {
m_faces = faces; m_triangles = triangles;
} }
void SkeletonGenerator::setPositionToNodeMap(const std::map<PositionKey, Uuid>& positionToNodeMap) void SkeletonGenerator::setPositionToNodeMap(const std::map<PositionKey, Uuid>& positionToNodeMap)
@ -48,6 +49,11 @@ void SkeletonGenerator::addBone(const Uuid& boneId, const Bone& bone)
m_boneMap.emplace(std::make_pair(boneId, bone)); m_boneMap.emplace(std::make_pair(boneId, bone));
} }
void SkeletonGenerator::addNode(const Uuid& nodeId, const Node& node)
{
m_nodeMap.emplace(std::make_pair(nodeId, node));
}
void SkeletonGenerator::addNodeBinding(const Uuid& nodeId, const NodeBinding& nodeBinding) void SkeletonGenerator::addNodeBinding(const Uuid& nodeId, const NodeBinding& nodeBinding)
{ {
m_nodeBindingMap.emplace(std::make_pair(nodeId, nodeBinding)); m_nodeBindingMap.emplace(std::make_pair(nodeId, nodeBinding));
@ -55,11 +61,11 @@ void SkeletonGenerator::addNodeBinding(const Uuid& nodeId, const NodeBinding& no
void SkeletonGenerator::buildEdges() void SkeletonGenerator::buildEdges()
{ {
for (const auto& face : m_faces) { for (const auto& triangle : m_triangles) {
for (size_t i = 0; i < face.size(); ++i) { for (size_t i = 0; i < 3; ++i) {
size_t j = (i + 1) % face.size(); size_t j = (i + 1) % 3;
m_edges[face[i]].insert(face[j]); m_edges[triangle[i]].insert(triangle[j]);
m_edges[face[j]].insert(face[i]); m_edges[triangle[j]].insert(triangle[i]);
} }
} }
} }
@ -104,17 +110,29 @@ void SkeletonGenerator::resolveVertexSources()
void SkeletonGenerator::buildBoneJoints() void SkeletonGenerator::buildBoneJoints()
{ {
// TODO: for (auto& boneIt : m_boneMap) {
boneIt.second.startPositions.resize(boneIt.second.joints.size());
for (size_t i = 0; i < boneIt.second.joints.size(); ++i) {
const auto& nodeId = boneIt.second.joints[i];
auto nodeIt = m_nodeMap.find(nodeId);
if (nodeIt == m_nodeMap.end())
continue;
boneIt.second.startPositions[i] = nodeIt->second.position;
}
boneIt.second.forwardVectors.resize(boneIt.second.startPositions.size());
for (size_t i = 0; i + 1 < boneIt.second.startPositions.size(); ++i) {
boneIt.second.forwardVectors[i] = boneIt.second.startPositions[i + 1] - boneIt.second.startPositions[i];
}
}
} }
void SkeletonGenerator::assignBoneJointToVertices() void SkeletonGenerator::assignVerticesToBoneJoints()
{ {
// TODO: // TODO:
} }
void SkeletonGenerator::groupBoneVertices() void SkeletonGenerator::groupBoneVertices()
{ {
/*
for (size_t i = 0; i < m_vertexSourceNodes.size(); ++i) { for (size_t i = 0; i < m_vertexSourceNodes.size(); ++i) {
const Uuid& sourceNodeId = m_vertexSourceNodes[i]; const Uuid& sourceNodeId = m_vertexSourceNodes[i];
if (sourceNodeId.isNull()) if (sourceNodeId.isNull())
@ -122,19 +140,55 @@ void SkeletonGenerator::groupBoneVertices()
auto findBinding = m_nodeBindingMap.find(sourceNodeId); auto findBinding = m_nodeBindingMap.find(sourceNodeId);
if (findBinding == m_nodeBindingMap.end()) if (findBinding == m_nodeBindingMap.end())
continue; continue;
// TODO: for (const auto& boneId : findBinding->second.boneIds) {
m_boneVertices[boneId].insert(i);
}
} }
*/
// TODO:
} }
void SkeletonGenerator::bind() void SkeletonGenerator::generate()
{ {
buildEdges(); buildEdges();
resolveVertexSources(); resolveVertexSources();
groupBoneVertices(); groupBoneVertices();
buildBoneJoints(); buildBoneJoints();
assignBoneJointToVertices(); assignVerticesToBoneJoints();
generateBonePreviews();
}
void SkeletonGenerator::generateBonePreviews()
{
for (const auto& it : m_boneVertices) {
BonePreview bonePreview;
std::unordered_map<size_t, size_t> oldToNewVertexMap;
auto addTriangleAsLocal = [&](const std::vector<size_t>& globalTriangle) {
std::vector<size_t> newTriangle(3);
for (size_t i = 0; i < 3; ++i) {
auto findVertex = oldToNewVertexMap.find(globalTriangle[i]);
if (findVertex == oldToNewVertexMap.end()) {
oldToNewVertexMap.insert(std::make_pair(globalTriangle[i], bonePreview.vertices.size()));
newTriangle[i] = bonePreview.vertices.size();
bonePreview.vertices.push_back(m_vertices[globalTriangle[i]]);
} else {
newTriangle[i] = findVertex->first;
}
}
bonePreview.triangles.emplace_back(newTriangle);
};
for (const auto& triangle : m_triangles) {
size_t countedPoints = 0;
for (size_t i = 0; i < 3; ++i) {
if (it.second.end() != it.second.find(triangle[i]))
++countedPoints;
}
if (0 == countedPoints)
continue;
addTriangleAsLocal(triangle);
}
m_bonePreviews.emplace(std::make_pair(it.first, std::move(bonePreview)));
}
} }
} }

View File

@ -23,6 +23,8 @@
#ifndef DUST3D_RIG_SKELETON_GENERATOR_H_ #ifndef DUST3D_RIG_SKELETON_GENERATOR_H_
#define DUST3D_RIG_SKELETON_GENERATOR_H_ #define DUST3D_RIG_SKELETON_GENERATOR_H_
#include <array>
#include <dust3d/base/color.h>
#include <dust3d/base/position_key.h> #include <dust3d/base/position_key.h>
#include <dust3d/base/uuid.h> #include <dust3d/base/uuid.h>
#include <dust3d/base/vector3.h> #include <dust3d/base/vector3.h>
@ -36,37 +38,59 @@ namespace dust3d {
class SkeletonGenerator { class SkeletonGenerator {
public: public:
struct NodeBinding { struct NodeBinding {
std::vector<Uuid> boneIds; std::set<Uuid> boneIds;
bool bontJoint = false; };
struct VertexWeight {
size_t vertex;
double weight;
}; };
struct Bone { struct Bone {
std::string name; std::string name;
std::vector<Uuid> joints;
std::vector<Vector3> startPositions;
std::vector<Vector3> forwardVectors;
std::vector<VertexWeight> vertexWeights;
};
struct Node {
Vector3 position;
};
struct BonePreview {
std::vector<Vector3> vertices;
std::vector<std::vector<size_t>> triangles;
}; };
SkeletonGenerator(); SkeletonGenerator();
void setVertices(const std::vector<Vector3>& vertices); void setVertices(const std::vector<Vector3>& vertices);
void setFaces(const std::vector<std::vector<size_t>>& faces); void setTriangles(const std::vector<std::vector<size_t>>& triangles);
void setPositionToNodeMap(const std::map<PositionKey, Uuid>& positionToNodeMap); void setPositionToNodeMap(const std::map<PositionKey, Uuid>& positionToNodeMap);
void addBone(const Uuid& boneId, const Bone& bone); void addBone(const Uuid& boneId, const Bone& bone);
void addNodeBinding(const Uuid& nodeId, const NodeBinding& nodeBinding); void addNodeBinding(const Uuid& nodeId, const NodeBinding& nodeBidning);
void bind(); void addNode(const Uuid& nodeId, const Node& node);
void generate();
private: private:
std::vector<Vector3> m_vertices; std::vector<Vector3> m_vertices;
std::vector<std::vector<size_t>> m_faces; std::vector<std::vector<size_t>> m_triangles;
std::map<PositionKey, Uuid> m_positionToNodeMap; std::map<PositionKey, Uuid> m_positionToNodeMap;
std::map<Uuid, NodeBinding> m_nodeBindingMap; std::map<Uuid, NodeBinding> m_nodeBindingMap;
std::map<Uuid, Bone> m_boneMap; std::map<Uuid, Bone> m_boneMap;
std::map<Uuid, Node> m_nodeMap;
std::map<size_t, std::set<size_t>> m_edges; std::map<size_t, std::set<size_t>> m_edges;
std::vector<Uuid> m_vertexSourceNodes; std::vector<Uuid> m_vertexSourceNodes;
std::map<Uuid, std::unordered_set<size_t>> m_boneVertices;
std::map<Uuid, BonePreview> m_bonePreviews;
void buildEdges(); void buildEdges();
void resolveVertexSources(); void resolveVertexSources();
Uuid resolveVertexSourceByBreadthFirstSearch(size_t vertexIndex, std::unordered_set<size_t>& visited); Uuid resolveVertexSourceByBreadthFirstSearch(size_t vertexIndex, std::unordered_set<size_t>& visited);
void groupBoneVertices(); void groupBoneVertices();
void buildBoneJoints(); void buildBoneJoints();
void assignBoneJointToVertices(); void assignVerticesToBoneJoints();
void generateBonePreviews();
}; };
} }