feat(terrain): expose slot render dispatch
This commit is contained in:
@@ -183,6 +183,33 @@ pub struct TerrainSlotTable {
|
|||||||
pub slots_raw: Vec<[u8; SLOT_STRIDE]>,
|
pub slots_raw: Vec<[u8; SLOT_STRIDE]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The proven front fields of one 68-byte terrain slot record.
|
||||||
|
///
|
||||||
|
/// `Terrain.dll!CLandscape` supplies these fields to `GetShade`'s terrain
|
||||||
|
/// batch dispatcher: `pair_table_index` selects the pointer-table entry and
|
||||||
|
/// `pair_count` is the number of adjacent `u16` pairs to process. The pair
|
||||||
|
/// payload and the later material/blend interpretation remain external to the
|
||||||
|
/// disk record.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
pub struct TerrainSlotRenderDispatch {
|
||||||
|
/// Index into the runtime pair-pointer table.
|
||||||
|
pub pair_table_index: u16,
|
||||||
|
/// Number of adjacent `u16` pairs in that selected payload.
|
||||||
|
pub pair_count: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TerrainSlotTable {
|
||||||
|
/// Returns the render-dispatch header for one decoded slot record.
|
||||||
|
#[must_use]
|
||||||
|
pub fn render_dispatch(&self, slot_index: usize) -> Option<TerrainSlotRenderDispatch> {
|
||||||
|
let raw = self.slots_raw.get(slot_index)?;
|
||||||
|
Some(TerrainSlotRenderDispatch {
|
||||||
|
pair_table_index: u16::from_le_bytes([raw[0], raw[1]]),
|
||||||
|
pair_count: u16::from_le_bytes([raw[2], raw[3]]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Land mesh document.
|
/// Land mesh document.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct LandMeshDocument {
|
pub struct LandMeshDocument {
|
||||||
@@ -1460,6 +1487,26 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slot_render_dispatch_retains_pair_table_index_and_count() {
|
||||||
|
let mut raw = [0_u8; SLOT_STRIDE];
|
||||||
|
raw[..2].copy_from_slice(&7_u16.to_le_bytes());
|
||||||
|
raw[2..4].copy_from_slice(&3_u16.to_le_bytes());
|
||||||
|
let slots = TerrainSlotTable {
|
||||||
|
header_raw: SLOT_HEADER_ZERO.to_vec(),
|
||||||
|
slots_raw: vec![raw],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
slots.render_dispatch(0),
|
||||||
|
Some(TerrainSlotRenderDispatch {
|
||||||
|
pair_table_index: 7,
|
||||||
|
pair_count: 3,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
assert_eq!(slots.render_dispatch(1), None);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn terrain_material_tag_decodes_two_sidecar_selectors() {
|
fn terrain_material_tag_decodes_two_sidecar_selectors() {
|
||||||
let mut raw_face = face([0, 1, 2], [None, None, None]);
|
let mut raw_face = face([0, 1, 2], [None, None, None]);
|
||||||
|
|||||||
@@ -1575,12 +1575,15 @@ an overlay, blend, or microtexture shader.
|
|||||||
|
|
||||||
The terrain render traversal is now located at `Terrain.dll` RVA `0x11340`.
|
The terrain render traversal is now located at `Terrain.dll` RVA `0x11340`.
|
||||||
After visibility/cell work, it derives a 68-byte source-material record and
|
After visibility/cell work, it derives a 68-byte source-material record and
|
||||||
dispatches renderer-context slot `+16` with four arguments: zero, the record's
|
dispatches `Terrain!GetShade()` slot `+16` with four arguments: zero, the
|
||||||
16-bit word at `+2`, a pointer selected from a four-byte table by its word at
|
record's word at `+2`, a pointer selected from a four-byte table by its word at
|
||||||
`+0`, and zero. A preceding renderer-context slot `+60` receives the current
|
`+0`, and zero. `GetShade` is a Terrain singleton, not `niGet3DRender`; the
|
||||||
visibility mode. This is the concrete terrain-to-renderer handoff; it does not
|
preceding slot `+60` call sets its visibility mode. Slot `+16` consumes the
|
||||||
call `GetMaterialPhase` directly and does not yet identify either word, the
|
second word as the count of adjacent `u16` pairs and the first as the pair-table
|
||||||
four-byte payload, or the final blend operation.
|
index, then groups the pairs by material lookup before constructing draw work.
|
||||||
|
`TerrainSlotTable::render_dispatch` exposes exactly those two proven disk
|
||||||
|
fields. The pair payload, its material key, and the final blend operation remain
|
||||||
|
unassigned.
|
||||||
|
|
||||||
The static Vulkan bridge now carries each contiguous face run as a separate
|
The static Vulkan bridge now carries each contiguous face run as a separate
|
||||||
draw range keyed by the original packed `material_tag`; it neither reorders
|
draw range keyed by the original packed `material_tag`; it neither reorders
|
||||||
|
|||||||
Reference in New Issue
Block a user