mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-13 09:47:58 -06:00
FDM supports gizmo now uses VBOs instead of immediate mode
This commit is contained in:
parent
3e15d22f35
commit
23da5910c6
3 changed files with 101 additions and 36 deletions
|
@ -84,6 +84,10 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
|
||||||
{
|
{
|
||||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
|
||||||
|
glsafe(::glEnable(GL_POLYGON_OFFSET_FILL));
|
||||||
|
ScopeGuard offset_fill_guard([]() { glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); } );
|
||||||
|
glsafe(::glPolygonOffset(-1.0, 1.0));
|
||||||
|
|
||||||
int mesh_id = -1;
|
int mesh_id = -1;
|
||||||
for (const ModelVolume* mv : mo->volumes) {
|
for (const ModelVolume* mv : mo->volumes) {
|
||||||
if (! mv->is_model_part())
|
if (! mv->is_model_part())
|
||||||
|
@ -94,26 +98,14 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
|
||||||
const Transform3d trafo_matrix =
|
const Transform3d trafo_matrix =
|
||||||
mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() *
|
mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() *
|
||||||
mv->get_matrix();
|
mv->get_matrix();
|
||||||
const TriangleMesh* mesh = &mv->mesh();
|
|
||||||
|
|
||||||
for (size_t facet_idx=0; facet_idx<m_selected_facets[mesh_id].size(); ++facet_idx) {
|
glsafe(::glPushMatrix());
|
||||||
int8_t status = m_selected_facets[mesh_id][facet_idx];
|
glsafe(::glMultMatrixd(trafo_matrix.data()));
|
||||||
if (status == 0)
|
glsafe(::glColor4f(0.2f, 0.2f, 1.0f, 0.5f));
|
||||||
continue;
|
m_ivas[mesh_id][0].render();
|
||||||
::glColor4f(status==1 ? 0.2f : 1.f, 0.2f, status==1 ? 1.0f : 0.2f, 0.5f);
|
glsafe(::glColor4f(1.f, 0.2f, 0.2f, 0.5f));
|
||||||
|
m_ivas[mesh_id][1].render();
|
||||||
stl_normal normal = 0.01f * MeshRaycaster::get_triangle_normal(mesh->its, facet_idx);
|
glsafe(::glPopMatrix());
|
||||||
::glPushMatrix();
|
|
||||||
::glTranslatef(normal(0), normal(1), normal(2));
|
|
||||||
::glMultMatrixd(trafo_matrix.data());
|
|
||||||
|
|
||||||
::glBegin(GL_TRIANGLES);
|
|
||||||
::glVertex3f(mesh->its.vertices[mesh->its.indices[facet_idx](0)](0), mesh->its.vertices[mesh->its.indices[facet_idx](0)](1), mesh->its.vertices[mesh->its.indices[facet_idx](0)](2));
|
|
||||||
::glVertex3f(mesh->its.vertices[mesh->its.indices[facet_idx](1)](0), mesh->its.vertices[mesh->its.indices[facet_idx](1)](1), mesh->its.vertices[mesh->its.indices[facet_idx](1)](2));
|
|
||||||
::glVertex3f(mesh->its.vertices[mesh->its.indices[facet_idx](2)](0), mesh->its.vertices[mesh->its.indices[facet_idx](2)](1), mesh->its.vertices[mesh->its.indices[facet_idx](2)](2));
|
|
||||||
::glEnd();
|
|
||||||
::glPopMatrix();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +174,8 @@ void GLGizmoFdmSupports::update_mesh()
|
||||||
|
|
||||||
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.resize(num_of_volumes);
|
||||||
|
|
||||||
int volume_id = -1;
|
int volume_id = -1;
|
||||||
for (const ModelVolume* mv : mo->volumes) {
|
for (const ModelVolume* mv : mo->volumes) {
|
||||||
|
@ -193,7 +187,7 @@ void GLGizmoFdmSupports::update_mesh()
|
||||||
// This mesh does not account for the possible Z up SLA offset.
|
// This mesh does not account for the possible Z up SLA offset.
|
||||||
const TriangleMesh* mesh = &mv->mesh();
|
const TriangleMesh* mesh = &mv->mesh();
|
||||||
|
|
||||||
m_selected_facets[volume_id].assign(mesh->its.indices.size(), 0);
|
m_selected_facets[volume_id].assign(mesh->its.indices.size(), SelType::NONE);
|
||||||
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
||||||
|
|
||||||
// Prepare vector of vertex_index - facet_index pairs to quickly find adjacent facets
|
// Prepare vector of vertex_index - facet_index pairs to quickly find adjacent facets
|
||||||
|
@ -240,13 +234,6 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == SLAGizmoEventType::MouseWheelDown && control_down) {
|
|
||||||
double pos = m_c->object_clipper()->get_position();
|
|
||||||
pos = std::max(0., pos - 0.01);
|
|
||||||
m_c->object_clipper()->set_position(pos, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action == SLAGizmoEventType::ResetClippingPlane) {
|
if (action == SLAGizmoEventType::ResetClippingPlane) {
|
||||||
m_c->object_clipper()->set_position(-1., false);
|
m_c->object_clipper()->set_position(-1., false);
|
||||||
return true;
|
return true;
|
||||||
|
@ -256,12 +243,16 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
|| action == SLAGizmoEventType::RightDown
|
|| action == SLAGizmoEventType::RightDown
|
||||||
|| (action == SLAGizmoEventType::Dragging && m_button_down != Button::None)) {
|
|| (action == SLAGizmoEventType::Dragging && m_button_down != Button::None)) {
|
||||||
|
|
||||||
int8_t new_state = 0;
|
SelType new_state = SelType::NONE;
|
||||||
if (! shift_down) {
|
if (! shift_down) {
|
||||||
if (action == SLAGizmoEventType::Dragging)
|
if (action == SLAGizmoEventType::Dragging)
|
||||||
new_state = m_button_down == Button::Left ? 1 : -1;
|
new_state = m_button_down == Button::Left
|
||||||
|
? SelType::ENFORCER
|
||||||
|
: SelType::BLOCKER;
|
||||||
else
|
else
|
||||||
new_state = action == SLAGizmoEventType::LeftDown ? 1 : -1;
|
new_state = action == SLAGizmoEventType::LeftDown
|
||||||
|
? SelType::ENFORCER
|
||||||
|
: SelType::BLOCKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
@ -327,6 +318,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
++mesh_id;
|
++mesh_id;
|
||||||
|
bool update_both = false;
|
||||||
|
|
||||||
// For all hits on this mesh...
|
// For all hits on this mesh...
|
||||||
for (const std::pair<Vec3f, size_t>& hit_and_facet : hit_positions_and_facet_ids[mesh_id]) {
|
for (const std::pair<Vec3f, size_t>& hit_and_facet : hit_positions_and_facet_ids[mesh_id]) {
|
||||||
|
@ -382,22 +374,42 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
}
|
}
|
||||||
++facet_idx;
|
++facet_idx;
|
||||||
}
|
}
|
||||||
// Now just select all facets that passed
|
|
||||||
for (size_t next_facet : facets_to_select)
|
// Now just select all facets that passed.
|
||||||
m_selected_facets[mesh_id][next_facet] = new_state;
|
for (size_t next_facet : facets_to_select) {
|
||||||
|
SelType& facet = m_selected_facets[mesh_id][next_facet];
|
||||||
|
|
||||||
|
if (facet != new_state && facet != SelType::NONE) {
|
||||||
|
// this triangle is currently in the other VBA.
|
||||||
|
// Both VBAs need to be refreshed.
|
||||||
|
update_both = true;
|
||||||
}
|
}
|
||||||
|
facet = new_state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_vertex_buffers(mv, mesh_id,
|
||||||
|
new_state == SelType::ENFORCER || update_both,
|
||||||
|
new_state == SelType::BLOCKER || update_both
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (some_mesh_was_hit)
|
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);
|
||||||
m_parent.set_as_dirty();
|
// 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) {
|
||||||
|
@ -409,6 +421,35 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::update_vertex_buffers(const ModelVolume* mv,
|
||||||
|
int mesh_id,
|
||||||
|
bool update_enforcers,
|
||||||
|
bool update_blockers)
|
||||||
|
{
|
||||||
|
const TriangleMesh* mesh = &mv->mesh();
|
||||||
|
|
||||||
|
for (SelType type : {SelType::ENFORCER, SelType::BLOCKER}) {
|
||||||
|
if ((type == SelType::ENFORCER && ! update_enforcers)
|
||||||
|
|| (type == SelType::BLOCKER && ! update_blockers))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GLIndexedVertexArray& iva = m_ivas[mesh_id][type==SelType::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) {
|
||||||
|
SelType status = m_selected_facets[mesh_id][facet_idx];
|
||||||
|
if (status != type)
|
||||||
|
continue;
|
||||||
|
for (int i=0; i<3; ++i)
|
||||||
|
iva.push_geometry(mesh->its.vertices[mesh->its.indices[facet_idx](i)].cast<double>(),
|
||||||
|
MeshRaycaster::get_triangle_normal(mesh->its, facet_idx).cast<double>());
|
||||||
|
iva.push_triangle(3*triangle_cnt, 3*triangle_cnt+1, 3*triangle_cnt+2);
|
||||||
|
++triangle_cnt;
|
||||||
|
}
|
||||||
|
iva.finalize_geometry(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_limit)
|
void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_limit)
|
||||||
{
|
{
|
||||||
|
@ -529,6 +570,10 @@ void GLGizmoFdmSupports::on_set_state()
|
||||||
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
|
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
|
||||||
// we are actually shutting down
|
// we are actually shutting down
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("FDM gizmo turned off")));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("FDM gizmo turned off")));
|
||||||
|
m_old_mo = nullptr;
|
||||||
|
m_ivas.clear();
|
||||||
|
m_neighbors.clear();
|
||||||
|
m_selected_facets.clear();
|
||||||
}
|
}
|
||||||
m_old_state = m_state;
|
m_old_state = m_state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "GLGizmoBase.hpp"
|
#include "GLGizmoBase.hpp"
|
||||||
|
|
||||||
|
#include "slic3r/GUI/3DScene.hpp"
|
||||||
|
|
||||||
#include <cereal/types/vector.hpp>
|
#include <cereal/types/vector.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +26,24 @@ private:
|
||||||
static constexpr float CursorRadiusMax = 8.f;
|
static constexpr float CursorRadiusMax = 8.f;
|
||||||
static constexpr float CursorRadiusStep = 0.2f;
|
static constexpr float CursorRadiusStep = 0.2f;
|
||||||
|
|
||||||
std::vector<std::vector<int8_t>> m_selected_facets;
|
enum class SelType : int8_t {
|
||||||
|
NONE,
|
||||||
|
ENFORCER,
|
||||||
|
BLOCKER
|
||||||
|
};
|
||||||
|
|
||||||
|
// For each model-part volume, store a list of statuses of
|
||||||
|
// individual facets (one of the enum values above).
|
||||||
|
std::vector<std::vector<SelType>> m_selected_facets;
|
||||||
|
|
||||||
|
// Store two vertex buffer arrays (for enforcers/blockers)
|
||||||
|
// for each model-part volume.
|
||||||
|
std::vector<std::array<GLIndexedVertexArray, 2>> m_ivas;
|
||||||
|
|
||||||
|
void update_vertex_buffers(const ModelVolume* mv,
|
||||||
|
int mesh_id,
|
||||||
|
bool update_enforcers,
|
||||||
|
bool update_blockers);
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -232,6 +232,7 @@ const TriangleMesh* HollowedMesh::get_hollowed_mesh() const
|
||||||
|
|
||||||
void Raycaster::on_update()
|
void Raycaster::on_update()
|
||||||
{
|
{
|
||||||
|
wxBusyCursor wait;
|
||||||
const ModelObject* mo = get_pool()->selection_info()->model_object();
|
const ModelObject* mo = get_pool()->selection_info()->model_object();
|
||||||
|
|
||||||
if (! mo)
|
if (! mo)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue