Finished picking by color with a checksum in the alpha channel

to guard against unwanted alpha blending and / or multi sampling.
This commit is contained in:
bubnikv 2019-08-07 14:15:38 +02:00
parent 2ad3c05a65
commit 2d7f478dac
10 changed files with 89 additions and 74 deletions

View file

@ -3753,19 +3753,6 @@ void GLCanvas3D::_refresh_if_shown_on_screen()
} }
} }
static inline unsigned char picking_checksum(unsigned char red, unsigned char green, unsigned char blue)
{
// 8 bit hash for the color
unsigned char b = ((((37 * red) + green) & 0x0ff) * 37 + blue) & 0x0ff;
// Increase enthropy by a bit reversal
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
// Flip every second bit to increase the enthropy even more.
b ^= 0x55;
return b;
}
void GLCanvas3D::_picking_pass() const void GLCanvas3D::_picking_pass() const
{ {
if (m_picking_enabled && !m_mouse.dragging && (m_mouse.position != Vec2d(DBL_MAX, DBL_MAX))) if (m_picking_enabled && !m_mouse.dragging && (m_mouse.position != Vec2d(DBL_MAX, DBL_MAX)))
@ -3807,7 +3794,7 @@ void GLCanvas3D::_picking_pass() const
if (inside) if (inside)
{ {
glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color)); glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color));
if (picking_checksum(color[0], color[1], color[2]) == color[3]) if (picking_checksum_alpha_channel(color[0], color[1], color[2]) == color[3])
// Only non-interpolated colors are valid, those have their lowest three bits zeroed. // Only non-interpolated colors are valid, those have their lowest three bits zeroed.
volume_id = color[0] + (color[1] << 8) + (color[2] << 16); volume_id = color[0] + (color[1] << 8) + (color[2] << 16);
} }
@ -3859,7 +3846,7 @@ void GLCanvas3D::_rectangular_selection_picking_pass() const
{ {
std::array<GLubyte, 4> data; std::array<GLubyte, 4> data;
// Only non-interpolated colors are valid, those have their lowest three bits zeroed. // Only non-interpolated colors are valid, those have their lowest three bits zeroed.
bool valid() const { return picking_checksum(data[0], data[1], data[2]) == data[3]; } bool valid() const { return picking_checksum_alpha_channel(data[0], data[1], data[2]) == data[3]; }
int id() const { return data[0] + (data[1] << 8) + (data[2] << 16); } int id() const { return data[0] + (data[1] << 8) + (data[2] << 16); }
}; };
@ -4070,7 +4057,7 @@ void GLCanvas3D::_render_volumes_for_picking() const
unsigned int r = (id & (0x000000FF << 0)) << 0; unsigned int r = (id & (0x000000FF << 0)) << 0;
unsigned int g = (id & (0x000000FF << 8)) >> 8; unsigned int g = (id & (0x000000FF << 8)) >> 8;
unsigned int b = (id & (0x000000FF << 16)) >> 16; unsigned int b = (id & (0x000000FF << 16)) >> 16;
unsigned int a = picking_checksum(r, g, b); unsigned int a = picking_checksum_alpha_channel(r, g, b);
glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255)); glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255));
volume.first->render(); volume.first->render();
} }

View file

