|
|
@ -1,36 +1,43 @@ |
|
|
|
#include <container/btree.hpp> |
|
|
|
|
|
|
|
#include <prim_gen.hpp> |
|
|
|
#include "base/primitive.hpp" |
|
|
|
|
|
|
|
struct packed_sign_counter { |
|
|
|
uint8_t positive : 4; |
|
|
|
uint8_t negative : 4; |
|
|
|
// struct packed_sign_counter {
|
|
|
|
// uint8_t positive : 4;
|
|
|
|
// uint8_t negative : 4;
|
|
|
|
|
|
|
|
inline packed_sign_counter& operator+=(const packed_sign_counter& rhs) |
|
|
|
{ |
|
|
|
positive += rhs.positive; |
|
|
|
negative += rhs.negative; |
|
|
|
return *this; |
|
|
|
} |
|
|
|
}; |
|
|
|
// inline packed_sign_counter& operator+=(const packed_sign_counter& rhs)
|
|
|
|
// {
|
|
|
|
// positive += rhs.positive;
|
|
|
|
// negative += rhs.negative;
|
|
|
|
// return *this;
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
void filter_tet_by_subface(const flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>>& vertex_to_tet_mapping, |
|
|
|
flat_hash_map_mp<uint32_t, bg_mesh_vert_info_t>& vertex_infos, |
|
|
|
Eigen::Ref<Eigen::MatrixXd> vertex_infos, |
|
|
|
flat_hash_map_mp<uint32_t, uint32_t>& vertex_indices_mapping, |
|
|
|
stl_vector_mp<std::array<uint32_t, 4>>& tetrahedrons, |
|
|
|
stl_vector_mp<uint32_t>& tetrahedron_active_subface_start_index, |
|
|
|
stl_vector_mp<uint32_t>& active_subface_indices, |
|
|
|
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>>& zero_vertex_to_incident_tet_mapping) |
|
|
|
{ |
|
|
|
stl_vector_mp<btree_map_mp<uint32_t, packed_sign_counter>> sign_counts{}; |
|
|
|
using sign_count_buffer_t = Eigen::Vector<uint8_t, Eigen::Dynamic>; |
|
|
|
stl_vector_mp<sign_count_buffer_t> sign_counts{}; |
|
|
|
dynamic_bitset_mp<> sign_count_initialized{}; |
|
|
|
sign_counts.resize(tetrahedrons.size()); |
|
|
|
sign_count_initialized.resize(tetrahedrons.size()); |
|
|
|
|
|
|
|
btree_map_mp<uint32_t, packed_sign_counter> temp_sign_counts{}; |
|
|
|
// the highest 4 bits as positive sign count, the lowest 4 bits as negative sign count
|
|
|
|
sign_count_buffer_t temp_sign_counts(vertex_infos.rows()); |
|
|
|
temp_sign_counts += temp_sign_counts; |
|
|
|
for (const auto& [vertex_index, tet_indices] : vertex_to_tet_mapping) { |
|
|
|
const auto& vertex_info = vertex_infos.at(vertex_index); |
|
|
|
auto vertex_info = vertex_infos.row(vertex_index); |
|
|
|
|
|
|
|
temp_sign_counts.clear(); |
|
|
|
for (const auto& subface_info : vertex_info) { |
|
|
|
switch (subface_info.sdf_sign) { |
|
|
|
temp_sign_counts.setZero(); |
|
|
|
for (auto i = 0; i < vertex_info.size(); ++i) { |
|
|
|
switch (sign_by_sdf(vertex_info[i])) { |
|
|
|
case sign_t::zero: { |
|
|
|
const auto& vertex_index_ = vertex_index; |
|
|
|
const auto& tet_indices_ = tet_indices; |
|
|
@ -39,60 +46,58 @@ void filter_tet_by_subface(const flat_hash_map_mp<uint32_t, stl_vector_mp<uint32 |
|
|
|
}); |
|
|
|
break; |
|
|
|
} |
|
|
|
case sign_t::positive: temp_sign_counts[subface_info.subface_index].positive++; break; |
|
|
|
case sign_t::negative: temp_sign_counts[subface_info.subface_index].negative++; break; |
|
|
|
case sign_t::positive: temp_sign_counts[i] += 16; break; |
|
|
|
case sign_t::negative: temp_sign_counts[i] += 1; break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// broadcast sign counts of current vertex to all neighboring tetrahedrons
|
|
|
|
for (const auto& [subface_index, counts] : temp_sign_counts) { |
|
|
|
for (const auto& tet_index : tet_indices) { |
|
|
|
auto& tet_sign_counts = sign_counts[tet_index]; |
|
|
|
|
|
|
|
auto [iter, is_new_item] = tet_sign_counts.try_emplace(subface_index, counts); |
|
|
|
if (!is_new_item) iter->second += counts; |
|
|
|
if (!sign_count_initialized[tet_index]) { |
|
|
|
sign_counts[tet_index] = temp_sign_counts; |
|
|
|
sign_count_initialized.set(tet_index); |
|
|
|
} else { |
|
|
|
sign_counts[tet_index] += temp_sign_counts; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// filter tetrahedrons' subfaces which have same but not 0 signs
|
|
|
|
// and filter active terahedrons by the way
|
|
|
|
stl_vector_mp<std::array<uint32_t, 4>> filtered_tets{}; |
|
|
|
stl_vector_mp<uint32_t> filtered_active_vertices{}; |
|
|
|
filtered_tets.reserve(tetrahedrons.size()); |
|
|
|
filtered_active_vertices.reserve(tetrahedrons.size() * 4); |
|
|
|
tetrahedron_active_subface_start_index.reserve(tetrahedrons.size() + 1); |
|
|
|
active_subface_indices.reserve(tetrahedrons.size()); |
|
|
|
tetrahedron_active_subface_start_index.emplace_back(0); |
|
|
|
for (const auto& tet_info : sign_counts) { |
|
|
|
for (const auto& [subface_index, counts] : tet_info) { |
|
|
|
if (counts.positive < 4 && counts.negative < 4) active_subface_indices.emplace_back(subface_index); |
|
|
|
for (auto i = 0; i < tetrahedrons.size(); ++i) { |
|
|
|
const auto& tet_info = sign_counts[i]; |
|
|
|
for (auto j = 0; j < tet_info.size(); ++j) { |
|
|
|
auto sign = tet_info[j]; |
|
|
|
if ((sign & 0x0F) < 4 && (sign >> 4) < 4) { active_subface_indices.emplace_back(j); } |
|
|
|
} |
|
|
|
if (active_subface_indices.size() > tetrahedron_active_subface_start_index.back()) { |
|
|
|
tetrahedron_active_subface_start_index.emplace_back(active_subface_indices.size()); |
|
|
|
} |
|
|
|
active_subface_indices.shrink_to_fit(); |
|
|
|
|
|
|
|
stl_vector_mp<std::array<uint32_t, 4>> filtered_tets{}; |
|
|
|
stl_vector_mp<uint32_t> filtered_tetrahedron_active_subface_start_index{}; |
|
|
|
stl_vector_mp<uint32_t> filtered_active_vertices{}; |
|
|
|
filtered_tets.reserve(tetrahedrons.size()); |
|
|
|
filtered_tetrahedron_active_subface_start_index.reserve(tetrahedrons.size()); |
|
|
|
filtered_active_vertices.reserve(tetrahedrons.size()); |
|
|
|
for (size_t i = 0; i < tetrahedrons.size(); ++i) { |
|
|
|
if (tetrahedron_active_subface_start_index[i] < tetrahedron_active_subface_start_index[i + 1]) { |
|
|
|
filtered_tetrahedron_active_subface_start_index.emplace_back(tetrahedron_active_subface_start_index[i]); |
|
|
|
const auto& vertices = filtered_tets.emplace_back(std::move(tetrahedrons[i])); |
|
|
|
filtered_active_vertices.insert(filtered_active_vertices.end(), vertices.begin(), vertices.end()); |
|
|
|
} |
|
|
|
} |
|
|
|
// always keep the last element of tetrahedron_active_subface_start_index as an ender
|
|
|
|
filtered_tetrahedron_active_subface_start_index.emplace_back(tetrahedron_active_subface_start_index.back()); |
|
|
|
filtered_tetrahedron_active_subface_start_index.shrink_to_fit(); |
|
|
|
active_subface_indices.shrink_to_fit(); |
|
|
|
filtered_tets.shrink_to_fit(); |
|
|
|
std::swap(filtered_tetrahedron_active_subface_start_index, tetrahedron_active_subface_start_index); |
|
|
|
filtered_active_vertices.shrink_to_fit(); |
|
|
|
std::swap(filtered_tets, tetrahedrons); |
|
|
|
|
|
|
|
flat_hash_map_mp<uint32_t, bg_mesh_vert_info_t> filtered_vert_infos{}; |
|
|
|
std::sort(filtered_active_vertices.begin(), filtered_active_vertices.end()); |
|
|
|
auto end_iter = std::unique(filtered_active_vertices.begin(), filtered_active_vertices.end()); |
|
|
|
auto vertex_count = std::distance(filtered_active_vertices.begin(), end_iter); |
|
|
|
Eigen::MatrixXd filtered_vert_infos(vertex_count, vertex_infos.cols()); |
|
|
|
auto filtered_vert_infos_iter = filtered_vert_infos.rowwise().begin(); |
|
|
|
for (auto iter = filtered_active_vertices.begin(); iter != end_iter; ++iter) { |
|
|
|
const auto vertex_index = *iter; |
|
|
|
filtered_vert_infos.emplace(vertex_index, vertex_infos.at(vertex_index)); |
|
|
|
*filtered_vert_infos_iter = vertex_infos.row(vertex_index); |
|
|
|
vertex_indices_mapping[vertex_index] = std::distance(filtered_active_vertices.begin(), iter); |
|
|
|
filtered_vert_infos_iter++; |
|
|
|
} |
|
|
|
std::swap(filtered_vert_infos, vertex_infos); |
|
|
|
vertex_infos = filtered_vert_infos; |
|
|
|
} |