ENH: add app config: gizmo_keep_screen_size

jira: STUDIO-10293

Change-Id: Ie071d132d984adcee41e4d1c49e23b29fd0067bb
This commit is contained in:
jun.zhang 2025-03-13 19:25:19 +08:00 committed by lane.wei
parent d17f558610
commit ee2d6bc9d5
11 changed files with 108 additions and 91 deletions

View File

@ -207,6 +207,9 @@ void AppConfig::set_defaults()
if (get("enable_advanced_antialiasing").empty())
set_bool("enable_advanced_antialiasing", false);
if (get("gizmo_keep_screen_size").empty())
set_bool("gizmo_keep_screen_size", true);
if (get("show_3d_navigator").empty())
set_bool("show_3d_navigator", true);

View File

@ -2733,6 +2733,9 @@ bool GUI_App::on_init_inner()
p_ogl_manager->set_msaa_type(msaa_type);
const bool is_fxaa_enabled = app_config->get_bool("enable_advanced_antialiasing");
p_ogl_manager->set_fxaa_enabled(is_fxaa_enabled);
const bool gizmo_keep_screen_size = app_config->get_bool("gizmo_keep_screen_size");
p_ogl_manager->set_gizmo_keep_screen_size_enabled(gizmo_keep_screen_size);
}
BBLSplashScreen * scrn = nullptr;

View File