@ -29,19 +29,21 @@ GLGizmoBase::Grabber::Grabber()
color[0] = 1.0f; color[0] = 1.0f;
color[1] = 1.0f; color[1] = 1.0f;
color[2] = 1.0f; color[2] = 1.0f;
color[3] = 1.0f;
} }
void GLGizmoBase::Grabber::render(bool hover, float size) const void GLGizmoBase::Grabber::render(bool hover, float size) const
{ {
float render_color[3]; float render_color[4];
if (hover) if (hover)
{ {
render_color[0] = 1.0f - color[0]; render_color[0] = 1.0f - color[0];
render_color[1] = 1.0f - color[1]; render_color[1] = 1.0f - color[1];
render_color[2] = 1.0f - color[2]; render_color[2] = 1.0f - color[2];
render_color[3] = color[3];
} }
else else
::memcpy((void*)render_color, (const void*)color, 3 * sizeof(float)); ::memcpy((void*)render_color, (const void*)color, 4 * sizeof(float));
render(size, render_color, true); render(size, render_color, true);
} }
@ -63,7 +65,7 @@ void GLGizmoBase::Grabber::render(float size, const float* render_color, bool us
if (use_lighting) if (use_lighting)
glsafe(::glEnable(GL_LIGHTING)); glsafe(::glEnable(GL_LIGHTING));
glsafe(::glColor3fv(render_color)); glsafe(::glColor4fv(render_color));
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
glsafe(::glTranslated(center(0), center(1), center(2))); glsafe(::glTranslated(center(0), center(1), center(2)));
@ -144,9 +146,9 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, u
, m_dragging(false) , m_dragging(false)
, m_imgui(wxGetApp().imgui()) , m_imgui(wxGetApp().imgui())
{ {
::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 3 * sizeof(float)); ::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 4 * sizeof(float));
::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 3 * sizeof(float)); ::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 4 * sizeof(float));
::memcpy((void*)m_highlight_color, (const void*)DEFAULT_HIGHLIGHT_COLOR, 3 * sizeof(float)); ::memcpy((void*)m_highlight_color, (const void*)DEFAULT_HIGHLIGHT_COLOR, 4 * sizeof(float));
} }
void GLGizmoBase::set_hover_id(int id) void GLGizmoBase::set_hover_id(int id)
@ -161,7 +163,7 @@ void GLGizmoBase::set_hover_id(int id)
void GLGizmoBase::set_highlight_color(const float* color) void GLGizmoBase::set_highlight_color(const float* color)
{ {
if (color != nullptr) if (color != nullptr)
::memcpy((void*)m_highlight_color, (const void*)color, 3 * sizeof(float)); ::memcpy((void*)m_highlight_color, (const void*)color, 4 * sizeof(float));
} }
void GLGizmoBase::enable_grabber(unsigned int id) void GLGizmoBase::enable_grabber(unsigned int id)
@ -210,7 +212,7 @@ void GLGizmoBase::update(const UpdateData& data)
on_update(data); on_update(data);
} }
std::array<float, 3> GLGizmoBase::picking_color_component(unsigned int id) const std::array<float, 4> GLGizmoBase::picking_color_component(unsigned int id) const
{ {
static const float INV_255 = 1.0f / 255.0f; static const float INV_255 = 1.0f / 255.0f;
@ -220,9 +222,12 @@ std::array<float, 3> GLGizmoBase::picking_color_component(unsigned int id) const
id -= m_group_id; id -= m_group_id;
// color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass() // color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass()
return std::array<float, 3> { (float)((id >> 0) & 0xff) * INV_255, // red return std::array<float, 4> {
(float)((id >> 8) & 0xff) * INV_255, // green float((id >> 0) & 0xff) * INV_255, // red
(float)((id >> 16) & 0xff) * INV_255 }; // blue float((id >> 8) & 0xff) * INV_255, // green
float((id >> 16) & 0xff) * INV_255, // blue
float(picking_checksum_alpha_channel(id & 0xff, (id >> 8) & 0xff, (id >> 16) & 0xff))* INV_255 // checksum for validating against unwanted alpha blending and multi sampling
};
} }
void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
@ -247,10 +252,11 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
{ {
if (m_grabbers[i].enabled) if (m_grabbers[i].enabled)
{ {
std::array<float, 3> color = picking_color_component(i); std::array<float, 4> color = picking_color_component(i);
m_grabbers[i].color[0] = color[0]; m_grabbers[i].color[0] = color[0];
m_grabbers[i].color[1] = color[1]; m_grabbers[i].color[1] = color[1];
m_grabbers[i].color[2] = color[2]; m_grabbers[i].color[2] = color[2];
m_grabbers[i].color[3] = color[3];
m_grabbers[i].render_for_picking(mean_size); m_grabbers[i].render_for_picking(mean_size);
} }
} }
@ -267,5 +273,20 @@ std::string GLGizmoBase::format(float value, unsigned int decimals) const
return Slic3r::string_printf("%.*f", decimals, value); return Slic3r::string_printf("%.*f", decimals, value);
} }
// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components
// were not interpolated by alpha blending or multi sampling.
unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue)
{
// 8 bit hash for the color
unsigned char b = ((((37 * red) + green) & 0x0ff) * 37 + blue) & 0x0ff;
// Increase enthropy by a bit reversal
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
// Flip every second bit to increase the enthropy even more.
b ^= 0x55;
return b;
}
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View file

