Seperate mesh union as single source file
parent
53dfb62460
commit
f48d6bd5f5
|
@ -43,6 +43,9 @@ HEADERS += src/theme.h
|
|||
SOURCES += src/mesh.cpp
|
||||
HEADERS += src/mesh.h
|
||||
|
||||
SOURCES += src/unionmesh.cpp
|
||||
HEADERS += src/unionmesh.h
|
||||
|
||||
SOURCES += src/main.cpp
|
||||
|
||||
INCLUDEPATH += ../meshlite/include
|
||||
|
|
|
@ -124,7 +124,7 @@ void SkeletonEditNodeItem::updateAppearance()
|
|||
QColor penColor = m_sideColor;
|
||||
penColor.setAlphaF(m_checked ? Theme::checkedAlpha : (m_isBranch ? Theme::branchAlpha : Theme::normalAlpha));
|
||||
QPen pen(penColor);
|
||||
pen.setWidth(m_isRoot ? Theme::skeletonNodeBorderSize : (Theme::skeletonNodeBorderSize * 2));
|
||||
pen.setWidth(m_isRoot ? (Theme::skeletonNodeBorderSize * 2) : Theme::skeletonNodeBorderSize);
|
||||
setPen(pen);
|
||||
|
||||
QColor brushColor = m_sideColor;
|
||||
|
|
|
@ -3,205 +3,9 @@
|
|||
#include "skeletoneditnodeitem.h"
|
||||
#include "skeletoneditedgeitem.h"
|
||||
#include "skeletonsnapshot.h"
|
||||
#include "unionmesh.h"
|
||||
#include <vector>
|
||||
|
||||
#define USE_CARVE 0
|
||||
#define USE_CGAL 1
|
||||
#define USE_EXTERNAL (USE_CARVE == 1 || USE_CGAL == 1)
|
||||
|
||||
#if USE_CARVE == 1
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <carve_config.h>
|
||||
#endif
|
||||
#include <carve/carve.hpp>
|
||||
#include <carve/csg.hpp>
|
||||
#include <carve/input.hpp>
|
||||
#endif
|
||||
|
||||
#define MAX_VERTICES_PER_FACE 100
|
||||
|
||||
#if USE_CGAL == 1
|
||||
// Polygon_mesh_processing/corefinement_mesh_union.cpp
|
||||
// https://doc.cgal.org/latest/Polygon_mesh_processing/Polygon_mesh_processing_2corefinement_mesh_union_8cpp-example.html#a2
|
||||
// https://doc.cgal.org/latest/Polygon_mesh_processing/Polygon_mesh_processing_2triangulate_faces_example_8cpp-example.html
|
||||
// https://github.com/CGAL/cgal/issues/2875
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/corefinement.h>
|
||||
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
#include <CGAL/assertions_behaviour.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Surface_mesh<Kernel::Point_3> CgalMesh;
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
CgalMesh *makeCgalMeshFromMeshlite(void *meshlite, int meshId)
|
||||
{
|
||||
CgalMesh *mesh = new CgalMesh;
|
||||
int vertexCount = meshlite_get_vertex_count(meshlite, meshId);
|
||||
float *vertexPositions = new float[vertexCount * 3];
|
||||
int vertexArrayLen = meshlite_get_vertex_position_array(meshlite, meshId, vertexPositions, vertexCount * 3);
|
||||
int offset = 0;
|
||||
assert(vertexArrayLen == vertexCount * 3);
|
||||
std::vector<CgalMesh::Vertex_index> vertices;
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
vertices.push_back(mesh->add_vertex(Kernel::Point_3(vertexPositions[offset + 0],
|
||||
vertexPositions[offset + 1],
|
||||
vertexPositions[offset + 2])));
|
||||
offset += 3;
|
||||
}
|
||||
int faceCount = meshlite_get_face_count(meshlite, meshId);
|
||||
int *faceVertexNumAndIndices = new int[faceCount * MAX_VERTICES_PER_FACE];
|
||||
int filledLength = meshlite_get_face_index_array(meshlite, meshId, faceVertexNumAndIndices, faceCount * MAX_VERTICES_PER_FACE);
|
||||
int i = 0;
|
||||
while (i < filledLength) {
|
||||
int num = faceVertexNumAndIndices[i++];
|
||||
assert(num > 0 && num <= MAX_VERTICES_PER_FACE);
|
||||
std::vector<CgalMesh::Vertex_index> faceIndices;
|
||||
for (int j = 0; j < num; j++) {
|
||||
int index = faceVertexNumAndIndices[i++];
|
||||
assert(index >= 0 && index < vertexCount);
|
||||
faceIndices.push_back(vertices[index]);
|
||||
}
|
||||
mesh->add_face(faceIndices);
|
||||
}
|
||||
delete[] faceVertexNumAndIndices;
|
||||
delete[] vertexPositions;
|
||||
return mesh;
|
||||
}
|
||||
|
||||
// https://doc.cgal.org/latest/Surface_mesh/index.html#circulators_example
|
||||
// https://www.cgal.org/FAQ.html
|
||||
|
||||
int makeMeshliteMeshFromCgal(void *meshlite, CgalMesh *mesh)
|
||||
{
|
||||
CgalMesh::Vertex_range vertexRange = mesh->vertices();
|
||||
int vertexCount = vertexRange.size();
|
||||
float *vertexPositions = new float[vertexCount * 3];
|
||||
int offset = 0;
|
||||
CgalMesh::Vertex_range::iterator vertexIt;
|
||||
std::map<CgalMesh::Vertex_index, int> vertexIndexMap;
|
||||
int i = 0;
|
||||
for (vertexIt = vertexRange.begin(); vertexIt != vertexRange.end(); vertexIt++) {
|
||||
Kernel::Point_3 point = mesh->point(*vertexIt);
|
||||
vertexPositions[offset++] = CGAL::to_double(point.x());
|
||||
vertexPositions[offset++] = CGAL::to_double(point.y());
|
||||
vertexPositions[offset++] = CGAL::to_double(point.z());
|
||||
vertexIndexMap[*vertexIt] = i;
|
||||
i++;
|
||||
}
|
||||
CgalMesh::Face_range faceRage = mesh->faces();
|
||||
int faceCount = faceRage.size();
|
||||
int *faceVertexNumAndIndices = new int[faceCount * MAX_VERTICES_PER_FACE];
|
||||
CgalMesh::Face_range::iterator faceIt;
|
||||
offset = 0;
|
||||
for (faceIt = faceRage.begin(); faceIt != faceRage.end(); faceIt++) {
|
||||
CGAL::Vertex_around_face_iterator<CgalMesh> vbegin, vend;
|
||||
std::vector<int> indices;
|
||||
for (boost::tie(vbegin, vend) = CGAL::vertices_around_face(mesh->halfedge(*faceIt), *mesh);
|
||||
vbegin != vend;
|
||||
++vbegin){
|
||||
indices.push_back(vertexIndexMap[*vbegin]);
|
||||
}
|
||||
faceVertexNumAndIndices[offset++] = indices.size();
|
||||
for (int j = 0; j < (int)indices.size(); j++) {
|
||||
faceVertexNumAndIndices[offset++] = indices[j];
|
||||
}
|
||||
}
|
||||
int meshId = meshlite_build(meshlite, vertexPositions, vertexCount, faceVertexNumAndIndices, offset);
|
||||
delete[] vertexPositions;
|
||||
delete[] faceVertexNumAndIndices;
|
||||
return meshId;
|
||||
}
|
||||
|
||||
CgalMesh *unionCgalMeshs(CgalMesh *first, CgalMesh *second)
|
||||
{
|
||||
CgalMesh *mesh = new CgalMesh;
|
||||
if (!PMP::corefine_and_compute_union(*first, *second, *mesh)) {
|
||||
return NULL;
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_CARVE == 1
|
||||
|
||||
carve::poly::Polyhedron *makeCarveMeshFromMeshlite(void *meshlite, int meshId)
|
||||
{
|
||||
carve::input::PolyhedronData data;
|
||||
int vertexCount = meshlite_get_vertex_count(meshlite, meshId);
|
||||
float *vertexPositions = new float[vertexCount * 3];
|
||||
int vertexArrayLen = meshlite_get_vertex_position_array(meshlite, meshId, vertexPositions, vertexCount * 3);
|
||||
int offset = 0;
|
||||
assert(vertexArrayLen == vertexCount * 3);
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
data.addVertex(carve::geom::VECTOR(
|
||||
vertexPositions[offset + 0],
|
||||
vertexPositions[offset + 1],
|
||||
vertexPositions[offset + 2]));
|
||||
offset += 3;
|
||||
}
|
||||
int faceCount = meshlite_get_face_count(meshlite, meshId);
|
||||
int *faceVertexNumAndIndices = new int[faceCount * MAX_VERTICES_PER_FACE];
|
||||
int filledLength = meshlite_get_face_index_array(meshlite, meshId, faceVertexNumAndIndices, faceCount * MAX_VERTICES_PER_FACE);
|
||||
int i = 0;
|
||||
while (i < filledLength) {
|
||||
int num = faceVertexNumAndIndices[i++];
|
||||
assert(num > 0 && num <= MAX_VERTICES_PER_FACE);
|
||||
std::vector<int> faceIndices;
|
||||
for (int j = 0; j < num; j++) {
|
||||
int index = faceVertexNumAndIndices[i++];
|
||||
assert(index >= 0 && index < vertexCount);
|
||||
faceIndices.push_back(index);
|
||||
}
|
||||
data.addFace(faceIndices.begin(), faceIndices.end());
|
||||
}
|
||||
delete[] faceVertexNumAndIndices;
|
||||
delete[] vertexPositions;
|
||||
return new carve::poly::Polyhedron(data.points, data.getFaceCount(), data.faceIndices);
|
||||
}
|
||||
|
||||
int makeMeshliteMeshFromCarve(void *meshlite, carve::poly::Polyhedron *polyhedron)
|
||||
{
|
||||
int vertexCount = polyhedron->vertices.size();
|
||||
float *vertexPositions = new float[vertexCount * 3];
|
||||
int offset = 0;
|
||||
std::map<const carve::poly::Geometry<3>::vertex_t *, int> vertexIndexMap;
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
auto vertex = &polyhedron->vertices[i];
|
||||
vertexPositions[offset++] = vertex->v.x;
|
||||
vertexPositions[offset++] = vertex->v.y;
|
||||
vertexPositions[offset++] = vertex->v.z;
|
||||
vertexIndexMap[vertex] = i;
|
||||
}
|
||||
int faceCount = polyhedron->faces.size();
|
||||
int *faceVertexNumAndIndices = new int[faceCount * MAX_VERTICES_PER_FACE];
|
||||
offset = 0;
|
||||
for (int i = 0; i < faceCount; i++) {
|
||||
auto face = &polyhedron->faces[i];
|
||||
faceVertexNumAndIndices[offset++] = face->vertices.size();
|
||||
for (int j = 0; j < (int)face->vertices.size(); j++) {
|
||||
faceVertexNumAndIndices[offset++] = vertexIndexMap[face->vertices[j]];
|
||||
}
|
||||
}
|
||||
int meshId = meshlite_build(meshlite, vertexPositions, vertexCount, faceVertexNumAndIndices, offset);
|
||||
delete[] vertexPositions;
|
||||
delete[] faceVertexNumAndIndices;
|
||||
return meshId;
|
||||
}
|
||||
|
||||
carve::poly::Polyhedron *unionCarveMeshs(carve::poly::Polyhedron *first,
|
||||
carve::poly::Polyhedron *second)
|
||||
{
|
||||
carve::csg::CSG csg;
|
||||
carve::poly::Polyhedron *result = csg.compute(first, second, carve::csg::CSG::UNION, NULL, carve::csg::CSG::CLASSIFY_EDGE);
|
||||
return new carve::poly::Polyhedron(*result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct NodeItemInfo
|
||||
{
|
||||
int index;
|
||||
|
@ -256,10 +60,10 @@ void SkeletonToMesh::process()
|
|||
void *meshliteContext = meshlite_create_context();
|
||||
for (size_t i = 0; i < groups.size(); i++) {
|
||||
SkeletonSnapshot *skeleton = &groups[i];
|
||||
QRectF front = skeleton->boundingBoxFront();
|
||||
QRectF side = skeleton->boundingBoxSide();
|
||||
float canvasWidth = skeleton->canvas["width"].toFloat();
|
||||
float canvasHeight = skeleton->canvas["height"].toFloat();
|
||||
//QRectF front = skeleton->boundingBoxFront();
|
||||
//QRectF side = skeleton->boundingBoxSide();
|
||||
//float canvasWidth = skeleton->canvas["width"].toFloat();
|
||||
//float canvasHeight = skeleton->canvas["height"].toFloat();
|
||||
|
||||
std::map<QString, int> bmeshNodeMap;
|
||||
|
||||
|
@ -271,11 +75,11 @@ void SkeletonToMesh::process()
|
|||
std::map<QString, std::map<QString, QString>>::iterator nextSidePair = skeleton->nodes.find(nodeIterator->second["nextSidePair"]);
|
||||
if (nextSidePair == skeleton->nodes.end())
|
||||
continue;
|
||||
float x = (nodeIterator->second["x"].toFloat() - frontMiddleX) / canvasHeight;
|
||||
float y = (nodeIterator->second["y"].toFloat() - frontMiddleY) / canvasHeight;
|
||||
float z = (nextSidePair->second["x"].toFloat() - sideMiddleX) / canvasHeight;
|
||||
float r = nodeIterator->second["radius"].toFloat() / canvasHeight;
|
||||
float t = nextSidePair->second["radius"].toFloat() / canvasHeight;
|
||||
float x = (nodeIterator->second["x"].toFloat() - frontMiddleX) / globalFront.height();
|
||||
float y = (nodeIterator->second["y"].toFloat() - frontMiddleY) / globalFront.height();
|
||||
float z = (nextSidePair->second["x"].toFloat() - sideMiddleX) / globalFront.height();
|
||||
float r = nodeIterator->second["radius"].toFloat() / globalFront.height();
|
||||
float t = nextSidePair->second["radius"].toFloat() / globalFront.height();
|
||||
int bmeshNodeId = meshlite_bmesh_add_node(meshliteContext, bmeshId, x, y, z, r, t);
|
||||
printf("meshlite_bmesh_add_node x:%f y:%f z:%f r:%f t:%f nodeName:%s bmeshNodeId:%d\n", x, y, z, r, t, nodeIterator->first.toUtf8().constData(), bmeshNodeId);
|
||||
bmeshNodeMap[nodeIterator->first] = bmeshNodeId;
|
||||
|
@ -302,44 +106,10 @@ void SkeletonToMesh::process()
|
|||
}
|
||||
|
||||
if (meshIds.size() > 0) {
|
||||
#if USE_EXTERNAL
|
||||
# if USE_CGAL
|
||||
CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
|
||||
# endif
|
||||
std::vector<ExternalMesh *> externalMeshs;
|
||||
for (size_t i = 0; i < meshIds.size(); i++) {
|
||||
int triangledMeshId = meshlite_triangulate(meshliteContext, meshIds[i]);
|
||||
if (meshlite_is_triangulated_manifold(meshliteContext, triangledMeshId))
|
||||
externalMeshs.push_back(makeExternalMeshFromMeshlite(meshliteContext, triangledMeshId));
|
||||
int mergedMeshId = unionMeshs(meshliteContext, meshIds);
|
||||
if (mergedMeshId > 0) {
|
||||
m_mesh = new Mesh(meshliteContext, mergedMeshId);
|
||||
}
|
||||
if (externalMeshs.size() > 0) {
|
||||
ExternalMesh *mergedExternalMesh = externalMeshs[0];
|
||||
for (size_t i = 1; i < externalMeshs.size(); i++) {
|
||||
if (!mergedExternalMesh)
|
||||
break;
|
||||
ExternalMesh *unionedExternalMesh = NULL;
|
||||
try {
|
||||
unionedExternalMesh = unionExternalMeshs(mergedExternalMesh, externalMeshs[i]);
|
||||
} catch (...) {
|
||||
// ignore;
|
||||
}
|
||||
delete mergedExternalMesh;
|
||||
delete externalMeshs[i];
|
||||
mergedExternalMesh = unionedExternalMesh;
|
||||
}
|
||||
if (mergedExternalMesh) {
|
||||
int mergedMeshId = makeMeshliteMeshFromExternal(meshliteContext, mergedExternalMesh);
|
||||
delete mergedExternalMesh;
|
||||
m_mesh = new Mesh(meshliteContext, mergedMeshId);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int mergedMeshId = meshIds[0];
|
||||
for (size_t i = 1; i < meshIds.size(); i++) {
|
||||
mergedMeshId = meshlite_merge(meshliteContext, mergedMeshId, meshIds[i]);
|
||||
}
|
||||
m_mesh = new Mesh(meshliteContext, mergedMeshId);
|
||||
#endif
|
||||
}
|
||||
|
||||
meshlite_destroy_context(meshliteContext);
|
||||
|
|
|
@ -0,0 +1,257 @@
|
|||
#include "unionmesh.h"
|
||||
#include "meshlite.h"
|
||||
|
||||
#define USE_CARVE 0
|
||||
#define USE_CGAL 1
|
||||
|
||||
#define USE_EXTERNAL (USE_CARVE == 1 || USE_CGAL == 1)
|
||||
|
||||
#if USE_CARVE == 1
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <carve_config.h>
|
||||
#endif
|
||||
#include <carve/carve.hpp>
|
||||
#include <carve/csg.hpp>
|
||||
#include <carve/input.hpp>
|
||||
#endif
|
||||
|
||||
#define MAX_VERTICES_PER_FACE 100
|
||||
|
||||
#if USE_CGAL == 1
|
||||
// Polygon_mesh_processing/corefinement_mesh_union.cpp
|
||||
// https://doc.cgal.org/latest/Polygon_mesh_processing/Polygon_mesh_processing_2corefinement_mesh_union_8cpp-example.html#a2
|
||||
// https://doc.cgal.org/latest/Polygon_mesh_processing/Polygon_mesh_processing_2triangulate_faces_example_8cpp-example.html
|
||||
// https://github.com/CGAL/cgal/issues/2875
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/Polygon_mesh_processing/corefinement.h>
|
||||
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
||||
#include <CGAL/boost/graph/iterator.h>
|
||||
#include <CGAL/assertions_behaviour.h>
|
||||
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
|
||||
typedef CGAL::Surface_mesh<Kernel::Point_3> CgalMesh;
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
CgalMesh *makeCgalMeshFromMeshlite(void *meshlite, int meshId)
|
||||
{
|
||||
CgalMesh *mesh = new CgalMesh;
|
||||
int vertexCount = meshlite_get_vertex_count(meshlite, meshId);
|
||||
float *vertexPositions = new float[vertexCount * 3];
|
||||
int vertexArrayLen = meshlite_get_vertex_position_array(meshlite, meshId, vertexPositions, vertexCount * 3);
|
||||
int offset = 0;
|
||||
assert(vertexArrayLen == vertexCount * 3);
|
||||
std::vector<CgalMesh::Vertex_index> vertices;
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
vertices.push_back(mesh->add_vertex(Kernel::Point_3(vertexPositions[offset + 0],
|
||||
vertexPositions[offset + 1],
|
||||
vertexPositions[offset + 2])));
|
||||
offset += 3;
|
||||
}
|
||||
int faceCount = meshlite_get_face_count(meshlite, meshId);
|
||||
int *faceVertexNumAndIndices = new int[faceCount * MAX_VERTICES_PER_FACE];
|
||||
int filledLength = meshlite_get_face_index_array(meshlite, meshId, faceVertexNumAndIndices, faceCount * MAX_VERTICES_PER_FACE);
|
||||
int i = 0;
|
||||
while (i < filledLength) {
|
||||
int num = faceVertexNumAndIndices[i++];
|
||||
assert(num > 0 && num <= MAX_VERTICES_PER_FACE);
|
||||
std::vector<CgalMesh::Vertex_index> faceIndices;
|
||||
for (int j = 0; j < num; j++) {
|
||||
int index = faceVertexNumAndIndices[i++];
|
||||
assert(index >= 0 && index < vertexCount);
|
||||
faceIndices.push_back(vertices[index]);
|
||||
}
|
||||
mesh->add_face(faceIndices);
|
||||
}
|
||||
delete[] faceVertexNumAndIndices;
|
||||
delete[] vertexPositions;
|
||||
return mesh;
|
||||
}
|
||||
|
||||
// https://doc.cgal.org/latest/Surface_mesh/index.html#circulators_example
|
||||
// https://www.cgal.org/FAQ.html
|
||||
|
||||
int makeMeshliteMeshFromCgal(void *meshlite, CgalMesh *mesh)
|
||||
{
|
||||
CgalMesh::Vertex_range vertexRange = mesh->vertices();
|
||||
int vertexCount = vertexRange.size();
|
||||
float *vertexPositions = new float[vertexCount * 3];
|
||||
int offset = 0;
|
||||
CgalMesh::Vertex_range::iterator vertexIt;
|
||||
std::map<CgalMesh::Vertex_index, int> vertexIndexMap;
|
||||
int i = 0;
|
||||
for (vertexIt = vertexRange.begin(); vertexIt != vertexRange.end(); vertexIt++) {
|
||||
Kernel::Point_3 point = mesh->point(*vertexIt);
|
||||
vertexPositions[offset++] = CGAL::to_double(point.x());
|
||||
vertexPositions[offset++] = CGAL::to_double(point.y());
|
||||
vertexPositions[offset++] = CGAL::to_double(point.z());
|
||||
vertexIndexMap[*vertexIt] = i;
|
||||
i++;
|
||||
}
|
||||
CgalMesh::Face_range faceRage = mesh->faces();
|
||||
int faceCount = faceRage.size();
|
||||
int *faceVertexNumAndIndices = new int[faceCount * MAX_VERTICES_PER_FACE];
|
||||
CgalMesh::Face_range::iterator faceIt;
|
||||
offset = 0;
|
||||
for (faceIt = faceRage.begin(); faceIt != faceRage.end(); faceIt++) {
|
||||
CGAL::Vertex_around_face_iterator<CgalMesh> vbegin, vend;
|
||||
std::vector<int> indices;
|
||||
for (boost::tie(vbegin, vend) = CGAL::vertices_around_face(mesh->halfedge(*faceIt), *mesh);
|
||||
vbegin != vend;
|
||||
++vbegin){
|
||||
indices.push_back(vertexIndexMap[*vbegin]);
|
||||
}
|
||||
faceVertexNumAndIndices[offset++] = indices.size();
|
||||
for (int j = 0; j < (int)indices.size(); j++) {
|
||||
faceVertexNumAndIndices[offset++] = indices[j];
|
||||
}
|
||||
}
|
||||
int meshId = meshlite_build(meshlite, vertexPositions, vertexCount, faceVertexNumAndIndices, offset);
|
||||
delete[] vertexPositions;
|
||||
delete[] faceVertexNumAndIndices;
|
||||
return meshId;
|
||||
}
|
||||
|
||||
CgalMesh *unionCgalMeshs(CgalMesh *first, CgalMesh *second)
|
||||
{
|
||||
CgalMesh *mesh = new CgalMesh;
|
||||
if (!PMP::corefine_and_compute_union(*first, *second, *mesh)) {
|
||||
return NULL;
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_CARVE == 1
|
||||
|
||||
carve::poly::Polyhedron *makeCarveMeshFromMeshlite(void *meshlite, int meshId)
|
||||
{
|
||||
carve::input::PolyhedronData data;
|
||||
int vertexCount = meshlite_get_vertex_count(meshlite, meshId);
|
||||
float *vertexPositions = new float[vertexCount * 3];
|
||||
int vertexArrayLen = meshlite_get_vertex_position_array(meshlite, meshId, vertexPositions, vertexCount * 3);
|
||||
int offset = 0;
|
||||
assert(vertexArrayLen == vertexCount * 3);
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
data.addVertex(carve::geom::VECTOR(
|
||||
vertexPositions[offset + 0],
|
||||
vertexPositions[offset + 1],
|
||||
vertexPositions[offset + 2]));
|
||||
offset += 3;
|
||||
}
|
||||
int faceCount = meshlite_get_face_count(meshlite, meshId);
|
||||
int *faceVertexNumAndIndices = new int[faceCount * MAX_VERTICES_PER_FACE];
|
||||
int filledLength = meshlite_get_face_index_array(meshlite, meshId, faceVertexNumAndIndices, faceCount * MAX_VERTICES_PER_FACE);
|
||||
int i = 0;
|
||||
while (i < filledLength) {
|
||||
int num = faceVertexNumAndIndices[i++];
|
||||
assert(num > 0 && num <= MAX_VERTICES_PER_FACE);
|
||||
std::vector<int> faceIndices;
|
||||
for (int j = 0; j < num; j++) {
|
||||
int index = faceVertexNumAndIndices[i++];
|
||||
assert(index >= 0 && index < vertexCount);
|
||||
faceIndices.push_back(index);
|
||||
}
|
||||
data.addFace(faceIndices.begin(), faceIndices.end());
|
||||
}
|
||||
delete[] faceVertexNumAndIndices;
|
||||
delete[] vertexPositions;
|
||||
return new carve::poly::Polyhedron(data.points, data.getFaceCount(), data.faceIndices);
|
||||
}
|
||||
|
||||
int makeMeshliteMeshFromCarve(void *meshlite, carve::poly::Polyhedron *polyhedron)
|
||||
{
|
||||
int vertexCount = polyhedron->vertices.size();
|
||||
float *vertexPositions = new float[vertexCount * 3];
|
||||
int offset = 0;
|
||||
std::map<const carve::poly::Geometry<3>::vertex_t *, int> vertexIndexMap;
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
auto vertex = &polyhedron->vertices[i];
|
||||
vertexPositions[offset++] = vertex->v.x;
|
||||
vertexPositions[offset++] = vertex->v.y;
|
||||
vertexPositions[offset++] = vertex->v.z;
|
||||
vertexIndexMap[vertex] = i;
|
||||
}
|
||||
int faceCount = polyhedron->faces.size();
|
||||
int *faceVertexNumAndIndices = new int[faceCount * MAX_VERTICES_PER_FACE];
|
||||
offset = 0;
|
||||
for (int i = 0; i < faceCount; i++) {
|
||||
auto face = &polyhedron->faces[i];
|
||||
faceVertexNumAndIndices[offset++] = face->vertices.size();
|
||||
for (int j = 0; j < (int)face->vertices.size(); j++) {
|
||||
faceVertexNumAndIndices[offset++] = vertexIndexMap[face->vertices[j]];
|
||||
}
|
||||
}
|
||||
int meshId = meshlite_build(meshlite, vertexPositions, vertexCount, faceVertexNumAndIndices, offset);
|
||||
delete[] vertexPositions;
|
||||
delete[] faceVertexNumAndIndices;
|
||||
return meshId;
|
||||
}
|
||||
|
||||
carve::poly::Polyhedron *unionCarveMeshs(carve::poly::Polyhedron *first,
|
||||
carve::poly::Polyhedron *second)
|
||||
{
|
||||
carve::csg::CSG csg;
|
||||
carve::poly::Polyhedron *result = csg.compute(first, second, carve::csg::CSG::UNION, NULL, carve::csg::CSG::CLASSIFY_EDGE);
|
||||
return new carve::poly::Polyhedron(*result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_CARVE == 1
|
||||
#define ExternalMesh carve::poly::Polyhedron
|
||||
#define makeExternalMeshFromMeshlite makeCarveMeshFromMeshlite
|
||||
#define unionExternalMeshs unionCarveMeshs
|
||||
#define makeMeshliteMeshFromExternal makeMeshliteMeshFromCarve
|
||||
#endif
|
||||
|
||||
#if USE_CGAL == 1
|
||||
#define ExternalMesh CgalMesh
|
||||
#define makeExternalMeshFromMeshlite makeCgalMeshFromMeshlite
|
||||
#define unionExternalMeshs unionCgalMeshs
|
||||
#define makeMeshliteMeshFromExternal makeMeshliteMeshFromCgal
|
||||
#endif
|
||||
|
||||
int unionMeshs(void *meshliteContext, const std::vector<int> &meshIds)
|
||||
{
|
||||
#if USE_EXTERNAL
|
||||
# if USE_CGAL
|
||||
CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
|
||||
# endif
|
||||
std::vector<ExternalMesh *> externalMeshs;
|
||||
for (size_t i = 0; i < meshIds.size(); i++) {
|
||||
int triangledMeshId = meshlite_triangulate(meshliteContext, meshIds[i]);
|
||||
if (meshlite_is_triangulated_manifold(meshliteContext, triangledMeshId))
|
||||
externalMeshs.push_back(makeExternalMeshFromMeshlite(meshliteContext, triangledMeshId));
|
||||
}
|
||||
if (externalMeshs.size() > 0) {
|
||||
ExternalMesh *mergedExternalMesh = externalMeshs[0];
|
||||
for (size_t i = 1; i < externalMeshs.size(); i++) {
|
||||
if (!mergedExternalMesh)
|
||||
break;
|
||||
ExternalMesh *unionedExternalMesh = NULL;
|
||||
try {
|
||||
unionedExternalMesh = unionExternalMeshs(mergedExternalMesh, externalMeshs[i]);
|
||||
} catch (...) {
|
||||
// ignore;
|
||||
}
|
||||
delete mergedExternalMesh;
|
||||
delete externalMeshs[i];
|
||||
mergedExternalMesh = unionedExternalMesh;
|
||||
}
|
||||
if (mergedExternalMesh) {
|
||||
int mergedMeshId = makeMeshliteMeshFromExternal(meshliteContext, mergedExternalMesh);
|
||||
delete mergedExternalMesh;
|
||||
return mergedMeshId;
|
||||
}
|
||||
}
|
||||
#else
|
||||
int mergedMeshId = meshIds[0];
|
||||
for (size_t i = 1; i < meshIds.size(); i++) {
|
||||
mergedMeshId = meshlite_merge(meshliteContext, mergedMeshId, meshIds[i]);
|
||||
}
|
||||
return mergedMeshId;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef UNION_MESH_H
|
||||
#define UNION_MESH_H
|
||||
#include <vector>
|
||||
|
||||
int unionMeshs(void *meshliteContext, const std::vector<int> &meshIds);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue