feat(render): retain raw camera poses
This commit is contained in:
@@ -22,6 +22,42 @@
|
||||
|
||||
use fparkan_world::OriginalObjectId;
|
||||
|
||||
/// A 64-byte transform block returned by the original Terrain camera ABI.
|
||||
///
|
||||
/// The original uses two selector-dependent transform pointers. Their exact
|
||||
/// matrix convention is still under recovery, so words are deliberately kept
|
||||
/// losslessly rather than treated as a renderer-ready matrix. The three
|
||||
/// translation words have been confirmed at indices 3, 7, and 11.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct RawCameraTransform {
|
||||
/// The exact 16 little-endian dwords returned by the legacy camera.
|
||||
pub words: [u32; 16],
|
||||
}
|
||||
|
||||
impl RawCameraTransform {
|
||||
/// Indices of the confirmed X, Y, and Z translation floats.
|
||||
pub const TRANSLATION_WORD_INDICES: [usize; 3] = [3, 7, 11];
|
||||
|
||||
/// Returns the confirmed legacy world position (X, Y, Z).
|
||||
#[must_use]
|
||||
pub fn translation(self) -> [f32; 3] {
|
||||
Self::TRANSLATION_WORD_INDICES.map(|index| f32::from_bits(self.words[index]))
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw camera state observed through the original Terrain camera interface.
|
||||
///
|
||||
/// Selector 0 supplies the currently active transform and selector 2 supplies
|
||||
/// its paired transform. Keeping both lets a later compatibility layer derive
|
||||
/// a view/projection convention without re-reading the legacy process.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct RawCameraPose {
|
||||
/// Transform returned by selector 0.
|
||||
pub selector0: RawCameraTransform,
|
||||
/// Transform returned by selector 2.
|
||||
pub selector2: RawCameraTransform,
|
||||
}
|
||||
|
||||
/// Immutable camera data visible to command generation.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct CameraSnapshot {
|
||||
@@ -29,6 +65,12 @@ pub struct CameraSnapshot {
|
||||
pub view: [f32; 16],
|
||||
/// Projection matrix, row-major.
|
||||
pub projection: [f32; 16],
|
||||
/// Optional unconverted source-camera state.
|
||||
///
|
||||
/// This does not alter rendering until the original matrix and projection
|
||||
/// conventions have been recovered; it preserves the ABI boundary for the
|
||||
/// runtime adapter and deterministic captures.
|
||||
pub raw_pose: Option<RawCameraPose>,
|
||||
}
|
||||
|
||||
impl Default for CameraSnapshot {
|
||||
@@ -36,6 +78,7 @@ impl Default for CameraSnapshot {
|
||||
Self {
|
||||
view: identity_transform(),
|
||||
projection: identity_transform(),
|
||||
raw_pose: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -702,6 +745,29 @@ fn identity_transform() -> [f32; 16] {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn raw_camera_pose_preserves_words_and_extracts_confirmed_translation() {
|
||||
let mut active = [0_u32; 16];
|
||||
active[0] = 0x7FC0_0001;
|
||||
active[3] = 491.562_5_f32.to_bits();
|
||||
active[7] = 761.550_8_f32.to_bits();
|
||||
active[11] = 7.361_0_f32.to_bits();
|
||||
let paired = [0xA5A5_5A5A; 16];
|
||||
|
||||
let pose = RawCameraPose {
|
||||
selector0: RawCameraTransform { words: active },
|
||||
selector2: RawCameraTransform { words: paired },
|
||||
};
|
||||
|
||||
assert_eq!(pose.selector0.words, active);
|
||||
assert_eq!(pose.selector2.words, paired);
|
||||
assert_eq!(
|
||||
pose.selector0.translation(),
|
||||
[491.562_5, 761.550_8, 7.361_0]
|
||||
);
|
||||
assert_eq!(CameraSnapshot::default().raw_pose, None);
|
||||
}
|
||||
|
||||
fn snapshot_draw(
|
||||
id: u64,
|
||||
phase: RenderPhase,
|
||||
|
||||
@@ -1318,6 +1318,16 @@ is a proven orientation-angle path. Field names, angle order and matrix
|
||||
handedness remain unassigned, but a backend-neutral camera pose may now retain
|
||||
the raw affine transform and the exact translation triple without guessing them.
|
||||
|
||||
The render contract now represents that boundary directly. `RawCameraTransform`
|
||||
preserves each selector result as sixteen original `u32` words, so diagnostic
|
||||
data is not rounded or silently assigned a row/column convention. Its only
|
||||
typed accessor reinterprets the proven X/Y/Z words `3/7/11` as IEEE-754
|
||||
floats. `RawCameraPose` retains selector `0` and selector `2` together, and
|
||||
`CameraSnapshot::raw_pose` is optional. The present Vulkan renderer continues
|
||||
to use its existing view/projection matrices: raw pose capture is intentionally
|
||||
not converted into a view matrix until the original transform/projection
|
||||
convention has evidence.
|
||||
|
||||
A fresh no-input launch of the canonical `iron_3d.exe` did create a responsive
|
||||
window titled `Parkan. Железная Стратегия`. A read-only probe then requested
|
||||
`PROCESS_QUERY_INFORMATION | PROCESS_VM_READ` and attempted to read the known
|
||||
|
||||
Reference in New Issue
Block a user