Add isotropic remesh preprocess to cloth simulation
parent
579fa24e1c
commit
c4882dec1f
|
@ -488,6 +488,9 @@ HEADERS += src/clothsimulator.h
|
|||
SOURCES += src/componentlayer.cpp
|
||||
HEADERS += src/componentlayer.h
|
||||
|
||||
SOURCES += src/isotropicremesh.cpp
|
||||
HEADERS += src/isotropicremesh.h
|
||||
|
||||
SOURCES += src/main.cpp
|
||||
|
||||
HEADERS += src/version.h
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/remesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/border.h>
|
||||
#include <boost/function_output_iterator.hpp>
|
||||
#include "booleanmesh.h"
|
||||
#include "isotropicremesh.h"
|
||||
|
||||
typedef boost::graph_traits<CgalMesh>::halfedge_descriptor halfedge_descriptor;
|
||||
typedef boost::graph_traits<CgalMesh>::edge_descriptor edge_descriptor;
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
struct halfedge2edge
|
||||
{
|
||||
halfedge2edge(const CgalMesh& m, std::vector<edge_descriptor>& edges)
|
||||
: m_mesh(m), m_edges(edges)
|
||||
{}
|
||||
void operator()(const halfedge_descriptor& h) const
|
||||
{
|
||||
m_edges.push_back(edge(h, m_mesh));
|
||||
}
|
||||
const CgalMesh& m_mesh;
|
||||
std::vector<edge_descriptor>& m_edges;
|
||||
};
|
||||
|
||||
void isotropicRemesh(const std::vector<QVector3D> &inputVertices,
|
||||
std::vector<std::vector<size_t>> &inputTriangles,
|
||||
std::vector<QVector3D> &outputVertices,
|
||||
std::vector<std::vector<size_t>> &outputTriangles,
|
||||
float targetEdgeLength,
|
||||
unsigned int iterationNum)
|
||||
{
|
||||
CgalMesh *mesh = buildCgalMesh<CgalKernel>(inputVertices, inputTriangles);
|
||||
if (nullptr == mesh)
|
||||
return;
|
||||
|
||||
std::vector<edge_descriptor> border;
|
||||
PMP::border_halfedges(faces(*mesh),
|
||||
*mesh,
|
||||
boost::make_function_output_iterator(halfedge2edge(*mesh, border)));
|
||||
PMP::split_long_edges(border, targetEdgeLength, *mesh);
|
||||
|
||||
PMP::isotropic_remeshing(faces(*mesh),
|
||||
targetEdgeLength,
|
||||
*mesh,
|
||||
PMP::parameters::number_of_iterations(iterationNum)
|
||||
.protect_constraints(true));
|
||||
|
||||
outputVertices.clear();
|
||||
outputTriangles.clear();
|
||||
fetchFromCgalMesh<CgalKernel>(mesh, outputVertices, outputTriangles);
|
||||
|
||||
delete mesh;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef DUST3D_ISOTROPICREMESH_H
|
||||
#define DUST3D_ISOTROPICREMESH_H
|
||||
#include <QVector3D>
|
||||
#include <vector>
|
||||
|
||||
void isotropicRemesh(const std::vector<QVector3D> &inputVertices,
|
||||
std::vector<std::vector<size_t>> &inputTriangles,
|
||||
std::vector<QVector3D> &outputVertices,
|
||||
std::vector<std::vector<size_t>> &outputTriangles,
|
||||
float targetEdgeLength,
|
||||
unsigned int iterationNum);
|
||||
|
||||
#endif
|
|
@ -19,6 +19,7 @@
|
|||
#include "remesher.h"
|
||||
#include "polycount.h"
|
||||
#include "clothsimulator.h"
|
||||
#include "isotropicremesh.h"
|
||||
|
||||
MeshGenerator::MeshGenerator(Snapshot *snapshot) :
|
||||
m_snapshot(snapshot)
|
||||
|
@ -1090,9 +1091,11 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component
|
|||
});
|
||||
}
|
||||
delete mesh;
|
||||
mesh = new MeshCombiner::Mesh(newVertices, newTriangles, componentId.isNull());
|
||||
bool disableSelfIntersectionTest = componentId.isNull() ||
|
||||
CombineMode::Uncombined == componentCombineMode(component);
|
||||
mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest);
|
||||
if (nullptr != mesh) {
|
||||
if (!componentId.isNull()) {
|
||||
if (!disableSelfIntersectionTest) {
|
||||
if (mesh->isNull()) {
|
||||
delete mesh;
|
||||
mesh = nullptr;
|
||||
|
@ -1584,15 +1587,30 @@ void MeshGenerator::collectClothComponent(const QString &componentIdString)
|
|||
const auto &component = findComponent(componentIdString);
|
||||
if (ComponentLayer::Cloth == componentLayer(component)) {
|
||||
const auto &componentCache = m_cacheContext->components[componentIdString];
|
||||
if (nullptr == componentCache.mesh || componentCache.mesh->isNull()) {
|
||||
if (nullptr == componentCache.mesh) {
|
||||
return;
|
||||
}
|
||||
if (m_clothCollisionTriangles.empty())
|
||||
return;
|
||||
|
||||
std::vector<QVector3D> uncombinedVertices;
|
||||
std::vector<std::vector<size_t>> uncombinedOriginalFaces;
|
||||
std::vector<std::vector<size_t>> uncombinedFaces;
|
||||
componentCache.mesh->fetch(uncombinedVertices, uncombinedFaces);
|
||||
componentCache.mesh->fetch(uncombinedVertices, uncombinedOriginalFaces);
|
||||
uncombinedFaces.reserve(uncombinedOriginalFaces.size());
|
||||
for (const auto &it: uncombinedOriginalFaces) {
|
||||
if (4 == it.size()) {
|
||||
uncombinedFaces.push_back(std::vector<size_t> {
|
||||
it[0], it[1], it[2]
|
||||
});
|
||||
uncombinedFaces.push_back(std::vector<size_t> {
|
||||
it[2], it[3], it[0]
|
||||
});
|
||||
} else if (3 == it.size()) {
|
||||
uncombinedFaces.push_back(it);
|
||||
}
|
||||
}
|
||||
isotropicRemesh(uncombinedVertices, uncombinedFaces, uncombinedVertices, uncombinedFaces, 0.02f, 3);
|
||||
|
||||
std::map<PositionKey, std::pair<QUuid, QUuid>> positionMap;
|
||||
for (const auto &it: componentCache.outcomeNodeVertices) {
|
||||
|
@ -1625,7 +1643,18 @@ void MeshGenerator::collectClothComponent(const QString &componentIdString)
|
|||
updateVertexIndices(uncombinedFaces);
|
||||
|
||||
m_outcome->vertices.insert(m_outcome->vertices.end(), uncombinedVertices.begin(), uncombinedVertices.end());
|
||||
m_outcome->triangles.insert(m_outcome->triangles.end(), uncombinedFaces.begin(), uncombinedFaces.end());
|
||||
for (const auto &it: uncombinedFaces) {
|
||||
if (4 == it.size()) {
|
||||
m_outcome->triangles.push_back(std::vector<size_t> {
|
||||
it[0], it[1], it[2]
|
||||
});
|
||||
m_outcome->triangles.push_back(std::vector<size_t> {
|
||||
it[2], it[3], it[0]
|
||||
});
|
||||
} else if (3 == it.size()) {
|
||||
m_outcome->triangles.push_back(it);
|
||||
}
|
||||
}
|
||||
m_outcome->triangleAndQuads.insert(m_outcome->triangleAndQuads.end(), uncombinedFaces.begin(), uncombinedFaces.end());
|
||||
|
||||
m_outcome->nodes.insert(m_outcome->nodes.end(), componentCache.outcomeNodes.begin(), componentCache.outcomeNodes.end());
|
||||
|
|
Loading…
Reference in New Issue