Implement bone vertex weights calculation

master
Jeremy HU 2022-12-10 07:03:55 +11:00
parent b906409ab9
commit f70dbc47ae
3 changed files with 59 additions and 11 deletions

View File

@ -37,6 +37,14 @@ void BoneGenerator::process()
for (const auto& it : m_snapshot->boneIdList) { for (const auto& it : m_snapshot->boneIdList) {
Bone bone; Bone bone;
auto findBone = m_snapshot->bones.find(it);
if (findBone == m_snapshot->bones.end())
continue;
for (const auto& nodeIdString : dust3d::String::split(dust3d::String::valueOrEmpty(findBone->second, "jointNodeIdList"), ',')) {
if (nodeIdString.empty())
continue;
bone.joints.push_back(dust3d::Uuid(nodeIdString));
}
addBone(dust3d::Uuid(it), bone); addBone(dust3d::Uuid(it), bone);
} }

View File

@ -127,11 +127,6 @@ void BoneGenerator::buildBoneJoints()
} }
} }
void BoneGenerator::assignVerticesToBoneJoints()
{
// TODO:
}
void BoneGenerator::groupBoneVertices() void BoneGenerator::groupBoneVertices()
{ {
for (size_t i = 0; i < m_vertexSourceNodes.size(); ++i) { for (size_t i = 0; i < m_vertexSourceNodes.size(); ++i) {
@ -147,13 +142,53 @@ void BoneGenerator::groupBoneVertices()
} }
} }
void BoneGenerator::calculateBoneVertexWeights(const Uuid& boneId, Bone& bone)
{
auto findBoneVertices = m_boneVertices.find(boneId);
if (findBoneVertices == m_boneVertices.end())
return;
std::vector<std::unordered_set<size_t>> segments(bone.startPositions.size());
// Split bone vertices by joint position and forward direction
for (size_t jointIndex = 0; jointIndex + 1 < bone.startPositions.size(); ++jointIndex) {
const auto& nextJointPosition = bone.startPositions[jointIndex + 1];
auto forwardDirection = bone.forwardVectors[jointIndex].normalized();
for (const auto& vertex : findBoneVertices->second) {
const auto& vertexPosition = m_vertices[vertex];
if (Vector3::dotProduct(forwardDirection, (vertexPosition - nextJointPosition).normalized()) <= 0.0) {
segments[jointIndex].insert(vertex);
}
}
}
bone.vertexWeights.resize(bone.startPositions.size());
for (size_t jointIndex = 0; jointIndex < bone.startPositions.size(); ++jointIndex) {
for (const auto& it : segments[jointIndex])
bone.vertexWeights[jointIndex].push_back(VertexWeight { it, 1.0 });
}
// Calculate joint radius based on group all the boundary vertices,
// and use these vertices as points of sphere,
// boundary vertices means the edge connected these vertices in different bone vertex split
// Use m_triangles which contains all triangles to find the edges of vertices
// TODO:
// Weight vertex as normal when not in joint radius range
// TODO:
// Weight vertex as joint radius considered
// TODO:
}
void BoneGenerator::generate() void BoneGenerator::generate()
{ {
buildEdges(); buildEdges();
resolveVertexSources(); resolveVertexSources();
groupBoneVertices(); groupBoneVertices();
buildBoneJoints(); buildBoneJoints();
assignVerticesToBoneJoints(); for (auto& boneIt : m_boneMap)
calculateBoneVertexWeights(boneIt.first, boneIt.second);
generateBonePreviews(); generateBonePreviews();
} }
@ -228,9 +263,14 @@ void BoneGenerator::generateBonePreviews()
auto findBone = m_boneMap.find(it.first); auto findBone = m_boneMap.find(it.first);
if (findBone == m_boneMap.end()) if (findBone == m_boneMap.end())
continue; continue;
const auto& color = s_colors[findBone->second.index % s_colors.size()]; const auto& color = s_colors[(findBone->second.index) % s_colors.size()];
for (const auto& vertexIndex : it.second) const auto& alternativeColor = s_colors[(findBone->second.index + s_colors.size() / 2) % s_colors.size()];
vertexSkinColors[vertexIndex].push_back(color); for (size_t jointIndex = 0; jointIndex < findBone->second.vertexWeights.size(); ++jointIndex) {
const auto& useColor = 0 == jointIndex % 2 ? color : alternativeColor;
for (const auto& vertexWeight : findBone->second.vertexWeights[jointIndex]) {
vertexSkinColors[vertexWeight.vertex].push_back(useColor);
}
}
} }
std::vector<Color> bodyVertexColors(m_vertices.size()); std::vector<Color> bodyVertexColors(m_vertices.size());
for (const auto& it : vertexSkinColors) { for (const auto& it : vertexSkinColors) {

View File

@ -53,7 +53,7 @@ public:
std::vector<Uuid> joints; std::vector<Uuid> joints;
std::vector<Vector3> startPositions; std::vector<Vector3> startPositions;
std::vector<Vector3> forwardVectors; std::vector<Vector3> forwardVectors;
std::vector<VertexWeight> vertexWeights; std::vector<std::vector<VertexWeight>> vertexWeights;
}; };
struct Node { struct Node {
@ -97,12 +97,12 @@ private:
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 assignVerticesToBoneJoints();
void generateBonePreviews(); void generateBonePreviews();
void addBonePreviewTriangle(BonePreview& bonePreview, void addBonePreviewTriangle(BonePreview& bonePreview,
std::unordered_map<size_t, size_t>& oldToNewVertexMap, std::unordered_map<size_t, size_t>& oldToNewVertexMap,
const std::vector<size_t>& triangle, const std::vector<size_t>& triangle,
const Color& color); const Color& color);
void calculateBoneVertexWeights(const Uuid& boneId, Bone& bone);
}; };
} }