Fallback to uncombined when component mesh is not combinable [skip ci]

master
huxingyi 2020-04-11 16:23:12 +09:30
parent a7730884b2
commit 082b5ea1f1
4 changed files with 90 additions and 45 deletions

View File

@ -23,10 +23,11 @@ MeshCombiner::Mesh::Mesh(const std::vector<QVector3D> &vertices, const std::vect
} else {
if (CGAL::Polygon_mesh_processing::triangulate_faces(*cgalMesh)) {
if (CGAL::Polygon_mesh_processing::does_self_intersect(*cgalMesh)) {
m_isSelfIntersected = true;
qDebug() << "Mesh does_self_intersect";
delete cgalMesh;
cgalMesh = nullptr;
} else {
m_isCombinable = true;
}
} else {
qDebug() << "Mesh triangulate failed";
@ -43,7 +44,7 @@ MeshCombiner::Mesh::Mesh(const std::vector<QVector3D> &vertices, const std::vect
MeshCombiner::Mesh::Mesh(const Mesh &other)
{
if (other.m_privateData) {
m_isSelfIntersected = other.m_isSelfIntersected;
m_isCombinable = other.m_isCombinable;
m_privateData = new CgalMesh(*(CgalMesh *)other.m_privateData);
validate();
}
@ -69,21 +70,16 @@ bool MeshCombiner::Mesh::isNull() const
return nullptr == m_privateData;
}
bool MeshCombiner::Mesh::isSelfIntersected() const
bool MeshCombiner::Mesh::isCombinable() const
{
return m_isSelfIntersected;
}
void MeshCombiner::Mesh::markAsSelfIntersected()
{
m_isSelfIntersected = true;
return m_isCombinable;
}
MeshCombiner::Mesh *MeshCombiner::combine(const Mesh &firstMesh, const Mesh &secondMesh, Method method,
std::vector<std::pair<Source, size_t>> *combinedVerticesComeFrom)
{
if (firstMesh.isNull() || firstMesh.isSelfIntersected() ||
secondMesh.isNull() || secondMesh.isSelfIntersected())
if (firstMesh.isNull() || !firstMesh.isCombinable() ||
secondMesh.isNull() || !secondMesh.isCombinable())
return nullptr;
CgalMesh *resultCgalMesh = nullptr;
@ -157,9 +153,7 @@ MeshCombiner::Mesh *MeshCombiner::combine(const Mesh &firstMesh, const Mesh &sec
Mesh *mesh = new Mesh;
mesh->m_privateData = resultCgalMesh;
if (CGAL::Polygon_mesh_processing::does_self_intersect(*resultCgalMesh)) {
mesh->markAsSelfIntersected();
}
mesh->m_isCombinable = true;
return mesh;
}
@ -172,5 +166,6 @@ void MeshCombiner::Mesh::validate()
if (isNullCgalMesh<CgalKernel>(exactMesh)) {
delete exactMesh;
m_privateData = nullptr;
m_isCombinable = false;
}
}

View File

@ -28,14 +28,13 @@ public:
~Mesh();
void fetch(std::vector<QVector3D> &vertices, std::vector<std::vector<size_t>> &faces) const;
bool isNull() const;
bool isSelfIntersected() const;
void markAsSelfIntersected();
bool isCombinable() const;
friend MeshCombiner;
private:
void *m_privateData = nullptr;
bool m_isSelfIntersected = false;
bool m_isCombinable = false;
void validate();
};

View File

@ -1035,8 +1035,7 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
componentCache.outcomeEdges.clear();
componentCache.outcomeNodeVertices.clear();
componentCache.outcomePaintMaps.clear();
delete componentCache.mesh;
componentCache.mesh = nullptr;
componentCache.releaseMeshes();
QString linkDataType = valueOfKeyInMapOrEmpty(*component, "linkDataType");
if ("partId" == linkDataType) {
@ -1084,10 +1083,10 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
}
auto combineMode = componentCombineMode(child);
if (lastCombineMode != combineMode || lastCombineMode == CombineMode::Inversion) {
qDebug() << "New group[" << currentGroupIndex << "] for combine mode[" << CombineModeToString(combineMode) << "]";
combineGroups.push_back({combineMode, {}});
++currentGroupIndex;
lastCombineMode = combineMode;
qDebug() << "New group[" << currentGroupIndex << "] for combine mode[" << CombineModeToString(combineMode) << "]";
}
if (-1 == currentGroupIndex) {
qDebug() << "Should not happen: -1 == currentGroupIndex";
@ -1214,9 +1213,19 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
});
}
delete mesh;
mesh = nullptr;
bool disableSelfIntersectionTest = componentId.isNull() ||
CombineMode::Uncombined == componentCombineMode(component);
mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest);
if (!disableSelfIntersectionTest) {
if (isManifold(newTriangles)) {
mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest);
} else {
disableSelfIntersectionTest = true;
mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest);
}
} else {
mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest);
}
if (nullptr != mesh) {
if (!disableSelfIntersectionTest) {
if (mesh->isNull()) {
@ -1244,12 +1253,14 @@ MeshCombiner::Mesh *MeshGenerator::combineMultipleMeshes(const std::vector<std::
MeshCombiner::Mesh *subMesh = std::get<0>(it);
const QString &subMeshIdString = std::get<2>(it);
//qDebug() << "Combine mode:" << CombineModeToString(childCombineMode);
if (nullptr == subMesh) {
if (nullptr == subMesh || subMesh->isNull()) {
delete subMesh;
qDebug() << "Child mesh is null";
continue;
}
if (subMesh->isNull()) {
if (!subMesh->isCombinable()) {
qDebug() << "Child mesh is uncombinable";
// TODO: Collect vertices
delete subMesh;
continue;
}
@ -1330,6 +1341,11 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentChildGroupMesh(const std::vec
delete subMesh;
continue;
}
if (!subMesh->isCombinable()) {
componentCache.incombinableMeshes.push_back(subMesh);
continue;
}
multipleMeshes.push_back(std::make_tuple(subMesh, childCombineMode, childIdString));
}
@ -1359,7 +1375,7 @@ MeshCombiner::Mesh *MeshGenerator::combineTwoMeshes(const MeshCombiner::Mesh &fi
if (recombiner.recombine()) {
if (isManifold(recombiner.regeneratedFaces())) {
MeshCombiner::Mesh *reMesh = new MeshCombiner::Mesh(recombiner.regeneratedVertices(), recombiner.regeneratedFaces(), false);
if (!reMesh->isNull() && !reMesh->isSelfIntersected()) {
if (!reMesh->isNull() && reMesh->isCombinable()) {
delete newMesh;
newMesh = reMesh;
} else {
@ -1537,6 +1553,7 @@ void MeshGenerator::generate()
// Recursively check uncombined components
collectUncombinedComponent(QUuid().toString());
collectIncombinableComponentMeshes(QUuid().toString());
// Fetch nodes as body nodes before cloth nodes collecting
std::set<std::pair<QUuid, QUuid>> bodyNodeMap;
@ -1691,6 +1708,48 @@ void MeshGenerator::remesh(const std::vector<OutcomeNode> &inputNodes,
}
}
void MeshGenerator::collectIncombinableComponentMeshes(const QString &componentIdString)
{
const auto &componentCache = m_cacheContext->components[componentIdString];
for (const auto &mesh: componentCache.incombinableMeshes)
collectIncombinableMesh(mesh, componentCache);
const auto &component = findComponent(componentIdString);
for (const auto &childIdString: valueOfKeyInMapOrEmpty(*component, "children").split(",")) {
if (childIdString.isEmpty())
continue;
collectIncombinableComponentMeshes(childIdString);
}
}
void MeshGenerator::collectIncombinableMesh(const MeshCombiner::Mesh *mesh, const GeneratedComponent &componentCache)
{
if (nullptr == mesh)
return;
m_isSuccessful = false;
std::vector<QVector3D> uncombinedVertices;
std::vector<std::vector<size_t>> uncombinedFaces;
mesh->fetch(uncombinedVertices, uncombinedFaces);
std::vector<std::vector<size_t>> uncombinedTriangleAndQuads;
recoverQuads(uncombinedVertices, uncombinedFaces, componentCache.sharedQuadEdges, uncombinedTriangleAndQuads);
auto vertexStartIndex = m_outcome->vertices.size();
auto updateVertexIndices = [=](std::vector<std::vector<size_t>> &faces) {
for (auto &it: faces) {
for (auto &subIt: it)
subIt += vertexStartIndex;
}
};
updateVertexIndices(uncombinedFaces);
updateVertexIndices(uncombinedTriangleAndQuads);
m_outcome->vertices.insert(m_outcome->vertices.end(), uncombinedVertices.begin(), uncombinedVertices.end());
m_outcome->triangles.insert(m_outcome->triangles.end(), uncombinedFaces.begin(), uncombinedFaces.end());
m_outcome->triangleAndQuads.insert(m_outcome->triangleAndQuads.end(), uncombinedTriangleAndQuads.begin(), uncombinedTriangleAndQuads.end());
}
void MeshGenerator::collectUncombinedComponent(const QString &componentIdString)
{
const auto &component = findComponent(componentIdString);
@ -1708,26 +1767,7 @@ void MeshGenerator::collectUncombinedComponent(const QString &componentIdString)
m_outcome->nodeVertices.insert(m_outcome->nodeVertices.end(), componentCache.outcomeNodeVertices.begin(), componentCache.outcomeNodeVertices.end());
m_outcome->paintMaps.insert(m_outcome->paintMaps.end(), componentCache.outcomePaintMaps.begin(), componentCache.outcomePaintMaps.end());
std::vector<QVector3D> uncombinedVertices;
std::vector<std::vector<size_t>> uncombinedFaces;
componentCache.mesh->fetch(uncombinedVertices, uncombinedFaces);
std::vector<std::vector<size_t>> uncombinedTriangleAndQuads;
recoverQuads(uncombinedVertices, uncombinedFaces, componentCache.sharedQuadEdges, uncombinedTriangleAndQuads);
auto vertexStartIndex = m_outcome->vertices.size();
auto updateVertexIndices = [=](std::vector<std::vector<size_t>> &faces) {
for (auto &it: faces) {
for (auto &subIt: it)
subIt += vertexStartIndex;
}
};
updateVertexIndices(uncombinedFaces);
updateVertexIndices(uncombinedTriangleAndQuads);
m_outcome->vertices.insert(m_outcome->vertices.end(), uncombinedVertices.begin(), uncombinedVertices.end());
m_outcome->triangles.insert(m_outcome->triangles.end(), uncombinedFaces.begin(), uncombinedFaces.end());
m_outcome->triangleAndQuads.insert(m_outcome->triangleAndQuads.end(), uncombinedTriangleAndQuads.begin(), uncombinedTriangleAndQuads.end());
collectIncombinableMesh(componentCache.mesh, componentCache);
return;
}
for (const auto &childIdString: valueOfKeyInMapOrEmpty(*component, "children").split(",")) {

View File

@ -40,9 +40,18 @@ class GeneratedComponent
public:
~GeneratedComponent()
{
delete mesh;
releaseMeshes();
};
void releaseMeshes()
{
delete mesh;
mesh = nullptr;
for (auto &it: incombinableMeshes)
delete it;
incombinableMeshes.clear();
}
MeshCombiner::Mesh *mesh = nullptr;
std::vector<MeshCombiner::Mesh *> incombinableMeshes;
std::set<std::pair<PositionKey, PositionKey>> sharedQuadEdges;
std::set<PositionKey> noneSeamVertices;
std::vector<OutcomeNode> outcomeNodes;
@ -111,6 +120,8 @@ private:
bool m_weldEnabled = true;
void collectParts();
void collectIncombinableComponentMeshes(const QString &componentIdString);
void collectIncombinableMesh(const MeshCombiner::Mesh *mesh, const GeneratedComponent &componentCache);
bool checkIsComponentDirty(const QString &componentIdString);
bool checkIsPartDirty(const QString &partIdString);
bool checkIsPartDependencyDirty(const QString &partIdString);