Skip to content

Commit 86ac76b

Browse files
committed
refactor: create mesh point cloud
1 parent 14076ed commit 86ac76b

File tree

8 files changed

+135
-25
lines changed

8 files changed

+135
-25
lines changed

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,15 @@ set (core_sources
9898
"${SRC_DIR}/core/math.h"
9999
"${SRC_DIR}/core/mesh.cpp"
100100
"${SRC_DIR}/core/mesh.h"
101+
"${SRC_DIR}/core/mesh_point_cloud.cpp"
102+
"${SRC_DIR}/core/mesh_point_cloud.h"
101103
"${SRC_DIR}/core/rasterized_mesh.cpp"
102104
"${SRC_DIR}/core/rasterized_mesh.h"
103105
"${SRC_DIR}/core/scene.cpp"
104106
"${SRC_DIR}/core/scene.h"
105107
"${SRC_DIR}/core/scene_loader.cpp"
106108
"${SRC_DIR}/core/scene_loader.h"
107-
"${SRC_DIR}/thirdparty/nanoflann.hpp"
109+
"${SRC_DIR}/thirdparty/nanoflann/nanoflann.hpp"
108110
)
109111

110112
add_library(

src/core/closest_point_query.cpp

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,27 @@
22

33
#include "math.h"
44

5+
#include <chrono>
56
#include <cstddef>
7+
#include <inttypes.h>
8+
#include <iostream>
69
#include <limits>
710
#include <vector>
811

912
namespace core
1013
{
1114

12-
ClosestPointQuery::ClosestPointQuery(const Mesh& mesh)
13-
: m_mesh(mesh)
14-
{}
15+
ClosestPointQuery::ClosestPointQuery(const MeshPointCloud& mesh_point_cloud)
16+
: m_mesh_point_cloud(mesh_point_cloud)
17+
{
18+
// Start a timer to know how long it takes to build the query object.
19+
auto timer_start = std::chrono::high_resolution_clock::now();
20+
21+
auto timer_stop = std::chrono::high_resolution_clock::now();
22+
auto process_time = std::chrono::duration_cast<std::chrono::milliseconds>(timer_stop - timer_start).count();
23+
24+
std::printf("Generated mesh query tree in %" PRId64 "ms.", process_time);
25+
}
1526

1627
bool ClosestPointQuery::get_closest_point(
1728
const glm::vec3& query_point,
@@ -20,11 +31,7 @@ bool ClosestPointQuery::get_closest_point(
2031
{
2132
assert(max_distance > 0.0f);
2233

23-
const std::vector<Mesh::Vertex>& vertices = m_mesh.get_vertices();
24-
const std::size_t vertex_count = vertices.size();
25-
const std::vector<unsigned int>& triangles = m_mesh.get_triangles();
26-
assert(triangles.size() % 3 == 0);
27-
const std::size_t triangle_count = triangles.size() / 3;
34+
const std::size_t triangle_count = m_mesh_point_cloud.kdtree_get_point_count() / 3;
2835

2936
//=> Naive implementation.
3037
// 1. Go through each triangle
@@ -36,13 +43,9 @@ bool ClosestPointQuery::get_closest_point(
3643

3744
for (std::size_t triangle_index = 0; triangle_index < triangle_count; ++triangle_index)
3845
{
39-
const std::size_t v1_index = triangles[triangle_index * 3];
40-
const std::size_t v2_index = triangles[triangle_index * 3 + 1];
41-
const std::size_t v3_index = triangles[triangle_index * 3 + 2];
42-
43-
const glm::vec3& v1 = vertices[v1_index].pos;
44-
const glm::vec3& v2 = vertices[v2_index].pos;
45-
const glm::vec3& v3 = vertices[v3_index].pos;
46+
const glm::vec3& v1 = m_mesh_point_cloud.kdtree_get_pt(triangle_index * 3);
47+
const glm::vec3& v2 = m_mesh_point_cloud.kdtree_get_pt(triangle_index * 3 + 1);
48+
const glm::vec3& v3 = m_mesh_point_cloud.kdtree_get_pt(triangle_index * 3 + 2);
4649

4750
bool success = false;
4851
const glm::vec3 p = closest_point_in_triangle(

src/core/closest_point_query.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
#pragma once
22

3-
#include "mesh.h"
3+
#include "mesh_point_cloud.h"
44

5+
#include <nanoflann/nanoflann.hpp>
56
#include <glm/glm.hpp>
67

8+
#include <vector>
9+
710
namespace core
811
{
912

13+
/**
14+
* @brief Fast closest point to mesh.
15+
*
16+
* After creating the query object, just call
17+
* `get_closest_point`.
18+
*
19+
* When creating the query object, a tree will
20+
* be generated to speed up look up time.
21+
*/
1022
class ClosestPointQuery
1123
{
1224
public:
13-
ClosestPointQuery(const Mesh& mesh);
25+
ClosestPointQuery(const MeshPointCloud& mesh_point_cloud);
1426

1527
/**
1628
* @brief Return the closest point on the mesh within the specified maximum search distance.
@@ -21,7 +33,7 @@ class ClosestPointQuery
2133
glm::vec3& result) const;
2234

2335
private:
24-
const Mesh& m_mesh;
36+
const MeshPointCloud& m_mesh_point_cloud;
2537
};
2638

2739
} // namespace core

src/core/mesh_point_cloud.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include "mesh_point_cloud.h"
2+
3+
namespace core
4+
{
5+
6+
MeshPointCloud::MeshPointCloud(const Mesh& mesh)
7+
: m_mesh(mesh)
8+
{
9+
// Add all mesh vertices in the point cloud.
10+
// TODO: Uniform sample the mesh to generate a denser cloud.
11+
const std::vector<Mesh::Vertex>& vertices = m_mesh.get_vertices();
12+
const std::size_t vertex_count = vertices.size();
13+
const std::vector<unsigned int>& triangles = m_mesh.get_triangles();
14+
assert(triangles.size() % 3 == 0);
15+
const std::size_t triangle_count = triangles.size() / 3;
16+
17+
m_points.reserve(triangle_count * 3);
18+
19+
for (std::size_t triangle_index = 0; triangle_index < triangle_count; ++triangle_index)
20+
{
21+
const std::size_t v1_index = triangles[triangle_index * 3];
22+
const std::size_t v2_index = triangles[triangle_index * 3 + 1];
23+
const std::size_t v3_index = triangles[triangle_index * 3 + 2];
24+
25+
m_points.push_back(vertices[v1_index].pos);
26+
m_points.push_back(vertices[v2_index].pos);
27+
m_points.push_back(vertices[v3_index].pos);
28+
}
29+
}
30+
31+
} // namespace core

src/core/mesh_point_cloud.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#pragma once
2+
3+
#include "mesh.h"
4+
5+
#include <nanoflann/nanoflann.hpp>
6+
#include <glm/glm.hpp>
7+
8+
#include <cstdint>
9+
#include <vector>
10+
11+
namespace core
12+
{
13+
14+
/**
15+
* @brief Create a point cloud using a mesh.
16+
* TODO: Allow to generate points on the mesh to
17+
* increase precision.
18+
*/
19+
class MeshPointCloud
20+
{
21+
public:
22+
MeshPointCloud(const Mesh& mesh);
23+
24+
// nanoflann compatibility implementaiton.
25+
inline std::size_t kdtree_get_point_count() const
26+
{
27+
return m_points.size();
28+
}
29+
30+
inline float kdtree_get_pt(const std::size_t idx, int dim) const
31+
{
32+
if (dim == 0)
33+
return m_points[idx].x;
34+
else if (dim == 1)
35+
return m_points[idx].y;
36+
else
37+
return m_points[idx].z;
38+
}
39+
40+
inline glm::vec3 kdtree_get_pt(const std::size_t idx) const
41+
{
42+
return m_points[idx];
43+
}
44+
45+
template<class BBOX>
46+
bool kdtree_get_bbox(BBOX&) const
47+
{ return false; }
48+
49+
private:
50+
const Mesh& m_mesh;
51+
std::vector<glm::vec3> m_points;
52+
};
53+
54+
} // namespace core

src/gui/mainwindow.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
// core includes.
77
#include "core/closest_point_query.h"
8+
#include "core/mesh_point_cloud.h"
89
#include "core/scene.h"
910
#include "core/scene_loader.h"
1011

@@ -158,9 +159,11 @@ void MainWindow::load_scene(const std::string& path)
158159
// Load the scene.
159160
m_scene.reset(core::load_scene_from_file(path));
160161

162+
// Build a point cloud of the mesh.
163+
m_mesh_point_cloud.reset(new core::MeshPointCloud(m_scene->get_mesh()));
164+
161165
// Prepare closest point queries.
162-
core::ClosestPointQuery* query = new core::ClosestPointQuery(m_scene->get_mesh());
163-
m_closest_point_query.reset(query);
166+
m_closest_point_query.reset(new core::ClosestPointQuery(*m_mesh_point_cloud));
164167
}
165168

166169
// Constructor.
@@ -322,10 +325,13 @@ void MainWindow::find_closest_point()
322325
auto timer_start = std::chrono::high_resolution_clock::now();
323326

324327
// Run the query.
325-
m_closest_point_found = run && m_closest_point_query->get_closest_point(
326-
m_query_point_pos,
327-
m_query_point_max_serach_radius,
328-
m_closest_point_pos);
328+
for (int i = 0; i < 100; ++i)
329+
{
330+
m_closest_point_found = run && m_closest_point_query->get_closest_point(
331+
m_query_point_pos,
332+
m_query_point_max_serach_radius,
333+
m_closest_point_pos);
334+
}
329335

330336
auto timer_stop = std::chrono::high_resolution_clock::now();
331337
m_closest_point_query_time = std::chrono::duration_cast<std::chrono::milliseconds>(timer_stop - timer_start).count();

src/gui/mainwindow.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// Forward declarations.
1313
class GLFWwindow;
1414
namespace core { class ClosestPointQuery; }
15+
namespace core { class MeshPointCloud; }
1516
namespace core { class Scene; }
1617

1718
namespace gui
@@ -66,6 +67,7 @@ class MainWindow
6667
std::unique_ptr<Shader> m_drawing_shader;
6768
std::unique_ptr<Shader> m_point_shader;
6869

70+
std::unique_ptr<core::MeshPointCloud> m_mesh_point_cloud;
6971
std::unique_ptr<core::ClosestPointQuery> m_closest_point_query;
7072
glm::vec3 m_query_point_pos;
7173
float m_query_point_max_serach_radius;
File renamed without changes.

0 commit comments

Comments
 (0)