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 {
|
} else {
|
||||||
if (CGAL::Polygon_mesh_processing::triangulate_faces(*cgalMesh)) {
|
if (CGAL::Polygon_mesh_processing::triangulate_faces(*cgalMesh)) {
|
||||||
if (CGAL::Polygon_mesh_processing::does_self_intersect(*cgalMesh)) {
|
if (CGAL::Polygon_mesh_processing::does_self_intersect(*cgalMesh)) {
|
||||||
m_isSelfIntersected = true;
|
|
||||||
qDebug() << "Mesh does_self_intersect";
|
qDebug() << "Mesh does_self_intersect";
|
||||||
delete cgalMesh;
|
delete cgalMesh;
|
||||||
cgalMesh = nullptr;
|
cgalMesh = nullptr;
|
||||||
|
} else {
|
||||||
|
m_isCombinable = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Mesh triangulate failed";
|
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)
|
MeshCombiner::Mesh::Mesh(const Mesh &other)
|
||||||
{
|
{
|
||||||
if (other.m_privateData) {
|
if (other.m_privateData) {
|
||||||
m_isSelfIntersected = other.m_isSelfIntersected;
|
m_isCombinable = other.m_isCombinable;
|
||||||
m_privateData = new CgalMesh(*(CgalMesh *)other.m_privateData);
|
m_privateData = new CgalMesh(*(CgalMesh *)other.m_privateData);
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
@ -69,21 +70,16 @@ bool MeshCombiner::Mesh::isNull() const
|
||||||
return nullptr == m_privateData;
|
return nullptr == m_privateData;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MeshCombiner::Mesh::isSelfIntersected() const
|
bool MeshCombiner::Mesh::isCombinable() const
|
||||||
{
|
{
|
||||||
return m_isSelfIntersected;
|
return m_isCombinable;
|
||||||
}
|
|
||||||
|
|
||||||
void MeshCombiner::Mesh::markAsSelfIntersected()
|
|
||||||
{
|
|
||||||
m_isSelfIntersected = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshCombiner::Mesh *MeshCombiner::combine(const Mesh &firstMesh, const Mesh &secondMesh, Method method,
|
MeshCombiner::Mesh *MeshCombiner::combine(const Mesh &firstMesh, const Mesh &secondMesh, Method method,
|
||||||
std::vector<std::pair<Source, size_t>> *combinedVerticesComeFrom)
|
std::vector<std::pair<Source, size_t>> *combinedVerticesComeFrom)
|
||||||
{
|
{
|
||||||
if (firstMesh.isNull() || firstMesh.isSelfIntersected() ||
|
if (firstMesh.isNull() || !firstMesh.isCombinable() ||
|
||||||
secondMesh.isNull() || secondMesh.isSelfIntersected())
|
secondMesh.isNull() || !secondMesh.isCombinable())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
CgalMesh *resultCgalMesh = nullptr;
|
CgalMesh *resultCgalMesh = nullptr;
|
||||||
|
@ -157,9 +153,7 @@ MeshCombiner::Mesh *MeshCombiner::combine(const Mesh &firstMesh, const Mesh &sec
|
||||||
|
|
||||||
Mesh *mesh = new Mesh;
|
Mesh *mesh = new Mesh;
|
||||||
mesh->m_privateData = resultCgalMesh;
|
mesh->m_privateData = resultCgalMesh;
|
||||||
if (CGAL::Polygon_mesh_processing::does_self_intersect(*resultCgalMesh)) {
|
mesh->m_isCombinable = true;
|
||||||
mesh->markAsSelfIntersected();
|
|
||||||
}
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,5 +166,6 @@ void MeshCombiner::Mesh::validate()
|
||||||
if (isNullCgalMesh<CgalKernel>(exactMesh)) {
|
if (isNullCgalMesh<CgalKernel>(exactMesh)) {
|
||||||
delete exactMesh;
|
delete exactMesh;
|
||||||
m_privateData = nullptr;
|
m_privateData = nullptr;
|
||||||
|
m_isCombinable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,14 +28,13 @@ public:
|
||||||
~Mesh();
|
~Mesh();
|
||||||
void fetch(std::vector<QVector3D> &vertices, std::vector<std::vector<size_t>> &faces) const;
|
void fetch(std::vector<QVector3D> &vertices, std::vector<std::vector<size_t>> &faces) const;
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
bool isSelfIntersected() const;
|
bool isCombinable() const;
|
||||||
void markAsSelfIntersected();
|
|
||||||
|
|
||||||
friend MeshCombiner;
|
friend MeshCombiner;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void *m_privateData = nullptr;
|
void *m_privateData = nullptr;
|
||||||
bool m_isSelfIntersected = false;
|
bool m_isCombinable = false;
|
||||||
|
|
||||||
void validate();
|
void validate();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1035,8 +1035,7 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
|
||||||
componentCache.outcomeEdges.clear();
|
componentCache.outcomeEdges.clear();
|
||||||
componentCache.outcomeNodeVertices.clear();
|
componentCache.outcomeNodeVertices.clear();
|
||||||
componentCache.outcomePaintMaps.clear();
|
componentCache.outcomePaintMaps.clear();
|
||||||
delete componentCache.mesh;
|
componentCache.releaseMeshes();
|
||||||
componentCache.mesh = nullptr;
|
|
||||||
|
|
||||||
QString linkDataType = valueOfKeyInMapOrEmpty(*component, "linkDataType");
|
QString linkDataType = valueOfKeyInMapOrEmpty(*component, "linkDataType");
|
||||||
if ("partId" == linkDataType) {
|
if ("partId" == linkDataType) {
|
||||||
|
@ -1084,10 +1083,10 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
|
||||||
}
|
}
|
||||||
auto combineMode = componentCombineMode(child);
|
auto combineMode = componentCombineMode(child);
|
||||||
if (lastCombineMode != combineMode || lastCombineMode == CombineMode::Inversion) {
|
if (lastCombineMode != combineMode || lastCombineMode == CombineMode::Inversion) {
|
||||||
qDebug() << "New group[" << currentGroupIndex << "] for combine mode[" << CombineModeToString(combineMode) << "]";
|
|
||||||
combineGroups.push_back({combineMode, {}});
|
combineGroups.push_back({combineMode, {}});
|
||||||
++currentGroupIndex;
|
++currentGroupIndex;
|
||||||
lastCombineMode = combineMode;
|
lastCombineMode = combineMode;
|
||||||
|
qDebug() << "New group[" << currentGroupIndex << "] for combine mode[" << CombineModeToString(combineMode) << "]";
|
||||||
}
|
}
|
||||||
if (-1 == currentGroupIndex) {
|
if (-1 == currentGroupIndex) {
|
||||||
qDebug() << "Should not happen: -1 == currentGroupIndex";
|
qDebug() << "Should not happen: -1 == currentGroupIndex";
|
||||||
|
@ -1214,9 +1213,19 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
delete mesh;
|
delete mesh;
|
||||||
|
mesh = nullptr;
|
||||||
bool disableSelfIntersectionTest = componentId.isNull() ||
|
bool disableSelfIntersectionTest = componentId.isNull() ||
|
||||||
CombineMode::Uncombined == componentCombineMode(component);
|
CombineMode::Uncombined == componentCombineMode(component);
|
||||||
|
if (!disableSelfIntersectionTest) {
|
||||||
|
if (isManifold(newTriangles)) {
|
||||||
mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest);
|
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 (nullptr != mesh) {
|
||||||
if (!disableSelfIntersectionTest) {
|
if (!disableSelfIntersectionTest) {
|
||||||
if (mesh->isNull()) {
|
if (mesh->isNull()) {
|
||||||
|
@ -1244,12 +1253,14 @@ MeshCombiner::Mesh *MeshGenerator::combineMultipleMeshes(const std::vector<std::
|
||||||
MeshCombiner::Mesh *subMesh = std::get<0>(it);
|
MeshCombiner::Mesh *subMesh = std::get<0>(it);
|
||||||
const QString &subMeshIdString = std::get<2>(it);
|
const QString &subMeshIdString = std::get<2>(it);
|
||||||
//qDebug() << "Combine mode:" << CombineModeToString(childCombineMode);
|
//qDebug() << "Combine mode:" << CombineModeToString(childCombineMode);
|
||||||
if (nullptr == subMesh) {
|
if (nullptr == subMesh || subMesh->isNull()) {
|
||||||
|
delete subMesh;
|
||||||
qDebug() << "Child mesh is null";
|
qDebug() << "Child mesh is null";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (subMesh->isNull()) {
|
if (!subMesh->isCombinable()) {
|
||||||
qDebug() << "Child mesh is uncombinable";
|
qDebug() << "Child mesh is uncombinable";
|
||||||
|
// TODO: Collect vertices
|
||||||
delete subMesh;
|
delete subMesh;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1331,6 +1342,11 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentChildGroupMesh(const std::vec
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!subMesh->isCombinable()) {
|
||||||
|
componentCache.incombinableMeshes.push_back(subMesh);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
multipleMeshes.push_back(std::make_tuple(subMesh, childCombineMode, childIdString));
|
multipleMeshes.push_back(std::make_tuple(subMesh, childCombineMode, childIdString));
|
||||||
}
|
}
|
||||||
return combineMultipleMeshes(multipleMeshes);
|
return combineMultipleMeshes(multipleMeshes);
|
||||||
|
@ -1359,7 +1375,7 @@ MeshCombiner::Mesh *MeshGenerator::combineTwoMeshes(const MeshCombiner::Mesh &fi
|
||||||
if (recombiner.recombine()) {
|
if (recombiner.recombine()) {
|
||||||
if (isManifold(recombiner.regeneratedFaces())) {
|
if (isManifold(recombiner.regeneratedFaces())) {
|
||||||
MeshCombiner::Mesh *reMesh = new MeshCombiner::Mesh(recombiner.regeneratedVertices(), recombiner.regeneratedFaces(), false);
|
MeshCombiner::Mesh *reMesh = new MeshCombiner::Mesh(recombiner.regeneratedVertices(), recombiner.regeneratedFaces(), false);
|
||||||
if (!reMesh->isNull() && !reMesh->isSelfIntersected()) {
|
if (!reMesh->isNull() && reMesh->isCombinable()) {
|
||||||
delete newMesh;
|
delete newMesh;
|
||||||
newMesh = reMesh;
|
newMesh = reMesh;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1537,6 +1553,7 @@ void MeshGenerator::generate()
|
||||||
|
|
||||||
// Recursively check uncombined components
|
// Recursively check uncombined components
|
||||||
collectUncombinedComponent(QUuid().toString());
|
collectUncombinedComponent(QUuid().toString());
|
||||||
|
collectIncombinableComponentMeshes(QUuid().toString());
|
||||||
|
|
||||||
// Fetch nodes as body nodes before cloth nodes collecting
|
// Fetch nodes as body nodes before cloth nodes collecting
|
||||||
std::set<std::pair<QUuid, QUuid>> bodyNodeMap;
|
std::set<std::pair<QUuid, QUuid>> bodyNodeMap;
|
||||||
|
@ -1691,26 +1708,29 @@ void MeshGenerator::remesh(const std::vector<OutcomeNode> &inputNodes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshGenerator::collectUncombinedComponent(const QString &componentIdString)
|
void MeshGenerator::collectIncombinableComponentMeshes(const QString &componentIdString)
|
||||||
{
|
{
|
||||||
const auto &component = findComponent(componentIdString);
|
|
||||||
if (CombineMode::Uncombined == componentCombineMode(component)) {
|
|
||||||
if (ComponentLayer::Body != componentLayer(component))
|
|
||||||
return;
|
|
||||||
const auto &componentCache = m_cacheContext->components[componentIdString];
|
const auto &componentCache = m_cacheContext->components[componentIdString];
|
||||||
if (nullptr == componentCache.mesh || componentCache.mesh->isNull()) {
|
for (const auto &mesh: componentCache.incombinableMeshes)
|
||||||
qDebug() << "Uncombined mesh is null";
|
collectIncombinableMesh(mesh, componentCache);
|
||||||
return;
|
const auto &component = findComponent(componentIdString);
|
||||||
|
for (const auto &childIdString: valueOfKeyInMapOrEmpty(*component, "children").split(",")) {
|
||||||
|
if (childIdString.isEmpty())
|
||||||
|
continue;
|
||||||
|
collectIncombinableComponentMeshes(childIdString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_outcome->nodes.insert(m_outcome->nodes.end(), componentCache.outcomeNodes.begin(), componentCache.outcomeNodes.end());
|
void MeshGenerator::collectIncombinableMesh(const MeshCombiner::Mesh *mesh, const GeneratedComponent &componentCache)
|
||||||
m_outcome->edges.insert(m_outcome->edges.end(), componentCache.outcomeEdges.begin(), componentCache.outcomeEdges.end());
|
{
|
||||||
m_outcome->nodeVertices.insert(m_outcome->nodeVertices.end(), componentCache.outcomeNodeVertices.begin(), componentCache.outcomeNodeVertices.end());
|
if (nullptr == mesh)
|
||||||
m_outcome->paintMaps.insert(m_outcome->paintMaps.end(), componentCache.outcomePaintMaps.begin(), componentCache.outcomePaintMaps.end());
|
return;
|
||||||
|
|
||||||
|
m_isSuccessful = false;
|
||||||
|
|
||||||
std::vector<QVector3D> uncombinedVertices;
|
std::vector<QVector3D> uncombinedVertices;
|
||||||
std::vector<std::vector<size_t>> uncombinedFaces;
|
std::vector<std::vector<size_t>> uncombinedFaces;
|
||||||
componentCache.mesh->fetch(uncombinedVertices, uncombinedFaces);
|
mesh->fetch(uncombinedVertices, uncombinedFaces);
|
||||||
std::vector<std::vector<size_t>> uncombinedTriangleAndQuads;
|
std::vector<std::vector<size_t>> uncombinedTriangleAndQuads;
|
||||||
|
|
||||||
recoverQuads(uncombinedVertices, uncombinedFaces, componentCache.sharedQuadEdges, uncombinedTriangleAndQuads);
|
recoverQuads(uncombinedVertices, uncombinedFaces, componentCache.sharedQuadEdges, uncombinedTriangleAndQuads);
|
||||||
|
@ -1728,6 +1748,26 @@ void MeshGenerator::collectUncombinedComponent(const QString &componentIdString)
|
||||||
m_outcome->vertices.insert(m_outcome->vertices.end(), uncombinedVertices.begin(), uncombinedVertices.end());
|
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->triangles.insert(m_outcome->triangles.end(), uncombinedFaces.begin(), uncombinedFaces.end());
|
||||||
m_outcome->triangleAndQuads.insert(m_outcome->triangleAndQuads.end(), uncombinedTriangleAndQuads.begin(), uncombinedTriangleAndQuads.end());
|
m_outcome->triangleAndQuads.insert(m_outcome->triangleAndQuads.end(), uncombinedTriangleAndQuads.begin(), uncombinedTriangleAndQuads.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshGenerator::collectUncombinedComponent(const QString &componentIdString)
|
||||||
|
{
|
||||||
|
const auto &component = findComponent(componentIdString);
|
||||||
|
if (CombineMode::Uncombined == componentCombineMode(component)) {
|
||||||
|
if (ComponentLayer::Body != componentLayer(component))
|
||||||
|
return;
|
||||||
|
const auto &componentCache = m_cacheContext->components[componentIdString];
|
||||||
|
if (nullptr == componentCache.mesh || componentCache.mesh->isNull()) {
|
||||||
|
qDebug() << "Uncombined mesh is null";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_outcome->nodes.insert(m_outcome->nodes.end(), componentCache.outcomeNodes.begin(), componentCache.outcomeNodes.end());
|
||||||
|
m_outcome->edges.insert(m_outcome->edges.end(), componentCache.outcomeEdges.begin(), componentCache.outcomeEdges.end());
|
||||||
|
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());
|
||||||
|
|
||||||
|
collectIncombinableMesh(componentCache.mesh, componentCache);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto &childIdString: valueOfKeyInMapOrEmpty(*component, "children").split(",")) {
|
for (const auto &childIdString: valueOfKeyInMapOrEmpty(*component, "children").split(",")) {
|
||||||
|
|
|
@ -40,9 +40,18 @@ class GeneratedComponent
|
||||||
public:
|
public:
|
||||||
~GeneratedComponent()
|
~GeneratedComponent()
|
||||||
{
|
{
|
||||||
delete mesh;
|
releaseMeshes();
|
||||||
};
|
};
|
||||||
|
void releaseMeshes()
|
||||||
|
{
|
||||||
|
delete mesh;
|
||||||
|
mesh = nullptr;
|
||||||
|
for (auto &it: incombinableMeshes)
|
||||||
|
delete it;
|
||||||
|
incombinableMeshes.clear();
|
||||||
|
}
|
||||||
MeshCombiner::Mesh *mesh = nullptr;
|
MeshCombiner::Mesh *mesh = nullptr;
|
||||||
|
std::vector<MeshCombiner::Mesh *> incombinableMeshes;
|
||||||
std::set<std::pair<PositionKey, PositionKey>> sharedQuadEdges;
|
std::set<std::pair<PositionKey, PositionKey>> sharedQuadEdges;
|
||||||
std::set<PositionKey> noneSeamVertices;
|
std::set<PositionKey> noneSeamVertices;
|
||||||
std::vector<OutcomeNode> outcomeNodes;
|
std::vector<OutcomeNode> outcomeNodes;
|
||||||
|
@ -111,6 +120,8 @@ private:
|
||||||
bool m_weldEnabled = true;
|
bool m_weldEnabled = true;
|
||||||
|
|
||||||
void collectParts();
|
void collectParts();
|
||||||
|
void collectIncombinableComponentMeshes(const QString &componentIdString);
|
||||||
|
void collectIncombinableMesh(const MeshCombiner::Mesh *mesh, const GeneratedComponent &componentCache);
|
||||||
bool checkIsComponentDirty(const QString &componentIdString);
|
bool checkIsComponentDirty(const QString &componentIdString);
|
||||||
bool checkIsPartDirty(const QString &partIdString);
|
bool checkIsPartDirty(const QString &partIdString);
|
||||||
bool checkIsPartDependencyDirty(const QString &partIdString);
|
bool checkIsPartDependencyDirty(const QString &partIdString);
|
||||||
|
|
Loading…
Reference in New Issue