From e266dba83eb406329104e05d519da4c489edd635 Mon Sep 17 00:00:00 2001 From: Luciano Arnaldo Romero Calla Date: Mon, 22 Jan 2024 16:36:33 +0100 Subject: [PATCH 1/3] che_xyz: loading colors and extra value as heatmap --- include/gproshan/mesh/che.h | 3 +++ include/gproshan/util.h | 19 +++++++++++++++++++ src/gproshan/mesh/che.cpp | 8 ++++++++ src/gproshan/mesh/che_xyz.cpp | 10 ++++++++-- 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/include/gproshan/mesh/che.h b/include/gproshan/mesh/che.h index 048c7deb..29a3a4ad 100644 --- a/include/gproshan/mesh/che.h +++ b/include/gproshan/mesh/che.h @@ -2,6 +2,7 @@ #define CHE_H #include +#include #include #include @@ -63,6 +64,7 @@ class che vertex * VN = nullptr; ///< vertex normals : v -> normal(v) rgb_t * VC = nullptr; ///< vertex color : v -> color(v) real_t * VHC = nullptr; ///< vertex color heatmap : v -> heatmap(v) + real_t scale_hm = 1; ///< vertex color heatmap scale factor bool manifold = true; @@ -85,6 +87,7 @@ class che // vertex color methods const real_t * heatmap_ptr() const; + real_t heatmap_scale(const index_t v) const; real_t heatmap(const index_t v) const; real_t & heatmap(const index_t v); const rgb_t * rgb_ptr() const; diff --git a/include/gproshan/util.h b/include/gproshan/util.h index 9447db6f..5f2cae8e 100644 --- a/include/gproshan/util.h +++ b/include/gproshan/util.h @@ -83,6 +83,25 @@ void copy_real_t_array(double * destination, const float * source, const size_t void copy_real_t_array(double * destination, const double * source, const size_t n_elem); +template +T normalize(T * data, const size_t n_elem) +{ + T max = 0; + + #pragma omp parallel for reduction(std::max: max) + for(index_t i = 0; i < n_elem; ++i) + max = std::max(max, data[i]); + + if(max <= 1) return 1; + + #pragma omp parallel for + for(index_t i = 0; i < n_elem; ++i) + data[i] /= max; + + return max; +} + + } // namespace gproshan #endif // UTIL_H diff --git a/src/gproshan/mesh/che.cpp b/src/gproshan/mesh/che.cpp index 60b3cafc..51c5b43e 100644 --- a/src/gproshan/mesh/che.cpp +++ b/src/gproshan/mesh/che.cpp @@ -169,6 +169,12 @@ const real_t * che::heatmap_ptr() const return VHC; } +real_t che::heatmap_scale(const index_t v) const +{ + assert(v < n_vertices); + return scale_hm * VHC[v]; +} + real_t che::heatmap(const index_t v) const { assert(v < n_vertices); @@ -338,6 +344,7 @@ void che::update_heatmap(const real_t * hm) } memcpy(VHC, hm, n_vertices * sizeof(real_t)); + scale_hm = normalize(VHC, n_vertices); } void che::update_normals() @@ -1162,6 +1169,7 @@ che * che::load_mesh(const std::string & file_path) if(extension == "ply") return new che_ply(file_path); if(extension == "ptx") return new che_ptx(file_path); if(extension == "xyz") return new che_xyz(file_path); + if(extension == "txt") return new che_xyz(file_path); if(extension == "pts") return new che_pts(file_path); if(extension == "pcd") return new che_pcd(file_path); diff --git a/src/gproshan/mesh/che_xyz.cpp b/src/gproshan/mesh/che_xyz.cpp index c3d0117d..09589e0c 100644 --- a/src/gproshan/mesh/che_xyz.cpp +++ b/src/gproshan/mesh/che_xyz.cpp @@ -23,18 +23,21 @@ void che_xyz::read_file(const std::string & file) float x, y, z; unsigned char r, g, b; size_t n; + real_t h; std::vector vertices; std::vector vertices_color; + std::vector vertices_hm; while(fgets(line, sizeof(line), fp)) { sscanf(line, "%c", &c); if(c == '#') continue; - n = sscanf(line, "%f %f %f %hhu %hhu %hhu", &x, &y, &z, &r, &g, &b); + n = sscanf(line, "%f %f %f %hhu %hhu %hhu %f", &x, &y, &z, &r, &g, &b, &h); vertices.push_back({x, y, z}); - vertices_color.push_back(n == 6 ? rgb_t{r, g, b} : rgb_t()); + vertices_color.push_back(n > 5 ? rgb_t{r, g, b} : rgb_t()); + vertices_hm.push_back(n > 6 ? h : 0.45); } fclose(fp); @@ -42,6 +45,8 @@ void che_xyz::read_file(const std::string & file) alloc(size(vertices), 0); memcpy(GT, vertices.data(), n_vertices * sizeof(vertex)); memcpy(VC, vertices_color.data(), n_vertices * sizeof(rgb_t)); + + update_heatmap(vertices_hm.data()); } void che_xyz::write_file(const che * mesh, const std::string & file, const bool & color) @@ -60,6 +65,7 @@ void che_xyz::write_file(const che * mesh, const std::string & file, const bool { const rgb_t c = mesh->rgb(i); fprintf(fp, " %hhu %hhu %hhu", c.r, c.g, c.b); + fprintf(fp, " %f", mesh->heatmap_scale(i)); } fprintf(fp, "\n"); } From 1132f82ef659ddc52aa0b9a1592b60e8c3a3258f Mon Sep 17 00:00:00 2001 From: Luciano Arnaldo Romero Calla Date: Tue, 23 Jan 2024 01:14:15 +0100 Subject: [PATCH 2/3] raytracing: closes hit vertex utils function added --- include/gproshan/raytracing/utils.h | 25 +++++++++++++++++++++++++ src/gproshan/raytracing/embree.cpp | 21 +-------------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/include/gproshan/raytracing/utils.h b/include/gproshan/raytracing/utils.h index 33c5a886..33c496fc 100644 --- a/include/gproshan/raytracing/utils.h +++ b/include/gproshan/raytracing/utils.h @@ -263,6 +263,31 @@ vec ray_view_dir( const uvec2 & pos, } +template +__host_device__ +index_t closest_hit_vertex(const CHE & mesh, const H & hit) +{ + if(!mesh.n_trigs) return hit.primID; + + index_t he = 0; + real_t w = 1 - hit.u - hit.v; + + if(w < hit.u) + { + he = 1; + w = hit.u; + } + + if(w < hit.v) + { + he = 2; + w = hit.v; + } + + return mesh.VT[hit.primID * 3 + he]; +} + + } // namespace gproshan #endif // RT_UTILS_H diff --git a/src/gproshan/raytracing/embree.cpp b/src/gproshan/raytracing/embree.cpp index 6aa5b17a..ef17f346 100644 --- a/src/gproshan/raytracing/embree.cpp +++ b/src/gproshan/raytracing/embree.cpp @@ -87,26 +87,7 @@ index_t embree::closest_vertex(const vertex & org, const vertex & dir) const ray_hit r(org, dir); if(!intersect(r)) return NIL; - const CHE * mesh = g_meshes[r.hit.geomID]; - - if(!mesh->n_trigs) return r.hit.primID; - - index_t he = che::mtrig * r.hit.primID; - float w = 1 - r.hit.u - r.hit.v; - - if(w < r.hit.u) - { - he = che::mtrig * r.hit.primID + 1; - w = r.hit.u; - } - - if(w < r.hit.v) - { - he = che::mtrig * r.hit.primID + 2; - w = r.hit.v; - } - - return mesh->VT[he]; + return closest_hit_vertex(*g_meshes[r.hit.geomID], r.hit); } eval_hit embree::intersect(const vertex & org, const vertex & dir, const bool & flat) const From 8e09bf2e52e593e81d1403b476fe4f0962daba31 Mon Sep 17 00:00:00 2001 From: Luciano Arnaldo Romero Calla Date: Tue, 23 Jan 2024 01:53:48 +0100 Subject: [PATCH 3/3] scenes: scanner save heatmap --- include/gproshan/mesh/che.h | 2 ++ include/gproshan/raytracing/utils.h | 5 ++++- include/gproshan/scenes/scanner.h | 2 +- src/gproshan/app_viewer.cpp | 9 ++++++++- src/gproshan/mesh/che.cpp | 6 ++++++ src/gproshan/mesh/che.cu | 4 ++++ src/gproshan/scenes/scanner.cpp | 4 ++-- 7 files changed, 27 insertions(+), 5 deletions(-) diff --git a/include/gproshan/mesh/che.h b/include/gproshan/mesh/che.h index 29a3a4ad..13ce9016 100644 --- a/include/gproshan/mesh/che.h +++ b/include/gproshan/mesh/che.h @@ -87,6 +87,7 @@ class che // vertex color methods const real_t * heatmap_ptr() const; + void heatmap_scale(const real_t shm); real_t heatmap_scale(const index_t v) const; real_t heatmap(const index_t v) const; real_t & heatmap(const index_t v); @@ -215,6 +216,7 @@ struct CHE vertex * GT = nullptr; vertex * VN = nullptr; che::rgb_t * VC = nullptr; + real_t * VHC = nullptr; index_t * VT = nullptr; index_t * OT = nullptr; index_t * EVT = nullptr; diff --git a/include/gproshan/raytracing/utils.h b/include/gproshan/raytracing/utils.h index 33c496fc..86dc9fb6 100644 --- a/include/gproshan/raytracing/utils.h +++ b/include/gproshan/raytracing/utils.h @@ -75,8 +75,9 @@ struct t_eval_hit { index_t primID = NIL; int illum = 1; - T dist = 0; T u = 0, v = 0; + T dist = 0; + T heatmap = 0; vec position; vec normal; vec Ka = 1; @@ -101,6 +102,7 @@ struct t_eval_hit Kd = {T(mesh.VC[aprimID].r), T(mesh.VC[aprimID].g), T(mesh.VC[aprimID].b)}; Kd /= 255; normal = mesh.VN[aprimID]; + heatmap = mesh.VHC[aprimID]; return; } @@ -116,6 +118,7 @@ struct t_eval_hit Kd = ((1.f - u - v) * ca + u * cb + v * cc) / 255; normal = (1.f - u - v) * mesh.VN[a] + u * mesh.VN[b] + v * mesh.VN[c]; + heatmap = (1.f - u - v) * mesh.VHC[a] + u * mesh.VHC[b] + v * mesh.VHC[c]; if(!sc.trig_mat) return; if(sc.trig_mat[primID] == NIL) return; diff --git a/include/gproshan/scenes/scanner.h b/include/gproshan/scenes/scanner.h index 2de2ff25..be746751 100644 --- a/include/gproshan/scenes/scanner.h +++ b/include/gproshan/scenes/scanner.h @@ -9,7 +9,7 @@ namespace gproshan { -che * scanner_ptx(const rt::raytracing * rt, const size_t n_rows, const size_t n_cols, const vertex & cam_pos); +che * scanner_ptx(const rt::raytracing * rt, const size_t n_rows, const size_t n_cols, const vertex & cam_pos, const bool dist_error = false); che * scanner_ptx_jpg(const rt::raytracing * rt, const size_t n_rows, const size_t n_cols, const vertex & cam_pos, const std::string & file_jpg = ""); diff --git a/src/gproshan/app_viewer.cpp b/src/gproshan/app_viewer.cpp index 7539500a..76001140 100644 --- a/src/gproshan/app_viewer.cpp +++ b/src/gproshan/app_viewer.cpp @@ -193,6 +193,8 @@ bool app_viewer::process_simulate_scanner(viewer * p_view) static const size_t n_min = 100; static const size_t n_max = 10000; static vertex cam_pos = {0, 0, 0}; + static bool dist_error = true; + static bool save_jpg = false; if(size(view->sphere_points) != 1) { @@ -209,9 +211,14 @@ bool app_viewer::process_simulate_scanner(viewer * p_view) view->sphere_points[0] = cam_pos; } + ImGui::Checkbox("dist_error", &dist_error); + ImGui::Checkbox("save_jpg", &save_jpg); + if(ImGui::Button("Scan")) { - che * ptx_mesh = scanner_ptx_jpg(mesh.rt_embree, n_rows, n_cols, cam_pos, mesh->filename); + che * ptx_mesh = save_jpg ? scanner_ptx_jpg(mesh.rt_embree, n_rows, n_cols, cam_pos, mesh->filename) + : scanner_ptx(mesh.rt_embree, n_rows, n_cols, cam_pos, dist_error); + che_ptx::write_file(ptx_mesh, mesh->filename, n_rows, n_cols); ptx_mesh->filename = mesh->filename + ".ptx"; view->add_mesh(ptx_mesh); diff --git a/src/gproshan/mesh/che.cpp b/src/gproshan/mesh/che.cpp index 51c5b43e..465e8bc2 100644 --- a/src/gproshan/mesh/che.cpp +++ b/src/gproshan/mesh/che.cpp @@ -169,6 +169,11 @@ const real_t * che::heatmap_ptr() const return VHC; } +void che::heatmap_scale(const real_t shm) +{ + scale_hm = shm; +} + real_t che::heatmap_scale(const index_t v) const { assert(v < n_vertices); @@ -1219,6 +1224,7 @@ CHE::CHE(const che * mesh) GT = mesh->GT; VN = mesh->VN; VC = mesh->VC; + VHC = mesh->VHC; VT = mesh->VT; OT = mesh->OT; EVT = mesh->EVT; diff --git a/src/gproshan/mesh/che.cu b/src/gproshan/mesh/che.cu index 592cc91a..4970c678 100644 --- a/src/gproshan/mesh/che.cu +++ b/src/gproshan/mesh/che.cu @@ -25,6 +25,9 @@ void cuda_create_CHE(CHE * h_che, CHE *& dd_che, CHE *& d_che, const bool & norm { cudaMalloc(&dd_che->VC, sizeof(che::rgb_t) * h_che->n_vertices); cudaMemcpy(dd_che->VC, h_che->VC, sizeof(che::rgb_t) * h_che->n_vertices, cudaMemcpyHostToDevice); + + cudaMalloc(&dd_che->VHC, sizeof(real_t) * h_che->n_vertices); + cudaMemcpy(dd_che->VHC, h_che->VHC, sizeof(real_t) * h_che->n_vertices, cudaMemcpyHostToDevice); } cudaMalloc(&dd_che->VT, sizeof(index_t) * h_che->n_half_edges); @@ -45,6 +48,7 @@ void cuda_free_CHE(CHE *& dd_che, CHE *& d_che) cudaFree(dd_che->GT); cudaFree(dd_che->VN); cudaFree(dd_che->VC); + cudaFree(dd_che->VHC); cudaFree(dd_che->VT); cudaFree(dd_che->OT); cudaFree(dd_che->EVT); diff --git a/src/gproshan/scenes/scanner.cpp b/src/gproshan/scenes/scanner.cpp index 7b59c9e9..efa6f5a2 100644 --- a/src/gproshan/scenes/scanner.cpp +++ b/src/gproshan/scenes/scanner.cpp @@ -19,7 +19,7 @@ using namespace cimg_library; namespace gproshan { -che * scanner_ptx(const rt::raytracing * rt, const size_t n_rows, const size_t n_cols, const vertex & cam_pos) +che * scanner_ptx(const rt::raytracing * rt, const size_t n_rows, const size_t n_cols, const vertex & cam_pos, const bool dist_error) { che * mesh_ptx = new che(n_cols * n_rows); @@ -40,7 +40,7 @@ che * scanner_ptx(const rt::raytracing * rt, const size_t n_rows, const size_t n mesh_ptx->point(v) = h.position; mesh_ptx->normal(v) = h.normal; - mesh_ptx->heatmap(v) = h.dist; + mesh_ptx->heatmap(v) = dist_error ? h.dist : h.heatmap; mesh_ptx->rgb(v) = h.Kd; }