Merge branch 'lm_fdm_gizmo_experiments'
This commit is contained in:
commit
d0e0387b82
4 changed files with 160 additions and 116 deletions
|
@ -15,6 +15,8 @@
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
static constexpr size_t MaxVertexBuffers = 50;
|
||||||
|
|
||||||
GLGizmoFdmSupports::GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoFdmSupports::GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
, m_quadric(nullptr)
|
, m_quadric(nullptr)
|
||||||
|
@ -123,10 +125,9 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
|
||||||
|
|
||||||
// Now render both enforcers and blockers.
|
// Now render both enforcers and blockers.
|
||||||
for (int i=0; i<2; ++i) {
|
for (int i=0; i<2; ++i) {
|
||||||
if (m_ivas[mesh_id][i].has_VBOs()) {
|
|
||||||
glsafe(::glColor4f(i ? 1.f : 0.2f, 0.2f, i ? 0.2f : 1.0f, 0.5f));
|
glsafe(::glColor4f(i ? 1.f : 0.2f, 0.2f, i ? 0.2f : 1.0f, 0.5f));
|
||||||
m_ivas[mesh_id][i].render();
|
for (const GLIndexedVertexArray& iva : m_ivas[mesh_id][i])
|
||||||
}
|
iva.render();
|
||||||
}
|
}
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
}
|
}
|
||||||
|
@ -205,8 +206,14 @@ void GLGizmoFdmSupports::update_from_model_object()
|
||||||
++num_of_volumes;
|
++num_of_volumes;
|
||||||
m_selected_facets.resize(num_of_volumes);
|
m_selected_facets.resize(num_of_volumes);
|
||||||
m_neighbors.resize(num_of_volumes);
|
m_neighbors.resize(num_of_volumes);
|
||||||
|
|
||||||
m_ivas.clear();
|
m_ivas.clear();
|
||||||
m_ivas.resize(num_of_volumes);
|
m_ivas.resize(num_of_volumes);
|
||||||
|
for (size_t i=0; i<num_of_volumes; ++i) {
|
||||||
|
m_ivas[i][0].reserve(MaxVertexBuffers);
|
||||||
|
m_ivas[i][1].reserve(MaxVertexBuffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int volume_id = -1;
|
int volume_id = -1;
|
||||||
for (const ModelVolume* mv : mo->volumes) {
|
for (const ModelVolume* mv : mo->volumes) {
|
||||||
|
@ -226,7 +233,8 @@ void GLGizmoFdmSupports::update_from_model_object()
|
||||||
for (int i : list)
|
for (int i : list)
|
||||||
m_selected_facets[volume_id][i] = type;
|
m_selected_facets[volume_id][i] = type;
|
||||||
}
|
}
|
||||||
update_vertex_buffers(mv, volume_id, true, true);
|
update_vertex_buffers(mesh, volume_id, FacetSupportType::ENFORCER);
|
||||||
|
update_vertex_buffers(mesh, volume_id, FacetSupportType::BLOCKER);
|
||||||
|
|
||||||
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
||||||
|
|
||||||
|
@ -325,7 +333,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
Vec3f closest_hit = Vec3f::Zero();
|
Vec3f closest_hit = Vec3f::Zero();
|
||||||
double closest_hit_squared_distance = std::numeric_limits<double>::max();
|
double closest_hit_squared_distance = std::numeric_limits<double>::max();
|
||||||
size_t closest_facet = 0;
|
size_t closest_facet = 0;
|
||||||
size_t closest_hit_mesh_id = size_t(-1);
|
int closest_hit_mesh_id = -1;
|
||||||
|
|
||||||
// Transformations of individual meshes
|
// Transformations of individual meshes
|
||||||
std::vector<Transform3d> trafo_matrices;
|
std::vector<Transform3d> trafo_matrices;
|
||||||
|
@ -368,17 +376,22 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
}
|
}
|
||||||
// We now know where the ray hit, let's save it and cast another ray
|
// We now know where the ray hit, let's save it and cast another ray
|
||||||
if (closest_hit_mesh_id != size_t(-1)) // only if there is at least one hit
|
if (closest_hit_mesh_id != size_t(-1)) // only if there is at least one hit
|
||||||
hit_positions_and_facet_ids[closest_hit_mesh_id].emplace_back(closest_hit, closest_facet);
|
some_mesh_was_hit = true;
|
||||||
|
|
||||||
|
|
||||||
|
if (some_mesh_was_hit) {
|
||||||
// Now propagate the hits
|
// Now propagate the hits
|
||||||
mesh_id = -1;
|
mesh_id = -1;
|
||||||
|
const TriangleMesh* mesh = nullptr;
|
||||||
for (const ModelVolume* mv : mo->volumes) {
|
for (const ModelVolume* mv : mo->volumes) {
|
||||||
|
|
||||||
if (! mv->is_model_part())
|
if (! mv->is_model_part())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
++mesh_id;
|
++mesh_id;
|
||||||
|
if (mesh_id == closest_hit_mesh_id) {
|
||||||
|
mesh = &mv->mesh();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool update_both = false;
|
bool update_both = false;
|
||||||
|
|
||||||
const Transform3d& trafo_matrix = trafo_matrices[mesh_id];
|
const Transform3d& trafo_matrix = trafo_matrices[mesh_id];
|
||||||
|
@ -389,24 +402,22 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
const float avg_scaling = (sf(0) + sf(1) + sf(2))/3.;
|
const float avg_scaling = (sf(0) + sf(1) + sf(2))/3.;
|
||||||
const float limit = pow(m_cursor_radius/avg_scaling , 2.f);
|
const float limit = pow(m_cursor_radius/avg_scaling , 2.f);
|
||||||
|
|
||||||
// For all hits on this mesh...
|
const std::pair<Vec3f, size_t>& hit_and_facet = { closest_hit, closest_facet };
|
||||||
for (const std::pair<Vec3f, size_t>& hit_and_facet : hit_positions_and_facet_ids[mesh_id]) {
|
|
||||||
some_mesh_was_hit = true;
|
const std::vector<NeighborData>& neighbors = m_neighbors[mesh_id];
|
||||||
const TriangleMesh* mesh = &mv->mesh();
|
|
||||||
std::vector<NeighborData>& neighbors = m_neighbors[mesh_id];
|
|
||||||
|
|
||||||
// Calculate direction from camera to the hit (in mesh coords):
|
// Calculate direction from camera to the hit (in mesh coords):
|
||||||
Vec3f dir = ((trafo_matrix.inverse() * camera.get_position()).cast<float>() - hit_and_facet.first).normalized();
|
Vec3f dir = ((trafo_matrix.inverse() * camera.get_position()).cast<float>() - hit_and_facet.first).normalized();
|
||||||
|
|
||||||
// A lambda to calculate distance from the centerline:
|
// A lambda to calculate distance from the centerline:
|
||||||
auto squared_distance_from_line = [&hit_and_facet, &dir](const Vec3f point) -> float {
|
auto squared_distance_from_line = [&hit_and_facet, &dir](const Vec3f& point) -> float {
|
||||||
Vec3f diff = hit_and_facet.first - point;
|
Vec3f diff = hit_and_facet.first - point;
|
||||||
return (diff - diff.dot(dir) * dir).squaredNorm();
|
return (diff - diff.dot(dir) * dir).squaredNorm();
|
||||||
};
|
};
|
||||||
|
|
||||||
// A lambda to determine whether this facet is potentionally visible (still can be obscured)
|
// A lambda to determine whether this facet is potentionally visible (still can be obscured)
|
||||||
auto faces_camera = [&dir](const ModelVolume* mv, const size_t& facet) -> bool {
|
auto faces_camera = [&dir, &mesh](const size_t& facet) -> bool {
|
||||||
return (mv->mesh().stl.facet_start[facet].normal.dot(dir) > 0.);
|
return (mesh->stl.facet_start[facet].normal.dot(dir) > 0.);
|
||||||
};
|
};
|
||||||
// Now start with the facet the pointer points to and check all adjacent facets. neighbors vector stores
|
// Now start with the facet the pointer points to and check all adjacent facets. neighbors vector stores
|
||||||
// pairs of vertex_idx - facet_idx and is sorted with respect to the former. Neighboring facet index can be
|
// pairs of vertex_idx - facet_idx and is sorted with respect to the former. Neighboring facet index can be
|
||||||
|
@ -427,7 +438,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
if (dist < limit) {
|
if (dist < limit) {
|
||||||
it = std::lower_bound(neighbors.begin(), neighbors.end(), vertex);
|
it = std::lower_bound(neighbors.begin(), neighbors.end(), vertex);
|
||||||
while (it != neighbors.end() && it->first == vertex.first) {
|
while (it != neighbors.end() && it->first == vertex.first) {
|
||||||
if (it->second != facet && faces_camera(mv, it->second))
|
if (it->second != facet && faces_camera(it->second))
|
||||||
facets_to_select.push_back(it->second);
|
facets_to_select.push_back(it->second);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
@ -438,41 +449,50 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
++facet_idx;
|
++facet_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now just select all facets that passed.
|
std::vector<size_t> new_facets;
|
||||||
|
new_facets.reserve(facets_to_select.size());
|
||||||
|
|
||||||
|
// Now just select all facets that passed and remember which
|
||||||
|
// ones have really changed state.
|
||||||
for (size_t next_facet : facets_to_select) {
|
for (size_t next_facet : facets_to_select) {
|
||||||
FacetSupportType& facet = m_selected_facets[mesh_id][next_facet];
|
FacetSupportType& facet = m_selected_facets[mesh_id][next_facet];
|
||||||
|
|
||||||
if (facet != new_state && facet != FacetSupportType::NONE) {
|
if (facet != new_state) {
|
||||||
|
if (facet != FacetSupportType::NONE) {
|
||||||
// this triangle is currently in the other VBA.
|
// this triangle is currently in the other VBA.
|
||||||
// Both VBAs need to be refreshed.
|
// Both VBAs need to be refreshed.
|
||||||
update_both = true;
|
update_both = true;
|
||||||
}
|
}
|
||||||
facet = new_state;
|
facet = new_state;
|
||||||
|
new_facets.push_back(next_facet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_vertex_buffers(mv, mesh_id,
|
if (! new_facets.empty()) {
|
||||||
new_state == FacetSupportType::ENFORCER || update_both,
|
if (new_state != FacetSupportType::NONE) {
|
||||||
new_state == FacetSupportType::BLOCKER || update_both
|
// append triangles into the respective VBA
|
||||||
);
|
update_vertex_buffers(mesh, mesh_id, new_state, &new_facets);
|
||||||
|
if (update_both) {
|
||||||
|
auto other = new_state == FacetSupportType::ENFORCER
|
||||||
|
? FacetSupportType::BLOCKER
|
||||||
|
: FacetSupportType::ENFORCER;
|
||||||
|
update_vertex_buffers(mesh, mesh_id, other); // regenerate the other VBA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
update_vertex_buffers(mesh, mesh_id, FacetSupportType::ENFORCER);
|
||||||
|
update_vertex_buffers(mesh, mesh_id, FacetSupportType::BLOCKER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (some_mesh_was_hit)
|
|
||||||
{
|
|
||||||
if (m_button_down == Button::None)
|
if (m_button_down == Button::None)
|
||||||
m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right);
|
m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right);
|
||||||
// Force rendering. In case the user is dragging, the queue can be
|
|
||||||
// flooded by wxEVT_MOVING event and rendering would be skipped.
|
|
||||||
m_parent.render();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (action == SLAGizmoEventType::Dragging && m_button_down != Button::None) {
|
if (action == SLAGizmoEventType::Dragging && m_button_down != Button::None)
|
||||||
// Same as above. We don't want the cursor to freeze when we
|
|
||||||
// leave the mesh while painting.
|
|
||||||
m_parent.render();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp)
|
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp)
|
||||||
&& m_button_down != Button::None) {
|
&& m_button_down != Button::None) {
|
||||||
|
@ -493,34 +513,54 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoFdmSupports::update_vertex_buffers(const ModelVolume* mv,
|
void GLGizmoFdmSupports::update_vertex_buffers(const TriangleMesh* mesh,
|
||||||
int mesh_id,
|
int mesh_id,
|
||||||
bool update_enforcers,
|
FacetSupportType type,
|
||||||
bool update_blockers)
|
const std::vector<size_t>* new_facets)
|
||||||
{
|
{
|
||||||
const TriangleMesh* mesh = &mv->mesh();
|
std::vector<GLIndexedVertexArray>& ivas = m_ivas[mesh_id][type == FacetSupportType::ENFORCER ? 0 : 1];
|
||||||
|
|
||||||
for (FacetSupportType type : {FacetSupportType::ENFORCER, FacetSupportType::BLOCKER}) {
|
// lambda to push facet into vertex buffer
|
||||||
if ((type == FacetSupportType::ENFORCER && ! update_enforcers)
|
auto push_facet = [this, &mesh, &mesh_id](size_t idx, GLIndexedVertexArray& iva) {
|
||||||
|| (type == FacetSupportType::BLOCKER && ! update_blockers))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
GLIndexedVertexArray& iva = m_ivas[mesh_id][type==FacetSupportType::ENFORCER ? 0 : 1];
|
|
||||||
iva.release_geometry();
|
|
||||||
size_t triangle_cnt=0;
|
|
||||||
for (size_t facet_idx=0; facet_idx<m_selected_facets[mesh_id].size(); ++facet_idx) {
|
|
||||||
FacetSupportType status = m_selected_facets[mesh_id][facet_idx];
|
|
||||||
if (status != type)
|
|
||||||
continue;
|
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
iva.push_geometry(mesh->its.vertices[mesh->its.indices[facet_idx](i)].cast<double>(),
|
iva.push_geometry(
|
||||||
MeshRaycaster::get_triangle_normal(mesh->its, facet_idx).cast<double>());
|
mesh->its.vertices[mesh->its.indices[idx](i)].cast<double>(),
|
||||||
iva.push_triangle(3*triangle_cnt, 3*triangle_cnt+1, 3*triangle_cnt+2);
|
m_c->raycaster()->raycasters()[mesh_id]->get_triangle_normal(idx).cast<double>()
|
||||||
++triangle_cnt;
|
);
|
||||||
|
size_t num = iva.triangle_indices_size;
|
||||||
|
iva.push_triangle(num, num+1, num+2);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (ivas.size() == MaxVertexBuffers || ! new_facets) {
|
||||||
|
// If there are too many or they should be regenerated, make one large
|
||||||
|
// GLVertexBufferArray.
|
||||||
|
ivas.clear(); // destructors release geometry
|
||||||
|
ivas.push_back(GLIndexedVertexArray());
|
||||||
|
|
||||||
|
bool pushed = false;
|
||||||
|
for (size_t facet_idx=0; facet_idx<m_selected_facets[mesh_id].size(); ++facet_idx) {
|
||||||
|
if (m_selected_facets[mesh_id][facet_idx] == type) {
|
||||||
|
push_facet(facet_idx, ivas.back());
|
||||||
|
pushed = true;
|
||||||
}
|
}
|
||||||
if (! m_selected_facets[mesh_id].empty())
|
|
||||||
iva.finalize_geometry(true);
|
|
||||||
}
|
}
|
||||||
|
if (pushed)
|
||||||
|
ivas.back().finalize_geometry(true);
|
||||||
|
else
|
||||||
|
ivas.pop_back();
|
||||||
|
} else {
|
||||||
|
// we are only appending - let's make new vertex array and let the old ones live
|
||||||
|
ivas.push_back(GLIndexedVertexArray());
|
||||||
|
for (size_t facet_idx : *new_facets)
|
||||||
|
push_facet(facet_idx, ivas.back());
|
||||||
|
|
||||||
|
if (! new_facets->empty())
|
||||||
|
ivas.back().finalize_geometry(true);
|
||||||
|
else
|
||||||
|
ivas.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -553,7 +593,8 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool overwr
|
||||||
? FacetSupportType::BLOCKER
|
? FacetSupportType::BLOCKER
|
||||||
: FacetSupportType::ENFORCER;
|
: FacetSupportType::ENFORCER;
|
||||||
}
|
}
|
||||||
update_vertex_buffers(mv, mesh_id, true, true);
|
update_vertex_buffers(&mv->mesh(), mesh_id, FacetSupportType::ENFORCER);
|
||||||
|
update_vertex_buffers(&mv->mesh(), mesh_id, FacetSupportType::BLOCKER);
|
||||||
}
|
}
|
||||||
|
|
||||||
Plater::TakeSnapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
Plater::TakeSnapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
||||||
|
@ -623,7 +664,8 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||||
if (mv->is_model_part()) {
|
if (mv->is_model_part()) {
|
||||||
m_selected_facets[idx].assign(m_selected_facets[idx].size(), FacetSupportType::NONE);
|
m_selected_facets[idx].assign(m_selected_facets[idx].size(), FacetSupportType::NONE);
|
||||||
mv->m_supported_facets.clear();
|
mv->m_supported_facets.clear();
|
||||||
update_vertex_buffers(mv, idx, true, true);
|
update_vertex_buffers(&mv->mesh(), idx, FacetSupportType::ENFORCER);
|
||||||
|
update_vertex_buffers(&mv->mesh(), idx, FacetSupportType::BLOCKER);
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,14 +33,16 @@ private:
|
||||||
// individual facets (one of the enum values above).
|
// individual facets (one of the enum values above).
|
||||||
std::vector<std::vector<FacetSupportType>> m_selected_facets;
|
std::vector<std::vector<FacetSupportType>> m_selected_facets;
|
||||||
|
|
||||||
// Store two vertex buffer arrays (for enforcers/blockers)
|
// Vertex buffer arrays for each model-part volume. There is a vector of
|
||||||
// for each model-part volume.
|
// arrays so that adding triangles can be done without regenerating all
|
||||||
std::vector<std::array<GLIndexedVertexArray, 2>> m_ivas;
|
// other triangles. Enforcers and blockers are of course separate.
|
||||||
|
std::vector<std::array<std::vector<GLIndexedVertexArray>, 2>> m_ivas;
|
||||||
|
|
||||||
void update_vertex_buffers(const ModelVolume* mv,
|
void update_vertex_buffers(const TriangleMesh* mesh,
|
||||||
int mesh_id,
|
int mesh_id,
|
||||||
bool update_enforcers,
|
FacetSupportType type, // enforcers / blockers
|
||||||
bool update_blockers);
|
const std::vector<size_t>* new_facets = nullptr); // nullptr -> regenerate all
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||||
|
|
|
@ -95,11 +95,9 @@ void MeshClipper::recalculate_triangles()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Vec3f MeshRaycaster::get_triangle_normal(const indexed_triangle_set& its, size_t facet_idx)
|
Vec3f MeshRaycaster::get_triangle_normal(size_t facet_idx) const
|
||||||
{
|
{
|
||||||
Vec3f a(its.vertices[its.indices[facet_idx](1)] - its.vertices[its.indices[facet_idx](0)]);
|
return m_normals[facet_idx];
|
||||||
Vec3f b(its.vertices[its.indices[facet_idx](2)] - its.vertices[its.indices[facet_idx](0)]);
|
|
||||||
return Vec3f(a.cross(b)).normalized();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||||
|
@ -218,12 +216,9 @@ Vec3f MeshRaycaster::get_closest_point(const Vec3f& point, Vec3f* normal) const
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
Vec3d closest_point;
|
Vec3d closest_point;
|
||||||
m_emesh.squared_distance(point.cast<double>(), idx, closest_point);
|
m_emesh.squared_distance(point.cast<double>(), idx, closest_point);
|
||||||
if (normal) {
|
if (normal)
|
||||||
auto indices = m_emesh.F().row(idx);
|
*normal = m_normals[idx];
|
||||||
Vec3d a(m_emesh.V().row(indices(1)) - m_emesh.V().row(indices(0)));
|
|
||||||
Vec3d b(m_emesh.V().row(indices(2)) - m_emesh.V().row(indices(0)));
|
|
||||||
*normal = Vec3f(a.cross(b).cast<float>());
|
|
||||||
}
|
|
||||||
return closest_point.cast<float>();
|
return closest_point.cast<float>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,11 @@ public:
|
||||||
// The pointer can be invalidated after constructor returns.
|
// The pointer can be invalidated after constructor returns.
|
||||||
MeshRaycaster(const TriangleMesh& mesh)
|
MeshRaycaster(const TriangleMesh& mesh)
|
||||||
: m_emesh(mesh)
|
: m_emesh(mesh)
|
||||||
{}
|
{
|
||||||
|
m_normals.reserve(mesh.stl.facet_start.size());
|
||||||
|
for (const stl_facet& facet : mesh.stl.facet_start)
|
||||||
|
m_normals.push_back(facet.normal);
|
||||||
|
}
|
||||||
|
|
||||||
void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||||
Vec3d& point, Vec3d& direction) const;
|
Vec3d& point, Vec3d& direction) const;
|
||||||
|
@ -140,10 +144,11 @@ public:
|
||||||
|
|
||||||
Vec3f get_closest_point(const Vec3f& point, Vec3f* normal = nullptr) const;
|
Vec3f get_closest_point(const Vec3f& point, Vec3f* normal = nullptr) const;
|
||||||
|
|
||||||
static Vec3f get_triangle_normal(const indexed_triangle_set& its, size_t facet_idx);
|
Vec3f get_triangle_normal(size_t facet_idx) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sla::EigenMesh3D m_emesh;
|
sla::EigenMesh3D m_emesh;
|
||||||
|
std::vector<stl_normal> m_normals;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue