diff options
Diffstat (limited to 'adapters/fparkan-render-vulkan/src/asset_mesh.rs')
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/asset_mesh.rs | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/adapters/fparkan-render-vulkan/src/asset_mesh.rs b/adapters/fparkan-render-vulkan/src/asset_mesh.rs index f691b34..d813b91 100644 --- a/adapters/fparkan-render-vulkan/src/asset_mesh.rs +++ b/adapters/fparkan-render-vulkan/src/asset_mesh.rs @@ -866,6 +866,7 @@ fn append_node_fallback_batch( batch_flags: batch.batch_flags, pipeline_state: world_pipeline_state(), terrain_base_only: false, + terrain_reflection: false, alpha_test_reference: VulkanStaticDrawRange::NATIVE_DEFAULT_ALPHA_TEST_REFERENCE, }); Ok(()) @@ -1105,7 +1106,21 @@ fn project_land_msh_to_static_mesh_with_lod0( pub fn project_land_msh_to_static_mesh_in_world_space( terrain: &LandMeshDocument, ) -> Result<VulkanStaticMesh, VulkanAssetMeshError> { - let lod0 = static_terrain_lod0_assignments(terrain)?; + project_land_msh_lod_to_static_mesh_in_world_space(terrain, TerrainLod::Lod0) +} + +/// Projects one authored terrain LOD without changing source positions or attributes. +/// +/// # Errors +/// Returns an error for invalid slot assignments or an empty selected LOD. +pub fn project_land_msh_lod_to_static_mesh_in_world_space( + terrain: &LandMeshDocument, + lod: TerrainLod, +) -> Result<VulkanStaticMesh, VulkanAssetMeshError> { + let mut lod0 = terrain + .face_lod_assignments() + .map_err(VulkanAssetMeshError::InvalidTerrainLodMapping)?; + lod0.retain(|assignment| assignment.lod == lod); let indices = static_terrain_indices(terrain, &lod0)?; let vertices = terrain .positions @@ -1212,6 +1227,7 @@ fn static_terrain_draw_ranges( .ok_or(VulkanAssetMeshError::IndexOutOfRange)?; let material_index = first_face.material_tag; let terrain_base_only = first_face.flags.0 & 0x400 == 0; + let terrain_reflection = first_face.flags.0 & 0x20000 != 0; let mut end_face = start_face + 1; while end_face < lod0.len() { let next_face = terrain @@ -1220,6 +1236,10 @@ fn static_terrain_draw_ranges( .ok_or(VulkanAssetMeshError::IndexOutOfRange)?; if next_face.material_tag != material_index || (next_face.flags.0 & 0x400 == 0) != terrain_base_only + || (next_face.flags.0 & 0x20000 != 0) != terrain_reflection + || (terrain_reflection + && terrain.positions[usize::from(first_face.vertices[0])][2] + != terrain.positions[usize::from(next_face.vertices[0])][2]) { break; } @@ -1239,6 +1259,7 @@ fn static_terrain_draw_ranges( batch_flags: 0, pipeline_state: world_pipeline_state(), terrain_base_only, + terrain_reflection, alpha_test_reference: VulkanStaticDrawRange::NATIVE_DEFAULT_ALPHA_TEST_REFERENCE, }); start_face = end_face; @@ -1285,6 +1306,7 @@ fn static_model_indices_and_ranges( batch_flags: batch.batch_flags, pipeline_state: world_pipeline_state(), terrain_base_only: false, + terrain_reflection: false, alpha_test_reference: VulkanStaticDrawRange::NATIVE_DEFAULT_ALPHA_TEST_REFERENCE, }); } @@ -1492,6 +1514,7 @@ mod tests { batch_flags: 0, pipeline_state: world_pipeline_state(), terrain_base_only: false, + terrain_reflection: false, alpha_test_reference: VulkanStaticDrawRange::NATIVE_DEFAULT_ALPHA_TEST_REFERENCE, }] ); @@ -2022,6 +2045,7 @@ mod tests { batch_flags: 0, pipeline_state: world_pipeline_state(), terrain_base_only: false, + terrain_reflection: false, alpha_test_reference: VulkanStaticDrawRange::NATIVE_DEFAULT_ALPHA_TEST_REFERENCE, }, @@ -2033,6 +2057,7 @@ mod tests { batch_flags: 0, pipeline_state: world_pipeline_state(), terrain_base_only: false, + terrain_reflection: false, alpha_test_reference: VulkanStaticDrawRange::NATIVE_DEFAULT_ALPHA_TEST_REFERENCE, }, @@ -2118,6 +2143,13 @@ mod tests { assert_eq!(mesh.draw_ranges[0].index_count, 6); assert_eq!(mesh.draw_ranges[0].material_index, 0x0101); + let far = project_land_msh_lod_to_static_mesh_in_world_space(&terrain, TerrainLod::Lod1) + .expect("LOD1 terrain projection"); + assert_eq!(far.indices, [3, 4, 5, 3, 4, 5]); + assert_eq!(far.draw_ranges.len(), 1); + assert_eq!(far.draw_ranges[0].material_index, 0x0202); + assert_eq!(far.vertices[3].position, [10.0, 10.0, 10.0]); + terrain.nodes_raw.clear(); assert!(matches!( project_land_msh_to_static_mesh_in_world_space(&terrain), @@ -2277,5 +2309,21 @@ mod tests { assert!(ranges.iter().all(|range| { range.alpha_test_reference == VulkanStaticDrawRange::NATIVE_DEFAULT_ALPHA_TEST_REFERENCE })); + terrain.faces = vec![ + terrain_face_with_tag_and_flags(0xff04, 0x400, [0, 1, 2]), + terrain_face_with_tag_and_flags(0xff04, 0x20400, [0, 1, 2]), + terrain_face_with_tag_and_flags(0xff04, 0x20400, [0, 1, 2]), + terrain_face_with_tag_and_flags(0xff04, 0x20400, [3, 4, 5]), + ]; + terrain.positions.extend([[0.0, 0.0, 10.0]; 3]); + set_terrain_lod_slots(&mut terrain, &[[0, u16::MAX]], &[[0, 4]]); + let assignments = static_terrain_lod0_assignments(&terrain).unwrap(); + let ranges = static_terrain_draw_ranges(&terrain, &assignments).unwrap(); + assert_eq!(ranges.len(), 3); + assert!(!ranges[0].terrain_reflection); + assert!(ranges[1].terrain_reflection); + assert_eq!(ranges[1].index_count, 6); + assert!(ranges[2].terrain_reflection); + assert_eq!(ranges[2].index_count, 3); } } |