@ -21,11 +21,11 @@ class ModelObject;
namespace GUI { namespace GUI {
static const float DEFAULT_BASE_COLOR[3] = { 0.625f, 0.625f, 0.625f }; static const float DEFAULT_BASE_COLOR[4] = { 0.625f, 0.625f, 0.625f, 1.0f };
static const float DEFAULT_DRAG_COLOR[3] = { 1.0f, 1.0f, 1.0f }; static const float DEFAULT_DRAG_COLOR[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
static const float DEFAULT_HIGHLIGHT_COLOR[3] = { 1.0f, 0.38f, 0.0f }; static const float DEFAULT_HIGHLIGHT_COLOR[4] = { 1.0f, 0.38f, 0.0f, 1.0f };
static const float AXES_COLOR[3][3] = { { 0.75f, 0.0f, 0.0f }, { 0.0f, 0.75f, 0.0f }, { 0.0f, 0.0f, 0.75f } }; static const float AXES_COLOR[][4] = { { 0.75f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.75f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.75f, 1.0f } };
static const float CONSTRAINED_COLOR[3] = { 0.5f, 0.5f, 0.5f }; static const float CONSTRAINED_COLOR[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
@ -48,7 +48,7 @@ protected:
Vec3d center; Vec3d center;
Vec3d angles; Vec3d angles;
float color[3]; float color[4];
bool enabled; bool enabled;
bool dragging; bool dragging;
@ -94,9 +94,9 @@ protected:
unsigned int m_sprite_id; unsigned int m_sprite_id;
int m_hover_id; int m_hover_id;
bool m_dragging; bool m_dragging;
float m_base_color[3]; float m_base_color[4];
float m_drag_color[3]; float m_drag_color[4];
float m_highlight_color[3]; float m_highlight_color[4];
mutable std::vector<Grabber> m_grabbers; mutable std::vector<Grabber> m_grabbers;
ImGuiWrapper* m_imgui; ImGuiWrapper* m_imgui;
@ -166,7 +166,7 @@ protected:
// Returns the picking color for the given id, based on the BASE_ID constant // Returns the picking color for the given id, based on the BASE_ID constant
// No check is made for clashing with other picking color (i.e. GLVolumes) // No check is made for clashing with other picking color (i.e. GLVolumes)
std::array<float, 3> picking_color_component(unsigned int id) const; std::array<float, 4> picking_color_component(unsigned int id) const;
void render_grabbers(const BoundingBoxf3& box) const; void render_grabbers(const BoundingBoxf3& box) const;
void render_grabbers(float size) const; void render_grabbers(float size) const;
void render_grabbers_for_picking(const BoundingBoxf3& box) const; void render_grabbers_for_picking(const BoundingBoxf3& box) const;
@ -175,6 +175,10 @@ protected:
std::string format(float value, unsigned int decimals) const; std::string format(float value, unsigned int decimals) const;
}; };
// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components
// were not interpolated by alpha blending or multi sampling.
extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue);
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View file

@ -17,7 +17,7 @@ namespace GUI {
const double GLGizmoCut::Offset = 10.0; const double GLGizmoCut::Offset = 10.0;
const double GLGizmoCut::Margin = 20.0; const double GLGizmoCut::Margin = 20.0;
const std::array<float, 3> GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0 }; const std::array<float, 4> GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0, 1.0 };
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id)

View file

