Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/carve/carve-capi.cc')
-rw-r--r--extern/carve/carve-capi.cc440
1 files changed, 327 insertions, 113 deletions
diff --git a/extern/carve/carve-capi.cc b/extern/carve/carve-capi.cc
index 319a20129d1..ef7a95e578b 100644
--- a/extern/carve/carve-capi.cc
+++ b/extern/carve/carve-capi.cc
@@ -39,14 +39,14 @@ typedef std::pair<MeshSet<3>::vertex_t *, MeshSet<3>::vertex_t *> VertexPair;
typedef carve::interpolate::VertexAttr<OrigIndex> OrigVertMapping;
typedef carve::interpolate::FaceAttr<OrigIndex> OrigFaceMapping;
typedef carve::interpolate::FaceEdgeAttr<OrigIndex> OrigFaceEdgeMapping;
-typedef carve::interpolate::FaceEdgeAttr<bool> FaceEdgeTriangulatedFlag;
+typedef carve::interpolate::SimpleFaceEdgeAttr<bool> FaceEdgeTriangulatedFlag;
typedef struct CarveMeshDescr {
// Stores mesh data itself.
MeshSet<3> *poly;
// N-th element of the vector indicates index of an original mesh loop.
- std::vector<int> orig_loop_index_map;
+ std::unordered_map<std::pair<int, int>, int> orig_loop_index_map;
// N-th element of the vector indicates index of an original mesh poly.
std::vector<int> orig_poly_index_map;
@@ -123,6 +123,24 @@ bool edgeIndexMap_get_if_exists(const std::unordered_map<std::pair<T1, T1>, T2>
return true;
}
+template <typename T1, typename T2>
+bool edgeIndexMap_exists(const std::unordered_map<std::pair<T1, T1>, T2> &edge_map,
+ const T1 &v1,
+ const T1 &v2)
+{
+ typedef std::unordered_map<std::pair<T1, T1>, T2> Map;
+ typename Map::const_iterator found;
+
+ if (v1 < v2) {
+ found = edge_map.find(std::make_pair(v1, v2));
+ }
+ else {
+ found = edge_map.find(std::make_pair(v2, v1));
+ }
+
+ return found != edge_map.end();
+}
+
template <typename T>
inline int indexOf(const T *element, const std::vector<T> &vector_from)
{
@@ -131,7 +149,7 @@ inline int indexOf(const T *element, const std::vector<T> &vector_from)
void initOrigIndexMeshFaceMapping(CarveMeshDescr *mesh,
int which_mesh,
- const std::vector<int> &orig_loop_index_map,
+ std::unordered_map<std::pair<int, int>, int> &orig_loop_index_map,
const std::vector<int> &orig_poly_index_map,
OrigVertMapping *orig_vert_mapping,
OrigFaceEdgeMapping *orig_face_edge_mapping,
@@ -166,7 +184,17 @@ void initOrigIndexMeshFaceMapping(CarveMeshDescr *mesh,
edge_iter != face->end();
++edge_iter, ++loop_map_index)
{
- int orig_loop_index = orig_loop_index_map[loop_map_index];
+ int v1 = indexOf(edge_iter->v1(), poly->vertex_storage);
+ int v2 = indexOf(edge_iter->v2(), poly->vertex_storage);
+
+ int orig_loop_index;
+ if (!edgeIndexMap_get_if_exists(orig_loop_index_map,
+ v1, v2,
+ &orig_loop_index))
+ {
+ orig_loop_index = -1;
+ }
+
if (orig_loop_index != -1) {
// Mapping from carve face edge back to original loop index.
orig_face_edge_mapping->setAttribute(face,
@@ -175,7 +203,9 @@ void initOrigIndexMeshFaceMapping(CarveMeshDescr *mesh,
orig_loop_index));
}
else {
- face_edge_triangulated_flag->setAttribute(face, edge_iter.idx(), true);
+ face_edge_triangulated_flag->setAttribute(face,
+ edge_iter.idx(),
+ true);
}
}
}
@@ -215,11 +245,11 @@ void origEdgeMappingForFace(MeshSet<3>::face_t *face,
MeshSet<3>::edge_t *edge = face->edge;
for (int i = 0;
- i < face->n_edges;
+ i < face->nEdges();
++i, edge = edge->next)
{
- MeshSet<3>::vertex_t *v1 = edge->vert;
- MeshSet<3>::vertex_t *v2 = edge->next->vert;
+ MeshSet<3>::vertex_t *v1 = edge->v1();
+ MeshSet<3>::vertex_t *v2 = edge->v2();
OrigIndex orig_edge_index =
orig_face_edge_mapping->getAttribute(edge->face, i, origindex_none);
@@ -229,27 +259,43 @@ void origEdgeMappingForFace(MeshSet<3>::face_t *face,
}
void dissolveTriangulatedEdges(MeshSet<3>::mesh_t *mesh,
- OrigFaceEdgeMapping *orig_face_edge_mapping,
- FaceEdgeTriangulatedFlag *face_edge_triangulated_flag)
+ const std::set< std::pair<int, int> > &open_edges,
+ FaceEdgeTriangulatedFlag *face_edge_triangulated_flag,
+ OrigFaceEdgeMapping *orig_face_edge_mapping)
{
typedef std::unordered_set<MeshSet<3>::edge_t *> edge_set_t;
typedef std::unordered_set<MeshSet<3>::face_t *> face_set_t;
edge_set_t triangulated_face_edges;
- for (int face_index = 0; face_index < mesh->faces.size(); face_index++) {
+ for (int face_index = 0; face_index < mesh->faces.size(); ++face_index) {
MeshSet<3>::face_t *face = mesh->faces[face_index];
MeshSet<3>::edge_t *edge = face->edge;
for (int edge_index = 0;
- edge_index < face->n_edges;
+ edge_index < face->nEdges();
++edge_index, edge = edge->next)
{
- const bool is_triangulated_edge =
- face_edge_triangulated_flag->getAttribute(face,
- edge_index,
- false);
- if (is_triangulated_edge) {
- MeshSet<3>::edge_t *e1 = std::min(edge, edge->rev);
- triangulated_face_edges.insert(e1);
+ if (edge->rev) {
+ const bool is_triangulated_edge =
+ face_edge_triangulated_flag->getAttribute(face,
+ edge_index,
+ false);
+ if (is_triangulated_edge) {
+ MeshSet<3>::edge_t *e1 = std::min(edge, edge->rev);
+ int v1 = indexOf(e1->v1(), mesh->meshset->vertex_storage),
+ v2 = indexOf(e1->v2(), mesh->meshset->vertex_storage);
+
+ bool is_open = false;
+ if (v1 < v2) {
+ is_open = open_edges.find(std::make_pair(v1, v2)) != open_edges.end();
+ }
+ else {
+ is_open = open_edges.find(std::make_pair(v2, v1)) != open_edges.end();
+ }
+
+ if (is_open == false) {
+ triangulated_face_edges.insert(e1);
+ }
+ }
}
}
}
@@ -284,11 +330,11 @@ void dissolveTriangulatedEdges(MeshSet<3>::mesh_t *mesh,
if (triangulated_faces.find(face) != triangulated_faces.end()) {
MeshSet<3>::edge_t *edge = face->edge;
for (int edge_index = 0;
- edge_index < face->n_edges;
+ edge_index < face->nEdges();
++edge_index, edge = edge->next)
{
- MeshSet<3>::vertex_t *v1 = edge->vert;
- MeshSet<3>::vertex_t *v2 = edge->next->vert;
+ MeshSet<3>::vertex_t *v1 = edge->v1();
+ MeshSet<3>::vertex_t *v2 = edge->v2();
OrigIndex orig_edge_index =
edgeIndexMap_get(edge_origindex_map,
@@ -308,14 +354,174 @@ void dissolveTriangulatedEdges(CarveMeshDescr *mesh_descr)
FaceEdgeTriangulatedFlag *face_edge_triangulated_flag =
&mesh_descr->face_edge_triangulated_flag;
- for (int i = 0; i < poly->meshes.size(); ++i) {
- MeshSet<3>::mesh_t *mesh = poly->meshes[i];
+ std::set< std::pair<int, int> > open_edges;
+ for (int mesh_index = 0;
+ mesh_index < poly->meshes.size();
+ ++mesh_index)
+ {
+ const MeshSet<3>::mesh_t *mesh = poly->meshes[mesh_index];
+ for (int edge_index = 0;
+ edge_index < mesh->open_edges.size();
+ ++edge_index)
+ {
+ const MeshSet<3>::edge_t *edge = mesh->open_edges[edge_index];
+ int v1 = indexOf(edge->v1(), poly->vertex_storage),
+ v2 = indexOf(edge->v2(), poly->vertex_storage);
+ if (v1 < v2) {
+ open_edges.insert(std::make_pair(v1, v2));
+ }
+ else {
+ open_edges.insert(std::make_pair(v2, v1));
+ }
+ }
+ }
+
+ for (int mesh_index = 0; mesh_index < poly->meshes.size(); ++mesh_index) {
+ MeshSet<3>::mesh_t *mesh = poly->meshes[mesh_index];
dissolveTriangulatedEdges(mesh,
- &mesh_descr->orig_face_edge_mapping,
- face_edge_triangulated_flag);
+ open_edges,
+ face_edge_triangulated_flag,
+ &mesh_descr->orig_face_edge_mapping);
+ }
+}
+
+void clipEar(MeshSet<3>::edge_t *ear)
+{
+ MeshSet<3>::edge_t *p_edge = ear->prev;
+ MeshSet<3>::edge_t *n_edge = ear->next;
+
+ p_edge->next = n_edge;
+ n_edge->prev = p_edge;
+
+ if (ear->face->edge == ear) {
+ ear->face->edge = n_edge;
+ }
+ ear->face->n_edges--;
+
+ delete ear;
+}
+
+MeshSet<3>::edge_t *findDegenerateEar(MeshSet<3>::face_t *face)
+{
+ for (MeshSet<3>::face_t::edge_iter_t edge_iter = face->begin();
+ edge_iter != face->end();
+ ++edge_iter)
+ {
+ MeshSet<3>::edge_t &edge = *edge_iter;
+ if (edge.vert == edge.next->next->vert) {
+ return edge.next->next;
+ }
}
+ return NULL;
}
+class EarClipper : public carve::csg::CSG::Hook {
+public:
+ virtual ~EarClipper() {
+ }
+
+ virtual void processOutputFace(std::vector<MeshSet<3>::face_t *> &faces,
+ const MeshSet<3>::face_t *orig,
+ bool flipped) {
+ for (size_t face_index = 0; face_index < faces.size(); ++face_index) {
+ carve::mesh::MeshSet<3>::face_t *face = faces[face_index];
+
+ // There's no ears in quads and tris.
+ if (face->nVertices() <= 4) {
+ continue;
+ }
+
+ MeshSet<3>::edge_t *ear;
+ while ((ear = findDegenerateEar(face)) != NULL) {
+ clipEar(ear);
+ }
+
+ }
+ }
+};
+
+class HoleResolver : public carve::csg::CarveHoleResolver {
+
+ void removeDuplicatedFaces(std::vector<MeshSet<3>::face_t *> &faces) {
+ std::vector<MeshSet<3>::face_t *> out_faces;
+ std::vector<MeshSet<3>::face_t *> duplicated_faces;
+
+ for (size_t face_index = 0; face_index < faces.size(); ++face_index) {
+ carve::mesh::MeshSet<3>::face_t *face = faces[face_index];
+ face->canonicalize();
+ }
+
+ for (size_t i = 0; i < faces.size(); ++i) {
+ carve::mesh::MeshSet<3>::face_t *face = faces[i];
+
+ bool found = false;
+ for (size_t j = i + 1; j < faces.size() && found == false; ++j) {
+ MeshSet<3>::face_t *cur_face = faces[j];
+ if (cur_face->nEdges() == face->nEdges() &&
+ cur_face->edge->vert == face->edge->vert)
+ {
+
+ MeshSet<3>::edge_t *cur_edge = cur_face->edge,
+ *forward_edge = face->edge,
+ *backward_edge = face->edge;
+ bool forward_matches = true, backward_matches = true;
+
+ for (int a = 0; a < cur_face->nEdges(); ++a) {
+ if (forward_edge->vert != cur_edge->vert) {
+ forward_matches = false;
+ if (backward_matches == false) {
+ break;
+ }
+ }
+
+ if (backward_edge->vert != cur_edge->vert) {
+ backward_matches = false;
+ if (forward_matches == false) {
+ break;
+ }
+ }
+
+ cur_edge = cur_edge->next;
+ forward_edge = forward_edge->next;
+ backward_edge = backward_edge->prev;
+ }
+
+ if (forward_matches || backward_matches) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ duplicated_faces.push_back(face);
+ }
+ else {
+ out_faces.push_back(face);
+ }
+ }
+
+ for (int i = 0; i < duplicated_faces.size(); ++i) {
+ delete duplicated_faces[i];
+ }
+
+ std::swap(faces, out_faces);
+ }
+
+public:
+ virtual ~HoleResolver() {
+ }
+
+ virtual void processOutputFace(std::vector<MeshSet<3>::face_t *> &faces,
+ const MeshSet<3>::face_t *orig,
+ bool flipped) {
+ carve::csg::CarveHoleResolver::processOutputFace(faces, orig, flipped);
+ if (faces.size() > 1) {
+ removeDuplicatedFaces(faces);
+ }
+ }
+};
+
} // namespace
CarveMeshDescr *carve_addMesh(struct ImportMeshData *import_data,
@@ -348,8 +554,8 @@ CarveMeshDescr *carve_addMesh(struct ImportMeshData *import_data,
int num_tessellated_polys = 0;
std::vector<int> face_indices;
face_indices.reserve(num_loops);
- mesh_descr->orig_loop_index_map.reserve(num_polys);
mesh_descr->orig_poly_index_map.reserve(num_polys);
+ TrianglesStorage triangles_storage;
for (int i = 0; i < num_polys; i++) {
int verts_per_poly =
mesh_importer->getNumPolyVerts(import_data, i);
@@ -376,32 +582,35 @@ CarveMeshDescr *carve_addMesh(struct ImportMeshData *import_data,
verts_per_poly,
verts_of_poly,
&axis_matrix)) {
- int num_triangles;
-
- num_triangles = carve_triangulatePoly(import_data,
- mesh_importer,
- i,
- loop_index,
- vertices,
- verts_per_poly,
- verts_of_poly,
- axis_matrix,
- &face_indices,
- &mesh_descr->orig_loop_index_map,
- &mesh_descr->orig_poly_index_map);
+ int num_triangles = carve_triangulatePoly(import_data,
+ mesh_importer,
+ vertices,
+ verts_per_poly,
+ verts_of_poly,
+ axis_matrix,
+ &face_indices,
+ &triangles_storage);
+
+ for (int j = 0; j < num_triangles; ++j) {
+ mesh_descr->orig_poly_index_map.push_back(i);
+ }
num_tessellated_polys += num_triangles;
- loop_index += verts_per_poly;
}
else {
face_indices.push_back(verts_per_poly);
for (int j = 0; j < verts_per_poly; ++j) {
- mesh_descr->orig_loop_index_map.push_back(loop_index++);
face_indices.push_back(verts_of_poly[j]);
}
mesh_descr->orig_poly_index_map.push_back(i);
num_tessellated_polys++;
}
+
+ for (int j = 0; j < verts_per_poly; ++j) {
+ int v1 = verts_of_poly[j];
+ int v2 = verts_of_poly[(j + 1) % verts_per_poly];
+ edgeIndexMap_put(&mesh_descr->orig_loop_index_map, v1, v2, loop_index++);
+ }
}
if (verts_of_poly_dynamic != NULL) {
@@ -471,7 +680,10 @@ bool carve_performBooleanOperation(CarveMeshDescr *left_mesh,
carve::csg::CSG csg;
- csg.hooks.registerHook(new carve::csg::CarveHoleResolver,
+ csg.hooks.registerHook(new HoleResolver,
+ carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT);
+
+ csg.hooks.registerHook(new EarClipper,
carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT);
output_descr->orig_vert_mapping.installHooks(csg);
@@ -504,10 +716,11 @@ bool carve_performBooleanOperation(CarveMeshDescr *left_mesh,
op,
NULL,
carve::csg::CSG::CLASSIFY_EDGE);
+
if (output_descr->poly) {
output_descr->poly->transform(rev_r);
- dissolveTriangulatedEdges(output_descr);
+ //dissolveTriangulatedEdges(output_descr);
}
}
catch (carve::exception e) {
@@ -522,33 +735,32 @@ bool carve_performBooleanOperation(CarveMeshDescr *left_mesh,
return output_descr->poly != NULL;
}
-static void exportMesh_handle_edges_list(MeshSet<3> *poly,
- const std::vector<MeshSet<3>::edge_t*> &edges,
- int start_edge_index,
- CarveMeshExporter *mesh_exporter,
- struct ExportMeshData *export_data,
- const std::unordered_map<VertexPair, OrigIndex> &edge_origindex_map,
- std::unordered_map<VertexPair, int> *edge_map)
+static int exportMesh_handle_edges_list(MeshSet<3> *poly,
+ const std::vector<MeshSet<3>::edge_t*> &edges,
+ int start_edge_index,
+ CarveMeshExporter *mesh_exporter,
+ struct ExportMeshData *export_data,
+ std::unordered_map<VertexPair, OrigIndex> &edge_origindex_map,
+ std::unordered_map<VertexPair, int> *edge_map)
{
+ int num_exported_edges = 0;
+
for (int i = 0, edge_index = start_edge_index;
i < edges.size();
- ++i, ++edge_index)
+ ++i)
{
MeshSet<3>::edge_t *edge = edges.at(i);
- MeshSet<3>::vertex_t *v1 = edge->vert;
- MeshSet<3>::vertex_t *v2 = edge->next->vert;
+ MeshSet<3>::vertex_t *v1 = edge->v1();
+ MeshSet<3>::vertex_t *v2 = edge->v2();
- OrigIndex orig_edge_index;
-
- if (!edgeIndexMap_get_if_exists(edge_origindex_map,
- v1,
- v2,
- &orig_edge_index))
- {
- orig_edge_index.first = CARVE_MESH_NONE;
- orig_edge_index.second = -1;
+ if (edgeIndexMap_exists(*edge_map, v1, v2)) {
+ continue;
}
+ const OrigIndex &orig_edge_index = edgeIndexMap_get(edge_origindex_map,
+ v1,
+ v2);
+
mesh_exporter->setEdge(export_data,
edge_index,
indexOf(v1, poly->vertex_storage),
@@ -557,7 +769,11 @@ static void exportMesh_handle_edges_list(MeshSet<3> *poly,
orig_edge_index.second);
edgeIndexMap_put(edge_map, v1, v2, edge_index);
+ ++edge_index;
+ ++num_exported_edges;
}
+
+ return num_exported_edges;
}
void carve_exportMesh(CarveMeshDescr *mesh_descr,
@@ -569,28 +785,6 @@ void carve_exportMesh(CarveMeshDescr *mesh_descr,
int num_vertices = poly->vertex_storage.size();
int num_edges = 0, num_loops = 0, num_polys = 0;
- // Count edges from all manifolds.
- for (int i = 0; i < poly->meshes.size(); ++i) {
- carve::mesh::Mesh<3> *mesh = poly->meshes[i];
- num_edges += mesh->closed_edges.size() + mesh->open_edges.size();
- }
-
- // Count polys and loops from all manifolds.
- for (MeshSet<3>::face_iter face_iter = poly->faceBegin();
- face_iter != poly->faceEnd();
- ++face_iter, ++num_polys)
- {
- MeshSet<3>::face_t *face = *face_iter;
- num_loops += face->n_edges;
- }
-
- // Initialize arrays for geometry in exported mesh.
- mesh_exporter->initGeomArrays(export_data,
- num_vertices,
- num_edges,
- num_loops,
- num_polys);
-
// Get mapping from edge denoted by vertex pair to original edge index,
//
// This is needed because internally Carve interpolates data for per-face
@@ -613,23 +807,45 @@ void carve_exportMesh(CarveMeshDescr *mesh_descr,
edge_iter_index,
origindex_none);
- if (orig_loop_index.first != CARVE_MESH_NONE) {
- OrigIndex orig_edge_index;
+ OrigIndex orig_edge_index;
+ if (orig_loop_index.first != CARVE_MESH_NONE) {
orig_edge_index.first = orig_loop_index.first;
orig_edge_index.second =
mesh_exporter->mapLoopToEdge(export_data,
orig_loop_index.first,
orig_loop_index.second);
+ }
+ else {
+ orig_edge_index.first = CARVE_MESH_NONE;
+ orig_edge_index.second = -1;
+ }
- MeshSet<3>::vertex_t *v1 = edge.vert;
- MeshSet<3>::vertex_t *v2 = edge.next->vert;
+ MeshSet<3>::vertex_t *v1 = edge.v1();
+ MeshSet<3>::vertex_t *v2 = edge.v2();
- edgeIndexMap_put(&edge_origindex_map, v1, v2, orig_edge_index);
- }
+ edgeIndexMap_put(&edge_origindex_map, v1, v2, orig_edge_index);
}
}
+ num_edges = edge_origindex_map.size();
+
+ // Count polys and loops from all manifolds.
+ for (MeshSet<3>::face_iter face_iter = poly->faceBegin();
+ face_iter != poly->faceEnd();
+ ++face_iter, ++num_polys)
+ {
+ MeshSet<3>::face_t *face = *face_iter;
+ num_loops += face->nEdges();
+ }
+
+ // Initialize arrays for geometry in exported mesh.
+ mesh_exporter->initGeomArrays(export_data,
+ num_vertices,
+ num_edges,
+ num_loops,
+ num_polys);
+
// Export all the vertices.
std::vector<MeshSet<3>::vertex_t>::iterator vertex_iter = poly->vertex_storage.begin();
for (int i = 0; vertex_iter != poly->vertex_storage.end(); ++i, ++vertex_iter) {
@@ -652,24 +868,22 @@ void carve_exportMesh(CarveMeshDescr *mesh_descr,
for (int i = 0, edge_index = 0; i < poly->meshes.size(); ++i) {
carve::mesh::Mesh<3> *mesh = poly->meshes[i];
// Export closed edges.
- exportMesh_handle_edges_list(poly,
- mesh->closed_edges,
- edge_index,
- mesh_exporter,
- export_data,
- edge_origindex_map,
- &edge_map);
- edge_index += mesh->closed_edges.size();
+ edge_index += exportMesh_handle_edges_list(poly,
+ mesh->closed_edges,
+ edge_index,
+ mesh_exporter,
+ export_data,
+ edge_origindex_map,
+ &edge_map);
// Export open edges.
- exportMesh_handle_edges_list(poly,
- mesh->open_edges,
- edge_index,
- mesh_exporter,
- export_data,
- edge_origindex_map,
- &edge_map);
- edge_index += mesh->open_edges.size();
+ edge_index += exportMesh_handle_edges_list(poly,
+ mesh->open_edges,
+ edge_index,
+ mesh_exporter,
+ export_data,
+ edge_origindex_map,
+ &edge_map);
}
// Export all the loops and polys.
@@ -694,15 +908,15 @@ void carve_exportMesh(CarveMeshDescr *mesh_descr,
origindex_none);
mesh_exporter->setLoop(export_data,
- loop_index,
- indexOf(edge.vert, poly->vertex_storage),
- edgeIndexMap_get(edge_map, edge.vert, edge.next->vert),
- orig_loop_index.first,
- orig_loop_index.second);
+ loop_index,
+ indexOf(edge.vert, poly->vertex_storage),
+ edgeIndexMap_get(edge_map, edge.v1(), edge.v2()),
+ orig_loop_index.first,
+ orig_loop_index.second);
}
mesh_exporter->setPoly(export_data,
- poly_index, start_loop_index, face->n_edges,
+ poly_index, start_loop_index, face->nEdges(),
orig_face_index.first, orig_face_index.second);
}
}