Fix vertex source node resolving after remesh
parent
ec80f7bacd
commit
8775a09fa3
|
@ -1105,9 +1105,6 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
|
||||||
m_clothCollisionVertices.clear();
|
m_clothCollisionVertices.clear();
|
||||||
m_clothCollisionTriangles.clear();
|
m_clothCollisionTriangles.clear();
|
||||||
mesh->fetch(m_clothCollisionVertices, m_clothCollisionTriangles);
|
mesh->fetch(m_clothCollisionVertices, m_clothCollisionTriangles);
|
||||||
buildClothTargetNodes(componentCache.outcomeNodes,
|
|
||||||
componentCache.outcomeEdges,
|
|
||||||
&m_clothTargetNodes);
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: when no body is valid, may add ground plane as collision shape
|
// TODO: when no body is valid, may add ground plane as collision shape
|
||||||
// ... ...
|
// ... ...
|
||||||
|
@ -1124,7 +1121,12 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
|
||||||
std::vector<QVector3D> newVertices;
|
std::vector<QVector3D> newVertices;
|
||||||
std::vector<std::vector<size_t>> newQuads;
|
std::vector<std::vector<size_t>> newQuads;
|
||||||
std::vector<std::vector<size_t>> newTriangles;
|
std::vector<std::vector<size_t>> newTriangles;
|
||||||
|
std::vector<std::tuple<QVector3D, float, size_t>> interpolatedNodes;
|
||||||
|
buildInterpolatedNodes(componentCache.outcomeNodes,
|
||||||
|
componentCache.outcomeEdges,
|
||||||
|
&interpolatedNodes);
|
||||||
remesh(componentCache.outcomeNodes,
|
remesh(componentCache.outcomeNodes,
|
||||||
|
interpolatedNodes,
|
||||||
combinedVertices,
|
combinedVertices,
|
||||||
combinedFaces,
|
combinedFaces,
|
||||||
polyCountValue,
|
polyCountValue,
|
||||||
|
@ -1167,16 +1169,16 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshGenerator::buildClothTargetNodes(const std::vector<OutcomeNode> &nodes,
|
void MeshGenerator::buildInterpolatedNodes(const std::vector<OutcomeNode> &nodes,
|
||||||
const std::vector<std::pair<std::pair<QUuid, QUuid>, std::pair<QUuid, QUuid>>> &edges,
|
const std::vector<std::pair<std::pair<QUuid, QUuid>, std::pair<QUuid, QUuid>>> &edges,
|
||||||
std::vector<std::pair<QVector3D, float>> *targetNodes)
|
std::vector<std::tuple<QVector3D, float, size_t>> *targetNodes)
|
||||||
{
|
{
|
||||||
targetNodes->clear();
|
targetNodes->clear();
|
||||||
std::map<std::pair<QUuid, QUuid>, size_t> nodeMap;
|
std::map<std::pair<QUuid, QUuid>, size_t> nodeMap;
|
||||||
for (size_t nodeIndex = 0; nodeIndex < nodes.size(); ++nodeIndex) {
|
for (size_t nodeIndex = 0; nodeIndex < nodes.size(); ++nodeIndex) {
|
||||||
const auto &it = nodes[nodeIndex];
|
const auto &it = nodes[nodeIndex];
|
||||||
nodeMap.insert({{it.partId, it.nodeId}, nodeIndex});
|
nodeMap.insert({{it.partId, it.nodeId}, nodeIndex});
|
||||||
targetNodes->push_back(std::make_pair(it.origin, it.radius * 3.0f));
|
targetNodes->push_back(std::make_tuple(it.origin, it.radius, nodeIndex));
|
||||||
}
|
}
|
||||||
for (const auto &it: edges) {
|
for (const auto &it: edges) {
|
||||||
auto findFirst = nodeMap.find(it.first);
|
auto findFirst = nodeMap.find(it.first);
|
||||||
|
@ -1197,9 +1199,10 @@ void MeshGenerator::buildClothTargetNodes(const std::vector<OutcomeNode> &nodes,
|
||||||
float offset = segmentLength;
|
float offset = segmentLength;
|
||||||
while (offset < 1.0f) {
|
while (offset < 1.0f) {
|
||||||
float radius = firstNode.radius * (1.0f - offset) + secondNode.radius * offset;
|
float radius = firstNode.radius * (1.0f - offset) + secondNode.radius * offset;
|
||||||
targetNodes->push_back(std::make_pair(
|
targetNodes->push_back(std::make_tuple(
|
||||||
firstNode.origin * (1.0f - offset) + secondNode.origin * offset,
|
firstNode.origin * (1.0f - offset) + secondNode.origin * offset,
|
||||||
radius * 3.0
|
radius * 3.0,
|
||||||
|
offset <= 0.5 ? findFirst->second : findSecond->second
|
||||||
));
|
));
|
||||||
offset += segmentLength;
|
offset += segmentLength;
|
||||||
}
|
}
|
||||||
|
@ -1587,6 +1590,7 @@ void MeshGenerator::generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshGenerator::remesh(const std::vector<OutcomeNode> &inputNodes,
|
void MeshGenerator::remesh(const std::vector<OutcomeNode> &inputNodes,
|
||||||
|
const std::vector<std::tuple<QVector3D, float, size_t>> &interpolatedNodes,
|
||||||
const std::vector<QVector3D> &inputVertices,
|
const std::vector<QVector3D> &inputVertices,
|
||||||
const std::vector<std::vector<size_t>> &inputFaces,
|
const std::vector<std::vector<size_t>> &inputFaces,
|
||||||
float targetVertexMultiplyFactor,
|
float targetVertexMultiplyFactor,
|
||||||
|
@ -1597,11 +1601,12 @@ void MeshGenerator::remesh(const std::vector<OutcomeNode> &inputNodes,
|
||||||
{
|
{
|
||||||
std::vector<std::pair<QVector3D, float>> nodes;
|
std::vector<std::pair<QVector3D, float>> nodes;
|
||||||
std::vector<std::pair<QUuid, QUuid>> sourceIds;
|
std::vector<std::pair<QUuid, QUuid>> sourceIds;
|
||||||
nodes.reserve(inputNodes.size());
|
nodes.reserve(interpolatedNodes.size());
|
||||||
sourceIds.reserve(inputNodes.size());
|
sourceIds.reserve(interpolatedNodes.size());
|
||||||
for (const auto &it: inputNodes) {
|
for (const auto &it: interpolatedNodes) {
|
||||||
nodes.push_back(std::make_pair(it.origin, it.radius));
|
nodes.push_back(std::make_pair(std::get<0>(it), std::get<1>(it)));
|
||||||
sourceIds.push_back(std::make_pair(it.partId, it.nodeId));
|
const auto &sourceNode = inputNodes[std::get<2>(it)];
|
||||||
|
sourceIds.push_back(std::make_pair(sourceNode.partId, sourceNode.nodeId));
|
||||||
}
|
}
|
||||||
Remesher remesher;
|
Remesher remesher;
|
||||||
remesher.setMesh(inputVertices, inputFaces);
|
remesher.setMesh(inputVertices, inputFaces);
|
||||||
|
@ -1699,7 +1704,7 @@ void MeshGenerator::collectClothComponentIdStrings(const QString &componentIdStr
|
||||||
|
|
||||||
void MeshGenerator::collectClothComponent(const QString &componentIdString)
|
void MeshGenerator::collectClothComponent(const QString &componentIdString)
|
||||||
{
|
{
|
||||||
if (m_clothCollisionTriangles.empty() || m_clothTargetNodes.empty())
|
if (m_clothCollisionTriangles.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<QString> componentIdStrings;
|
std::vector<QString> componentIdStrings;
|
||||||
|
@ -1723,8 +1728,7 @@ void MeshGenerator::collectClothComponent(const QString &componentIdString)
|
||||||
}
|
}
|
||||||
simulateClothMeshes(&clothMeshes,
|
simulateClothMeshes(&clothMeshes,
|
||||||
&m_clothCollisionVertices,
|
&m_clothCollisionVertices,
|
||||||
&m_clothCollisionTriangles,
|
&m_clothCollisionTriangles);
|
||||||
&m_clothTargetNodes);
|
|
||||||
for (auto &clothMesh: clothMeshes) {
|
for (auto &clothMesh: clothMeshes) {
|
||||||
auto vertexStartIndex = m_outcome->vertices.size();
|
auto vertexStartIndex = m_outcome->vertices.size();
|
||||||
auto updateVertexIndices = [=](std::vector<std::vector<size_t>> &faces) {
|
auto updateVertexIndices = [=](std::vector<std::vector<size_t>> &faces) {
|
||||||
|
|
|
@ -106,7 +106,6 @@ private:
|
||||||
quint64 m_id = 0;
|
quint64 m_id = 0;
|
||||||
std::vector<QVector3D> m_clothCollisionVertices;
|
std::vector<QVector3D> m_clothCollisionVertices;
|
||||||
std::vector<std::vector<size_t>> m_clothCollisionTriangles;
|
std::vector<std::vector<size_t>> m_clothCollisionTriangles;
|
||||||
std::vector<std::pair<QVector3D, float>> m_clothTargetNodes;
|
|
||||||
|
|
||||||
void collectParts();
|
void collectParts();
|
||||||
bool checkIsComponentDirty(const QString &componentIdString);
|
bool checkIsComponentDirty(const QString &componentIdString);
|
||||||
|
@ -142,6 +141,7 @@ private:
|
||||||
std::vector<QString> *componentIdStrings);
|
std::vector<QString> *componentIdStrings);
|
||||||
void cutFaceStringToCutTemplate(const QString &cutFaceString, std::vector<QVector2D> &cutTemplate);
|
void cutFaceStringToCutTemplate(const QString &cutFaceString, std::vector<QVector2D> &cutTemplate);
|
||||||
void remesh(const std::vector<OutcomeNode> &inputNodes,
|
void remesh(const std::vector<OutcomeNode> &inputNodes,
|
||||||
|
const std::vector<std::tuple<QVector3D, float, size_t>> &interpolatedNodes,
|
||||||
const std::vector<QVector3D> &inputVertices,
|
const std::vector<QVector3D> &inputVertices,
|
||||||
const std::vector<std::vector<size_t>> &inputFaces,
|
const std::vector<std::vector<size_t>> &inputFaces,
|
||||||
float targetVertexMultiplyFactor,
|
float targetVertexMultiplyFactor,
|
||||||
|
@ -149,9 +149,9 @@ private:
|
||||||
std::vector<std::vector<size_t>> *outputQuads,
|
std::vector<std::vector<size_t>> *outputQuads,
|
||||||
std::vector<std::vector<size_t>> *outputTriangles,
|
std::vector<std::vector<size_t>> *outputTriangles,
|
||||||
std::vector<std::pair<QVector3D, std::pair<QUuid, QUuid>>> *outputNodeVertices);
|
std::vector<std::pair<QVector3D, std::pair<QUuid, QUuid>>> *outputNodeVertices);
|
||||||
void buildClothTargetNodes(const std::vector<OutcomeNode> &nodes,
|
void buildInterpolatedNodes(const std::vector<OutcomeNode> &nodes,
|
||||||
const std::vector<std::pair<std::pair<QUuid, QUuid>, std::pair<QUuid, QUuid>>> &edges,
|
const std::vector<std::pair<std::pair<QUuid, QUuid>, std::pair<QUuid, QUuid>>> &edges,
|
||||||
std::vector<std::pair<QVector3D, float>> *targetNodes);
|
std::vector<std::tuple<QVector3D, float, size_t>> *targetNodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -383,7 +383,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted)
|
||||||
std::vector<QUuid> componentIds = collectSelectedComponentIds(pos);
|
std::vector<QUuid> componentIds = collectSelectedComponentIds(pos);
|
||||||
|
|
||||||
if (shorted) {
|
if (shorted) {
|
||||||
if (componentIds.size() != 1)
|
if (componentIds.size() > 1)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ void projectFacesToNodes(const std::vector<QVector3D> &vertices,
|
||||||
const std::vector<std::pair<QVector3D, float>> &sourceNodes,
|
const std::vector<std::pair<QVector3D, float>> &sourceNodes,
|
||||||
std::vector<size_t> *faceSources)
|
std::vector<size_t> *faceSources)
|
||||||
{
|
{
|
||||||
faceSources->resize(faces.size());
|
faceSources->resize(faces.size(), std::numeric_limits<size_t>::max());
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, faces.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, faces.size()),
|
||||||
FacesToNodesProjector(&vertices, &faces, &sourceNodes, faceSources));
|
FacesToNodesProjector(&vertices, &faces, &sourceNodes, faceSources));
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,8 @@ void Remesher::resolveSources()
|
||||||
for (size_t i = 0; i < m_remeshedFaces.size(); ++i) {
|
for (size_t i = 0; i < m_remeshedFaces.size(); ++i) {
|
||||||
const auto &face = m_remeshedFaces[i];
|
const auto &face = m_remeshedFaces[i];
|
||||||
const auto &source = faceSources[i];
|
const auto &source = faceSources[i];
|
||||||
|
if (source >= m_nodes.size())
|
||||||
|
continue;
|
||||||
for (const auto &vertexIndex: face)
|
for (const auto &vertexIndex: face)
|
||||||
vertexToNodeVotes[vertexIndex][source]++;
|
vertexToNodeVotes[vertexIndex][source]++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,10 @@ class ClothMeshesSimulator
|
||||||
public:
|
public:
|
||||||
ClothMeshesSimulator(std::vector<ClothMesh> *clothMeshes,
|
ClothMeshesSimulator(std::vector<ClothMesh> *clothMeshes,
|
||||||
const std::vector<QVector3D> *clothCollisionVertices,
|
const std::vector<QVector3D> *clothCollisionVertices,
|
||||||
const std::vector<std::vector<size_t>> *clothCollisionTriangles,
|
const std::vector<std::vector<size_t>> *clothCollisionTriangles) :
|
||||||
const std::vector<std::pair<QVector3D, float>> *clothTargetNodes) :
|
|
||||||
m_clothMeshes(clothMeshes),
|
m_clothMeshes(clothMeshes),
|
||||||
m_clothCollisionVertices(clothCollisionVertices),
|
m_clothCollisionVertices(clothCollisionVertices),
|
||||||
m_clothCollisionTriangles(clothCollisionTriangles),
|
m_clothCollisionTriangles(clothCollisionTriangles)
|
||||||
m_clothTargetNodes(clothTargetNodes)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void simulate(ClothMesh *clothMesh) const
|
void simulate(ClothMesh *clothMesh) const
|
||||||
|
@ -77,17 +75,14 @@ private:
|
||||||
std::vector<ClothMesh> *m_clothMeshes = nullptr;
|
std::vector<ClothMesh> *m_clothMeshes = nullptr;
|
||||||
const std::vector<QVector3D> *m_clothCollisionVertices = nullptr;
|
const std::vector<QVector3D> *m_clothCollisionVertices = nullptr;
|
||||||
const std::vector<std::vector<size_t>> *m_clothCollisionTriangles = nullptr;
|
const std::vector<std::vector<size_t>> *m_clothCollisionTriangles = nullptr;
|
||||||
const std::vector<std::pair<QVector3D, float>> *m_clothTargetNodes = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void simulateClothMeshes(std::vector<ClothMesh> *clothMeshes,
|
void simulateClothMeshes(std::vector<ClothMesh> *clothMeshes,
|
||||||
const std::vector<QVector3D> *clothCollisionVertices,
|
const std::vector<QVector3D> *clothCollisionVertices,
|
||||||
const std::vector<std::vector<size_t>> *clothCollisionTriangles,
|
const std::vector<std::vector<size_t>> *clothCollisionTriangles)
|
||||||
const std::vector<std::pair<QVector3D, float>> *clothTargetNodes)
|
|
||||||
{
|
{
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, clothMeshes->size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, clothMeshes->size()),
|
||||||
ClothMeshesSimulator(clothMeshes,
|
ClothMeshesSimulator(clothMeshes,
|
||||||
clothCollisionVertices,
|
clothCollisionVertices,
|
||||||
clothCollisionTriangles,
|
clothCollisionTriangles));
|
||||||
clothTargetNodes));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ struct ClothMesh
|
||||||
|
|
||||||
void simulateClothMeshes(std::vector<ClothMesh> *clothMeshes,
|
void simulateClothMeshes(std::vector<ClothMesh> *clothMeshes,
|
||||||
const std::vector<QVector3D> *clothCollisionVertices,
|
const std::vector<QVector3D> *clothCollisionVertices,
|
||||||
const std::vector<std::vector<size_t>> *clothCollisionTriangles,
|
const std::vector<std::vector<size_t>> *clothCollisionTriangles);
|
||||||
const std::vector<std::pair<QVector3D, float>> *clothTargetNodes);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue