|
|
@ -4,16 +4,15 @@ |
|
|
|
|
|
|
|
// ===========================================================================================================
|
|
|
|
|
|
|
|
void collect_active_prims(const flat_index_group& patches, |
|
|
|
const flat_index_group& chain_of_patch, |
|
|
|
const flat_index_group& arrangement_cells, |
|
|
|
void collect_active_prims(const flat_index_group& patches, |
|
|
|
const flat_index_group& chain_of_patch, |
|
|
|
const flat_index_group& arrangement_cells, |
|
|
|
const stl_vector_mp<uint32_t>& shell_of_half_patch, |
|
|
|
const flat_index_group& shells, |
|
|
|
const flat_index_group& shells, |
|
|
|
const stl_vector_mp<uint32_t>& shell_to_cell, |
|
|
|
const dynamic_bitset_mp<>& active_cell_label, |
|
|
|
dynamic_bitset_mp<>& active_patch_label, |
|
|
|
dynamic_bitset_mp<>& patch_sign_label, |
|
|
|
dynamic_bitset_mp<>& active_chain_label) |
|
|
|
dynamic_bitset_mp<>& patch_sign_label) |
|
|
|
{ |
|
|
|
stl_vector_mp<bool> visited_cells(arrangement_cells.size(), false); |
|
|
|
std::queue<uint32_t> Q{}; |
|
|
@ -36,10 +35,6 @@ void collect_active_prims(const flat_index_group& patches, |
|
|
|
active_patch_label[patch_index].flip(); |
|
|
|
patch_sign_label[patch_index] = ((half_patch_index & 1) == 0); |
|
|
|
|
|
|
|
chain_of_patch.loop_on_group(patch_index, [&](uint32_t _, uint32_t chain_index) { |
|
|
|
active_chain_label[chain_index].set(); |
|
|
|
}); |
|
|
|
|
|
|
|
auto oppose_cell = shell_to_cell[shell_of_half_patch[(half_patch_index & 1) == 1 ? (half_patch_index + 1) |
|
|
|
: (half_patch_index - 1)]]; |
|
|
|
if (active_cell_label[oppose_cell] && !visited_cells[oppose_cell]) Q.emplace(oppose_cell); |
|
|
@ -49,89 +44,140 @@ void collect_active_prims(const flat_index_group& patches, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ===========================================================================================================
|
|
|
|
|
|
|
|
dynamic_bitset_mp<> filter_polygon_faces(const stl_vector_mp<polygon_face_t>& faces, |
|
|
|
const flat_index_group& patches, |
|
|
|
const flat_index_group& arrangement_cells, |
|
|
|
const stl_vector_mp<uint32_t>& shell_of_half_patch, |
|
|
|
const flat_index_group& shells, |
|
|
|
const stl_vector_mp<uint32_t>& shell_to_cell, |
|
|
|
const dynamic_bitset_mp<>& active_cell_label, |
|
|
|
stl_vector_mp<uint32_t>& output_polygon_faces, |
|
|
|
stl_vector_mp<uint32_t>& output_vertex_counts_of_face) |
|
|
|
void transfer_active_prims(const stl_vector_mp<polygon_face_t>& faces, |
|
|
|
const flat_index_group& patches, |
|
|
|
const flat_index_group& chain_of_patch, |
|
|
|
const dynamic_bitset_mp<>& active_patch_label, |
|
|
|
const dynamic_bitset_mp<>& patch_sign_label, |
|
|
|
stl_vector_mp<uint32_t>& output_polygon_faces, |
|
|
|
stl_vector_mp<uint32_t>& output_vertex_counts_of_face, |
|
|
|
stl_vector_mp<parametric_plane>& output_parametric_planes) |
|
|
|
{ |
|
|
|
dynamic_bitset_mp<> active_face_label(faces.size(), false); |
|
|
|
dynamic_bitset_mp<> active_patch_label(patches.size(), false); |
|
|
|
dynamic_bitset_mp<> patch_sign_label(patches.size(), false); |
|
|
|
output_polygon_faces.reserve(faces.size() * 3); |
|
|
|
output_vertex_counts_of_face.reserve(faces.size()); |
|
|
|
auto active_patch_index = active_patch_label.find_first(); |
|
|
|
if (active_patch_index != dynamic_bitset_mp<>::npos) { |
|
|
|
do { |
|
|
|
// NOTE: since patch inside the sdf should be oriented counterclockwise when viewed from inside
|
|
|
|
// i.e. it is viewed to be clockwise when viewed from outside
|
|
|
|
// so we need to flip its vertex order here
|
|
|
|
// NOTE: as for the integral, surface integral is always positive so we just add them up
|
|
|
|
// however for the partial volume integral, the right one should be corresponding to the normal which
|
|
|
|
// points outside. Here's a simple prove that the partial volume integral always have right sign: If the
|
|
|
|
// surface is outside (i.e. counterclockwise), then it is obviously right; If the surface is inside
|
|
|
|
// (i.e. clockwise), then its normal should point to the other side of that surface, which is the
|
|
|
|
// outside of that surface, so it is also right
|
|
|
|
if (!patch_sign_label[active_patch_index]) { |
|
|
|
patches.loop_on_group(active_patch_index, [&](uint32_t _, uint32_t face_index) { |
|
|
|
const auto& face_vertices = faces[face_index].vertex_indices; |
|
|
|
output_vertex_counts_of_face.emplace_back(face_vertices.size()); |
|
|
|
output_polygon_faces.insert(output_polygon_faces.end(), |
|
|
|
std::make_move_iterator(face_vertices.rbegin()), |
|
|
|
std::make_move_iterator(face_vertices.rend())); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
patches.loop_on_group(active_patch_index, [&](uint32_t _, uint32_t face_index) { |
|
|
|
const auto& face_vertices = faces[face_index].vertex_indices; |
|
|
|
output_vertex_counts_of_face.emplace_back(face_vertices.size()); |
|
|
|
output_polygon_faces.insert(output_polygon_faces.end(), |
|
|
|
std::make_move_iterator(face_vertices.begin()), |
|
|
|
std::make_move_iterator(face_vertices.end())); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
stl_vector_mp<bool> visited_cells(arrangement_cells.size(), false); |
|
|
|
std::queue<uint32_t> Q{}; |
|
|
|
for (uint32_t i = 0; i < arrangement_cells.size(); ++i) { |
|
|
|
if (active_cell_label[i]) { |
|
|
|
Q.emplace(i); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
while (!Q.empty()) { |
|
|
|
const auto cell_index = Q.front(); |
|
|
|
Q.pop(); |
|
|
|
chain_of_patch.loop_on_group(active_patch_index, |
|
|
|
[&](uint32_t _, uint32_t chain_index) { active_chain_label[chain_index].set(); }); |
|
|
|
|
|
|
|
if (!visited_cells[cell_index] && active_cell_label[cell_index]) { |
|
|
|
visited_cells[cell_index] = true; |
|
|
|
arrangement_cells.loop_on_group(cell_index, [&](uint32_t _, uint32_t shell_index) { |
|
|
|
// it is secured that one shell cell cannot have a pair of half patches with same patch index
|
|
|
|
shells.loop_on_group(shell_index, [&](uint32_t _, uint32_t half_patch_index) { |
|
|
|
bool sign = (half_patch_index % 2 == 0) ? 0 : 1; |
|
|
|
auto oppose_cell = |
|
|
|
shell_to_cell[shell_of_half_patch[!sign ? (half_patch_index + 1) : (half_patch_index - 1)]]; |
|
|
|
|
|
|
|
// iff not interior patch, we do surface propagation
|
|
|
|
if (!active_cell_label[oppose_cell]) { |
|
|
|
// NOTE: since patch inside the sdf should be oriented counterclockwise when viewed from inside
|
|
|
|
// i.e. it is viewed to be clockwise when viewed from outside
|
|
|
|
// so we need to flip its vertex order here
|
|
|
|
// NOTE: as for the integral, surface integral is always positive so we just add them up
|
|
|
|
// however for the partial volume integral, the right one should be corresponding to the normal which
|
|
|
|
// points outside. Here's a simple prove that the partial volume integral always have right sign: If the
|
|
|
|
// surface is outside (i.e. counterclockwise), then it is obviously right; If the surface is inside
|
|
|
|
// (i.e. clockwise), then its normal should point to the other side of that surface, which is the
|
|
|
|
// outside of that surface, so it is also right
|
|
|
|
if (!sign) { |
|
|
|
patches.loop_on_group(half_patch_index / 2, [&](uint32_t _, uint32_t face_index) { |
|
|
|
active_face_label[face_index] = true; |
|
|
|
const auto& face_vertices = faces[face_index].vertex_indices; |
|
|
|
output_vertex_counts_of_face.emplace_back(face_vertices.size()); |
|
|
|
output_polygon_faces.insert(output_polygon_faces.end(), |
|
|
|
std::make_move_iterator(face_vertices.rbegin()), |
|
|
|
std::make_move_iterator(face_vertices.rend())); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
patches.loop_on_group(half_patch_index / 2, [&](uint32_t _, uint32_t face_index) { |
|
|
|
active_face_label[face_index] = true; |
|
|
|
const auto& face_vertices = faces[face_index].vertex_indices; |
|
|
|
output_vertex_counts_of_face.emplace_back(face_vertices.size()); |
|
|
|
output_polygon_faces.insert(output_polygon_faces.end(), |
|
|
|
std::make_move_iterator(face_vertices.begin()), |
|
|
|
std::make_move_iterator(face_vertices.end())); |
|
|
|
}); |
|
|
|
} |
|
|
|
} else if (!visited_cells[oppose_cell]) { |
|
|
|
// active and not visited cell, enqueue it
|
|
|
|
Q.emplace(oppose_cell); |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
active_patch_index = active_patch_label.find_next(active_patch_index); |
|
|
|
} while (active_patch_index != dynamic_bitset_mp<>::npos); |
|
|
|
} |
|
|
|
|
|
|
|
output_polygon_faces.shrink_to_fit(); |
|
|
|
output_vertex_counts_of_face.shrink_to_fit(); |
|
|
|
return active_face_label; |
|
|
|
} |
|
|
|
|
|
|
|
// ===========================================================================================================
|
|
|
|
|
|
|
|
// dynamic_bitset_mp<> filter_polygon_faces(const stl_vector_mp<polygon_face_t>& faces,
|
|
|
|
// const flat_index_group& patches,
|
|
|
|
// const flat_index_group& arrangement_cells,
|
|
|
|
// const stl_vector_mp<uint32_t>& shell_of_half_patch,
|
|
|
|
// const flat_index_group& shells,
|
|
|
|
// const stl_vector_mp<uint32_t>& shell_to_cell,
|
|
|
|
// const dynamic_bitset_mp<>& active_cell_label,
|
|
|
|
// stl_vector_mp<uint32_t>& output_polygon_faces,
|
|
|
|
// stl_vector_mp<uint32_t>& output_vertex_counts_of_face)
|
|
|
|
// {
|
|
|
|
// dynamic_bitset_mp<> active_face_label(faces.size(), false);
|
|
|
|
// dynamic_bitset_mp<> active_patch_label(patches.size(), false);
|
|
|
|
// dynamic_bitset_mp<> patch_sign_label(patches.size(), false);
|
|
|
|
// output_polygon_faces.reserve(faces.size() * 3);
|
|
|
|
// output_vertex_counts_of_face.reserve(faces.size());
|
|
|
|
|
|
|
|
// stl_vector_mp<bool> visited_cells(arrangement_cells.size(), false);
|
|
|
|
// std::queue<uint32_t> Q{};
|
|
|
|
// for (uint32_t i = 0; i < arrangement_cells.size(); ++i) {
|
|
|
|
// if (active_cell_label[i]) {
|
|
|
|
// Q.emplace(i);
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// while (!Q.empty()) {
|
|
|
|
// const auto cell_index = Q.front();
|
|
|
|
// Q.pop();
|
|
|
|
|
|
|
|
// if (!visited_cells[cell_index] && active_cell_label[cell_index]) {
|
|
|
|
// visited_cells[cell_index] = true;
|
|
|
|
// arrangement_cells.loop_on_group(cell_index, [&](uint32_t _, uint32_t shell_index) {
|
|
|
|
// // it is secured that one shell cell cannot have a pair of half patches with same patch index
|
|
|
|
// shells.loop_on_group(shell_index, [&](uint32_t _, uint32_t half_patch_index) {
|
|
|
|
// bool sign = (half_patch_index % 2 == 0) ? 0 : 1;
|
|
|
|
// auto oppose_cell =
|
|
|
|
// shell_to_cell[shell_of_half_patch[!sign ? (half_patch_index + 1) : (half_patch_index - 1)]];
|
|
|
|
|
|
|
|
// // iff not interior patch, we do surface propagation
|
|
|
|
// if (!active_cell_label[oppose_cell]) {
|
|
|
|
// // NOTE: since patch inside the sdf should be oriented counterclockwise when viewed from inside
|
|
|
|
// // i.e. it is viewed to be clockwise when viewed from outside
|
|
|
|
// // so we need to flip its vertex order here
|
|
|
|
// // NOTE: as for the integral, surface integral is always positive so we just add them up
|
|
|
|
// // however for the partial volume integral, the right one should be corresponding to the normal which
|
|
|
|
// // points outside. Here's a simple prove that the partial volume integral always have right sign: If
|
|
|
|
// the
|
|
|
|
// // surface is outside (i.e. counterclockwise), then it is obviously right; If the surface is inside
|
|
|
|
// // (i.e. clockwise), then its normal should point to the other side of that surface, which is the
|
|
|
|
// // outside of that surface, so it is also right
|
|
|
|
// if (!sign) {
|
|
|
|
// patches.loop_on_group(half_patch_index / 2, [&](uint32_t _, uint32_t face_index) {
|
|
|
|
// active_face_label[face_index] = true;
|
|
|
|
// const auto& face_vertices = faces[face_index].vertex_indices;
|
|
|
|
// output_vertex_counts_of_face.emplace_back(face_vertices.size());
|
|
|
|
// output_polygon_faces.insert(output_polygon_faces.end(),
|
|
|
|
// std::make_move_iterator(face_vertices.rbegin()),
|
|
|
|
// std::make_move_iterator(face_vertices.rend()));
|
|
|
|
// });
|
|
|
|
// } else {
|
|
|
|
// patches.loop_on_group(half_patch_index / 2, [&](uint32_t _, uint32_t face_index) {
|
|
|
|
// active_face_label[face_index] = true;
|
|
|
|
// const auto& face_vertices = faces[face_index].vertex_indices;
|
|
|
|
// output_vertex_counts_of_face.emplace_back(face_vertices.size());
|
|
|
|
// output_polygon_faces.insert(output_polygon_faces.end(),
|
|
|
|
// std::make_move_iterator(face_vertices.begin()),
|
|
|
|
// std::make_move_iterator(face_vertices.end()));
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
// } else if (!visited_cells[oppose_cell]) {
|
|
|
|
// // active and not visited cell, enqueue it
|
|
|
|
// Q.emplace(oppose_cell);
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// output_polygon_faces.shrink_to_fit();
|
|
|
|
// output_vertex_counts_of_face.shrink_to_fit();
|
|
|
|
// return active_face_label;
|
|
|
|
// }
|
|
|
|
|
|
|
|
void filter_active_vertices(stl_vector_mp<Eigen::Vector3d>& vertices, stl_vector_mp<uint32_t>& output_polygon_faces) |
|
|
|
{ |
|
|
|
stl_vector_mp<uint32_t> unique_vertex_indices{}; |
|
|
|