@ -11,7 +11,7 @@ class GLGizmoCut : public GLGizmoBase
{ {
static const double Offset; static const double Offset;
static const double Margin; static const double Margin;
static const std::array<float, 3> GrabberColor; static const std::array<float, 4> GrabberColor;
mutable double m_cut_z; mutable double m_cut_z;
double m_start_z; double m_start_z;

View file

@ -115,7 +115,7 @@ void GLGizmoFlatten::on_render_for_picking() const
const_cast<GLGizmoFlatten*>(this)->update_planes(); const_cast<GLGizmoFlatten*>(this)->update_planes();
for (int i = 0; i < (int)m_planes.size(); ++i) for (int i = 0; i < (int)m_planes.size(); ++i)
{ {
glsafe(::glColor3fv(picking_color_component(i).data())); glsafe(::glColor4fv(picking_color_component(i).data()));
::glBegin(GL_POLYGON); ::glBegin(GL_POLYGON);
for (const Vec3d& vertex : m_planes[i].vertices) for (const Vec3d& vertex : m_planes[i].vertices)
{ {

View file

@ -104,15 +104,15 @@ void GLGizmoMove3D::on_render() const
// x axis // x axis
m_grabbers[0].center = Vec3d(box.max(0) + Offset, center(1), center(2)); m_grabbers[0].center = Vec3d(box.max(0) + Offset, center(1), center(2));
::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 4 * sizeof(float));
// y axis // y axis
m_grabbers[1].center = Vec3d(center(0), box.max(1) + Offset, center(2)); m_grabbers[1].center = Vec3d(center(0), box.max(1) + Offset, center(2));
::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[1], 4 * sizeof(float));
// z axis // z axis
m_grabbers[2].center = Vec3d(center(0), center(1), box.max(2) + Offset); m_grabbers[2].center = Vec3d(center(0), center(1), box.max(2) + Offset);
::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[2], 4 * sizeof(float));
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
@ -123,7 +123,7 @@ void GLGizmoMove3D::on_render() const
{ {
if (m_grabbers[i].enabled) if (m_grabbers[i].enabled)
{ {
glsafe(::glColor3fv(AXES_COLOR[i])); glsafe(::glColor4fv(AXES_COLOR[i]));
::glBegin(GL_LINES); ::glBegin(GL_LINES);
::glVertex3dv(center.data()); ::glVertex3dv(center.data());
::glVertex3dv(m_grabbers[i].center.data()); ::glVertex3dv(m_grabbers[i].center.data());
@ -142,7 +142,7 @@ void GLGizmoMove3D::on_render() const
else else
{ {
// draw axis // draw axis
glsafe(::glColor3fv(AXES_COLOR[m_hover_id])); glsafe(::glColor4fv(AXES_COLOR[m_hover_id]));
::glBegin(GL_LINES); ::glBegin(GL_LINES);
::glVertex3dv(center.data()); ::glVertex3dv(center.data());
::glVertex3dv(m_grabbers[m_hover_id].center.data()); ::glVertex3dv(m_grabbers[m_hover_id].center.data());
@ -220,19 +220,20 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0); float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0);
double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size(mean_size) : (double)m_grabbers[axis].get_half_size(mean_size); double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size(mean_size) : (double)m_grabbers[axis].get_half_size(mean_size);
float color[3]; float color[4];
::memcpy((void*)color, (const void*)m_grabbers[axis].color, 3 * sizeof(float)); ::memcpy((void*)color, (const void*)m_grabbers[axis].color, 4 * sizeof(float));
if (!picking && (m_hover_id != -1)) if (!picking && (m_hover_id != -1))
{ {
color[0] = 1.0f - color[0]; color[0] = 1.0f - color[0];
color[1] = 1.0f - color[1]; color[1] = 1.0f - color[1];
color[2] = 1.0f - color[2]; color[2] = 1.0f - color[2];
color[3] = color[3];
} }
if (!picking) if (!picking)
glsafe(::glEnable(GL_LIGHTING)); glsafe(::glEnable(GL_LIGHTING));
glsafe(::glColor3fv(color)); glsafe(::glColor4fv(color));
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
glsafe(::glTranslated(m_grabbers[axis].center(0), m_grabbers[axis].center(1), m_grabbers[axis].center(2))); glsafe(::glTranslated(m_grabbers[axis].center(0), m_grabbers[axis].center(1), m_grabbers[axis].center(2)));
if (axis == X) if (axis == X)

View file

@ -155,7 +155,7 @@ void GLGizmoRotate::on_render() const
transform_to_local(selection); transform_to_local(selection);
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
glsafe(::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color)); glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color : m_highlight_color));
render_circle(); render_circle();
@ -166,7 +166,7 @@ void GLGizmoRotate::on_render() const
render_reference_radius(); render_reference_radius();
} }
glsafe(::glColor3fv(m_highlight_color)); glsafe(::glColor4fv(m_highlight_color));
if (m_hover_id != -1) if (m_hover_id != -1)
render_angle(); render_angle();
@ -287,14 +287,14 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const
m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0);
m_grabbers[0].angles(2) = m_angle; m_grabbers[0].angles(2) = m_angle;
glsafe(::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color)); glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color : m_highlight_color));
::glBegin(GL_LINES); ::glBegin(GL_LINES);
::glVertex3f(0.0f, 0.0f, 0.0f); ::glVertex3f(0.0f, 0.0f, 0.0f);
::glVertex3dv(m_grabbers[0].center.data()); ::glVertex3dv(m_grabbers[0].center.data());
glsafe(::glEnd()); glsafe(::glEnd());
::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float)); ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 4 * sizeof(float));
render_grabbers(box); render_grabbers(box);
} }
@ -306,8 +306,8 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0); float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0);
double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_size); double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_size);
float color[3]; float color[4];
::memcpy((void*)color, (const void*)m_grabbers[0].color, 3 * sizeof(float)); ::memcpy((void*)color, (const void*)m_grabbers[0].color, 4 * sizeof(float));
if (!picking && (m_hover_id != -1)) if (!picking && (m_hover_id != -1))
{ {
color[0] = 1.0f - color[0]; color[0] = 1.0f - color[0];
@ -318,7 +318,7 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
if (!picking) if (!picking)
glsafe(::glEnable(GL_LIGHTING)); glsafe(::glEnable(GL_LIGHTING));
glsafe(::glColor3fv(color)); glsafe(::glColor4fv(color));
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
glsafe(::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2))); glsafe(::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2)));
glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0)); glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0));

