feat(render): retain raw camera projection state
This commit is contained in:
@@ -142,6 +142,37 @@ pub struct RawCameraPose {
|
|||||||
pub selector2: RawCameraTransform,
|
pub selector2: RawCameraTransform,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Raw projection state observed through the original `CBufferingCamera` ABI.
|
||||||
|
///
|
||||||
|
/// The five-float context block is intentionally represented as original words:
|
||||||
|
/// its indices are observed, but their semantic labels have not yet all been
|
||||||
|
/// recovered. The field-of-view value is the type-0 input to `tan(fov / 2)`.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
pub struct RawCameraProjection {
|
||||||
|
/// Viewport rectangle as `(left, top, right, bottom)`.
|
||||||
|
pub viewport: [i32; 4],
|
||||||
|
/// Original projection selector.
|
||||||
|
pub projection_type: u32,
|
||||||
|
/// Original IEEE-754 FOV value in radians.
|
||||||
|
pub field_of_view_radians_bits: u32,
|
||||||
|
/// Exact five-float context block returned by the primary renderer.
|
||||||
|
pub context_words: [u32; 5],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawCameraProjection {
|
||||||
|
/// Returns the type-0 FOV input in radians.
|
||||||
|
#[must_use]
|
||||||
|
pub fn field_of_view_radians(self) -> f32 {
|
||||||
|
f32::from_bits(self.field_of_view_radians_bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the five context values without assigning semantic labels.
|
||||||
|
#[must_use]
|
||||||
|
pub fn context_values(self) -> [f32; 5] {
|
||||||
|
self.context_words.map(f32::from_bits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Immutable camera data visible to command generation.
|
/// Immutable camera data visible to command generation.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct CameraSnapshot {
|
pub struct CameraSnapshot {
|
||||||
@@ -155,6 +186,11 @@ pub struct CameraSnapshot {
|
|||||||
/// conventions have been recovered; it preserves the ABI boundary for the
|
/// conventions have been recovered; it preserves the ABI boundary for the
|
||||||
/// runtime adapter and deterministic captures.
|
/// runtime adapter and deterministic captures.
|
||||||
pub raw_pose: Option<RawCameraPose>,
|
pub raw_pose: Option<RawCameraPose>,
|
||||||
|
/// Optional unconverted source-projection state.
|
||||||
|
///
|
||||||
|
/// This is retained independently of `projection`, because its legacy
|
||||||
|
/// context words have not yet been mapped to a Vulkan clip convention.
|
||||||
|
pub raw_projection: Option<RawCameraProjection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CameraSnapshot {
|
impl Default for CameraSnapshot {
|
||||||
@@ -163,6 +199,7 @@ impl Default for CameraSnapshot {
|
|||||||
view: identity_transform(),
|
view: identity_transform(),
|
||||||
projection: identity_transform(),
|
projection: identity_transform(),
|
||||||
raw_pose: None,
|
raw_pose: None,
|
||||||
|
raw_projection: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -874,6 +911,26 @@ mod tests {
|
|||||||
assert_eq!(CameraSnapshot::default().raw_pose, None);
|
assert_eq!(CameraSnapshot::default().raw_pose, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn raw_camera_projection_preserves_live_context_words_without_labeling_them() {
|
||||||
|
let projection = RawCameraProjection {
|
||||||
|
viewport: [0, 0, 1024, 768],
|
||||||
|
projection_type: 0,
|
||||||
|
field_of_view_radians_bits: 1.04_f32.to_bits(),
|
||||||
|
context_words: [
|
||||||
|
0.0_f32.to_bits(),
|
||||||
|
0.5_f32.to_bits(),
|
||||||
|
700.0_f32.to_bits(),
|
||||||
|
0.1_f32.to_bits(),
|
||||||
|
0.99_f32.to_bits(),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(projection.field_of_view_radians(), 1.04);
|
||||||
|
assert_eq!(projection.context_values(), [0.0, 0.5, 700.0, 0.1, 0.99]);
|
||||||
|
assert_eq!(CameraSnapshot::default().raw_projection, None);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn raw_camera_transform_inverts_only_non_singular_affine_blocks() {
|
fn raw_camera_transform_inverts_only_non_singular_affine_blocks() {
|
||||||
let source = [
|
let source = [
|
||||||
|
|||||||
@@ -1364,6 +1364,13 @@ is only a table lookup keyed by two still-unnamed inputs. No virtual call was
|
|||||||
made by the probe. Therefore the block's values cannot yet be assigned as
|
made by the probe. Therefore the block's values cannot yet be assigned as
|
||||||
near/far or reused by the Vulkan adapter.
|
near/far or reused by the Vulkan adapter.
|
||||||
|
|
||||||
|
The runtime render model now retains this evidence as `RawCameraProjection` on
|
||||||
|
`CameraSnapshot`: the viewport rectangle, projection selector, exact FOV bits,
|
||||||
|
and all five context words travel through the backend-neutral boundary without
|
||||||
|
changing the current Vulkan projection. Its float accessors deliberately leave
|
||||||
|
the context fields unnamed; preserving a raw ABI value is safer than encoding a
|
||||||
|
near/far or clip-space convention before it is demonstrated.
|
||||||
|
|
||||||
A fresh no-input launch of the canonical `iron_3d.exe` did create a responsive
|
A fresh no-input launch of the canonical `iron_3d.exe` did create a responsive
|
||||||
window titled `Parkan. Железная Стратегия`. A read-only probe then requested
|
window titled `Parkan. Железная Стратегия`. A read-only probe then requested
|
||||||
`PROCESS_QUERY_INFORMATION | PROCESS_VM_READ` and attempted to read the known
|
`PROCESS_QUERY_INFORMATION | PROCESS_VM_READ` and attempted to read the known
|
||||||
|
|||||||
Reference in New Issue
Block a user