feat(render): preview explicit animation frames
This commit is contained in:
@@ -9,6 +9,7 @@ build = "build.rs"
|
||||
[dependencies]
|
||||
ash = "0.38"
|
||||
ash-window = "0.13"
|
||||
fparkan-animation = { path = "../../crates/fparkan-animation", version = "0.1.0" }
|
||||
fparkan-binary = { path = "../../crates/fparkan-binary", version = "0.1.0" }
|
||||
fparkan-msh = { path = "../../crates/fparkan-msh", version = "0.1.0" }
|
||||
fparkan-platform = { path = "../../crates/fparkan-platform", version = "0.1.0" }
|
||||
@@ -17,9 +18,6 @@ fparkan-terrain-format = { path = "../../crates/fparkan-terrain-format", version
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
fparkan-animation = { path = "../../crates/fparkan-animation", version = "0.1.0" }
|
||||
|
||||
[lints.rust]
|
||||
unsafe_code = "allow"
|
||||
missing_docs = "warn"
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
use crate::{VulkanStaticDrawRange, VulkanStaticMesh, VulkanStaticVertex};
|
||||
use fparkan_msh::{
|
||||
draw_batches, node38_fallback_hierarchy, selected_slot, Group, Lod, ModelAsset, NodeId,
|
||||
draw_batches, node38_fallback_hierarchy, node38_sampled_hierarchy, selected_slot, Group, Lod,
|
||||
ModelAsset, NodeId,
|
||||
};
|
||||
use fparkan_render::{LegacyIron3dEulerTransform, LegacyPipelineState};
|
||||
use fparkan_terrain_format::LandMeshDocument;
|
||||
@@ -206,6 +207,39 @@ pub fn project_msh_to_static_mesh_in_xy_frame_with_node_fallback_poses(
|
||||
Ok(mesh)
|
||||
}
|
||||
|
||||
/// Projects a standard `Node38` model at one explicit portable-reference
|
||||
/// animation frame into a diagnostic XY frame.
|
||||
///
|
||||
/// This is the diagnostic-camera counterpart of
|
||||
/// [`project_msh_to_static_mesh_in_world_space_with_node_sampled_poses`].
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns [`VulkanAssetMeshError`] when the source cannot be represented by
|
||||
/// the static bridge or a transformed coordinate is non-finite.
|
||||
pub fn project_msh_to_static_mesh_in_xy_frame_with_node_sampled_poses(
|
||||
model: &ModelAsset,
|
||||
frame: VulkanStaticXyFrame,
|
||||
transform: LegacyIron3dEulerTransform,
|
||||
scale: [f32; 3],
|
||||
animation_frame: u16,
|
||||
) -> Result<VulkanStaticMesh, VulkanAssetMeshError> {
|
||||
let mut mesh = project_msh_to_static_mesh_in_world_space_with_node_sampled_poses(
|
||||
model,
|
||||
transform,
|
||||
scale,
|
||||
animation_frame,
|
||||
)?;
|
||||
for vertex in &mut mesh.vertices {
|
||||
if !vertex.position.iter().all(|value| value.is_finite()) {
|
||||
return Err(VulkanAssetMeshError::NonFinitePosition);
|
||||
}
|
||||
let projected = frame.project(vertex.position);
|
||||
vertex.position = [projected[0], projected[1], 0.0];
|
||||
}
|
||||
Ok(mesh)
|
||||
}
|
||||
|
||||
/// Projects MSH geometry into source world coordinates with known translation and scale.
|
||||
///
|
||||
/// Unlike [`project_msh_to_static_mesh_in_xy_frame`], this does not normalize
|
||||
@@ -307,6 +341,45 @@ pub fn project_msh_to_static_mesh_in_world_space_with_node_fallback_poses(
|
||||
model: &ModelAsset,
|
||||
transform: LegacyIron3dEulerTransform,
|
||||
scale: [f32; 3],
|
||||
) -> Result<VulkanStaticMesh, VulkanAssetMeshError> {
|
||||
project_msh_to_static_mesh_in_world_space_with_node_poses(
|
||||
model,
|
||||
transform,
|
||||
scale,
|
||||
node38_fallback_hierarchy(model),
|
||||
)
|
||||
}
|
||||
|
||||
/// Projects a standard `Node38` model at one explicit portable-reference
|
||||
/// animation frame.
|
||||
///
|
||||
/// This uses decoded type-8 keys and the type-19 map but deliberately does
|
||||
/// not infer the original engine's animation clock or x87 profile. Models
|
||||
/// without a complete sampled hierarchy retain the established unposed bridge.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns [`VulkanAssetMeshError`] when source geometry or transforms cannot
|
||||
/// be represented by the current static Vulkan input contract.
|
||||
pub fn project_msh_to_static_mesh_in_world_space_with_node_sampled_poses(
|
||||
model: &ModelAsset,
|
||||
transform: LegacyIron3dEulerTransform,
|
||||
scale: [f32; 3],
|
||||
animation_frame: u16,
|
||||
) -> Result<VulkanStaticMesh, VulkanAssetMeshError> {
|
||||
project_msh_to_static_mesh_in_world_space_with_node_poses(
|
||||
model,
|
||||
transform,
|
||||
scale,
|
||||
node38_sampled_hierarchy(model, animation_frame),
|
||||
)
|
||||
}
|
||||
|
||||
fn project_msh_to_static_mesh_in_world_space_with_node_poses(
|
||||
model: &ModelAsset,
|
||||
transform: LegacyIron3dEulerTransform,
|
||||
scale: [f32; 3],
|
||||
hierarchy: Option<fparkan_animation::NodePoseBuffer>,
|
||||
) -> Result<VulkanStaticMesh, VulkanAssetMeshError> {
|
||||
if !transform
|
||||
.translation
|
||||
@@ -320,7 +393,7 @@ pub fn project_msh_to_static_mesh_in_world_space_with_node_fallback_poses(
|
||||
if model.node_stride != 38 || model.node_count == 0 || model.animation.is_none() {
|
||||
return project_msh_to_static_mesh_in_world_space_with_transform(model, transform, scale);
|
||||
}
|
||||
let Some(hierarchy) = node38_fallback_hierarchy(model) else {
|
||||
let Some(hierarchy) = hierarchy else {
|
||||
return project_msh_to_static_mesh_in_world_space_with_transform(model, transform, scale);
|
||||
};
|
||||
|
||||
|
||||
@@ -44,9 +44,11 @@ pub use self::asset_mesh::{
|
||||
project_land_msh_to_static_mesh_in_world_space, project_land_msh_to_static_mesh_in_xy_frame,
|
||||
project_msh_to_static_mesh, project_msh_to_static_mesh_in_world_space,
|
||||
project_msh_to_static_mesh_in_world_space_with_node_fallback_poses,
|
||||
project_msh_to_static_mesh_in_world_space_with_node_sampled_poses,
|
||||
project_msh_to_static_mesh_in_world_space_with_transform,
|
||||
project_msh_to_static_mesh_in_xy_frame,
|
||||
project_msh_to_static_mesh_in_xy_frame_with_node_fallback_poses, VulkanAssetMeshError,
|
||||
project_msh_to_static_mesh_in_xy_frame_with_node_fallback_poses,
|
||||
project_msh_to_static_mesh_in_xy_frame_with_node_sampled_poses, VulkanAssetMeshError,
|
||||
VulkanStaticXyFrame,
|
||||
};
|
||||
pub use self::capabilities::{
|
||||
|
||||
Reference in New Issue
Block a user