123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995 |
- /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation,
- * Sergey Sharybin
- *
- * ***** END GPL LICENSE BLOCK *****
- */
- #include "carve-capi.h"
- #include "carve-util.h"
- #include <carve/interpolator.hpp>
- #include <carve/rescale.hpp>
- #include <carve/csg_triangulator.hpp>
- #include <carve/mesh_simplify.hpp>
- using carve::mesh::MeshSet;
- typedef std::pair<int, int> OrigIndex;
- 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::SwapableFaceEdgeAttr<OrigIndex> OrigFaceEdgeMapping;
- 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::unordered_map<std::pair<int, int>, int> orig_loop_index_map;
- // Mapping from carve face to an original face index in DM.
- std::unordered_map<const MeshSet<3>::face_t *, int> orig_poly_index_map;
- // The folloving mapping is only filled in for output mesh.
- // Mapping from the face verts back to original vert index.
- OrigVertMapping orig_vert_mapping;
- // Mapping from the face edges back to (original edge index, original loop index).
- OrigFaceEdgeMapping orig_face_edge_mapping;
- FaceEdgeTriangulatedFlag face_edge_triangulated_flag;
- // Mapping from the faces back to original poly index.
- OrigFaceMapping orig_face_mapping;
- } CarveMeshDescr;
- namespace {
- template <typename T1, typename T2>
- void edgeIndexMap_put(std::unordered_map<std::pair<T1, T1>, T2> *edge_map,
- const T1 &v1,
- const T1 &v2,
- const T2 &index)
- {
- if (v1 < v2) {
- (*edge_map)[std::make_pair(v1, v2)] = index;
- }
- else {
- (*edge_map)[std::make_pair(v2, v1)] = index;
- }
- }
- template <typename T1, typename T2>
- const T2 &edgeIndexMap_get(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));
- }
- assert(found != edge_map.end());
- return found->second;
- }
- template <typename T1, typename T2>
- bool edgeIndexMap_get_if_exists(const std::unordered_map<std::pair<T1, T1>, T2> &edge_map,
- const T1 &v1,
- const T1 &v2,
- T2 *out)
- {
- 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));
- }
- if (found == edge_map.end()) {
- return false;
- }
- *out = found->second;
- 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)
- {
- return element - &vector_from.at(0);
- }
- void initOrigIndexMeshFaceMapping(CarveMeshDescr *mesh,
- int which_mesh,
- std::unordered_map<std::pair<int, int>, int> &orig_loop_index_map,
- std::unordered_map<const MeshSet<3>::face_t*, int> &orig_poly_index_map,
- OrigVertMapping *orig_vert_mapping,
- OrigFaceEdgeMapping *orig_face_edge_mapping,
- FaceEdgeTriangulatedFlag *face_edge_triangulated_flag,
- OrigFaceMapping *orig_face_attr)
- {
- MeshSet<3> *poly = mesh->poly;
- 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)
- {
- MeshSet<3>::vertex_t *vertex = &(*vertex_iter);
- orig_vert_mapping->setAttribute(vertex,
- std::make_pair(which_mesh, i));
- }
- MeshSet<3>::face_iter face_iter = poly->faceBegin();
- for (int i = 0, loop_map_index = 0;
- face_iter != poly->faceEnd();
- ++face_iter, ++i)
- {
- const MeshSet<3>::face_t *face = *face_iter;
- // Mapping from carve face back to original poly index.
- int orig_poly_index = orig_poly_index_map[face];
- orig_face_attr->setAttribute(face, std::make_pair(which_mesh, orig_poly_index));
- for (MeshSet<3>::face_t::const_edge_iter_t edge_iter = face->begin();
- edge_iter != face->end();
- ++edge_iter, ++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,
- edge_iter.idx(),
- std::make_pair(which_mesh,
- orig_loop_index));
- }
- else {
- face_edge_triangulated_flag->setAttribute(face,
- edge_iter.idx(),
- true);
- }
- }
- }
- }
- void initOrigIndexMapping(CarveMeshDescr *left_mesh,
- CarveMeshDescr *right_mesh,
- OrigVertMapping *orig_vert_mapping,
- OrigFaceEdgeMapping *orig_face_edge_mapping,
- FaceEdgeTriangulatedFlag *face_edge_triangulated_flag,
- OrigFaceMapping *orig_face_mapping)
- {
- initOrigIndexMeshFaceMapping(left_mesh,
- CARVE_MESH_LEFT,
- left_mesh->orig_loop_index_map,
- left_mesh->orig_poly_index_map,
- orig_vert_mapping,
- orig_face_edge_mapping,
- face_edge_triangulated_flag,
- orig_face_mapping);
- initOrigIndexMeshFaceMapping(right_mesh,
- CARVE_MESH_RIGHT,
- right_mesh->orig_loop_index_map,
- right_mesh->orig_poly_index_map,
- orig_vert_mapping,
- orig_face_edge_mapping,
- face_edge_triangulated_flag,
- orig_face_mapping);
- }
- void origEdgeMappingForFace(MeshSet<3>::face_t *face,
- OrigFaceEdgeMapping *orig_face_edge_mapping,
- std::unordered_map<VertexPair, OrigIndex> *edge_origindex_map)
- {
- OrigIndex origindex_none = std::make_pair((int)CARVE_MESH_NONE, -1);
- MeshSet<3>::edge_t *edge = face->edge;
- for (int i = 0;
- i < face->nEdges();
- ++i, edge = edge->next)
- {
- 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);
- edgeIndexMap_put(edge_origindex_map, v1, v2, orig_edge_index);
- }
- }
- void dissolveTriangulatedEdges(MeshSet<3>::mesh_t *mesh,
- 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) {
- MeshSet<3>::face_t *face = mesh->faces[face_index];
- MeshSet<3>::edge_t *edge = face->edge;
- for (int edge_index = 0;
- edge_index < face->nEdges();
- ++edge_index, edge = edge->next)
- {
- 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);
- }
- }
- }
- }
- }
- if (triangulated_face_edges.size()) {
- face_set_t triangulated_faces;
- std::unordered_map<VertexPair, OrigIndex> edge_origindex_map;
- for (edge_set_t::iterator it = triangulated_face_edges.begin();
- it != triangulated_face_edges.end();
- ++it)
- {
- MeshSet<3>::edge_t *edge = *it;
- origEdgeMappingForFace(edge->face,
- orig_face_edge_mapping,
- &edge_origindex_map);
- triangulated_faces.insert(edge->face);
- origEdgeMappingForFace(edge->rev->face,
- orig_face_edge_mapping,
- &edge_origindex_map);
- triangulated_faces.insert(edge->rev->face);
- }
- carve::mesh::MeshSimplifier simplifier;
- simplifier.dissolveMeshEdges(mesh, triangulated_face_edges);
- for (int face_index = 0; face_index < mesh->faces.size(); face_index++) {
- MeshSet<3>::face_t *face = mesh->faces[face_index];
- if (triangulated_faces.find(face) != triangulated_faces.end()) {
- MeshSet<3>::edge_t *edge = face->edge;
- for (int edge_index = 0;
- edge_index < face->nEdges();
- ++edge_index, edge = edge->next)
- {
- MeshSet<3>::vertex_t *v1 = edge->v1();
- MeshSet<3>::vertex_t *v2 = edge->v2();
- OrigIndex orig_edge_index =
- edgeIndexMap_get(edge_origindex_map,
- v1,
- v2);
- orig_face_edge_mapping->setAttribute(face, edge_index, orig_edge_index);
- }
- }
- }
- }
- }
- void dissolveTriangulatedEdges(CarveMeshDescr *mesh_descr)
- {
- MeshSet<3> *poly = mesh_descr->poly;
- FaceEdgeTriangulatedFlag *face_edge_triangulated_flag =
- &mesh_descr->face_edge_triangulated_flag;
- 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,
- 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);
- }
- }
- };
- template <typename Interpolator>
- void copyFaceEdgeAttrs(const MeshSet<3> *poly,
- Interpolator *old_interpolator,
- Interpolator *new_interpolator)
- {
- for (MeshSet<3>::const_face_iter face_iter = poly->faceBegin();
- face_iter != poly->faceEnd();
- ++face_iter)
- {
- const MeshSet<3>::face_t *face = *face_iter;
- for (int edge_index = 0;
- edge_index < face->nEdges();
- ++edge_index)
- {
- new_interpolator->copyAttribute(face,
- edge_index,
- old_interpolator);
- }
- }
- }
- template <typename Interpolator>
- void cleanupFaceEdgeAttrs(const MeshSet<3> *left,
- const MeshSet<3> *right,
- Interpolator *interpolator)
- {
- Interpolator new_interpolator;
- copyFaceEdgeAttrs(left, interpolator, &new_interpolator);
- copyFaceEdgeAttrs(right, interpolator, &new_interpolator);
- interpolator->swapAttributes(&new_interpolator);
- }
- void cleanupFaceEdgeAttrsCallback(const MeshSet<3> *left,
- const MeshSet<3> *right,
- void *descr_v)
- {
- CarveMeshDescr *descr = (CarveMeshDescr *) descr_v;
- cleanupFaceEdgeAttrs(left,
- right,
- &descr->face_edge_triangulated_flag);
- cleanupFaceEdgeAttrs(left,
- right,
- &descr->orig_face_edge_mapping);
- }
- void copyVertexAttrsCallback(const carve::mesh::MeshSet<3>::vertex_t *orig_vert,
- const carve::mesh::MeshSet<3>::vertex_t *new_vert,
- void *descr_v)
- {
- CarveMeshDescr *descr = (CarveMeshDescr *) descr_v;
- if (!descr->orig_vert_mapping.hasAttribute(orig_vert)) {
- return;
- }
- if (descr->orig_vert_mapping.hasAttribute(new_vert)) {
- return;
- }
- OrigIndex attr = descr->orig_vert_mapping.getAttribute(orig_vert);
- descr->orig_vert_mapping.setAttribute(new_vert, attr);
- descr->orig_vert_mapping.removeAttribute(orig_vert);
- }
- } // namespace
- CarveMeshDescr *carve_addMesh(struct ImportMeshData *import_data,
- CarveMeshImporter *mesh_importer)
- {
- #define MAX_STATIC_VERTS 64
- CarveMeshDescr *mesh_descr = new CarveMeshDescr;
- // Import verices from external mesh to Carve.
- int num_verts = mesh_importer->getNumVerts(import_data);
- std::vector<MeshSet<3>::vertex_t> vertex_storage;
- vertex_storage.reserve(num_verts);
- for (int i = 0; i < num_verts; i++) {
- float position[3];
- mesh_importer->getVertCoord(import_data, i, position);
- vertex_storage.push_back(carve::geom::VECTOR(position[0],
- position[1],
- position[2]));
- }
- // Import polys from external mesh to Carve.
- int verts_of_poly_static[MAX_STATIC_VERTS];
- int *verts_of_poly_dynamic = NULL;
- int verts_of_poly_dynamic_size = 0;
- int num_polys = mesh_importer->getNumPolys(import_data);
- int loop_index = 0;
- std::vector<int> face_indices;
- TrianglesStorage triangles_storage;
- std::vector<MeshSet<3>::face_t *> faces;
- std::vector<MeshSet<3>::vertex_t *> face_vertices;
- faces.reserve(num_polys);
- for (int i = 0; i < num_polys; i++) {
- int verts_per_poly =
- mesh_importer->getNumPolyVerts(import_data, i);
- int *verts_of_poly;
- if (verts_per_poly <= MAX_STATIC_VERTS) {
- verts_of_poly = verts_of_poly_static;
- }
- else {
- if (verts_of_poly_dynamic_size < verts_per_poly) {
- if (verts_of_poly_dynamic != NULL) {
- delete [] verts_of_poly_dynamic;
- }
- verts_of_poly_dynamic = new int[verts_per_poly];
- verts_of_poly_dynamic_size = verts_per_poly;
- }
- verts_of_poly = verts_of_poly_dynamic;
- }
- mesh_importer->getPolyVerts(import_data, i, verts_of_poly);
- carve::math::Matrix3 axis_matrix;
- if (!carve_checkPolyPlanarAndGetNormal(vertex_storage,
- verts_per_poly,
- verts_of_poly,
- &axis_matrix)) {
- face_indices.clear();
- int num_triangles = carve_triangulatePoly(import_data,
- mesh_importer,
- vertex_storage,
- verts_per_poly,
- verts_of_poly,
- axis_matrix,
- &face_indices,
- &triangles_storage);
- for (int j = 0; j < num_triangles; ++j) {
- MeshSet<3>::face_t *face = new MeshSet<3>::face_t(
- &vertex_storage[face_indices[j * 3]],
- &vertex_storage[face_indices[j * 3 + 1]],
- &vertex_storage[face_indices[j * 3 + 2]]);
- mesh_descr->orig_poly_index_map[face] = i;
- faces.push_back(face);
- }
- }
- else {
- face_vertices.clear();
- face_vertices.reserve(verts_per_poly);
- for (int j = 0; j < verts_per_poly; ++j) {
- face_vertices.push_back(&vertex_storage[verts_of_poly[j]]);
- }
- MeshSet<3>::face_t *face =
- new MeshSet<3>::face_t(face_vertices.begin(),
- face_vertices.end());
- mesh_descr->orig_poly_index_map[face] = i;
- faces.push_back(face);
- }
- 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) {
- delete [] verts_of_poly_dynamic;
- }
- std::vector<MeshSet<3>::mesh_t *> meshes;
- MeshSet<3>::mesh_t::create(faces.begin(), faces.end(), meshes, carve::mesh::MeshOptions());
- mesh_descr->poly = new MeshSet<3> (vertex_storage, meshes);
- return mesh_descr;
- #undef MAX_STATIC_VERTS
- }
- void carve_deleteMesh(CarveMeshDescr *mesh_descr)
- {
- delete mesh_descr->poly;
- delete mesh_descr;
- }
- bool carve_performBooleanOperation(CarveMeshDescr *left_mesh,
- CarveMeshDescr *right_mesh,
- int operation,
- CarveMeshDescr **output_mesh)
- {
- *output_mesh = NULL;
- carve::csg::CSG::OP op;
- switch (operation) {
- #define OP_CONVERT(the_op) \
- case CARVE_OP_ ## the_op: \
- op = carve::csg::CSG::the_op; \
- break;
- OP_CONVERT(UNION)
- OP_CONVERT(INTERSECTION)
- OP_CONVERT(A_MINUS_B)
- default:
- return false;
- #undef OP_CONVERT
- }
- CarveMeshDescr *output_descr = new CarveMeshDescr;
- output_descr->poly = NULL;
- try {
- MeshSet<3> *left = left_mesh->poly, *right = right_mesh->poly;
- carve::geom3d::Vector min, max;
- // TODO(sergey): Make importer/exporter to care about re-scale
- // to save extra mesh iteration here.
- carve_getRescaleMinMax(left, right, &min, &max);
- carve::rescale::rescale scaler(min.x, min.y, min.z, max.x, max.y, max.z);
- carve::rescale::fwd fwd_r(scaler);
- carve::rescale::rev rev_r(scaler);
- left->transform(fwd_r);
- right->transform(fwd_r);
- // Initialize attributes for maping from boolean result mesh back to
- // original geometry indices.
- initOrigIndexMapping(left_mesh, right_mesh,
- &output_descr->orig_vert_mapping,
- &output_descr->orig_face_edge_mapping,
- &output_descr->face_edge_triangulated_flag,
- &output_descr->orig_face_mapping);
- carve::csg::CSG csg;
- 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);
- output_descr->orig_face_edge_mapping.installHooks(csg);
- output_descr->face_edge_triangulated_flag.installHooks(csg);
- output_descr->orig_face_mapping.installHooks(csg);
- // Prepare operands for actual boolean operation.
- //
- // It's needed because operands might consist of several intersecting
- // meshes and in case of another operands intersect an edge loop of
- // intersecting that meshes tessellation of operation result can't be
- // done properly. The only way to make such situations working is to
- // union intersecting meshes of the same operand.
- carve_unionIntersections(&csg, &left, &right,
- copyVertexAttrsCallback,
- cleanupFaceEdgeAttrsCallback,
- (void *) output_descr);
- left_mesh->poly = left;
- right_mesh->poly = right;
- if (left->meshes.size() == 0 || right->meshes.size() == 0) {
- // Normally shouldn't happen (zero-faces objects are handled by
- // modifier itself), but unioning intersecting meshes which doesn't
- // have consistent normals might lead to empty result which
- // wouldn't work here.
- return false;
- }
- output_descr->poly = csg.compute(left,
- right,
- op,
- NULL,
- carve::csg::CSG::CLASSIFY_EDGE);
- if (output_descr->poly) {
- output_descr->poly->transform(rev_r);
- dissolveTriangulatedEdges(output_descr);
- }
- }
- catch (carve::exception e) {
- std::cerr << "CSG failed, exception " << e.str() << std::endl;
- }
- catch (...) {
- std::cerr << "Unknown error in Carve library" << std::endl;
- }
- *output_mesh = output_descr;
- return output_descr->poly != NULL;
- }
- 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)
- {
- MeshSet<3>::edge_t *edge = edges.at(i);
- MeshSet<3>::vertex_t *v1 = edge->v1();
- MeshSet<3>::vertex_t *v2 = edge->v2();
- 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),
- indexOf(v2, poly->vertex_storage),
- orig_edge_index.first,
- 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,
- CarveMeshExporter *mesh_exporter,
- struct ExportMeshData *export_data)
- {
- OrigIndex origindex_none = std::make_pair((int)CARVE_MESH_NONE, -1);
- MeshSet<3> *poly = mesh_descr->poly;
- int num_vertices = poly->vertex_storage.size();
- int num_edges = 0, num_loops = 0, num_polys = 0;
- // Get mapping from edge denoted by vertex pair to original edge index,
- //
- // This is needed because internally Carve interpolates data for per-face
- // edges rather then having some global edge storage.
- std::unordered_map<VertexPair, OrigIndex> edge_origindex_map;
- for (MeshSet<3>::face_iter face_iter = poly->faceBegin();
- face_iter != poly->faceEnd();
- ++face_iter)
- {
- MeshSet<3>::face_t *face = *face_iter;
- 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;
- int edge_iter_index = edge_iter.idx();
- const OrigIndex &orig_loop_index =
- mesh_descr->orig_face_edge_mapping.getAttribute(face,
- edge_iter_index,
- origindex_none);
- 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.v1();
- MeshSet<3>::vertex_t *v2 = edge.v2();
- 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) {
- MeshSet<3>::vertex_t *vertex = &(*vertex_iter);
- OrigIndex orig_vert_index =
- mesh_descr->orig_vert_mapping.getAttribute(vertex, origindex_none);
- float coord[3];
- coord[0] = vertex->v[0];
- coord[1] = vertex->v[1];
- coord[2] = vertex->v[2];
- mesh_exporter->setVert(export_data, i, coord,
- orig_vert_index.first,
- orig_vert_index.second);
- }
- // Export all the edges.
- std::unordered_map<VertexPair, int> edge_map;
- for (int i = 0, edge_index = 0; i < poly->meshes.size(); ++i) {
- carve::mesh::Mesh<3> *mesh = poly->meshes[i];
- // Export closed edges.
- edge_index += exportMesh_handle_edges_list(poly,
- mesh->closed_edges,
- edge_index,
- mesh_exporter,
- export_data,
- edge_origindex_map,
- &edge_map);
- // Export open edges.
- 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.
- MeshSet<3>::face_iter face_iter = poly->faceBegin();
- for (int loop_index = 0, poly_index = 0;
- face_iter != poly->faceEnd();
- ++face_iter, ++poly_index)
- {
- int start_loop_index = loop_index;
- MeshSet<3>::face_t *face = *face_iter;
- const OrigIndex &orig_face_index =
- mesh_descr->orig_face_mapping.getAttribute(face, origindex_none);
- for (MeshSet<3>::face_t::edge_iter_t edge_iter = face->begin();
- edge_iter != face->end();
- ++edge_iter, ++loop_index)
- {
- MeshSet<3>::edge_t &edge = *edge_iter;
- const OrigIndex &orig_loop_index =
- mesh_descr->orig_face_edge_mapping.getAttribute(face,
- edge_iter.idx(),
- origindex_none);
- mesh_exporter->setLoop(export_data,
- 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->nEdges(),
- orig_face_index.first, orig_face_index.second);
- }
- }
|