View file

@ -172,20 +172,20 @@ void GLGizmoScale3D::on_render() const
// x axis // x axis
m_grabbers[0].center = m_transform * Vec3d(m_box.min(0), center(1), center(2)) - offset_x; m_grabbers[0].center = m_transform * Vec3d(m_box.min(0), center(1), center(2)) - offset_x;
m_grabbers[1].center = m_transform * Vec3d(m_box.max(0), center(1), center(2)) + offset_x; m_grabbers[1].center = m_transform * Vec3d(m_box.max(0), center(1), center(2)) + offset_x;
::memcpy((void*)m_grabbers[0].color, (ctrl_down && (m_hover_id == 1)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[0], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[0].color, (ctrl_down && (m_hover_id == 1)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[0], 4 * sizeof(float));
::memcpy((void*)m_grabbers[1].color, (ctrl_down && (m_hover_id == 0)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[0], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[1].color, (ctrl_down && (m_hover_id == 0)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[0], 4 * sizeof(float));
// y axis // y axis
m_grabbers[2].center = m_transform * Vec3d(center(0), m_box.min(1), center(2)) - offset_y; m_grabbers[2].center = m_transform * Vec3d(center(0), m_box.min(1), center(2)) - offset_y;
m_grabbers[3].center = m_transform * Vec3d(center(0), m_box.max(1), center(2)) + offset_y; m_grabbers[3].center = m_transform * Vec3d(center(0), m_box.max(1), center(2)) + offset_y;
::memcpy((void*)m_grabbers[2].color, (ctrl_down && (m_hover_id == 3)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[1], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[2].color, (ctrl_down && (m_hover_id == 3)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[1], 4 * sizeof(float));
::memcpy((void*)m_grabbers[3].color, (ctrl_down && (m_hover_id == 2)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[1], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[3].color, (ctrl_down && (m_hover_id == 2)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[1], 4 * sizeof(float));
// z axis // z axis
m_grabbers[4].center = m_transform * Vec3d(center(0), center(1), m_box.min(2)) - offset_z; m_grabbers[4].center = m_transform * Vec3d(center(0), center(1), m_box.min(2)) - offset_z;
m_grabbers[5].center = m_transform * Vec3d(center(0), center(1), m_box.max(2)) + offset_z; m_grabbers[5].center = m_transform * Vec3d(center(0), center(1), m_box.max(2)) + offset_z;
::memcpy((void*)m_grabbers[4].color, (ctrl_down && (m_hover_id == 5)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[2], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[4].color, (ctrl_down && (m_hover_id == 5)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[2], 4 * sizeof(float));
::memcpy((void*)m_grabbers[5].color, (ctrl_down && (m_hover_id == 4)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[2], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[5].color, (ctrl_down && (m_hover_id == 4)) ? (const void*)CONSTRAINED_COLOR : (const void*)&AXES_COLOR[2], 4 * sizeof(float));
// uniform // uniform
m_grabbers[6].center = m_transform * Vec3d(m_box.min(0), m_box.min(1), center(2)) - offset_x - offset_y; m_grabbers[6].center = m_transform * Vec3d(m_box.min(0), m_box.min(1), center(2)) - offset_x - offset_y;
@ -194,7 +194,7 @@ void GLGizmoScale3D::on_render() const
m_grabbers[9].center = m_transform * Vec3d(m_box.min(0), m_box.max(1), center(2)) - offset_x + offset_y; m_grabbers[9].center = m_transform * Vec3d(m_box.min(0), m_box.max(1), center(2)) - offset_x + offset_y;
for (int i = 6; i < 10; ++i) for (int i = 6; i < 10; ++i)
{ {
::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 3 * sizeof(float)); ::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 4 * sizeof(float));
} }
// sets grabbers orientation // sets grabbers orientation
@ -214,20 +214,20 @@ void GLGizmoScale3D::on_render() const
// draw connections // draw connections
if (m_grabbers[0].enabled && m_grabbers[1].enabled) if (m_grabbers[0].enabled && m_grabbers[1].enabled)
{ {
glsafe(::glColor3fv(m_grabbers[0].color)); glsafe(::glColor4fv(m_grabbers[0].color));
render_grabbers_connection(0, 1); render_grabbers_connection(0, 1);
} }
if (m_grabbers[2].enabled && m_grabbers[3].enabled) if (m_grabbers[2].enabled && m_grabbers[3].enabled)
{ {
glsafe(::glColor3fv(m_grabbers[2].color)); glsafe(::glColor4fv(m_grabbers[2].color));
render_grabbers_connection(2, 3); render_grabbers_connection(2, 3);
} }
if (m_grabbers[4].enabled && m_grabbers[5].enabled) if (m_grabbers[4].enabled && m_grabbers[5].enabled)
{ {
glsafe(::glColor3fv(m_grabbers[4].color)); glsafe(::glColor4fv(m_grabbers[4].color));
render_grabbers_connection(4, 5); render_grabbers_connection(4, 5);
} }
glsafe(::glColor3fv(m_base_color)); glsafe(::glColor4fv(m_base_color));
render_grabbers_connection(6, 7); render_grabbers_connection(6, 7);
render_grabbers_connection(7, 8); render_grabbers_connection(7, 8);
render_grabbers_connection(8, 9); render_grabbers_connection(8, 9);
@ -238,7 +238,7 @@ void GLGizmoScale3D::on_render() const
else if ((m_hover_id == 0) || (m_hover_id == 1)) else if ((m_hover_id == 0) || (m_hover_id == 1))
{ {
// draw connection // draw connection
glsafe(::glColor3fv(m_grabbers[0].color)); glsafe(::glColor4fv(m_grabbers[0].color));
render_grabbers_connection(0, 1); render_grabbers_connection(0, 1);
// draw grabbers // draw grabbers
m_grabbers[0].render(true, grabber_mean_size); m_grabbers[0].render(true, grabber_mean_size);
@ -247,7 +247,7 @@ void GLGizmoScale3D::on_render() const
else if ((m_hover_id == 2) || (m_hover_id == 3)) else if ((m_hover_id == 2) || (m_hover_id == 3))
{ {
// draw connection // draw connection
glsafe(::glColor3fv(m_grabbers[2].color)); glsafe(::glColor4fv(m_grabbers[2].color));
render_grabbers_connection(2, 3); render_grabbers_connection(2, 3);
// draw grabbers // draw grabbers
m_grabbers[2].render(true, grabber_mean_size); m_grabbers[2].render(true, grabber_mean_size);
@ -256,7 +256,7 @@ void GLGizmoScale3D::on_render() const
else if ((m_hover_id == 4) || (m_hover_id == 5)) else if ((m_hover_id == 4) || (m_hover_id == 5))
{ {
// draw connection // draw connection
glsafe(::glColor3fv(m_grabbers[4].color)); glsafe(::glColor4fv(m_grabbers[4].color));
render_grabbers_connection(4, 5); render_grabbers_connection(4, 5);
// draw grabbers // draw grabbers
m_grabbers[4].render(true, grabber_mean_size); m_grabbers[4].render(true, grabber_mean_size);
@ -265,7 +265,7 @@ void GLGizmoScale3D::on_render() const
else if (m_hover_id >= 6) else if (m_hover_id >= 6)
{ {
// draw connection // draw connection
glsafe(::glColor3fv(m_drag_color)); glsafe(::glColor4fv(m_drag_color));
render_grabbers_connection(6, 7); render_grabbers_connection(6, 7);
render_grabbers_connection(7, 8); render_grabbers_connection(7, 8);
render_grabbers_connection(8, 9); render_grabbers_connection(8, 9);

View file

@ -286,7 +286,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
glsafe(::glTranslated(0.0, 0.0, m_z_shift)); glsafe(::glTranslated(0.0, 0.0, m_z_shift));
glsafe(::glMultMatrixd(instance_matrix.data())); glsafe(::glMultMatrixd(instance_matrix.data()));
float render_color[3]; float render_color[4];
size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size(); size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size();
for (size_t i = 0; i < cache_size; ++i) for (size_t i = 0; i < cache_size; ++i)
{ {
@ -298,12 +298,14 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
// First decide about the color of the point. // First decide about the color of the point.
if (picking) { if (picking) {
std::array<float, 3> color = picking_color_component(i); std::array<float, 4> color = picking_color_component(i);
render_color[0] = color[0]; render_color[0] = color[0];
render_color[1] = color[1]; render_color[1] = color[1];
render_color[2] = color[2]; render_color[2] = color[2];
render_color[3] = picking_checksum_alpha_channel(render_color[0], render_color[1], render_color[2]);
} }
else { else {
render_color[3] = 1.f;
if ((m_hover_id == i && m_editing_mode)) { // ignore hover state unless editing mode is active if ((m_hover_id == i && m_editing_mode)) { // ignore hover state unless editing mode is active
render_color[0] = 0.f; render_color[0] = 0.f;
render_color[1] = 1.0f; render_color[1] = 1.0f;
@ -320,7 +322,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
for (unsigned char i=0; i<3; ++i) render_color[i] = 0.5f; for (unsigned char i=0; i<3; ++i) render_color[i] = 0.5f;
} }
} }
glsafe(::glColor3fv(render_color)); glsafe(::glColor4fv(render_color));
float render_color_emissive[4] = { 0.5f * render_color[0], 0.5f * render_color[1], 0.5f * render_color[2], 1.f}; float render_color_emissive[4] = { 0.5f * render_color[0], 0.5f * render_color[1], 0.5f * render_color[2], 1.f};
glsafe(::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive)); glsafe(::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive));