Add intermediate bone remover.
- Remove intermediate bones when user marked leg nodes - Add flags to toggle gltf comment and normal output - Fix face normal - Adjust the skeleton bone mesh radiusmaster
parent
bed110b678
commit
c4505ba788
|
@ -128,6 +128,9 @@ HEADERS += src/markiconcreator.h
|
||||||
SOURCES += src/skeletonbonemark.cpp
|
SOURCES += src/skeletonbonemark.cpp
|
||||||
HEADERS += src/skeletonbonemark.h
|
HEADERS += src/skeletonbonemark.h
|
||||||
|
|
||||||
|
SOURCES += src/intermediateboneremover.cpp
|
||||||
|
HEADERS += src/intermediateboneremover.h
|
||||||
|
|
||||||
HEADERS += src/qtlightmapper.h
|
HEADERS += src/qtlightmapper.h
|
||||||
|
|
||||||
SOURCES += src/main.cpp
|
SOURCES += src/main.cpp
|
||||||
|
|
|
@ -17,8 +17,11 @@
|
||||||
// http://quaternions.online/
|
// http://quaternions.online/
|
||||||
// https://en.m.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions?wprov=sfla1
|
// https://en.m.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions?wprov=sfla1
|
||||||
|
|
||||||
|
bool GLTFFileWriter::m_enableComment = false;
|
||||||
|
|
||||||
GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &filename) :
|
GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &filename) :
|
||||||
m_filename(filename)
|
m_filename(filename),
|
||||||
|
m_outputNormal(true)
|
||||||
{
|
{
|
||||||
const BmeshNode *rootNode = resultContext.centerBmeshNode();
|
const BmeshNode *rootNode = resultContext.centerBmeshNode();
|
||||||
if (!rootNode) {
|
if (!rootNode) {
|
||||||
|
@ -107,6 +110,8 @@ GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &
|
||||||
|
|
||||||
int bufferViewIndex = 0;
|
int bufferViewIndex = 0;
|
||||||
|
|
||||||
|
if (m_enableComment)
|
||||||
|
m_json["accessors"][bufferViewIndex]["__comment"] = QString("/accessors/%1: mat").arg(QString::number(bufferViewIndex)).toUtf8().constData();
|
||||||
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
||||||
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
||||||
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
||||||
|
@ -140,12 +145,14 @@ GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &
|
||||||
int bufferViewFromOffset;
|
int bufferViewFromOffset;
|
||||||
|
|
||||||
m_json["meshes"][0]["primitives"][primitiveIndex]["indices"] = bufferViewIndex;
|
m_json["meshes"][0]["primitives"][primitiveIndex]["indices"] = bufferViewIndex;
|
||||||
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["POSITION"] = bufferViewIndex + 1;
|
|
||||||
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["NORMAL"] = bufferViewIndex + 2;
|
|
||||||
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["JOINTS_0"] = bufferViewIndex + 3;
|
|
||||||
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["WEIGHTS_0"] = bufferViewIndex + 4;
|
|
||||||
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["TEXCOORD_0"] = bufferViewIndex + 5;
|
|
||||||
m_json["meshes"][0]["primitives"][primitiveIndex]["material"] = primitiveIndex;
|
m_json["meshes"][0]["primitives"][primitiveIndex]["material"] = primitiveIndex;
|
||||||
|
int attributeIndex = 0;
|
||||||
|
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["POSITION"] = bufferViewIndex + (++attributeIndex);
|
||||||
|
if (m_outputNormal)
|
||||||
|
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["NORMAL"] = bufferViewIndex + (++attributeIndex);
|
||||||
|
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["JOINTS_0"] = bufferViewIndex + (++attributeIndex);
|
||||||
|
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["WEIGHTS_0"] = bufferViewIndex + (++attributeIndex);
|
||||||
|
m_json["meshes"][0]["primitives"][primitiveIndex]["attributes"]["TEXCOORD_0"] = bufferViewIndex + (++attributeIndex);
|
||||||
/*
|
/*
|
||||||
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["baseColorFactor"] = {
|
m_json["materials"][primitiveIndex]["pbrMetallicRoughness"]["baseColorFactor"] = {
|
||||||
part.second.color.redF(),
|
part.second.color.redF(),
|
||||||
|
@ -169,6 +176,8 @@ GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &
|
||||||
m_json["bufferViews"][bufferViewIndex]["target"] = 34963;
|
m_json["bufferViews"][bufferViewIndex]["target"] = 34963;
|
||||||
Q_ASSERT(part.second.triangles.size() * 3 * sizeof(quint16) == binaries.size() - bufferViewFromOffset);
|
Q_ASSERT(part.second.triangles.size() * 3 * sizeof(quint16) == binaries.size() - bufferViewFromOffset);
|
||||||
alignBinaries();
|
alignBinaries();
|
||||||
|
if (m_enableComment)
|
||||||
|
m_json["accessors"][bufferViewIndex]["__comment"] = QString("/accessors/%1: triangle indicies").arg(QString::number(bufferViewIndex)).toUtf8().constData();
|
||||||
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
||||||
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
||||||
m_json["accessors"][bufferViewIndex]["componentType"] = 5123;
|
m_json["accessors"][bufferViewIndex]["componentType"] = 5123;
|
||||||
|
@ -204,7 +213,8 @@ GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &
|
||||||
m_json["bufferViews"][bufferViewIndex]["byteLength"] = part.second.vertices.size() * 3 * sizeof(float);
|
m_json["bufferViews"][bufferViewIndex]["byteLength"] = part.second.vertices.size() * 3 * sizeof(float);
|
||||||
m_json["bufferViews"][bufferViewIndex]["target"] = 34962;
|
m_json["bufferViews"][bufferViewIndex]["target"] = 34962;
|
||||||
alignBinaries();
|
alignBinaries();
|
||||||
|
if (m_enableComment)
|
||||||
|
m_json["accessors"][bufferViewIndex]["__comment"] = QString("/accessors/%1: xyz").arg(QString::number(bufferViewIndex)).toUtf8().constData();
|
||||||
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
||||||
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
||||||
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
||||||
|
@ -214,23 +224,29 @@ GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &
|
||||||
m_json["accessors"][bufferViewIndex]["min"] = {minX, minY, minZ};
|
m_json["accessors"][bufferViewIndex]["min"] = {minX, minY, minZ};
|
||||||
bufferViewIndex++;
|
bufferViewIndex++;
|
||||||
|
|
||||||
bufferViewFromOffset = (int)binaries.size();
|
if (m_outputNormal) {
|
||||||
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
|
bufferViewFromOffset = (int)binaries.size();
|
||||||
m_json["bufferViews"][bufferViewIndex]["byteOffset"] = bufferViewFromOffset;
|
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
|
||||||
for (const auto &it: part.second.interpolatedVertexNormals) {
|
m_json["bufferViews"][bufferViewIndex]["byteOffset"] = bufferViewFromOffset;
|
||||||
stream << (float)it.x() << (float)it.y() << (float)it.z();
|
QStringList normalList;
|
||||||
|
for (const auto &it: part.second.interpolatedVertexNormals) {
|
||||||
|
stream << (float)it.x() << (float)it.y() << (float)it.z();
|
||||||
|
if (m_outputNormal)
|
||||||
|
normalList.append(QString("<%1,%2,%3>").arg(QString::number(it.x())).arg(QString::number(it.y())).arg(QString::number(it.z())));
|
||||||
|
}
|
||||||
|
Q_ASSERT( part.second.interpolatedVertexNormals.size() * 3 * sizeof(float) == binaries.size() - bufferViewFromOffset);
|
||||||
|
m_json["bufferViews"][bufferViewIndex]["byteLength"] = part.second.vertices.size() * 3 * sizeof(float);
|
||||||
|
m_json["bufferViews"][bufferViewIndex]["target"] = 34962;
|
||||||
|
alignBinaries();
|
||||||
|
if (m_enableComment)
|
||||||
|
m_json["accessors"][bufferViewIndex]["__comment"] = QString("/accessors/%1: normal %2").arg(QString::number(bufferViewIndex)).arg(normalList.join(" ")).toUtf8().constData();
|
||||||
|
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
||||||
|
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
||||||
|
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
||||||
|
m_json["accessors"][bufferViewIndex]["count"] = part.second.vertices.size();
|
||||||
|
m_json["accessors"][bufferViewIndex]["type"] = "VEC3";
|
||||||
|
bufferViewIndex++;
|
||||||
}
|
}
|
||||||
Q_ASSERT( part.second.interpolatedVertexNormals.size() * 3 * sizeof(float) == binaries.size() - bufferViewFromOffset);
|
|
||||||
m_json["bufferViews"][bufferViewIndex]["byteLength"] = part.second.vertices.size() * 3 * sizeof(float);
|
|
||||||
m_json["bufferViews"][bufferViewIndex]["target"] = 34962;
|
|
||||||
alignBinaries();
|
|
||||||
|
|
||||||
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
|
||||||
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
|
||||||
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
|
||||||
m_json["accessors"][bufferViewIndex]["count"] = part.second.vertices.size();
|
|
||||||
m_json["accessors"][bufferViewIndex]["type"] = "VEC3";
|
|
||||||
bufferViewIndex++;
|
|
||||||
|
|
||||||
bufferViewFromOffset = (int)binaries.size();
|
bufferViewFromOffset = (int)binaries.size();
|
||||||
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
|
m_json["bufferViews"][bufferViewIndex]["buffer"] = 0;
|
||||||
|
@ -246,6 +262,8 @@ GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &
|
||||||
}
|
}
|
||||||
m_json["bufferViews"][bufferViewIndex]["byteLength"] = binaries.size() - bufferViewFromOffset;
|
m_json["bufferViews"][bufferViewIndex]["byteLength"] = binaries.size() - bufferViewFromOffset;
|
||||||
alignBinaries();
|
alignBinaries();
|
||||||
|
if (m_enableComment)
|
||||||
|
m_json["accessors"][bufferViewIndex]["__comment"] = QString("/accessors/%1: bone indicies").arg(QString::number(bufferViewIndex)).toUtf8().constData();
|
||||||
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
||||||
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
||||||
m_json["accessors"][bufferViewIndex]["componentType"] = 5123;
|
m_json["accessors"][bufferViewIndex]["componentType"] = 5123;
|
||||||
|
@ -267,6 +285,8 @@ GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &
|
||||||
}
|
}
|
||||||
m_json["bufferViews"][bufferViewIndex]["byteLength"] = binaries.size() - bufferViewFromOffset;
|
m_json["bufferViews"][bufferViewIndex]["byteLength"] = binaries.size() - bufferViewFromOffset;
|
||||||
alignBinaries();
|
alignBinaries();
|
||||||
|
if (m_enableComment)
|
||||||
|
m_json["accessors"][bufferViewIndex]["__comment"] = QString("/accessors/%1: bone weights").arg(QString::number(bufferViewIndex)).toUtf8().constData();
|
||||||
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
||||||
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
||||||
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
||||||
|
@ -282,6 +302,8 @@ GLTFFileWriter::GLTFFileWriter(MeshResultContext &resultContext, const QString &
|
||||||
}
|
}
|
||||||
m_json["bufferViews"][bufferViewIndex]["byteLength"] = binaries.size() - bufferViewFromOffset;
|
m_json["bufferViews"][bufferViewIndex]["byteLength"] = binaries.size() - bufferViewFromOffset;
|
||||||
alignBinaries();
|
alignBinaries();
|
||||||
|
if (m_enableComment)
|
||||||
|
m_json["accessors"][bufferViewIndex]["__comment"] = QString("/accessors/%1: uv").arg(QString::number(bufferViewIndex)).toUtf8().constData();
|
||||||
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
m_json["accessors"][bufferViewIndex]["bufferView"] = bufferViewIndex;
|
||||||
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
m_json["accessors"][bufferViewIndex]["byteOffset"] = 0;
|
||||||
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
m_json["accessors"][bufferViewIndex]["componentType"] = 5126;
|
||||||
|
|
|
@ -36,8 +36,11 @@ private:
|
||||||
QString getMatrixStringInColumnOrder(const QMatrix4x4 &mat);
|
QString getMatrixStringInColumnOrder(const QMatrix4x4 &mat);
|
||||||
QString m_filename;
|
QString m_filename;
|
||||||
QString m_textureFilename;
|
QString m_textureFilename;
|
||||||
|
bool m_outputNormal;
|
||||||
private:
|
private:
|
||||||
nlohmann::json m_json;
|
nlohmann::json m_json;
|
||||||
|
public:
|
||||||
|
static bool m_enableComment;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
#include "intermediateboneremover.h"
|
||||||
|
|
||||||
|
void IntermediateBoneRemover::addEdge(int fromPartId, int fromNodeId, int toPartId, int toNodeId)
|
||||||
|
{
|
||||||
|
auto &neighborMap = m_neighborMap[std::make_pair(fromPartId, fromNodeId)];
|
||||||
|
neighborMap.push_back(std::make_pair(toPartId, toNodeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::map<std::pair<int, int>, IntermediateBoneNode> &IntermediateBoneRemover::intermediateNodes()
|
||||||
|
{
|
||||||
|
return m_intermediateNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::tuple<int, int, int, int>> &IntermediateBoneRemover::newEdges()
|
||||||
|
{
|
||||||
|
return m_newEdges;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntermediateBoneRemover::markNodeAsStart(int partId, int nodeId)
|
||||||
|
{
|
||||||
|
m_startNodeSet.insert(std::make_pair(partId, nodeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntermediateBoneRemover::markNodeAsEssential(int partId, int nodeId)
|
||||||
|
{
|
||||||
|
m_essentialNodeSet.insert(std::make_pair(partId, nodeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntermediateBoneRemover::solveFrom(int partId, int nodeId)
|
||||||
|
{
|
||||||
|
std::pair<int, int> pair = std::make_pair(partId, nodeId);
|
||||||
|
std::vector<std::pair<int, int>> trace;
|
||||||
|
solveFromPairAndSaveTraceTo(pair, trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntermediateBoneRemover::addNeighborsOfIntermediateNodeFrom(std::pair<int, int> node, const IntermediateBoneNode &source)
|
||||||
|
{
|
||||||
|
if (m_addedSet.find(node) != m_addedSet.end())
|
||||||
|
return;
|
||||||
|
m_addedSet.insert(node);
|
||||||
|
if (m_essentialNodeSet.find(node) != m_essentialNodeSet.end() ||
|
||||||
|
m_startNodeSet.find(node) != m_startNodeSet.end())
|
||||||
|
return;
|
||||||
|
IntermediateBoneNode intermediate = source;
|
||||||
|
intermediate.partId = node.first;
|
||||||
|
intermediate.nodeId = node.second;
|
||||||
|
m_intermediateNodes[std::make_pair(intermediate.partId, intermediate.nodeId)] = intermediate;
|
||||||
|
const auto &it = m_neighborMap.find(node);
|
||||||
|
if (it == m_neighborMap.end())
|
||||||
|
return;
|
||||||
|
for (const auto &neighbor: it->second) {
|
||||||
|
addNeighborsOfIntermediateNodeFrom(neighbor, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntermediateBoneRemover::solveFromPairAndSaveTraceTo(std::pair<int, int> node, std::vector<std::pair<int, int>> &history)
|
||||||
|
{
|
||||||
|
if (m_solvedSet.find(node) != m_solvedSet.end())
|
||||||
|
return;
|
||||||
|
m_solvedSet.insert(node);
|
||||||
|
if (m_essentialNodeSet.find(node) != m_essentialNodeSet.end()) {
|
||||||
|
for (int i = history.size() - 1; i >= 0; i--) {
|
||||||
|
if (m_essentialNodeSet.find(history[i]) != m_essentialNodeSet.end() ||
|
||||||
|
m_startNodeSet.find(history[i]) != m_startNodeSet.end()) {
|
||||||
|
IntermediateBoneNode intermediate;
|
||||||
|
intermediate.attachedFromPartId = history[i].first;
|
||||||
|
intermediate.attachedFromNodeId = history[i].second;
|
||||||
|
intermediate.attachedToPartId = node.first;
|
||||||
|
intermediate.attachedToNodeId = node.second;
|
||||||
|
int removedNodeNum = 0;
|
||||||
|
for (int j = i + 1; j <= (int)history.size() - 1; j++) {
|
||||||
|
intermediate.partId = history[j].first;
|
||||||
|
intermediate.nodeId = history[j].second;
|
||||||
|
removedNodeNum++;
|
||||||
|
m_intermediateNodes[std::make_pair(intermediate.partId, intermediate.nodeId)] = intermediate;
|
||||||
|
addNeighborsOfIntermediateNodeFrom(std::make_pair(intermediate.partId, intermediate.nodeId), intermediate);
|
||||||
|
}
|
||||||
|
if (removedNodeNum > 0) {
|
||||||
|
m_newEdges.push_back(std::make_tuple(intermediate.attachedFromPartId,
|
||||||
|
intermediate.attachedFromNodeId,
|
||||||
|
intermediate.attachedToPartId,
|
||||||
|
intermediate.attachedToNodeId));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
history.push_back(node);
|
||||||
|
const auto &it = m_neighborMap.find(node);
|
||||||
|
if (it == m_neighborMap.end())
|
||||||
|
return;
|
||||||
|
for (const auto &neighbor: it->second) {
|
||||||
|
std::vector<std::pair<int, int>> subHistory = history;
|
||||||
|
solveFromPairAndSaveTraceTo(neighbor, subHistory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef INTERMEDIATE_BONE_REMOVER_H
|
||||||
|
#define INTERMEDIATE_BONE_REMOVER_H
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
struct IntermediateBoneNode
|
||||||
|
{
|
||||||
|
int partId;
|
||||||
|
int nodeId;
|
||||||
|
int attachedFromPartId;
|
||||||
|
int attachedFromNodeId;
|
||||||
|
int attachedToPartId;
|
||||||
|
int attachedToNodeId;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IntermediateBoneRemover
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void addEdge(int fromPartId, int fromNodeId, int toPartId, int toNodeId);
|
||||||
|
void markNodeAsStart(int partId, int nodeId);
|
||||||
|
void markNodeAsEssential(int partId, int nodeId);
|
||||||
|
void solveFrom(int partId, int nodeId);
|
||||||
|
const std::map<std::pair<int, int>, IntermediateBoneNode> &intermediateNodes();
|
||||||
|
const std::vector<std::tuple<int, int, int, int>> &newEdges();
|
||||||
|
private:
|
||||||
|
void solveFromPairAndSaveTraceTo(std::pair<int, int> node, std::vector<std::pair<int, int>> &history);
|
||||||
|
void addNeighborsOfIntermediateNodeFrom(std::pair<int, int> node, const IntermediateBoneNode &source);
|
||||||
|
std::map<std::pair<int, int>, IntermediateBoneNode> m_intermediateNodes;
|
||||||
|
std::set<std::pair<int, int>> m_startNodeSet;
|
||||||
|
std::set<std::pair<int, int>> m_essentialNodeSet;
|
||||||
|
std::map<std::pair<int, int>, std::vector<std::pair<int, int>>> m_neighborMap;
|
||||||
|
std::set<std::pair<int, int>> m_solvedSet;
|
||||||
|
std::vector<std::tuple<int, int, int, int>> m_newEdges;
|
||||||
|
std::set<std::pair<int, int>> m_addedSet;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -401,6 +401,7 @@ const std::map<std::pair<int, int>, std::vector<std::pair<int, int>>> &MeshResul
|
||||||
|
|
||||||
void MeshResultContext::calculateBmeshNodeNeighbors(std::map<std::pair<int, int>, std::vector<std::pair<int, int>>> &nodeNeighbors)
|
void MeshResultContext::calculateBmeshNodeNeighbors(std::map<std::pair<int, int>, std::vector<std::pair<int, int>>> &nodeNeighbors)
|
||||||
{
|
{
|
||||||
|
nodeNeighbors.clear();
|
||||||
for (const auto &it: bmeshEdges) {
|
for (const auto &it: bmeshEdges) {
|
||||||
nodeNeighbors[std::make_pair(it.fromBmeshId, it.fromNodeId)].push_back(std::make_pair(it.toBmeshId, it.toNodeId));
|
nodeNeighbors[std::make_pair(it.fromBmeshId, it.fromNodeId)].push_back(std::make_pair(it.toBmeshId, it.toNodeId));
|
||||||
nodeNeighbors[std::make_pair(it.toBmeshId, it.toNodeId)].push_back(std::make_pair(it.fromBmeshId, it.fromNodeId));
|
nodeNeighbors[std::make_pair(it.toBmeshId, it.toNodeId)].push_back(std::make_pair(it.fromBmeshId, it.fromNodeId));
|
||||||
|
@ -459,7 +460,7 @@ const std::vector<std::vector<ResultVertexWeight>> &MeshResultContext::vertexWei
|
||||||
return m_resultVertexWeights;
|
return m_resultVertexWeights;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshResultContext::calculateVertexWeights(std::vector<std::vector<ResultVertexWeight>> &vertexWeights)
|
void MeshResultContext::calculateVertexWeights(std::vector<std::vector<ResultVertexWeight>> &vertexWeights, const std::map<std::pair<int, int>, IntermediateBoneNode> *intermediateNodes)
|
||||||
{
|
{
|
||||||
vertexWeights.clear();
|
vertexWeights.clear();
|
||||||
vertexWeights.resize(vertices.size());
|
vertexWeights.resize(vertices.size());
|
||||||
|
@ -493,6 +494,48 @@ void MeshResultContext::calculateVertexWeights(std::vector<std::vector<ResultVer
|
||||||
it[i].weight = (float)it[i].count / total;
|
it[i].weight = (float)it[i].count / total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (nullptr != intermediateNodes) {
|
||||||
|
// We removed some intermediate nodes, so we should recalculate the vertex weights.
|
||||||
|
for (auto &it: vertexWeights) {
|
||||||
|
std::vector<std::pair<std::pair<int, int>, float>> weights;
|
||||||
|
for (auto i = 0u; i < it.size(); i++) {
|
||||||
|
const auto &findInter = intermediateNodes->find(it[i].sourceNode);
|
||||||
|
if (findInter != intermediateNodes->end()) {
|
||||||
|
const auto &interBmeshNode = bmeshNodeMap().find(findInter->first);
|
||||||
|
const auto &attachedFromBmeshNode = bmeshNodeMap().find(std::make_pair(findInter->second.attachedFromPartId, findInter->second.attachedFromNodeId));
|
||||||
|
const auto &attachedToBmeshNode = bmeshNodeMap().find(std::make_pair(findInter->second.attachedToPartId, findInter->second.attachedToNodeId));
|
||||||
|
if (interBmeshNode != bmeshNodeMap().end() &&
|
||||||
|
attachedFromBmeshNode != bmeshNodeMap().end() &&
|
||||||
|
attachedToBmeshNode != bmeshNodeMap().end()) {
|
||||||
|
float distWithFrom = interBmeshNode->second->origin.distanceToPoint(attachedFromBmeshNode->second->origin);
|
||||||
|
float distWithTo = interBmeshNode->second->origin.distanceToPoint(attachedToBmeshNode->second->origin);
|
||||||
|
float distTotal = distWithFrom + distWithTo;
|
||||||
|
if (distTotal > 0) {
|
||||||
|
weights.push_back(std::make_pair(attachedFromBmeshNode->first, it[i].weight * distWithFrom / distTotal));
|
||||||
|
weights.push_back(std::make_pair(attachedToBmeshNode->first, it[i].weight * distWithTo / distTotal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
weights.push_back(std::make_pair(it[i].sourceNode, it[i].weight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(weights.begin(), weights.end(), [](const std::pair<std::pair<int, int>, float> &a, const std::pair<std::pair<int, int>, float> &b) -> bool {
|
||||||
|
return a.second > b.second;
|
||||||
|
});
|
||||||
|
float total = 0;
|
||||||
|
for (auto i = 0u; i < MAX_WEIGHT_NUM && i < weights.size(); i++) {
|
||||||
|
total += weights[i].second;
|
||||||
|
}
|
||||||
|
for (auto i = 0u; i < MAX_WEIGHT_NUM && i < weights.size(); i++) {
|
||||||
|
weights[i].second = weights[i].second / total;
|
||||||
|
}
|
||||||
|
for (auto i = 0u; i < MAX_WEIGHT_NUM && i < weights.size(); i++) {
|
||||||
|
it[i].sourceNode = weights[i].first;
|
||||||
|
it[i].weight = weights[i].second;
|
||||||
|
it[i].count = -1; // no use
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<int, ResultPart> &MeshResultContext::parts()
|
const std::map<int, ResultPart> &MeshResultContext::parts()
|
||||||
|
@ -716,3 +759,46 @@ void MeshResultContext::calculateResultRearrangedVertices(std::vector<ResultRear
|
||||||
rearrangedTriangles.push_back(newTriangle);
|
rearrangedTriangles.push_back(newTriangle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MeshResultContext::removeIntermediateBones()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_vertexWeightsResolved);
|
||||||
|
Q_ASSERT(m_bmeshNodeNeighborsResolved);
|
||||||
|
IntermediateBoneRemover remover;
|
||||||
|
for (const auto &edge: bmeshEdges) {
|
||||||
|
remover.addEdge(edge.fromBmeshId, edge.fromNodeId, edge.toBmeshId, edge.toNodeId);
|
||||||
|
}
|
||||||
|
for (const auto &node: bmeshNodes) {
|
||||||
|
if (SkeletonBoneMarkIsStart(node.boneMark)) {
|
||||||
|
remover.markNodeAsStart(node.bmeshId, node.nodeId);
|
||||||
|
} else if (SkeletonBoneMark::None != node.boneMark) {
|
||||||
|
remover.markNodeAsEssential(node.bmeshId, node.nodeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const BmeshNode *centerNode = centerBmeshNode();
|
||||||
|
if (nullptr == centerNode)
|
||||||
|
return;
|
||||||
|
remover.solveFrom(centerNode->bmeshId, centerNode->nodeId);
|
||||||
|
|
||||||
|
const auto &intermediateNodes = remover.intermediateNodes();
|
||||||
|
|
||||||
|
calculateVertexWeights(m_resultVertexWeights, &intermediateNodes);
|
||||||
|
|
||||||
|
const auto oldEdges = bmeshEdges;
|
||||||
|
bmeshEdges.clear();
|
||||||
|
for (const auto &old: oldEdges) {
|
||||||
|
if (intermediateNodes.find(std::make_pair(old.fromBmeshId, old.fromNodeId)) != intermediateNodes.end() ||
|
||||||
|
intermediateNodes.find(std::make_pair(old.toBmeshId, old.toNodeId)) != intermediateNodes.end())
|
||||||
|
continue;
|
||||||
|
bmeshEdges.push_back(old);
|
||||||
|
}
|
||||||
|
for (const auto &edge: remover.newEdges()) {
|
||||||
|
BmeshEdge newEdge;
|
||||||
|
newEdge.fromBmeshId = std::get<0>(edge);
|
||||||
|
newEdge.fromNodeId = std::get<1>(edge);
|
||||||
|
newEdge.toBmeshId = std::get<2>(edge);
|
||||||
|
newEdge.toNodeId = std::get<3>(edge);
|
||||||
|
bmeshEdges.push_back(newEdge);
|
||||||
|
}
|
||||||
|
calculateBmeshNodeNeighbors(m_nodeNeighbors);
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include "positionmap.h"
|
#include "positionmap.h"
|
||||||
#include "skeletonbonemark.h"
|
#include "skeletonbonemark.h"
|
||||||
|
#include "intermediateboneremover.h"
|
||||||
|
|
||||||
#define MAX_WEIGHT_NUM 4
|
#define MAX_WEIGHT_NUM 4
|
||||||
|
|
||||||
|
@ -117,6 +118,7 @@ public:
|
||||||
const std::vector<ResultTriangleUv> &triangleUvs();
|
const std::vector<ResultTriangleUv> &triangleUvs();
|
||||||
const std::vector<ResultRearrangedVertex> &rearrangedVertices();
|
const std::vector<ResultRearrangedVertex> &rearrangedVertices();
|
||||||
const std::vector<ResultRearrangedTriangle> &rearrangedTriangles();
|
const std::vector<ResultRearrangedTriangle> &rearrangedTriangles();
|
||||||
|
void removeIntermediateBones();
|
||||||
private:
|
private:
|
||||||
bool m_triangleSourceResolved;
|
bool m_triangleSourceResolved;
|
||||||
bool m_triangleColorResolved;
|
bool m_triangleColorResolved;
|
||||||
|
@ -154,7 +156,7 @@ private:
|
||||||
void calculateBmeshNodeNeighbors();
|
void calculateBmeshNodeNeighbors();
|
||||||
void calculateBmeshEdgeDirectionsFromNode(std::pair<int, int> node, std::set<std::pair<int, int>> &visitedNodes, std::set<std::pair<std::pair<int, int>, std::pair<int, int>>> &connections, std::vector<BmeshEdge> &rearrangedEdges);
|
void calculateBmeshEdgeDirectionsFromNode(std::pair<int, int> node, std::set<std::pair<int, int>> &visitedNodes, std::set<std::pair<std::pair<int, int>, std::pair<int, int>>> &connections, std::vector<BmeshEdge> &rearrangedEdges);
|
||||||
void calculateBmeshNodeNeighbors(std::map<std::pair<int, int>, std::vector<std::pair<int, int>>> &nodeNeighbors);
|
void calculateBmeshNodeNeighbors(std::map<std::pair<int, int>, std::vector<std::pair<int, int>>> &nodeNeighbors);
|
||||||
void calculateVertexWeights(std::vector<std::vector<ResultVertexWeight>> &vertexWeights);
|
void calculateVertexWeights(std::vector<std::vector<ResultVertexWeight>> &vertexWeights, const std::map<std::pair<int, int>, IntermediateBoneNode> *intermediateNodes=nullptr);
|
||||||
void calculateResultParts(std::map<int, ResultPart> &parts);
|
void calculateResultParts(std::map<int, ResultPart> &parts);
|
||||||
void calculateResultTriangleUvs(std::vector<ResultTriangleUv> &uvs, std::set<int> &seamVertices);
|
void calculateResultTriangleUvs(std::vector<ResultTriangleUv> &uvs, std::set<int> &seamVertices);
|
||||||
void calculateResultRearrangedVertices(std::vector<ResultRearrangedVertex> &rearrangedVertices, std::vector<ResultRearrangedTriangle> &rearrangedTriangles);
|
void calculateResultRearrangedVertices(std::vector<ResultRearrangedVertex> &rearrangedVertices, std::vector<ResultRearrangedTriangle> &rearrangedTriangles);
|
||||||
|
|
|
@ -24,6 +24,8 @@ void MeshResultPostProcessor::process()
|
||||||
if (!m_meshResultContext->bmeshNodes.empty()) {
|
if (!m_meshResultContext->bmeshNodes.empty()) {
|
||||||
m_meshResultContext->resolveBmeshConnectivity();
|
m_meshResultContext->resolveBmeshConnectivity();
|
||||||
m_meshResultContext->resolveBmeshEdgeDirections();
|
m_meshResultContext->resolveBmeshEdgeDirections();
|
||||||
|
m_meshResultContext->vertexWeights();
|
||||||
|
m_meshResultContext->removeIntermediateBones();
|
||||||
m_meshResultContext->rearrangedVertices();
|
m_meshResultContext->rearrangedVertices();
|
||||||
m_meshResultContext->rearrangedTriangles();
|
m_meshResultContext->rearrangedTriangles();
|
||||||
m_meshResultContext->parts();
|
m_meshResultContext->parts();
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue