From a5b26832869493e7d32d5c4b5f0b3c69d5f1e848 Mon Sep 17 00:00:00 2001 From: cilix42 Date: Tue, 7 Aug 2007 08:05:16 +0000 Subject: [PATCH] Compute the correct visible front corner (also for 'upended' boxes) and set the z-orders accordingly so that they are correct for any relative position of the handles --- src/axis-manip.h | 10 ++++++++++ src/box3d.cpp | 35 ++++++++++++++++++++++------------- src/box3d.h | 2 ++ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/axis-manip.h b/src/axis-manip.h index 5690eedcb..8574bf3ff 100644 --- a/src/axis-manip.h +++ b/src/axis-manip.h @@ -75,6 +75,16 @@ inline bool is_single_axis_direction (Box3D::Axis dir) { return (!(dir & (dir - 1)) && dir); } +// Warning: We don't check that axis really unamiguously specifies a plane. +// Make sure this is the case when calling this function. +inline guint face_containing_corner (Box3D::Axis axis, guint corner) { + if (!is_single_axis_direction (axis)) { + axis = (Box3D::Axis) (axis ^ Box3D::XYZ); + } + return face_to_int (axis ^ ((corner & axis) ? Box3D::REAR : Box3D::FRONT)); +} + + /** * Given two axis directions out of {X, Y, Z} or the corresponding plane, return the remaining one * We don't check if 'plane' really specifies a plane (i.e., if it consists of precisely two directions). diff --git a/src/box3d.cpp b/src/box3d.cpp index 7f04efde6..0f71a99a8 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -406,7 +406,7 @@ bool sp_3dbox_recompute_z_orders (SP3DBox *box) Box3D::Perspective3D *persp = Box3D::get_persp_of_box (box); // TODO: Determine the front corner depending on the distance from VPs and/or the user presets - guint front_corner = 1; + guint front_corner = sp_3dbox_get_front_corner_id (box); gdouble dir_1x = sp_3dbox_corner_angle_to_VP (box, Box3D::X, front_corner); gdouble dir_3x = sp_3dbox_corner_angle_to_VP (box, Box3D::X, front_corner ^ Box3D::Y); @@ -419,25 +419,25 @@ bool sp_3dbox_recompute_z_orders (SP3DBox *box) // Still not perfect, but only fails in some rather degenerate cases. // I suspect that there is a more elegant model, though. :) - new_z_orders[0] = Box3D::face_to_int (Box3D::XY ^ Box3D::FRONT); + new_z_orders[0] = Box3D::face_containing_corner (Box3D::XY, front_corner); if (normalized_angle (dir_1y - dir_1z) > 0) { - new_z_orders[1] = Box3D::face_to_int (Box3D::YZ ^ Box3D::REAR); + new_z_orders[1] = Box3D::face_containing_corner (Box3D::YZ, front_corner); if (normalized_angle (dir_1x - dir_1z) > 0) { - new_z_orders[2] = Box3D::face_to_int (Box3D::XZ ^ Box3D::REAR); + new_z_orders[2] = Box3D::face_containing_corner (Box3D::XZ, front_corner ^ Box3D::Y); } else { - new_z_orders[2] = Box3D::face_to_int (Box3D::XZ ^ Box3D::FRONT); + new_z_orders[2] = Box3D::face_containing_corner (Box3D::XZ, front_corner); } } else { if (normalized_angle (dir_3x - dir_3z) > 0) { - new_z_orders[1] = Box3D::face_to_int (Box3D::XZ ^ Box3D::REAR); - new_z_orders[2] = Box3D::face_to_int (Box3D::YZ ^ Box3D::FRONT); + new_z_orders[1] = Box3D::face_containing_corner (Box3D::XZ, front_corner ^ Box3D::Y); + new_z_orders[2] = Box3D::face_containing_corner (Box3D::YZ, front_corner ^ Box3D::X); } else { if (normalized_angle (dir_1x - dir_1z) > 0) { - new_z_orders[1] = Box3D::face_to_int (Box3D::YZ ^ Box3D::FRONT); - new_z_orders[2] = Box3D::face_to_int (Box3D::XZ ^ Box3D::FRONT); + new_z_orders[1] = Box3D::face_containing_corner (Box3D::YZ, front_corner ^ Box3D::X); + new_z_orders[2] = Box3D::face_containing_corner (Box3D::XZ, front_corner); } else { - new_z_orders[1] = Box3D::face_to_int (Box3D::XZ ^ Box3D::FRONT); - new_z_orders[2] = Box3D::face_to_int (Box3D::YZ ^ Box3D::FRONT); + new_z_orders[1] = Box3D::face_containing_corner (Box3D::XZ, front_corner); + new_z_orders[2] = Box3D::face_containing_corner (Box3D::YZ, front_corner ^ Box3D::X); } } } @@ -448,8 +448,7 @@ bool sp_3dbox_recompute_z_orders (SP3DBox *box) /* We only need to look for changes among the topmost three faces because the order of the other ones is just inverted. */ - // Currently we can even skip the first test since the front face is always in the XY plane. - if (// (box->z_orders[0] != new_z_orders[0]) || + if ((box->z_orders[0] != new_z_orders[0]) || (box->z_orders[1] != new_z_orders[1]) || (box->z_orders[2] != new_z_orders[2])) { @@ -763,6 +762,16 @@ sp_3dbox_get_corner_along_edge (const SP3DBox *box, guint corner, Box3D::Axis ax return box->corners[sp_3dbox_get_corner_id_along_edge (box, corner, axis, rel_pos)]; } +guint +sp_3dbox_get_front_corner_id (const SP3DBox *box) +{ + guint front_corner = 1; // this could in fact be any corner, but we choose the one that is normally in front + front_corner = sp_3dbox_get_corner_id_along_edge (box, front_corner, Box3D::X, Box3D::FRONT); + front_corner = sp_3dbox_get_corner_id_along_edge (box, front_corner, Box3D::Y, Box3D::FRONT); + front_corner = sp_3dbox_get_corner_id_along_edge (box, front_corner, Box3D::Z, Box3D::FRONT); + return front_corner; +} + // auxiliary functions static void sp_3dbox_update_corner_with_value_from_svg (SPObject *object, guint corner_id, const gchar *value) diff --git a/src/box3d.h b/src/box3d.h index bca319e67..aecc40462 100644 --- a/src/box3d.h +++ b/src/box3d.h @@ -74,6 +74,8 @@ void sp_3dbox_update_perspective_lines(); void sp_3dbox_corners_for_perspective_lines (const SP3DBox * box, Box3D::Axis axis, NR::Point &corner1, NR::Point &corner2, NR::Point &corner3, NR::Point &corner4); guint sp_3dbox_get_corner_id_along_edge (const SP3DBox *box, guint corner, Box3D::Axis axis, Box3D::FrontOrRear rel_pos); NR::Point sp_3dbox_get_corner_along_edge (const SP3DBox *box, guint corner, Box3D::Axis axis, Box3D::FrontOrRear rel_pos); +guint sp_3dbox_get_front_corner_id (const SP3DBox *box); + gchar * sp_3dbox_get_svg_descr_of_persp (Box3D::Perspective3D *persp); -- 2.30.2