Fallback to uncombined when component mesh is not combinable [skip ci]
parent
a7730884b2
commit
082b5ea1f1
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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(",")) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue