forked from 1b-agent/opencadstudio-upstream
feat(render): add scene environment pipeline
This commit is contained in:
1 parent
b667eeeb05
commit
c45daeffb6
17 files changed
+2236
-213
No files matched your search
+35
-9
@@ -405,7 +405,7 @@ impl Scene {
|
||||
model_space: bool,
|
||||
) -> bool {
|
||||
let _ = model_space;
|
||||
let Some(cam) = self.camera_from_view(
|
||||
let Some(cam) = self.camera_from_view_mode(
|
||||
view.direction,
|
||||
view.target,
|
||||
acadrust::types::Vector2 {
|
||||
@@ -414,6 +414,8 @@ impl Scene {
|
||||
},
|
||||
view.height,
|
||||
view.twist_angle,
|
||||
view.perspective,
|
||||
view.lens_length,
|
||||
) else {
|
||||
return false;
|
||||
};
|
||||
@@ -463,16 +465,15 @@ impl Scene {
|
||||
/// their already-effective `view_target` / `view_center` / `view_height`.
|
||||
///
|
||||
/// Returns `None` for a zero `view_height` (an uninitialised entry).
|
||||
pub(super) fn camera_from_view(
|
||||
pub(super) fn camera_from_view_mode(
|
||||
&self,
|
||||
view_direction: acadrust::types::Vector3,
|
||||
view_target: acadrust::types::Vector3,
|
||||
view_center: acadrust::types::Vector2,
|
||||
view_height: f64,
|
||||
twist: f64,
|
||||
// Subtracted from `view_target` to reach wire-space. Model views pass
|
||||
// `[0.0_f64; 3]`; paper-space views (whose entities carry no
|
||||
// offset) pass `[0; 3]`.
|
||||
perspective: bool,
|
||||
lens_length: f64,
|
||||
) -> Option<Camera> {
|
||||
if view_height.abs() < 1e-9 {
|
||||
return None;
|
||||
@@ -516,14 +517,26 @@ impl Scene {
|
||||
let target = base
|
||||
+ view_right.as_dvec3() * view_center.x
|
||||
+ view_up.as_dvec3() * view_center.y;
|
||||
let fov_y = 45.0_f32.to_radians();
|
||||
let lens_length = lens_length.max(1.0) as f32;
|
||||
// The saved-view convention uses a 24 mm vertical aperture. This is
|
||||
// the inverse of the projection path's documented
|
||||
// `distance = view_height * lens / 24` relation.
|
||||
let fov_y = if perspective {
|
||||
2.0 * (12.0 / lens_length).atan()
|
||||
} else {
|
||||
45.0_f32.to_radians()
|
||||
};
|
||||
let distance = ((view_height as f32 / 2.0) / (fov_y * 0.5).tan()).max(0.001);
|
||||
Some(Camera {
|
||||
target,
|
||||
rotation,
|
||||
distance,
|
||||
fov_y,
|
||||
projection: view::camera::Projection::Orthographic,
|
||||
projection: if perspective {
|
||||
view::camera::Projection::Perspective
|
||||
} else {
|
||||
view::camera::Projection::Orthographic
|
||||
},
|
||||
yaw,
|
||||
pitch,
|
||||
// Sized from the saved view height (not a zoom-scaled range) so a
|
||||
@@ -544,12 +557,14 @@ impl Scene {
|
||||
|
||||
/// Decode a VPort table entry (model-space tiled view) into a `Camera`.
|
||||
fn camera_from_vport(&self, vp: &acadrust::tables::VPort) -> Option<Camera> {
|
||||
self.camera_from_view(
|
||||
self.camera_from_view_mode(
|
||||
vp.view_direction,
|
||||
vp.view_target,
|
||||
vp.view_center,
|
||||
vp.view_height,
|
||||
vp.view_twist,
|
||||
vp.perspective,
|
||||
vp.lens_length,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -580,6 +595,8 @@ impl Scene {
|
||||
z: view_dir.z as f64,
|
||||
};
|
||||
entry.view_height = view_height as f64;
|
||||
entry.perspective = cam.projection == view::camera::Projection::Perspective;
|
||||
entry.lens_length = (12.0 / (cam.fov_y * 0.5).tan().max(1e-6)) as f64;
|
||||
entry.view_center = acadrust::types::Vector2::ZERO;
|
||||
// Stored twist = -roll, matching the decoder (roll = -twist).
|
||||
entry.view_twist = -cam.roll() as f64;
|
||||
@@ -796,7 +813,7 @@ impl Scene {
|
||||
|
||||
// Paper-space entities carry no world_offset → decode with a zero
|
||||
// offset, through the same shared decoder (twist included).
|
||||
let Some(cam) = self.camera_from_view(
|
||||
let Some(cam) = self.camera_from_view_mode(
|
||||
vp.view_direction,
|
||||
vp.view_target,
|
||||
acadrust::types::Vector2 {
|
||||
@@ -805,6 +822,8 @@ impl Scene {
|
||||
},
|
||||
vp.view_height,
|
||||
vp.twist_angle,
|
||||
vp.status.perspective,
|
||||
vp.lens_length,
|
||||
) else {
|
||||
return false;
|
||||
};
|
||||
@@ -847,6 +866,8 @@ impl Scene {
|
||||
vp.view_direction = vd3;
|
||||
vp.view_height = view_height as f64;
|
||||
vp.view_twist = twist;
|
||||
vp.perspective = cam.projection == view::camera::Projection::Perspective;
|
||||
vp.lens_length = (12.0 / (cam.fov_y * 0.5).tan().max(1e-6)) as f64;
|
||||
}
|
||||
|
||||
// Persist the tiled layout as duplicate `*Active` VPort entries.
|
||||
@@ -878,6 +899,9 @@ impl Scene {
|
||||
vp.view_direction = vd3;
|
||||
vp.view_height = view_height as f64;
|
||||
vp.twist_angle = twist;
|
||||
vp.status.perspective =
|
||||
cam.projection == view::camera::Projection::Perspective;
|
||||
vp.lens_length = (12.0 / (cam.fov_y * 0.5).tan().max(1e-6)) as f64;
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -985,6 +1009,7 @@ impl Scene {
|
||||
None,
|
||||
scale,
|
||||
self.annotation_all_visible(),
|
||||
None,
|
||||
) {
|
||||
let is_infinite = Self::handle_from_wire_name(&wire.name)
|
||||
.and_then(|handle| self.document.get_entity(handle))
|
||||
@@ -1081,6 +1106,7 @@ impl Scene {
|
||||
None,
|
||||
scale,
|
||||
self.annotation_all_visible(),
|
||||
None,
|
||||
);
|
||||
// Ray / XLine tessellate as ±DISPLAY_EXTENT display segments
|
||||
// (entities/ray.rs) — their endpoints are rendering artifacts, not
|
||||
|
||||
Reference in new issue
Block a user