forked from 1b-agent/opencadstudio-upstream
fix(viewcube): deterministic horizon for obliques, generic opposite
Top Front Right/Left kept Y (north) as up when starting from Top, tilting the base because orbit is turntable (never banks). Make snap_to_direction deterministic: world +Z horizon except near +-Z where north +Y is used, sign-preserved only for intentionally inverted views. Expand opposite() from faces-only to all 26 regions so already-there flip works for edges/corners.
This commit is contained in:
1 parent
5ba72ec3e4
commit
4fdef48502
3 files changed
+50
-49
No files matched your search
@@ -142,24 +142,39 @@ impl CubeRegion {
|
||||
|
||||
/// Unit eye-direction vector (from target toward the camera) that
|
||||
/// looks straight at this region. Used by `Camera::snap_to_direction`
|
||||
/// which derives the full orientation by re-using the current
|
||||
/// camera's up vector, projected onto the plane perpendicular to
|
||||
/// this direction — so clicking an edge spins the cube around the
|
||||
/// edge without rolling the user's "up" sense.
|
||||
/// / `snap_to_face` which derive a deterministic horizon (world +Z,
|
||||
/// except top/bottom where north +Y is used) so every cube click
|
||||
/// lands repeatably.
|
||||
pub fn snap_direction(self) -> glam::Vec3 {
|
||||
let c = region_centroids()[self.id()];
|
||||
glam::Vec3::new(c[0], c[1], c[2]).normalize_or(glam::Vec3::Z)
|
||||
}
|
||||
|
||||
pub fn opposite(self) -> CubeRegion {
|
||||
match self {
|
||||
CubeRegion::Face(FACE_TOP) => CubeRegion::Face(FACE_BOTTOM),
|
||||
CubeRegion::Face(FACE_BOTTOM) => CubeRegion::Face(FACE_TOP),
|
||||
CubeRegion::Face(FACE_FRONT) => CubeRegion::Face(FACE_BACK),
|
||||
CubeRegion::Face(FACE_BACK) => CubeRegion::Face(FACE_FRONT),
|
||||
CubeRegion::Face(FACE_RIGHT) => CubeRegion::Face(FACE_LEFT),
|
||||
CubeRegion::Face(FACE_LEFT) => CubeRegion::Face(FACE_RIGHT),
|
||||
other => other,
|
||||
// Generic opposite: the region whose centroid is nearest to -self.
|
||||
// Covers faces, edges and corners so "already there → flip" works
|
||||
// for every cube click, not just faces.
|
||||
let centroids = region_centroids();
|
||||
let c = centroids[self.id()];
|
||||
let neg = [-c[0], -c[1], -c[2]];
|
||||
let mut best = self.id();
|
||||
let mut best_d = f32::MAX;
|
||||
for (i, cc) in centroids.iter().enumerate() {
|
||||
let dx = cc[0] - neg[0];
|
||||
let dy = cc[1] - neg[1];
|
||||
let dz = cc[2] - neg[2];
|
||||
let d = dx * dx + dy * dy + dz * dz;
|
||||
if d < best_d {
|
||||
best_d = d;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
if best < 6 {
|
||||
CubeRegion::Face(best)
|
||||
} else if best < 18 {
|
||||
CubeRegion::Edge(best)
|
||||
} else {
|
||||
CubeRegion::Corner(best)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user