feat: Orthographic 카메라 추가 — 실측 확인용
사용자 피드백: 거더 높이 변경 시 차이가 미미해 보이는 것은 원근 투영의 시각 효과일 수 있음. 평행(Orthographic) 투영으로 보면 거리 무관 실측 크기가 그대로 보여 모델이 실제로 변하는지 객관적으로 확인 가능. 변경: - camera.rs: Projection enum (Perspective / Orthographic) 추가. - Camera.projection 필드 + view_proj() 분기. - Ortho 반높이 = radius * tan(fov_y/2) → 전환 시 시각 스케일 일치. - toggle_projection() 메서드. - lib.rs: - 카메라 초기값 projection: Perspective. - 키 O → 투영 토글. - egui 표시 섹션에 투영 버튼 추가 (◇ Perspective / ■ Ortho). 사용: 거더 높이 슬라이더 조정 → Apply → O 키로 Ortho 전환 → 모델 치수 실측 확인. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,16 @@ pub enum StandardView {
|
||||
Iso, // Home
|
||||
}
|
||||
|
||||
/// Camera projection mode.
|
||||
///
|
||||
/// - `Perspective`: 원근 투영. 멀수록 작게 보임. 일반 3D 뷰.
|
||||
/// - `Orthographic`: 평행 투영. 거리 무관 실측 크기. 치수 검증·도면 스타일 뷰.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Projection {
|
||||
Perspective,
|
||||
Orthographic,
|
||||
}
|
||||
|
||||
/// Orbit camera — spherical coordinates around a fixed target point.
|
||||
///
|
||||
/// All distances in millimetres (scene units).
|
||||
@@ -48,6 +58,8 @@ pub struct Camera {
|
||||
pub aspect: f32,
|
||||
pub znear: f32,
|
||||
pub zfar: f32,
|
||||
/// 투영 모드 (원근 / 평행). 토글 O.
|
||||
pub projection: Projection,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
@@ -62,6 +74,7 @@ impl Camera {
|
||||
aspect: 16.0 / 9.0,
|
||||
znear: 10.0, // 10 mm
|
||||
zfar: 10_000_000.0, // 10 km
|
||||
projection: Projection::Perspective,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,10 +94,29 @@ impl Camera {
|
||||
/// View-projection matrix (right-handed, depth 0→1).
|
||||
pub fn view_proj(&self) -> Mat4 {
|
||||
let view = Mat4::look_at_rh(self.eye(), self.target, Vec3::Y);
|
||||
let proj = Mat4::perspective_rh(self.fov_y, self.aspect, self.znear, self.zfar);
|
||||
let proj = match self.projection {
|
||||
Projection::Perspective => {
|
||||
Mat4::perspective_rh(self.fov_y, self.aspect, self.znear, self.zfar)
|
||||
}
|
||||
Projection::Orthographic => {
|
||||
// Ortho 수직 반높이: 같은 radius·FOV 의 원근 뷰와 시각 스케일 일치 →
|
||||
// target 평면에서 보이던 크기를 그대로 유지한 채 평행 투영.
|
||||
let half_h = self.radius * (self.fov_y * 0.5).tan();
|
||||
let half_w = half_h * self.aspect;
|
||||
Mat4::orthographic_rh(-half_w, half_w, -half_h, half_h, self.znear, self.zfar)
|
||||
}
|
||||
};
|
||||
proj * view
|
||||
}
|
||||
|
||||
/// Perspective ↔ Orthographic 토글.
|
||||
pub fn toggle_projection(&mut self) {
|
||||
self.projection = match self.projection {
|
||||
Projection::Perspective => Projection::Orthographic,
|
||||
Projection::Orthographic => Projection::Perspective,
|
||||
};
|
||||
}
|
||||
|
||||
/// Build GPU uniform from current state.
|
||||
pub fn to_uniform(&self) -> CameraUniform {
|
||||
CameraUniform { view_proj: self.view_proj().to_cols_array_2d() }
|
||||
|
||||
Reference in New Issue
Block a user