diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-04-09 12:23:35 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-04-09 12:27:34 +0400 |
commit | ccf9afddbaa0a08f4e277b3c19bc15735be9f4a4 (patch) | |
tree | 676d2d4bc38f053606bfa24d545bdf1a7b3d2492 /extern/carve/carve-capi.cc | |
parent | dfbd994aaf6f95ddf3d6f9ecc64fa3a550b5e895 (diff) |
Fix T39608: Blender 2.70 crashes when performing union
This was a nasty bug which was caused by specific of how face-edge
attributes are stored in Carve.
Face pointer is used in the map key which works just fine in all
cases except for the cases when some face is getting freed after
it was stored in the map.
This might give real issues when new face is allocating because
it's possible new face would have the same address as the freed
one.
Such cases used to happen when union of separate manifolds is
needed for the operands AND jemalloc is enabled.
Solved by dropping attributes for the freed faces from the map.
Maybe not the fastest ever approach, but not sure how to make
it faster actually. Should work just fine. It only happens for
complex setups with intersecting manifolds in the operands.
Diffstat (limited to 'extern/carve/carve-capi.cc')
-rw-r--r-- | extern/carve/carve-capi.cc | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/extern/carve/carve-capi.cc b/extern/carve/carve-capi.cc index a65d1a8d766..af9ecad685d 100644 --- a/extern/carve/carve-capi.cc +++ b/extern/carve/carve-capi.cc @@ -38,7 +38,7 @@ 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::FaceEdgeAttr<OrigIndex> OrigFaceEdgeMapping; +typedef carve::interpolate::SwapableFaceEdgeAttr<OrigIndex> OrigFaceEdgeMapping; typedef carve::interpolate::SimpleFaceEdgeAttr<bool> FaceEdgeTriangulatedFlag; typedef struct CarveMeshDescr { @@ -522,6 +522,39 @@ public: } }; +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); +} + } // namespace CarveMeshDescr *carve_addMesh(struct ImportMeshData *import_data, @@ -698,7 +731,15 @@ bool carve_performBooleanOperation(CarveMeshDescr *left_mesh, // 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); + if (carve_unionIntersections(&csg, &left, &right)) { + cleanupFaceEdgeAttrs(left, + right, + &output_descr->face_edge_triangulated_flag); + cleanupFaceEdgeAttrs(left, + right, + &output_descr->orig_face_edge_mapping); + } + left_mesh->poly = left; right_mesh->poly = right; |