@ -95,7 +95,7 @@ static void rotate_z_3d(std::array<Vec3d, 4>& verts, float radian_angle)
rotate_point_2d(verts[i](0), verts[i](1), c, s);
}
const double GLGizmoAdvancedCut::Offset = 10.0;
const double GLGizmoAdvancedCut::Offset = 20.0;
const double GLGizmoAdvancedCut::Margin = 20.0;
const std::array<float, 4> GLGizmoAdvancedCut::GrabberColor = { 1.0, 1.0, 0.0, 1.0 };
const std::array<float, 4> GLGizmoAdvancedCut::GrabberHoverColor = { 0.7, 0.7, 0.0, 1.0};
@ -1242,12 +1242,6 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
}
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d screen_scalling_matrix{ Transform3d::Identity() };
const auto& t_zoom = camera.get_zoom();
screen_scalling_matrix.data()[0 * 4 + 0] = 1.0f / t_zoom;
screen_scalling_matrix.data()[1 * 4 + 1] = 1.0f / t_zoom;
screen_scalling_matrix.data()[2 * 4 + 2] = 1.0f / t_zoom;
const auto& view_matrix = camera.get_view_matrix();
const auto& projection_matrix = camera.get_projection_matrix();
render_glmodel(m_plane, cp_clr.get_data(), view_matrix * Geometry::translation_transform(m_plane_center) * m_rotate_matrix, projection_matrix);
@ -1257,7 +1251,10 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
glsafe(::glDisable(GL_BLEND));
// Draw the grabber and the connecting line
m_move_z_grabber.center = m_plane_center + m_plane_normal * Offset;
float radius = Offset;
modify_radius(radius);
radius *= 0.5f;
m_move_z_grabber.center = m_plane_center + m_plane_normal * radius;
bool is_render_z_grabber = true; // m_hover_id < 0 || m_hover_id == cube_z_move_id;
bool is_render_x_grabber = m_cut_mode == CutMode::cutTongueAndGroove; // m_hover_id < 0 || m_hover_id == cube_x_move_id;
glsafe(::glDisable(GL_DEPTH_TEST));
@ -1279,10 +1276,10 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
}
m_grabber_model.set_color({ 1.0f, 1.0f, 0.0f, 1.0f });
auto calculate_model_matrix = [&screen_scalling_matrix](const Vec3d& source, const Vec3d& target, Transform3d& model_matrix, float fullsize)->void {
auto calculate_model_matrix = [](const Vec3d& source, const Vec3d& target, Transform3d& model_matrix)->void {
Vec3d the_vector = target - source;
const auto scale = fullsize * the_vector.stableNorm();
const Vec3d center = source + screen_scalling_matrix.matrix().block<3, 3>(0, 0) * 0.5f * scale * the_vector.normalized();
const auto scale = the_vector.stableNorm();
const Vec3d center = source + 0.5f * scale * the_vector.normalized();
Vec3d rotation_axis;
double rotation_angle;
@ -1300,7 +1297,7 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
* Geometry::scale_transform({ scale, scale, scale }).matrix();
};
const float fullsize = get_fixed_grabber_size();
const float fullsize = get_grabber_size();
const auto& p_flat_shader = wxGetApp().get_shader("flat");
if (p_flat_shader && (is_render_z_grabber || is_render_x_grabber)) {
wxGetApp().bind_shader(p_flat_shader);
@ -1327,8 +1324,7 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
if (is_render_z_grabber) {
Transform3d model_matrix{ Transform3d::Identity() };
calculate_model_matrix(m_plane_center, m_move_z_grabber.center, model_matrix, 0.3 * fullsize);
model_matrix = model_matrix * screen_scalling_matrix;
calculate_model_matrix(m_plane_center, m_move_z_grabber.center, model_matrix);
p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
m_grabber_model.render_geometry();
}
@ -1337,8 +1333,7 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
if (is_render_x_grabber) {
Transform3d model_matrix{ Transform3d::Identity() };
calculate_model_matrix(m_plane_center, m_move_x_grabber.center, model_matrix, 0.3 * fullsize);
model_matrix = model_matrix * screen_scalling_matrix;
calculate_model_matrix(m_plane_center, m_move_x_grabber.center, model_matrix);
p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
m_grabber_model.render_geometry();
}
@ -1363,20 +1358,20 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers()
if (is_render_z_grabber) {
Vec3d t_z_dir = m_move_z_grabber.center - m_plane_center;
const auto scale_z = screen_scalling_matrix.matrix().block<3, 3>(0, 0) * 0.3 * fullsize * t_z_dir.stableNorm();
const auto scale_z = t_z_dir.stableNorm();
const Vec3d target_z = m_plane_center + scale_z * t_z_dir.normalized();
Transform3d cube_mat_z = Geometry::translation_transform(target_z) * m_rotate_matrix * Geometry::scale_transform(fullsize); //
m_move_z_grabber.m_matrix = cube_mat_z * screen_scalling_matrix;
m_move_z_grabber.m_matrix = cube_mat_z;
render_glmodel(cube_z, render_color, view_matrix * m_move_z_grabber.m_matrix, projection_matrix);
}
if (is_render_x_grabber) {
GLModel& cube_x = m_move_x_grabber.get_cube();
Vec3d t_x_dir = m_move_x_grabber.center - m_plane_center;
const auto scale_x = screen_scalling_matrix.matrix().block<3, 3>(0, 0) * 0.3 * fullsize * t_x_dir.stableNorm();
const auto scale_x = t_x_dir.stableNorm();
const Vec3d target_x = m_plane_center + scale_x * t_x_dir.normalized();
Transform3d cube_mat_x = Geometry::translation_transform(target_x) * m_rotate_matrix * Geometry::scale_transform(fullsize); //
m_move_x_grabber.m_matrix = cube_mat_x * screen_scalling_matrix;
m_move_x_grabber.m_matrix = cube_mat_x;
render_glmodel(cube_x, render_color, view_matrix * m_move_x_grabber.m_matrix, projection_matrix);
}
// Should be placed at last, because GLGizmoRotate3D clears depth buffer

View File

@ -281,17 +281,11 @@ float GLGizmoBase::get_grabber_size()
{
float grabber_size = 8.0f;
if (GLGizmoBase::INV_ZOOM > 0) {
grabber_size = get_fixed_grabber_size() * GLGizmoBase::INV_ZOOM;
grabber_size = GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::Grabber::GrabberSizeFactor * GLGizmoBase::INV_ZOOM;
}
return grabber_size;
}
float GLGizmoBase::get_fixed_grabber_size()
{
const float grabber_size = GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::Grabber::GrabberSizeFactor;
return grabber_size;
}
GLGizmoBase::GLGizmoBase(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id)
: m_parent(parent)
, m_group_id(-1)
@ -635,6 +629,20 @@ BoundingBoxf3 GLGizmoBase::get_cross_mask_aabb(const Transform3d& matrix, const
return t_aabb;
}
void GLGizmoBase::modify_radius(float& radius) const
{
const auto& ogl_manager = wxGetApp().get_opengl_manager();
if (ogl_manager) {
if (ogl_manager->is_gizmo_keep_screen_size_enabled()) {
uint32_t t_width = 0;
uint32_t t_height = 0;
ogl_manager->get_viewport_size(t_width, t_height);
radius = 0.2f * std::min(t_width, t_height);
radius *= GLGizmoBase::INV_ZOOM;
}
}
}
Transform3d GLGizmoBase::get_corss_mask_model_matrix(ECrossMaskType type, const Vec3f& target, bool is_single) const
{
double half_length = 4.0;

View File

@ -177,7 +177,6 @@ protected:
size_t &selection_idx, float label_width, float item_width);
void render_cross_mark(const Transform3d& matrix, const Vec3f& target,bool is_single =false);
static float get_grabber_size();
static float get_fixed_grabber_size();
public:
GLGizmoBase(GLCanvas3D& parent,
@ -303,6 +302,8 @@ protected:
BoundingBoxf3 get_cross_mask_aabb(const Transform3d& matrix, const Vec3f& target, bool is_single = false) const;
void modify_radius(float& radius) const;
private:
enum class ECrossMaskType
{

View File

@ -72,16 +72,9 @@ BoundingBoxf3 GLGizmoMove3D::get_bounding_box() const
if (m_cone.is_initialized()) {
const auto& t_cone_aabb = m_cone.get_bounding_box();
const auto& [box, box_trafo] = selection.get_bounding_box_in_current_reference_system();
Transform3d model_matrix = box_trafo;
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d screen_scalling_matrix{ Transform3d::Identity() };
const auto& t_zoom = camera.get_zoom();
screen_scalling_matrix.data()[0 * 4 + 0] = 1.0f / t_zoom;
screen_scalling_matrix.data()[1 * 4 + 1] = 1.0f / t_zoom;
screen_scalling_matrix.data()[2 * 4 + 2] = 1.0f / t_zoom;
auto model_matrix = box_trafo * screen_scalling_matrix;
double size = get_fixed_grabber_size() * 0.75;//0.75 for arrow show
double size = get_grabber_size() * 0.75;//0.75 for arrow show
for (unsigned int i = 0; i < 3; ++i) {
if (m_grabbers[i].enabled) {
auto i_model_matrix = model_matrix * Geometry::assemble_transform(m_grabbers[i].center);
@ -197,16 +190,13 @@ void GLGizmoMove3D::on_render()
}
m_orient_matrix = box_trafo;
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d screen_scalling_matrix{ Transform3d::Identity() };
const auto& t_zoom = camera.get_zoom();
screen_scalling_matrix.data()[0 * 4 + 0] = 1.0f / t_zoom;
screen_scalling_matrix.data()[1 * 4 + 1] = 1.0f / t_zoom;
screen_scalling_matrix.data()[2 * 4 + 2] = 1.0f / t_zoom;
m_orient_matrix = m_orient_matrix * screen_scalling_matrix;
const auto& p_ogl_manager = wxGetApp().get_opengl_manager();
if (!p_ogl_manager) {
return;
}
float space_size = 120.f;
space_size *= GLGizmoBase::Grabber::GrabberSizeFactor;
float space_size = 20.f * INV_ZOOM * GLGizmoBase::Grabber::GrabberSizeFactor;
modify_radius(space_size);
#if ENABLE_FIXED_GRABBER
// x axis
m_grabbers[0].center = {space_size, 0, 0};
@ -214,6 +204,11 @@ void GLGizmoMove3D::on_render()
m_grabbers[1].center = {0, space_size,0};
// z axis
m_grabbers[2].center = {0,0, space_size};
if (!p_ogl_manager->is_gizmo_keep_screen_size_enabled()) {
m_grabbers[0].center.x() += m_bounding_box.max.x();
m_grabbers[1].center.y() += m_bounding_box.max.y();
m_grabbers[2].center.z() += m_bounding_box.max.z();
}
for (int i = 0; i < 3; ++i) {
m_grabbers[i].color = AXES_COLOR[i];
@ -233,7 +228,6 @@ void GLGizmoMove3D::on_render()
m_grabbers[2].color = AXES_COLOR[2];
#endif
const auto& p_ogl_manager = wxGetApp().get_opengl_manager();
p_ogl_manager->set_line_width((m_hover_id != -1) ? 2.0f : 1.5f);
const auto& gl_info = p_ogl_manager->get_gl_info();
const auto formated_gl_version = gl_info.get_formated_gl_version();
@ -287,6 +281,7 @@ void GLGizmoMove3D::on_render()
const auto& shader = wxGetApp().get_shader("flat");
if (shader) {
wxGetApp().bind_shader(shader);
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * m_orient_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
for (unsigned int i = 0; i < 3; ++i) {
@ -365,8 +360,7 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const
void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const
{
double size = get_fixed_grabber_size() * 0.75;//0.75 for arrow show
double size = get_grabber_size() * 0.75;//0.75 for arrow show
std::array<float, 4> color = m_grabbers[axis].color;
if (!picking && m_hover_id != -1) {
if (m_hover_id == axis) {
@ -424,6 +418,5 @@ void GLGizmoMove3D::change_cs_by_selection() {
}
}
} // namespace GUI
} // namespace Slic3r

View File

@ -17,7 +17,7 @@ namespace Slic3r {
namespace GUI {
const float GLGizmoRotate::Offset = 100.0f;
const float GLGizmoRotate::Offset = 5.0;
const unsigned int GLGizmoRotate::CircleResolution = 64;
const unsigned int GLGizmoRotate::AngleResolution = 64;
const unsigned int GLGizmoRotate::ScaleStepsCount = 72;
@ -99,8 +99,11 @@ void GLGizmoRotate::on_update(const UpdateData& data)
double len = mouse_pos.norm();
auto radius = m_radius;
modify_radius(radius);
const auto& scale_factor = Geometry::Transformation(m_base_model_matrix).get_scaling_factor();
const float radius = scale_factor.maxCoeff()* m_radius;
radius = scale_factor.maxCoeff()* radius;
// snap to coarse snap region
if ((m_snap_coarse_in_radius * radius <= len) && (len <= m_snap_coarse_out_radius * radius))
{
@ -132,22 +135,24 @@ void GLGizmoRotate::on_render()
if (m_hover_id != 0 && !m_grabbers[0].dragging) {
init_data_from_selection(selection);
}
const double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset);
auto radius = m_radius;
modify_radius(radius);
const double grabber_radius = (double)radius * (1.0 + (double)GrabberOffset);
m_grabbers.front().center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0);
m_grabbers.front().color = AXES_COLOR[m_axis];
m_grabbers.front().hover_color = AXES_HOVER_COLOR[m_axis];
m_base_model_matrix = calculate_base_model_matrix();
m_base_model_matrix = transform_to_local(selection);
const auto t_angle = Vec3d(0.0f, 0.0f, m_angle);
const auto t_fullsize = get_fixed_grabber_size();
const auto t_fullsize = get_grabber_size();
m_grabbers.front().m_matrix = m_base_model_matrix * Geometry::assemble_transform(m_grabbers.front().center, t_angle, t_fullsize * Vec3d::Ones());
glsafe(::glEnable(GL_DEPTH_TEST));
const auto& p_ogl_manager = wxGetApp().get_opengl_manager();
p_ogl_manager->set_line_width((m_hover_id != -1) ? 2.0f : 1.5f);
if (p_ogl_manager) {
p_ogl_manager->set_line_width((m_hover_id != -1) ? 2.0f : 1.5f);
}
ColorRGBA color((m_hover_id != -1) ? m_drag_color : m_highlight_color);
const auto& shader = wxGetApp().get_shader("flat");
if (shader) {
@ -155,7 +160,7 @@ void GLGizmoRotate::on_render()
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d redius_scale_matrix;
Geometry::scale_transform(redius_scale_matrix, { m_radius, m_radius, m_radius });
Geometry::scale_transform(redius_scale_matrix, { radius, radius, radius });
Transform3d view_model_matrix = camera.get_view_matrix() * m_base_model_matrix * redius_scale_matrix;
shader->set_uniform("view_model_matrix", view_model_matrix);
@ -407,8 +412,7 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const
void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool picking) const
{
double size = get_fixed_grabber_size() * 0.75;//0.75 for arrow show
double size = get_grabber_size() * 0.75;//0.75 for arrow show
std::array<float, 4> color = m_grabbers[0].color;
if (!picking && m_hover_id != -1) {
color = m_grabbers[0].hover_color;
@ -451,27 +455,15 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
wxGetApp().unbind_shader();
}
Transform3d GLGizmoRotate::calculate_base_model_matrix() const
{
const Selection& selection = m_parent.get_selection();
/*if (m_hover_id != 0 && !m_grabbers[0].dragging) {
init_data_from_selection(selection);
}*/
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d scalling_matrix{ Transform3d::Identity() };
const auto& t_zoom = camera.get_zoom();
scalling_matrix.data()[0 * 4 + 0] = 1.0f / t_zoom;
scalling_matrix.data()[1 * 4 + 1] = 1.0f / t_zoom;
scalling_matrix.data()[2 * 4 + 2] = 1.0f / t_zoom;
return transform_to_local(selection) * scalling_matrix;
}
Transform3d GLGizmoRotate::calculate_circle_model_matrix() const
{
auto radius = m_radius;
modify_radius(radius);
Transform3d redius_scale_matrix;
Geometry::scale_transform(redius_scale_matrix, { m_radius, m_radius, m_radius });
const auto t_base_model_matrix = calculate_base_model_matrix();
return t_base_model_matrix * redius_scale_matrix;
Geometry::scale_transform(redius_scale_matrix, { radius, radius, radius });
const Selection& selection = m_parent.get_selection();
const Transform3d model_matrix = transform_to_local(selection);
return model_matrix * redius_scale_matrix;
}
Transform3d GLGizmoRotate::transform_to_local(const Selection &selection) const
@ -548,7 +540,7 @@ void GLGizmoRotate::init_data_from_selection(const Selection &selection) {
m_bounding_box = box;
const std::pair<Vec3d, double> sphere = selection.get_bounding_sphere();
m_center = sphere.first;
m_radius = Offset;// +sphere.second;
m_radius = Offset +sphere.second;
m_orient_matrix = box_trafo;
m_orient_matrix.translation() = m_center;
m_snap_coarse_in_radius = 1.0f / 3.0f;

View File

@ -94,7 +94,6 @@ private:
void render_grabber_connection(const ColorRGBA& color);
void render_grabber(const BoundingBoxf3& box) const;
void render_grabber_extension(const BoundingBoxf3& box, bool picking) const;
Transform3d calculate_base_model_matrix() const;
Transform3d calculate_circle_model_matrix() const;
Transform3d transform_to_local(const Selection& selection) const;
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate

View File

@ -985,6 +985,16 @@ bool OpenGLManager::is_legacy_framebuffer_enabled() const
return m_b_legacy_framebuffer_enabled;
}
void OpenGLManager::set_gizmo_keep_screen_size_enabled(bool is_enabled)
{
m_b_gizmo_keep_screen_size_enabled = is_enabled;
}
bool OpenGLManager::is_gizmo_keep_screen_size_enabled() const
{
return m_b_gizmo_keep_screen_size_enabled;
}
std::string OpenGLManager::framebuffer_type_to_string(EFramebufferType type)
{
switch (type)

View File

@ -217,6 +217,7 @@ private:
EVAOType m_vao_type{ EVAOType::Unknown };
uint32_t m_vao{ 0 };
bool m_b_legacy_framebuffer_enabled{ true };
bool m_b_gizmo_keep_screen_size_enabled{ true };
static GLInfo s_gl_info;
#ifdef __APPLE__
// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
@ -253,6 +254,8 @@ public:
void set_line_width(float width) const;
void set_legacy_framebuffer_enabled(bool is_enabled);
bool is_legacy_framebuffer_enabled() const;
void set_gizmo_keep_screen_size_enabled(bool is_enabled);
bool is_gizmo_keep_screen_size_enabled() const;
void set_msaa_type(const std::string& type);
void set_msaa_type(EMSAAType type);

View File

@ -2627,15 +2627,29 @@ static std::array<float, 4> get_color(Axis axis)
GLGizmoBase::AXES_COLOR[axis][3] };
};
void Selection::render_sidebar_position_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& model_matrix) const
Transform3d get_screen_scalling_matrix()
{
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d screen_scalling_matrix{ Transform3d::Identity() };
const auto& t_zoom = camera.get_zoom();
screen_scalling_matrix.data()[0 * 4 + 0] = 5.0f / t_zoom;
screen_scalling_matrix.data()[1 * 4 + 1] = 5.0f / t_zoom;
screen_scalling_matrix.data()[2 * 4 + 2] = 5.0f / t_zoom;
const auto& p_ogl_manager = wxGetApp().get_opengl_manager();
if (p_ogl_manager) {
if (p_ogl_manager->is_gizmo_keep_screen_size_enabled()) {
const auto& t_zoom = camera.get_zoom();
screen_scalling_matrix.data()[0 * 4 + 0] = 5.0f / t_zoom;
screen_scalling_matrix.data()[1 * 4 + 1] = 5.0f / t_zoom;
screen_scalling_matrix.data()[2 * 4 + 2] = 5.0f / t_zoom;
}
}
return screen_scalling_matrix;
}
void Selection::render_sidebar_position_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& model_matrix) const
{
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d screen_scalling_matrix = get_screen_scalling_matrix();
const Transform3d view_matrix = camera.get_view_matrix() * model_matrix * screen_scalling_matrix;
shader.set_uniform("projection_matrix", camera.get_projection_matrix());
@ -2668,11 +2682,7 @@ void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field,
const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d screen_scalling_matrix{ Transform3d::Identity() };
const auto& t_zoom = camera.get_zoom();
screen_scalling_matrix.data()[0 * 4 + 0] = 5.0f / t_zoom;
screen_scalling_matrix.data()[1 * 4 + 1] = 5.0f / t_zoom;
screen_scalling_matrix.data()[2 * 4 + 2] = 5.0f / t_zoom;
const Transform3d screen_scalling_matrix = get_screen_scalling_matrix();
Transform3d view_model_matrix = matrix * screen_scalling_matrix;
shader.set_uniform("view_model_matrix", view_model_matrix);