diff --git a/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c b/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c
index 30067c1902599722d710cd512290359bcb14241d..95eb2a6c31cbe866ecfdb58efb6f420267a1f3f1 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetDelaunay.c
@@ -768,17 +768,12 @@ HXT_ASSERT(((size_t) verticesID)%SIMD_ALIGN==0);
 
 
 /**************************************************************
- * compute adjacencies by sorting => O(n log n)
+ * compute adjacencies with a hash table => ~O(n)
  **************************************************************/
-
-static inline uint64_t hash64(uint64_t x) {
-    x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
-    x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb);
-    return x ^ (x >> 31);
-}
-
-// key must be unique, and it cannot be 0
-static inline uint64_t hashTableSearch(HXTGroup2* pairs, uint64_t mask, uint64_t key, uint64_t neigh) {
+// search neighbors in an already initialized hash table. `key` must be unique, and cannot be 0
+static inline uint64_t hashTableSearch(HXTGroup2* pairs, uint64_t mask, uint64_t key, uint64_t value) {
+  HXT_ASSERT(key != 0);
+  
   uint64_t hash = hash64(key) & mask;
   while(pairs[hash].v[0] != key && pairs[hash].v[0] != 0) {
     hash = (hash + 1) & mask;
@@ -788,11 +783,10 @@ static inline uint64_t hashTableSearch(HXTGroup2* pairs, uint64_t mask, uint64_t
   }
 
   pairs[hash].v[0] = key;
-  pairs[hash].v[1] = neigh;
+  pairs[hash].v[1] = value;
   return HXT_NO_ADJACENT;
 }
 
-
 static inline HXTStatus computeAdjacenciesSlow(HXTMesh* mesh, TetLocal* local, const uint64_t start, const uint64_t blength)
 {
   uint64_t size = UINT64_C(1) << u64_log2(5*blength);// 3*blength/2 entries => we want a hash table of at least 3*blength for a good load factor
@@ -845,7 +839,9 @@ static inline HXTStatus computeAdjacenciesSlow(HXTMesh* mesh, TetLocal* local, c
 }
 
 
-
+/**************************************************************
+ * compute adjacencies by sorting => O(n log n)
+ **************************************************************/
 // static inline HXTStatus computeAdjacenciesSlow(HXTMesh* mesh, TetLocal* local, const uint64_t start, const uint64_t blength)
 // {
 //   HXTGroup2* edges;
diff --git a/contrib/hxt/tetMesh/src/hxt_tetDelaunayReshape.c b/contrib/hxt/tetMesh/src/hxt_tetDelaunayReshape.c
index 87d13c029d0dbbed2d61a938bcfb8f5ec3b30a0a..8b1f0f1a8ecb56c7c2762cf52475214ad26deca2 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetDelaunayReshape.c
+++ b/contrib/hxt/tetMesh/src/hxt_tetDelaunayReshape.c
@@ -230,70 +230,153 @@ HXTStatus respectEdgeConstraint(TetLocal* local, HXTMesh* mesh, const uint32_t v
 }
 
 
-// functions above should be replaced
+// search neighbors in an already initialized hash table. `key` must be unique, and cannot be UINT64_MAX
+static inline void hashTablePut(HXTGroup2* pairs, uint64_t mask, uint64_t key, uint64_t value) {
+  HXT_ASSERT(key != UINT64_MAX);
+
+  uint64_t hash = hash64(key) & mask;
+  while(pairs[hash].v[0] != UINT64_MAX) {
+    HXT_ASSERT(pairs[hash].v[0] != key); // same key cannot already be there
+    hash = (hash + 1) & mask;
+  }
 
+  pairs[hash].v[0] = key;
+  pairs[hash].v[1] = value;
+}
 
+static inline uint64_t hashTableGet(HXTGroup2* pairs, uint64_t mask, uint64_t key) {
+  uint64_t hash = hash64(key) & mask;
+  while(pairs[hash].v[0] != key && pairs[hash].v[0] != UINT64_MAX) {
+    hash = (hash + 1) & mask;
+  }
+  if(pairs[hash].v[0] == key) {
+    return pairs[hash].v[1];
+  }
+  return HXT_NO_ADJACENT;
+}
 
 
-// make a super simple hash table to get a index in the deleted array (the value) from the index of a tet (the key)
-// the hash table is of a size similar to the number of tet in the cavity.
-typedef struct {
-  HXTGroup2* pairs; // key, value pairs
-  uint64_t mask;
-} HXTHashTable;
 
-HXTStatus hashTableInit(HXTHashTable* map, uint64_t numTet) {
-  unsigned h =  u64_log2(numTet) + 1;
-#ifdef DEBUG
-  if(h > 63)
-    return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
-#endif
 
-  uint64_t size = UINT64_C(1) << h;
-  map->mask = size - 1;
-  HXT_CHECK( hxtMalloc(&map->pairs, sizeof(HXTGroup2) * size) );
+// remove the tetrahedra adjacent to the face that does not see the point, progressively, until the cavity is star shaped...
+HXTStatus reshapeCavityIfNeeded(TetLocal* local, HXTMesh* mesh, const uint32_t vta, const uint64_t prevNumDeleted)
+{
+
+  // we need an array index for all faces that tells if the face is in the boundary or not, it should correspond to the deleted tet array
+  // In he same array, we can store adjacencies between deleted tet !
+  // => compute those adjacencies with a hash table.
+
+  // 1. put all the deleted tet in a hash table : key = meshIndex, value = deletedIndex
+  // 2. create the faces array
+  // 3. iterate over all deleted tet, and fill the faces array using the hash table. A special bit is set for non deleted neighbors
+  // 4. reshape the cavity
+
+  // point 1 and 2 can take a lot of memory... can we recycle some ??
+
+  uint64_t numTet = local->deleted.num - prevNumDeleted;
+  uint64_t* tets = &local->deleted.array[prevNumDeleted];
+
+  uint64_t size = UINT64_C(1) << u64_log2(5*numTet/2);// we want a hash table of at least 2.5*numTet for a good load factor
+  uint64_t mask = size - 1;
 
-  for(uint64_t i=0; i<size; i++) {
-    map->pairs[i].v[0] = HXT_NO_ADJACENT; // no tet in here
+  int64_t* faces;
+  HXTGroup2* pairs;
+
+  HXT_CHECK( hxtMalloc(&pairs, sizeof(HXTGroup2) * size));
+  memset(pairs, -1, size * sizeof(HXTGroup2));
+
+  // 1.
+  for(uint64_t i=0; i<numTet; i++) {
+    hashTablePut(pairs, mask, tets[i], i);
   }
 
-  return HXT_STATUS_OK;
-}
+  // 2.
+  HXT_CHECK( hxtMalloc(&faces, sizeof(int64_t) * 4 * numTet) );
 
-// this super simple hash table does not accept repeating the same element !
-void hashTablePut(HXTHashTable* map, uint64_t key, uint64_t value) {
-  uint64_t hash = key & map->mask;
-  while(map->pairs[hash].v[0] != HXT_NO_ADJACENT) {
-    hash = (hash + 1) & map->mask;
+  // 3.
+  uint64_t curFace = 0;
+  for(uint64_t i=0; i<numTet; i++) {
+    uint64_t curTet = tets[i];
+
+    for(int j=0; j<4; j++) {
+      // search in the table, but without replacing...
+      uint64_t neigh = mesh->tetrahedra.neigh[4 * curTet + j];
+      
+      if(neigh != HXT_NO_ADJACENT && getDeletedFlag(mesh, neigh / 4)) {
+        uint64_t deletedIndex = hashTableGet(pairs, mask, neigh / 4);
+        HXT_ASSERT(deletedIndex != HXT_NO_ADJACENT);
+
+        faces[4 * i + j] = 4 * deletedIndex + neigh % 4;
+      }
+      else { // it should be the next one in the ball, (we didn't change the order since @diggingACavity)
+        HXT_ASSERT(local->ball.array[curFace].neigh==neigh);
+        faces[4 * i + j] = -curFace;
+        curFace++;
+      }
+    }
   }
-  map->pairs[hash].v[0] = key;
-  map->pairs[hash].v[1] = value;
-}
 
-// this super simple hash talbe does not accept key that were not inserted !
-uint64_t hashTableGet(HXTHashTable* map, uint64_t key) {
-  uint64_t hash = key & map->mask;
-  while(map->pairs[hash].v[0] != key) {
-    hash = (hash + 1) & map->mask;
+  #ifndef NDEBUG
+  if(curFace != local->ball.num) {
+    return HXT_ERROR_MSG(HXT_STATUS_ERROR, "DEBUG: Faces did not appear in the same order as deleted tet");
   }
-  return map->pairs[hash].v[1];
-}
+  #endif
+
+  HXT_CHECK( hxtFree(&pairs) );
+
+
+  /* 4. iterate over all faces, and undelete (remove from the cavity) the associated tet when the face does not see vta
+   * We have got to update the faces array and the boundary correctly
+   * We also have to update the curFace index such that all faces below it are good
+   * and all faces above or equal are unchecked.
+   */
+
+
+  double *vtaCoord = &mesh->vertices.coord[4 * vta];
+
+  for (uint64_t curFace=0; curFace<local->ball.num; curFace++) {
+    if(local->ball.array[curFace].node[2]==HXT_GHOST_VERTEX){
+      continue;
+    }
+
+    double* b = &mesh->vertices.coord[4 * local->ball.array[curFace].node[0]];
+    double* c = &mesh->vertices.coord[4 * local->ball.array[curFace].node[1]];
+    double* d = &mesh->vertices.coord[4 * local->ball.array[curFace].node[2]];
+    if(orient3d(vtaCoord, b, c, d)<0.0){
+      continue;
+    }
+
+    // 4.1: undelete the tetrahedron
+    uint64_t exteriorNeigh = local->ball.array[curFace].neigh;
+    uint64_t interiorNeigh = mesh->tetrahedra.neigh[exteriorNeigh];
+    uint64_t tetToUndelete = interiorNeigh / 4;
+    unsigned facet = interiorNeigh % 4;
+    unsetDeletedFlag(mesh, tetToUndelete);
+
+    // 4.2 simply add the tetrahedron to a list of tet that we will have to undelete at the end
+    HXT_CHECK( askForDeleted(&local->deleted, 1) );
+    local->deleted.array[local->deleted.num] = tetToUndelete;
+
+    for(int f=0; f<4; f++) {
+      if(f == facet) { // this is the facet that we did not want
+        
+      }
+    }
+  }
+
+  HXT_CHECK( hxtFree(&faces) );
+
+
+  
+
 
-HXTStatus hashTableDestroy(HXTHashTable* map) {
-  HXT_CHECK( hxtFree(&map->pairs) );
-  return HXT_STATUS_OK;
-}
 
-// remove the tetrahedra adjacent to the face that does not see the point, progressively, until the cavity is star shaped...
-HXTStatus reshapeCavityIfNeeded(TetLocal* local, HXTMesh* mesh, const uint32_t vta, uint64_t prevNumDeleted)
-{
 //   uint64_t count = 0;
 
 //   // STEP 1: for each ball faces, we need the index of the tet in the deleted array, instead of the index of the tet in the mesh
 //   // for each deleted tet, we need the index of the 4 faces in the ball, or the index of the neighbor in the deleted array
 //   // if the facet is not a facet of the cavity. To differentiate both, BND_FACE_FLAG is set for indices of the ball.
-//   uint64_t numTet = local->deleted.num - prevNumDeleted;
-//   uint64_t* tets = &local->deleted.array[prevNumDeleted];
+
 
 
 //   HXTHashTable map;
@@ -307,31 +390,11 @@ HXTStatus reshapeCavityIfNeeded(TetLocal* local, HXTMesh* mesh, const uint32_t v
 //   uint64_t* faces;
 //   HXT_CHECK( hxtMalloc(&faces, sizeof(uint64_t) * 4 * numTet) );
 
-//   // just copy the adjacency into faces
-//   uint64_t curFace = 0;
-//   for(uint64_t i=0; i<numTet; i++) {
-//     uint64_t curTet = tets[i];
-//     for(uint64_t j=0; j<4; j++) {
-
-//       uint64_t neigh = mesh->tetrahedra.neigh[4 * curTet + j];
-//       if(neigh != HXT_NO_ADJACENT && getDeletedFlag(mesh, neigh / 4)) {
-//         faces[4 * i + j] = 4 * hashTableGet(&map, neigh / 4) + neigh % 4;
-//       }
-//       else { // it should be the next one in the ball, (we didn't change the order since @diggingACavity)
-//         HXT_ASSERT(local->ball.array[curFace].neigh==neigh);
-//         faces[4 * i + j] = curFace;
-//         curFace++;
-//       }
-//     }
-//   }
+
 
 //   HXT_CHECK( hashTableDestroy(&map) );
 
-// #ifndef NDEBUG
-//   if(curFace != local->ball.num) {
-//     return HXT_ERROR_MSG(HXT_STATUS_ERROR, "DEBUG: Faces did not appear in the same order as deleted tet");
-//   }
-// #endif
+
 
 //   // double *vtaCoord = &mesh->vertices.coord[4 * vta];
 
diff --git a/contrib/hxt/tetMesh/src/hxt_tetDelaunayReshape.h b/contrib/hxt/tetMesh/src/hxt_tetDelaunayReshape.h
index 30bea1d327ea97c224b1b185393d27fe44c03777..ab118548f2162154bba959d08b54486970d5c09f 100644
--- a/contrib/hxt/tetMesh/src/hxt_tetDelaunayReshape.h
+++ b/contrib/hxt/tetMesh/src/hxt_tetDelaunayReshape.h
@@ -60,6 +60,13 @@ static inline HXTStatus askForBall(TetLocal* local, uint64_t needed) {
 }
 
 
+static inline uint64_t hash64(uint64_t x) {
+    x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
+    x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb);
+    return x ^ (x >> 31);
+}
+
+
 // TODO: it only needs the ball and the deleted... no need to know about the whole tetLocal structure
 HXTStatus reshapeCavityIfNeeded(TetLocal* local, HXTMesh* mesh, const uint32_t vta, uint64_t prevNumDeleted);
 HXTStatus respectEdgeConstraint(TetLocal* local, HXTMesh* mesh, const uint32_t vta, const uint32_t color, const uint64_t prevDeleted);