From f70dbc47ae9ab90a66506389ab3bb9996a53b461 Mon Sep 17 00:00:00 2001 From: Jeremy HU Date: Sat, 10 Dec 2022 07:03:55 +1100 Subject: [PATCH] Implement bone vertex weights calculation --- application/sources/bone_generator.cc | 8 ++++ dust3d/rig/bone_generator.cc | 58 ++++++++++++++++++++++----- dust3d/rig/bone_generator.h | 4 +- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/application/sources/bone_generator.cc b/application/sources/bone_generator.cc index d6897c9a..3f9efda1 100644 --- a/application/sources/bone_generator.cc +++ b/application/sources/bone_generator.cc @@ -37,6 +37,14 @@ void BoneGenerator::process() for (const auto& it : m_snapshot->boneIdList) { 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); } diff --git a/dust3d/rig/bone_generator.cc b/dust3d/rig/bone_generator.cc index db389aac..02afdd97 100644 --- a/dust3d/rig/bone_generator.cc +++ b/dust3d/rig/bone_generator.cc @@ -127,11 +127,6 @@ void BoneGenerator::buildBoneJoints() } } -void BoneGenerator::assignVerticesToBoneJoints() -{ - // TODO: -} - void BoneGenerator::groupBoneVertices() { 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> 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() { buildEdges(); resolveVertexSources(); groupBoneVertices(); buildBoneJoints(); - assignVerticesToBoneJoints(); + for (auto& boneIt : m_boneMap) + calculateBoneVertexWeights(boneIt.first, boneIt.second); generateBonePreviews(); } @@ -228,9 +263,14 @@ void BoneGenerator::generateBonePreviews() auto findBone = m_boneMap.find(it.first); if (findBone == m_boneMap.end()) continue; - const auto& color = s_colors[findBone->second.index % s_colors.size()]; - for (const auto& vertexIndex : it.second) - vertexSkinColors[vertexIndex].push_back(color); + const auto& color = s_colors[(findBone->second.index) % s_colors.size()]; + const auto& alternativeColor = s_colors[(findBone->second.index + s_colors.size() / 2) % s_colors.size()]; + 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 bodyVertexColors(m_vertices.size()); for (const auto& it : vertexSkinColors) { diff --git a/dust3d/rig/bone_generator.h b/dust3d/rig/bone_generator.h index 4e288304..1c948793 100644 --- a/dust3d/rig/bone_generator.h +++ b/dust3d/rig/bone_generator.h @@ -53,7 +53,7 @@ public: std::vector joints; std::vector startPositions; std::vector forwardVectors; - std::vector vertexWeights; + std::vector> vertexWeights; }; struct Node { @@ -97,12 +97,12 @@ private: Uuid resolveVertexSourceByBreadthFirstSearch(size_t vertexIndex, std::unordered_set& visited); void groupBoneVertices(); void buildBoneJoints(); - void assignVerticesToBoneJoints(); void generateBonePreviews(); void addBonePreviewTriangle(BonePreview& bonePreview, std::unordered_map& oldToNewVertexMap, const std::vector& triangle, const Color& color); + void calculateBoneVertexWeights(const Uuid& boneId, Bone& bone); }; }