You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
227 lines
11 KiB
227 lines
11 KiB
#include <process.hpp>
|
|
|
|
#include <prim_gen.hpp>
|
|
#include <connect_by_topo.hpp>
|
|
#include <post_topo.hpp>
|
|
|
|
#include <fstream>
|
|
|
|
|
|
void export_halfpatch_obj(
|
|
const stl_vector_mp<Eigen::Vector3d>& iso_pts,
|
|
const stl_vector_mp<polygon_face_t>& iso_faces,
|
|
const stl_vector_mp<stl_vector_mp<uint32_t>>& patches,
|
|
const std::string& filename)
|
|
{
|
|
std::string mtl_filename = filename + ".mtl";
|
|
std::ofstream mtl(mtl_filename);
|
|
for (size_t half_patch = 0; half_patch < patches.size() * 2; ++half_patch) {
|
|
size_t patch_idx = half_patch / 2;
|
|
bool is_forward = (half_patch % 2 == 0);
|
|
mtl << "newmtl patch_" << patch_idx << (is_forward ? "_in" : "_out") << "\n";
|
|
// 随机或规律分配颜色
|
|
float r = float(patch_idx % 7) / 7.0f;
|
|
float g = float(patch_idx % 3) / 3.0f;
|
|
float b = float(patch_idx % 5) / 5.0f;
|
|
mtl << "Kd " << r << " " << g << " " << b << "\n";
|
|
}
|
|
mtl.close();
|
|
|
|
std::string obj_filename = filename + ".obj";
|
|
std::ofstream ofs(obj_filename);
|
|
if (!ofs) return;
|
|
|
|
ofs << "mtllib "<< mtl_filename << "\n";
|
|
|
|
// 输出所有顶点
|
|
for (const auto& v : iso_pts) {
|
|
ofs << "v " << v.x() << " " << v.y() << " " << v.z() << "\n";
|
|
}
|
|
|
|
// 遍历所有 half-patch
|
|
for (size_t half_patch = 0; half_patch < patches.size() * 2; ++half_patch) {
|
|
size_t patch_idx = half_patch / 2;
|
|
bool is_forward = (half_patch % 2 == 0);
|
|
ofs << "g halfpatch_" << half_patch << "\n";
|
|
ofs << "usemtl patch_" << patch_idx << (is_forward ? "_in" : "_out") << "\n";
|
|
for (auto face_idx : patches[patch_idx]) {
|
|
const auto& face = iso_faces[face_idx];
|
|
ofs << "f";
|
|
if (is_forward) {
|
|
for (auto vi : face.vertex_indices)
|
|
ofs << " " << (vi + 1);
|
|
} else {
|
|
for (auto it = face.vertex_indices.rbegin(); it != face.vertex_indices.rend(); ++it)
|
|
ofs << " " << (*it + 1);
|
|
}
|
|
ofs << "\n";
|
|
}
|
|
}
|
|
ofs.close();
|
|
}
|
|
|
|
|
|
ISNP_API void build_implicit_network_by_blobtree(const s_settings& settings,
|
|
const baked_blobtree_t& tree,
|
|
stl_vector_mp<Eigen::Vector3d>& output_vertices,
|
|
stl_vector_mp<uint32_t>& output_polygon_faces,
|
|
stl_vector_mp<uint32_t>& output_vertex_counts_of_face)
|
|
{
|
|
// load LUT for implicit arrangement
|
|
load_lut();
|
|
|
|
scene_bg_mesh_info_t scene_bg_mesh_info{};
|
|
stl_vector_mp<std::array<uint32_t, 4>> tetrahedrons{};
|
|
flat_hash_map_mp<uint32_t, uint32_t> vertex_lexigraphical_adjacency{};
|
|
stl_vector_mp<uint32_t> tetrahedron_active_subface_start_index{};
|
|
stl_vector_mp<uint32_t> active_subface_indices{};
|
|
stl_vector_mp<arrangement_t> tetrahedron_arrangements{};
|
|
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> zero_vertex_to_incident_tet_mapping{};
|
|
stl_vector_mp<Eigen::Vector3d> iso_pts{};
|
|
stl_vector_mp<iso_vertex_t> iso_verts{};
|
|
stl_vector_mp<polygon_face_t> iso_faces{};
|
|
// primitive generation
|
|
{
|
|
Eigen::MatrixXd vertex_infos =
|
|
Eigen::MatrixXd::Zero((settings.resolution + 1) * (settings.resolution + 1) * (settings.resolution + 1),
|
|
tree.subfaces.size());
|
|
flat_hash_map_mp<uint32_t, uint32_t> vertex_indices_mapping{};
|
|
{
|
|
btree_map_mp<uint32_t, stl_vector_mp<uint32_t>> vertex_to_tet_mapping{};
|
|
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> reverse_vertex_adjacency{};
|
|
{
|
|
stl_vector_mp<grid_region> vertex_exist_regions{};
|
|
extract_vertex_infos(settings, tree, scene_bg_mesh_info, vertex_infos);
|
|
build_tetrahedron_and_adjacency(scene_bg_mesh_info,
|
|
tetrahedrons,
|
|
vertex_lexigraphical_adjacency,
|
|
reverse_vertex_adjacency,
|
|
vertex_to_tet_mapping);
|
|
}
|
|
filter_tet_by_subface(vertex_to_tet_mapping,
|
|
vertex_infos,
|
|
vertex_indices_mapping,
|
|
tetrahedrons,
|
|
vertex_lexigraphical_adjacency,
|
|
reverse_vertex_adjacency,
|
|
tetrahedron_active_subface_start_index,
|
|
active_subface_indices,
|
|
zero_vertex_to_incident_tet_mapping);
|
|
}
|
|
|
|
auto tet_active_subface_counts = compute_implicit_arrangements(vertex_infos,
|
|
vertex_indices_mapping,
|
|
tetrahedrons,
|
|
tetrahedron_active_subface_start_index,
|
|
active_subface_indices,
|
|
tetrahedron_arrangements);
|
|
extract_iso_mesh(tet_active_subface_counts,
|
|
tetrahedron_arrangements,
|
|
scene_bg_mesh_info,
|
|
tetrahedrons,
|
|
tetrahedron_active_subface_start_index,
|
|
active_subface_indices,
|
|
vertex_infos,
|
|
vertex_indices_mapping,
|
|
iso_pts,
|
|
iso_verts,
|
|
iso_faces);
|
|
}
|
|
// connect components by topology
|
|
stl_vector_mp<uint32_t> patch_of_face(iso_faces.size());
|
|
stl_vector_mp<uint32_t> shell_of_half_patch{};
|
|
stl_vector_mp<uint32_t> component_of_patch{};
|
|
stl_vector_mp<stl_vector_mp<uint32_t>> patches{};
|
|
stl_vector_mp<stl_list_mp<iso_edge_t>> chains{};
|
|
stl_vector_mp<stl_vector_mp<uint32_t>> shells{};
|
|
stl_vector_mp<stl_vector_mp<uint32_t>> components{};
|
|
stl_vector_mp<stl_vector_mp<uint32_t>> arrangement_cells{};
|
|
stl_vector_mp<uint32_t> shell_to_cell{};
|
|
{
|
|
{
|
|
stl_vector_mp<stl_vector_mp<uint32_t>> edges_of_iso_face{};
|
|
stl_vector_mp<iso_edge_t> iso_edges{};
|
|
compute_patch_edges(iso_faces, edges_of_iso_face, iso_edges);
|
|
compute_patches(edges_of_iso_face, iso_edges, iso_faces, patches, patch_of_face);
|
|
compute_chains(iso_verts.size(), iso_edges, chains);
|
|
export_halfpatch_obj(iso_pts, iso_faces, patches, "halfpatch_before_connect");
|
|
}
|
|
stl_vector_mp<stl_vector_mp<uint32_t>> half_patch_adj_list(2 * patches.size());
|
|
for (size_t i = 0; i < chains.size(); ++i)
|
|
compute_patch_order(tetrahedrons,
|
|
chains[i].front(),
|
|
iso_verts,
|
|
iso_faces,
|
|
tetrahedron_arrangements,
|
|
tetrahedron_active_subface_start_index,
|
|
active_subface_indices,
|
|
zero_vertex_to_incident_tet_mapping,
|
|
patch_of_face,
|
|
half_patch_adj_list);
|
|
compute_shells_and_components(half_patch_adj_list, shells, shell_of_half_patch, components, component_of_patch);
|
|
|
|
if (components.size() == 1) // no nesting problem, each shell is an arrangement cell
|
|
{
|
|
arrangement_cells.reserve(shells.size());
|
|
for (uint32_t i = 0; i < shells.size(); ++i) { arrangement_cells.emplace_back(stl_vector_mp<uint32_t>{i}); }
|
|
|
|
} else {
|
|
{
|
|
stl_vector_mp<std::pair<uint32_t, uint32_t>> shell_links{};
|
|
topo_ray_shooting(scene_bg_mesh_info,
|
|
tetrahedrons,
|
|
vertex_lexigraphical_adjacency,
|
|
tetrahedron_arrangements,
|
|
iso_verts,
|
|
iso_faces,
|
|
patches,
|
|
patch_of_face,
|
|
shells,
|
|
shell_of_half_patch,
|
|
components,
|
|
component_of_patch,
|
|
shell_links);
|
|
compute_arrangement_cells(static_cast<uint32_t>(shells.size()), shell_links, arrangement_cells);
|
|
}
|
|
}
|
|
shell_to_cell.resize(shells.size());
|
|
for (uint32_t i = 0; i < arrangement_cells.size(); i++) {
|
|
for (auto shell : arrangement_cells[i]) shell_to_cell[shell] = i;
|
|
}
|
|
// post process
|
|
{
|
|
dynamic_bitset_mp<> active_cell_label{};
|
|
{
|
|
stl_vector_mp<dynamic_bitset_mp<>> cell_primitive_signs(tree.primitives.size(),
|
|
dynamic_bitset_mp<>(arrangement_cells.size()));
|
|
{
|
|
stl_vector_mp<dynamic_bitset_mp<>> cell_subface_signs(tree.subfaces.size(),
|
|
dynamic_bitset_mp<>(arrangement_cells.size()));
|
|
propagate_subface_labels(tree,
|
|
iso_faces,
|
|
patches,
|
|
arrangement_cells,
|
|
shell_of_half_patch,
|
|
shells,
|
|
shell_to_cell,
|
|
cell_subface_signs);
|
|
transform_subface_to_primitive_labels(tree, cell_subface_signs, cell_primitive_signs);
|
|
}
|
|
active_cell_label = filter_cells_by_boolean(tree, cell_primitive_signs);
|
|
}
|
|
filter_polygon_faces(iso_faces,
|
|
patches,
|
|
arrangement_cells,
|
|
shell_of_half_patch,
|
|
shells,
|
|
shell_to_cell,
|
|
active_cell_label,
|
|
output_polygon_faces,
|
|
output_vertex_counts_of_face);
|
|
filter_active_vertices(output_vertices, output_polygon_faces);
|
|
export_halfpatch_obj(iso_pts, iso_faces, patches, "halfpatch_final");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|